summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp764
-rw-r--r--ApiDocs.bp436
-rw-r--r--CleanSpec.mk3
-rw-r--r--StubLibraries.bp340
-rw-r--r--apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java76
-rw-r--r--apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java74
-rw-r--r--apex/sdkext/Android.bp2
-rw-r--r--apex/sdkext/derive_sdk/derive_sdk.cpp2
-rw-r--r--apex/statsd/aidl/Android.bp12
-rw-r--r--apex/statsd/aidl/android/os/IPullAtomCallback.aidl2
-rw-r--r--apex/statsd/aidl/android/os/IStatsCompanionService.aidl3
-rw-r--r--apex/statsd/aidl/android/os/IStatsManagerService.aidl65
-rw-r--r--apex/statsd/aidl/android/os/IStatsd.aidl5
-rw-r--r--apex/statsd/framework/Android.bp2
-rw-r--r--apex/statsd/service/java/com/android/server/stats/StatsCompanion.java70
-rw-r--r--apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java124
-rw-r--r--apex/statsd/service/java/com/android/server/stats/StatsManagerService.java114
-rw-r--r--api/current.txt400
-rw-r--r--api/lint-baseline.txt8
-rw-r--r--api/removed.txt9
-rwxr-xr-xapi/system-current.txt381
-rw-r--r--api/system-lint-baseline.txt5
-rw-r--r--api/test-current.txt226
-rw-r--r--api/test-lint-baseline.txt12
-rw-r--r--cmds/idmap2/CPPLINT.cfg2
-rw-r--r--cmds/idmap2/include/idmap2/BinaryStreamVisitor.h3
-rw-r--r--cmds/idmap2/include/idmap2/Idmap.h19
-rw-r--r--cmds/idmap2/include/idmap2/LogInfo.h81
-rw-r--r--cmds/idmap2/include/idmap2/RawPrintVisitor.h2
-rw-r--r--cmds/idmap2/include/idmap2/ResourceMapping.h8
-rw-r--r--cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp15
-rw-r--r--cmds/idmap2/libidmap2/Idmap.cpp39
-rw-r--r--cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp20
-rw-r--r--cmds/idmap2/libidmap2/RawPrintVisitor.cpp19
-rw-r--r--cmds/idmap2/libidmap2/ResourceMapping.cpp31
-rw-r--r--cmds/idmap2/tests/IdmapTests.cpp15
-rw-r--r--cmds/idmap2/tests/RawPrintVisitorTests.cpp70
-rw-r--r--cmds/idmap2/tests/ResourceMappingTests.cpp4
-rw-r--r--cmds/idmap2/tests/TestHelpers.h47
-rw-r--r--cmds/incidentd/src/WorkDirectory.cpp2
-rw-r--r--cmds/statsd/Android.bp14
-rw-r--r--cmds/statsd/src/FieldValue.cpp19
-rw-r--r--cmds/statsd/src/FieldValue.h4
-rw-r--r--cmds/statsd/src/HashableDimensionKey.cpp4
-rw-r--r--cmds/statsd/src/HashableDimensionKey.h2
-rw-r--r--cmds/statsd/src/StatsLogProcessor.h4
-rw-r--r--cmds/statsd/src/StatsService.cpp7
-rw-r--r--cmds/statsd/src/StatsService.h5
-rw-r--r--cmds/statsd/src/atom_field_options.proto4
-rw-r--r--cmds/statsd/src/atoms.proto145
-rw-r--r--cmds/statsd/src/external/StatsPuller.cpp1
-rw-r--r--cmds/statsd/src/external/StatsPullerManager.cpp17
-rw-r--r--cmds/statsd/src/external/StatsPullerManager.h4
-rw-r--r--cmds/statsd/src/guardrail/StatsdStats.h2
-rw-r--r--cmds/statsd/src/metrics/CountMetricProducer.cpp4
-rw-r--r--cmds/statsd/src/metrics/CountMetricProducer.h4
-rw-r--r--cmds/statsd/src/metrics/DurationMetricProducer.cpp4
-rw-r--r--cmds/statsd/src/metrics/DurationMetricProducer.h4
-rw-r--r--cmds/statsd/src/metrics/EventMetricProducer.cpp4
-rw-r--r--cmds/statsd/src/metrics/EventMetricProducer.h4
-rw-r--r--cmds/statsd/src/metrics/GaugeMetricProducer.cpp39
-rw-r--r--cmds/statsd/src/metrics/GaugeMetricProducer.h7
-rw-r--r--cmds/statsd/src/metrics/MetricProducer.cpp17
-rw-r--r--cmds/statsd/src/metrics/MetricProducer.h56
-rw-r--r--cmds/statsd/src/metrics/MetricsManager.h4
-rw-r--r--cmds/statsd/src/metrics/ValueMetricProducer.cpp235
-rw-r--r--cmds/statsd/src/metrics/ValueMetricProducer.h52
-rw-r--r--cmds/statsd/src/metrics/metrics_manager_util.cpp44
-rw-r--r--cmds/statsd/src/state/StateManager.cpp10
-rw-r--r--cmds/statsd/src/state/StateManager.h11
-rw-r--r--cmds/statsd/src/stats_log.proto33
-rw-r--r--cmds/statsd/src/statsd_config.proto6
-rw-r--r--cmds/statsd/tests/FieldValue_test.cpp131
-rw-r--r--cmds/statsd/tests/e2e/CountMetric_e2e_test.cpp3
-rw-r--r--cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp162
-rw-r--r--cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp77
-rw-r--r--cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp2015
-rw-r--r--cmds/statsd/tests/state/StateTracker_test.cpp1
-rw-r--r--cmds/statsd/tests/statsd_test_util.cpp17
-rw-r--r--cmds/statsd/tests/statsd_test_util.h7
-rw-r--r--cmds/svc/src/com/android/commands/svc/DataCommand.java46
-rw-r--r--cmds/svc/src/com/android/commands/svc/Svc.java1
-rwxr-xr-xcmds/svc/svc14
-rw-r--r--core/java/android/accessibilityservice/AccessibilityButtonController.java8
-rw-r--r--core/java/android/accessibilityservice/AccessibilityService.java2
-rw-r--r--core/java/android/accessibilityservice/AccessibilityServiceInfo.java2
-rw-r--r--core/java/android/accounts/Account.java2
-rw-r--r--core/java/android/accounts/AccountAndUser.java2
-rw-r--r--core/java/android/accounts/AccountAuthenticatorResponse.java4
-rw-r--r--core/java/android/accounts/AccountManager.java2
-rw-r--r--core/java/android/accounts/AuthenticatorDescription.java4
-rw-r--r--core/java/android/animation/Animator.java2
-rw-r--r--core/java/android/animation/ArgbEvaluator.java2
-rw-r--r--core/java/android/animation/LayoutTransition.java2
-rw-r--r--core/java/android/animation/ValueAnimator.java2
-rw-r--r--core/java/android/annotation/CallbackExecutor.java10
-rw-r--r--core/java/android/annotation/RequiresPermission.java11
-rw-r--r--core/java/android/annotation/SystemApi.java22
-rw-r--r--core/java/android/app/ActionBar.java2
-rw-r--r--core/java/android/app/Activity.java29
-rw-r--r--core/java/android/app/ActivityGroup.java2
-rw-r--r--core/java/android/app/ActivityManager.java141
-rw-r--r--core/java/android/app/ActivityManagerNative.java2
-rw-r--r--core/java/android/app/ActivityOptions.java2
-rw-r--r--core/java/android/app/ActivityTaskManager.java17
-rw-r--r--core/java/android/app/ActivityThread.java69
-rw-r--r--core/java/android/app/AlarmManager.java2
-rw-r--r--core/java/android/app/AlertDialog.java2
-rw-r--r--core/java/android/app/AppGlobals.java2
-rw-r--r--core/java/android/app/AppOpsManager.aidl3
-rw-r--r--core/java/android/app/AppOpsManager.java1944
-rw-r--r--core/java/android/app/Application.java2
-rw-r--r--core/java/android/app/ApplicationLoaders.java2
-rw-r--r--core/java/android/app/ApplicationPackageManager.java2
-rw-r--r--core/java/android/app/AsyncNotedAppOp.java2
-rw-r--r--core/java/android/app/ClientTransactionHandler.java3
-rw-r--r--core/java/android/app/ContentProviderHolder.java2
-rw-r--r--core/java/android/app/ContextImpl.java2
-rw-r--r--core/java/android/app/DatePickerDialog.java2
-rw-r--r--core/java/android/app/Dialog.java2
-rw-r--r--core/java/android/app/DialogFragment.java2
-rw-r--r--core/java/android/app/DownloadManager.java2
-rw-r--r--core/java/android/app/Fragment.java2
-rw-r--r--core/java/android/app/FragmentController.java2
-rw-r--r--core/java/android/app/FragmentHostCallback.java2
-rw-r--r--core/java/android/app/FragmentManager.java2
-rw-r--r--core/java/android/app/IActivityManager.aidl5
-rw-r--r--core/java/android/app/IActivityTaskManager.aidl6
-rw-r--r--core/java/android/app/Instrumentation.java12
-rw-r--r--core/java/android/app/IntentService.java4
-rw-r--r--core/java/android/app/KeyguardManager.java34
-rw-r--r--core/java/android/app/LoadedApk.java15
-rw-r--r--core/java/android/app/LocalActivityManager.java2
-rw-r--r--core/java/android/app/NativeActivity.java2
-rw-r--r--core/java/android/app/Notification.java2
-rw-r--r--core/java/android/app/NotificationChannel.java2
-rw-r--r--core/java/android/app/NotificationChannelGroup.java2
-rw-r--r--core/java/android/app/NotificationManager.java2
-rw-r--r--core/java/android/app/PackageDeleteObserver.java2
-rw-r--r--core/java/android/app/PackageInstallObserver.java2
-rw-r--r--core/java/android/app/PendingIntent.java2
-rw-r--r--core/java/android/app/Presentation.java12
-rw-r--r--core/java/android/app/ProgressDialog.java6
-rw-r--r--core/java/android/app/QueuedWork.java2
-rw-r--r--core/java/android/app/ResourcesManager.java2
-rw-r--r--core/java/android/app/ResultInfo.java2
-rw-r--r--core/java/android/app/SearchDialog.java2
-rw-r--r--core/java/android/app/SearchManager.java2
-rw-r--r--core/java/android/app/SearchableInfo.java10
-rw-r--r--core/java/android/app/Service.java2
-rw-r--r--core/java/android/app/SharedPreferencesImpl.java2
-rw-r--r--core/java/android/app/StatsManager.java108
-rw-r--r--core/java/android/app/StatusBarManager.java2
-rw-r--r--core/java/android/app/SystemServiceRegistry.java46
-rw-r--r--core/java/android/app/TaskEmbedder.java11
-rw-r--r--core/java/android/app/TaskInfo.java2
-rw-r--r--core/java/android/app/TaskStackListener.java2
-rw-r--r--core/java/android/app/TimePickerDialog.java2
-rw-r--r--core/java/android/app/UiAutomation.java2
-rw-r--r--core/java/android/app/UiAutomationConnection.java3
-rw-r--r--core/java/android/app/UiModeManager.java2
-rw-r--r--core/java/android/app/UserSwitchObserver.java2
-rw-r--r--core/java/android/app/VrManager.java2
-rw-r--r--core/java/android/app/WallpaperManager.java144
-rw-r--r--core/java/android/app/WindowConfiguration.java23
-rw-r--r--core/java/android/app/admin/DeviceAdminInfo.java2
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java24
-rw-r--r--core/java/android/app/admin/SecurityLog.java2
-rw-r--r--core/java/android/app/assist/AssistContent.java2
-rw-r--r--core/java/android/app/backup/BackupDataInput.java2
-rw-r--r--core/java/android/app/backup/BackupDataInputStream.java5
-rw-r--r--core/java/android/app/backup/BackupDataOutput.java2
-rw-r--r--core/java/android/app/backup/BackupHelperDispatcher.java2
-rw-r--r--core/java/android/app/backup/BackupManager.java2
-rw-r--r--core/java/android/app/backup/FileBackupHelperBase.java2
-rw-r--r--core/java/android/app/backup/FullBackup.java2
-rw-r--r--core/java/android/app/backup/FullBackupDataOutput.java2
-rw-r--r--core/java/android/app/role/RoleControllerService.java15
-rw-r--r--core/java/android/app/role/RoleManager.java33
-rw-r--r--core/java/android/app/servertransaction/ActivityResultItem.java2
-rw-r--r--core/java/android/app/servertransaction/ClientTransaction.java5
-rw-r--r--core/java/android/app/servertransaction/EnterPipRequestedItem.java78
-rw-r--r--core/java/android/app/servertransaction/LaunchActivityItem.java2
-rw-r--r--core/java/android/app/servertransaction/NewIntentItem.java2
-rw-r--r--core/java/android/app/trust/TrustManager.java2
-rw-r--r--core/java/android/app/usage/ConfigurationStats.java2
-rw-r--r--core/java/android/app/usage/IStorageStatsManager.aidl8
-rw-r--r--core/java/android/app/usage/NetworkStatsManager.java2
-rw-r--r--core/java/android/app/usage/StorageStatsManager.java101
-rw-r--r--core/java/android/app/usage/UsageEvents.java2
-rw-r--r--core/java/android/app/usage/UsageStats.java2
-rw-r--r--core/java/android/app/usage/UsageStatsManager.java2
-rw-r--r--core/java/android/appwidget/AppWidgetHost.java2
-rw-r--r--core/java/android/appwidget/AppWidgetHostView.java2
-rw-r--r--core/java/android/appwidget/AppWidgetManager.java2
-rw-r--r--core/java/android/appwidget/AppWidgetProviderInfo.java2
-rw-r--r--core/java/android/bluetooth/BluetoothA2dp.java2
-rwxr-xr-xcore/java/android/bluetooth/BluetoothA2dpSink.java2
-rw-r--r--core/java/android/bluetooth/BluetoothAdapter.java2
-rwxr-xr-xcore/java/android/bluetooth/BluetoothClass.java2
-rw-r--r--core/java/android/bluetooth/BluetoothCodecConfig.java2
-rw-r--r--core/java/android/bluetooth/BluetoothDevice.java2
-rw-r--r--core/java/android/bluetooth/BluetoothGatt.java2
-rw-r--r--core/java/android/bluetooth/BluetoothGattCharacteristic.java2
-rw-r--r--core/java/android/bluetooth/BluetoothGattDescriptor.java2
-rw-r--r--core/java/android/bluetooth/BluetoothGattService.java2
-rw-r--r--core/java/android/bluetooth/BluetoothHeadset.java2
-rw-r--r--core/java/android/bluetooth/BluetoothHeadsetClient.java2
-rw-r--r--core/java/android/bluetooth/BluetoothHeadsetClientCall.java2
-rw-r--r--core/java/android/bluetooth/BluetoothHearingAid.java59
-rw-r--r--core/java/android/bluetooth/BluetoothMap.java2
-rw-r--r--core/java/android/bluetooth/BluetoothMapClient.java2
-rw-r--r--core/java/android/bluetooth/BluetoothPan.java2
-rw-r--r--core/java/android/bluetooth/BluetoothPbap.java2
-rw-r--r--core/java/android/bluetooth/BluetoothProfile.java2
-rw-r--r--core/java/android/bluetooth/BluetoothSap.java2
-rw-r--r--core/java/android/bluetooth/BluetoothServerSocket.java2
-rw-r--r--core/java/android/bluetooth/BluetoothSocket.java2
-rw-r--r--core/java/android/bluetooth/BluetoothUuid.java2
-rw-r--r--core/java/android/bluetooth/le/ScanRecord.java2
-rw-r--r--core/java/android/companion/Association.aidl18
-rw-r--r--core/java/android/companion/Association.java179
-rw-r--r--core/java/android/companion/AssociationRequest.java2
-rw-r--r--core/java/android/companion/BluetoothDeviceFilter.java2
-rw-r--r--core/java/android/companion/BluetoothDeviceFilterUtils.java2
-rw-r--r--core/java/android/companion/BluetoothLeDeviceFilter.java4
-rw-r--r--core/java/android/companion/CompanionDeviceManager.java14
-rw-r--r--core/java/android/companion/DeviceFilter.java2
-rw-r--r--core/java/android/companion/ICompanionDeviceDiscoveryService.aidl5
-rw-r--r--core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl25
-rw-r--r--core/java/android/content/AsyncTaskLoader.java2
-rw-r--r--core/java/android/content/BroadcastReceiver.java2
-rw-r--r--core/java/android/content/ClipData.java2
-rw-r--r--core/java/android/content/ClipboardManager.java7
-rw-r--r--core/java/android/content/ComponentName.java2
-rw-r--r--core/java/android/content/ContentProvider.java2
-rw-r--r--core/java/android/content/ContentProviderClient.java48
-rw-r--r--core/java/android/content/ContentProviderNative.java2
-rw-r--r--core/java/android/content/ContentResolver.java75
-rw-r--r--core/java/android/content/ContentValues.java3
-rw-r--r--core/java/android/content/Context.java25
-rw-r--r--core/java/android/content/ContextWrapper.java2
-rw-r--r--core/java/android/content/CursorEntityIterator.java2
-rw-r--r--core/java/android/content/CursorLoader.java2
-rw-r--r--core/java/android/content/Entity.java2
-rw-r--r--core/java/android/content/IContentProvider.java2
-rw-r--r--core/java/android/content/Intent.java3
-rw-r--r--core/java/android/content/IntentFilter.java2
-rw-r--r--core/java/android/content/IntentSender.java4
-rw-r--r--core/java/android/content/RestrictionsManager.java2
-rw-r--r--core/java/android/content/SearchRecentSuggestionsProvider.java2
-rw-r--r--core/java/android/content/SyncAdapterType.java6
-rw-r--r--core/java/android/content/SyncAdaptersCache.java4
-rw-r--r--core/java/android/content/SyncContext.java4
-rw-r--r--core/java/android/content/SyncInfo.java2
-rw-r--r--core/java/android/content/SyncRequest.java2
-rw-r--r--core/java/android/content/SyncStatusInfo.java2
-rw-r--r--core/java/android/content/UndoManager.java2
-rw-r--r--core/java/android/content/UndoOperation.java2
-rw-r--r--core/java/android/content/UriMatcher.java2
-rw-r--r--core/java/android/content/integrity/AppInstallMetadata.java30
-rw-r--r--core/java/android/content/integrity/Rule.java3
-rw-r--r--core/java/android/content/integrity/RuleSet.java5
-rw-r--r--core/java/android/content/om/OverlayInfo.java2
-rw-r--r--core/java/android/content/pm/ActivityInfo.java33
-rw-r--r--core/java/android/content/pm/ApplicationInfo.java2
-rw-r--r--core/java/android/content/pm/BaseParceledListSlice.java2
-rw-r--r--core/java/android/content/pm/ComponentInfo.java2
-rw-r--r--core/java/android/content/pm/DataLoaderParams.java126
-rw-r--r--core/java/android/content/pm/DataLoaderParamsParcel.aidl (renamed from core/java/android/os/incremental/IncrementalDataLoaderParamsParcel.aidl)11
-rw-r--r--core/java/android/content/pm/DataLoaderType.aidl37
-rw-r--r--core/java/android/content/pm/FileSystemControlParcel.aidl31
-rw-r--r--core/java/android/content/pm/IDataLoader.aidl5
-rw-r--r--core/java/android/content/pm/IDataLoaderStatusListener.aidl17
-rw-r--r--core/java/android/content/pm/IPackageInstallerSessionFileSystemConnector.aidl (renamed from packages/SystemUI/src/com/android/systemui/dagger/qualifiers/BgHandler.java)16
-rw-r--r--core/java/android/content/pm/LauncherActivityInfo.java2
-rw-r--r--core/java/android/content/pm/LauncherApps.java13
-rw-r--r--core/java/android/content/pm/NamedParcelFileDescriptor.aidl (renamed from core/java/android/os/incremental/NamedParcelFileDescriptor.aidl)2
-rw-r--r--core/java/android/content/pm/PackageInfo.java2
-rw-r--r--core/java/android/content/pm/PackageInfoLite.java2
-rw-r--r--core/java/android/content/pm/PackageInstaller.java119
-rw-r--r--core/java/android/content/pm/PackageItemInfo.java4
-rw-r--r--core/java/android/content/pm/PackageManager.java41
-rw-r--r--core/java/android/content/pm/PackageParser.java2
-rw-r--r--core/java/android/content/pm/PackageStats.java2
-rw-r--r--core/java/android/content/pm/PackageUserState.java2
-rw-r--r--core/java/android/content/pm/ParceledListSlice.java2
-rw-r--r--core/java/android/content/pm/PermissionInfo.java14
-rw-r--r--core/java/android/content/pm/RegisteredServicesCache.java6
-rw-r--r--core/java/android/content/pm/ResolveInfo.java2
-rw-r--r--core/java/android/content/pm/ShortcutInfo.java27
-rw-r--r--core/java/android/content/pm/ShortcutManager.java2
-rw-r--r--core/java/android/content/pm/Signature.java2
-rw-r--r--core/java/android/content/pm/UserInfo.java2
-rw-r--r--core/java/android/content/pm/VerifierInfo.java2
-rw-r--r--core/java/android/content/pm/XmlSerializerAndParser.java5
-rw-r--r--core/java/android/content/pm/parsing/AndroidPackage.java2
-rw-r--r--core/java/android/content/pm/parsing/ApkParseUtils.java3
-rw-r--r--core/java/android/content/pm/parsing/PackageImpl.java14
-rw-r--r--core/java/android/content/pm/parsing/ParsingPackage.java2
-rw-r--r--core/java/android/content/res/ApkAssets.java12
-rw-r--r--core/java/android/content/res/AssetFileDescriptor.java2
-rw-r--r--core/java/android/content/res/AssetManager.java48
-rw-r--r--core/java/android/content/res/ColorStateList.java19
-rw-r--r--core/java/android/content/res/CompatibilityInfo.java2
-rw-r--r--core/java/android/content/res/Configuration.java2
-rw-r--r--core/java/android/content/res/ConfigurationBoundResourceCache.java2
-rw-r--r--core/java/android/content/res/DrawableCache.java2
-rw-r--r--core/java/android/content/res/ObbInfo.java2
-rw-r--r--core/java/android/content/res/Resources.java2
-rw-r--r--core/java/android/content/res/ResourcesImpl.java2
-rw-r--r--core/java/android/content/res/ResourcesKey.java2
-rw-r--r--core/java/android/content/res/StringBlock.java2
-rw-r--r--core/java/android/content/res/ThemedResourceCache.java2
-rw-r--r--core/java/android/content/res/TypedArray.java2
-rw-r--r--core/java/android/content/res/XmlBlock.java2
-rw-r--r--core/java/android/content/rollback/PackageRollbackInfo.java24
-rw-r--r--core/java/android/database/sqlite/SQLiteQueryBuilder.java63
-rw-r--r--core/java/android/hardware/biometrics/BiometricManager.java10
-rw-r--r--core/java/android/hardware/biometrics/BiometricPrompt.java19
-rw-r--r--core/java/android/hardware/camera2/CameraCharacteristics.java103
-rw-r--r--core/java/android/hardware/camera2/CameraManager.java4
-rw-r--r--core/java/android/hardware/camera2/CameraMetadata.java4
-rw-r--r--core/java/android/hardware/camera2/CaptureRequest.java92
-rw-r--r--core/java/android/hardware/camera2/CaptureResult.java122
-rw-r--r--core/java/android/hardware/camera2/impl/CameraMetadataNative.java108
-rw-r--r--core/java/android/hardware/camera2/marshal/impl/MarshalQueryableCapabilityAndMaxSize.java77
-rw-r--r--core/java/android/hardware/camera2/params/Capability.java (renamed from core/java/android/hardware/camera2/params/CapabilityAndMaxSize.java)61
-rw-r--r--core/java/android/hardware/display/BrightnessConfiguration.java185
-rw-r--r--core/java/android/hardware/display/DisplayManagerInternal.java7
-rw-r--r--core/java/android/hardware/hdmi/HdmiControlManager.java18
-rw-r--r--core/java/android/hardware/hdmi/HdmiSwitchClient.java11
-rw-r--r--core/java/android/hardware/location/ContextHubClient.java18
-rw-r--r--core/java/android/hardware/location/ContextHubIntentEvent.java4
-rw-r--r--core/java/android/hardware/location/ContextHubManager.java25
-rw-r--r--core/java/android/hardware/location/ContextHubTransaction.java9
-rw-r--r--core/java/android/hardware/location/NanoApp.java8
-rw-r--r--core/java/android/hardware/usb/UsbAccessory.java5
-rw-r--r--core/java/android/hardware/usb/UsbDevice.java7
-rw-r--r--core/java/android/hardware/usb/UsbPort.java4
-rw-r--r--core/java/android/hardware/usb/UsbRequest.java3
-rw-r--r--core/java/android/inputmethodservice/InputMethodService.java15
-rw-r--r--core/java/android/net/ConnectivityManager.java174
-rw-r--r--core/java/android/net/IConnectivityManager.aidl43
-rw-r--r--core/java/android/net/LinkProperties.java70
-rw-r--r--core/java/android/net/MatchAllNetworkSpecifier.java9
-rw-r--r--core/java/android/net/NetworkCapabilities.java38
-rw-r--r--core/java/android/net/StringNetworkSpecifier.java13
-rw-r--r--core/java/android/net/nsd/NsdServiceInfo.java6
-rw-r--r--core/java/android/nfc/ErrorCodes.java2
-rw-r--r--core/java/android/nfc/INfcCardEmulation.aidl1
-rw-r--r--core/java/android/nfc/NdefRecord.java2
-rw-r--r--core/java/android/nfc/NfcActivityManager.java3
-rw-r--r--core/java/android/nfc/NfcAdapter.java27
-rw-r--r--core/java/android/nfc/NfcManager.java2
-rw-r--r--core/java/android/nfc/Tag.java2
-rw-r--r--core/java/android/nfc/cardemulation/AidGroup.java14
-rw-r--r--core/java/android/nfc/cardemulation/ApduServiceInfo.java2
-rw-r--r--core/java/android/nfc/cardemulation/CardEmulation.java104
-rw-r--r--core/java/android/os/AsyncResult.java3
-rw-r--r--core/java/android/os/AsyncTask.java2
-rw-r--r--core/java/android/os/BaseBundle.java2
-rw-r--r--core/java/android/os/BatteryManager.java2
-rw-r--r--core/java/android/os/BatteryStats.java2
-rw-r--r--core/java/android/os/Binder.java2
-rw-r--r--core/java/android/os/Broadcaster.java2
-rwxr-xr-xcore/java/android/os/Build.java2
-rw-r--r--core/java/android/os/Bundle.java2
-rw-r--r--core/java/android/os/CancellationSignal.java4
-rw-r--r--core/java/android/os/Debug.java41
-rw-r--r--core/java/android/os/DropBoxManager.java2
-rw-r--r--core/java/android/os/Environment.java2
-rw-r--r--core/java/android/os/FileObserver.java2
-rw-r--r--core/java/android/os/FileUtils.java2
-rw-r--r--core/java/android/os/Handler.java2
-rw-r--r--core/java/android/os/HwBinder.java2
-rw-r--r--core/java/android/os/HwParcel.java2
-rw-r--r--core/java/android/os/HwRemoteBinder.java3
-rw-r--r--core/java/android/os/IBinder.java2
-rw-r--r--core/java/android/os/IVibratorService.aidl1
-rw-r--r--core/java/android/os/LocaleList.java2
-rw-r--r--core/java/android/os/Looper.java2
-rw-r--r--core/java/android/os/MemoryFile.java2
-rw-r--r--core/java/android/os/Message.java2
-rw-r--r--core/java/android/os/MessageQueue.java3
-rw-r--r--core/java/android/os/Parcel.java2
-rw-r--r--core/java/android/os/ParcelFileDescriptor.java2
-rw-r--r--core/java/android/os/ParcelUuid.java2
-rw-r--r--core/java/android/os/ParcelableParcel.java2
-rw-r--r--core/java/android/os/PerformanceCollector.java3
-rw-r--r--core/java/android/os/PowerManager.java26
-rw-r--r--core/java/android/os/Process.java17
-rw-r--r--core/java/android/os/RecoverySystem.java2
-rw-r--r--core/java/android/os/Registrant.java4
-rw-r--r--core/java/android/os/RegistrantList.java2
-rw-r--r--core/java/android/os/RemoteCallback.java3
-rw-r--r--core/java/android/os/RemoteCallbackList.java2
-rw-r--r--core/java/android/os/SELinux.java2
-rw-r--r--core/java/android/os/ServiceManager.java2
-rw-r--r--core/java/android/os/ServiceManagerNative.java11
-rw-r--r--core/java/android/os/SharedMemory.java2
-rw-r--r--core/java/android/os/ShellCommand.java2
-rw-r--r--core/java/android/os/StatFs.java2
-rw-r--r--core/java/android/os/StrictMode.java2
-rw-r--r--core/java/android/os/SystemClock.java2
-rw-r--r--core/java/android/os/SystemProperties.java2
-rw-r--r--core/java/android/os/SystemService.java3
-rw-r--r--core/java/android/os/SystemVibrator.java16
-rw-r--r--core/java/android/os/Trace.java4
-rw-r--r--core/java/android/os/UEventObserver.java2
-rw-r--r--core/java/android/os/UpdateLock.java2
-rw-r--r--core/java/android/os/UserHandle.java2
-rw-r--r--core/java/android/os/UserManager.java15
-rw-r--r--core/java/android/os/VibrationEffect.java3
-rw-r--r--core/java/android/os/Vibrator.java21
-rw-r--r--core/java/android/os/VintfObject.java30
-rw-r--r--core/java/android/os/WorkSource.java3
-rw-r--r--core/java/android/os/ZygoteProcess.java37
-rw-r--r--core/java/android/os/health/HealthStatsParceler.java3
-rw-r--r--core/java/android/os/health/SystemHealthManager.java3
-rw-r--r--core/java/android/os/incremental/IIncrementalManager.aidl8
-rw-r--r--core/java/android/os/incremental/IIncrementalManagerNative.aidl4
-rw-r--r--core/java/android/os/incremental/IncrementalDataLoaderParams.java84
-rw-r--r--core/java/android/os/incremental/IncrementalFileStorages.java11
-rw-r--r--core/java/android/os/incremental/IncrementalManager.java9
-rw-r--r--core/java/android/os/storage/CrateInfo.aidl21
-rw-r--r--core/java/android/os/storage/CrateInfo.java282
-rw-r--r--core/java/android/os/storage/DiskInfo.java2
-rw-r--r--core/java/android/os/storage/StorageEventListener.java2
-rw-r--r--core/java/android/os/storage/StorageManager.java2
-rw-r--r--core/java/android/os/storage/StorageVolume.java2
-rw-r--r--core/java/android/os/storage/VolumeInfo.java2
-rw-r--r--core/java/android/os/storage/VolumeRecord.java2
-rw-r--r--core/java/android/permission/IPermissionController.aidl1
-rw-r--r--core/java/android/permission/IPermissionManager.aidl6
-rw-r--r--core/java/android/permission/PermissionControllerManager.java14
-rw-r--r--core/java/android/permission/PermissionControllerService.java21
-rw-r--r--core/java/android/permission/PermissionManager.java66
-rw-r--r--core/java/android/preference/DialogPreference.java2
-rw-r--r--core/java/android/preference/EditTextPreference.java2
-rw-r--r--core/java/android/preference/ListPreference.java2
-rw-r--r--core/java/android/preference/Preference.java2
-rw-r--r--core/java/android/preference/PreferenceActivity.java2
-rw-r--r--core/java/android/preference/PreferenceFragment.java2
-rw-r--r--core/java/android/preference/PreferenceGroupAdapter.java2
-rw-r--r--core/java/android/preference/PreferenceManager.java2
-rw-r--r--core/java/android/preference/PreferenceScreen.java2
-rw-r--r--core/java/android/preference/RingtonePreference.java2
-rw-r--r--core/java/android/preference/SeekBarDialogPreference.java2
-rw-r--r--core/java/android/preference/SeekBarPreference.java2
-rw-r--r--core/java/android/preference/SeekBarVolumizer.java2
-rw-r--r--core/java/android/preference/SwitchPreference.java2
-rw-r--r--core/java/android/preference/TwoStatePreference.java2
-rw-r--r--core/java/android/preference/VolumePreference.java2
-rw-r--r--core/java/android/print/PrintDocumentAdapter.java2
-rw-r--r--core/java/android/print/PrintJobInfo.java2
-rw-r--r--core/java/android/print/PrintManager.java2
-rw-r--r--core/java/android/print/PrinterId.java2
-rw-r--r--core/java/android/provider/Browser.java6
-rw-r--r--core/java/android/provider/BrowserContract.java2
-rw-r--r--core/java/android/provider/CalendarContract.java2
-rw-r--r--core/java/android/provider/CallLog.java2
-rw-r--r--core/java/android/provider/Column.java50
-rw-r--r--core/java/android/provider/ContactsContract.java2
-rw-r--r--core/java/android/provider/MediaStore.java3832
-rw-r--r--core/java/android/provider/Settings.java200
-rw-r--r--core/java/android/provider/Telephony.java1
-rw-r--r--core/java/android/se/omapi/SEService.java26
-rw-r--r--core/java/android/security/FileIntegrityManager.java77
-rw-r--r--core/java/android/security/IFileIntegrityService.aidl (renamed from packages/SystemUI/src/com/android/systemui/dagger/qualifiers/MainLooper.java)22
-rw-r--r--core/java/android/security/keystore/recovery/KeyChainProtectionParams.java7
-rw-r--r--core/java/android/security/keystore/recovery/KeyChainSnapshot.java7
-rw-r--r--core/java/android/security/keystore/recovery/KeyDerivationParams.java5
-rw-r--r--core/java/android/security/keystore/recovery/RecoveryCertPath.java9
-rw-r--r--core/java/android/security/keystore/recovery/WrappedApplicationKey.java10
-rw-r--r--core/java/android/service/autofill/Dataset.aidl (renamed from core/java/android/service/controls/ControlState.aidl)6
-rw-r--r--core/java/android/service/autofill/augmented/AugmentedAutofillService.java8
-rw-r--r--core/java/android/service/autofill/augmented/FillRequest.java91
-rw-r--r--core/java/android/service/autofill/augmented/FillResponse.java178
-rw-r--r--core/java/android/service/autofill/augmented/IFillCallback.aidl4
-rw-r--r--core/java/android/service/controls/Control.java393
-rw-r--r--core/java/android/service/controls/ControlState.java389
-rw-r--r--core/java/android/service/controls/ControlsProviderService.java226
-rw-r--r--core/java/android/service/controls/DeviceTypes.java173
-rw-r--r--core/java/android/service/controls/IControlsProvider.aidl2
-rw-r--r--core/java/android/service/controls/IControlsProviderCallback.aidl7
-rw-r--r--core/java/android/service/controls/actions/BooleanAction.aidl (renamed from core/java/android/service/controls/BooleanAction.aidl)2
-rw-r--r--core/java/android/service/controls/actions/BooleanAction.java (renamed from core/java/android/service/controls/BooleanAction.java)14
-rw-r--r--core/java/android/service/controls/actions/CommandAction.aidl18
-rw-r--r--core/java/android/service/controls/actions/CommandAction.java61
-rw-r--r--core/java/android/service/controls/actions/ControlAction.aidl (renamed from core/java/android/service/controls/ControlAction.aidl)2
-rw-r--r--core/java/android/service/controls/actions/ControlAction.java (renamed from core/java/android/service/controls/ControlAction.java)63
-rw-r--r--core/java/android/service/controls/actions/FloatAction.aidl (renamed from core/java/android/service/controls/FloatAction.aidl)2
-rw-r--r--core/java/android/service/controls/actions/FloatAction.java (renamed from core/java/android/service/controls/FloatAction.java)11
-rw-r--r--core/java/android/service/controls/actions/ModeAction.aidl19
-rw-r--r--core/java/android/service/controls/actions/ModeAction.java77
-rw-r--r--core/java/android/service/controls/actions/MultiFloatAction.aidl18
-rw-r--r--core/java/android/service/controls/actions/MultiFloatAction.java91
-rw-r--r--core/java/android/service/controls/templates/ControlButton.aidl (renamed from core/java/android/service/controls/ControlButton.aidl)2
-rw-r--r--core/java/android/service/controls/templates/ControlButton.java (renamed from core/java/android/service/controls/ControlButton.java)39
-rw-r--r--core/java/android/service/controls/templates/ControlTemplate.aidl (renamed from core/java/android/service/controls/ControlTemplate.aidl)2
-rw-r--r--core/java/android/service/controls/templates/ControlTemplate.java (renamed from core/java/android/service/controls/ControlTemplate.java)44
-rw-r--r--core/java/android/service/controls/templates/CoordinatedRangeTemplate.aidl19
-rw-r--r--core/java/android/service/controls/templates/CoordinatedRangeTemplate.java177
-rw-r--r--core/java/android/service/controls/templates/DiscreteToggleTemplate.aidl18
-rw-r--r--core/java/android/service/controls/templates/DiscreteToggleTemplate.java (renamed from core/java/android/service/controls/DiscreteToggleTemplate.java)15
-rw-r--r--core/java/android/service/controls/templates/RangeTemplate.aidl (renamed from core/java/android/service/controls/RangeTemplate.aidl)2
-rw-r--r--core/java/android/service/controls/templates/RangeTemplate.java (renamed from core/java/android/service/controls/RangeTemplate.java)27
-rw-r--r--core/java/android/service/controls/templates/StatelessTemplate.aidl19
-rw-r--r--core/java/android/service/controls/templates/StatelessTemplate.java52
-rw-r--r--core/java/android/service/controls/templates/TemperatureControlTemplate.java192
-rw-r--r--core/java/android/service/controls/templates/ThermostatTemplate.aidl19
-rw-r--r--core/java/android/service/controls/templates/ThumbnailTemplate.aidl (renamed from core/java/android/service/controls/ThumbnailTemplate.aidl)2
-rw-r--r--core/java/android/service/controls/templates/ThumbnailTemplate.java (renamed from core/java/android/service/controls/ThumbnailTemplate.java)9
-rw-r--r--core/java/android/service/controls/templates/ToggleRangeTemplate.aidl19
-rw-r--r--core/java/android/service/controls/templates/ToggleRangeTemplate.java104
-rw-r--r--core/java/android/service/controls/templates/ToggleTemplate.aidl (renamed from core/java/android/service/controls/ToggleTemplate.aidl)2
-rw-r--r--core/java/android/service/controls/templates/ToggleTemplate.java (renamed from core/java/android/service/controls/ToggleTemplate.java)23
-rw-r--r--core/java/android/service/dataloader/DataLoaderService.java245
-rw-r--r--core/java/android/service/incremental/IncrementalDataLoaderService.java563
-rw-r--r--core/java/android/speech/tts/TextToSpeech.java6
-rw-r--r--core/java/android/telephony/PhoneStateListener.java19
-rw-r--r--core/java/android/telephony/TelephonyRegistryManager.java9
-rw-r--r--core/java/android/util/CloseGuard.java9
-rw-r--r--core/java/android/util/proto/ProtoOutputStream.java316
-rw-r--r--core/java/android/util/proto/ProtoStream.java322
-rw-r--r--core/java/android/util/proto/ProtoUtils.java4
-rw-r--r--core/java/android/util/proto/TEST_MAPPING5
-rw-r--r--core/java/android/util/proto/package.html4
-rw-r--r--core/java/android/view/Choreographer.java2
-rw-r--r--core/java/android/view/ContextThemeWrapper.java2
-rw-r--r--core/java/android/view/Display.java78
-rw-r--r--core/java/android/view/DisplayAdjustments.java2
-rw-r--r--core/java/android/view/DisplayEventReceiver.java2
-rw-r--r--core/java/android/view/DisplayInfo.java14
-rw-r--r--core/java/android/view/DisplayListCanvas.java2
-rw-r--r--core/java/android/view/DragEvent.java2
-rw-r--r--core/java/android/view/FrameMetrics.java2
-rw-r--r--core/java/android/view/FrameMetricsObserver.java61
-rw-r--r--core/java/android/view/GestureDetector.java2
-rw-r--r--core/java/android/view/GhostView.java2
-rw-r--r--core/java/android/view/IPinnedStackController.aidl13
-rw-r--r--core/java/android/view/IWindowSession.aidl2
-rw-r--r--core/java/android/view/InputChannel.java2
-rw-r--r--core/java/android/view/InputDevice.java2
-rw-r--r--core/java/android/view/InputEvent.java2
-rw-r--r--core/java/android/view/InputEventConsistencyVerifier.java2
-rw-r--r--core/java/android/view/InputEventReceiver.java5
-rw-r--r--core/java/android/view/InputEventSender.java2
-rw-r--r--core/java/android/view/InputFilter.java2
-rw-r--r--core/java/android/view/InputQueue.java2
-rw-r--r--core/java/android/view/InputWindowHandle.java4
-rw-r--r--core/java/android/view/InsetsAnimationControlCallbacks.java55
-rw-r--r--core/java/android/view/InsetsAnimationControlImpl.java67
-rw-r--r--core/java/android/view/InsetsController.java50
-rw-r--r--core/java/android/view/InsetsSourceControl.java11
-rw-r--r--core/java/android/view/KeyCharacterMap.java2
-rw-r--r--core/java/android/view/KeyEvent.java2
-rw-r--r--core/java/android/view/LayoutInflater.java5
-rw-r--r--core/java/android/view/MotionEvent.java2
-rw-r--r--core/java/android/view/NotificationHeaderView.java2
-rw-r--r--core/java/android/view/PointerIcon.java2
-rw-r--r--core/java/android/view/RemoteAnimationAdapter.java2
-rw-r--r--core/java/android/view/RemoteAnimationDefinition.java19
-rw-r--r--core/java/android/view/RemoteAnimationTarget.java2
-rw-r--r--core/java/android/view/RenderNodeAnimator.java2
-rw-r--r--core/java/android/view/ScaleGestureDetector.java2
-rw-r--r--core/java/android/view/Surface.java2
-rw-r--r--core/java/android/view/SurfaceControl.java242
-rw-r--r--core/java/android/view/SurfaceControlViewHost.java (renamed from core/java/android/view/WindowlessViewRoot.java)40
-rw-r--r--core/java/android/view/SurfaceSession.java2
-rw-r--r--core/java/android/view/SurfaceView.java65
-rw-r--r--core/java/android/view/TextureView.java2
-rw-r--r--core/java/android/view/TouchDelegate.java2
-rw-r--r--core/java/android/view/VelocityTracker.java2
-rw-r--r--core/java/android/view/View.java39
-rw-r--r--core/java/android/view/ViewConfiguration.java2
-rw-r--r--core/java/android/view/ViewDebug.java2
-rw-r--r--core/java/android/view/ViewGroup.java6
-rw-r--r--core/java/android/view/ViewHierarchyEncoder.java2
-rw-r--r--core/java/android/view/ViewOverlay.java2
-rw-r--r--core/java/android/view/ViewRootImpl.java55
-rw-r--r--core/java/android/view/ViewTreeObserver.java2
-rw-r--r--core/java/android/view/Window.java40
-rw-r--r--core/java/android/view/WindowAnimationFrameStats.java2
-rw-r--r--core/java/android/view/WindowContentFrameStats.java2
-rw-r--r--core/java/android/view/WindowInsets.java2
-rw-r--r--core/java/android/view/WindowManager.java42
-rw-r--r--core/java/android/view/WindowManagerGlobal.java2
-rw-r--r--core/java/android/view/WindowManagerImpl.java2
-rw-r--r--core/java/android/view/WindowlessWindowManager.java2
-rw-r--r--core/java/android/view/accessibility/AccessibilityEvent.java2
-rw-r--r--core/java/android/view/accessibility/AccessibilityInteractionClient.java2
-rw-r--r--core/java/android/view/accessibility/AccessibilityManager.java2
-rw-r--r--core/java/android/view/accessibility/AccessibilityNodeInfo.java2
-rw-r--r--core/java/android/view/accessibility/AccessibilityRecord.java2
-rw-r--r--core/java/android/view/accessibility/CaptioningManager.java2
-rw-r--r--core/java/android/view/animation/Animation.java2
-rw-r--r--core/java/android/view/animation/AnimationUtils.java2
-rw-r--r--core/java/android/view/animation/Transformation.java2
-rw-r--r--core/java/android/view/animation/TranslateAnimation.java2
-rw-r--r--core/java/android/view/animation/TranslateYAnimation.java2
-rw-r--r--core/java/android/view/autofill/AutofillValue.java8
-rw-r--r--core/java/android/view/inline/InlinePresentationSpec.java69
-rw-r--r--core/java/android/view/inputmethod/InlineSuggestionsRequest.java38
-rw-r--r--core/java/android/view/inputmethod/InputMethodInfo.java2
-rw-r--r--core/java/android/view/inputmethod/InputMethodManager.java4
-rw-r--r--core/java/android/view/inputmethod/InputMethodSubtypeArray.java2
-rw-r--r--core/java/android/view/textclassifier/ConversationAction.java9
-rw-r--r--core/java/android/view/textclassifier/ConversationActions.java13
-rw-r--r--core/java/android/view/textclassifier/EntityConfidence.java7
-rw-r--r--core/java/android/view/textclassifier/GenerateLinksLogger.java7
-rw-r--r--core/java/android/view/textclassifier/ModelFileManager.java21
-rw-r--r--core/java/android/view/textclassifier/SelectionEvent.java10
-rw-r--r--core/java/android/view/textclassifier/SelectionSessionLogger.java13
-rw-r--r--core/java/android/view/textclassifier/SystemTextClassifier.java22
-rw-r--r--core/java/android/view/textclassifier/TextClassification.java4
-rw-r--r--core/java/android/view/textclassifier/TextClassificationContext.java11
-rw-r--r--core/java/android/view/textclassifier/TextClassificationManager.java16
-rw-r--r--core/java/android/view/textclassifier/TextClassificationSession.java9
-rw-r--r--core/java/android/view/textclassifier/TextClassificationSessionId.java5
-rw-r--r--core/java/android/view/textclassifier/TextClassifier.java17
-rw-r--r--core/java/android/view/textclassifier/TextClassifierEvent.java8
-rw-r--r--core/java/android/view/textclassifier/TextClassifierEventTronLogger.java6
-rw-r--r--core/java/android/view/textclassifier/TextClassifierImpl.java16
-rw-r--r--core/java/android/view/textclassifier/TextLinks.java47
-rw-r--r--core/java/android/view/textclassifier/TextLinksParams.java7
-rw-r--r--core/java/android/view/textclassifier/TextSelection.java3
-rw-r--r--core/java/android/view/textclassifier/intent/LabeledIntent.java11
-rw-r--r--core/java/android/view/textclassifier/intent/TemplateClassificationIntentFactory.java5
-rw-r--r--core/java/android/view/textclassifier/logging/SmartSelectionEventTracker.java12
-rw-r--r--core/java/android/view/textservice/SpellCheckerSession.java2
-rw-r--r--core/java/android/view/textservice/TextServicesManager.java2
-rw-r--r--core/java/android/webkit/CacheManager.java2
-rw-r--r--core/java/android/webkit/ConsoleMessage.java2
-rw-r--r--core/java/android/webkit/JsResult.java2
-rw-r--r--core/java/android/webkit/PluginData.java3
-rw-r--r--core/java/android/webkit/URLUtil.java2
-rw-r--r--core/java/android/webkit/UrlInterceptHandler.java3
-rw-r--r--core/java/android/webkit/UrlInterceptRegistry.java4
-rw-r--r--core/java/android/webkit/WebResourceResponse.java2
-rw-r--r--core/java/android/webkit/WebSettings.java2
-rw-r--r--core/java/android/webkit/WebSyncManager.java2
-rw-r--r--core/java/android/webkit/WebView.java2
-rw-r--r--core/java/android/webkit/WebViewDelegate.java2
-rw-r--r--core/java/android/webkit/WebViewFactory.java2
-rw-r--r--core/java/android/webkit/WebViewProviderInfo.java2
-rw-r--r--core/java/android/webkit/WebViewProviderResponse.java2
-rw-r--r--core/java/android/webkit/WebViewUpdateService.java2
-rw-r--r--core/java/android/widget/AbsListView.java2
-rw-r--r--core/java/android/widget/AbsSeekBar.java2
-rw-r--r--core/java/android/widget/ActionMenuPresenter.java2
-rw-r--r--core/java/android/widget/ActionMenuView.java2
-rw-r--r--core/java/android/widget/ActivityChooserModel.java2
-rw-r--r--core/java/android/widget/ActivityChooserView.java2
-rw-r--r--core/java/android/widget/AdapterView.java2
-rw-r--r--core/java/android/widget/AnalogClock.java2
-rw-r--r--core/java/android/widget/ArrayAdapter.java2
-rw-r--r--core/java/android/widget/AutoCompleteTextView.java2
-rw-r--r--core/java/android/widget/BaseAdapter.java2
-rw-r--r--core/java/android/widget/CalendarView.java2
-rw-r--r--core/java/android/widget/CheckedTextView.java2
-rw-r--r--core/java/android/widget/Editor.java132
-rw-r--r--core/java/android/widget/EditorTouchState.java33
-rw-r--r--core/java/android/widget/Switch.java3
-rw-r--r--core/java/android/widget/TextView.java4
-rw-r--r--core/java/android/widget/ToggleButton.java3
-rw-r--r--core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java7
-rw-r--r--core/java/com/android/internal/app/AccessibilityButtonChooserActivity.java73
-rw-r--r--core/java/com/android/internal/app/ChooserActivity.java102
-rw-r--r--core/java/com/android/internal/app/ChooserStackedAppDialogFragment.java20
-rw-r--r--core/java/com/android/internal/app/IAppOpsService.aidl5
-rw-r--r--core/java/com/android/internal/app/ResolverActivity.java56
-rw-r--r--core/java/com/android/internal/app/ResolverTargetActionsDialogFragment.java2
-rw-r--r--core/java/com/android/internal/app/SuspendedAppActivity.java11
-rw-r--r--core/java/com/android/internal/app/chooser/MultiDisplayResolveInfo.java41
-rw-r--r--core/java/com/android/internal/content/FileSystemProvider.java19
-rw-r--r--core/java/com/android/internal/content/PackageMonitor.java4
-rw-r--r--core/java/com/android/internal/infra/AndroidFuture.aidl2
-rw-r--r--core/java/com/android/internal/infra/PerUser.java59
-rw-r--r--core/java/com/android/internal/infra/ServiceConnector.java6
-rw-r--r--core/java/com/android/internal/infra/WhitelistHelper.java9
-rw-r--r--core/java/com/android/internal/os/FuseAppLoop.java11
-rw-r--r--core/java/com/android/internal/os/Zygote.java28
-rw-r--r--core/java/com/android/internal/os/ZygoteArguments.java8
-rw-r--r--core/java/com/android/internal/os/ZygoteConnection.java2
-rw-r--r--core/java/com/android/internal/os/ZygoteServer.java3
-rw-r--r--core/java/com/android/internal/telephony/IPhoneStateListener.aidl7
-rw-r--r--core/java/com/android/internal/telephony/ITelephonyRegistry.aidl8
-rw-r--r--core/java/com/android/internal/util/ArrayUtils.java43
-rw-r--r--core/java/com/android/internal/util/FileRotator.java7
-rw-r--r--core/java/com/android/internal/util/FunctionalUtils.java33
-rw-r--r--core/java/com/android/internal/util/MemInfoReader.java19
-rw-r--r--core/java/com/android/internal/util/ObjectUtils.java3
-rwxr-xr-xcore/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java3
-rw-r--r--core/java/com/android/internal/view/FloatingActionMode.java12
-rw-r--r--core/java/com/android/internal/view/menu/StandardMenuPopup.java4
-rw-r--r--core/java/com/android/internal/widget/FloatingToolbar.java26
-rw-r--r--core/java/com/android/internal/widget/LockscreenCredential.java3
-rw-r--r--core/jni/Android.bp4
-rw-r--r--core/jni/AndroidRuntime.cpp2
-rw-r--r--core/jni/android/graphics/apex/jni_runtime.cpp4
-rw-r--r--core/jni/android_graphics_HardwareRendererObserver.cpp130
-rw-r--r--core/jni/android_graphics_HardwareRendererObserver.h75
-rw-r--r--core/jni/android_hardware_input_InputWindowHandle.cpp6
-rw-r--r--core/jni/android_media_AudioFormat.h5
-rw-r--r--core/jni/android_os_Debug.cpp81
-rw-r--r--core/jni/android_os_VintfObject.cpp22
-rw-r--r--core/jni/android_os_incremental_IncrementalManager.cpp46
-rw-r--r--core/jni/android_service_DataLoaderService.cpp209
-rw-r--r--core/jni/android_view_FrameMetricsObserver.cpp149
-rw-r--r--core/jni/android_view_FrameMetricsObserver.h71
-rw-r--r--core/jni/android_view_SurfaceControl.cpp118
-rw-r--r--core/jni/android_view_ThreadedRenderer.cpp29
-rw-r--r--core/jni/com_android_internal_os_Zygote.cpp307
-rw-r--r--core/jni/fd_utils.cpp4
-rw-r--r--core/proto/android/app/settings_enums.proto67
-rw-r--r--core/proto/android/providers/settings/secure.proto2
-rw-r--r--core/proto/android/server/activitymanagerservice.proto3
-rw-r--r--core/proto/android/stats/docsui/docsui_enums.proto1
-rw-r--r--core/proto/android/util/quotatracker.proto26
-rw-r--r--core/res/AndroidManifest.xml72
-rw-r--r--core/res/res/layout/accessibility_button_chooser.xml73
-rw-r--r--core/res/res/layout/accessibility_button_chooser_item.xml51
-rw-r--r--core/res/res/values-af/strings.xml39
-rw-r--r--core/res/res/values-am/strings.xml39
-rw-r--r--core/res/res/values-ar/strings.xml41
-rw-r--r--core/res/res/values-as/strings.xml39
-rw-r--r--core/res/res/values-az/strings.xml39
-rw-r--r--core/res/res/values-b+sr+Latn/strings.xml39
-rw-r--r--core/res/res/values-be/strings.xml39
-rw-r--r--core/res/res/values-bg/strings.xml39
-rw-r--r--core/res/res/values-bn/strings.xml39
-rw-r--r--core/res/res/values-bs/strings.xml39
-rw-r--r--core/res/res/values-ca/strings.xml39
-rw-r--r--core/res/res/values-cs/strings.xml39
-rw-r--r--core/res/res/values-da/strings.xml41
-rw-r--r--core/res/res/values-de/strings.xml39
-rw-r--r--core/res/res/values-el/strings.xml39
-rw-r--r--core/res/res/values-en-rAU/strings.xml39
-rw-r--r--core/res/res/values-en-rCA/strings.xml39
-rw-r--r--core/res/res/values-en-rGB/strings.xml39
-rw-r--r--core/res/res/values-en-rIN/strings.xml39
-rw-r--r--core/res/res/values-en-rXC/strings.xml39
-rw-r--r--core/res/res/values-es-rUS/strings.xml41
-rw-r--r--core/res/res/values-es/strings.xml39
-rw-r--r--core/res/res/values-et/strings.xml39
-rw-r--r--core/res/res/values-eu/strings.xml39
-rw-r--r--core/res/res/values-fa/strings.xml41
-rw-r--r--core/res/res/values-fi/strings.xml39
-rw-r--r--core/res/res/values-fr-rCA/strings.xml39
-rw-r--r--core/res/res/values-fr/strings.xml39
-rw-r--r--core/res/res/values-gl/strings.xml43
-rw-r--r--core/res/res/values-gu/strings.xml43
-rw-r--r--core/res/res/values-hi/strings.xml49
-rw-r--r--core/res/res/values-hr/strings.xml39
-rw-r--r--core/res/res/values-hu/strings.xml39
-rw-r--r--core/res/res/values-hy/strings.xml41
-rw-r--r--core/res/res/values-in/strings.xml43
-rw-r--r--core/res/res/values-is/strings.xml39
-rw-r--r--core/res/res/values-it/strings.xml41
-rw-r--r--core/res/res/values-iw/strings.xml45
-rw-r--r--core/res/res/values-ja/strings.xml39
-rw-r--r--core/res/res/values-ka/strings.xml39
-rw-r--r--core/res/res/values-kk/strings.xml39
-rw-r--r--core/res/res/values-km/strings.xml39
-rw-r--r--core/res/res/values-kn/strings.xml41
-rw-r--r--core/res/res/values-ko/strings.xml39
-rw-r--r--core/res/res/values-ky/strings.xml49
-rw-r--r--core/res/res/values-lo/strings.xml39
-rw-r--r--core/res/res/values-lt/strings.xml39
-rw-r--r--core/res/res/values-lv/strings.xml39
-rw-r--r--core/res/res/values-mk/strings.xml39
-rw-r--r--core/res/res/values-ml/strings.xml39
-rw-r--r--core/res/res/values-mn/strings.xml45
-rw-r--r--core/res/res/values-mr/strings.xml41
-rw-r--r--core/res/res/values-ms/strings.xml39
-rw-r--r--core/res/res/values-my/strings.xml39
-rw-r--r--core/res/res/values-nb/strings.xml41
-rw-r--r--core/res/res/values-ne/strings.xml41
-rw-r--r--core/res/res/values-nl/strings.xml41
-rw-r--r--core/res/res/values-or/strings.xml39
-rw-r--r--core/res/res/values-pa/strings.xml39
-rw-r--r--core/res/res/values-pl/strings.xml39
-rw-r--r--core/res/res/values-pt-rBR/strings.xml39
-rw-r--r--core/res/res/values-pt-rPT/strings.xml39
-rw-r--r--core/res/res/values-pt/strings.xml39
-rw-r--r--core/res/res/values-ro/strings.xml39
-rw-r--r--core/res/res/values-ru/strings.xml39
-rw-r--r--core/res/res/values-si/strings.xml39
-rw-r--r--core/res/res/values-sk/strings.xml39
-rw-r--r--core/res/res/values-sl/strings.xml37
-rw-r--r--core/res/res/values-sq/strings.xml39
-rw-r--r--core/res/res/values-sr/strings.xml39
-rw-r--r--core/res/res/values-sv/strings.xml39
-rw-r--r--core/res/res/values-sw/strings.xml39
-rw-r--r--core/res/res/values-ta/strings.xml41
-rw-r--r--core/res/res/values-te/strings.xml39
-rw-r--r--core/res/res/values-th/strings.xml39
-rw-r--r--core/res/res/values-tl/strings.xml39
-rw-r--r--core/res/res/values-tr/strings.xml39
-rw-r--r--core/res/res/values-uk/strings.xml45
-rw-r--r--core/res/res/values-ur/strings.xml39
-rw-r--r--core/res/res/values-uz/strings.xml39
-rw-r--r--core/res/res/values-vi/strings.xml39
-rw-r--r--core/res/res/values-zh-rCN/strings.xml39
-rw-r--r--core/res/res/values-zh-rHK/strings.xml39
-rw-r--r--core/res/res/values-zh-rTW/strings.xml39
-rw-r--r--core/res/res/values-zu/strings.xml39
-rw-r--r--core/res/res/values/attrs_manifest.xml33
-rw-r--r--core/res/res/values/config.xml46
-rw-r--r--core/res/res/values/dimens.xml5
-rw-r--r--core/res/res/values/public.xml12
-rw-r--r--core/res/res/values/strings.xml20
-rw-r--r--core/res/res/values/symbols.xml20
-rw-r--r--core/tests/coretests/AndroidManifest.xml1
-rw-r--r--core/tests/coretests/src/android/app/PullAtomMetadataTest.java85
-rw-r--r--core/tests/coretests/src/android/app/activity/ActivityManagerTest.java122
-rw-r--r--core/tests/coretests/src/android/app/activity/ActivityThreadTest.java77
-rw-r--r--core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java40
-rw-r--r--core/tests/coretests/src/android/os/PowerManagerTest.java13
-rw-r--r--core/tests/coretests/src/android/service/controls/ControlActionTest.java36
-rw-r--r--core/tests/coretests/src/android/service/controls/ControlTemplateTest.java154
-rw-r--r--core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java13
-rw-r--r--core/tests/coretests/src/android/view/textclassifier/ActionsSuggestionsHelperTest.java1
-rw-r--r--core/tests/coretests/src/android/view/textclassifier/TextLinksTest.java8
-rw-r--r--core/tests/coretests/src/android/widget/EditorCursorDragTest.java176
-rw-r--r--core/tests/coretests/src/android/widget/EditorTouchStateTest.java92
-rw-r--r--core/tests/coretests/src/android/widget/espresso/TextViewActions.java21
-rw-r--r--core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java11
-rw-r--r--core/tests/overlaytests/device/res/layout/layout.xml39
-rw-r--r--core/tests/overlaytests/device/res/values/config.xml12
-rw-r--r--core/tests/overlaytests/device/src/com/android/overlaytest/OverlayBaseTest.java54
-rw-r--r--core/tests/overlaytests/device/src/com/android/overlaytest/view/TestTextView.java48
-rw-r--r--core/tests/overlaytests/device/test-apps/AppOverlayOne/AndroidManifest.xml3
-rw-r--r--core/tests/overlaytests/device/test-apps/AppOverlayOne/res/layout/layout.xml39
-rw-r--r--core/tests/overlaytests/device/test-apps/AppOverlayOne/res/values/config.xml5
-rw-r--r--core/tests/overlaytests/device/test-apps/AppOverlayOne/res/xml/overlays.xml61
-rw-r--r--core/tests/systemproperties/src/android/os/SystemPropertiesTest.java2
-rw-r--r--data/etc/Android.bp9
-rw-r--r--data/etc/CleanSpec.mk2
-rw-r--r--data/etc/car/Android.bp2
-rw-r--r--data/etc/car/CleanSpec.mk50
-rw-r--r--data/etc/hiddenapi-package-whitelist.xml3
-rw-r--r--data/etc/preinstalled-packages-platform-overlays.xml47
-rw-r--r--data/etc/preinstalled-packages-platform.xml3
-rw-r--r--data/etc/privapp-permissions-platform.xml4
-rw-r--r--data/etc/services.core.protolog.json36
-rw-r--r--graphics/java/android/graphics/HardwareRenderer.java18
-rw-r--r--graphics/java/android/graphics/HardwareRendererObserver.java103
-rw-r--r--graphics/java/android/graphics/drawable/ColorDrawable.java2
-rw-r--r--graphics/java/android/graphics/drawable/Drawable.java2
-rw-r--r--graphics/java/android/graphics/drawable/DrawableContainer.java2
-rw-r--r--graphics/java/android/graphics/drawable/DrawableInflater.java8
-rw-r--r--graphics/java/android/graphics/drawable/DrawableWrapper.java2
-rw-r--r--graphics/java/android/graphics/drawable/GradientDrawable.java2
-rw-r--r--graphics/java/android/graphics/drawable/Icon.java2
-rw-r--r--graphics/java/android/graphics/drawable/InsetDrawable.java2
-rw-r--r--graphics/java/android/graphics/drawable/LayerDrawable.java2
-rw-r--r--graphics/java/android/graphics/drawable/NinePatchDrawable.java2
-rw-r--r--graphics/java/android/graphics/drawable/RippleDrawable.java2
-rw-r--r--graphics/java/android/graphics/drawable/RotateDrawable.java20
-rw-r--r--graphics/java/android/graphics/drawable/ScaleDrawable.java12
-rw-r--r--graphics/java/android/graphics/drawable/StateListDrawable.java2
-rw-r--r--graphics/java/android/graphics/drawable/TransitionDrawable.java2
-rw-r--r--graphics/java/android/graphics/drawable/VectorDrawable.java2
-rw-r--r--graphics/java/android/graphics/fonts/FontVariationAxis.java2
-rw-r--r--graphics/java/android/graphics/pdf/PdfRenderer.java4
-rw-r--r--keystore/java/android/security/Credentials.java2
-rw-r--r--keystore/java/android/security/GateKeeper.java2
-rw-r--r--keystore/java/android/security/KeyStore.java3
-rw-r--r--keystore/java/android/security/keystore/AndroidKeyStoreProvider.java2
-rw-r--r--keystore/java/android/security/keystore/KeyGenParameterSpec.java2
-rw-r--r--libs/androidfw/Idmap.cpp16
-rw-r--r--libs/androidfw/LocaleDataTables.cpp27
-rw-r--r--libs/androidfw/OWNERS1
-rw-r--r--libs/androidfw/include/androidfw/Idmap.h9
-rw-r--r--libs/androidfw/include/androidfw/ResourceTypes.h9
-rw-r--r--libs/androidfw/tests/data/overlay/overlay.apkbin2988 -> 2988 bytes
-rw-r--r--libs/androidfw/tests/data/overlay/overlay.idmapbin1077 -> 1137 bytes
-rw-r--r--libs/hwui/renderthread/EglManager.cpp1
-rw-r--r--libs/hwui/renderthread/VulkanSurface.cpp20
-rw-r--r--location/java/android/location/Country.java2
-rw-r--r--location/java/android/location/CountryDetector.java6
-rw-r--r--location/java/android/location/CountryListener.java2
-rw-r--r--location/java/android/location/GeocoderParams.java2
-rw-r--r--location/java/android/location/Geofence.java2
-rw-r--r--location/java/android/location/Location.java2
-rw-r--r--location/java/android/location/LocationListener.java25
-rw-r--r--location/java/android/location/LocationManager.java2
-rw-r--r--location/java/android/location/LocationRequest.java2
-rw-r--r--location/java/com/android/internal/location/GpsNetInitiatedHandler.java5
-rw-r--r--location/java/com/android/internal/location/ProviderRequest.java2
-rw-r--r--media/Android.bp4
-rw-r--r--media/java/android/media/AmrInputStream.java10
-rw-r--r--media/java/android/media/AsyncPlayer.java3
-rw-r--r--media/java/android/media/AudioAttributes.java2
-rw-r--r--media/java/android/media/AudioDevicePort.java3
-rw-r--r--media/java/android/media/AudioDevicePortConfig.java2
-rw-r--r--media/java/android/media/AudioFormat.java14
-rw-r--r--media/java/android/media/AudioGain.java2
-rw-r--r--media/java/android/media/AudioGainConfig.java2
-rw-r--r--media/java/android/media/AudioHandle.java2
-rw-r--r--media/java/android/media/AudioManager.java14
-rw-r--r--media/java/android/media/AudioMixPort.java2
-rw-r--r--media/java/android/media/AudioMixPortConfig.java2
-rw-r--r--media/java/android/media/AudioPatch.java2
-rw-r--r--media/java/android/media/AudioPlaybackConfiguration.java23
-rw-r--r--media/java/android/media/AudioPort.java2
-rw-r--r--media/java/android/media/AudioPortConfig.java2
-rw-r--r--media/java/android/media/AudioPortEventHandler.java2
-rw-r--r--media/java/android/media/AudioRecord.java2
-rw-r--r--media/java/android/media/AudioRecordingConfiguration.java2
-rw-r--r--media/java/android/media/AudioSystem.java10
-rw-r--r--media/java/android/media/AudioTrack.java2
-rw-r--r--media/java/android/media/CamcorderProfile.java2
-rw-r--r--media/java/android/media/DecoderCapabilities.java5
-rw-r--r--media/java/android/media/EncoderCapabilities.java5
-rw-r--r--media/java/android/media/ExifInterface.java2
-rw-r--r--media/java/android/media/IMediaRoute2Provider.aidl10
-rw-r--r--media/java/android/media/IMediaRoute2ProviderClient.aidl7
-rw-r--r--media/java/android/media/IMediaRouter2Client.aidl4
-rw-r--r--media/java/android/media/IMediaRouterService.aidl28
-rw-r--r--media/java/android/media/Image.java7
-rw-r--r--media/java/android/media/JetPlayer.java2
-rw-r--r--media/java/android/media/MediaCodec.java5
-rw-r--r--media/java/android/media/MediaCodecInfo.java2
-rw-r--r--media/java/android/media/MediaDrm.java6
-rw-r--r--media/java/android/media/MediaFile.java2
-rw-r--r--media/java/android/media/MediaFormat.java2
-rw-r--r--media/java/android/media/MediaHTTPConnection.java3
-rw-r--r--media/java/android/media/MediaHTTPService.java2
-rw-r--r--media/java/android/media/MediaInserter.java2
-rw-r--r--media/java/android/media/MediaMetadata.java2
-rw-r--r--media/java/android/media/MediaMetadataRetriever.java2
-rw-r--r--media/java/android/media/MediaMuxer.java8
-rw-r--r--media/java/android/media/MediaPlayer.java2
-rw-r--r--media/java/android/media/MediaRecorder.java2
-rw-r--r--media/java/android/media/MediaRoute2Info.java213
-rw-r--r--media/java/android/media/MediaRoute2ProviderInfo.java10
-rw-r--r--media/java/android/media/MediaRoute2ProviderService.java350
-rw-r--r--media/java/android/media/MediaRouter.java2
-rw-r--r--media/java/android/media/MediaRouter2.java879
-rw-r--r--media/java/android/media/MediaRouter2Manager.java151
-rw-r--r--media/java/android/media/MediaScanner.java2
-rw-r--r--media/java/android/media/Metadata.java2
-rw-r--r--media/java/android/media/MicrophoneInfo.java2
-rw-r--r--media/java/android/media/PlaybackParams.java2
-rw-r--r--media/java/android/media/RemoteControlClient.java2
-rw-r--r--media/java/android/media/RemoteController.java2
-rw-r--r--media/java/android/media/RemoteDisplay.java6
-rw-r--r--media/java/android/media/RemoteDisplayState.java2
-rw-r--r--media/java/android/media/Ringtone.java2
-rw-r--r--media/java/android/media/RingtoneManager.java2
-rw-r--r--media/java/android/media/RouteSessionController.java208
-rw-r--r--media/java/android/media/RouteSessionInfo.aidl19
-rw-r--r--media/java/android/media/RouteSessionInfo.java426
-rw-r--r--media/java/android/media/SubtitleController.java8
-rw-r--r--media/java/android/media/SubtitleTrack.java2
-rw-r--r--media/java/android/media/ThumbnailUtils.java2
-rw-r--r--media/java/android/media/TimedText.java7
-rw-r--r--media/java/android/media/ToneGenerator.java2
-rw-r--r--media/java/android/media/TtmlRenderer.java10
-rw-r--r--media/java/android/media/VolumeShaper.java3
-rw-r--r--media/java/android/media/WebVttRenderer.java2
-rw-r--r--media/java/android/media/audiofx/AudioEffect.java2
-rw-r--r--media/java/android/media/audiofx/Visualizer.java2
-rw-r--r--media/java/android/media/audiopolicy/AudioMix.java2
-rw-r--r--media/java/android/media/audiopolicy/AudioMixingRule.java2
-rw-r--r--media/java/android/media/session/ISessionCallback.aidl63
-rw-r--r--media/java/android/media/session/ISessionController.aidl57
-rw-r--r--media/java/android/media/session/MediaController.java53
-rw-r--r--media/java/android/media/session/MediaSession.java72
-rw-r--r--media/java/android/media/session/MediaSessionLegacyHelper.java3
-rw-r--r--media/java/android/media/session/MediaSessionManager.java2
-rw-r--r--media/java/android/media/tv/tuner/FilterEvent.java118
-rw-r--r--media/java/android/media/tv/tuner/FilterSettings.java92
-rw-r--r--media/java/android/media/tv/tuner/FrontendSettings.java61
-rw-r--r--media/java/android/media/tv/tuner/FrontendStatus.java258
-rw-r--r--media/java/android/media/tv/tuner/ScanMessage.java131
-rw-r--r--media/java/android/media/tv/tuner/Tuner.java455
-rw-r--r--media/java/android/media/tv/tuner/TunerConstants.java515
-rw-r--r--media/java/android/media/tv/tuner/TunerUtils.java135
-rw-r--r--media/jni/android_media_MediaExtractor.h2
-rw-r--r--media/jni/android_media_MediaMetricsJNI.cpp44
-rw-r--r--media/jni/android_media_MediaMuxer.cpp33
-rw-r--r--media/jni/android_media_tv_Tuner.cpp176
-rw-r--r--media/jni/android_media_tv_Tuner.h2
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraErrorCollector.java4
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/InMatcher.java2
-rw-r--r--media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java162
-rw-r--r--media/tests/MediaRouter/Android.bp1
-rw-r--r--media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2Test.java652
-rw-r--r--media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java251
-rw-r--r--media/tests/MediaRouter/src/com/android/mediaroutertest/RouteSessionTest.java62
-rw-r--r--native/android/libandroid.map.txt1
-rw-r--r--packages/CarSystemUI/Android.bp5
-rw-r--r--packages/CarSystemUI/CleanSpec.mk50
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java19
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/car/CarDeviceProvisionedController.java37
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/car/CarDeviceProvisionedControllerImpl.java116
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/car/CarDeviceProvisionedListener.java36
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBar.java46
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java107
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java36
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarTrustAgentUnlockDialogHelper.java4
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java4
-rw-r--r--packages/CompanionDeviceManager/Android.bp1
-rw-r--r--packages/CompanionDeviceManager/AndroidManifest.xml1
-rw-r--r--packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java22
-rw-r--r--packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java7
-rw-r--r--packages/Incremental/NativeAdbDataLoader/jni/com_android_incremental_nativeadb_DataLoaderService.cpp12
-rw-r--r--packages/Incremental/NativeAdbDataLoader/src/com/android/incremental/nativeadb/NativeAdbDataLoaderService.java4
-rw-r--r--packages/PackageInstaller/res/values-fr/strings.xml2
-rw-r--r--packages/PrintSpooler/res/values-cs/strings.xml2
-rw-r--r--packages/PrintSpooler/res/values-eu/strings.xml2
-rw-r--r--packages/PrintSpooler/res/values-iw/strings.xml2
-rw-r--r--packages/SettingsLib/SearchWidget/res/values-or/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-af/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-af/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-am/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-am/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-ar/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-ar/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-as/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-as/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-az/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-az/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-b+sr+Latn/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-b+sr+Latn/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-be/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-be/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-bg/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-bg/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-bn/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-bn/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-bs/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-bs/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-ca/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-ca/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-cs/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-cs/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-da/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-da/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-de/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-de/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-el/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-el/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-en-rAU/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-en-rAU/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-en-rCA/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-en-rCA/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-en-rGB/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-en-rGB/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-en-rIN/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-en-rIN/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-en-rXC/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-en-rXC/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-es-rUS/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-es-rUS/strings.xml10
-rw-r--r--packages/SettingsLib/res/values-es/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-es/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-et/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-et/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-eu/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-eu/strings.xml6
-rw-r--r--packages/SettingsLib/res/values-fa/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-fa/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-fi/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-fi/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-fr-rCA/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-fr-rCA/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-fr/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-fr/strings.xml9
-rw-r--r--packages/SettingsLib/res/values-gl/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-gl/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-gu/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-gu/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-hi/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-hi/strings.xml10
-rw-r--r--packages/SettingsLib/res/values-hr/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-hr/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-hu/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-hu/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-hy/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-hy/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-in/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-in/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-is/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-is/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-it/arrays.xml20
-rw-r--r--packages/SettingsLib/res/values-it/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-iw/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-iw/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-ja/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-ja/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-ka/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-ka/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-kk/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-kk/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-km/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-km/strings.xml6
-rw-r--r--packages/SettingsLib/res/values-kn/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-kn/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-ko/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-ko/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-ky/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-ky/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-lo/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-lo/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-lt/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-lt/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-lv/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-lv/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-mk/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-mk/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-ml/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-ml/strings.xml6
-rw-r--r--packages/SettingsLib/res/values-mn/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-mn/strings.xml6
-rw-r--r--packages/SettingsLib/res/values-mr/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-mr/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-ms/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-ms/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-my/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-my/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-nb/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-nb/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-ne/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-ne/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-nl/arrays.xml6
-rw-r--r--packages/SettingsLib/res/values-nl/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-or/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-or/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-pa/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-pa/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-pl/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-pl/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-pt-rBR/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-pt-rBR/strings.xml6
-rw-r--r--packages/SettingsLib/res/values-pt-rPT/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-pt-rPT/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-pt/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-pt/strings.xml6
-rw-r--r--packages/SettingsLib/res/values-ro/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-ro/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-ru/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-ru/strings.xml6
-rw-r--r--packages/SettingsLib/res/values-si/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-si/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-sk/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-sk/strings.xml12
-rw-r--r--packages/SettingsLib/res/values-sq/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-sq/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-sr/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-sr/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-sv/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-sv/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-sw/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-sw/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-ta/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-ta/strings.xml6
-rw-r--r--packages/SettingsLib/res/values-te/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-te/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-th/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-th/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-tl/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-tl/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-tr/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-tr/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-uk/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-uk/strings.xml6
-rw-r--r--packages/SettingsLib/res/values-ur/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-ur/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-uz/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-uz/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-vi/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-vi/strings.xml6
-rw-r--r--packages/SettingsLib/res/values-zh-rCN/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-zh-rCN/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-zh-rHK/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-zh-rHK/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-zh-rTW/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-zh-rTW/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-zu/arrays.xml4
-rw-r--r--packages/SettingsLib/res/values-zu/strings.xml4
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/Utils.java27
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java21
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/core/instrumentation/EventLogWriter.java8
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/core/instrumentation/LogWriter.java2
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/core/instrumentation/MetricsFeatureProvider.java10
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixin.java17
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java26
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java80
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java21
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/media/MediaDeviceUtils.java11
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/media/MediaOutputSliceConstants.java5
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java2
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java52
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixinTest.java8
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAccessesTest.java18
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java19
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaDeviceTest.java98
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java82
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java23
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceUtilsTest.java5
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageUtilsTest.java4
-rw-r--r--packages/SettingsProvider/res/values/blocked_settings.xml24
-rw-r--r--packages/SettingsProvider/res/values/overlayable.xml25
-rw-r--r--packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java1
-rw-r--r--packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java4
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java143
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java3
-rw-r--r--packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java1
-rw-r--r--packages/SettingsProvider/test/src/com/android/providers/settings/SettingsBackupAgentTest.java54
-rw-r--r--packages/Shell/AndroidManifest.xml3
-rw-r--r--packages/Shell/res/values-uk/strings.xml20
-rw-r--r--packages/SystemUI/Android.bp5
-rw-r--r--packages/SystemUI/AndroidManifest.xml3
-rw-r--r--packages/SystemUI/CleanSpec.mk (renamed from packages/Tethering/CleanSpec.mk)6
-rw-r--r--packages/SystemUI/res-keyguard/values-af/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-am/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-ar/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-as/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-az/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-be/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-bg/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-bn/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-bs/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-ca/strings.xml10
-rw-r--r--packages/SystemUI/res-keyguard/values-cs/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-da/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-de/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-el/strings.xml10
-rw-r--r--packages/SystemUI/res-keyguard/values-en-rAU/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-en-rCA/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-en-rGB/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-en-rIN/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-es-rUS/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-es/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-et/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-eu/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-fa/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-fi/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-fr/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-gl/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-gu/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-hi/strings.xml10
-rw-r--r--packages/SystemUI/res-keyguard/values-hr/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-hu/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-hy/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-in/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-is/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-it/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-iw/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-ja/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-ka/strings.xml10
-rw-r--r--packages/SystemUI/res-keyguard/values-kk/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-km/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-kn/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-ko/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-ky/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-lo/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-lt/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-lv/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-mk/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-ml/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-mn/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-mr/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-ms/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-my/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-nb/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-ne/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-nl/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-or/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-pa/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-pl/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-pt/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-ro/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-ru/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-si/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-sk/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-sl/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-sq/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-sr/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-sv/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-sw/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-ta/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-te/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-th/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-tl/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-tr/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-uk/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-ur/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-uz/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-vi/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml8
-rw-r--r--packages/SystemUI/res-keyguard/values-zu/strings.xml8
-rw-r--r--packages/SystemUI/res-product/values-af/strings.xml64
-rw-r--r--packages/SystemUI/res-product/values-am/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-ar/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-as/strings.xml69
-rw-r--r--packages/SystemUI/res-product/values-az/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-b+sr+Latn/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-be/strings.xml68
-rw-r--r--packages/SystemUI/res-product/values-bg/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-bn/strings.xml69
-rw-r--r--packages/SystemUI/res-product/values-bs/strings.xml68
-rw-r--r--packages/SystemUI/res-product/values-ca/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-cs/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-da/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-de/strings.xml71
-rw-r--r--packages/SystemUI/res-product/values-el/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-en-rAU/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-en-rCA/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-en-rGB/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-en-rIN/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-en-rXC/strings.xml55
-rw-r--r--packages/SystemUI/res-product/values-es-rUS/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-es/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-et/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-eu/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-fa/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-fi/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-fr-rCA/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-fr/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-gl/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-gu/strings.xml69
-rw-r--r--packages/SystemUI/res-product/values-hi/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-hr/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-hu/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-hy/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-in/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-is/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-it/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-iw/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-ja/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-ka/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-kk/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-km/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-kn/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-ko/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-ky/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-lo/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-lt/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-lv/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-mk/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-ml/strings.xml69
-rw-r--r--packages/SystemUI/res-product/values-mn/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-mr/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-ms/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-my/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-nb/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-ne/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-nl/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-or/strings.xml69
-rw-r--r--packages/SystemUI/res-product/values-pa/strings.xml69
-rw-r--r--packages/SystemUI/res-product/values-pl/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-pt-rBR/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-pt-rPT/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-pt/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-ro/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-ru/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-si/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-sk/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-sl/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-sq/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-sr/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-sv/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-sw/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-ta/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-te/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-th/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-tl/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-tr/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-uk/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-ur/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-uz/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-vi/strings.xml69
-rw-r--r--packages/SystemUI/res-product/values-zh-rCN/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-zh-rHK/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-zh-rTW/strings.xml65
-rw-r--r--packages/SystemUI/res-product/values-zu/strings.xml65
-rw-r--r--packages/SystemUI/res/values-af/strings.xml41
-rw-r--r--packages/SystemUI/res/values-af/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-am/strings.xml41
-rw-r--r--packages/SystemUI/res/values-am/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-ar/strings.xml41
-rw-r--r--packages/SystemUI/res/values-ar/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-as/strings.xml47
-rw-r--r--packages/SystemUI/res/values-as/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-az/strings.xml41
-rw-r--r--packages/SystemUI/res/values-az/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-b+sr+Latn/strings.xml41
-rw-r--r--packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-be/strings.xml41
-rw-r--r--packages/SystemUI/res/values-be/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-bg/strings.xml41
-rw-r--r--packages/SystemUI/res/values-bg/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-bn/strings.xml47
-rw-r--r--packages/SystemUI/res/values-bn/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-bs/strings.xml43
-rw-r--r--packages/SystemUI/res/values-bs/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-ca/strings.xml61
-rw-r--r--packages/SystemUI/res/values-ca/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-cs/strings.xml43
-rw-r--r--packages/SystemUI/res/values-cs/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-da/strings.xml45
-rw-r--r--packages/SystemUI/res/values-da/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-de/strings.xml41
-rw-r--r--packages/SystemUI/res/values-de/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-el/strings.xml45
-rw-r--r--packages/SystemUI/res/values-el/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-en-rAU/strings.xml41
-rw-r--r--packages/SystemUI/res/values-en-rAU/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-en-rCA/strings.xml41
-rw-r--r--packages/SystemUI/res/values-en-rCA/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-en-rGB/strings.xml41
-rw-r--r--packages/SystemUI/res/values-en-rGB/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-en-rIN/strings.xml41
-rw-r--r--packages/SystemUI/res/values-en-rIN/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-en-rXC/strings.xml26
-rw-r--r--packages/SystemUI/res/values-en-rXC/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-es-rUS/strings.xml43
-rw-r--r--packages/SystemUI/res/values-es-rUS/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-es/strings.xml43
-rw-r--r--packages/SystemUI/res/values-es/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-et/strings.xml41
-rw-r--r--packages/SystemUI/res/values-et/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-eu/strings.xml41
-rw-r--r--packages/SystemUI/res/values-eu/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-fa/strings.xml41
-rw-r--r--packages/SystemUI/res/values-fa/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-fi/strings.xml41
-rw-r--r--packages/SystemUI/res/values-fi/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-fr-rCA/strings.xml43
-rw-r--r--packages/SystemUI/res/values-fr-rCA/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-fr/strings.xml41
-rw-r--r--packages/SystemUI/res/values-fr/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-gl/strings.xml53
-rw-r--r--packages/SystemUI/res/values-gl/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-gu/strings.xml51
-rw-r--r--packages/SystemUI/res/values-gu/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-hi/strings.xml48
-rw-r--r--packages/SystemUI/res/values-hi/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-hr/strings.xml41
-rw-r--r--packages/SystemUI/res/values-hr/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-hu/strings.xml41
-rw-r--r--packages/SystemUI/res/values-hu/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-hy/strings.xml43
-rw-r--r--packages/SystemUI/res/values-hy/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-in/strings.xml45
-rw-r--r--packages/SystemUI/res/values-in/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-is/strings.xml41
-rw-r--r--packages/SystemUI/res/values-is/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-it/strings.xml47
-rw-r--r--packages/SystemUI/res/values-it/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-iw/strings.xml41
-rw-r--r--packages/SystemUI/res/values-iw/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-ja/strings.xml43
-rw-r--r--packages/SystemUI/res/values-ja/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-ka/strings.xml41
-rw-r--r--packages/SystemUI/res/values-ka/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-kk/strings.xml41
-rw-r--r--packages/SystemUI/res/values-kk/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-km/strings.xml41
-rw-r--r--packages/SystemUI/res/values-km/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-kn/strings.xml45
-rw-r--r--packages/SystemUI/res/values-kn/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-ko/strings.xml41
-rw-r--r--packages/SystemUI/res/values-ko/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-ky/strings.xml45
-rw-r--r--packages/SystemUI/res/values-ky/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-lo/strings.xml41
-rw-r--r--packages/SystemUI/res/values-lo/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-lt/strings.xml41
-rw-r--r--packages/SystemUI/res/values-lt/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-lv/strings.xml41
-rw-r--r--packages/SystemUI/res/values-lv/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-mk/strings.xml41
-rw-r--r--packages/SystemUI/res/values-mk/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-ml/strings.xml53
-rw-r--r--packages/SystemUI/res/values-ml/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-mn/strings.xml41
-rw-r--r--packages/SystemUI/res/values-mn/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-mr/strings.xml41
-rw-r--r--packages/SystemUI/res/values-mr/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-ms/strings.xml41
-rw-r--r--packages/SystemUI/res/values-ms/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-my/strings.xml41
-rw-r--r--packages/SystemUI/res/values-my/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-nb/strings.xml41
-rw-r--r--packages/SystemUI/res/values-nb/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-ne/strings.xml41
-rw-r--r--packages/SystemUI/res/values-ne/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-nl/strings.xml43
-rw-r--r--packages/SystemUI/res/values-nl/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-or/strings.xml51
-rw-r--r--packages/SystemUI/res/values-or/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-pa/strings.xml51
-rw-r--r--packages/SystemUI/res/values-pa/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-pl/strings.xml43
-rw-r--r--packages/SystemUI/res/values-pl/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-pt-rBR/strings.xml41
-rw-r--r--packages/SystemUI/res/values-pt-rBR/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-pt-rPT/strings.xml41
-rw-r--r--packages/SystemUI/res/values-pt-rPT/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-pt/strings.xml41
-rw-r--r--packages/SystemUI/res/values-pt/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-ro/strings.xml41
-rw-r--r--packages/SystemUI/res/values-ro/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-ru/strings.xml41
-rw-r--r--packages/SystemUI/res/values-ru/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-si/strings.xml41
-rw-r--r--packages/SystemUI/res/values-si/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-sk/strings.xml41
-rw-r--r--packages/SystemUI/res/values-sk/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-sl/strings.xml43
-rw-r--r--packages/SystemUI/res/values-sl/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-sq/strings.xml41
-rw-r--r--packages/SystemUI/res/values-sq/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-sr/strings.xml41
-rw-r--r--packages/SystemUI/res/values-sr/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-sv/strings.xml41
-rw-r--r--packages/SystemUI/res/values-sv/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-sw/strings.xml41
-rw-r--r--packages/SystemUI/res/values-sw/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-ta/strings.xml44
-rw-r--r--packages/SystemUI/res/values-ta/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-te/strings.xml41
-rw-r--r--packages/SystemUI/res/values-te/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-television/config.xml1
-rw-r--r--packages/SystemUI/res/values-th/strings.xml45
-rw-r--r--packages/SystemUI/res/values-th/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-tl/strings.xml41
-rw-r--r--packages/SystemUI/res/values-tl/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-tr/strings.xml43
-rw-r--r--packages/SystemUI/res/values-tr/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-uk/strings.xml41
-rw-r--r--packages/SystemUI/res/values-uk/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-ur/strings.xml47
-rw-r--r--packages/SystemUI/res/values-ur/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-uz/strings.xml43
-rw-r--r--packages/SystemUI/res/values-uz/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-vi/strings.xml51
-rw-r--r--packages/SystemUI/res/values-vi/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-zh-rCN/strings.xml41
-rw-r--r--packages/SystemUI/res/values-zh-rCN/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-zh-rHK/strings.xml43
-rw-r--r--packages/SystemUI/res/values-zh-rHK/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-zh-rTW/strings.xml45
-rw-r--r--packages/SystemUI/res/values-zh-rTW/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-zu/strings.xml41
-rw-r--r--packages/SystemUI/res/values-zu/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values/strings.xml9
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityCompat.java7
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java2
-rw-r--r--packages/SystemUI/src/com/android/keyguard/CarrierTextController.java6
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java33
-rw-r--r--packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java86
-rw-r--r--packages/SystemUI/src/com/android/systemui/CornerHandleView.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/Dependency.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/ExpandHelper.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/ImageWallpaper.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/ScreenDecorations.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/SwipeHelper.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIApplication.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIService.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/UiOffloadThread.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java105
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java163
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java52
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java37
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java80
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleIconFactory.java33
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleViewInfoTask.java182
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java53
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUIRootComponent.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/qualifiers/MainResources.java31
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/qualifiers/UiBackground.java (renamed from packages/SystemUI/src/com/android/systemui/dagger/qualifiers/BgLooper.java)6
-rw-r--r--packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/glwallpaper/EglHelper.java98
-rw-r--r--packages/SystemUI/src/com/android/systemui/glwallpaper/GLWallpaperRenderer.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/glwallpaper/ImageProcessHelper.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/BasePipManager.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java87
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/PipSnapAlgorithm.java (renamed from core/java/com/android/internal/policy/PipSnapAlgorithm.java)2
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/PipUI.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java25
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroupController.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java236
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java328
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java345
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationsController.java293
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotServiceErrorReceiver.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSmartActions.java139
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/DividerModule.java41
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/FlingAnimationUtils.java61
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImpl.java214
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinator.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinator.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/NotifListBuilder.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeTransformGroupsListener.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/PipelineState.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifFilter.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifEvent.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java92
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java304
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinder.java155
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java37
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java71
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java28
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java75
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/animation/PhysicsAnimator.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/animation/PhysicsAnimatorTestUtils.kt14
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/concurrency/ConcurrencyModule.java70
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/time/SystemClock.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/time/SystemClockImpl.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/wm/DisplayWindowController.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/wm/SystemWindows.java10
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java29
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceNotificationListenerTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java15
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java43
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java9
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/glwallpaper/EglHelperTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/DismissCallbackRegistryTest.java17
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java38
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInterruptionStateProviderTest.java1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java37
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/VisualStabilityManagerTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/GroupEntryTest.java1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImplTest.java172
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryBuilder.java (renamed from packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryBuilder.java)38
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinatorTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinatorTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java58
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/provider/IsHighPriorityProviderTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/ExpansionStateLoggerTest.java26
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java24
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java128
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupTestHelper.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java39
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java25
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/InflatedSmartRepliesTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/util/animation/PhysicsAnimatorTest.kt7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/util/concurrency/FakeExecutor.java16
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/util/concurrency/FakeExecutorTest.java32
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/util/time/FakeSystemClock.java119
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeBluetoothController.java10
-rw-r--r--packages/Tethering/Android.bp11
-rw-r--r--packages/Tethering/AndroidManifest.xml17
-rw-r--r--packages/Tethering/AndroidManifestBase.xml2
-rw-r--r--packages/Tethering/AndroidManifest_InProcess.xml6
-rw-r--r--packages/Tethering/apex/Android.bp15
-rw-r--r--packages/Tethering/apex/AndroidManifest.xml2
-rw-r--r--packages/Tethering/apex/com.android.tethering.apex.avbpubkeybin1032 -> 0 bytes
-rw-r--r--packages/Tethering/apex/com.android.tethering.apex.pem51
-rw-r--r--packages/Tethering/apex/com.android.tethering.apex.pk8bin2375 -> 0 bytes
-rw-r--r--packages/Tethering/apex/com.android.tethering.apex.x509.pem36
-rw-r--r--packages/Tethering/apex/com.android.tethering.avbpubkeybin0 -> 1032 bytes
-rw-r--r--packages/Tethering/apex/com.android.tethering.pem51
-rw-r--r--packages/Tethering/apex/com.android.tethering.pk8bin0 -> 2375 bytes
-rw-r--r--packages/Tethering/apex/com.android.tethering.x509.pem35
-rw-r--r--packages/Tethering/apex/manifest.json2
-rw-r--r--packages/Tethering/common/TetheringLib/Android.bp32
-rw-r--r--packages/Tethering/common/TetheringLib/jarjar-rules.txt1
-rw-r--r--packages/Tethering/common/TetheringLib/src/android/net/IIntResultListener.aidl (renamed from core/java/android/net/ITetheringEventCallback.aidl)11
-rw-r--r--packages/Tethering/common/TetheringLib/src/android/net/ITetheringConnector.aidl24
-rw-r--r--packages/Tethering/common/TetheringLib/src/android/net/ITetheringEventCallback.aidl (renamed from packages/Tethering/common/TetheringLib/src/android/net/ITetherInternalCallback.aidl)9
-rw-r--r--packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java617
-rw-r--r--packages/Tethering/jarjar-rules.txt15
-rw-r--r--packages/Tethering/proguard.flags10
-rw-r--r--packages/Tethering/src/android/net/ip/IpServer.java17
-rw-r--r--packages/Tethering/src/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java27
-rw-r--r--packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java103
-rw-r--r--packages/Tethering/src/com/android/server/connectivity/tethering/TetheringDependencies.java18
-rw-r--r--packages/Tethering/src/com/android/server/connectivity/tethering/TetheringInterfaceUtils.java5
-rw-r--r--packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java253
-rw-r--r--packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java44
-rw-r--r--packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkState.java51
-rw-r--r--packages/Tethering/tests/unit/Android.bp2
-rw-r--r--packages/Tethering/tests/unit/AndroidManifest.xml4
-rw-r--r--packages/Tethering/tests/unit/jarjar-rules.txt11
-rw-r--r--packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java97
-rw-r--r--packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java3
-rw-r--r--packages/VpnDialogs/res/values-am/strings.xml2
-rw-r--r--packages/WAPPushManager/Android.bp2
-rw-r--r--packages/WAPPushManager/CleanSpec.mk2
-rw-r--r--packages/WallpaperCropper/Android.bp2
-rw-r--r--packages/WallpaperCropper/CleanSpec.mk1
-rw-r--r--packages/WindowManager/OWNERS3
-rw-r--r--packages/WindowManager/Shell/Android.bp29
-rw-r--r--packages/WindowManager/Shell/AndroidManifest.xml20
-rw-r--r--packages/WindowManager/Shell/OWNERS4
-rw-r--r--packages/WindowManager/Shell/res/values/config.xml21
-rw-r--r--packages/WindowManager/Shell/src/com/android/wm/shell/WindowManagerShell.java23
-rw-r--r--packages/WindowManager/Shell/tests/Android.bp45
-rw-r--r--packages/WindowManager/Shell/tests/AndroidManifest.xml32
-rw-r--r--packages/WindowManager/Shell/tests/AndroidTest.xml31
-rw-r--r--packages/WindowManager/Shell/tests/res/values/config.xml21
-rw-r--r--packages/WindowManager/Shell/tests/src/com/android/wm/shell/tests/WindowManagerShellTest.java40
-rw-r--r--packages/overlays/Android.mk5
-rw-r--r--services/Android.bp12
-rw-r--r--services/accessibility/java/com/android/server/accessibility/gestures/GestureManifold.java2
-rw-r--r--services/accessibility/java/com/android/server/accessibility/gestures/SecondFingerMultiTap.java167
-rw-r--r--services/accessibility/java/com/android/server/accessibility/gestures/Swipe.java11
-rw-r--r--services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java26
-rw-r--r--services/api/current.txt1
-rw-r--r--services/api/removed.txt1
-rw-r--r--services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java2
-rw-r--r--services/autofill/java/com/android/server/autofill/AutofillManagerService.java9
-rw-r--r--services/autofill/java/com/android/server/autofill/FieldClassificationStrategy.java7
-rw-r--r--services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java4
-rw-r--r--services/autofill/java/com/android/server/autofill/Session.java11
-rw-r--r--services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java14
-rw-r--r--services/backup/java/com/android/server/backup/UserBackupManagerService.java6
-rw-r--r--services/backup/java/com/android/server/backup/internal/RunInitializeReceiver.java15
-rw-r--r--services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java3
-rw-r--r--services/backup/java/com/android/server/backup/utils/TarBackupReader.java8
-rw-r--r--services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java189
-rw-r--r--services/core/Android.bp1
-rw-r--r--services/core/java/android/content/pm/PackageManagerInternal.java56
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java222
-rw-r--r--services/core/java/com/android/server/CountryDetectorService.java76
-rw-r--r--services/core/java/com/android/server/DynamicSystemService.java13
-rw-r--r--services/core/java/com/android/server/MmsServiceBroker.java22
-rw-r--r--services/core/java/com/android/server/NetworkTimeUpdateServiceImpl.java6
-rw-r--r--services/core/java/com/android/server/StorageManagerService.java27
-rw-r--r--services/core/java/com/android/server/SystemService.java23
-rw-r--r--services/core/java/com/android/server/TelephonyRegistry.java143
-rw-r--r--services/core/java/com/android/server/UiModeManagerService.java20
-rw-r--r--services/core/java/com/android/server/VibratorService.java63
-rw-r--r--services/core/java/com/android/server/am/ActiveServices.java2
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java220
-rw-r--r--services/core/java/com/android/server/am/AppErrorDialog.java6
-rw-r--r--services/core/java/com/android/server/am/AppErrors.java32
-rw-r--r--services/core/java/com/android/server/am/AppNotRespondingDialog.java14
-rw-r--r--services/core/java/com/android/server/am/AppWaitingForDebuggerDialog.java2
-rw-r--r--services/core/java/com/android/server/am/ProcessList.java85
-rw-r--r--services/core/java/com/android/server/am/ProcessRecord.java185
-rw-r--r--services/core/java/com/android/server/am/StrictModeViolationDialog.java4
-rw-r--r--services/core/java/com/android/server/am/UserController.java7
-rw-r--r--services/core/java/com/android/server/appop/AppOpsService.java879
-rw-r--r--services/core/java/com/android/server/audio/AudioDeviceInventory.java101
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java45
-rw-r--r--services/core/java/com/android/server/audio/AudioSystemAdapter.java155
-rw-r--r--services/core/java/com/android/server/biometrics/BiometricService.java60
-rw-r--r--services/core/java/com/android/server/connectivity/DnsManager.java1
-rw-r--r--services/core/java/com/android/server/display/AutomaticBrightnessController.java39
-rw-r--r--services/core/java/com/android/server/display/BrightnessMappingStrategy.java89
-rw-r--r--services/core/java/com/android/server/display/DisplayDevice.java31
-rw-r--r--services/core/java/com/android/server/display/DisplayDeviceInfo.java16
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java57
-rw-r--r--services/core/java/com/android/server/display/DisplayModeDirector.java136
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerController.java5
-rw-r--r--services/core/java/com/android/server/display/LocalDisplayAdapter.java254
-rw-r--r--services/core/java/com/android/server/display/LogicalDisplay.java49
-rw-r--r--services/core/java/com/android/server/display/OverlayDisplayAdapter.java6
-rw-r--r--services/core/java/com/android/server/incremental/IncrementalManagerService.java28
-rw-r--r--services/core/java/com/android/server/incremental/IncrementalManagerShellCommand.java12
-rw-r--r--services/core/java/com/android/server/infra/AbstractMasterSystemService.java1
-rw-r--r--services/core/java/com/android/server/input/ConfigurationProcessor.java16
-rw-r--r--services/core/java/com/android/server/input/InputManagerService.java51
-rw-r--r--services/core/java/com/android/server/integrity/AppIntegrityManagerService.java4
-rw-r--r--services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java498
-rw-r--r--services/core/java/com/android/server/integrity/IntegrityFileManager.java181
-rw-r--r--services/core/java/com/android/server/integrity/IntegrityUtils.java79
-rw-r--r--services/core/java/com/android/server/integrity/OWNERS1
-rw-r--r--services/core/java/com/android/server/integrity/engine/RuleEvaluationEngine.java70
-rw-r--r--services/core/java/com/android/server/integrity/engine/RuleEvaluator.java27
-rw-r--r--services/core/java/com/android/server/integrity/model/BitOutputStream.java2
-rw-r--r--services/core/java/com/android/server/integrity/model/ComponentBitSize.java2
-rw-r--r--services/core/java/com/android/server/integrity/model/RuleMetadata.java41
-rw-r--r--services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java52
-rw-r--r--services/core/java/com/android/server/integrity/parser/RuleMetadataParser.java67
-rw-r--r--services/core/java/com/android/server/integrity/serializer/ByteTrackedOutputStream.java53
-rw-r--r--services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java135
-rw-r--r--services/core/java/com/android/server/integrity/serializer/RuleIndexTypeIdentifier.java117
-rw-r--r--services/core/java/com/android/server/integrity/serializer/RuleIndexingDetails.java67
-rw-r--r--services/core/java/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifier.java160
-rw-r--r--services/core/java/com/android/server/integrity/serializer/RuleMetadataSerializer.java52
-rw-r--r--services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java40
-rw-r--r--services/core/java/com/android/server/locksettings/LockSettingsService.java70
-rw-r--r--services/core/java/com/android/server/media/AudioPlayerStateMonitor.java3
-rw-r--r--services/core/java/com/android/server/media/MediaRoute2Provider.java48
-rw-r--r--services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java139
-rw-r--r--services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java543
-rw-r--r--services/core/java/com/android/server/media/MediaRouterService.java38
-rw-r--r--services/core/java/com/android/server/media/MediaSessionRecord.java382
-rw-r--r--services/core/java/com/android/server/media/MediaSessionService.java47
-rw-r--r--services/core/java/com/android/server/media/MediaSessionStack.java13
-rw-r--r--services/core/java/com/android/server/media/SystemMediaRoute2Provider.java35
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java23
-rw-r--r--services/core/java/com/android/server/net/NetworkStatsService.java7
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java58
-rw-r--r--services/core/java/com/android/server/notification/PreferencesHelper.java38
-rw-r--r--services/core/java/com/android/server/os/BugreportManagerServiceImpl.java7
-rw-r--r--services/core/java/com/android/server/package-info.java5
-rw-r--r--services/core/java/com/android/server/pm/DataLoaderManagerService.java30
-rw-r--r--services/core/java/com/android/server/pm/Installer.java62
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerService.java4
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java236
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java657
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerShellCommand.java13
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java92
-rw-r--r--services/core/java/com/android/server/pm/PackageVerificationState.java58
-rw-r--r--services/core/java/com/android/server/pm/Settings.java1
-rw-r--r--services/core/java/com/android/server/pm/StagingManager.java36
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java59
-rw-r--r--services/core/java/com/android/server/pm/UserRestrictionsUtils.java15
-rw-r--r--services/core/java/com/android/server/pm/UserSystemPackageInstaller.java75
-rw-r--r--services/core/java/com/android/server/pm/permission/BasePermission.java3
-rw-r--r--services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java12
-rw-r--r--services/core/java/com/android/server/pm/permission/OneTimePermissionUserManager.java281
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java70
-rw-r--r--services/core/java/com/android/server/policy/LegacyGlobalActions.java7
-rw-r--r--services/core/java/com/android/server/policy/PermissionPolicyService.java17
-rw-r--r--services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java3
-rw-r--r--services/core/java/com/android/server/policy/WindowManagerPolicy.java7
-rw-r--r--services/core/java/com/android/server/power/TEST_MAPPING45
-rw-r--r--services/core/java/com/android/server/role/RoleManagerService.java12
-rw-r--r--services/core/java/com/android/server/rollback/AppDataRollbackHelper.java41
-rw-r--r--services/core/java/com/android/server/rollback/Rollback.java15
-rw-r--r--services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java2
-rw-r--r--services/core/java/com/android/server/rollback/RollbackStore.java10
-rw-r--r--services/core/java/com/android/server/security/FileIntegrityService.java170
-rw-r--r--services/core/java/com/android/server/slice/SliceManagerService.java2
-rw-r--r--services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareService.java5
-rw-r--r--services/core/java/com/android/server/soundtrigger_middleware/ValidationUtil.java31
-rw-r--r--services/core/java/com/android/server/storage/AppCollector.java2
-rw-r--r--services/core/java/com/android/server/storage/CacheQuotaStrategy.java9
-rw-r--r--services/core/java/com/android/server/storage/StorageSessionController.java3
-rw-r--r--services/core/java/com/android/server/storage/StorageUserConnection.java11
-rw-r--r--services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java39
-rw-r--r--services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java68
-rw-r--r--services/core/java/com/android/server/timezonedetector/ArrayMapWithHistory.java187
-rw-r--r--services/core/java/com/android/server/timezonedetector/ReferenceWithHistory.java118
-rw-r--r--services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java67
-rw-r--r--services/core/java/com/android/server/uri/UriGrantsManagerService.java3
-rw-r--r--services/core/java/com/android/server/utils/quota/Categorizer.java38
-rw-r--r--services/core/java/com/android/server/utils/quota/Category.java77
-rw-r--r--services/core/java/com/android/server/utils/quota/QuotaChangeListener.java34
-rw-r--r--services/core/java/com/android/server/utils/quota/QuotaTracker.java661
-rw-r--r--services/core/java/com/android/server/utils/quota/Uptc.java88
-rw-r--r--services/core/java/com/android/server/wm/AccessibilityController.java11
-rw-r--r--services/core/java/com/android/server/wm/ActivityMetricsLogger.java16
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java252
-rw-r--r--services/core/java/com/android/server/wm/ActivityStack.java529
-rw-r--r--services/core/java/com/android/server/wm/ActivityStackSupervisor.java126
-rw-r--r--services/core/java/com/android/server/wm/ActivityStartController.java2
-rw-r--r--services/core/java/com/android/server/wm/ActivityStartInterceptor.java14
-rw-r--r--services/core/java/com/android/server/wm/ActivityStarter.java81
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java313
-rw-r--r--services/core/java/com/android/server/wm/AppTaskImpl.java8
-rw-r--r--services/core/java/com/android/server/wm/AppTransitionController.java165
-rw-r--r--services/core/java/com/android/server/wm/BoundsAnimationController.java8
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java110
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java12
-rw-r--r--services/core/java/com/android/server/wm/DisplayRotation.java14
-rw-r--r--services/core/java/com/android/server/wm/DisplayWindowListenerController.java4
-rw-r--r--services/core/java/com/android/server/wm/DragState.java7
-rw-r--r--services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java2
-rw-r--r--services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java5
-rw-r--r--services/core/java/com/android/server/wm/InputConsumerImpl.java7
-rw-r--r--services/core/java/com/android/server/wm/InputMonitor.java4
-rw-r--r--services/core/java/com/android/server/wm/InsetsSourceProvider.java7
-rw-r--r--services/core/java/com/android/server/wm/KeyguardController.java37
-rw-r--r--services/core/java/com/android/server/wm/LaunchParamsPersister.java4
-rw-r--r--services/core/java/com/android/server/wm/LockTaskController.java10
-rw-r--r--services/core/java/com/android/server/wm/PinnedStackController.java221
-rw-r--r--services/core/java/com/android/server/wm/RecentTasks.java2
-rw-r--r--services/core/java/com/android/server/wm/RecentsAnimation.java16
-rw-r--r--services/core/java/com/android/server/wm/RecentsAnimationController.java7
-rw-r--r--services/core/java/com/android/server/wm/ResetTargetTaskHelper.java2
-rw-r--r--services/core/java/com/android/server/wm/RootActivityContainer.java2676
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java2682
-rw-r--r--services/core/java/com/android/server/wm/RunningTasks.java4
-rw-r--r--services/core/java/com/android/server/wm/Session.java4
-rw-r--r--services/core/java/com/android/server/wm/TapExcludeRegionHolder.java62
-rw-r--r--services/core/java/com/android/server/wm/Task.java37
-rw-r--r--services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java8
-rw-r--r--services/core/java/com/android/server/wm/TaskPersister.java5
-rw-r--r--services/core/java/com/android/server/wm/TaskPositioner.java1
-rw-r--r--services/core/java/com/android/server/wm/TaskPositioningController.java4
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotController.java164
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotPersister.java2
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotSurface.java18
-rw-r--r--services/core/java/com/android/server/wm/WindowContainer.java27
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerInternal.java6
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java78
-rw-r--r--services/core/java/com/android/server/wm/WindowProcessController.java28
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java223
-rw-r--r--services/core/java/com/android/server/wm/WindowToken.java2
-rw-r--r--services/core/jni/Android.bp2
-rw-r--r--services/core/jni/com_android_server_VibratorService.cpp17
-rw-r--r--services/core/jni/com_android_server_incremental_IncrementalManagerService.cpp47
-rw-r--r--services/core/jni/com_android_server_input_InputManagerService.cpp6
-rw-r--r--services/core/jni/onload.cpp2
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java644
-rw-r--r--services/incremental/Android.bp110
-rw-r--r--services/incremental/BinderIncrementalService.cpp230
-rw-r--r--services/incremental/BinderIncrementalService.h77
-rw-r--r--services/incremental/IncrementalService.cpp1045
-rw-r--r--services/incremental/IncrementalService.h231
-rw-r--r--services/incremental/Metadata.proto25
-rw-r--r--services/incremental/ServiceWrappers.cpp67
-rw-r--r--services/incremental/ServiceWrappers.h183
-rw-r--r--services/incremental/include/incremental_service.h (renamed from packages/SystemUI/src/com/android/systemui/dagger/qualifiers/MainHandler.java)22
-rw-r--r--services/incremental/incremental_service.c17
-rw-r--r--services/incremental/path.cpp178
-rw-r--r--services/incremental/path.h89
-rw-r--r--services/incremental/test/IncrementalServiceTest.cpp461
-rw-r--r--services/incremental/test/path_test.cpp43
-rw-r--r--services/java/com/android/server/SystemServer.java29
-rw-r--r--services/net/Android.bp4
-rw-r--r--services/print/java/com/android/server/print/PrintManagerService.java33
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java14
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java146
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java7
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java5
-rw-r--r--services/tests/servicestests/Android.bp1
-rw-r--r--services/tests/servicestests/assets/AppIntegrityManagerServiceImplTest/test.apkbin0 -> 1357952 bytes
-rw-r--r--services/tests/servicestests/src/com/android/server/CountryDetectorServiceTest.java143
-rw-r--r--services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java13
-rw-r--r--services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java19
-rw-r--r--services/tests/servicestests/src/com/android/server/backup/BackupManagerServiceTest.java34
-rw-r--r--services/tests/servicestests/src/com/android/server/backup/DataChangedJournalTest.java1
-rw-r--r--services/tests/servicestests/src/com/android/server/backup/utils/FileUtilsTest.java16
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java83
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java91
-rw-r--r--services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java26
-rw-r--r--services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java21
-rw-r--r--services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java1
-rw-r--r--services/tests/servicestests/src/com/android/server/input/ConfigurationProcessorTest.java12
-rw-r--r--services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java349
-rw-r--r--services/tests/servicestests/src/com/android/server/integrity/IntegrityFileManagerTest.java175
-rw-r--r--services/tests/servicestests/src/com/android/server/integrity/IntegrityUtilsTest.java61
-rw-r--r--services/tests/servicestests/src/com/android/server/integrity/engine/RuleEvaluationEngineTest.java197
-rw-r--r--services/tests/servicestests/src/com/android/server/integrity/parser/RuleBinaryParserTest.java64
-rw-r--r--services/tests/servicestests/src/com/android/server/integrity/serializer/ByteTrackedOutputStreamTest.java72
-rw-r--r--services/tests/servicestests/src/com/android/server/integrity/serializer/RuleBinarySerializerTest.java250
-rw-r--r--services/tests/servicestests/src/com/android/server/integrity/serializer/RuleIndexTypeIdentifierTest.java218
-rw-r--r--services/tests/servicestests/src/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifierTest.java346
-rw-r--r--services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java190
-rw-r--r--services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java99
-rw-r--r--services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java55
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/PackageVerificationStateTest.java75
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java381
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java45
-rw-r--r--services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/power/batterysaver/FileUpdaterTest.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/timedetector/ArrayMapWithHistoryTest.java180
-rw-r--r--services/tests/servicestests/src/com/android/server/timedetector/ReferenceWithHistoryTest.java142
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryManagerTest.java3
-rwxr-xr-xservices/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java24
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java55
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java83
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java34
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java8
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java27
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java100
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java59
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AnimatingActivityRegistryTest.java1
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java356
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java12
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java15
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java8
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java7
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java32
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java174
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java6
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java1
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java32
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java71
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java86
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java17
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java19
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java31
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java5
-rw-r--r--services/usage/java/com/android/server/usage/StorageStatsService.java163
-rw-r--r--services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java8
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java11
-rw-r--r--startop/iorap/src/com/google/android/startop/iorap/EventSequenceValidator.java255
-rw-r--r--startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java2
-rw-r--r--telecomm/java/android/telecom/Conference.java3
-rw-r--r--telecomm/java/android/telecom/TelecomManager.java97
-rw-r--r--telephony/common/com/android/internal/telephony/SmsNumberUtils.java4
-rw-r--r--telephony/common/com/android/internal/telephony/TelephonyPermissions.java2
-rw-r--r--telephony/java/android/telephony/Annotation.java122
-rwxr-xr-xtelephony/java/android/telephony/CarrierConfigManager.java163
-rw-r--r--telephony/java/android/telephony/CbGeoUtils.java77
-rw-r--r--telephony/java/android/telephony/CellIdentity.java4
-rw-r--r--telephony/java/android/telephony/CellIdentityCdma.java2
-rw-r--r--telephony/java/android/telephony/CellIdentityGsm.java2
-rw-r--r--telephony/java/android/telephony/CellIdentityLte.java2
-rw-r--r--telephony/java/android/telephony/CellIdentityNr.java2
-rw-r--r--telephony/java/android/telephony/CellIdentityTdscdma.java1
-rw-r--r--telephony/java/android/telephony/CellIdentityWcdma.java2
-rw-r--r--telephony/java/android/telephony/CellSignalStrengthLte.java230
-rw-r--r--telephony/java/android/telephony/PreciseCallState.java24
-rw-r--r--telephony/java/android/telephony/PreciseDataConnectionState.java8
-rw-r--r--telephony/java/android/telephony/ServiceState.java109
-rw-r--r--telephony/java/android/telephony/SmsManager.java28
-rw-r--r--telephony/java/android/telephony/SmsMessage.java18
-rw-r--r--telephony/java/android/telephony/SubscriptionManager.java61
-rw-r--r--telephony/java/android/telephony/TelephonyFrameworkInitializer.java6
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java163
-rw-r--r--telephony/java/android/telephony/ims/ImsCallProfile.java3
-rwxr-xr-xtelephony/java/com/android/internal/telephony/ISub.aidl2
-rw-r--r--telephony/java/com/android/internal/telephony/ITelephony.aidl8
-rw-r--r--telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java4
-rw-r--r--telephony/java/com/android/internal/telephony/SmsMessageBase.java44
-rw-r--r--telephony/java/com/android/internal/telephony/TelephonyIntents.java41
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java521
-rw-r--r--telephony/java/com/android/internal/telephony/util/TelephonyUtils.java29
-rw-r--r--test-mock/Android.bp2
-rw-r--r--tests/ApkVerityTest/AndroidTest.xml2
-rw-r--r--tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java36
-rw-r--r--tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java49
-rw-r--r--tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java20
-rw-r--r--tests/SurfaceControlViewHostTest/Android.bp (renamed from tests/WindowlessWmTest/Android.bp)2
-rw-r--r--tests/SurfaceControlViewHostTest/AndroidManifest.xml (renamed from tests/WindowlessWmTest/AndroidManifest.xml)2
-rw-r--r--tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceControlViewHostTest.java (renamed from tests/WindowlessWmTest/src/com/android/test/viewembed/WindowlessWmTest.java)13
-rw-r--r--tests/UsbManagerTests/Android.bp32
-rw-r--r--tests/UsbManagerTests/AndroidManifest.xml29
-rw-r--r--tests/UsbManagerTests/AndroidTest.xml31
-rw-r--r--tests/UsbManagerTests/lib/Android.bp34
-rw-r--r--tests/UsbManagerTests/lib/AndroidManifest.xml22
-rw-r--r--tests/UsbManagerTests/lib/src/com/android/server/usblib/UsbManagerTestLib.java129
-rw-r--r--tests/UsbManagerTests/src/com/android/server/usbtest/UsbManagerApiTest.java95
-rw-r--r--tests/UsbTests/Android.bp1
-rw-r--r--tests/UsbTests/src/com/android/server/usb/UsbManagerNoPermTest.java81
-rw-r--r--tests/libs-permissions/Android.bp1
-rw-r--r--tests/net/common/java/android/net/LinkPropertiesTest.java113
-rw-r--r--tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt2
-rw-r--r--tests/net/java/com/android/server/ConnectivityServiceTest.java2
-rw-r--r--tools/aapt2/Resource.h9
-rw-r--r--tools/aapt2/ResourceTable.cpp16
-rw-r--r--tools/aapt2/ResourceUtils.cpp10
-rw-r--r--tools/aapt2/ResourceValues.cpp6
-rw-r--r--tools/aapt2/process/SymbolTable.cpp4
-rw-r--r--tools/stats_log_api_gen/Android.bp14
-rw-r--r--tools/stats_log_api_gen/Collation.cpp4
-rw-r--r--tools/stats_log_api_gen/atoms_info_writer.h3
-rw-r--r--tools/stats_log_api_gen/java_writer.cpp26
-rw-r--r--tools/stats_log_api_gen/java_writer.h3
-rw-r--r--tools/stats_log_api_gen/java_writer_q.h12
-rw-r--r--tools/stats_log_api_gen/main.cpp508
-rw-r--r--tools/stats_log_api_gen/native_writer.cpp342
-rw-r--r--tools/stats_log_api_gen/native_writer.h37
-rw-r--r--tools/stats_log_api_gen/native_writer_q.cpp276
-rw-r--r--tools/stats_log_api_gen/native_writer_q.h49
-rw-r--r--tools/stats_log_api_gen/test.proto6
-rw-r--r--tools/stats_log_api_gen/utils.cpp59
-rw-r--r--tools/stats_log_api_gen/utils.h16
-rw-r--r--wifi/Android.bp34
-rw-r--r--wifi/java/android/net/wifi/EasyConnectStatusCallback.java132
-rw-r--r--wifi/java/android/net/wifi/IDppCallback.aidl2
-rw-r--r--wifi/java/android/net/wifi/ISoftApCallback.aidl9
-rw-r--r--wifi/java/android/net/wifi/ScanResult.java23
-rw-r--r--wifi/java/android/net/wifi/SoftApCapability.aidl19
-rw-r--r--wifi/java/android/net/wifi/SoftApCapability.java173
-rw-r--r--wifi/java/android/net/wifi/SoftApConfiguration.java174
-rw-r--r--wifi/java/android/net/wifi/SoftApInfo.java25
-rw-r--r--wifi/java/android/net/wifi/WifiAnnotations.java12
-rw-r--r--wifi/java/android/net/wifi/WifiConfiguration.java134
-rw-r--r--wifi/java/android/net/wifi/WifiEnterpriseConfig.java67
-rw-r--r--wifi/java/android/net/wifi/WifiManager.java138
-rw-r--r--wifi/java/android/net/wifi/WifiNetworkSuggestion.java59
-rw-r--r--wifi/java/android/net/wifi/WifiScanner.java27
-rw-r--r--wifi/java/android/net/wifi/aware/Characteristics.java37
-rw-r--r--wifi/java/android/net/wifi/p2p/WifiP2pConfig.java35
-rw-r--r--wifi/java/android/net/wifi/p2p/WifiP2pGroup.java7
-rw-r--r--wifi/java/android/net/wifi/wificond/NativeScanResult.java158
-rw-r--r--wifi/java/android/net/wifi/wificond/NativeWifiClient.java33
-rw-r--r--wifi/java/android/net/wifi/wificond/PnoNetwork.java116
-rw-r--r--wifi/java/android/net/wifi/wificond/PnoSettings.java159
-rw-r--r--wifi/java/android/net/wifi/wificond/RadioChainInfo.java43
-rw-r--r--wifi/java/android/net/wifi/wificond/SingleScanSettings.java1
-rw-r--r--wifi/java/android/net/wifi/wificond/WifiCondManager.java (renamed from wifi/java/android/net/wifi/WifiCondManager.java)458
-rw-r--r--wifi/tests/src/android/net/wifi/EasyConnectStatusCallbackTest.java84
-rw-r--r--wifi/tests/src/android/net/wifi/SoftApCapabilityTest.java73
-rw-r--r--wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java12
-rw-r--r--wifi/tests/src/android/net/wifi/WifiConfigurationTest.java40
-rw-r--r--wifi/tests/src/android/net/wifi/WifiManagerTest.java98
-rw-r--r--wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java82
-rw-r--r--wifi/tests/src/android/net/wifi/WifiScannerTest.java20
-rw-r--r--wifi/tests/src/android/net/wifi/wificond/PnoSettingsTest.java38
-rw-r--r--wifi/tests/src/android/net/wifi/wificond/SingleScanSettingsTest.java1
-rw-r--r--wifi/tests/src/android/net/wifi/wificond/WifiCondManagerTest.java (renamed from wifi/tests/src/android/net/wifi/WifiCondManagerTest.java)194
2216 files changed, 56083 insertions, 33998 deletions
diff --git a/Android.bp b/Android.bp
index 15188ece0a6d..4b82e1d26edc 100644
--- a/Android.bp
+++ b/Android.bp
@@ -245,7 +245,7 @@ filegroup {
":libcamera_client_framework_aidl",
":libupdate_engine_aidl",
// TODO: this needs to be removed when statsd-framework.jar is separated out
- ":statsd_aidl",
+ ":statsd_java_aidl",
":storaged_aidl",
":vold_aidl",
@@ -264,7 +264,9 @@ filegroup {
":framework-appsearch-sources",
":framework-sdkext-sources",
":framework-statsd-sources",
+ ":framework-tethering-srcs",
":updatable-media-srcs",
+ ":framework-mediaprovider-sources",
":framework-wifi-updatable-sources",
]
}
@@ -351,9 +353,6 @@ java_library {
"com.android.sysprop.apex",
"PlatformProperties",
],
- aidl: {
- include_dirs: ["system/connectivity/wificond/aidl"],
- },
sdk_version: "core_platform",
installable: false,
}
@@ -380,6 +379,8 @@ java_defaults {
"ext",
"unsupportedappusage",
"updatable_media_stubs",
+ "framework_mediaprovider_stubs",
+ "framework-tethering",
],
jarjar_rules: ":framework-jarjar-rules",
@@ -467,6 +468,8 @@ java_library {
installable: false, // this lib is a build-only library
static_libs: [
"framework-minus-apex",
+ "updatable_media_stubs",
+ "framework_mediaprovider_stubs",
"framework-appsearch", // TODO(b/146218515): should be framework-appsearch-stubs
"framework-sdkext-stubs-systemapi",
// TODO(b/146167933): Use framework-statsd-stubs instead.
@@ -582,11 +585,14 @@ gensrcs {
filegroup {
name: "framework-annotations",
srcs: [
- "core/java/android/annotation/NonNull.java",
- "core/java/android/annotation/Nullable.java",
"core/java/android/annotation/IntDef.java",
"core/java/android/annotation/IntRange.java",
+ "core/java/android/annotation/NonNull.java",
+ "core/java/android/annotation/Nullable.java",
+ "core/java/android/annotation/RequiresPermission.java",
+ "core/java/android/annotation/SdkConstant.java",
"core/java/android/annotation/SystemApi.java",
+ "core/java/android/annotation/TestApi.java",
"core/java/android/annotation/UnsupportedAppUsage.java",
"core/java/com/android/internal/annotations/GuardedBy.java",
"core/java/com/android/internal/annotations/VisibleForTesting.java",
@@ -596,7 +602,7 @@ filegroup {
java_library {
name: "framework-annotations-lib",
srcs: [ ":framework-annotations" ],
- sdk_version: "current",
+ sdk_version: "core_current",
}
filegroup {
@@ -620,10 +626,26 @@ filegroup {
],
}
+// keep these files in sync with the package/Tethering/jarjar-rules.txt for the tethering module.
filegroup {
name: "framework-tethering-shared-srcs",
srcs: [
"core/java/android/util/LocalLog.java",
+ "core/java/com/android/internal/util/BitUtils.java",
+ "core/java/com/android/internal/util/IndentingPrintWriter.java",
+ "core/java/com/android/internal/util/IState.java",
+ "core/java/com/android/internal/util/MessageUtils.java",
+ "core/java/com/android/internal/util/Preconditions.java",
+ "core/java/com/android/internal/util/State.java",
+ "core/java/com/android/internal/util/StateMachine.java",
+ ],
+}
+
+filegroup {
+ name: "framework-tethering-annotations",
+ srcs: [
+ "core/java/android/annotation/NonNull.java",
+ "core/java/android/annotation/SystemApi.java",
],
}
// Build ext.jar
@@ -674,7 +696,7 @@ java_library {
"core/proto/android/privacy.proto",
"core/proto/android/section.proto",
],
- sdk_version: "current",
+ sdk_version: "9",
srcs: [
"core/proto/**/*.proto",
"libs/incident/proto/android/os/**/*.proto",
@@ -697,6 +719,7 @@ java_library {
"core/proto/android/privacy.proto",
"core/proto/android/section.proto",
],
+ sdk_version: "core_current",
// Protos have lots of MissingOverride and similar.
errorprone: {
javacflags: ["-XepDisableAllChecks"],
@@ -799,11 +822,7 @@ cc_library {
filegroup {
name: "incremental_aidl",
srcs: [
- "core/java/android/os/incremental/IIncrementalManagerNative.aidl",
- "core/java/android/os/incremental/IIncrementalManager.aidl",
- "core/java/android/os/incremental/IncrementalDataLoaderParamsParcel.aidl",
"core/java/android/os/incremental/IncrementalFileSystemControlParcel.aidl",
- "core/java/android/os/incremental/NamedParcelFileDescriptor.aidl",
],
path: "core/java",
}
@@ -811,7 +830,21 @@ filegroup {
filegroup {
name: "dataloader_aidl",
srcs: [
+ "core/java/android/content/pm/DataLoaderParamsParcel.aidl",
+ "core/java/android/content/pm/DataLoaderType.aidl",
+ "core/java/android/content/pm/FileSystemControlParcel.aidl",
"core/java/android/content/pm/IDataLoaderStatusListener.aidl",
+ "core/java/android/content/pm/IPackageInstallerSessionFileSystemConnector.aidl",
+ "core/java/android/content/pm/NamedParcelFileDescriptor.aidl",
+ ],
+ path: "core/java",
+}
+
+filegroup {
+ name: "incremental_manager_aidl",
+ srcs: [
+ "core/java/android/os/incremental/IIncrementalManager.aidl",
+ "core/java/android/os/incremental/IIncrementalManagerNative.aidl",
],
path: "core/java",
}
@@ -821,9 +854,6 @@ aidl_interface {
srcs: [
":incremental_aidl",
],
- imports: [
- "libdataloader_aidl",
- ],
backend: {
java: {
sdk_version: "28",
@@ -842,6 +872,9 @@ aidl_interface {
srcs: [
":dataloader_aidl",
],
+ imports: [
+ "libincremental_aidl",
+ ],
backend: {
java: {
sdk_version: "28",
@@ -850,8 +883,30 @@ aidl_interface {
enabled: true,
},
ndk: {
+ enabled: false,
+ },
+ },
+}
+
+aidl_interface {
+ name: "libincremental_manager_aidl",
+ srcs: [
+ ":incremental_manager_aidl",
+ ],
+ imports: [
+ "libincremental_aidl",
+ "libdataloader_aidl",
+ ],
+ backend: {
+ java: {
+ sdk_version: "28",
+ },
+ cpp: {
enabled: true,
},
+ ndk: {
+ enabled: false,
+ },
},
}
@@ -935,6 +990,7 @@ java_library {
"core/java/android/os/RemoteException.java",
"core/java/android/util/AndroidException.java",
],
+ libs: [ "unsupportedappusage" ],
dxflags: ["--core-library"],
installable: false,
@@ -966,645 +1022,6 @@ python_binary_host {
],
}
-// Make the api/current.txt file available for use by modules in other
-// directories.
-filegroup {
- name: "frameworks-base-api-current.txt",
- srcs: [
- "api/current.txt",
- ],
-}
-
-// Make the api/system-current.txt file available for use by modules in other
-// directories.
-filegroup {
- name: "frameworks-base-api-system-current.txt",
- srcs: [
- "api/system-current.txt",
- ],
-}
-
-// Make the api/system-removed.txt file available for use by modules in other
-// directories.
-filegroup {
- name: "frameworks-base-api-system-removed.txt",
- srcs: [
- "api/system-removed.txt",
- ],
-}
-
-framework_docs_only_args = " -android -manifest $(location core/res/AndroidManifest.xml) " +
- "-werror -lerror -hide 111 -hide 113 -hide 125 -hide 126 -hide 127 -hide 128 " +
- "-overview $(location core/java/overview.html) " +
- // Federate Support Library references against local API file.
- "-federate SupportLib https://developer.android.com " +
- "-federationapi SupportLib $(location :current-support-api) " +
- // Federate Support Library references against local API file.
- "-federate AndroidX https://developer.android.com " +
- "-federationapi AndroidX $(location :current-androidx-api) "
-
-framework_docs_only_libs = [
- "voip-common",
- "android.test.mock",
- "android-support-annotations",
- "android-support-compat",
- "android-support-core-ui",
- "android-support-core-utils",
- "android-support-design",
- "android-support-dynamic-animation",
- "android-support-exifinterface",
- "android-support-fragment",
- "android-support-media-compat",
- "android-support-percent",
- "android-support-transition",
- "android-support-v7-cardview",
- "android-support-v7-gridlayout",
- "android-support-v7-mediarouter",
- "android-support-v7-palette",
- "android-support-v7-preference",
- "android-support-v13",
- "android-support-v14-preference",
- "android-support-v17-leanback",
- "android-support-vectordrawable",
- "android-support-animatedvectordrawable",
- "android-support-v7-appcompat",
- "android-support-v7-recyclerview",
- "android-support-v8-renderscript",
- "android-support-multidex",
- "android-support-multidex-instrumentation",
-]
-
-metalava_framework_docs_args = "--manifest $(location core/res/AndroidManifest.xml) " +
- "--ignore-classes-on-classpath " +
- "--hide-package com.android.server " +
- "--error UnhiddenSystemApi " +
- "--hide RequiresPermission " +
- "--hide CallbackInterface " +
- "--hide MissingPermission --hide BroadcastBehavior " +
- "--hide HiddenSuperclass --hide DeprecationMismatch --hide UnavailableSymbol " +
- "--hide SdkConstant --hide HiddenTypeParameter --hide Todo --hide Typo " +
- "--force-convert-to-warning-nullability-annotations +*:-android.*:+android.icu.*:-dalvik.*"
-
-packages_to_document = [
- "android",
- "dalvik",
- "java",
- "javax",
- "junit",
- "org.apache.http",
- "org.json",
- "org.w3c.dom",
- "org.xml.sax",
- "org.xmlpull",
-]
-
-stubs_defaults {
- name: "framework-doc-stubs-default",
- srcs: [
- ":framework-mime-sources",
- ":framework-non-updatable-sources",
- ":framework-updatable-sources",
- "core/java/**/*.logtags",
- "test-base/src/**/*.java",
- ":opt-telephony-srcs",
- ":opt-net-voip-srcs",
- ":core-current-stubs-source",
- ":core_public_api_files",
- "test-mock/src/**/*.java",
- "test-runner/src/**/*.java",
- ],
- libs: framework_docs_only_libs,
- create_doc_stubs: true,
- annotations_enabled: true,
- api_levels_annotations_enabled: true,
- api_levels_annotations_dirs: [
- "sdk-dir",
- "api-versions-jars-dir",
- ],
- previous_api: ":last-released-public-api",
- merge_annotations_dirs: [
- "metalava-manual",
- ],
-}
-
-doc_defaults {
- name: "framework-docs-default",
- libs: framework_docs_only_libs +
- ["stub-annotations"],
- html_dirs: [
- "docs/html",
- ],
- knowntags: [
- "docs/knowntags.txt",
- ":known-oj-tags",
- ],
- custom_template: "droiddoc-templates-sdk",
- resourcesdir: "docs/html/reference/images/",
- resourcesoutdir: "reference/android/images/",
- hdf: [
- "dac true",
- "sdk.codename O",
- "sdk.preview.version 1",
- "sdk.version 7.0",
- "sdk.rel.id 1",
- "sdk.preview 0",
- ],
- arg_files: [
- "core/res/AndroidManifest.xml",
- "core/java/overview.html",
- ":current-support-api",
- ":current-androidx-api",
- ],
- create_stubs: false,
-}
-
-doc_defaults {
- name: "framework-dokka-docs-default",
- create_stubs: false,
-}
-
-stubs_defaults {
- name: "metalava-api-stubs-default",
- srcs: [
- ":framework-non-updatable-sources",
- ":framework-updatable-sources",
- "core/java/**/*.logtags",
- ":opt-telephony-srcs",
- ":opt-net-voip-srcs",
- ":core-current-stubs-source",
- ":core_public_api_files",
- ":ike-api-srcs",
- ],
- libs: ["framework-internal-utils"],
- installable: false,
- annotations_enabled: true,
- previous_api: ":last-released-public-api",
- merge_annotations_dirs: [
- "metalava-manual",
- ],
- api_levels_annotations_enabled: true,
- api_levels_annotations_dirs: [
- "sdk-dir",
- "api-versions-jars-dir",
- ],
- sdk_version: "core_platform",
- filter_packages: packages_to_document,
-}
-
-droidstubs {
- name: "framework-doc-stubs",
- defaults: ["framework-doc-stubs-default"],
- arg_files: [
- "core/res/AndroidManifest.xml",
- ],
- args: metalava_framework_docs_args,
- write_sdk_values: true,
-}
-
-droidstubs {
- name: "framework-doc-system-stubs",
- defaults: ["framework-doc-stubs-default"],
- arg_files: [
- "core/res/AndroidManifest.xml",
- ],
- args: metalava_framework_docs_args + " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS,process=android.annotation.SystemApi.Process.ALL\\) ",
- write_sdk_values: true,
-}
-
-droiddoc {
- name: "doc-comment-check-docs",
- defaults: ["framework-docs-default"],
- srcs: [
- ":framework-doc-stubs",
- ],
- args: framework_docs_only_args + " -referenceonly -parsecomments",
- installable: false,
-}
-
-droiddoc {
- name: "offline-sdk-docs",
- defaults: ["framework-docs-default"],
- srcs: [
- ":framework-doc-stubs",
- ],
- hdf: [
- "android.whichdoc offline",
- ],
- proofread_file: "offline-sdk-docs-proofrerad.txt",
- args: framework_docs_only_args + " -offlinemode -title \"Android SDK\"",
- static_doc_index_redirect: "docs/docs-preview-index.html",
-}
-
-droiddoc {
- // Please sync with android-api-council@ before making any changes for the name property below.
- // Since there's cron jobs that fetch offline-sdk-referenceonly-docs-docs.zip periodically.
- // See b/116221385 for reference.
- name: "offline-sdk-referenceonly-docs",
- defaults: ["framework-docs-default"],
- srcs: [
- ":framework-doc-stubs",
- ],
- hdf: [
- "android.whichdoc offline",
- ],
- proofread_file: "offline-sdk-referenceonly-docs-proofrerad.txt",
- args: framework_docs_only_args + " -offlinemode -title \"Android SDK\" -referenceonly",
- static_doc_index_redirect: "docs/docs-documentation-redirect.html",
- static_doc_properties: "docs/source.properties",
-}
-
-droiddoc {
- // Please sync with android-api-council@ before making any changes for the name property below.
- // Since there's cron jobs that fetch offline-system-sdk-referenceonly-docs-docs.zip periodically.
- // See b/116221385 for reference.
- name: "offline-system-sdk-referenceonly-docs",
- defaults: ["framework-docs-default"],
- srcs: [
- ":framework-doc-system-stubs",
- ],
- hdf: [
- "android.whichdoc offline",
- ],
- proofread_file: "offline-system-sdk-referenceonly-docs-proofrerad.txt",
- args: framework_docs_only_args + " -hide 101 -hide 104 -hide 108" +
- " -offlinemode -title \"Android System SDK\" -referenceonly",
- static_doc_index_redirect: "docs/docs-documentation-redirect.html",
- static_doc_properties: "docs/source.properties",
-}
-
-droiddoc {
- name: "online-sdk-docs",
- defaults: ["framework-docs-default"],
- srcs: [
- ":framework-doc-stubs",
- ],
- hdf: [
- "android.whichdoc online",
- "android.hasSamples true",
- ],
- proofread_file: "online-sdk-docs-proofrerad.txt",
- args: framework_docs_only_args +
- " -toroot / -samplegroup Admin " +
- " -samplegroup Background " +
- " -samplegroup Connectivity " +
- " -samplegroup Content " +
- " -samplegroup Input " +
- " -samplegroup Media " +
- " -samplegroup Notification " +
- " -samplegroup RenderScript " +
- " -samplegroup Security " +
- " -samplegroup Sensors " +
- " -samplegroup System " +
- " -samplegroup Testing " +
- " -samplegroup UI " +
- " -samplegroup Views " +
- " -samplegroup Wearable -samplesdir development/samples/browseable ",
-}
-
-droiddoc {
- name: "online-system-api-sdk-docs",
- defaults: ["framework-docs-default"],
- srcs: [
- ":framework-doc-system-stubs",
- ],
- hdf: [
- "android.whichdoc online",
- "android.hasSamples true",
- ],
- proofread_file: "online-system-api-sdk-docs-proofrerad.txt",
- args: framework_docs_only_args +
- " -referenceonly " +
- " -title \"Android SDK - Including system APIs.\" " +
- " -hide 101 " +
- " -hide 104 " +
- " -hide 108 " +
- " -toroot / -samplegroup Admin " +
- " -samplegroup Background " +
- " -samplegroup Connectivity " +
- " -samplegroup Content " +
- " -samplegroup Input " +
- " -samplegroup Media " +
- " -samplegroup Notification " +
- " -samplegroup RenderScript " +
- " -samplegroup Security " +
- " -samplegroup Sensors " +
- " -samplegroup System " +
- " -samplegroup Testing " +
- " -samplegroup UI " +
- " -samplegroup Views " +
- " -samplegroup Wearable -samplesdir development/samples/browseable ",
- installable: false,
-}
-
-droiddoc {
- name: "ds-docs-java",
- defaults: ["framework-docs-default"],
- srcs: [
- ":framework-doc-stubs",
- ],
- hdf: [
- "android.whichdoc online",
- "android.hasSamples true",
- ],
- proofread_file: "ds-docs-proofrerad.txt",
- args: framework_docs_only_args +
- " -toroot / -yamlV2 -metalavaApiSince -samplegroup Admin " +
- " -samplegroup Background " +
- " -samplegroup Connectivity " +
- " -samplegroup Content " +
- " -samplegroup Input " +
- " -samplegroup Media " +
- " -samplegroup Notification " +
- " -samplegroup RenderScript " +
- " -samplegroup Security " +
- " -samplegroup Sensors " +
- " -samplegroup System " +
- " -samplegroup Testing " +
- " -samplegroup UI " +
- " -samplegroup Views " +
- " -samplegroup Wearable -devsite -samplesdir development/samples/browseable ",
-}
-
-droiddoc {
- name: "ds-docs-kt",
- defaults: ["framework-dokka-docs-default"],
- srcs: [
- ":framework-doc-stubs",
- ],
- args: "-noJdkLink -links https://kotlinlang.org/api/latest/jvm/stdlib/^external/dokka/package-list " +
- "-noStdlibLink",
- proofread_file: "ds-dokka-proofread.txt",
- dokka_enabled: true,
-}
-
-java_genrule {
- name: "ds-docs",
- tools: [
- "zip2zip",
- "merge_zips",
- ],
- srcs: [
- ":ds-docs-java{.docs.zip}",
- ":ds-docs-kt{.docs.zip}",
- ],
- out: ["ds-docs.zip"],
- dist: {
- targets: ["docs"],
- },
- cmd: "$(location zip2zip) -i $(location :ds-docs-kt{.docs.zip}) -o $(genDir)/ds-docs-kt-moved.zip **/*:en/reference/kotlin && " +
- "$(location merge_zips) $(out) $(location :ds-docs-java{.docs.zip}) $(genDir)/ds-docs-kt-moved.zip",
-}
-
-java_genrule {
- name: "ds-docs-switched",
- tools: [
- "switcher4",
- "soong_zip",
- ],
- srcs: [
- ":ds-docs-java{.docs.zip}",
- ":ds-docs-kt{.docs.zip}",
- ],
- out: ["ds-docs-switched.zip"],
- dist: {
- targets: ["docs"],
- },
- cmd: "unzip $(location :ds-docs-java{.docs.zip}) -d $(genDir) && " +
- "unzip $(location :ds-docs-kt{.docs.zip}) -d $(genDir)/en/reference/kotlin && " +
- "SWITCHER=$$(cd $$(dirname $(location switcher4)) && pwd)/$$(basename $(location switcher4)) && " +
- "(cd $(genDir)/en/reference && $$SWITCHER --work platform) && " +
- "$(location soong_zip) -o $(out) -C $(genDir) -D $(genDir)",
-}
-
-
-droiddoc {
- name: "ds-static-docs",
- defaults: ["framework-docs-default"],
- srcs: [
- ":framework-doc-stubs",
- ],
- hdf: [
- "android.whichdoc online",
- ],
- proofread_file: "ds-static-docs-proofrerad.txt",
- args: framework_docs_only_args +
- " -staticonly " +
- " -toroot / " +
- " -devsite " +
- " -ignoreJdLinks ",
-}
-
-droiddoc {
- name: "ds-ref-navtree-docs",
- defaults: ["framework-docs-default"],
- srcs: [
- ":framework-doc-stubs",
- ],
- hdf: [
- "android.whichdoc online",
- ],
- proofread_file: "ds-ref-navtree-docs-proofrerad.txt",
- args: framework_docs_only_args +
- " -toroot / " +
- " -atLinksNavtree " +
- " -navtreeonly ",
-}
-
-droiddoc {
- name: "online-sdk-dev-docs",
- defaults: ["framework-docs-default"],
- srcs: [
- ":framework-doc-stubs",
- ],
- hdf: [
- "android.whichdoc online",
- "android.hasSamples true",
- ],
- proofread_file: "online-sdk-dev-docs-proofrerad.txt",
- args: framework_docs_only_args +
- " -toroot / -samplegroup Admin " +
- " -samplegroup Background " +
- " -samplegroup Connectivity " +
- " -samplegroup Content " +
- " -samplegroup Input " +
- " -samplegroup Media " +
- " -samplegroup Notification " +
- " -samplegroup RenderScript " +
- " -samplegroup Security " +
- " -samplegroup Sensors " +
- " -samplegroup System " +
- " -samplegroup Testing " +
- " -samplegroup UI " +
- " -samplegroup Views " +
- " -samplegroup Wearable -samplesdir development/samples/browseable ",
-}
-
-droiddoc {
- name: "hidden-docs",
- defaults: ["framework-docs-default"],
- srcs: [
- ":framework-doc-stubs",
- ],
- proofread_file: "hidden-docs-proofrerad.txt",
- args: framework_docs_only_args +
- " -referenceonly " +
- " -title \"Android SDK - Including hidden APIs.\"",
-}
-
-droidstubs {
- name: "hwbinder-stubs-docs",
- srcs: [
- "core/java/android/os/HidlSupport.java",
- "core/java/android/annotation/IntDef.java",
- "core/java/android/annotation/IntRange.java",
- "core/java/android/annotation/NonNull.java",
- "core/java/android/annotation/SystemApi.java",
- "core/java/android/os/HidlMemory.java",
- "core/java/android/os/HwBinder.java",
- "core/java/android/os/HwBlob.java",
- "core/java/android/os/HwParcel.java",
- "core/java/android/os/IHwBinder.java",
- "core/java/android/os/IHwInterface.java",
- "core/java/android/os/DeadObjectException.java",
- "core/java/android/os/DeadSystemException.java",
- "core/java/android/os/NativeHandle.java",
- "core/java/android/os/RemoteException.java",
- "core/java/android/util/AndroidException.java",
- ],
- installable: false,
- sdk_version: "core_platform",
- annotations_enabled: true,
- previous_api: ":last-released-public-api",
- merge_annotations_dirs: [
- "metalava-manual",
- ],
- args: " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS,process=android.annotation.SystemApi.Process.ALL\\)",
-}
-
-java_library_static {
- name: "hwbinder.stubs",
- sdk_version: "core_current",
- srcs: [
- ":hwbinder-stubs-docs",
- ],
-}
-
-droidstubs {
- name: "hiddenapi-lists-docs",
- defaults: ["metalava-api-stubs-default"],
- arg_files: [
- "core/res/AndroidManifest.xml",
- ],
- dex_api_filename: "public-dex.txt",
- private_dex_api_filename: "private-dex.txt",
- removed_dex_api_filename: "removed-dex.txt",
- args: metalava_framework_docs_args +
- " --show-unannotated " +
- " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS,process=android.annotation.SystemApi.Process.ALL\\) " +
- " --show-annotation android.annotation.TestApi ",
-}
-
-droidstubs {
- name: "hiddenapi-mappings",
- defaults: ["metalava-api-stubs-default"],
- srcs: [
- ":opt-telephony-common-srcs",
- ],
-
- arg_files: [
- "core/res/AndroidManifest.xml",
- ],
- dex_mapping_filename: "dex-mapping.txt",
- args: metalava_framework_docs_args +
- " --hide ReferencesHidden " +
- " --hide UnhiddenSystemApi " +
- " --show-unannotated " +
- " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS,process=android.annotation.SystemApi.Process.ALL\\) " +
- " --show-annotation android.annotation.TestApi ",
-}
-
-droidstubs {
- name: "api-stubs-docs",
- defaults: ["metalava-api-stubs-default"],
- api_filename: "public_api.txt",
- private_api_filename: "private.txt",
- removed_api_filename: "removed.txt",
- arg_files: [
- "core/res/AndroidManifest.xml",
- ],
- args: metalava_framework_docs_args,
- check_api: {
- current: {
- api_file: "api/current.txt",
- removed_api_file: "api/removed.txt",
- },
- last_released: {
- api_file: ":last-released-public-api",
- removed_api_file: "api/removed.txt",
- baseline_file: ":public-api-incompatibilities-with-last-released",
- },
- api_lint: {
- enabled: true,
- new_since: ":last-released-public-api",
- baseline_file: "api/lint-baseline.txt",
- },
- },
- jdiff_enabled: true,
-}
-
-droidstubs {
- name: "system-api-stubs-docs",
- defaults: ["metalava-api-stubs-default"],
- api_tag_name: "SYSTEM",
- api_filename: "system-api.txt",
- private_api_filename: "system-private.txt",
- private_dex_api_filename: "system-private-dex.txt",
- removed_api_filename: "system-removed.txt",
- arg_files: [
- "core/res/AndroidManifest.xml",
- ],
- args: metalava_framework_docs_args + " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS,process=android.annotation.SystemApi.Process.ALL\\)",
- check_api: {
- current: {
- api_file: "api/system-current.txt",
- removed_api_file: "api/system-removed.txt",
- },
- last_released: {
- api_file: ":last-released-system-api",
- removed_api_file: "api/system-removed.txt",
- baseline_file: ":system-api-incompatibilities-with-last-released"
- },
- api_lint: {
- enabled: true,
- new_since: ":last-released-system-api",
- baseline_file: "api/system-lint-baseline.txt",
- },
- },
- jdiff_enabled: true,
-}
-
-droidstubs {
- name: "test-api-stubs-docs",
- defaults: ["metalava-api-stubs-default"],
- api_tag_name: "TEST",
- api_filename: "test-api.txt",
- removed_api_filename: "test-removed.txt",
- arg_files: [
- "core/res/AndroidManifest.xml",
- ],
- args: metalava_framework_docs_args + " --show-annotation android.annotation.TestApi",
- check_api: {
- current: {
- api_file: "api/test-current.txt",
- removed_api_file: "api/test-removed.txt",
- },
- api_lint: {
- enabled: true,
- baseline_file: "api/test-lint-baseline.txt",
- },
- },
-}
-
filegroup {
name: "framework-annotation-nonnull-srcs",
srcs: [
@@ -1615,20 +1032,23 @@ filegroup {
filegroup {
name: "framework-media-annotation-srcs",
srcs: [
+ ":framework-annotations",
"core/java/android/annotation/CallbackExecutor.java",
"core/java/android/annotation/CallSuper.java",
"core/java/android/annotation/DrawableRes.java",
- "core/java/android/annotation/IntDef.java",
"core/java/android/annotation/LongDef.java",
- "core/java/android/annotation/NonNull.java",
- "core/java/android/annotation/Nullable.java",
- "core/java/android/annotation/RequiresPermission.java",
- "core/java/android/annotation/SdkConstant.java",
"core/java/android/annotation/StringDef.java",
- "core/java/android/annotation/SystemApi.java",
- "core/java/android/annotation/TestApi.java",
- "core/java/android/annotation/UnsupportedAppUsage.java",
- "core/java/com/android/internal/annotations/GuardedBy.java",
+ ],
+}
+
+filegroup {
+ name: "framework-mediaprovider-annotation-sources",
+ srcs: [
+ ":framework-annotations",
+ "core/java/android/annotation/BytesLong.java",
+ "core/java/android/annotation/CurrentTimeMillisLong.java",
+ "core/java/android/annotation/CurrentTimeSecondsLong.java",
+ "core/java/android/annotation/DurationMillisLong.java",
],
}
@@ -1655,6 +1075,7 @@ genrule {
filegroup {
name: "framework-telephony-stack-shared-srcs",
srcs: [
+ "core/java/android/os/BasicShellCommandHandler.java",
"core/java/android/os/RegistrantList.java",
"core/java/android/os/Registrant.java",
"core/java/android/util/LocalLog.java",
@@ -1717,3 +1138,20 @@ filegroup {
"core/java/com/android/internal/util/XmlUtils.java",
],
}
+
+// TODO(b/145644363): move this to under StubLibraries.bp or ApiDocs.bp
+metalava_framework_docs_args = "--manifest $(location core/res/AndroidManifest.xml) " +
+ "--ignore-classes-on-classpath " +
+ "--hide-package com.android.server " +
+ "--error UnhiddenSystemApi " +
+ "--hide RequiresPermission " +
+ "--hide CallbackInterface " +
+ "--hide MissingPermission --hide BroadcastBehavior " +
+ "--hide HiddenSuperclass --hide DeprecationMismatch --hide UnavailableSymbol " +
+ "--hide SdkConstant --hide HiddenTypeParameter --hide Todo --hide Typo " +
+ "--force-convert-to-warning-nullability-annotations +*:-android.*:+android.icu.*:-dalvik.*"
+
+build = [
+ "StubLibraries.bp",
+ "ApiDocs.bp",
+]
diff --git a/ApiDocs.bp b/ApiDocs.bp
new file mode 100644
index 000000000000..e373db66925f
--- /dev/null
+++ b/ApiDocs.bp
@@ -0,0 +1,436 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// How API docs are generated:
+//
+// raw source files --(metalava)--> stub source files --(doclava)--> API doc
+//
+// The metalava conversion is done by droidstub modules framework-doc-*-stubs.
+// The API doc generation is done by the various droiddoc modules each of which
+// is for different format.
+
+/////////////////////////////////////////////////////////////////////
+// stub source files are generated using metalava
+/////////////////////////////////////////////////////////////////////
+
+framework_docs_only_libs = [
+ "voip-common",
+ "android.test.mock",
+ "android-support-annotations",
+ "android-support-compat",
+ "android-support-core-ui",
+ "android-support-core-utils",
+ "android-support-design",
+ "android-support-dynamic-animation",
+ "android-support-exifinterface",
+ "android-support-fragment",
+ "android-support-media-compat",
+ "android-support-percent",
+ "android-support-transition",
+ "android-support-v7-cardview",
+ "android-support-v7-gridlayout",
+ "android-support-v7-mediarouter",
+ "android-support-v7-palette",
+ "android-support-v7-preference",
+ "android-support-v13",
+ "android-support-v14-preference",
+ "android-support-v17-leanback",
+ "android-support-vectordrawable",
+ "android-support-animatedvectordrawable",
+ "android-support-v7-appcompat",
+ "android-support-v7-recyclerview",
+ "android-support-v8-renderscript",
+ "android-support-multidex",
+ "android-support-multidex-instrumentation",
+]
+
+stubs_defaults {
+ name: "framework-doc-stubs-default",
+ srcs: [
+ ":framework-mime-sources",
+ ":framework-non-updatable-sources",
+ ":framework-updatable-sources",
+ "core/java/**/*.logtags",
+ "test-base/src/**/*.java",
+ ":opt-telephony-srcs",
+ ":opt-net-voip-srcs",
+ ":core-current-stubs-source",
+ ":core_public_api_files",
+ "test-mock/src/**/*.java",
+ "test-runner/src/**/*.java",
+ ],
+ libs: framework_docs_only_libs,
+ create_doc_stubs: true,
+ annotations_enabled: true,
+ api_levels_annotations_enabled: true,
+ api_levels_annotations_dirs: [
+ "sdk-dir",
+ "api-versions-jars-dir",
+ ],
+ previous_api: ":last-released-public-api",
+ merge_annotations_dirs: [
+ "metalava-manual",
+ ],
+}
+
+droidstubs {
+ name: "framework-doc-stubs",
+ defaults: ["framework-doc-stubs-default"],
+ arg_files: [
+ "core/res/AndroidManifest.xml",
+ ],
+ args: metalava_framework_docs_args,
+ write_sdk_values: true,
+}
+
+droidstubs {
+ name: "framework-doc-system-stubs",
+ defaults: ["framework-doc-stubs-default"],
+ arg_files: [
+ "core/res/AndroidManifest.xml",
+ ],
+ args: metalava_framework_docs_args + " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS,process=android.annotation.SystemApi.Process.ALL\\) ",
+ write_sdk_values: true,
+}
+
+/////////////////////////////////////////////////////////////////////
+// API docs are created from the generated stub source files
+// using droiddoc
+/////////////////////////////////////////////////////////////////////
+
+framework_docs_only_args = " -android -manifest $(location core/res/AndroidManifest.xml) " +
+ "-werror -lerror -hide 111 -hide 113 -hide 125 -hide 126 -hide 127 -hide 128 " +
+ "-overview $(location core/java/overview.html) " +
+ // Federate Support Library references against local API file.
+ "-federate SupportLib https://developer.android.com " +
+ "-federationapi SupportLib $(location :current-support-api) " +
+ // Federate Support Library references against local API file.
+ "-federate AndroidX https://developer.android.com " +
+ "-federationapi AndroidX $(location :current-androidx-api) "
+
+doc_defaults {
+ name: "framework-docs-default",
+ libs: framework_docs_only_libs +
+ ["stub-annotations"],
+ html_dirs: [
+ "docs/html",
+ ],
+ knowntags: [
+ "docs/knowntags.txt",
+ ":known-oj-tags",
+ ],
+ custom_template: "droiddoc-templates-sdk",
+ resourcesdir: "docs/html/reference/images/",
+ resourcesoutdir: "reference/android/images/",
+ hdf: [
+ "dac true",
+ "sdk.codename O",
+ "sdk.preview.version 1",
+ "sdk.version 7.0",
+ "sdk.rel.id 1",
+ "sdk.preview 0",
+ ],
+ arg_files: [
+ "core/res/AndroidManifest.xml",
+ "core/java/overview.html",
+ ":current-support-api",
+ ":current-androidx-api",
+ ],
+ create_stubs: false,
+}
+
+doc_defaults {
+ name: "framework-dokka-docs-default",
+ create_stubs: false,
+}
+
+droiddoc {
+ name: "doc-comment-check-docs",
+ defaults: ["framework-docs-default"],
+ srcs: [
+ ":framework-doc-stubs",
+ ],
+ args: framework_docs_only_args + " -referenceonly -parsecomments",
+ installable: false,
+}
+
+droiddoc {
+ name: "offline-sdk-docs",
+ defaults: ["framework-docs-default"],
+ srcs: [
+ ":framework-doc-stubs",
+ ],
+ hdf: [
+ "android.whichdoc offline",
+ ],
+ proofread_file: "offline-sdk-docs-proofrerad.txt",
+ args: framework_docs_only_args + " -offlinemode -title \"Android SDK\"",
+ static_doc_index_redirect: "docs/docs-preview-index.html",
+}
+
+droiddoc {
+ // Please sync with android-api-council@ before making any changes for the name property below.
+ // Since there's cron jobs that fetch offline-sdk-referenceonly-docs-docs.zip periodically.
+ // See b/116221385 for reference.
+ name: "offline-sdk-referenceonly-docs",
+ defaults: ["framework-docs-default"],
+ srcs: [
+ ":framework-doc-stubs",
+ ],
+ hdf: [
+ "android.whichdoc offline",
+ ],
+ proofread_file: "offline-sdk-referenceonly-docs-proofrerad.txt",
+ args: framework_docs_only_args + " -offlinemode -title \"Android SDK\" -referenceonly",
+ static_doc_index_redirect: "docs/docs-documentation-redirect.html",
+ static_doc_properties: "docs/source.properties",
+}
+
+droiddoc {
+ // Please sync with android-api-council@ before making any changes for the name property below.
+ // Since there's cron jobs that fetch offline-system-sdk-referenceonly-docs-docs.zip periodically.
+ // See b/116221385 for reference.
+ name: "offline-system-sdk-referenceonly-docs",
+ defaults: ["framework-docs-default"],
+ srcs: [
+ ":framework-doc-system-stubs",
+ ],
+ hdf: [
+ "android.whichdoc offline",
+ ],
+ proofread_file: "offline-system-sdk-referenceonly-docs-proofrerad.txt",
+ args: framework_docs_only_args + " -hide 101 -hide 104 -hide 108" +
+ " -offlinemode -title \"Android System SDK\" -referenceonly",
+ static_doc_index_redirect: "docs/docs-documentation-redirect.html",
+ static_doc_properties: "docs/source.properties",
+}
+
+droiddoc {
+ name: "online-sdk-docs",
+ defaults: ["framework-docs-default"],
+ srcs: [
+ ":framework-doc-stubs",
+ ],
+ hdf: [
+ "android.whichdoc online",
+ "android.hasSamples true",
+ ],
+ proofread_file: "online-sdk-docs-proofrerad.txt",
+ args: framework_docs_only_args +
+ " -toroot / -samplegroup Admin " +
+ " -samplegroup Background " +
+ " -samplegroup Connectivity " +
+ " -samplegroup Content " +
+ " -samplegroup Input " +
+ " -samplegroup Media " +
+ " -samplegroup Notification " +
+ " -samplegroup RenderScript " +
+ " -samplegroup Security " +
+ " -samplegroup Sensors " +
+ " -samplegroup System " +
+ " -samplegroup Testing " +
+ " -samplegroup UI " +
+ " -samplegroup Views " +
+ " -samplegroup Wearable -samplesdir development/samples/browseable ",
+}
+
+droiddoc {
+ name: "online-system-api-sdk-docs",
+ defaults: ["framework-docs-default"],
+ srcs: [
+ ":framework-doc-system-stubs",
+ ],
+ hdf: [
+ "android.whichdoc online",
+ "android.hasSamples true",
+ ],
+ proofread_file: "online-system-api-sdk-docs-proofrerad.txt",
+ args: framework_docs_only_args +
+ " -referenceonly " +
+ " -title \"Android SDK - Including system APIs.\" " +
+ " -hide 101 " +
+ " -hide 104 " +
+ " -hide 108 " +
+ " -toroot / -samplegroup Admin " +
+ " -samplegroup Background " +
+ " -samplegroup Connectivity " +
+ " -samplegroup Content " +
+ " -samplegroup Input " +
+ " -samplegroup Media " +
+ " -samplegroup Notification " +
+ " -samplegroup RenderScript " +
+ " -samplegroup Security " +
+ " -samplegroup Sensors " +
+ " -samplegroup System " +
+ " -samplegroup Testing " +
+ " -samplegroup UI " +
+ " -samplegroup Views " +
+ " -samplegroup Wearable -samplesdir development/samples/browseable ",
+ installable: false,
+}
+
+droiddoc {
+ name: "ds-docs-java",
+ defaults: ["framework-docs-default"],
+ srcs: [
+ ":framework-doc-stubs",
+ ],
+ hdf: [
+ "android.whichdoc online",
+ "android.hasSamples true",
+ ],
+ proofread_file: "ds-docs-proofrerad.txt",
+ args: framework_docs_only_args +
+ " -toroot / -yamlV2 -metalavaApiSince -samplegroup Admin " +
+ " -samplegroup Background " +
+ " -samplegroup Connectivity " +
+ " -samplegroup Content " +
+ " -samplegroup Input " +
+ " -samplegroup Media " +
+ " -samplegroup Notification " +
+ " -samplegroup RenderScript " +
+ " -samplegroup Security " +
+ " -samplegroup Sensors " +
+ " -samplegroup System " +
+ " -samplegroup Testing " +
+ " -samplegroup UI " +
+ " -samplegroup Views " +
+ " -samplegroup Wearable -devsite -samplesdir development/samples/browseable ",
+}
+
+droiddoc {
+ name: "ds-docs-kt",
+ defaults: ["framework-dokka-docs-default"],
+ srcs: [
+ ":framework-doc-stubs",
+ ],
+ args: "-noJdkLink -links https://kotlinlang.org/api/latest/jvm/stdlib/^external/dokka/package-list " +
+ "-noStdlibLink",
+ proofread_file: "ds-dokka-proofread.txt",
+ dokka_enabled: true,
+}
+
+java_genrule {
+ name: "ds-docs",
+ tools: [
+ "zip2zip",
+ "merge_zips",
+ ],
+ srcs: [
+ ":ds-docs-java{.docs.zip}",
+ ":ds-docs-kt{.docs.zip}",
+ ],
+ out: ["ds-docs.zip"],
+ dist: {
+ targets: ["docs"],
+ },
+ cmd: "$(location zip2zip) -i $(location :ds-docs-kt{.docs.zip}) -o $(genDir)/ds-docs-kt-moved.zip **/*:en/reference/kotlin && " +
+ "$(location merge_zips) $(out) $(location :ds-docs-java{.docs.zip}) $(genDir)/ds-docs-kt-moved.zip",
+}
+
+java_genrule {
+ name: "ds-docs-switched",
+ tools: [
+ "switcher4",
+ "soong_zip",
+ ],
+ srcs: [
+ ":ds-docs-java{.docs.zip}",
+ ":ds-docs-kt{.docs.zip}",
+ ],
+ out: ["ds-docs-switched.zip"],
+ dist: {
+ targets: ["docs"],
+ },
+ cmd: "unzip $(location :ds-docs-java{.docs.zip}) -d $(genDir) && " +
+ "unzip $(location :ds-docs-kt{.docs.zip}) -d $(genDir)/en/reference/kotlin && " +
+ "SWITCHER=$$(cd $$(dirname $(location switcher4)) && pwd)/$$(basename $(location switcher4)) && " +
+ "(cd $(genDir)/en/reference && $$SWITCHER --work platform) && " +
+ "$(location soong_zip) -o $(out) -C $(genDir) -D $(genDir)",
+}
+
+droiddoc {
+ name: "ds-static-docs",
+ defaults: ["framework-docs-default"],
+ srcs: [
+ ":framework-doc-stubs",
+ ],
+ hdf: [
+ "android.whichdoc online",
+ ],
+ proofread_file: "ds-static-docs-proofrerad.txt",
+ args: framework_docs_only_args +
+ " -staticonly " +
+ " -toroot / " +
+ " -devsite " +
+ " -ignoreJdLinks ",
+}
+
+droiddoc {
+ name: "ds-ref-navtree-docs",
+ defaults: ["framework-docs-default"],
+ srcs: [
+ ":framework-doc-stubs",
+ ],
+ hdf: [
+ "android.whichdoc online",
+ ],
+ proofread_file: "ds-ref-navtree-docs-proofrerad.txt",
+ args: framework_docs_only_args +
+ " -toroot / " +
+ " -atLinksNavtree " +
+ " -navtreeonly ",
+}
+
+droiddoc {
+ name: "online-sdk-dev-docs",
+ defaults: ["framework-docs-default"],
+ srcs: [
+ ":framework-doc-stubs",
+ ],
+ hdf: [
+ "android.whichdoc online",
+ "android.hasSamples true",
+ ],
+ proofread_file: "online-sdk-dev-docs-proofrerad.txt",
+ args: framework_docs_only_args +
+ " -toroot / -samplegroup Admin " +
+ " -samplegroup Background " +
+ " -samplegroup Connectivity " +
+ " -samplegroup Content " +
+ " -samplegroup Input " +
+ " -samplegroup Media " +
+ " -samplegroup Notification " +
+ " -samplegroup RenderScript " +
+ " -samplegroup Security " +
+ " -samplegroup Sensors " +
+ " -samplegroup System " +
+ " -samplegroup Testing " +
+ " -samplegroup UI " +
+ " -samplegroup Views " +
+ " -samplegroup Wearable -samplesdir development/samples/browseable ",
+}
+
+droiddoc {
+ name: "hidden-docs",
+ defaults: ["framework-docs-default"],
+ srcs: [
+ ":framework-doc-stubs",
+ ],
+ proofread_file: "hidden-docs-proofrerad.txt",
+ args: framework_docs_only_args +
+ " -referenceonly " +
+ " -title \"Android SDK - Including hidden APIs.\"",
+}
+
diff --git a/CleanSpec.mk b/CleanSpec.mk
index f94de29d41b1..0b7ea2832afa 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -257,6 +257,9 @@ $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/framework/ext.jar)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/telephony/java/com/google/android/mms)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/framework/*-service.jar)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/framework/service-statsd.jar)
+$(call add-clean-step, rm -rf $(SOONG_OUT_DIR)/.intermediates/frameworks/base/libincremental_aidl-cpp-source/)
+$(call add-clean-step, rm -rf $(SOONG_OUT_DIR)/.intermediates/frameworks/base/libincremental_manager_aidl-cpp-source/)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/priv-app/InProcessTethering)
# ******************************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
# ******************************************************************
diff --git a/StubLibraries.bp b/StubLibraries.bp
new file mode 100644
index 000000000000..78f1b9ca26e5
--- /dev/null
+++ b/StubLibraries.bp
@@ -0,0 +1,340 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// How stubs are generated:
+//
+// raw source files --(metalava)--> stub source files --(javac)--> stub jar files
+//
+// The metalava conversion is done by droidstub modules *-api-stubs-docs.
+// The javac compilation is done by java_library modules android_*_stubs_current.
+// The metalava conversion is also responsible for creating API signature files
+// and comparing them against the last API signature in api/*-current.txt files
+// and also against the latest frozen API signature in prebuilts/sdk/*/*/api/android.txt
+// files.
+
+/////////////////////////////////////////////////////////////////////
+// Common metalava configs
+/////////////////////////////////////////////////////////////////////
+
+packages_to_document = [
+ "android",
+ "dalvik",
+ "java",
+ "javax",
+ "junit",
+ "org.apache.http",
+ "org.json",
+ "org.w3c.dom",
+ "org.xml.sax",
+ "org.xmlpull",
+]
+
+stubs_defaults {
+ name: "metalava-api-stubs-default",
+ srcs: [
+ ":framework-non-updatable-sources",
+ ":framework-updatable-sources",
+ "core/java/**/*.logtags",
+ ":opt-telephony-srcs",
+ ":opt-net-voip-srcs",
+ ":core-current-stubs-source",
+ ":core_public_api_files",
+ ":ike-api-srcs",
+ ],
+ libs: ["framework-internal-utils"],
+ installable: false,
+ annotations_enabled: true,
+ previous_api: ":last-released-public-api",
+ merge_annotations_dirs: [
+ "metalava-manual",
+ ],
+ api_levels_annotations_enabled: true,
+ api_levels_annotations_dirs: [
+ "sdk-dir",
+ "api-versions-jars-dir",
+ ],
+ sdk_version: "core_platform",
+ filter_packages: packages_to_document,
+}
+
+/////////////////////////////////////////////////////////////////////
+// *-api-stubs-docs modules providing source files for the stub libraries
+/////////////////////////////////////////////////////////////////////
+
+droidstubs {
+ name: "api-stubs-docs",
+ defaults: ["metalava-api-stubs-default"],
+ api_filename: "public_api.txt",
+ private_api_filename: "private.txt",
+ removed_api_filename: "removed.txt",
+ arg_files: [
+ "core/res/AndroidManifest.xml",
+ ],
+ args: metalava_framework_docs_args,
+ check_api: {
+ current: {
+ api_file: "api/current.txt",
+ removed_api_file: "api/removed.txt",
+ },
+ last_released: {
+ api_file: ":last-released-public-api",
+ removed_api_file: "api/removed.txt",
+ baseline_file: ":public-api-incompatibilities-with-last-released",
+ },
+ api_lint: {
+ enabled: true,
+ new_since: ":last-released-public-api",
+ baseline_file: "api/lint-baseline.txt",
+ },
+ },
+ jdiff_enabled: true,
+}
+
+droidstubs {
+ name: "system-api-stubs-docs",
+ defaults: ["metalava-api-stubs-default"],
+ api_tag_name: "SYSTEM",
+ api_filename: "system-api.txt",
+ private_api_filename: "system-private.txt",
+ private_dex_api_filename: "system-private-dex.txt",
+ removed_api_filename: "system-removed.txt",
+ arg_files: [
+ "core/res/AndroidManifest.xml",
+ ],
+ args: metalava_framework_docs_args + " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS,process=android.annotation.SystemApi.Process.ALL\\)",
+ check_api: {
+ current: {
+ api_file: "api/system-current.txt",
+ removed_api_file: "api/system-removed.txt",
+ },
+ last_released: {
+ api_file: ":last-released-system-api",
+ removed_api_file: "api/system-removed.txt",
+ baseline_file: ":system-api-incompatibilities-with-last-released"
+ },
+ api_lint: {
+ enabled: true,
+ new_since: ":last-released-system-api",
+ baseline_file: "api/system-lint-baseline.txt",
+ },
+ },
+ jdiff_enabled: true,
+}
+
+droidstubs {
+ name: "test-api-stubs-docs",
+ defaults: ["metalava-api-stubs-default"],
+ api_tag_name: "TEST",
+ api_filename: "test-api.txt",
+ removed_api_filename: "test-removed.txt",
+ arg_files: [
+ "core/res/AndroidManifest.xml",
+ ],
+ args: metalava_framework_docs_args + " --show-annotation android.annotation.TestApi",
+ check_api: {
+ current: {
+ api_file: "api/test-current.txt",
+ removed_api_file: "api/test-removed.txt",
+ },
+ api_lint: {
+ enabled: true,
+ baseline_file: "api/test-lint-baseline.txt",
+ },
+ },
+}
+
+/////////////////////////////////////////////////////////////////////
+// android_*_stubs_current modules are the stubs libraries compiled
+// from *-api-stubs-docs
+/////////////////////////////////////////////////////////////////////
+
+java_defaults {
+ name: "framework-stubs-default",
+ errorprone: {
+ javacflags: [
+ "-XepDisableAllChecks",
+ ],
+ },
+ java_resources: [
+ ":notices-for-framework-stubs",
+ ],
+ sdk_version: "core_current",
+ system_modules: "none",
+ java_version: "1.8",
+ compile_dex: true,
+}
+
+java_library_static {
+ name: "android_stubs_current",
+ srcs: [
+ ":api-stubs-docs",
+ ],
+ libs: [
+ "stub-annotations",
+ ],
+ static_libs: [
+ "private-stub-annotations-jar",
+ ],
+ defaults: ["framework-stubs-default"],
+}
+
+java_library_static {
+ name: "android_system_stubs_current",
+ srcs: [
+ ":system-api-stubs-docs",
+ ],
+ libs: [
+ "stub-annotations",
+ ],
+ static_libs: [
+ "private-stub-annotations-jar",
+ ],
+ defaults: ["framework-stubs-default"],
+}
+
+java_library_static {
+ name: "android_test_stubs_current",
+ srcs: [
+ ":test-api-stubs-docs",
+ ],
+ libs: [
+ "stub-annotations",
+ ],
+ static_libs: [
+ "private-stub-annotations-jar",
+ ],
+ defaults: ["framework-stubs-default"],
+}
+
+java_system_modules {
+ name: "android_stubs_current_system_modules",
+ libs: ["android_stubs_current"],
+}
+
+java_system_modules {
+ name: "android_system_stubs_current_system_modules",
+ libs: ["android_system_stubs_current"],
+}
+
+java_system_modules {
+ name: "android_test_stubs_current_system_modules",
+ libs: ["android_test_stubs_current"],
+}
+
+/////////////////////////////////////////////////////////////////////
+// hwbinder.stubs provides APIs required for building HIDL Java
+// libraries.
+/////////////////////////////////////////////////////////////////////
+
+droidstubs {
+ name: "hwbinder-stubs-docs",
+ srcs: [
+ "core/java/android/os/HidlSupport.java",
+ "core/java/android/annotation/IntDef.java",
+ "core/java/android/annotation/IntRange.java",
+ "core/java/android/annotation/NonNull.java",
+ "core/java/android/annotation/SystemApi.java",
+ "core/java/android/os/HidlMemory.java",
+ "core/java/android/os/HwBinder.java",
+ "core/java/android/os/HwBlob.java",
+ "core/java/android/os/HwParcel.java",
+ "core/java/android/os/IHwBinder.java",
+ "core/java/android/os/IHwInterface.java",
+ "core/java/android/os/DeadObjectException.java",
+ "core/java/android/os/DeadSystemException.java",
+ "core/java/android/os/NativeHandle.java",
+ "core/java/android/os/RemoteException.java",
+ "core/java/android/util/AndroidException.java",
+ ],
+ installable: false,
+ sdk_version: "core_platform",
+ annotations_enabled: true,
+ previous_api: ":last-released-public-api",
+ merge_annotations_dirs: [
+ "metalava-manual",
+ ],
+ args: " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS,process=android.annotation.SystemApi.Process.ALL\\)",
+}
+
+java_library_static {
+ name: "hwbinder.stubs",
+ sdk_version: "core_current",
+ srcs: [
+ ":hwbinder-stubs-docs",
+ ],
+}
+
+/////////////////////////////////////////////////////////////////////
+// Stubs for hiddenapi processing.
+/////////////////////////////////////////////////////////////////////
+
+droidstubs {
+ name: "hiddenapi-lists-docs",
+ defaults: ["metalava-api-stubs-default"],
+ arg_files: [
+ "core/res/AndroidManifest.xml",
+ ],
+ dex_api_filename: "public-dex.txt",
+ private_dex_api_filename: "private-dex.txt",
+ removed_dex_api_filename: "removed-dex.txt",
+ args: metalava_framework_docs_args +
+ " --show-unannotated " +
+ " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS,process=android.annotation.SystemApi.Process.ALL\\) " +
+ " --show-annotation android.annotation.TestApi ",
+}
+
+droidstubs {
+ name: "hiddenapi-mappings",
+ defaults: ["metalava-api-stubs-default"],
+ srcs: [
+ ":opt-telephony-common-srcs",
+ ],
+
+ arg_files: [
+ "core/res/AndroidManifest.xml",
+ ],
+ dex_mapping_filename: "dex-mapping.txt",
+ args: metalava_framework_docs_args +
+ " --hide ReferencesHidden " +
+ " --hide UnhiddenSystemApi " +
+ " --show-unannotated " +
+ " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS,process=android.annotation.SystemApi.Process.ALL\\) " +
+ " --show-annotation android.annotation.TestApi ",
+}
+
+/////////////////////////////////////////////////////////////////////
+// api/*-current.txt files for use by modules in other directories
+// like the CTS test
+/////////////////////////////////////////////////////////////////////
+
+filegroup {
+ name: "frameworks-base-api-current.txt",
+ srcs: [
+ "api/current.txt",
+ ],
+}
+
+filegroup {
+ name: "frameworks-base-api-system-current.txt",
+ srcs: [
+ "api/system-current.txt",
+ ],
+}
+
+filegroup {
+ name: "frameworks-base-api-system-removed.txt",
+ srcs: [
+ "api/system-removed.txt",
+ ],
+}
diff --git a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
index 278a78676a0b..661f32f35cb2 100644
--- a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
+++ b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
@@ -146,7 +146,8 @@ public class UserLifecycleTests {
final CountDownLatch latch = new CountDownLatch(1);
registerBroadcastReceiver(Intent.ACTION_USER_STARTED, latch, userId);
- // Don't use this.startUserInBackground() since only waiting until ACTION_USER_STARTED.
+ // Don't use this.startUserInBackgroundAndWaitForUnlock() since only waiting until
+ // ACTION_USER_STARTED.
mIam.startUserInBackground(userId);
latch.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS);
@@ -156,6 +157,48 @@ public class UserLifecycleTests {
}
}
+ /**
+ * Measures the time until ACTION_USER_STARTED is received.
+ */
+ @Test
+ public void startUser() throws Exception {
+ while (mRunner.keepRunning()) {
+ mRunner.pauseTiming();
+ final int userId = createUserNoFlags();
+ final CountDownLatch latch = new CountDownLatch(1);
+ registerBroadcastReceiver(Intent.ACTION_USER_STARTED, latch, userId);
+ mRunner.resumeTiming();
+
+ mIam.startUserInBackground(userId);
+ latch.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS);
+
+ mRunner.pauseTiming();
+ removeUser(userId);
+ mRunner.resumeTiming();
+ }
+ }
+
+ /**
+ * Measures the time until unlock listener is triggered and user is unlocked.
+ */
+ @Test
+ public void startAndUnlockUser() throws Exception {
+ while (mRunner.keepRunning()) {
+ mRunner.pauseTiming();
+ final int userId = createUserNoFlags();
+ mRunner.resumeTiming();
+
+ // Waits for UserState.mUnlockProgress.finish().
+ startUserInBackgroundAndWaitForUnlock(userId);
+
+ mRunner.pauseTiming();
+ removeUser(userId);
+ mRunner.resumeTiming();
+ }
+ }
+
+
+
@Test
public void switchUser() throws Exception {
while (mRunner.keepRunning()) {
@@ -309,7 +352,7 @@ public class UserLifecycleTests {
final int userId = createManagedProfile();
mRunner.resumeTiming();
- startUserInBackground(userId);
+ startUserInBackgroundAndWaitForUnlock(userId);
mRunner.pauseTiming();
removeUser(userId);
@@ -326,11 +369,11 @@ public class UserLifecycleTests {
mRunner.pauseTiming();
final int userId = createManagedProfile();
// Start the profile initially, then stop it. Similar to setQuietModeEnabled.
- startUserInBackground(userId);
+ startUserInBackgroundAndWaitForUnlock(userId);
stopUser(userId, true);
mRunner.resumeTiming();
- startUserInBackground(userId);
+ startUserInBackgroundAndWaitForUnlock(userId);
mRunner.pauseTiming();
removeUser(userId);
@@ -352,7 +395,7 @@ public class UserLifecycleTests {
installPreexistingApp(userId, DUMMY_PACKAGE_NAME);
mRunner.resumeTiming();
- startUserInBackground(userId);
+ startUserInBackgroundAndWaitForUnlock(userId);
startApp(userId, DUMMY_PACKAGE_NAME);
mRunner.pauseTiming();
@@ -376,13 +419,13 @@ public class UserLifecycleTests {
final int userId = createManagedProfile();
WindowManagerGlobal.getWindowManagerService().dismissKeyguard(null, null);
installPreexistingApp(userId, DUMMY_PACKAGE_NAME);
- startUserInBackground(userId);
+ startUserInBackgroundAndWaitForUnlock(userId);
startApp(userId, DUMMY_PACKAGE_NAME);
stopUser(userId, true);
TimeUnit.SECONDS.sleep(1); // Brief cool-down before re-starting profile.
mRunner.resumeTiming();
- startUserInBackground(userId);
+ startUserInBackgroundAndWaitForUnlock(userId);
startApp(userId, DUMMY_PACKAGE_NAME);
mRunner.pauseTiming();
@@ -423,7 +466,7 @@ public class UserLifecycleTests {
mRunner.resumeTiming();
final int userId = createManagedProfile();
- startUserInBackground(userId);
+ startUserInBackgroundAndWaitForUnlock(userId);
installPreexistingApp(userId, DUMMY_PACKAGE_NAME);
startApp(userId, DUMMY_PACKAGE_NAME);
@@ -441,7 +484,7 @@ public class UserLifecycleTests {
while (mRunner.keepRunning()) {
mRunner.pauseTiming();
final int userId = createManagedProfile();
- startUserInBackground(userId);
+ startUserInBackgroundAndWaitForUnlock(userId);
mRunner.resumeTiming();
stopUser(userId, true);
@@ -467,7 +510,7 @@ public class UserLifecycleTests {
final int userId = createManagedProfile();
mRunner.resumeTiming();
- startUserInBackground(userId);
+ startUserInBackgroundAndWaitForUnlock(userId);
mRunner.pauseTiming();
removeUser(userId);
@@ -490,7 +533,7 @@ public class UserLifecycleTests {
final int userId = createManagedProfile();
mRunner.resumeTiming();
- startUserInBackground(userId);
+ startUserInBackgroundAndWaitForUnlock(userId);
mRunner.pauseTiming();
removeUser(userId);
@@ -526,18 +569,19 @@ public class UserLifecycleTests {
}
/**
- * Start user in background and wait for it to unlock (equivalent to ACTION_USER_UNLOCKED).
- * To start in foreground instead, see {@link #switchUser(int)}.
- * This should always be used for profiles since profiles cannot be started in foreground.
+ * Start user in background and wait for it to unlock by waiting for
+ * UserState.mUnlockProgress.finish().
+ * <p> To start in foreground instead, see {@link #switchUser(int)}.
+ * <p> This should always be used for profiles since profiles cannot be started in foreground.
*/
- private void startUserInBackground(int userId) {
+ private void startUserInBackgroundAndWaitForUnlock(int userId) {
final ProgressWaiter waiter = new ProgressWaiter();
try {
mIam.startUserInBackgroundWithListener(userId, waiter);
boolean success = waiter.waitForFinish(TIMEOUT_IN_SECOND);
attestTrue("Failed to start user " + userId + " in background.", success);
} catch (RemoteException e) {
- Log.e(TAG, "startUserInBackground failed", e);
+ Log.e(TAG, "startUserInBackgroundAndWaitForUnlock failed", e);
}
}
diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
index 701ea849c38f..3f58c72cbdc2 100644
--- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
+++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
@@ -617,6 +617,14 @@ public class DeviceIdleController extends SystemService
}
};
+ /** AlarmListener to start monitoring motion if there are registered stationary listeners. */
+ private final AlarmManager.OnAlarmListener mMotionRegistrationAlarmListener = () -> {
+ synchronized (DeviceIdleController.this) {
+ if (mStationaryListeners.size() > 0) {
+ startMonitoringMotionLocked();
+ }
+ }
+ };
private final AlarmManager.OnAlarmListener mMotionTimeoutAlarmListener = () -> {
synchronized (DeviceIdleController.this) {
@@ -753,6 +761,7 @@ public class DeviceIdleController extends SystemService
@Override
public void onTrigger(TriggerEvent event) {
synchronized (DeviceIdleController.this) {
+ active = false;
motionLocked();
}
}
@@ -760,6 +769,8 @@ public class DeviceIdleController extends SystemService
@Override
public void onSensorChanged(SensorEvent event) {
synchronized (DeviceIdleController.this) {
+ mSensorManager.unregisterListener(this, mMotionSensor);
+ active = false;
motionLocked();
}
}
@@ -1878,6 +1889,27 @@ public class DeviceIdleController extends SystemService
return controller.new MyHandler(BackgroundThread.getHandler().getLooper());
}
+ Sensor getMotionSensor() {
+ final SensorManager sensorManager = getSensorManager();
+ Sensor motionSensor = null;
+ int sigMotionSensorId = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_autoPowerModeAnyMotionSensor);
+ if (sigMotionSensorId > 0) {
+ motionSensor = sensorManager.getDefaultSensor(sigMotionSensorId, true);
+ }
+ if (motionSensor == null && mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_autoPowerModePreferWristTilt)) {
+ motionSensor = sensorManager.getDefaultSensor(
+ Sensor.TYPE_WRIST_TILT_GESTURE, true);
+ }
+ if (motionSensor == null) {
+ // As a last ditch, fall back to SMD.
+ motionSensor = sensorManager.getDefaultSensor(
+ Sensor.TYPE_SIGNIFICANT_MOTION, true);
+ }
+ return motionSensor;
+ }
+
PowerManager getPowerManager() {
return mContext.getSystemService(PowerManager.class);
}
@@ -2031,21 +2063,7 @@ public class DeviceIdleController extends SystemService
mSensorManager = mInjector.getSensorManager();
if (mUseMotionSensor) {
- int sigMotionSensorId = getContext().getResources().getInteger(
- com.android.internal.R.integer.config_autoPowerModeAnyMotionSensor);
- if (sigMotionSensorId > 0) {
- mMotionSensor = mSensorManager.getDefaultSensor(sigMotionSensorId, true);
- }
- if (mMotionSensor == null && getContext().getResources().getBoolean(
- com.android.internal.R.bool.config_autoPowerModePreferWristTilt)) {
- mMotionSensor = mSensorManager.getDefaultSensor(
- Sensor.TYPE_WRIST_TILT_GESTURE, true);
- }
- if (mMotionSensor == null) {
- // As a last ditch, fall back to SMD.
- mMotionSensor = mSensorManager.getDefaultSensor(
- Sensor.TYPE_SIGNIFICANT_MOTION, true);
- }
+ mMotionSensor = mInjector.getMotionSensor();
}
if (getContext().getResources().getBoolean(
@@ -3434,6 +3452,10 @@ public class DeviceIdleController extends SystemService
if (mStationaryListeners.size() > 0) {
postStationaryStatusUpdated();
scheduleMotionTimeoutAlarmLocked();
+ // We need to re-register the motion listener, but we don't want the sensors to be
+ // constantly active or to churn the CPU by registering too early, register after some
+ // delay.
+ scheduleMotionRegistrationAlarmLocked();
}
if (mQuickDozeActivated && !mQuickDozeActivatedWhileIdling) {
// Don't exit idle due to motion if quick doze is enabled.
@@ -3500,9 +3522,12 @@ public class DeviceIdleController extends SystemService
*/
private void maybeStopMonitoringMotionLocked() {
if (DEBUG) Slog.d(TAG, "maybeStopMonitoringMotionLocked()");
- if (mMotionSensor != null && mMotionListener.active && mStationaryListeners.size() == 0) {
- mMotionListener.unregisterLocked();
- cancelMotionTimeoutAlarmLocked();
+ if (mMotionSensor != null && mStationaryListeners.size() == 0) {
+ if (mMotionListener.active) {
+ mMotionListener.unregisterLocked();
+ cancelMotionTimeoutAlarmLocked();
+ }
+ cancelMotionRegistrationAlarmLocked();
}
}
@@ -3533,6 +3558,10 @@ public class DeviceIdleController extends SystemService
mAlarmManager.cancel(mMotionTimeoutAlarmListener);
}
+ private void cancelMotionRegistrationAlarmLocked() {
+ mAlarmManager.cancel(mMotionRegistrationAlarmListener);
+ }
+
void cancelSensingTimeoutAlarmLocked() {
if (mNextSensingTimeoutAlarmTime != 0) {
mNextSensingTimeoutAlarmTime = 0;
@@ -3573,6 +3602,15 @@ public class DeviceIdleController extends SystemService
mNextLightAlarmTime, "DeviceIdleController.light", mLightAlarmListener, mHandler);
}
+ private void scheduleMotionRegistrationAlarmLocked() {
+ if (DEBUG) Slog.d(TAG, "scheduleMotionRegistrationAlarmLocked");
+ long nextMotionRegistrationAlarmTime =
+ mInjector.getElapsedRealtime() + mConstants.MOTION_INACTIVE_TIMEOUT / 2;
+ mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, nextMotionRegistrationAlarmTime,
+ "DeviceIdleController.motion_registration", mMotionRegistrationAlarmListener,
+ mHandler);
+ }
+
private void scheduleMotionTimeoutAlarmLocked() {
if (DEBUG) Slog.d(TAG, "scheduleMotionAlarmLocked");
long nextMotionTimeoutAlarmTime =
diff --git a/apex/sdkext/Android.bp b/apex/sdkext/Android.bp
index 5369a96d965c..f62f167cdcfa 100644
--- a/apex/sdkext/Android.bp
+++ b/apex/sdkext/Android.bp
@@ -32,7 +32,7 @@ apex {
sdk {
name: "sdkext-sdk",
- java_libs: [ "framework-sdkext-stubs-systemapi" ],
+ java_header_libs: [ "framework-sdkext-stubs-systemapi" ],
}
apex_key {
diff --git a/apex/sdkext/derive_sdk/derive_sdk.cpp b/apex/sdkext/derive_sdk/derive_sdk.cpp
index 7536def60767..0a9711677015 100644
--- a/apex/sdkext/derive_sdk/derive_sdk.cpp
+++ b/apex/sdkext/derive_sdk/derive_sdk.cpp
@@ -63,6 +63,7 @@ int main(int, char**) {
LOG(ERROR) << "failed to parse " << path;
continue;
}
+ LOG(INFO) << "Read version " << sdk_version.version() << " from " << path;
versions.push_back(sdk_version.version());
}
auto itr = std::min_element(versions.begin(), versions.end());
@@ -73,5 +74,6 @@ int main(int, char**) {
return EXIT_FAILURE;
}
+ LOG(INFO) << "R extension version is " << prop_value;
return EXIT_SUCCESS;
}
diff --git a/apex/statsd/aidl/Android.bp b/apex/statsd/aidl/Android.bp
index e6ca544c04be..aed6ad9fc08a 100644
--- a/apex/statsd/aidl/Android.bp
+++ b/apex/statsd/aidl/Android.bp
@@ -17,6 +17,18 @@
// TODO(b/145815909): move StatsDimensionsValue.aidl and StatsLogEventWrapper.aidl here
filegroup {
name: "statsd_aidl",
+ srcs: [
+ "android/os/IPullAtomCallback.aidl",
+ "android/os/IPullAtomResultReceiver.aidl",
+ "android/os/IStatsCompanionService.aidl",
+ "android/os/IStatsd.aidl",
+ "android/os/IStatsPullerCallback.aidl",
+ "android/util/StatsEventParcel.aidl",
+ ],
+}
+
+filegroup {
+ name: "statsd_java_aidl",
srcs: ["**/*.aidl"],
}
diff --git a/apex/statsd/aidl/android/os/IPullAtomCallback.aidl b/apex/statsd/aidl/android/os/IPullAtomCallback.aidl
index 88d3c3e46ff5..ff0b97bb5b84 100644
--- a/apex/statsd/aidl/android/os/IPullAtomCallback.aidl
+++ b/apex/statsd/aidl/android/os/IPullAtomCallback.aidl
@@ -26,6 +26,6 @@ interface IPullAtomCallback {
/**
* Initiate a request for a pull for an atom.
*/
- void onPullAtom(int atomTag, IPullAtomResultReceiver resultReceiver);
+ oneway void onPullAtom(int atomTag, IPullAtomResultReceiver resultReceiver);
}
diff --git a/apex/statsd/aidl/android/os/IStatsCompanionService.aidl b/apex/statsd/aidl/android/os/IStatsCompanionService.aidl
index 22a25374e064..5a6118ef81ca 100644
--- a/apex/statsd/aidl/android/os/IStatsCompanionService.aidl
+++ b/apex/statsd/aidl/android/os/IStatsCompanionService.aidl
@@ -90,4 +90,7 @@ interface IStatsCompanionService {
/** Tells StatsCompanionService to tell statsd to register a puller for the given atom id */
oneway void registerPullAtomCallback(int atomTag, long coolDownNs, long timeoutNs,
in int[] additiveFields, IPullAtomCallback pullerCallback);
+
+ /** Tells StatsCompanionService to tell statsd to unregister a puller for the given atom id */
+ oneway void unregisterPullAtomCallback(int atomTag);
}
diff --git a/apex/statsd/aidl/android/os/IStatsManagerService.aidl b/apex/statsd/aidl/android/os/IStatsManagerService.aidl
new file mode 100644
index 000000000000..45ba3a21ed5b
--- /dev/null
+++ b/apex/statsd/aidl/android/os/IStatsManagerService.aidl
@@ -0,0 +1,65 @@
+/**
+ * Copyright (c) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.app.PendingIntent;
+
+/**
+ * Binder interface to communicate with the Java-based statistics service helper.
+ * Contains parcelable objects available only in Java.
+ * {@hide}
+ */
+interface IStatsManagerService {
+
+ /**
+ * Registers the given pending intent for this config key. This intent is invoked when the
+ * memory consumed by the metrics for this configuration approach the pre-defined limits. There
+ * can be at most one listener per config key.
+ *
+ * Requires Manifest.permission.DUMP.
+ */
+ void setDataFetchOperation(long configKey, in PendingIntent pendingIntent,
+ in String packageName);
+
+ /**
+ * Registers the given pending intent for this packagename. This intent is invoked when the
+ * active status of any of the configs sent by this package changes and will contain a list of
+ * config ids that are currently active. It also returns the list of configs that are currently
+ * active. There can be at most one active configs changed listener per package.
+ *
+ * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS.
+ */
+ long[] setActiveConfigsChangedOperation(in PendingIntent pendingIntent, in String packageName);
+
+ /**
+ * Set the PendingIntent to be used when broadcasting subscriber
+ * information to the given subscriberId within the given config.
+ *
+ * Suppose that the calling uid has added a config with key configKey, and that in this config
+ * it is specified that when a particular anomaly is detected, a broadcast should be sent to
+ * a BroadcastSubscriber with id subscriberId. This function links the given pendingIntent with
+ * that subscriberId (for that config), so that this pendingIntent is used to send the broadcast
+ * when the anomaly is detected.
+ *
+ * This function can only be called by the owner (uid) of the config. It must be called each
+ * time statsd starts. Later calls overwrite previous calls; only one PendingIntent is stored.
+ *
+ * Requires Manifest.permission.DUMP.
+ */
+ void setBroadcastSubscriber(long configKey, long subscriberId, in PendingIntent pendingIntent,
+ in String packageName);
+} \ No newline at end of file
diff --git a/apex/statsd/aidl/android/os/IStatsd.aidl b/apex/statsd/aidl/android/os/IStatsd.aidl
index cffc6ce6e4df..cce79fae7587 100644
--- a/apex/statsd/aidl/android/os/IStatsd.aidl
+++ b/apex/statsd/aidl/android/os/IStatsd.aidl
@@ -215,6 +215,11 @@ interface IStatsd {
*/
oneway void unregisterPullerCallback(int atomTag, String packageName);
+ /**
+ * Unregisters any pullAtomCallback for the given uid/atom.
+ */
+ oneway void unregisterPullAtomCallback(int uid, int atomTag);
+
/**
* The install requires staging.
*/
diff --git a/apex/statsd/framework/Android.bp b/apex/statsd/framework/Android.bp
index 37b07a6380aa..a2b0577fe001 100644
--- a/apex/statsd/framework/Android.bp
+++ b/apex/statsd/framework/Android.bp
@@ -24,7 +24,7 @@ java_library {
name: "framework-statsd",
installable: true,
// TODO(b/146209659): Use system_current instead.
- sdk_version: "core_platform",
+ sdk_version: "core_current",
srcs: [
":framework-statsd-sources",
],
diff --git a/apex/statsd/service/java/com/android/server/stats/StatsCompanion.java b/apex/statsd/service/java/com/android/server/stats/StatsCompanion.java
new file mode 100644
index 000000000000..71b52e26b7db
--- /dev/null
+++ b/apex/statsd/service/java/com/android/server/stats/StatsCompanion.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.stats;
+
+import android.content.Context;
+import android.util.Slog;
+
+import com.android.server.SystemService;
+
+/**
+ * @hide
+ */
+public class StatsCompanion {
+ private static final String TAG = "StatsCompanion";
+ private static final boolean DEBUG = false;
+
+ /**
+ * Lifecycle class for both {@link StatsCompanionService} and {@link StatsManagerService}.
+ */
+ public static final class Lifecycle extends SystemService {
+ private StatsCompanionService mStatsCompanionService;
+ private StatsManagerService mStatsManagerService;
+
+ public Lifecycle(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void onStart() {
+ mStatsCompanionService = new StatsCompanionService(getContext());
+ mStatsManagerService = new StatsManagerService(getContext());
+ mStatsCompanionService.setStatsManagerService(mStatsManagerService);
+ mStatsManagerService.setStatsCompanionService(mStatsCompanionService);
+
+ try {
+ publishBinderService(Context.STATS_COMPANION_SERVICE,
+ mStatsCompanionService);
+ if (DEBUG) Slog.d(TAG, "Published " + Context.STATS_COMPANION_SERVICE);
+ publishBinderService(Context.STATS_MANAGER_SERVICE,
+ mStatsManagerService);
+ if (DEBUG) Slog.d(TAG, "Published " + Context.STATS_MANAGER_SERVICE);
+ } catch (Exception e) {
+ Slog.e(TAG, "Failed to publishBinderService", e);
+ }
+ }
+
+ @Override
+ public void onBootPhase(int phase) {
+ super.onBootPhase(phase);
+ if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
+ mStatsCompanionService.systemReady();
+ mStatsManagerService.systemReady();
+ }
+ }
+ }
+}
diff --git a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
index bc7716e5f6eb..7ed51caf23dd 100644
--- a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
+++ b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
@@ -112,7 +112,6 @@ import android.util.Log;
import android.util.Slog;
import android.util.StatsLog;
import android.util.proto.ProtoOutputStream;
-import android.util.proto.ProtoStream;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.procstats.IProcessStats;
@@ -137,7 +136,6 @@ import com.android.internal.os.StoragedUidIoStatsReader;
import com.android.internal.util.DumpUtils;
import com.android.server.BinderCallsStatsService;
import com.android.server.LocalServices;
-import com.android.server.SystemService;
import com.android.server.SystemServiceManager;
import com.android.server.am.MemoryStatUtil.MemoryStat;
import com.android.server.notification.NotificationManagerService;
@@ -173,6 +171,7 @@ import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
+import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@@ -278,6 +277,8 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
private final BroadcastReceiver mUserUpdateReceiver;
private final ShutdownEventReceiver mShutdownEventReceiver;
+ private StatsManagerService mStatsManagerService;
+
private static final class PullerKey {
private final int mUid;
private final int mAtomTag;
@@ -541,9 +542,9 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
private void informAllUidsLocked(Context context) throws RemoteException {
UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
PackageManager pm = context.getPackageManager();
- final List<UserInfo> users = um.getUsers(true);
+ final List<UserHandle> users = um.getUserHandles(true);
if (DEBUG) {
- Slog.d(TAG, "Iterating over " + users.size() + " profiles.");
+ Slog.d(TAG, "Iterating over " + users.size() + " userHandles.");
}
ParcelFileDescriptor[] fds;
@@ -570,11 +571,11 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
ProtoOutputStream output = new ProtoOutputStream(fout);
int numRecords = 0;
// Add in all the apps for every user/profile.
- for (UserInfo profile : users) {
+ for (UserHandle userHandle : users) {
List<PackageInfo> pi =
pm.getInstalledPackagesAsUser(PackageManager.MATCH_UNINSTALLED_PACKAGES
| PackageManager.MATCH_ANY_USER,
- profile.id);
+ userHandle.getIdentifier());
for (int j = 0; j < pi.size(); j++) {
if (pi.get(j).applicationInfo != null) {
String installer;
@@ -584,23 +585,24 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
installer = "";
}
long applicationInfoToken =
- output.start(ProtoStream.FIELD_TYPE_MESSAGE
- | ProtoStream.FIELD_COUNT_REPEATED
+ output.start(ProtoOutputStream.FIELD_TYPE_MESSAGE
+ | ProtoOutputStream.FIELD_COUNT_REPEATED
| APPLICATION_INFO_FIELD_ID);
- output.write(ProtoStream.FIELD_TYPE_INT32
- | ProtoStream.FIELD_COUNT_SINGLE | UID_FIELD_ID,
+ output.write(ProtoOutputStream.FIELD_TYPE_INT32
+ | ProtoOutputStream.FIELD_COUNT_SINGLE | UID_FIELD_ID,
pi.get(j).applicationInfo.uid);
- output.write(ProtoStream.FIELD_TYPE_INT64
- | ProtoStream.FIELD_COUNT_SINGLE
+ output.write(ProtoOutputStream.FIELD_TYPE_INT64
+ | ProtoOutputStream.FIELD_COUNT_SINGLE
| VERSION_FIELD_ID, pi.get(j).getLongVersionCode());
- output.write(ProtoStream.FIELD_TYPE_STRING
- | ProtoStream.FIELD_COUNT_SINGLE | VERSION_STRING_FIELD_ID,
+ output.write(ProtoOutputStream.FIELD_TYPE_STRING
+ | ProtoOutputStream.FIELD_COUNT_SINGLE
+ | VERSION_STRING_FIELD_ID,
pi.get(j).versionName);
- output.write(ProtoStream.FIELD_TYPE_STRING
- | ProtoStream.FIELD_COUNT_SINGLE
+ output.write(ProtoOutputStream.FIELD_TYPE_STRING
+ | ProtoOutputStream.FIELD_COUNT_SINGLE
| PACKAGE_NAME_FIELD_ID, pi.get(j).packageName);
- output.write(ProtoStream.FIELD_TYPE_STRING
- | ProtoStream.FIELD_COUNT_SINGLE
+ output.write(ProtoOutputStream.FIELD_TYPE_STRING
+ | ProtoOutputStream.FIELD_COUNT_SINGLE
| INSTALLER_FIELD_ID,
installer == null ? "" : installer);
numRecords++;
@@ -2135,8 +2137,8 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
pulledData.add(e);
}
- private void pullDangerousPermissionState(long elapsedNanos, final long wallClockNanos,
- List<StatsLogEventWrapper> pulledData) {
+ private void pullDangerousPermissionState(int atomId, long elapsedNanos,
+ final long wallClockNanos, List<StatsLogEventWrapper> pulledData) {
long token = Binder.clearCallingIdentity();
Set<Integer> reportedUids = new HashSet<>();
try {
@@ -2165,6 +2167,11 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
}
reportedUids.add(pkg.applicationInfo.uid);
+ if (atomId == StatsLog.DANGEROUS_PERMISSION_STATE_SAMPLED
+ && ThreadLocalRandom.current().nextFloat() > 0.2f) {
+ continue;
+ }
+
int numPerms = pkg.requestedPermissions.length;
for (int permNum = 0; permNum < numPerms; permNum++) {
String permName = pkg.requestedPermissions[permNum];
@@ -2174,7 +2181,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
try {
permissionInfo = pm.getPermissionInfo(permName, 0);
permissionFlags =
- pm.getPermissionFlags(permName, pkg.packageName, user);
+ pm.getPermissionFlags(permName, pkg.packageName, user);
} catch (PackageManager.NameNotFoundException ignored) {
continue;
@@ -2185,11 +2192,13 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
}
StatsLogEventWrapper e = new StatsLogEventWrapper(
- StatsLog.DANGEROUS_PERMISSION_STATE, elapsedNanos, wallClockNanos);
+ atomId, elapsedNanos, wallClockNanos);
e.writeString(permName);
e.writeInt(pkg.applicationInfo.uid);
- e.writeString(null);
+ if (atomId == StatsLog.DANGEROUS_PERMISSION_STATE) {
+ e.writeString(null);
+ }
e.writeBoolean((pkg.requestedPermissionsFlags[permNum]
& REQUESTED_PERMISSION_GRANTED) != 0);
e.writeInt(permissionFlags);
@@ -2639,7 +2648,13 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
break;
}
case StatsLog.DANGEROUS_PERMISSION_STATE: {
- pullDangerousPermissionState(elapsedNanos, wallClockNanos, ret);
+ pullDangerousPermissionState(StatsLog.DANGEROUS_PERMISSION_STATE, elapsedNanos,
+ wallClockNanos, ret);
+ break;
+ }
+ case StatsLog.DANGEROUS_PERMISSION_STATE_SAMPLED: {
+ pullDangerousPermissionState(StatsLog.DANGEROUS_PERMISSION_STATE_SAMPLED,
+ elapsedNanos, wallClockNanos, ret);
break;
}
case StatsLog.TIME_ZONE_DATA_INFO: {
@@ -2681,6 +2696,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
Slog.d(TAG, "learned that statsdReady");
}
sayHiToStatsd(); // tell statsd that we're ready too and link to it
+ mStatsManagerService.systemReady();
mContext.sendBroadcastAsUser(new Intent(StatsManager.ACTION_STATSD_STARTED)
.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND),
UserHandle.SYSTEM, android.Manifest.permission.DUMP);
@@ -2736,7 +2752,31 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
}
}
- // Lifecycle and related code
+ @Override
+ public void unregisterPullAtomCallback(int atomTag) {
+ synchronized (sStatsdLock) {
+ // Always remove the puller in SCS.
+ // If statsd is down, we will not register it when it comes back up.
+ int callingUid = Binder.getCallingUid();
+ final long token = Binder.clearCallingIdentity();
+ PullerKey key = new PullerKey(callingUid, atomTag);
+ mPullers.remove(key);
+
+ if (sStatsd == null) {
+ Slog.w(TAG, "Could not access statsd for registering puller for atom " + atomTag);
+ return;
+ }
+ try {
+ sStatsd.unregisterPullAtomCallback(callingUid, atomTag);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to access statsd to register puller for atom " + atomTag);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ }
+
+ // Statsd related code
/**
* Fetches the statsd IBinder service.
@@ -2747,42 +2787,18 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
return IStatsd.Stub.asInterface(ServiceManager.getService("stats"));
}
- public static final class Lifecycle extends SystemService {
- private StatsCompanionService mStatsCompanionService;
-
- public Lifecycle(Context context) {
- super(context);
- }
-
- @Override
- public void onStart() {
- mStatsCompanionService = new StatsCompanionService(getContext());
- try {
- publishBinderService(Context.STATS_COMPANION_SERVICE,
- mStatsCompanionService);
- if (DEBUG) Slog.d(TAG, "Published " + Context.STATS_COMPANION_SERVICE);
- } catch (Exception e) {
- Slog.e(TAG, "Failed to publishBinderService", e);
- }
- }
-
- @Override
- public void onBootPhase(int phase) {
- super.onBootPhase(phase);
- if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
- mStatsCompanionService.systemReady();
- }
- }
- }
-
/**
* Now that the android system is ready, StatsCompanion is ready too, so inform statsd.
*/
- private void systemReady() {
+ void systemReady() {
if (DEBUG) Slog.d(TAG, "Learned that systemReady");
sayHiToStatsd();
}
+ void setStatsManagerService(StatsManagerService statsManagerService) {
+ mStatsManagerService = statsManagerService;
+ }
+
/**
* Tells statsd that statscompanion is ready. If the binder call returns, link to
* statsd.
diff --git a/apex/statsd/service/java/com/android/server/stats/StatsManagerService.java b/apex/statsd/service/java/com/android/server/stats/StatsManagerService.java
new file mode 100644
index 000000000000..24b7978506d0
--- /dev/null
+++ b/apex/statsd/service/java/com/android/server/stats/StatsManagerService.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.stats;
+
+import android.app.PendingIntent;
+import android.content.Context;
+import android.os.IBinder;
+import android.os.IStatsManagerService;
+import android.os.IStatsd;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Slog;
+
+import com.android.internal.annotations.GuardedBy;
+
+/**
+ * @hide
+ */
+public class StatsManagerService extends IStatsManagerService.Stub {
+
+ private static final String TAG = "StatsManagerService";
+ private static final boolean DEBUG = false;
+
+ @GuardedBy("sStatsdLock")
+ private static IStatsd sStatsd;
+ private static final Object sStatsdLock = new Object();
+
+ private StatsCompanionService mStatsCompanionService;
+
+ public StatsManagerService(Context context) {
+ super();
+ }
+
+ @Override
+ public void setDataFetchOperation(long configKey, PendingIntent pendingIntent,
+ String packageName) {
+ // no-op
+ if (DEBUG) {
+ Slog.d(TAG, "setDataFetchOperation");
+ }
+ }
+
+ @Override
+ public long[] setActiveConfigsChangedOperation(PendingIntent pendingIntent,
+ String packageName) {
+ // no-op
+ if (DEBUG) {
+ Slog.d(TAG, "setActiveConfigsChangedOperation");
+ }
+ return new long[]{};
+ }
+
+ @Override
+ public void setBroadcastSubscriber(long configKey, long subscriberId,
+ PendingIntent pendingIntent, String packageName) {
+ //no-op
+ if (DEBUG) {
+ Slog.d(TAG, "setBroadcastSubscriber");
+ }
+ }
+
+ void setStatsCompanionService(StatsCompanionService statsCompanionService) {
+ mStatsCompanionService = statsCompanionService;
+ }
+
+ void systemReady() {
+ if (DEBUG) {
+ Slog.d(TAG, "statsdReady");
+ }
+ setupStatsManagerService();
+ }
+
+ private void setupStatsManagerService() {
+ synchronized (sStatsdLock) {
+ if (sStatsd != null) {
+ if (DEBUG) {
+ Slog.e(TAG, "Trying to fetch statsd, but it was already fetched",
+ new IllegalStateException(
+ "sStatsd is not null when being fetched"));
+ }
+ return;
+ }
+ sStatsd = IStatsd.Stub.asInterface(ServiceManager.getService("stats"));
+ if (sStatsd == null) {
+ if (DEBUG) {
+ Slog.d(TAG, "Failed to get stats service.");
+ }
+ return;
+ }
+ // Assume statsd is ready since this is called form statscompanion, link to statsd.
+ try {
+ sStatsd.asBinder().linkToDeath((IBinder.DeathRecipient) () -> {
+ sStatsd = null;
+ }, 0);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "linkToDeath(StatsdDeathRecipient) failed", e);
+ }
+ }
+ }
+}
diff --git a/api/current.txt b/api/current.txt
index 52dd1a16cc93..c734db5196a9 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -99,6 +99,7 @@ package android {
field public static final String MOUNT_FORMAT_FILESYSTEMS = "android.permission.MOUNT_FORMAT_FILESYSTEMS";
field public static final String MOUNT_UNMOUNT_FILESYSTEMS = "android.permission.MOUNT_UNMOUNT_FILESYSTEMS";
field public static final String NFC = "android.permission.NFC";
+ field public static final String NFC_PREFERRED_PAYMENT_INFO = "android.permission.NFC_PREFERRED_PAYMENT_INFO";
field public static final String NFC_TRANSACTION_EVENT = "android.permission.NFC_TRANSACTION_EVENT";
field public static final String PACKAGE_USAGE_STATS = "android.permission.PACKAGE_USAGE_STATS";
field @Deprecated public static final String PERSISTENT_ACTIVITY = "android.permission.PERSISTENT_ACTIVITY";
@@ -1061,6 +1062,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 preferMinimalPostProcessing = 16844300; // 0x101060c
field public static final int preferenceCategoryStyle = 16842892; // 0x101008c
field public static final int preferenceFragmentStyle = 16844038; // 0x1010506
field public static final int preferenceInformationStyle = 16842893; // 0x101008d
@@ -3811,6 +3813,7 @@ package android.app {
method public void onPerformDirectAction(@NonNull String, @NonNull android.os.Bundle, @NonNull android.os.CancellationSignal, @NonNull java.util.function.Consumer<android.os.Bundle>);
method public void onPictureInPictureModeChanged(boolean, android.content.res.Configuration);
method @Deprecated public void onPictureInPictureModeChanged(boolean);
+ method public void onPictureInPictureRequested();
method @CallSuper protected void onPostCreate(@Nullable android.os.Bundle);
method public void onPostCreate(@Nullable android.os.Bundle, @Nullable android.os.PersistableBundle);
method @CallSuper protected void onPostResume();
@@ -3954,6 +3957,7 @@ package android.app {
public class ActivityManager {
method public int addAppTask(@NonNull android.app.Activity, @NonNull android.content.Intent, @Nullable android.app.ActivityManager.TaskDescription, @NonNull android.graphics.Bitmap);
+ method public void appNotResponding(@NonNull String);
method public boolean clearApplicationUserData();
method public void clearWatchHeapLimit();
method @RequiresPermission(android.Manifest.permission.DUMP) public void dumpPackageState(java.io.FileDescriptor, String);
@@ -4308,7 +4312,7 @@ package android.app {
method public static String permissionToOp(String);
method public void setNotedAppOpsCollector(@Nullable android.app.AppOpsManager.AppOpsCollector);
method @Deprecated public int startOp(@NonNull String, int, @NonNull String);
- method public int startOp(@NonNull String, int, @Nullable String, @NonNull String, @Nullable String);
+ method public int startOp(@NonNull String, int, @Nullable String, @Nullable String, @Nullable String);
method @Deprecated public int startOpNoThrow(@NonNull String, int, @NonNull String);
method public int startOpNoThrow(@NonNull String, int, @NonNull String, @NonNull String, @Nullable String);
method public void startWatchingActive(@NonNull String[], @NonNull java.util.concurrent.Executor, @NonNull android.app.AppOpsManager.OnOpActiveChangedListener);
@@ -5100,6 +5104,7 @@ package android.app {
method public void callActivityOnDestroy(android.app.Activity);
method public void callActivityOnNewIntent(android.app.Activity, android.content.Intent);
method public void callActivityOnPause(android.app.Activity);
+ method public void callActivityOnPictureInPictureRequested(@NonNull android.app.Activity);
method public void callActivityOnPostCreate(@NonNull android.app.Activity, @Nullable android.os.Bundle);
method public void callActivityOnPostCreate(@NonNull android.app.Activity, @Nullable android.os.Bundle, @Nullable android.os.PersistableBundle);
method public void callActivityOnRestart(android.app.Activity);
@@ -9971,6 +9976,7 @@ package android.content {
field public static final String DOWNLOAD_SERVICE = "download";
field public static final String DROPBOX_SERVICE = "dropbox";
field public static final String EUICC_SERVICE = "euicc";
+ field public static final String FILE_INTEGRITY_SERVICE = "file_integrity";
field public static final String FINGERPRINT_SERVICE = "fingerprint";
field public static final String HARDWARE_PROPERTIES_SERVICE = "hardware_properties";
field public static final String INPUT_METHOD_SERVICE = "input_method";
@@ -11187,6 +11193,7 @@ package android.content.pm {
field public String parentActivityName;
field public String permission;
field public int persistableMode;
+ field public boolean preferMinimalPostProcessing;
field public int screenOrientation;
field public int softInputMode;
field public String targetActivity;
@@ -16934,7 +16941,7 @@ package android.hardware.camera2 {
field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<android.util.Rational> CONTROL_AE_COMPENSATION_STEP;
field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Boolean> CONTROL_AE_LOCK_AVAILABLE;
field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> CONTROL_AF_AVAILABLE_MODES;
- field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<android.hardware.camera2.params.CapabilityAndMaxSize[]> CONTROL_AVAILABLE_BOKEH_CAPABILITIES;
+ field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<android.hardware.camera2.params.Capability[]> CONTROL_AVAILABLE_BOKEH_CAPABILITIES;
field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> CONTROL_AVAILABLE_EFFECTS;
field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> CONTROL_AVAILABLE_MODES;
field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> CONTROL_AVAILABLE_SCENE_MODES;
@@ -16945,6 +16952,7 @@ package android.hardware.camera2 {
field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> CONTROL_MAX_REGIONS_AF;
field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> CONTROL_MAX_REGIONS_AWB;
field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<android.util.Range<java.lang.Integer>> CONTROL_POST_RAW_SENSITIVITY_BOOST_RANGE;
+ field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<android.util.Range<java.lang.Float>> CONTROL_ZOOM_RATIO_RANGE;
field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Boolean> DEPTH_DEPTH_IS_EXCLUSIVE;
field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> DISTORTION_CORRECTION_AVAILABLE_MODES;
field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> EDGE_AVAILABLE_EDGE_MODES;
@@ -17357,6 +17365,7 @@ package android.hardware.camera2 {
field @NonNull public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> CONTROL_POST_RAW_SENSITIVITY_BOOST;
field @NonNull public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> CONTROL_SCENE_MODE;
field @NonNull public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> CONTROL_VIDEO_STABILIZATION_MODE;
+ field @NonNull public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Float> CONTROL_ZOOM_RATIO;
field @NonNull public static final android.os.Parcelable.Creator<android.hardware.camera2.CaptureRequest> CREATOR;
field @NonNull public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> DISTORTION_CORRECTION_MODE;
field @NonNull public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> EDGE_MODE;
@@ -17443,6 +17452,7 @@ package android.hardware.camera2 {
field @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> CONTROL_POST_RAW_SENSITIVITY_BOOST;
field @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> CONTROL_SCENE_MODE;
field @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> CONTROL_VIDEO_STABILIZATION_MODE;
+ field @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Float> CONTROL_ZOOM_RATIO;
field @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> DISTORTION_CORRECTION_MODE;
field @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> EDGE_MODE;
field @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> FLASH_MODE;
@@ -17532,9 +17542,10 @@ package android.hardware.camera2.params {
field public static final int COUNT = 4; // 0x4
}
- public final class CapabilityAndMaxSize {
+ public final class Capability {
method @NonNull public android.util.Size getMaxStreamingSize();
method public int getMode();
+ method @NonNull public android.util.Range<java.lang.Float> getZoomRatioRange();
}
public final class ColorSpaceTransform {
@@ -19613,6 +19624,197 @@ package android.icu.math {
}
+package android.icu.number {
+
+ public class CompactNotation extends android.icu.number.Notation {
+ }
+
+ public abstract class CurrencyPrecision extends android.icu.number.Precision {
+ method public android.icu.number.Precision withCurrency(android.icu.util.Currency);
+ }
+
+ public class FormattedNumber implements java.lang.CharSequence {
+ method public char charAt(int);
+ method public int length();
+ method public CharSequence subSequence(int, int);
+ method public java.math.BigDecimal toBigDecimal();
+ method public java.text.AttributedCharacterIterator toCharacterIterator();
+ }
+
+ public class FormattedNumberRange implements java.lang.CharSequence {
+ method public char charAt(int);
+ method public java.math.BigDecimal getFirstBigDecimal();
+ method public android.icu.number.NumberRangeFormatter.RangeIdentityResult getIdentityResult();
+ method public java.math.BigDecimal getSecondBigDecimal();
+ method public int length();
+ method public CharSequence subSequence(int, int);
+ method public java.text.AttributedCharacterIterator toCharacterIterator();
+ }
+
+ public abstract class FractionPrecision extends android.icu.number.Precision {
+ method public android.icu.number.Precision withMaxDigits(int);
+ method public android.icu.number.Precision withMinDigits(int);
+ }
+
+ public class IntegerWidth {
+ method public android.icu.number.IntegerWidth truncateAt(int);
+ method public static android.icu.number.IntegerWidth zeroFillTo(int);
+ }
+
+ public class LocalizedNumberFormatter extends android.icu.number.NumberFormatterSettings<android.icu.number.LocalizedNumberFormatter> {
+ method public android.icu.number.FormattedNumber format(long);
+ method public android.icu.number.FormattedNumber format(double);
+ method public android.icu.number.FormattedNumber format(Number);
+ method public android.icu.number.FormattedNumber format(android.icu.util.Measure);
+ method public java.text.Format toFormat();
+ }
+
+ public class LocalizedNumberRangeFormatter extends android.icu.number.NumberRangeFormatterSettings<android.icu.number.LocalizedNumberRangeFormatter> {
+ method public android.icu.number.FormattedNumberRange formatRange(int, int);
+ method public android.icu.number.FormattedNumberRange formatRange(double, double);
+ method public android.icu.number.FormattedNumberRange formatRange(Number, Number);
+ }
+
+ public class Notation {
+ method public static android.icu.number.CompactNotation compactLong();
+ method public static android.icu.number.CompactNotation compactShort();
+ method public static android.icu.number.ScientificNotation engineering();
+ method public static android.icu.number.ScientificNotation scientific();
+ method public static android.icu.number.SimpleNotation simple();
+ }
+
+ public final class NumberFormatter {
+ method public static android.icu.number.UnlocalizedNumberFormatter with();
+ method public static android.icu.number.LocalizedNumberFormatter withLocale(java.util.Locale);
+ method public static android.icu.number.LocalizedNumberFormatter withLocale(android.icu.util.ULocale);
+ }
+
+ public enum NumberFormatter.DecimalSeparatorDisplay {
+ enum_constant public static final android.icu.number.NumberFormatter.DecimalSeparatorDisplay ALWAYS;
+ enum_constant public static final android.icu.number.NumberFormatter.DecimalSeparatorDisplay AUTO;
+ }
+
+ public enum NumberFormatter.GroupingStrategy {
+ enum_constant public static final android.icu.number.NumberFormatter.GroupingStrategy AUTO;
+ enum_constant public static final android.icu.number.NumberFormatter.GroupingStrategy MIN2;
+ enum_constant public static final android.icu.number.NumberFormatter.GroupingStrategy OFF;
+ enum_constant public static final android.icu.number.NumberFormatter.GroupingStrategy ON_ALIGNED;
+ enum_constant public static final android.icu.number.NumberFormatter.GroupingStrategy THOUSANDS;
+ }
+
+ public enum NumberFormatter.SignDisplay {
+ enum_constant public static final android.icu.number.NumberFormatter.SignDisplay ACCOUNTING;
+ enum_constant public static final android.icu.number.NumberFormatter.SignDisplay ACCOUNTING_ALWAYS;
+ enum_constant public static final android.icu.number.NumberFormatter.SignDisplay ACCOUNTING_EXCEPT_ZERO;
+ enum_constant public static final android.icu.number.NumberFormatter.SignDisplay ALWAYS;
+ enum_constant public static final android.icu.number.NumberFormatter.SignDisplay AUTO;
+ enum_constant public static final android.icu.number.NumberFormatter.SignDisplay EXCEPT_ZERO;
+ enum_constant public static final android.icu.number.NumberFormatter.SignDisplay NEVER;
+ }
+
+ public enum NumberFormatter.UnitWidth {
+ enum_constant public static final android.icu.number.NumberFormatter.UnitWidth FULL_NAME;
+ enum_constant public static final android.icu.number.NumberFormatter.UnitWidth HIDDEN;
+ enum_constant public static final android.icu.number.NumberFormatter.UnitWidth ISO_CODE;
+ enum_constant public static final android.icu.number.NumberFormatter.UnitWidth NARROW;
+ enum_constant public static final android.icu.number.NumberFormatter.UnitWidth SHORT;
+ }
+
+ public abstract class NumberFormatterSettings<T extends android.icu.number.NumberFormatterSettings<?>> {
+ method public T decimal(android.icu.number.NumberFormatter.DecimalSeparatorDisplay);
+ method public T grouping(android.icu.number.NumberFormatter.GroupingStrategy);
+ method public T integerWidth(android.icu.number.IntegerWidth);
+ method public T notation(android.icu.number.Notation);
+ method public T perUnit(android.icu.util.MeasureUnit);
+ method public T precision(android.icu.number.Precision);
+ method public T roundingMode(java.math.RoundingMode);
+ method public T scale(android.icu.number.Scale);
+ method public T sign(android.icu.number.NumberFormatter.SignDisplay);
+ method public T symbols(android.icu.text.DecimalFormatSymbols);
+ method public T symbols(android.icu.text.NumberingSystem);
+ method public T unit(android.icu.util.MeasureUnit);
+ method public T unitWidth(android.icu.number.NumberFormatter.UnitWidth);
+ }
+
+ public abstract class NumberRangeFormatter {
+ method public static android.icu.number.UnlocalizedNumberRangeFormatter with();
+ method public static android.icu.number.LocalizedNumberRangeFormatter withLocale(java.util.Locale);
+ method public static android.icu.number.LocalizedNumberRangeFormatter withLocale(android.icu.util.ULocale);
+ }
+
+ public enum NumberRangeFormatter.RangeCollapse {
+ enum_constant public static final android.icu.number.NumberRangeFormatter.RangeCollapse ALL;
+ enum_constant public static final android.icu.number.NumberRangeFormatter.RangeCollapse AUTO;
+ enum_constant public static final android.icu.number.NumberRangeFormatter.RangeCollapse NONE;
+ enum_constant public static final android.icu.number.NumberRangeFormatter.RangeCollapse UNIT;
+ }
+
+ public enum NumberRangeFormatter.RangeIdentityFallback {
+ enum_constant public static final android.icu.number.NumberRangeFormatter.RangeIdentityFallback APPROXIMATELY;
+ enum_constant public static final android.icu.number.NumberRangeFormatter.RangeIdentityFallback APPROXIMATELY_OR_SINGLE_VALUE;
+ enum_constant public static final android.icu.number.NumberRangeFormatter.RangeIdentityFallback RANGE;
+ enum_constant public static final android.icu.number.NumberRangeFormatter.RangeIdentityFallback SINGLE_VALUE;
+ }
+
+ public enum NumberRangeFormatter.RangeIdentityResult {
+ enum_constant public static final android.icu.number.NumberRangeFormatter.RangeIdentityResult EQUAL_AFTER_ROUNDING;
+ enum_constant public static final android.icu.number.NumberRangeFormatter.RangeIdentityResult EQUAL_BEFORE_ROUNDING;
+ enum_constant public static final android.icu.number.NumberRangeFormatter.RangeIdentityResult NOT_EQUAL;
+ }
+
+ public abstract class NumberRangeFormatterSettings<T extends android.icu.number.NumberRangeFormatterSettings<?>> {
+ method public T collapse(android.icu.number.NumberRangeFormatter.RangeCollapse);
+ method public T identityFallback(android.icu.number.NumberRangeFormatter.RangeIdentityFallback);
+ method public T numberFormatterBoth(android.icu.number.UnlocalizedNumberFormatter);
+ method public T numberFormatterFirst(android.icu.number.UnlocalizedNumberFormatter);
+ method public T numberFormatterSecond(android.icu.number.UnlocalizedNumberFormatter);
+ }
+
+ public abstract class Precision implements java.lang.Cloneable {
+ method public Object clone();
+ method public static android.icu.number.CurrencyPrecision currency(android.icu.util.Currency.CurrencyUsage);
+ method public static android.icu.number.FractionPrecision fixedFraction(int);
+ method public static android.icu.number.Precision fixedSignificantDigits(int);
+ method public static android.icu.number.Precision increment(java.math.BigDecimal);
+ method public static android.icu.number.FractionPrecision integer();
+ method public static android.icu.number.FractionPrecision maxFraction(int);
+ method public static android.icu.number.Precision maxSignificantDigits(int);
+ method public static android.icu.number.FractionPrecision minFraction(int);
+ method public static android.icu.number.FractionPrecision minMaxFraction(int, int);
+ method public static android.icu.number.Precision minMaxSignificantDigits(int, int);
+ method public static android.icu.number.Precision minSignificantDigits(int);
+ method public static android.icu.number.Precision unlimited();
+ }
+
+ public class Scale {
+ method public static android.icu.number.Scale byBigDecimal(java.math.BigDecimal);
+ method public static android.icu.number.Scale byDouble(double);
+ method public static android.icu.number.Scale byDoubleAndPowerOfTen(double, int);
+ method public static android.icu.number.Scale none();
+ method public static android.icu.number.Scale powerOfTen(int);
+ }
+
+ public class ScientificNotation extends android.icu.number.Notation implements java.lang.Cloneable {
+ method public Object clone();
+ method public android.icu.number.ScientificNotation withExponentSignDisplay(android.icu.number.NumberFormatter.SignDisplay);
+ method public android.icu.number.ScientificNotation withMinExponentDigits(int);
+ }
+
+ public class SimpleNotation extends android.icu.number.Notation {
+ }
+
+ public class UnlocalizedNumberFormatter extends android.icu.number.NumberFormatterSettings<android.icu.number.UnlocalizedNumberFormatter> {
+ method public android.icu.number.LocalizedNumberFormatter locale(java.util.Locale);
+ method public android.icu.number.LocalizedNumberFormatter locale(android.icu.util.ULocale);
+ }
+
+ public class UnlocalizedNumberRangeFormatter extends android.icu.number.NumberRangeFormatterSettings<android.icu.number.UnlocalizedNumberRangeFormatter> {
+ method public android.icu.number.LocalizedNumberRangeFormatter locale(java.util.Locale);
+ method public android.icu.number.LocalizedNumberRangeFormatter locale(android.icu.util.ULocale);
+ }
+
+}
+
package android.icu.text {
public final class AlphabeticIndex<V> implements java.lang.Iterable<android.icu.text.AlphabeticIndex.Bucket<V>> {
@@ -22127,6 +22329,7 @@ package android.icu.util {
field public static final android.icu.util.MeasureUnit ARC_MINUTE;
field public static final android.icu.util.MeasureUnit ARC_SECOND;
field public static final android.icu.util.MeasureUnit ASTRONOMICAL_UNIT;
+ field public static final android.icu.util.MeasureUnit ATMOSPHERE;
field public static final android.icu.util.MeasureUnit BIT;
field public static final android.icu.util.MeasureUnit BUSHEL;
field public static final android.icu.util.MeasureUnit BYTE;
@@ -22228,6 +22431,9 @@ package android.icu.util {
field public static final android.icu.util.MeasureUnit OUNCE_TROY;
field public static final android.icu.util.MeasureUnit PARSEC;
field public static final android.icu.util.MeasureUnit PART_PER_MILLION;
+ field public static final android.icu.util.MeasureUnit PERCENT;
+ field public static final android.icu.util.MeasureUnit PERMILLE;
+ field public static final android.icu.util.MeasureUnit PETABYTE;
field public static final android.icu.util.MeasureUnit PICOMETER;
field public static final android.icu.util.MeasureUnit PINT;
field public static final android.icu.util.MeasureUnit PINT_METRIC;
@@ -23236,10 +23442,10 @@ package android.location {
}
public interface LocationListener {
- method public void onLocationChanged(android.location.Location);
- method public void onProviderDisabled(String);
- method public void onProviderEnabled(String);
- method @Deprecated public void onStatusChanged(String, int, android.os.Bundle);
+ method public void onLocationChanged(@NonNull android.location.Location);
+ method public default void onProviderDisabled(@NonNull String);
+ method public default void onProviderEnabled(@NonNull String);
+ method @Deprecated public default void onStatusChanged(String, int, android.os.Bundle);
}
public class LocationManager {
@@ -23542,6 +23748,7 @@ package android.media {
field public static final int ENCODING_IEC61937 = 13; // 0xd
field public static final int ENCODING_INVALID = 0; // 0x0
field public static final int ENCODING_MP3 = 9; // 0x9
+ field public static final int ENCODING_OPUS = 20; // 0x14
field public static final int ENCODING_PCM_16BIT = 2; // 0x2
field public static final int ENCODING_PCM_8BIT = 3; // 0x3
field public static final int ENCODING_PCM_FLOAT = 4; // 0x4
@@ -23596,9 +23803,9 @@ package android.media {
method public void loadSoundEffects();
method public void playSoundEffect(int);
method public void playSoundEffect(int, float);
- method public void registerAudioDeviceCallback(android.media.AudioDeviceCallback, android.os.Handler);
- method public void registerAudioPlaybackCallback(@NonNull android.media.AudioManager.AudioPlaybackCallback, android.os.Handler);
- method public void registerAudioRecordingCallback(@NonNull android.media.AudioManager.AudioRecordingCallback, android.os.Handler);
+ method public void registerAudioDeviceCallback(android.media.AudioDeviceCallback, @Nullable android.os.Handler);
+ method public void registerAudioPlaybackCallback(@NonNull android.media.AudioManager.AudioPlaybackCallback, @Nullable android.os.Handler);
+ method public void registerAudioRecordingCallback(@NonNull android.media.AudioManager.AudioRecordingCallback, @Nullable android.os.Handler);
method @Deprecated public void registerMediaButtonEventReceiver(android.content.ComponentName);
method @Deprecated public void registerMediaButtonEventReceiver(android.app.PendingIntent);
method @Deprecated public void registerRemoteControlClient(android.media.RemoteControlClient);
@@ -27639,6 +27846,7 @@ package android.media.session {
method @Nullable public android.app.PendingIntent getSessionActivity();
method @NonNull public android.os.Bundle getSessionInfo();
method @NonNull public android.media.session.MediaSession.Token getSessionToken();
+ method @NonNull public String getTag();
method @NonNull public android.media.session.MediaController.TransportControls getTransportControls();
method public void registerCallback(@NonNull android.media.session.MediaController.Callback);
method public void registerCallback(@NonNull android.media.session.MediaController.Callback, @Nullable android.os.Handler);
@@ -29150,14 +29358,25 @@ package android.net {
}
public final class NetworkCapabilities implements android.os.Parcelable {
+ ctor public NetworkCapabilities();
ctor public NetworkCapabilities(android.net.NetworkCapabilities);
+ method @NonNull public android.net.NetworkCapabilities addCapability(int);
+ method @NonNull public android.net.NetworkCapabilities addTransportType(int);
+ method public void clearAll();
method public int describeContents();
method public int getLinkDownstreamBandwidthKbps();
method public int getLinkUpstreamBandwidthKbps();
+ method @Nullable public android.net.NetworkSpecifier getNetworkSpecifier();
method public int getSignalStrength();
method @Nullable public android.net.TransportInfo getTransportInfo();
method public boolean hasCapability(int);
method public boolean hasTransport(int);
+ method @NonNull public android.net.NetworkCapabilities removeCapability(int);
+ method @NonNull public android.net.NetworkCapabilities setCapability(int, boolean);
+ method @NonNull public android.net.NetworkCapabilities setLinkDownstreamBandwidthKbps(int);
+ method @NonNull public android.net.NetworkCapabilities setLinkUpstreamBandwidthKbps(int);
+ method @NonNull public android.net.NetworkCapabilities setNetworkSpecifier(@NonNull android.net.NetworkSpecifier);
+ method @NonNull public android.net.NetworkCapabilities setSignalStrength(int);
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkCapabilities> CREATOR;
field public static final int NET_CAPABILITY_CAPTIVE_PORTAL = 17; // 0x11
@@ -29950,6 +30169,21 @@ package android.net.ssl {
package android.net.wifi {
+ public abstract class EasyConnectStatusCallback {
+ field public static final int EASY_CONNECT_EVENT_FAILURE_AUTHENTICATION = -2; // 0xfffffffe
+ field public static final int EASY_CONNECT_EVENT_FAILURE_BUSY = -5; // 0xfffffffb
+ field public static final int EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK = -10; // 0xfffffff6
+ field public static final int EASY_CONNECT_EVENT_FAILURE_CONFIGURATION = -4; // 0xfffffffc
+ field public static final int EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION = -11; // 0xfffffff5
+ field public static final int EASY_CONNECT_EVENT_FAILURE_ENROLLEE_REJECTED_CONFIGURATION = -12; // 0xfffffff4
+ field public static final int EASY_CONNECT_EVENT_FAILURE_GENERIC = -7; // 0xfffffff9
+ field public static final int EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK = -9; // 0xfffffff7
+ field public static final int EASY_CONNECT_EVENT_FAILURE_INVALID_URI = -1; // 0xffffffff
+ field public static final int EASY_CONNECT_EVENT_FAILURE_NOT_COMPATIBLE = -3; // 0xfffffffd
+ field public static final int EASY_CONNECT_EVENT_FAILURE_NOT_SUPPORTED = -8; // 0xfffffff8
+ field public static final int EASY_CONNECT_EVENT_FAILURE_TIMEOUT = -6; // 0xfffffffa
+ }
+
public class ScanResult implements android.os.Parcelable {
method public int describeContents();
method public int getWifiStandard();
@@ -30041,6 +30275,7 @@ package android.net.wifi {
@Deprecated public static class WifiConfiguration.GroupCipher {
field @Deprecated public static final int CCMP = 3; // 0x3
field @Deprecated public static final int GCMP_256 = 5; // 0x5
+ field @Deprecated public static final int SMS4 = 6; // 0x6
field @Deprecated public static final int TKIP = 2; // 0x2
field @Deprecated public static final int WEP104 = 1; // 0x1
field @Deprecated public static final int WEP40 = 0; // 0x0
@@ -30070,6 +30305,7 @@ package android.net.wifi {
field @Deprecated public static final int CCMP = 2; // 0x2
field @Deprecated public static final int GCMP_256 = 3; // 0x3
field @Deprecated public static final int NONE = 0; // 0x0
+ field @Deprecated public static final int SMS4 = 4; // 0x4
field @Deprecated public static final int TKIP = 1; // 0x1
field @Deprecated public static final String[] strings;
field @Deprecated public static final String varName = "pairwise";
@@ -30077,6 +30313,7 @@ package android.net.wifi {
@Deprecated public static class WifiConfiguration.Protocol {
field @Deprecated public static final int RSN = 1; // 0x1
+ field @Deprecated public static final int WAPI = 3; // 0x3
field @Deprecated public static final int WPA = 0; // 0x0
field @Deprecated public static final String[] strings;
field @Deprecated public static final String varName = "proto";
@@ -30123,6 +30360,12 @@ package android.net.wifi {
method @Deprecated public void setSubjectMatch(String);
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.WifiEnterpriseConfig> CREATOR;
+ field public static final String EXTRA_WAPI_AS_CERTIFICATE_DATA = "android.net.wifi.extra.WAPI_AS_CERTIFICATE_DATA";
+ field public static final String EXTRA_WAPI_AS_CERTIFICATE_NAME = "android.net.wifi.extra.WAPI_AS_CERTIFICATE_NAME";
+ field public static final String EXTRA_WAPI_USER_CERTIFICATE_DATA = "android.net.wifi.extra.WAPI_USER_CERTIFICATE_DATA";
+ field public static final String EXTRA_WAPI_USER_CERTIFICATE_NAME = "android.net.wifi.extra.WAPI_USER_CERTIFICATE_NAME";
+ field public static final String WAPI_AS_CERTIFICATE = "WAPIAS_";
+ field public static final String WAPI_USER_CERTIFICATE = "WAPIUSR_";
}
public static final class WifiEnterpriseConfig.Eap {
@@ -30135,6 +30378,7 @@ package android.net.wifi {
field public static final int TLS = 1; // 0x1
field public static final int TTLS = 2; // 0x2
field public static final int UNAUTH_TLS = 7; // 0x7
+ field public static final int WAPI_CERT = 8; // 0x8
}
public static final class WifiEnterpriseConfig.Phase2 {
@@ -30206,6 +30450,7 @@ package android.net.wifi {
method public boolean isPreferredNetworkOffloadSupported();
method @Deprecated public boolean isScanAlwaysAvailable();
method public boolean isTdlsSupported();
+ method public boolean isWapiSupported();
method public boolean isWifiEnabled();
method public boolean isWpa3SaeSupported();
method public boolean isWpa3SuiteBSupported();
@@ -30362,6 +30607,8 @@ package android.net.wifi {
method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setPasspointConfig(@NonNull android.net.wifi.hotspot2.PasspointConfiguration);
method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setPriority(@IntRange(from=0) int);
method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setSsid(@NonNull String);
+ method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setWapiEnterpriseConfig(@NonNull android.net.wifi.WifiEnterpriseConfig);
+ method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setWapiPassphrase(@NonNull String);
method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setWpa2EnterpriseConfig(@NonNull android.net.wifi.WifiEnterpriseConfig);
method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setWpa2Passphrase(@NonNull String);
method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setWpa3EnterpriseConfig(@NonNull android.net.wifi.WifiEnterpriseConfig);
@@ -30399,8 +30646,11 @@ package android.net.wifi.aware {
method public int getMaxMatchFilterLength();
method public int getMaxServiceNameLength();
method public int getMaxServiceSpecificInfoLength();
+ method public int getSupportedCipherSuites();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.aware.Characteristics> CREATOR;
+ field public static final int WIFI_AWARE_CIPHER_SUITE_NCS_SK_128 = 1; // 0x1
+ field public static final int WIFI_AWARE_CIPHER_SUITE_NCS_SK_256 = 2; // 0x2
}
public class DiscoverySession implements java.lang.AutoCloseable {
@@ -30648,6 +30898,10 @@ package android.net.wifi.p2p {
ctor public WifiP2pConfig();
ctor public WifiP2pConfig(android.net.wifi.p2p.WifiP2pConfig);
method public int describeContents();
+ method public int getGroupOwnerBand();
+ method public int getNetworkId();
+ method @Nullable public String getNetworkName();
+ method @Nullable public String getPassphrase();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.p2p.WifiP2pConfig> CREATOR;
field public static final int GROUP_OWNER_BAND_2GHZ = 1; // 0x1
@@ -30721,6 +30975,8 @@ package android.net.wifi.p2p {
method public boolean isGroupOwner();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.p2p.WifiP2pGroup> CREATOR;
+ field public static final int PERSISTENT_NET_ID = -2; // 0xfffffffe
+ field public static final int TEMPORARY_NET_ID = -1; // 0xffffffff
}
public class WifiP2pInfo implements android.os.Parcelable {
@@ -31106,6 +31362,7 @@ package android.nfc {
method @Deprecated public void setOnNdefPushCompleteCallback(android.nfc.NfcAdapter.OnNdefPushCompleteCallback, android.app.Activity, android.app.Activity...);
field public static final String ACTION_ADAPTER_STATE_CHANGED = "android.nfc.action.ADAPTER_STATE_CHANGED";
field public static final String ACTION_NDEF_DISCOVERED = "android.nfc.action.NDEF_DISCOVERED";
+ field @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public static final String ACTION_PREFERRED_PAYMENT_CHANGED = "android.nfc.action.PREFERRED_PAYMENT_CHANGED";
field public static final String ACTION_TAG_DISCOVERED = "android.nfc.action.TAG_DISCOVERED";
field public static final String ACTION_TECH_DISCOVERED = "android.nfc.action.TECH_DISCOVERED";
field @RequiresPermission(android.Manifest.permission.NFC_TRANSACTION_EVENT) public static final String ACTION_TRANSACTION_DETECTED = "android.nfc.action.TRANSACTION_DETECTED";
@@ -31114,6 +31371,7 @@ package android.nfc {
field public static final String EXTRA_DATA = "android.nfc.extra.DATA";
field public static final String EXTRA_ID = "android.nfc.extra.ID";
field public static final String EXTRA_NDEF_MESSAGES = "android.nfc.extra.NDEF_MESSAGES";
+ field public static final String EXTRA_PREFERRED_PAYMENT_CHANGED_REASON = "android.nfc.extra.PREFERRED_PAYMENT_CHANGED_REASON";
field public static final String EXTRA_READER_PRESENCE_CHECK_DELAY = "presence";
field public static final String EXTRA_SECURE_ELEMENT_NAME = "android.nfc.extra.SECURE_ELEMENT_NAME";
field public static final String EXTRA_TAG = "android.nfc.extra.TAG";
@@ -31124,6 +31382,9 @@ package android.nfc {
field public static final int FLAG_READER_NFC_V = 8; // 0x8
field public static final int FLAG_READER_NO_PLATFORM_SOUNDS = 256; // 0x100
field public static final int FLAG_READER_SKIP_NDEF_CHECK = 128; // 0x80
+ field public static final int PREFERRED_PAYMENT_CHANGED = 2; // 0x2
+ field public static final int PREFERRED_PAYMENT_LOADED = 1; // 0x1
+ field public static final int PREFERRED_PAYMENT_UPDATED = 3; // 0x3
field public static final int STATE_OFF = 1; // 0x1
field public static final int STATE_ON = 3; // 0x3
field public static final int STATE_TURNING_OFF = 4; // 0x4
@@ -31179,8 +31440,11 @@ package android.nfc.cardemulation {
public final class CardEmulation {
method public boolean categoryAllowsForegroundPreference(String);
+ method @Nullable @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public java.util.List<java.lang.String> getAidsForPreferredPaymentService();
method public java.util.List<java.lang.String> getAidsForService(android.content.ComponentName, String);
+ method @Nullable @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public String getDescriptionForPreferredPaymentService();
method public static android.nfc.cardemulation.CardEmulation getInstance(android.nfc.NfcAdapter);
+ method @Nullable @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public String getRouteDestinationForPreferredPaymentService();
method public int getSelectionModeForCategory(String);
method public boolean isDefaultServiceForAid(android.content.ComponentName, String);
method public boolean isDefaultServiceForCategory(android.content.ComponentName, String);
@@ -35418,11 +35682,12 @@ package android.os {
method public boolean isIgnoringBatteryOptimizations(String);
method public boolean isInteractive();
method public boolean isPowerSaveMode();
+ method public boolean isRebootingUserspaceSupported();
method @Deprecated public boolean isScreenOn();
method public boolean isSustainedPerformanceModeSupported();
method public boolean isWakeLockLevelSupported(int);
method public android.os.PowerManager.WakeLock newWakeLock(int, String);
- method public void reboot(String);
+ method public void reboot(@Nullable String);
method public void removeThermalStatusListener(@NonNull android.os.PowerManager.OnThermalStatusChangedListener);
field public static final int ACQUIRE_CAUSES_WAKEUP = 268435456; // 0x10000000
field public static final String ACTION_DEVICE_IDLE_MODE_CHANGED = "android.os.action.DEVICE_IDLE_MODE_CHANGED";
@@ -35753,7 +36018,7 @@ package android.os {
method @Deprecated public void setUserRestrictions(android.os.Bundle, android.os.UserHandle);
method public static boolean supportsMultipleUsers();
field public static final String ALLOW_PARENT_PROFILE_APP_LINKING = "allow_parent_profile_app_linking";
- field public static final String DISALLOW_ADD_MANAGED_PROFILE = "no_add_managed_profile";
+ field @Deprecated public static final String DISALLOW_ADD_MANAGED_PROFILE = "no_add_managed_profile";
field public static final String DISALLOW_ADD_USER = "no_add_user";
field public static final String DISALLOW_ADJUST_VOLUME = "no_adjust_volume";
field public static final String DISALLOW_AIRPLANE_MODE = "no_airplane_mode";
@@ -35792,7 +36057,7 @@ package android.os {
field public static final String DISALLOW_OUTGOING_BEAM = "no_outgoing_beam";
field public static final String DISALLOW_OUTGOING_CALLS = "no_outgoing_calls";
field public static final String DISALLOW_PRINTING = "no_printing";
- field public static final String DISALLOW_REMOVE_MANAGED_PROFILE = "no_remove_managed_profile";
+ field @Deprecated public static final String DISALLOW_REMOVE_MANAGED_PROFILE = "no_remove_managed_profile";
field public static final String DISALLOW_REMOVE_USER = "no_remove_user";
field public static final String DISALLOW_SAFE_BOOT = "no_safe_boot";
field public static final String DISALLOW_SET_USER_ICON = "no_set_user_icon";
@@ -39036,6 +39301,8 @@ package android.provider {
field public static final String GENRE = "genre";
field public static final String HEIGHT = "height";
field public static final String INSTANCE_ID = "instance_id";
+ field public static final String IS_DOWNLOAD = "is_download";
+ field public static final String IS_DRM = "is_drm";
field public static final String IS_FAVORITE = "is_favorite";
field public static final String IS_PENDING = "is_pending";
field public static final String IS_TRASHED = "is_trashed";
@@ -39139,6 +39406,7 @@ package android.provider {
field public static final String ACTION_APP_SEARCH_SETTINGS = "android.settings.APP_SEARCH_SETTINGS";
field public static final String ACTION_APP_USAGE_SETTINGS = "android.settings.action.APP_USAGE_SETTINGS";
field public static final String ACTION_BATTERY_SAVER_SETTINGS = "android.settings.BATTERY_SAVER_SETTINGS";
+ field public static final String ACTION_BIOMETRIC_ENROLL = "android.settings.BIOMETRIC_ENROLL";
field public static final String ACTION_BLUETOOTH_SETTINGS = "android.settings.BLUETOOTH_SETTINGS";
field public static final String ACTION_CAPTIONING_SETTINGS = "android.settings.CAPTIONING_SETTINGS";
field public static final String ACTION_CAST_SETTINGS = "android.settings.CAST_SETTINGS";
@@ -39150,7 +39418,7 @@ package android.provider {
field public static final String ACTION_DEVICE_INFO_SETTINGS = "android.settings.DEVICE_INFO_SETTINGS";
field public static final String ACTION_DISPLAY_SETTINGS = "android.settings.DISPLAY_SETTINGS";
field public static final String ACTION_DREAM_SETTINGS = "android.settings.DREAM_SETTINGS";
- field public static final String ACTION_FINGERPRINT_ENROLL = "android.settings.FINGERPRINT_ENROLL";
+ field @Deprecated public static final String ACTION_FINGERPRINT_ENROLL = "android.settings.FINGERPRINT_ENROLL";
field public static final String ACTION_HARD_KEYBOARD_SETTINGS = "android.settings.HARD_KEYBOARD_SETTINGS";
field public static final String ACTION_HOME_SETTINGS = "android.settings.HOME_SETTINGS";
field public static final String ACTION_IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS = "android.settings.IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS";
@@ -39213,9 +39481,14 @@ package android.provider {
field public static final String EXTRA_APP_PACKAGE = "android.provider.extra.APP_PACKAGE";
field public static final String EXTRA_AUTHORITIES = "authorities";
field public static final String EXTRA_BATTERY_SAVER_MODE_ENABLED = "android.settings.extra.battery_saver_mode_enabled";
+ field public static final String EXTRA_BIOMETRIC_MINIMUM_STRENGTH_REQUIRED = "android.provider.extra.BIOMETRIC_MINIMUM_STRENGTH_REQUIRED";
field public static final String EXTRA_CHANNEL_ID = "android.provider.extra.CHANNEL_ID";
field public static final String EXTRA_DO_NOT_DISTURB_MODE_ENABLED = "android.settings.extra.do_not_disturb_mode_enabled";
field public static final String EXTRA_DO_NOT_DISTURB_MODE_MINUTES = "android.settings.extra.do_not_disturb_mode_minutes";
+ field public static final String EXTRA_EASY_CONNECT_ATTEMPTED_SSID = "android.provider.extra.EASY_CONNECT_ATTEMPTED_SSID";
+ field public static final String EXTRA_EASY_CONNECT_BAND_LIST = "android.provider.extra.EASY_CONNECT_BAND_LIST";
+ field public static final String EXTRA_EASY_CONNECT_CHANNEL_LIST = "android.provider.extra.EASY_CONNECT_CHANNEL_LIST";
+ field public static final String EXTRA_EASY_CONNECT_ERROR_CODE = "android.provider.extra.EASY_CONNECT_ERROR_CODE";
field public static final String EXTRA_INPUT_METHOD_ID = "input_method_id";
field public static final String EXTRA_NOTIFICATION_LISTENER_COMPONENT_NAME = "android.provider.extra.NOTIFICATION_LISTENER_COMPONENT_NAME";
field public static final String EXTRA_SUB_ID = "android.provider.extra.SUB_ID";
@@ -41151,6 +41424,11 @@ package android.security {
method public android.security.ConfirmationPrompt.Builder setPromptText(CharSequence);
}
+ public final class FileIntegrityManager {
+ method public boolean isApkVeritySupported();
+ method @RequiresPermission(anyOf={android.Manifest.permission.INSTALL_PACKAGES, android.Manifest.permission.REQUEST_INSTALL_PACKAGES}) public boolean isAppSourceCertificateTrusted(@NonNull java.security.cert.X509Certificate) throws java.security.cert.CertificateEncodingException;
+ }
+
public final class KeyChain {
ctor public KeyChain();
method public static void choosePrivateKeyAlias(@NonNull android.app.Activity, @NonNull android.security.KeyChainAliasCallback, @Nullable String[], @Nullable java.security.Principal[], @Nullable String, int, @Nullable String);
@@ -44364,19 +44642,27 @@ package android.telecom {
field @Deprecated public static final String ACTION_INCOMING_CALL = "android.telecom.action.INCOMING_CALL";
field public static final String ACTION_PHONE_ACCOUNT_REGISTERED = "android.telecom.action.PHONE_ACCOUNT_REGISTERED";
field public static final String ACTION_PHONE_ACCOUNT_UNREGISTERED = "android.telecom.action.PHONE_ACCOUNT_UNREGISTERED";
+ field public static final String ACTION_POST_CALL = "android.telecom.action.POST_CALL";
field public static final String ACTION_SHOW_CALL_ACCESSIBILITY_SETTINGS = "android.telecom.action.SHOW_CALL_ACCESSIBILITY_SETTINGS";
field public static final String ACTION_SHOW_CALL_SETTINGS = "android.telecom.action.SHOW_CALL_SETTINGS";
field public static final String ACTION_SHOW_MISSED_CALLS_NOTIFICATION = "android.telecom.action.SHOW_MISSED_CALLS_NOTIFICATION";
field public static final String ACTION_SHOW_RESPOND_VIA_SMS_SETTINGS = "android.telecom.action.SHOW_RESPOND_VIA_SMS_SETTINGS";
field public static final char DTMF_CHARACTER_PAUSE = 44; // 0x002c ','
field public static final char DTMF_CHARACTER_WAIT = 59; // 0x003b ';'
+ field public static final int DURATION_LONG = 3; // 0x3
+ field public static final int DURATION_MEDIUM = 2; // 0x2
+ field public static final int DURATION_SHORT = 1; // 0x1
+ field public static final int DURATION_VERY_SHORT = 0; // 0x0
field public static final String EXTRA_CALL_BACK_NUMBER = "android.telecom.extra.CALL_BACK_NUMBER";
field public static final String EXTRA_CALL_DISCONNECT_CAUSE = "android.telecom.extra.CALL_DISCONNECT_CAUSE";
field public static final String EXTRA_CALL_DISCONNECT_MESSAGE = "android.telecom.extra.CALL_DISCONNECT_MESSAGE";
+ field public static final String EXTRA_CALL_DURATION = "android.telecom.extra.CALL_DURATION";
field public static final String EXTRA_CALL_NETWORK_TYPE = "android.telecom.extra.CALL_NETWORK_TYPE";
field public static final String EXTRA_CALL_SUBJECT = "android.telecom.extra.CALL_SUBJECT";
field public static final String EXTRA_CHANGE_DEFAULT_DIALER_PACKAGE_NAME = "android.telecom.extra.CHANGE_DEFAULT_DIALER_PACKAGE_NAME";
field public static final String EXTRA_DEFAULT_CALL_SCREENING_APP_COMPONENT_NAME = "android.telecom.extra.DEFAULT_CALL_SCREENING_APP_COMPONENT_NAME";
+ field public static final String EXTRA_DISCONNECT_CAUSE = "android.telecom.extra.DISCONNECT_CAUSE";
+ field public static final String EXTRA_HANDLE = "android.telecom.extra.HANDLE";
field public static final String EXTRA_INCOMING_CALL_ADDRESS = "android.telecom.extra.INCOMING_CALL_ADDRESS";
field public static final String EXTRA_INCOMING_CALL_EXTRAS = "android.telecom.extra.INCOMING_CALL_EXTRAS";
field public static final String EXTRA_INCOMING_VIDEO_STATE = "android.telecom.extra.INCOMING_VIDEO_STATE";
@@ -44720,6 +45006,8 @@ package android.telephony {
field public static final String KEY_IMS_CONFERENCE_SIZE_LIMIT_INT = "ims_conference_size_limit_int";
field public static final String KEY_IMS_DTMF_TONE_DELAY_INT = "ims_dtmf_tone_delay_int";
field public static final String KEY_IS_IMS_CONFERENCE_SIZE_ENFORCED_BOOL = "is_ims_conference_size_enforced_bool";
+ field public static final String KEY_LTE_RSRQ_THRESHOLDS_INT_ARRAY = "lte_rsrq_thresholds_int_array";
+ field public static final String KEY_LTE_RSSNR_THRESHOLDS_INT_ARRAY = "lte_rssnr_thresholds_int_array";
field public static final String KEY_MDN_IS_ADDITIONAL_VOICEMAIL_NUMBER_BOOL = "mdn_is_additional_voicemail_number_bool";
field public static final String KEY_MMS_ALIAS_ENABLED_BOOL = "aliasEnabled";
field public static final String KEY_MMS_ALIAS_MAX_CHARS_INT = "aliasMaxChars";
@@ -44805,6 +45093,11 @@ package android.telephony {
field public static final String KEY_WORLD_PHONE_BOOL = "world_phone_bool";
}
+ public static final class CarrierConfigManager.Gps {
+ field public static final String KEY_PERSIST_LPP_MODE_BOOL = "gps.persist_lpp_mode_bool";
+ field public static final String KEY_PREFIX = "gps.";
+ }
+
public static final class CarrierConfigManager.Ims {
field public static final String KEY_PREFIX = "ims.";
}
@@ -45238,6 +45531,7 @@ package android.telephony {
ctor public PhoneStateListener();
ctor public PhoneStateListener(@NonNull java.util.concurrent.Executor);
method public void onActiveDataSubscriptionIdChanged(int);
+ method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onCallDisconnectCauseChanged(int, int);
method public void onCallForwardingIndicatorChanged(boolean);
method public void onCallStateChanged(int, String);
method public void onCellInfoChanged(java.util.List<android.telephony.CellInfo>);
@@ -45245,6 +45539,7 @@ package android.telephony {
method public void onDataActivity(int);
method public void onDataConnectionStateChanged(int);
method public void onDataConnectionStateChanged(int, int);
+ method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onImsCallDisconnectCauseChanged(@NonNull android.telephony.ims.ImsReasonInfo);
method public void onMessageWaitingIndicatorChanged(boolean);
method @RequiresPermission("android.permission.MODIFY_PHONE_STATE") public void onPreciseDataConnectionStateChanged(@NonNull android.telephony.PreciseDataConnectionState);
method public void onServiceStateChanged(android.telephony.ServiceState);
@@ -45252,6 +45547,7 @@ package android.telephony {
method public void onSignalStrengthsChanged(android.telephony.SignalStrength);
method public void onUserMobileDataStateChanged(boolean);
field public static final int LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE = 4194304; // 0x400000
+ field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_CALL_DISCONNECT_CAUSES = 33554432; // 0x2000000
field public static final int LISTEN_CALL_FORWARDING_INDICATOR = 8; // 0x8
field public static final int LISTEN_CALL_STATE = 32; // 0x20
field public static final int LISTEN_CELL_INFO = 1024; // 0x400
@@ -45259,6 +45555,7 @@ package android.telephony {
field public static final int LISTEN_DATA_ACTIVITY = 128; // 0x80
field public static final int LISTEN_DATA_CONNECTION_STATE = 64; // 0x40
field public static final int LISTEN_EMERGENCY_NUMBER_LIST = 16777216; // 0x1000000
+ field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_IMS_CALL_DISCONNECT_CAUSES = 134217728; // 0x8000000
field public static final int LISTEN_MESSAGE_WAITING_INDICATOR = 4; // 0x4
field public static final int LISTEN_NONE = 0; // 0x0
field @RequiresPermission("android.permission.MODIFY_PHONE_STATE") public static final int LISTEN_PRECISE_DATA_CONNECTION_STATE = 4096; // 0x1000
@@ -45490,6 +45787,7 @@ package android.telephony {
method public byte[] getPdu();
method public int getProtocolIdentifier();
method public String getPseudoSubject();
+ method @Nullable public String getRecipientAddress();
method public String getServiceCenterAddress();
method public int getStatus();
method public int getStatusOnIcc();
@@ -45706,6 +46004,7 @@ package android.telephony {
method public int getSimState();
method public int getSimState(int);
method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getSubscriberId();
+ method public int getSubscriptionId();
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int getSubscriptionId(@NonNull android.telecom.PhoneAccountHandle);
method public int getSupportedModemCount();
method @Nullable public String getTypeAllocationCode();
@@ -49441,6 +49740,71 @@ package android.util {
}
+package android.util.proto {
+
+ public final class ProtoOutputStream {
+ ctor public ProtoOutputStream();
+ ctor public ProtoOutputStream(int);
+ ctor public ProtoOutputStream(@NonNull java.io.OutputStream);
+ method public static int checkFieldId(long, long);
+ method public void dump(@NonNull String);
+ method public void end(long);
+ method public void flush();
+ method @NonNull public byte[] getBytes();
+ method @Nullable public static String getFieldCountString(long);
+ method @NonNull public static String getFieldIdString(long);
+ method @Nullable public static String getFieldTypeString(long);
+ method public int getRawSize();
+ method @Nullable public static String getWireTypeString(int);
+ method public static long makeFieldId(int, long);
+ method public static long makeToken(int, boolean, int, int, int);
+ method public long start(long);
+ method @NonNull public static String token2String(long);
+ method public void write(long, double);
+ method public void write(long, float);
+ method public void write(long, int);
+ method public void write(long, long);
+ method public void write(long, boolean);
+ method public void write(long, @Nullable String);
+ method public void write(long, @Nullable byte[]);
+ method public void writeTag(int, int);
+ field public static final long FIELD_COUNT_MASK = 16492674416640L; // 0xf0000000000L
+ field public static final long FIELD_COUNT_PACKED = 5497558138880L; // 0x50000000000L
+ field public static final long FIELD_COUNT_REPEATED = 2199023255552L; // 0x20000000000L
+ field public static final int FIELD_COUNT_SHIFT = 40; // 0x28
+ field public static final long FIELD_COUNT_SINGLE = 1099511627776L; // 0x10000000000L
+ field public static final long FIELD_COUNT_UNKNOWN = 0L; // 0x0L
+ field public static final int FIELD_ID_SHIFT = 3; // 0x3
+ field public static final long FIELD_TYPE_BOOL = 34359738368L; // 0x800000000L
+ field public static final long FIELD_TYPE_BYTES = 51539607552L; // 0xc00000000L
+ field public static final long FIELD_TYPE_DOUBLE = 4294967296L; // 0x100000000L
+ field public static final long FIELD_TYPE_ENUM = 60129542144L; // 0xe00000000L
+ field public static final long FIELD_TYPE_FIXED32 = 30064771072L; // 0x700000000L
+ field public static final long FIELD_TYPE_FIXED64 = 25769803776L; // 0x600000000L
+ field public static final long FIELD_TYPE_FLOAT = 8589934592L; // 0x200000000L
+ field public static final long FIELD_TYPE_INT32 = 21474836480L; // 0x500000000L
+ field public static final long FIELD_TYPE_INT64 = 12884901888L; // 0x300000000L
+ field public static final long FIELD_TYPE_MASK = 1095216660480L; // 0xff00000000L
+ field public static final long FIELD_TYPE_MESSAGE = 47244640256L; // 0xb00000000L
+ field public static final long FIELD_TYPE_SFIXED32 = 64424509440L; // 0xf00000000L
+ field public static final long FIELD_TYPE_SFIXED64 = 68719476736L; // 0x1000000000L
+ field public static final int FIELD_TYPE_SHIFT = 32; // 0x20
+ field public static final long FIELD_TYPE_SINT32 = 73014444032L; // 0x1100000000L
+ field public static final long FIELD_TYPE_SINT64 = 77309411328L; // 0x1200000000L
+ field public static final long FIELD_TYPE_STRING = 38654705664L; // 0x900000000L
+ field public static final long FIELD_TYPE_UINT32 = 55834574848L; // 0xd00000000L
+ field public static final long FIELD_TYPE_UINT64 = 17179869184L; // 0x400000000L
+ field public static final int WIRE_TYPE_END_GROUP = 4; // 0x4
+ field public static final int WIRE_TYPE_FIXED32 = 5; // 0x5
+ field public static final int WIRE_TYPE_FIXED64 = 1; // 0x1
+ field public static final int WIRE_TYPE_LENGTH_DELIMITED = 2; // 0x2
+ field public static final int WIRE_TYPE_MASK = 7; // 0x7
+ field public static final int WIRE_TYPE_START_GROUP = 3; // 0x3
+ field public static final int WIRE_TYPE_VARINT = 0; // 0x0
+ }
+
+}
+
package android.view {
public abstract class AbsSavedState implements android.os.Parcelable {
@@ -49575,6 +49939,7 @@ package android.view {
method @Deprecated public float[] getSupportedRefreshRates();
method @Deprecated public int getWidth();
method public boolean isHdr();
+ method public boolean isMinimalPostProcessingSupported();
method public boolean isValid();
method public boolean isWideColorGamut();
field public static final int DEFAULT_DISPLAY = 0; // 0x0
@@ -51367,6 +51732,7 @@ package android.view {
method public boolean isScrollContainer();
method public boolean isScrollbarFadingEnabled();
method @android.view.ViewDebug.ExportedProperty public boolean isSelected();
+ method public final boolean isShowingLayoutBounds();
method public boolean isShown();
method @android.view.ViewDebug.ExportedProperty public boolean isSoundEffectsEnabled();
method public final boolean isTemporarilyDetached();
@@ -52606,6 +52972,7 @@ package android.view {
method public abstract void setNavigationBarColor(@ColorInt int);
method public void setNavigationBarContrastEnforced(boolean);
method public void setNavigationBarDividerColor(@ColorInt int);
+ method public void setPreferMinimalPostProcessing(boolean);
method public void setReenterTransition(android.transition.Transition);
method public abstract void setResizingCaptionDrawable(android.graphics.drawable.Drawable);
method public final void setRestrictedCaptionAreaListener(android.view.Window.OnRestrictedCaptionAreaChangedListener);
@@ -52993,6 +53360,7 @@ package android.view {
field public int layoutInDisplayCutoutMode;
field @Deprecated public int memoryType;
field public String packageName;
+ field public boolean preferMinimalPostProcessing;
field public int preferredDisplayModeId;
field @Deprecated public float preferredRefreshRate;
field public int rotationAnimation;
@@ -54005,6 +54373,7 @@ package android.view.inline {
public static final class InlinePresentationSpec.Builder {
ctor public InlinePresentationSpec.Builder(@NonNull android.util.Size, @NonNull android.util.Size);
method @NonNull public android.view.inline.InlinePresentationSpec build();
+ method @NonNull public android.view.inline.InlinePresentationSpec.Builder setStyle(@Nullable String);
}
}
@@ -54942,6 +55311,7 @@ package android.view.textclassifier {
method public int describeContents();
method @NonNull public android.os.Bundle getExtras();
method @NonNull public java.util.Collection<android.view.textclassifier.TextLinks.TextLink> getLinks();
+ method @NonNull public String getText();
method public void writeToParcel(android.os.Parcel, int);
field public static final int APPLY_STRATEGY_IGNORE = 0; // 0x0
field public static final int APPLY_STRATEGY_REPLACE = 1; // 0x1
@@ -54968,6 +55338,7 @@ package android.view.textclassifier {
method @Nullable public android.os.LocaleList getDefaultLocales();
method @Nullable public android.view.textclassifier.TextClassifier.EntityConfig getEntityConfig();
method @NonNull public android.os.Bundle getExtras();
+ method @Nullable public java.time.ZonedDateTime getReferenceTime();
method @NonNull public CharSequence getText();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.view.textclassifier.TextLinks.Request> CREATOR;
@@ -54979,6 +55350,7 @@ package android.view.textclassifier {
method @NonNull public android.view.textclassifier.TextLinks.Request.Builder setDefaultLocales(@Nullable android.os.LocaleList);
method @NonNull public android.view.textclassifier.TextLinks.Request.Builder setEntityConfig(@Nullable android.view.textclassifier.TextClassifier.EntityConfig);
method public android.view.textclassifier.TextLinks.Request.Builder setExtras(@Nullable android.os.Bundle);
+ method @NonNull public android.view.textclassifier.TextLinks.Request.Builder setReferenceTime(@Nullable java.time.ZonedDateTime);
}
public static final class TextLinks.TextLink implements android.os.Parcelable {
diff --git a/api/lint-baseline.txt b/api/lint-baseline.txt
index 4a37e67c48b0..508718e10bd9 100644
--- a/api/lint-baseline.txt
+++ b/api/lint-baseline.txt
@@ -527,6 +527,14 @@ MissingNullability: android.icu.text.DateTimePatternGenerator#getFieldDisplayNam
MissingNullability: android.icu.text.DateTimePatternGenerator#getFieldDisplayName(int, android.icu.text.DateTimePatternGenerator.DisplayWidth) parameter #1:
+MissingNullability: android.icu.util.MeasureUnit#ATMOSPHERE:
+ Missing nullability on field `ATMOSPHERE` in class `class android.icu.util.MeasureUnit`
+MissingNullability: android.icu.util.MeasureUnit#PERCENT:
+ Missing nullability on field `PERCENT` in class `class android.icu.util.MeasureUnit`
+MissingNullability: android.icu.util.MeasureUnit#PERMILLE:
+ Missing nullability on field `PERMILLE` in class `class android.icu.util.MeasureUnit`
+MissingNullability: android.icu.util.MeasureUnit#PETABYTE:
+ Missing nullability on field `PETABYTE` in class `class android.icu.util.MeasureUnit`
MissingNullability: android.icu.util.VersionInfo#UNICODE_12_0:
MissingNullability: android.icu.util.VersionInfo#UNICODE_12_1:
diff --git a/api/removed.txt b/api/removed.txt
index 8b30d0a5cf39..fb6d57694c78 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -435,15 +435,6 @@ package android.provider {
field @Deprecated public static final String TIMESTAMP = "timestamp";
}
- public final class MediaStore {
- method @Deprecated @NonNull public static java.util.Set<java.lang.String> getAllVolumeNames(@NonNull android.content.Context);
- method @Deprecated public static boolean getIncludePending(@NonNull android.net.Uri);
- method @Deprecated @NonNull public static android.net.Uri setIncludeTrashed(@NonNull android.net.Uri);
- method @Deprecated public static void trash(@NonNull android.content.Context, @NonNull android.net.Uri);
- method @Deprecated public static void trash(@NonNull android.content.Context, @NonNull android.net.Uri, long);
- method @Deprecated public static void untrash(@NonNull android.content.Context, @NonNull android.net.Uri);
- }
-
public static interface MediaStore.Audio.AudioColumns extends android.provider.MediaStore.MediaColumns {
field public static final String ALBUM = "album";
field public static final String ARTIST = "artist";
diff --git a/api/system-current.txt b/api/system-current.txt
index dd68e44ffe21..8a888db638b0 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -8,6 +8,7 @@ package android {
field public static final String ACCESS_DRM_CERTIFICATES = "android.permission.ACCESS_DRM_CERTIFICATES";
field @Deprecated public static final String ACCESS_FM_RADIO = "android.permission.ACCESS_FM_RADIO";
field public static final String ACCESS_INSTANT_APPS = "android.permission.ACCESS_INSTANT_APPS";
+ field public static final String ACCESS_MESSAGES_ON_ICC = "android.permission.ACCESS_MESSAGES_ON_ICC";
field public static final String ACCESS_MOCK_LOCATION = "android.permission.ACCESS_MOCK_LOCATION";
field public static final String ACCESS_MTP = "android.permission.ACCESS_MTP";
field public static final String ACCESS_NETWORK_CONDITIONS = "android.permission.ACCESS_NETWORK_CONDITIONS";
@@ -15,6 +16,7 @@ package android {
field public static final String ACCESS_SHARED_LIBRARIES = "android.permission.ACCESS_SHARED_LIBRARIES";
field public static final String ACCESS_SHORTCUTS = "android.permission.ACCESS_SHORTCUTS";
field public static final String ACCESS_SURFACE_FLINGER = "android.permission.ACCESS_SURFACE_FLINGER";
+ field public static final String ACCESS_TV_TUNER = "android.permission.ACCESS_TV_TUNER";
field public static final String ACTIVITY_EMBEDDING = "android.permission.ACTIVITY_EMBEDDING";
field public static final String ADJUST_RUNTIME_PERMISSIONS_POLICY = "android.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY";
field public static final String ALLOCATE_AGGRESSIVE = "android.permission.ALLOCATE_AGGRESSIVE";
@@ -259,7 +261,6 @@ package android {
public static final class R.drawable {
field public static final int ic_info = 17301684; // 0x10800b4
- field public static final int stat_notify_wifi_in_range = 17301685; // 0x10800b5
}
public static final class R.raw {
@@ -280,9 +281,6 @@ package android {
field public static final int config_helpIntentNameKey = 17039390; // 0x104001e
field public static final int config_helpPackageNameKey = 17039387; // 0x104001b
field public static final int config_helpPackageNameValue = 17039388; // 0x104001c
- field public static final int notification_channel_network_alerts = 17039398; // 0x1040026
- field public static final int notification_channel_network_available = 17039399; // 0x1040027
- field public static final int notification_channel_network_status = 17039397; // 0x1040025
}
public static final class R.style {
@@ -365,6 +363,7 @@ package android.app {
field public static final String OPSTR_GPS = "android:gps";
field public static final String OPSTR_INSTANT_APP_START_FOREGROUND = "android:instant_app_start_foreground";
field public static final String OPSTR_LEGACY_STORAGE = "android:legacy_storage";
+ field public static final String OPSTR_MANAGE_EXTERNAL_STORAGE = "android:manage_external_storage";
field public static final String OPSTR_MANAGE_IPSEC_TUNNELS = "android:manage_ipsec_tunnels";
field public static final String OPSTR_MUTE_MICROPHONE = "android:mute_microphone";
field public static final String OPSTR_NEIGHBORING_CELLS = "android:neighboring_cells";
@@ -473,15 +472,20 @@ package android.app {
public static final class AppOpsManager.OpEntry implements android.os.Parcelable {
method public int describeContents();
- method public long getDuration();
+ method @Deprecated public long getDuration();
method @NonNull public java.util.Map<java.lang.String,android.app.AppOpsManager.OpFeatureEntry> getFeatures();
method public long getLastAccessBackgroundTime(int);
method public long getLastAccessForegroundTime(int);
method public long getLastAccessTime(int);
method public long getLastAccessTime(int, int, int);
method public long getLastBackgroundDuration(int);
+ method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastBackgroundProxyInfo(int);
+ method public long getLastDuration(int);
method public long getLastDuration(int, int, int);
method public long getLastForegroundDuration(int);
+ method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastForegroundProxyInfo(int);
+ method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastProxyInfo(int);
+ method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastProxyInfo(int, int, int);
method public long getLastRejectBackgroundTime(int);
method public long getLastRejectForegroundTime(int);
method public long getLastRejectTime(int);
@@ -489,34 +493,44 @@ package android.app {
method public int getMode();
method @NonNull public String getOpStr();
method @Deprecated @Nullable public String getProxyPackageName();
- method @Nullable public String getProxyPackageName(int, int);
+ method @Deprecated @Nullable public String getProxyPackageName(int, int);
method @Deprecated public int getProxyUid();
- method public int getProxyUid(int, int);
+ method @Deprecated public int getProxyUid(int, int);
method public boolean isRunning();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.OpEntry> CREATOR;
}
- public static final class AppOpsManager.OpFeatureEntry {
- method public long getDuration();
+ public static final class AppOpsManager.OpEventProxyInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method @Nullable public String getFeatureId();
+ method @Nullable public String getPackageName();
+ method @IntRange(from=0) public int getUid();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.OpEventProxyInfo> CREATOR;
+ }
+
+ public static final class AppOpsManager.OpFeatureEntry implements android.os.Parcelable {
+ method public int describeContents();
method public long getLastAccessBackgroundTime(int);
method public long getLastAccessForegroundTime(int);
method public long getLastAccessTime(int);
method public long getLastAccessTime(int, int, int);
method public long getLastBackgroundDuration(int);
+ method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastBackgroundProxyInfo(int);
+ method public long getLastDuration(int);
method public long getLastDuration(int, int, int);
method public long getLastForegroundDuration(int);
+ method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastForegroundProxyInfo(int);
+ method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastProxyInfo(int);
+ method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastProxyInfo(int, int, int);
method public long getLastRejectBackgroundTime(int);
method public long getLastRejectForegroundTime(int);
method public long getLastRejectTime(int);
method public long getLastRejectTime(int, int, int);
- method @Nullable public String getProxyFeatureId();
- method @Nullable public String getProxyFeatureId(int, int);
- method @Nullable public String getProxyPackageName();
- method @Nullable public String getProxyPackageName(int, int);
- method public int getProxyUid();
- method public int getProxyUid(int, int);
method public boolean isRunning();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.OpFeatureEntry> CREATOR;
}
public static final class AppOpsManager.PackageOps implements android.os.Parcelable {
@@ -524,7 +538,7 @@ package android.app {
method @NonNull public java.util.List<android.app.AppOpsManager.OpEntry> getOps();
method @NonNull public String getPackageName();
method public int getUid();
- method public void writeToParcel(android.os.Parcel, int);
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.PackageOps> CREATOR;
}
@@ -764,6 +778,7 @@ package android.app.admin {
method @Nullable public android.content.ComponentName getProfileOwner() throws java.lang.IllegalArgumentException;
method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public String getProfileOwnerNameAsUser(int) throws java.lang.IllegalArgumentException;
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public int getUserProvisioningState();
+ method public boolean hasDeviceIdentifierAccess(@NonNull String, int, int);
method public boolean isDeviceManaged();
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isDeviceProvisioned();
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isDeviceProvisioningConfigApplied();
@@ -1653,6 +1668,7 @@ package android.content {
field public static final String SYSTEM_UPDATE_SERVICE = "system_update";
field public static final String TELEPHONY_IMS_SERVICE = "telephony_ims";
field public static final String TELEPHONY_REGISTRY_SERVICE = "telephony_registry";
+ field public static final String TETHERING_SERVICE = "tethering";
field public static final String VR_SERVICE = "vrmanager";
field @Deprecated public static final String WIFI_RTT_SERVICE = "rttmanager";
field public static final String WIFI_SCANNING_SERVICE = "wifiscanner";
@@ -1915,6 +1931,15 @@ package android.content.pm {
method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_PROFILES) public void startActivity(@NonNull android.content.ComponentName, @NonNull android.os.UserHandle);
}
+ public class DataLoaderParams {
+ method @NonNull public static final android.content.pm.DataLoaderParams forIncremental(@NonNull android.content.ComponentName, @NonNull String, @Nullable java.util.Map<java.lang.String,android.os.ParcelFileDescriptor>);
+ method @NonNull public static final android.content.pm.DataLoaderParams forStreaming(@NonNull android.content.ComponentName, @NonNull String);
+ method @NonNull public final String getArguments();
+ method @NonNull public final android.content.ComponentName getComponentName();
+ method @NonNull public final java.util.Map<java.lang.String,android.os.ParcelFileDescriptor> getDynamicArgs();
+ method @NonNull public final int getType();
+ }
+
public final class InstantAppInfo implements android.os.Parcelable {
ctor public InstantAppInfo(android.content.pm.ApplicationInfo, String[], String[]);
ctor public InstantAppInfo(String, CharSequence, String[], String[]);
@@ -2004,6 +2029,7 @@ package android.content.pm {
}
public static class PackageInstaller.Session implements java.io.Closeable {
+ method public void addFile(@NonNull String, long, @NonNull byte[]);
method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void commitTransferred(@NonNull android.content.IntentSender);
}
@@ -2017,14 +2043,17 @@ package android.content.pm {
method public boolean getInstallAsInstantApp(boolean);
method public boolean getInstallAsVirtualPreload();
method public boolean getRequestDowngrade();
+ method public int getRollbackDataPolicy();
method @NonNull public java.util.Set<java.lang.String> getWhitelistedRestrictedPermissions();
}
public static class PackageInstaller.SessionParams implements android.os.Parcelable {
method @RequiresPermission(android.Manifest.permission.ALLOCATE_AGGRESSIVE) public void setAllocateAggressive(boolean);
method @Deprecated public void setAllowDowngrade(boolean);
+ method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setDataLoaderParams(@NonNull android.content.pm.DataLoaderParams);
method public void setDontKillApp(boolean);
method public void setEnableRollback(boolean);
+ method public void setEnableRollback(boolean, int);
method @RequiresPermission(android.Manifest.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS) public void setGrantedRuntimePermissions(String[]);
method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setInstallAsApex();
method public void setInstallAsInstantApp(boolean);
@@ -2088,6 +2117,7 @@ package android.content.pm {
field public static final int FLAG_PERMISSION_APPLY_RESTRICTION = 16384; // 0x4000
field public static final int FLAG_PERMISSION_GRANTED_BY_DEFAULT = 32; // 0x20
field public static final int FLAG_PERMISSION_GRANTED_BY_ROLE = 32768; // 0x8000
+ field public static final int FLAG_PERMISSION_ONE_TIME = 65536; // 0x10000
field public static final int FLAG_PERMISSION_POLICY_FIXED = 4; // 0x4
field public static final int FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT = 2048; // 0x800
field public static final int FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT = 4096; // 0x1000
@@ -2162,7 +2192,7 @@ package android.content.pm {
method public void onPermissionsChanged(int);
}
- @IntDef(prefix={"FLAG_PERMISSION_"}, value={android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET, android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED, android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED, android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE, android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED, android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT, android.content.pm.PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED, android.content.pm.PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED, android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT, android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT, android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT, android.content.pm.PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION, android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE, android.content.pm.PackageManager.FLAG_PERMISSION_REVOKED_COMPAT}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface PackageManager.PermissionFlags {
+ @IntDef(prefix={"FLAG_PERMISSION_"}, value={android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET, android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED, android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED, android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE, android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED, android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT, android.content.pm.PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED, android.content.pm.PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED, android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT, android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT, android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT, android.content.pm.PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION, android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE, android.content.pm.PackageManager.FLAG_PERMISSION_REVOKED_COMPAT, android.content.pm.PackageManager.FLAG_PERMISSION_ONE_TIME}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface PackageManager.PermissionFlags {
}
public class PermissionGroupInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
@@ -2175,6 +2205,7 @@ package android.content.pm {
public class PermissionInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
field public static final int FLAG_REMOVED = 2; // 0x2
field public static final int PROTECTION_FLAG_APP_PREDICTOR = 2097152; // 0x200000
+ field public static final int PROTECTION_FLAG_COMPANION = 8388608; // 0x800000
field public static final int PROTECTION_FLAG_CONFIGURATOR = 524288; // 0x80000
field public static final int PROTECTION_FLAG_DOCUMENTER = 262144; // 0x40000
field public static final int PROTECTION_FLAG_INCIDENT_REPORT_APPROVER = 1048576; // 0x100000
@@ -2383,9 +2414,13 @@ package android.hardware.display {
method @Nullable public android.hardware.display.BrightnessCorrection getCorrectionByCategory(int);
method @Nullable public android.hardware.display.BrightnessCorrection getCorrectionByPackageName(@NonNull String);
method public android.util.Pair<float[],float[]> getCurve();
+ method public float getShortTermModelLowerLuxMultiplier();
+ method public long getShortTermModelTimeout();
+ method public float getShortTermModelUpperLuxMultiplier();
method public boolean shouldCollectColorSamples();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.hardware.display.BrightnessConfiguration> CREATOR;
+ field public static final long SHORT_TERM_TIMEOUT_UNSET = -1L; // 0xffffffffffffffffL
}
public static class BrightnessConfiguration.Builder {
@@ -2396,6 +2431,9 @@ package android.hardware.display {
method public int getMaxCorrectionsByCategory();
method public int getMaxCorrectionsByPackageName();
method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setDescription(@Nullable String);
+ method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShortTermModelLowerLuxMultiplier(@FloatRange(from=0.0f) float);
+ method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShortTermModelTimeout(long);
+ method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShortTermModelUpperLuxMultiplier(@FloatRange(from=0.0f) float);
method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShouldCollectColorSamples(boolean);
}
@@ -4015,6 +4053,7 @@ package android.media {
field public static final int AUDIOFOCUS_FLAG_DELAY_OK = 1; // 0x1
field public static final int AUDIOFOCUS_FLAG_LOCK = 4; // 0x4
field public static final int AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS = 2; // 0x2
+ field @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static final int STREAM_ASSISTANT = 11; // 0xb
field public static final int SUCCESS = 0; // 0x0
}
@@ -4036,6 +4075,7 @@ package android.media {
method public android.media.PlayerProxy getPlayerProxy();
method public int getPlayerState();
method public int getPlayerType();
+ method public boolean isActive();
field public static final int PLAYER_STATE_IDLE = 1; // 0x1
field public static final int PLAYER_STATE_PAUSED = 3; // 0x3
field public static final int PLAYER_STATE_RELEASED = 0; // 0x0
@@ -4481,6 +4521,24 @@ package android.media.tv {
}
+package android.media.tv.tuner {
+
+ public abstract class FrontendSettings {
+ method public final int getFrequency();
+ method public abstract int getType();
+ }
+
+ public final class Tuner implements java.lang.AutoCloseable {
+ ctor public Tuner(@NonNull android.content.Context);
+ method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public android.media.tv.tuner.Tuner.Descrambler openDescrambler();
+ method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int tune(@NonNull android.media.tv.tuner.FrontendSettings);
+ }
+
+ public class Tuner.Descrambler {
+ }
+
+}
+
package android.metrics {
public class LogMaker {
@@ -4656,12 +4714,20 @@ package android.net {
ctor public LinkProperties(@Nullable android.net.LinkProperties);
method public boolean addDnsServer(@NonNull java.net.InetAddress);
method public boolean addLinkAddress(@NonNull android.net.LinkAddress);
+ method public boolean addPcscfServer(@NonNull java.net.InetAddress);
+ method @NonNull public java.util.List<java.net.InetAddress> getAddresses();
+ method @NonNull public java.util.List<java.lang.String> getAllInterfaceNames();
+ method @NonNull public java.util.List<android.net.LinkAddress> getAllLinkAddresses();
+ method @NonNull public java.util.List<android.net.RouteInfo> getAllRoutes();
method @NonNull public java.util.List<java.net.InetAddress> getPcscfServers();
method @Nullable public String getTcpBufferSizes();
method @NonNull public java.util.List<java.net.InetAddress> getValidatedPrivateDnsServers();
method public boolean hasGlobalIpv6Address();
method public boolean hasIpv4Address();
+ method public boolean hasIpv4DefaultRoute();
+ method public boolean hasIpv4DnsServer();
method public boolean hasIpv6DefaultRoute();
+ method public boolean hasIpv6DnsServer();
method public boolean isIpv4Provisioned();
method public boolean isIpv6Provisioned();
method public boolean isProvisioned();
@@ -4676,6 +4742,13 @@ package android.net {
method public void setValidatedPrivateDnsServers(@NonNull java.util.Collection<java.net.InetAddress>);
}
+ public final class MatchAllNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable {
+ ctor public MatchAllNetworkSpecifier();
+ method public int describeContents();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.MatchAllNetworkSpecifier> CREATOR;
+ }
+
public class Network implements android.os.Parcelable {
ctor public Network(@NonNull android.net.Network);
method @NonNull public android.net.Network getPrivateDnsBypassingCopy();
@@ -4685,6 +4758,8 @@ package android.net {
public final class NetworkCapabilities implements android.os.Parcelable {
method @NonNull public int[] getTransportTypes();
method public boolean satisfiedByNetworkCapabilities(@Nullable android.net.NetworkCapabilities);
+ method @NonNull public android.net.NetworkCapabilities setSSID(@Nullable String);
+ method @NonNull public android.net.NetworkCapabilities setTransportInfo(@NonNull android.net.TransportInfo);
field public static final int NET_CAPABILITY_OEM_PAID = 22; // 0x16
field public static final int NET_CAPABILITY_PARTIAL_CONNECTIVITY = 24; // 0x18
}
@@ -4800,6 +4875,14 @@ package android.net {
method @NonNull public android.net.StaticIpConfiguration.Builder setIpAddress(@Nullable android.net.LinkAddress);
}
+ public final class StringNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable {
+ ctor public StringNetworkSpecifier(@NonNull String);
+ method public int describeContents();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.StringNetworkSpecifier> CREATOR;
+ field @NonNull public final String specifier;
+ }
+
public class TrafficStats {
method public static void setThreadStatsTagApp();
method public static void setThreadStatsTagBackup();
@@ -5338,19 +5421,14 @@ package android.net.wifi {
ctor public EasyConnectStatusCallback();
method public abstract void onConfiguratorSuccess(int);
method public abstract void onEnrolleeSuccess(int);
- method public abstract void onFailure(int);
+ method public void onFailure(int);
+ method public void onFailure(int, @Nullable String, @NonNull android.util.SparseArray<int[]>, @NonNull int[]);
method public abstract void onProgress(int);
- field public static final int EASY_CONNECT_EVENT_FAILURE_AUTHENTICATION = -2; // 0xfffffffe
- field public static final int EASY_CONNECT_EVENT_FAILURE_BUSY = -5; // 0xfffffffb
- field public static final int EASY_CONNECT_EVENT_FAILURE_CONFIGURATION = -4; // 0xfffffffc
- field public static final int EASY_CONNECT_EVENT_FAILURE_GENERIC = -7; // 0xfffffff9
- field public static final int EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK = -9; // 0xfffffff7
- field public static final int EASY_CONNECT_EVENT_FAILURE_INVALID_URI = -1; // 0xffffffff
- field public static final int EASY_CONNECT_EVENT_FAILURE_NOT_COMPATIBLE = -3; // 0xfffffffd
- field public static final int EASY_CONNECT_EVENT_FAILURE_NOT_SUPPORTED = -8; // 0xfffffff8
- field public static final int EASY_CONNECT_EVENT_FAILURE_TIMEOUT = -6; // 0xfffffffa
field public static final int EASY_CONNECT_EVENT_PROGRESS_AUTHENTICATION_SUCCESS = 0; // 0x0
+ field public static final int EASY_CONNECT_EVENT_PROGRESS_CONFIGURATION_ACCEPTED = 3; // 0x3
+ field public static final int EASY_CONNECT_EVENT_PROGRESS_CONFIGURATION_SENT_WAITING_RESPONSE = 2; // 0x2
field public static final int EASY_CONNECT_EVENT_PROGRESS_RESPONSE_PENDING = 1; // 0x1
+ field public static final int EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_APPLIED = 1; // 0x1
field public static final int EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_SENT = 0; // 0x0
}
@@ -5546,19 +5624,36 @@ package android.net.wifi {
field @Deprecated public byte id;
}
+ public class ScanResult implements android.os.Parcelable {
+ field public static final int KEY_MGMT_WAPI_CERT = 14; // 0xe
+ field public static final int KEY_MGMT_WAPI_PSK = 13; // 0xd
+ }
+
+ public final class SoftApCapability implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getMaxSupportedClients();
+ method public boolean isFeatureSupported(int);
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.SoftApCapability> CREATOR;
+ field public static final int SOFTAP_FEATURE_ACS_OFFLOAD = 1; // 0x1
+ field public static final int SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT = 2; // 0x2
+ }
+
public final class SoftApConfiguration implements android.os.Parcelable {
method public int describeContents();
method public int getBand();
method @Nullable public android.net.MacAddress getBssid();
method public int getChannel();
+ method public int getMaxNumberOfClients();
method public int getSecurityType();
method @Nullable public String getSsid();
method @Nullable public String getWpa2Passphrase();
method public boolean isHiddenSsid();
method public void writeToParcel(@NonNull android.os.Parcel, int);
- field public static final int BAND_2GHZ = 0; // 0x0
- field public static final int BAND_5GHZ = 1; // 0x1
- field public static final int BAND_ANY = -1; // 0xffffffff
+ field public static final int BAND_2GHZ = 1; // 0x1
+ field public static final int BAND_5GHZ = 2; // 0x2
+ field public static final int BAND_6GHZ = 4; // 0x4
+ field public static final int BAND_ANY = 7; // 0x7
field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.SoftApConfiguration> CREATOR;
field public static final int SECURITY_TYPE_OPEN = 0; // 0x0
field public static final int SECURITY_TYPE_WPA2_PSK = 1; // 0x1
@@ -5570,8 +5665,9 @@ package android.net.wifi {
method @NonNull public android.net.wifi.SoftApConfiguration build();
method @NonNull public android.net.wifi.SoftApConfiguration.Builder setBand(int);
method @NonNull public android.net.wifi.SoftApConfiguration.Builder setBssid(@Nullable android.net.MacAddress);
- method @NonNull public android.net.wifi.SoftApConfiguration.Builder setChannel(int);
+ method @NonNull public android.net.wifi.SoftApConfiguration.Builder setChannel(int, int);
method @NonNull public android.net.wifi.SoftApConfiguration.Builder setHiddenSsid(boolean);
+ method @NonNull public android.net.wifi.SoftApConfiguration.Builder setMaxNumberOfClients(int);
method @NonNull public android.net.wifi.SoftApConfiguration.Builder setSsid(@Nullable String);
method @NonNull public android.net.wifi.SoftApConfiguration.Builder setWpa2Passphrase(@Nullable String);
}
@@ -5601,6 +5697,7 @@ package android.net.wifi {
@Deprecated public class WifiConfiguration implements android.os.Parcelable {
method @Deprecated public int getAuthType();
method @Deprecated @NonNull public android.net.IpConfiguration.IpAssignment getIpAssignment();
+ method @Deprecated @NonNull public android.net.IpConfiguration getIpConfiguration();
method @Deprecated @NonNull public android.net.wifi.WifiConfiguration.NetworkSelectionStatus getNetworkSelectionStatus();
method @Deprecated @NonNull public String getPrintableSsid();
method @Deprecated @NonNull public android.net.IpConfiguration.ProxySettings getProxySettings();
@@ -5643,6 +5740,8 @@ package android.net.wifi {
}
@Deprecated public static class WifiConfiguration.KeyMgmt {
+ field @Deprecated public static final int WAPI_CERT = 14; // 0xe
+ field @Deprecated public static final int WAPI_PSK = 13; // 0xd
field @Deprecated public static final int WPA2_PSK = 4; // 0x4
}
@@ -5679,10 +5778,12 @@ package android.net.wifi {
method @NonNull public String getCaPath();
method @NonNull public String getClientCertificateAlias();
method public int getOcsp();
+ method @Nullable public String getWapiCertSuite();
method public void setCaCertificateAliases(@Nullable String[]);
method public void setCaPath(@Nullable String);
method public void setClientCertificateAlias(@Nullable String);
method public void setOcsp(int);
+ method public void setWapiCertSuite(@Nullable String);
field public static final int OCSP_NONE = 0; // 0x0
field public static final int OCSP_REQUEST_CERT_STATUS = 1; // 0x1
field public static final int OCSP_REQUIRE_ALL_NON_TRUSTED_CERTS_STATUS = 3; // 0x3
@@ -5801,6 +5902,7 @@ package android.net.wifi {
field public static final int PASSPOINT_ROAMING_NETWORK = 1; // 0x1
field public static final int SAP_START_FAILURE_GENERAL = 0; // 0x0
field public static final int SAP_START_FAILURE_NO_CHANNEL = 1; // 0x1
+ field public static final int SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION = 2; // 0x2
field public static final String WIFI_AP_STATE_CHANGED_ACTION = "android.net.wifi.WIFI_AP_STATE_CHANGED";
field public static final int WIFI_AP_STATE_DISABLED = 11; // 0xb
field public static final int WIFI_AP_STATE_DISABLING = 10; // 0xa
@@ -5839,6 +5941,7 @@ package android.net.wifi {
}
public static interface WifiManager.SoftApCallback {
+ method public default void onCapabilityChanged(@NonNull android.net.wifi.SoftApCapability);
method public default void onConnectedClientsChanged(@NonNull java.util.List<android.net.wifi.WifiClient>);
method public default void onInfoChanged(@NonNull android.net.wifi.SoftApInfo);
method public default void onStateChanged(int, int);
@@ -6194,6 +6297,130 @@ package android.net.wifi.rtt {
}
+package android.net.wifi.wificond {
+
+ public final class NativeScanResult implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public byte[] getBssid();
+ method @NonNull public java.util.BitSet getCapabilities();
+ method public int getFrequencyMhz();
+ method @NonNull public byte[] getInformationElements();
+ method @NonNull public java.util.List<android.net.wifi.wificond.RadioChainInfo> getRadioChainInfos();
+ method public int getSignalMbm();
+ method @NonNull public byte[] getSsid();
+ method public long getTsf();
+ method public boolean isAssociated();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.wificond.NativeScanResult> CREATOR;
+ }
+
+ public final class NativeWifiClient implements android.os.Parcelable {
+ method public int describeContents();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.wificond.NativeWifiClient> CREATOR;
+ field @NonNull public final byte[] macAddress;
+ }
+
+ public final class PnoNetwork implements android.os.Parcelable {
+ ctor public PnoNetwork();
+ method public int describeContents();
+ method @NonNull public int[] getFrequenciesMhz();
+ method @NonNull public byte[] getSsid();
+ method public boolean isHidden();
+ method public void setFrequenciesMhz(@NonNull int[]);
+ method public void setHidden(boolean);
+ method public void setSsid(@NonNull byte[]);
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.wificond.PnoNetwork> CREATOR;
+ }
+
+ public final class PnoSettings implements android.os.Parcelable {
+ ctor public PnoSettings();
+ method public int describeContents();
+ method public int getIntervalMillis();
+ method public int getMin2gRssiDbm();
+ method public int getMin5gRssiDbm();
+ method public int getMin6gRssiDbm();
+ method @NonNull public java.util.List<android.net.wifi.wificond.PnoNetwork> getPnoNetworks();
+ method public void setIntervalMillis(int);
+ method public void setMin2gRssiDbm(int);
+ method public void setMin5gRssiDbm(int);
+ method public void setMin6gRssiDbm(int);
+ method public void setPnoNetworks(@NonNull java.util.List<android.net.wifi.wificond.PnoNetwork>);
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.wificond.PnoSettings> CREATOR;
+ }
+
+ public final class RadioChainInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getChainId();
+ method public int getLevelDbm();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.wificond.RadioChainInfo> CREATOR;
+ }
+
+ public class WifiCondManager {
+ method public void abortScan(@NonNull String);
+ method public void enableVerboseLogging(boolean);
+ method @NonNull public int[] getChannelsMhzForBand(int);
+ method @NonNull public java.util.List<android.net.wifi.wificond.NativeScanResult> getScanResults(@NonNull String, int);
+ method @Nullable public android.net.wifi.wificond.WifiCondManager.TxPacketCounters getTxPacketCounters(@NonNull String);
+ method public boolean initialize(@NonNull Runnable);
+ method public boolean registerApCallback(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.wificond.WifiCondManager.SoftApCallback);
+ method public void sendMgmtFrame(@NonNull String, @NonNull byte[], int, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.wificond.WifiCondManager.SendMgmtFrameCallback);
+ method public boolean setupInterfaceForClientMode(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.wificond.WifiCondManager.ScanEventCallback, @NonNull android.net.wifi.wificond.WifiCondManager.ScanEventCallback);
+ method public boolean setupInterfaceForSoftApMode(@NonNull String);
+ method @Nullable public android.net.wifi.wificond.WifiCondManager.SignalPollResult signalPoll(@NonNull String);
+ method public boolean startPnoScan(@NonNull String, @NonNull android.net.wifi.wificond.PnoSettings, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.wificond.WifiCondManager.PnoScanRequestCallback);
+ method public boolean startScan(@NonNull String, int, @Nullable java.util.Set<java.lang.Integer>, @Nullable java.util.List<byte[]>);
+ method public boolean stopPnoScan(@NonNull String);
+ method public boolean tearDownClientInterface(@NonNull String);
+ method public boolean tearDownInterfaces();
+ method public boolean tearDownSoftApInterface(@NonNull String);
+ field public static final int SCAN_TYPE_PNO_SCAN = 1; // 0x1
+ field public static final int SCAN_TYPE_SINGLE_SCAN = 0; // 0x0
+ field public static final int SEND_MGMT_FRAME_ERROR_ALREADY_STARTED = 5; // 0x5
+ field public static final int SEND_MGMT_FRAME_ERROR_MCS_UNSUPPORTED = 2; // 0x2
+ field public static final int SEND_MGMT_FRAME_ERROR_NO_ACK = 3; // 0x3
+ field public static final int SEND_MGMT_FRAME_ERROR_TIMEOUT = 4; // 0x4
+ field public static final int SEND_MGMT_FRAME_ERROR_UNKNOWN = 1; // 0x1
+ }
+
+ public static interface WifiCondManager.PnoScanRequestCallback {
+ method public void onPnoRequestFailed();
+ method public void onPnoRequestSucceeded();
+ }
+
+ public static interface WifiCondManager.ScanEventCallback {
+ method public void onScanFailed();
+ method public void onScanResultReady();
+ }
+
+ public static interface WifiCondManager.SendMgmtFrameCallback {
+ method public void onAck(int);
+ method public void onFailure(int);
+ }
+
+ public static class WifiCondManager.SignalPollResult {
+ field public final int associationFrequencyMHz;
+ field public final int currentRssiDbm;
+ field public final int rxBitrateMbps;
+ field public final int txBitrateMbps;
+ }
+
+ public static interface WifiCondManager.SoftApCallback {
+ method public void onConnectedClientsChanged(@NonNull android.net.wifi.wificond.NativeWifiClient, boolean);
+ method public void onFailure();
+ method public void onSoftApChannelSwitched(int, int);
+ }
+
+ public static class WifiCondManager.TxPacketCounters {
+ field public final int txPacketFailed;
+ field public final int txPacketSucceeded;
+ }
+
+}
+
package android.nfc {
public final class NfcAdapter {
@@ -6609,6 +6836,7 @@ package android.os {
method @RequiresPermission(anyOf={android.Manifest.permission.DEVICE_POWER, android.Manifest.permission.USER_ACTIVITY}) public void userActivity(long, int, int);
field public static final int POWER_SAVE_MODE_TRIGGER_DYNAMIC = 1; // 0x1
field public static final int POWER_SAVE_MODE_TRIGGER_PERCENTAGE = 0; // 0x0
+ field public static final String REBOOT_USERSPACE = "userspace";
field public static final int USER_ACTIVITY_EVENT_ACCESSIBILITY = 3; // 0x3
field public static final int USER_ACTIVITY_EVENT_BUTTON = 1; // 0x1
field public static final int USER_ACTIVITY_EVENT_OTHER = 0; // 0x0
@@ -6802,6 +7030,7 @@ package android.os {
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isRestrictedProfile();
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isRestrictedProfile(@NonNull android.os.UserHandle);
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isSameProfileGroup(@NonNull android.os.UserHandle, @NonNull android.os.UserHandle);
+ method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.GET_ACCOUNTS_PRIVILEGED}) public boolean isUserNameSet();
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}) public boolean isUserUnlockingOrUnlocked(@NonNull android.os.UserHandle);
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean removeUser(@NonNull android.os.UserHandle);
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void setUserIcon(@NonNull android.graphics.Bitmap);
@@ -7001,6 +7230,7 @@ package android.permission {
method @BinderThread public abstract void onGetPermissionUsages(boolean, long, @NonNull java.util.function.Consumer<java.util.List<android.permission.RuntimePermissionUsageInfo>>);
method @BinderThread public abstract void onGetRuntimePermissionsBackup(@NonNull android.os.UserHandle, @NonNull java.io.OutputStream, @NonNull Runnable);
method @BinderThread public abstract void onGrantOrUpgradeDefaultRuntimePermissions(@NonNull Runnable);
+ method @BinderThread public void onOneTimePermissionSessionTimeout(@NonNull String);
method @Deprecated @BinderThread public void onRestoreDelayedRuntimePermissionsBackup(@NonNull String, @NonNull android.os.UserHandle, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @Deprecated @BinderThread public void onRestoreRuntimePermissionsBackup(@NonNull android.os.UserHandle, @NonNull java.io.InputStream, @NonNull Runnable);
method @BinderThread public abstract void onRevokeRuntimePermission(@NonNull String, @NonNull String, @NonNull Runnable);
@@ -7017,6 +7247,8 @@ package android.permission {
method @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS) public void grantDefaultPermissionsToLuiApp(@NonNull String, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS) public void revokeDefaultPermissionsFromLuiApps(@NonNull String[], @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @RequiresPermission(android.Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY) public void setRuntimePermissionsVersion(@IntRange(from=0) int);
+ method @RequiresPermission(allOf={android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void startOneTimePermissionSession(@NonNull String, long, int, int);
+ method @RequiresPermission(allOf={android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void stopOneTimePermissionSession(@NonNull String);
}
public static final class PermissionManager.SplitPermissionInfo {
@@ -7258,8 +7490,12 @@ package android.provider {
}
public final class MediaStore {
+ method @NonNull public static android.net.Uri rewriteToLegacy(@NonNull android.net.Uri);
method @NonNull public static android.net.Uri scanFile(@NonNull android.content.ContentResolver, @NonNull java.io.File);
method public static void scanVolume(@NonNull android.content.ContentResolver, @NonNull String);
+ method public static void waitForIdle(@NonNull android.content.ContentResolver);
+ field public static final String AUTHORITY_LEGACY = "media_legacy";
+ field @NonNull public static final android.net.Uri AUTHORITY_LEGACY_URI;
}
public abstract class SearchIndexableData {
@@ -7403,6 +7639,7 @@ package android.provider {
field public static final String INSTALL_CARRIER_APP_NOTIFICATION_SLEEP_MILLIS = "install_carrier_app_notification_sleep_millis";
field public static final String OTA_DISABLE_AUTOMATIC_UPDATE = "ota_disable_automatic_update";
field public static final String REQUIRE_PASSWORD_TO_DECRYPT = "require_password_to_decrypt";
+ field public static final String TETHER_SUPPORTED = "tether_supported";
field public static final String THEATER_MODE_ON = "theater_mode_on";
field public static final String WEBVIEW_MULTIPROCESS = "webview_multiprocess";
field public static final String WIFI_BADGING_THRESHOLDS = "wifi_badging_thresholds";
@@ -7774,6 +8011,7 @@ package android.service.autofill.augmented {
method @NonNull public android.content.ComponentName getActivityComponent();
method @NonNull public android.view.autofill.AutofillId getFocusedId();
method @NonNull public android.view.autofill.AutofillValue getFocusedValue();
+ method @Nullable public android.view.inputmethod.InlineSuggestionsRequest getInlineSuggestionsRequest();
method @Nullable public android.service.autofill.augmented.PresentationParams getPresentationParams();
method public int getTaskId();
}
@@ -7784,7 +8022,8 @@ package android.service.autofill.augmented {
public static final class FillResponse.Builder {
ctor public FillResponse.Builder();
method @NonNull public android.service.autofill.augmented.FillResponse build();
- method @NonNull public android.service.autofill.augmented.FillResponse.Builder setFillWindow(@NonNull android.service.autofill.augmented.FillWindow);
+ method @NonNull public android.service.autofill.augmented.FillResponse.Builder setFillWindow(@Nullable android.service.autofill.augmented.FillWindow);
+ method @NonNull public android.service.autofill.augmented.FillResponse.Builder setInlineSuggestions(@Nullable java.util.List<android.service.autofill.Dataset>);
}
public final class FillWindow implements java.lang.AutoCloseable {
@@ -7890,6 +8129,14 @@ package android.service.contentsuggestions {
}
+package android.service.dataloader {
+
+ public abstract class DataLoaderService extends android.app.Service {
+ ctor public DataLoaderService();
+ }
+
+}
+
package android.service.euicc {
public final class DownloadSubscriptionResult implements android.os.Parcelable {
@@ -8691,10 +8938,17 @@ package android.telephony {
}
public class CarrierConfigManager {
+ method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getDefaultCarrierServicePackageName();
method @NonNull public static android.os.PersistableBundle getDefaultConfig();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void overrideConfig(int, @Nullable android.os.PersistableBundle);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void updateConfigForPhoneId(int, String);
field public static final String KEY_CARRIER_SETUP_APP_STRING = "carrier_setup_app_string";
+ field public static final String KEY_SUPPORT_CDMA_1X_VOICE_CALLS_BOOL = "support_cdma_1x_voice_calls_bool";
+ }
+
+ public static final class CarrierConfigManager.Wifi {
+ field public static final String KEY_HOTSPOT_MAX_CLIENT_COUNT = "wifi.hotspot_maximum_client_count";
+ field public static final String KEY_PREFIX = "wifi.";
}
public final class CarrierRestrictionRules implements android.os.Parcelable {
@@ -8726,6 +8980,13 @@ package android.telephony {
public class CbGeoUtils {
}
+ public static class CbGeoUtils.Circle implements android.telephony.CbGeoUtils.Geometry {
+ ctor public CbGeoUtils.Circle(@NonNull android.telephony.CbGeoUtils.LatLng, double);
+ method public boolean contains(@NonNull android.telephony.CbGeoUtils.LatLng);
+ method @NonNull public android.telephony.CbGeoUtils.LatLng getCenter();
+ method public double getRadius();
+ }
+
public static interface CbGeoUtils.Geometry {
method public boolean contains(@NonNull android.telephony.CbGeoUtils.LatLng);
}
@@ -8738,6 +8999,12 @@ package android.telephony {
field public final double lng;
}
+ public static class CbGeoUtils.Polygon implements android.telephony.CbGeoUtils.Geometry {
+ ctor public CbGeoUtils.Polygon(@NonNull java.util.List<android.telephony.CbGeoUtils.LatLng>);
+ method public boolean contains(@NonNull android.telephony.CbGeoUtils.LatLng);
+ method @NonNull public java.util.List<android.telephony.CbGeoUtils.LatLng> getVertices();
+ }
+
public class CellBroadcastIntents {
method public static void sendOrderedBroadcastForBackgroundReceivers(@NonNull android.content.Context, @Nullable android.os.UserHandle, @NonNull android.content.Intent, @Nullable String, @Nullable String, @Nullable android.content.BroadcastReceiver, @Nullable android.os.Handler, int, @Nullable String, @Nullable android.os.Bundle);
}
@@ -8751,6 +9018,34 @@ package android.telephony {
field public static final String CELL_BROADCAST_SERVICE_INTERFACE = "android.telephony.CellBroadcastService";
}
+ public abstract class CellIdentity implements android.os.Parcelable {
+ method @NonNull public abstract android.telephony.CellLocation asCellLocation();
+ }
+
+ public final class CellIdentityCdma extends android.telephony.CellIdentity {
+ method @NonNull public android.telephony.cdma.CdmaCellLocation asCellLocation();
+ }
+
+ public final class CellIdentityGsm extends android.telephony.CellIdentity {
+ method @NonNull public android.telephony.gsm.GsmCellLocation asCellLocation();
+ }
+
+ public final class CellIdentityLte extends android.telephony.CellIdentity {
+ method @NonNull public android.telephony.gsm.GsmCellLocation asCellLocation();
+ }
+
+ public final class CellIdentityNr extends android.telephony.CellIdentity {
+ method @NonNull public android.telephony.CellLocation asCellLocation();
+ }
+
+ public final class CellIdentityTdscdma extends android.telephony.CellIdentity {
+ method @NonNull public android.telephony.gsm.GsmCellLocation asCellLocation();
+ }
+
+ public final class CellIdentityWcdma extends android.telephony.CellIdentity {
+ method @NonNull public android.telephony.gsm.GsmCellLocation asCellLocation();
+ }
+
public final class DataFailCause {
field public static final int ACCESS_ATTEMPT_ALREADY_IN_PROGRESS = 2219; // 0x8ab
field public static final int ACCESS_BLOCK = 2087; // 0x827
@@ -9330,8 +9625,6 @@ package android.telephony {
public class PhoneStateListener {
method public void onCallAttributesChanged(@NonNull android.telephony.CallAttributes);
- method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onCallDisconnectCauseChanged(int, int);
- method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onImsCallDisconnectCauseChanged(@NonNull android.telephony.ims.ImsReasonInfo);
method public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber);
method public void onOutgoingEmergencySms(@NonNull android.telephony.emergency.EmergencyNumber);
method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onPreciseCallStateChanged(@NonNull android.telephony.PreciseCallState);
@@ -9339,8 +9632,6 @@ package android.telephony {
method public void onSrvccStateChanged(int);
method public void onVoiceActivationStateChanged(int);
field public static final int LISTEN_CALL_ATTRIBUTES_CHANGED = 67108864; // 0x4000000
- field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_CALL_DISCONNECT_CAUSES = 33554432; // 0x2000000
- field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_IMS_CALL_DISCONNECT_CAUSES = 134217728; // 0x8000000
field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_CALL = 268435456; // 0x10000000
field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_SMS = 536870912; // 0x20000000
field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_PRECISE_CALL_STATE = 2048; // 0x800
@@ -9350,6 +9641,7 @@ package android.telephony {
}
public final class PreciseCallState implements android.os.Parcelable {
+ ctor public PreciseCallState(int, int, int, int, int);
method public int describeContents();
method public int getBackgroundCallState();
method public int getForegroundCallState();
@@ -9369,6 +9661,7 @@ package android.telephony {
}
public final class PreciseDataConnectionState implements android.os.Parcelable {
+ ctor public PreciseDataConnectionState(int, int, int, @NonNull String, @Nullable android.net.LinkProperties, int, @Nullable android.telephony.data.ApnSetting);
method @Deprecated @NonNull public String getDataConnectionApn();
method @Deprecated public int getDataConnectionApnTypeBitMask();
method @Deprecated public int getDataConnectionFailCause();
@@ -9475,6 +9768,8 @@ package android.telephony {
}
public class ServiceState implements android.os.Parcelable {
+ method @NonNull public android.telephony.ServiceState createLocationInfoSanitizedCopy(boolean);
+ method public int getDataRegistrationState();
method @Nullable public android.telephony.NetworkRegistrationInfo getNetworkRegistrationInfo(int, int);
method @NonNull public java.util.List<android.telephony.NetworkRegistrationInfo> getNetworkRegistrationInfoList();
method @NonNull public java.util.List<android.telephony.NetworkRegistrationInfo> getNetworkRegistrationInfoListForDomain(int);
@@ -9611,8 +9906,10 @@ package android.telephony {
}
public final class SmsManager {
+ method @RequiresPermission(android.Manifest.permission.ACCESS_MESSAGES_ON_ICC) public boolean deleteMessageFromIcc(int);
method public boolean disableCellBroadcastRange(int, int, int);
method public boolean enableCellBroadcastRange(int, int, int);
+ method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_MESSAGES_ON_ICC) public java.util.List<android.telephony.SmsMessage> getMessagesFromIcc();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSmsCapacityOnIcc();
method public void sendMultipartTextMessage(@NonNull String, @NonNull String, @NonNull java.util.List<java.lang.String>, @Nullable java.util.List<android.app.PendingIntent>, @Nullable java.util.List<android.app.PendingIntent>, @NonNull String);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void sendMultipartTextMessageWithoutPersisting(String, String, java.util.List<java.lang.String>, java.util.List<android.app.PendingIntent>, java.util.List<android.app.PendingIntent>);
@@ -9627,6 +9924,7 @@ package android.telephony {
public class SubscriptionManager {
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean canDisablePhysicalSubscription();
+ method public boolean canManageSubscription(@Nullable android.telephony.SubscriptionInfo, @Nullable String);
method public java.util.List<android.telephony.SubscriptionInfo> getAvailableSubscriptionInfoList();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getEnabledSubscriptionId(int);
method @NonNull public static android.content.res.Resources getResourcesForSubId(@NonNull android.content.Context, int);
@@ -9636,8 +9934,12 @@ package android.telephony {
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDefaultDataSubId(int);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDefaultSmsSubId(int);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDefaultVoiceSubscriptionId(int);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setDisplayName(@Nullable String, int, int);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setIconTint(@ColorInt int, int);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setPreferredDataSubscriptionId(int, boolean, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setSubscriptionEnabled(int, boolean);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUiccApplicationsEnabled(boolean, int);
+ field @RequiresPermission(android.Manifest.permission.MANAGE_SUBSCRIPTION_PLANS) public static final String ACTION_SUBSCRIPTION_PLANS_CHANGED = "android.telephony.action.SUBSCRIPTION_PLANS_CHANGED";
field @NonNull public static final android.net.Uri ADVANCED_CALLING_ENABLED_CONTENT_URI;
field public static final int PROFILE_CLASS_DEFAULT = -1; // 0xffffffff
field public static final int PROFILE_CLASS_OPERATIONAL = 2; // 0x2
@@ -9719,6 +10021,7 @@ package android.telephony {
method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Map<java.lang.Integer,java.lang.Integer> getLogicalToPhysicalSlotMapping();
method public int getMaxNumberOfSimultaneouslyActiveSims();
method public static long getMaxNumberVerificationTimeoutMillis();
+ method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String[] getMergedImsisFromGroup();
method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getNetworkCountryIso(int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getPreferredNetworkTypeBitmask();
method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public int getRadioPowerState();
@@ -9739,7 +10042,9 @@ package android.telephony {
method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String iccTransmitApduBasicChannelBySlot(int, int, int, int, int, int, @Nullable String);
method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String iccTransmitApduLogicalChannelBySlot(int, int, int, int, int, int, int, @Nullable String);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAnyRadioPoweredOn();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isApnMetered(int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isApplicationOnUicc(int);
+ method public boolean isCurrentSimOperator(@NonNull String, int, @Nullable String);
method public boolean isDataConnectivityPossible();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isDataEnabledForApn(int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isEmergencyAssistanceEnabled();
@@ -9792,6 +10097,10 @@ package android.telephony {
method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void updateTestOtaEmergencyNumberDbFilePath(@NonNull String);
field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final String ACTION_ANOMALY_REPORTED = "android.telephony.action.ANOMALY_REPORTED";
field public static final String ACTION_EMERGENCY_ASSISTANCE = "android.telephony.action.EMERGENCY_ASSISTANCE";
+ field public static final String ACTION_EMERGENCY_CALLBACK_MODE_CHANGED = "android.intent.action.EMERGENCY_CALLBACK_MODE_CHANGED";
+ field public static final String ACTION_EMERGENCY_CALL_STATE_CHANGED = "android.intent.action.EMERGENCY_CALL_STATE_CHANGED";
+ field public static final String ACTION_NETWORK_SET_TIME = "android.telephony.action.NETWORK_SET_TIME";
+ field public static final String ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS = "android.telephony.action.SHOW_NOTICE_ECM_BLOCK_OTHERS";
field public static final String ACTION_SIM_APPLICATION_STATE_CHANGED = "android.telephony.action.SIM_APPLICATION_STATE_CHANGED";
field public static final String ACTION_SIM_CARD_STATE_CHANGED = "android.telephony.action.SIM_CARD_STATE_CHANGED";
field public static final String ACTION_SIM_SLOT_STATUS_CHANGED = "android.telephony.action.SIM_SLOT_STATUS_CHANGED";
diff --git a/api/system-lint-baseline.txt b/api/system-lint-baseline.txt
index 9a6357572d36..da0aae0f14ad 100644
--- a/api/system-lint-baseline.txt
+++ b/api/system-lint-baseline.txt
@@ -24,6 +24,11 @@ ExecutorRegistration: android.net.wifi.p2p.WifiP2pManager#setWfdInfo(android.net
ExecutorRegistration: android.net.wifi.p2p.WifiP2pManager#setWifiP2pChannels(android.net.wifi.p2p.WifiP2pManager.Channel, int, int, android.net.wifi.p2p.WifiP2pManager.ActionListener):
Registration methods should have overload that accepts delivery Executor: `setWifiP2pChannels`
+HeavyBitSet: android.net.wifi.wificond.NativeScanResult#getCapabilities():
+ Type must not be heavy BitSet (method android.net.wifi.wificond.NativeScanResult.getCapabilities())
+PairedRegistration: android.net.wifi.wificond.WifiCondManager#registerApCallback(String, java.util.concurrent.Executor, android.net.wifi.wificond.WifiCondManager.SoftApCallback):
+ Found registerApCallback but not unregisterApCallback in android.net.wifi.wificond.WifiCondManager
+
GenericException: android.app.prediction.AppPredictor#finalize():
diff --git a/api/test-current.txt b/api/test-current.txt
index 219258ef50b0..e7153e61647f 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -12,6 +12,7 @@ package android {
field public static final String CONFIGURE_DISPLAY_BRIGHTNESS = "android.permission.CONFIGURE_DISPLAY_BRIGHTNESS";
field public static final String FORCE_STOP_PACKAGES = "android.permission.FORCE_STOP_PACKAGES";
field public static final String MANAGE_ACTIVITY_STACKS = "android.permission.MANAGE_ACTIVITY_STACKS";
+ field public static final String MANAGE_CRATES = "android.permission.MANAGE_CRATES";
field public static final String MANAGE_ROLLBACKS = "android.permission.MANAGE_ROLLBACKS";
field public static final String READ_CELL_BROADCASTS = "android.permission.READ_CELL_BROADCASTS";
field public static final String REMOVE_TASKS = "android.permission.REMOVE_TASKS";
@@ -104,6 +105,7 @@ package android.app {
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public boolean moveTopActivityToPinnedStack(int, android.graphics.Rect);
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void removeStacksInWindowingModes(int[]) throws java.lang.SecurityException;
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void removeStacksWithActivityTypes(int[]) throws java.lang.SecurityException;
+ method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void requestPictureInPictureMode(@NonNull android.os.IBinder);
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void resizeDockedStack(android.graphics.Rect, android.graphics.Rect);
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void resizePinnedStack(int, android.graphics.Rect, boolean);
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void resizeTask(int, android.graphics.Rect);
@@ -157,6 +159,7 @@ package android.app {
method @RequiresPermission("android.permission.MANAGE_APPOPS") public void getHistoricalOpsFromDiskRaw(@NonNull android.app.AppOpsManager.HistoricalOpsRequest, @Nullable java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.AppOpsManager.HistoricalOps>);
method public static int getNumOps();
method public static String[] getOpStrs();
+ method @NonNull @RequiresPermission("android.permission.GET_APP_OPS_STATS") public java.util.List<android.app.AppOpsManager.PackageOps> getOpsForPackage(int, @NonNull String, @Nullable java.lang.String...);
method public boolean isOperationActive(int, int, String);
method @RequiresPermission("android.permission.MANAGE_APPOPS") public void offsetHistory(long);
method public static int opToDefaultMode(@NonNull String);
@@ -307,15 +310,20 @@ package android.app {
public static final class AppOpsManager.OpEntry implements android.os.Parcelable {
method public int describeContents();
- method public long getDuration();
+ method @Deprecated public long getDuration();
method @NonNull public java.util.Map<java.lang.String,android.app.AppOpsManager.OpFeatureEntry> getFeatures();
method public long getLastAccessBackgroundTime(int);
method public long getLastAccessForegroundTime(int);
method public long getLastAccessTime(int);
method public long getLastAccessTime(int, int, int);
method public long getLastBackgroundDuration(int);
+ method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastBackgroundProxyInfo(int);
+ method public long getLastDuration(int);
method public long getLastDuration(int, int, int);
method public long getLastForegroundDuration(int);
+ method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastForegroundProxyInfo(int);
+ method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastProxyInfo(int);
+ method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastProxyInfo(int, int, int);
method public long getLastRejectBackgroundTime(int);
method public long getLastRejectForegroundTime(int);
method public long getLastRejectTime(int);
@@ -323,34 +331,53 @@ package android.app {
method public int getMode();
method @NonNull public String getOpStr();
method @Deprecated @Nullable public String getProxyPackageName();
- method @Nullable public String getProxyPackageName(int, int);
+ method @Deprecated @Nullable public String getProxyPackageName(int, int);
method @Deprecated public int getProxyUid();
- method public int getProxyUid(int, int);
+ method @Deprecated public int getProxyUid(int, int);
method public boolean isRunning();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.OpEntry> CREATOR;
}
- public static final class AppOpsManager.OpFeatureEntry {
- method public long getDuration();
+ public static final class AppOpsManager.OpEventProxyInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method @Nullable public String getFeatureId();
+ method @Nullable public String getPackageName();
+ method @IntRange(from=0) public int getUid();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.OpEventProxyInfo> CREATOR;
+ }
+
+ public static final class AppOpsManager.OpFeatureEntry implements android.os.Parcelable {
+ method public int describeContents();
method public long getLastAccessBackgroundTime(int);
method public long getLastAccessForegroundTime(int);
method public long getLastAccessTime(int);
method public long getLastAccessTime(int, int, int);
method public long getLastBackgroundDuration(int);
+ method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastBackgroundProxyInfo(int);
+ method public long getLastDuration(int);
method public long getLastDuration(int, int, int);
method public long getLastForegroundDuration(int);
+ method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastForegroundProxyInfo(int);
+ method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastProxyInfo(int);
+ method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastProxyInfo(int, int, int);
method public long getLastRejectBackgroundTime(int);
method public long getLastRejectForegroundTime(int);
method public long getLastRejectTime(int);
method public long getLastRejectTime(int, int, int);
- method @Nullable public String getProxyFeatureId();
- method @Nullable public String getProxyFeatureId(int, int);
- method @Nullable public String getProxyPackageName();
- method @Nullable public String getProxyPackageName(int, int);
- method public int getProxyUid();
- method public int getProxyUid(int, int);
method public boolean isRunning();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.OpFeatureEntry> CREATOR;
+ }
+
+ public static final class AppOpsManager.PackageOps implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public java.util.List<android.app.AppOpsManager.OpEntry> getOps();
+ method @NonNull public String getPackageName();
+ method public int getUid();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.PackageOps> CREATOR;
}
public class DownloadManager {
@@ -454,6 +481,7 @@ package android.app {
field public static final int WINDOWING_MODE_FREEFORM = 5; // 0x5
field public static final int WINDOWING_MODE_FULLSCREEN = 1; // 0x1
field public static final int WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY = 4; // 0x4
+ field public static final int WINDOWING_MODE_MULTI_WINDOW = 6; // 0x6
field public static final int WINDOWING_MODE_PINNED = 2; // 0x2
field public static final int WINDOWING_MODE_SPLIT_SCREEN_PRIMARY = 3; // 0x3
field public static final int WINDOWING_MODE_SPLIT_SCREEN_SECONDARY = 4; // 0x4
@@ -629,6 +657,9 @@ package android.app.usage {
public class StorageStatsManager {
method public boolean isQuotaSupported(@NonNull java.util.UUID);
method public boolean isReservedSupported(@NonNull java.util.UUID);
+ method @NonNull @WorkerThread public java.util.Collection<android.os.storage.CrateInfo> queryCratesForPackage(@NonNull java.util.UUID, @NonNull String, @NonNull android.os.UserHandle) throws java.io.IOException, android.content.pm.PackageManager.NameNotFoundException;
+ method @NonNull @WorkerThread public java.util.Collection<android.os.storage.CrateInfo> queryCratesForUid(@NonNull java.util.UUID, int) throws java.io.IOException, android.content.pm.PackageManager.NameNotFoundException;
+ method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_CRATES) @WorkerThread public java.util.Collection<android.os.storage.CrateInfo> queryCratesForUser(@NonNull java.util.UUID, @NonNull android.os.UserHandle) throws java.io.IOException, android.content.pm.PackageManager.NameNotFoundException;
}
public final class UsageStatsManager {
@@ -749,11 +780,13 @@ package android.content.pm {
}
public static class PackageInstaller.SessionInfo implements android.os.Parcelable {
+ method public int getRollbackDataPolicy();
method @NonNull public java.util.Set<java.lang.String> getWhitelistedRestrictedPermissions();
}
public static class PackageInstaller.SessionParams implements android.os.Parcelable {
method public void setEnableRollback(boolean);
+ method public void setEnableRollback(boolean, int);
method @RequiresPermission("android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS") public void setGrantedRuntimePermissions(String[]);
method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setInstallAsApex();
method public void setInstallerPackageName(@Nullable String);
@@ -809,6 +842,7 @@ package android.content.pm {
public class PermissionInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
field public static final int FLAG_REMOVED = 2; // 0x2
field public static final int PROTECTION_FLAG_APP_PREDICTOR = 2097152; // 0x200000
+ field public static final int PROTECTION_FLAG_COMPANION = 8388608; // 0x800000
field public static final int PROTECTION_FLAG_CONFIGURATOR = 524288; // 0x80000
field public static final int PROTECTION_FLAG_DOCUMENTER = 262144; // 0x40000
field public static final int PROTECTION_FLAG_INCIDENT_REPORT_APPROVER = 1048576; // 0x100000
@@ -1024,9 +1058,13 @@ package android.hardware.display {
method @Nullable public android.hardware.display.BrightnessCorrection getCorrectionByCategory(int);
method @Nullable public android.hardware.display.BrightnessCorrection getCorrectionByPackageName(@NonNull String);
method public android.util.Pair<float[],float[]> getCurve();
+ method public float getShortTermModelLowerLuxMultiplier();
+ method public long getShortTermModelTimeout();
+ method public float getShortTermModelUpperLuxMultiplier();
method public boolean shouldCollectColorSamples();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.hardware.display.BrightnessConfiguration> CREATOR;
+ field public static final long SHORT_TERM_TIMEOUT_UNSET = -1L; // 0xffffffffffffffffL
}
public static class BrightnessConfiguration.Builder {
@@ -1037,6 +1075,9 @@ package android.hardware.display {
method public int getMaxCorrectionsByCategory();
method public int getMaxCorrectionsByPackageName();
method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setDescription(@Nullable String);
+ method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShortTermModelLowerLuxMultiplier(@FloatRange(from=0.0f) float);
+ method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShortTermModelTimeout(long);
+ method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShortTermModelUpperLuxMultiplier(@FloatRange(from=0.0f) float);
method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShouldCollectColorSamples(boolean);
}
@@ -2314,6 +2355,17 @@ package android.os.image {
package android.os.storage {
+ public final class CrateInfo implements android.os.Parcelable {
+ ctor public CrateInfo(@NonNull CharSequence, long);
+ ctor public CrateInfo(@NonNull CharSequence);
+ method @Nullable public static android.os.storage.CrateInfo copyFrom(int, @Nullable String, @Nullable String);
+ method public int describeContents();
+ method public long getExpirationMillis();
+ method @NonNull public CharSequence getLabel();
+ method public void writeToParcel(@Nullable android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.os.storage.CrateInfo> CREATOR;
+ }
+
public class StorageManager {
method public static boolean hasIsolatedStorage();
}
@@ -2741,6 +2793,7 @@ package android.service.autofill.augmented {
method @NonNull public android.content.ComponentName getActivityComponent();
method @NonNull public android.view.autofill.AutofillId getFocusedId();
method @NonNull public android.view.autofill.AutofillValue getFocusedValue();
+ method @Nullable public android.view.inputmethod.InlineSuggestionsRequest getInlineSuggestionsRequest();
method @Nullable public android.service.autofill.augmented.PresentationParams getPresentationParams();
method public int getTaskId();
}
@@ -2751,7 +2804,8 @@ package android.service.autofill.augmented {
public static final class FillResponse.Builder {
ctor public FillResponse.Builder();
method @NonNull public android.service.autofill.augmented.FillResponse build();
- method @NonNull public android.service.autofill.augmented.FillResponse.Builder setFillWindow(@NonNull android.service.autofill.augmented.FillWindow);
+ method @NonNull public android.service.autofill.augmented.FillResponse.Builder setFillWindow(@Nullable android.service.autofill.augmented.FillWindow);
+ method @NonNull public android.service.autofill.augmented.FillResponse.Builder setInlineSuggestions(@Nullable java.util.List<android.service.autofill.Dataset>);
}
public final class FillWindow implements java.lang.AutoCloseable {
@@ -4232,138 +4286,10 @@ package android.util.proto {
method public void writeRawZigZag64(long);
}
- public final class ProtoOutputStream extends android.util.proto.ProtoStream {
- ctor public ProtoOutputStream();
- ctor public ProtoOutputStream(int);
- ctor public ProtoOutputStream(java.io.OutputStream);
- ctor public ProtoOutputStream(java.io.FileDescriptor);
- method public static int checkFieldId(long, long);
- method public void dump(String);
- method public void end(long);
- method @Deprecated public void endObject(long);
- method @Deprecated public void endRepeatedObject(long);
- method public void flush();
- method public byte[] getBytes();
- method public int getRawSize();
- method public static long makeFieldId(int, long);
- method public long start(long);
- method @Deprecated public long startObject(long);
- method @Deprecated public long startRepeatedObject(long);
- method public void write(long, double);
- method public void write(long, float);
- method public void write(long, int);
- method public void write(long, long);
- method public void write(long, boolean);
- method public void write(long, String);
- method public void write(long, byte[]);
- method @Deprecated public void writeBool(long, boolean);
- method @Deprecated public void writeBytes(long, byte[]);
- method @Deprecated public void writeDouble(long, double);
- method @Deprecated public void writeEnum(long, int);
- method @Deprecated public void writeFixed32(long, int);
- method @Deprecated public void writeFixed64(long, long);
- method @Deprecated public void writeFloat(long, float);
- method @Deprecated public void writeInt32(long, int);
- method @Deprecated public void writeInt64(long, long);
- method @Deprecated public void writeObject(long, byte[]);
- method @Deprecated public void writePackedBool(long, boolean[]);
- method @Deprecated public void writePackedDouble(long, double[]);
- method @Deprecated public void writePackedEnum(long, int[]);
- method @Deprecated public void writePackedFixed32(long, int[]);
- method @Deprecated public void writePackedFixed64(long, long[]);
- method @Deprecated public void writePackedFloat(long, float[]);
- method @Deprecated public void writePackedInt32(long, int[]);
- method @Deprecated public void writePackedInt64(long, long[]);
- method @Deprecated public void writePackedSFixed32(long, int[]);
- method @Deprecated public void writePackedSFixed64(long, long[]);
- method @Deprecated public void writePackedSInt32(long, int[]);
- method @Deprecated public void writePackedSInt64(long, long[]);
- method @Deprecated public void writePackedUInt32(long, int[]);
- method @Deprecated public void writePackedUInt64(long, long[]);
- method @Deprecated public void writeRepeatedBool(long, boolean);
- method @Deprecated public void writeRepeatedBytes(long, byte[]);
- method @Deprecated public void writeRepeatedDouble(long, double);
- method @Deprecated public void writeRepeatedEnum(long, int);
- method @Deprecated public void writeRepeatedFixed32(long, int);
- method @Deprecated public void writeRepeatedFixed64(long, long);
- method @Deprecated public void writeRepeatedFloat(long, float);
- method @Deprecated public void writeRepeatedInt32(long, int);
- method @Deprecated public void writeRepeatedInt64(long, long);
- method @Deprecated public void writeRepeatedObject(long, byte[]);
- method @Deprecated public void writeRepeatedSFixed32(long, int);
- method @Deprecated public void writeRepeatedSFixed64(long, long);
- method @Deprecated public void writeRepeatedSInt32(long, int);
- method @Deprecated public void writeRepeatedSInt64(long, long);
- method @Deprecated public void writeRepeatedString(long, String);
- method @Deprecated public void writeRepeatedUInt32(long, int);
- method @Deprecated public void writeRepeatedUInt64(long, long);
- method @Deprecated public void writeSFixed32(long, int);
- method @Deprecated public void writeSFixed64(long, long);
- method @Deprecated public void writeSInt32(long, int);
- method @Deprecated public void writeSInt64(long, long);
- method @Deprecated public void writeString(long, String);
- method public void writeTag(int, int);
- method @Deprecated public void writeUInt32(long, int);
- method @Deprecated public void writeUInt64(long, long);
- }
-
public class ProtoParseException extends java.lang.RuntimeException {
ctor public ProtoParseException(String);
}
- public abstract class ProtoStream {
- ctor public ProtoStream();
- method public static int convertObjectIdToOrdinal(int);
- method public static int getDepthFromToken(long);
- method public static String getFieldCountString(long);
- method public static String getFieldIdString(long);
- method public static String getFieldTypeString(long);
- method public static int getObjectIdFromToken(long);
- method public static int getOffsetFromToken(long);
- method public static boolean getRepeatedFromToken(long);
- method public static int getTagSizeFromToken(long);
- method public static String getWireTypeString(int);
- method public static long makeFieldId(int, long);
- method public static long makeToken(int, boolean, int, int, int);
- method public static String token2String(long);
- field public static final long FIELD_COUNT_MASK = 16492674416640L; // 0xf0000000000L
- field public static final long FIELD_COUNT_PACKED = 5497558138880L; // 0x50000000000L
- field public static final long FIELD_COUNT_REPEATED = 2199023255552L; // 0x20000000000L
- field public static final int FIELD_COUNT_SHIFT = 40; // 0x28
- field public static final long FIELD_COUNT_SINGLE = 1099511627776L; // 0x10000000000L
- field public static final long FIELD_COUNT_UNKNOWN = 0L; // 0x0L
- field public static final int FIELD_ID_MASK = -8; // 0xfffffff8
- field public static final int FIELD_ID_SHIFT = 3; // 0x3
- field public static final long FIELD_TYPE_BOOL = 34359738368L; // 0x800000000L
- field public static final long FIELD_TYPE_BYTES = 51539607552L; // 0xc00000000L
- field public static final long FIELD_TYPE_DOUBLE = 4294967296L; // 0x100000000L
- field public static final long FIELD_TYPE_ENUM = 60129542144L; // 0xe00000000L
- field public static final long FIELD_TYPE_FIXED32 = 30064771072L; // 0x700000000L
- field public static final long FIELD_TYPE_FIXED64 = 25769803776L; // 0x600000000L
- field public static final long FIELD_TYPE_FLOAT = 8589934592L; // 0x200000000L
- field public static final long FIELD_TYPE_INT32 = 21474836480L; // 0x500000000L
- field public static final long FIELD_TYPE_INT64 = 12884901888L; // 0x300000000L
- field public static final long FIELD_TYPE_MASK = 1095216660480L; // 0xff00000000L
- field public static final long FIELD_TYPE_MESSAGE = 47244640256L; // 0xb00000000L
- field protected static final String[] FIELD_TYPE_NAMES;
- field public static final long FIELD_TYPE_SFIXED32 = 64424509440L; // 0xf00000000L
- field public static final long FIELD_TYPE_SFIXED64 = 68719476736L; // 0x1000000000L
- field public static final int FIELD_TYPE_SHIFT = 32; // 0x20
- field public static final long FIELD_TYPE_SINT32 = 73014444032L; // 0x1100000000L
- field public static final long FIELD_TYPE_SINT64 = 77309411328L; // 0x1200000000L
- field public static final long FIELD_TYPE_STRING = 38654705664L; // 0x900000000L
- field public static final long FIELD_TYPE_UINT32 = 55834574848L; // 0xd00000000L
- field public static final long FIELD_TYPE_UINT64 = 17179869184L; // 0x400000000L
- field public static final long FIELD_TYPE_UNKNOWN = 0L; // 0x0L
- field public static final int WIRE_TYPE_END_GROUP = 4; // 0x4
- field public static final int WIRE_TYPE_FIXED32 = 5; // 0x5
- field public static final int WIRE_TYPE_FIXED64 = 1; // 0x1
- field public static final int WIRE_TYPE_LENGTH_DELIMITED = 2; // 0x2
- field public static final int WIRE_TYPE_MASK = 7; // 0x7
- field public static final int WIRE_TYPE_START_GROUP = 3; // 0x3
- field public static final int WIRE_TYPE_VARINT = 0; // 0x0
- }
-
public class WireTypeMismatchException extends android.util.proto.ProtoParseException {
ctor public WireTypeMismatchException(String);
}
@@ -4424,6 +4350,18 @@ package android.view {
method public abstract String asyncImpl() default "";
}
+ public class SurfaceControlViewHost {
+ ctor public SurfaceControlViewHost(@NonNull android.content.Context, @NonNull android.view.Display, @Nullable android.os.IBinder);
+ method public void addView(android.view.View, android.view.WindowManager.LayoutParams);
+ method public void dispose();
+ method @Nullable public android.view.SurfaceControlViewHost.SurfacePackage getSurfacePackage();
+ method public void relayout(android.view.WindowManager.LayoutParams);
+ }
+
+ public class SurfaceControlViewHost.SurfacePackage {
+ method @NonNull public android.view.SurfaceControl getSurfaceControl();
+ }
+
public class SurfaceView extends android.view.View {
method @Nullable public android.os.IBinder getInputToken();
}
@@ -4444,6 +4382,7 @@ package android.view {
method public void setAutofilled(boolean);
method public final void setFocusedInCluster();
method public void setIsRootNamespace(boolean);
+ method public final void setShowingLayoutBounds(boolean);
}
public class ViewConfiguration {
@@ -4474,13 +4413,6 @@ package android.view {
field @android.view.ViewDebug.ExportedProperty(flagMapping={@android.view.ViewDebug.FlagToString(mask=0x1, equals=0x1, name="FAKE_HARDWARE_ACCELERATED"), @android.view.ViewDebug.FlagToString(mask=0x2, equals=0x2, name="FORCE_HARDWARE_ACCELERATED"), @android.view.ViewDebug.FlagToString(mask=0x4, equals=0x4, name="WANTS_OFFSET_NOTIFICATIONS"), @android.view.ViewDebug.FlagToString(mask=0x10, equals=0x10, name="SHOW_FOR_ALL_USERS"), @android.view.ViewDebug.FlagToString(mask=android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION, equals=android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION, name="NO_MOVE_ANIMATION"), @android.view.ViewDebug.FlagToString(mask=0x80, equals=0x80, name="COMPATIBLE_WINDOW"), @android.view.ViewDebug.FlagToString(mask=0x100, equals=0x100, name="SYSTEM_ERROR"), @android.view.ViewDebug.FlagToString(mask=0x400, equals=0x400, name="KEYGUARD"), @android.view.ViewDebug.FlagToString(mask=0x800, equals=0x800, name="DISABLE_WALLPAPER_TOUCH_EVENTS"), @android.view.ViewDebug.FlagToString(mask=0x1000, equals=0x1000, name="FORCE_STATUS_BAR_VISIBLE_TRANSPARENT"), @android.view.ViewDebug.FlagToString(mask=0x2000, equals=0x2000, name="PRESERVE_GEOMETRY"), @android.view.ViewDebug.FlagToString(mask=0x4000, equals=0x4000, name="FORCE_DECOR_VIEW_VISIBILITY"), @android.view.ViewDebug.FlagToString(mask=0x8000, equals=0x8000, name="WILL_NOT_REPLACE_ON_RELAUNCH"), @android.view.ViewDebug.FlagToString(mask=0x10000, equals=0x10000, name="LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME"), @android.view.ViewDebug.FlagToString(mask=0x20000, equals=0x20000, name="FORCE_DRAW_STATUS_BAR_BACKGROUND"), @android.view.ViewDebug.FlagToString(mask=0x40000, equals=0x40000, name="SUSTAINED_PERFORMANCE_MODE"), @android.view.ViewDebug.FlagToString(mask=0x80000, equals=0x80000, name="HIDE_NON_SYSTEM_OVERLAY_WINDOWS"), @android.view.ViewDebug.FlagToString(mask=0x100000, equals=0x100000, name="IS_ROUNDED_CORNERS_OVERLAY"), @android.view.ViewDebug.FlagToString(mask=0x400000, equals=0x400000, name="IS_SCREEN_DECOR"), @android.view.ViewDebug.FlagToString(mask=0x800000, equals=0x800000, name="STATUS_FORCE_SHOW_NAVIGATION"), @android.view.ViewDebug.FlagToString(mask=0x1000000, equals=0x1000000, name="COLOR_SPACE_AGNOSTIC"), @android.view.ViewDebug.FlagToString(mask=0x4000000, equals=0x4000000, name="FIT_INSETS_CONTROLLED"), @android.view.ViewDebug.FlagToString(mask=0x8000000, equals=0x8000000, name="ONLY_DRAW_BOTTOM_BAR_BACKGROUND")}) public int privateFlags;
}
- public class WindowlessViewRoot {
- ctor public WindowlessViewRoot(@NonNull android.content.Context, @NonNull android.view.Display, @NonNull android.view.SurfaceControl, @Nullable android.os.IBinder);
- method public void addView(android.view.View, android.view.WindowManager.LayoutParams);
- method public void dispose();
- method public void relayout(android.view.WindowManager.LayoutParams);
- }
-
}
package android.view.accessibility {
diff --git a/api/test-lint-baseline.txt b/api/test-lint-baseline.txt
index ef8165fc6edb..6d1f29122b71 100644
--- a/api/test-lint-baseline.txt
+++ b/api/test-lint-baseline.txt
@@ -2079,17 +2079,17 @@ MissingNullability: android.view.ViewDebug#startRenderingCommandsCapture(android
MissingNullability: android.view.WindowManager.LayoutParams#accessibilityTitle:
-MissingNullability: android.view.WindowlessViewRoot#WindowlessViewRoot(android.content.Context, android.view.Display, android.view.SurfaceControl) parameter #0:
+MissingNullability: android.view.SurfaceControlViewHost#SurfaceControlViewHost(android.content.Context, android.view.Display, android.view.SurfaceControl) parameter #0:
-MissingNullability: android.view.WindowlessViewRoot#WindowlessViewRoot(android.content.Context, android.view.Display, android.view.SurfaceControl) parameter #1:
+MissingNullability: android.view.SurfaceControlViewHost#SurfaceControlViewHost(android.content.Context, android.view.Display, android.view.SurfaceControl) parameter #1:
-MissingNullability: android.view.WindowlessViewRoot#WindowlessViewRoot(android.content.Context, android.view.Display, android.view.SurfaceControl) parameter #2:
+MissingNullability: android.view.SurfaceControlViewHost#SurfaceControlViewHost(android.content.Context, android.view.Display, android.view.SurfaceControl) parameter #2:
-MissingNullability: android.view.WindowlessViewRoot#addView(android.view.View, android.view.WindowManager.LayoutParams) parameter #0:
+MissingNullability: android.view.SurfaceControlViewHost#addView(android.view.View, android.view.WindowManager.LayoutParams) parameter #0:
-MissingNullability: android.view.WindowlessViewRoot#addView(android.view.View, android.view.WindowManager.LayoutParams) parameter #1:
+MissingNullability: android.view.SurfaceControlViewHost#addView(android.view.View, android.view.WindowManager.LayoutParams) parameter #1:
-MissingNullability: android.view.WindowlessViewRoot#relayout(android.view.WindowManager.LayoutParams) parameter #0:
+MissingNullability: android.view.SurfaceControlViewHost#relayout(android.view.WindowManager.LayoutParams) parameter #0:
MissingNullability: android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener#onAccessibilityServicesStateChanged(android.view.accessibility.AccessibilityManager) parameter #0:
diff --git a/cmds/idmap2/CPPLINT.cfg b/cmds/idmap2/CPPLINT.cfg
index 9dc6b4a77380..20ed43c2a76a 100644
--- a/cmds/idmap2/CPPLINT.cfg
+++ b/cmds/idmap2/CPPLINT.cfg
@@ -15,4 +15,4 @@
set noparent
linelength=100
root=..
-filter=+build/include_alpha
+filter=+build/include_alpha,-runtime/references,-build/c++
diff --git a/cmds/idmap2/include/idmap2/BinaryStreamVisitor.h b/cmds/idmap2/include/idmap2/BinaryStreamVisitor.h
index 924efe5cfb7b..ff45b1407dea 100644
--- a/cmds/idmap2/include/idmap2/BinaryStreamVisitor.h
+++ b/cmds/idmap2/include/idmap2/BinaryStreamVisitor.h
@@ -40,7 +40,8 @@ class BinaryStreamVisitor : public Visitor {
void Write8(uint8_t value);
void Write16(uint16_t value);
void Write32(uint32_t value);
- void WriteString(const StringPiece& value);
+ void WriteString256(const StringPiece& value);
+ void WriteString(const std::string& value);
std::ostream& stream_;
};
diff --git a/cmds/idmap2/include/idmap2/Idmap.h b/cmds/idmap2/include/idmap2/Idmap.h
index 2639c6f470ae..d4a0c3221c20 100644
--- a/cmds/idmap2/include/idmap2/Idmap.h
+++ b/cmds/idmap2/include/idmap2/Idmap.h
@@ -18,19 +18,21 @@
* # idmap file format (current version)
*
* idmap := header data*
- * header := magic version target_crc overlay_crc target_path overlay_path
+ * header := magic version target_crc overlay_crc target_path overlay_path debug_info
* data := data_header data_block*
* data_header := target_package_id types_count
* data_block := target_type overlay_type entry_count entry_offset entry*
- * overlay_path := string
- * target_path := string
+ * overlay_path := string256
+ * target_path := string256
+ * debug_info := string
+ * string := <uint32_t> <uint8_t>+ '\0'+
* entry := <uint32_t>
* entry_count := <uint16_t>
* entry_offset := <uint16_t>
* magic := <uint32_t>
* overlay_crc := <uint32_t>
* overlay_type := <uint16_t>
- * string := <uint8_t>[256]
+ * string256 := <uint8_t>[256]
* target_crc := <uint32_t>
* target_package_id := <uint16_t>
* target_type := <uint16_t>
@@ -41,6 +43,7 @@
* # idmap file format changelog
* ## v1
* - Identical to idmap v1.
+ *
* ## v2
* - Entries are no longer separated by type into type specific data blocks.
* - Added overlay-indexed target resource id lookup capabilities.
@@ -53,6 +56,9 @@
* - Idmap can now encode a type and value to override a resource without needing a table entry.
* - A string pool block is included to retrieve the value of strings that do not have a resource
* table entry.
+ *
+ * ## v3
+ * - Add 'debug' block to IdmapHeader.
*/
#ifndef IDMAP2_INCLUDE_IDMAP2_IDMAP_H_
@@ -116,6 +122,10 @@ class IdmapHeader {
return StringPiece(overlay_path_);
}
+ inline const std::string& GetDebugInfo() const {
+ return debug_info_;
+ }
+
// Invariant: anytime the idmap data encoding is changed, the idmap version
// field *must* be incremented. Because of this, we know that if the idmap
// header is up-to-date the entire file is up-to-date.
@@ -133,6 +143,7 @@ class IdmapHeader {
uint32_t overlay_crc_;
char target_path_[kIdmapStringLength];
char overlay_path_[kIdmapStringLength];
+ std::string debug_info_;
friend Idmap;
DISALLOW_COPY_AND_ASSIGN(IdmapHeader);
diff --git a/cmds/idmap2/include/idmap2/LogInfo.h b/cmds/idmap2/include/idmap2/LogInfo.h
new file mode 100644
index 000000000000..a6237e6f6ba9
--- /dev/null
+++ b/cmds/idmap2/include/idmap2/LogInfo.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef IDMAP2_INCLUDE_IDMAP2_LOGINFO_H_
+#define IDMAP2_INCLUDE_IDMAP2_LOGINFO_H_
+
+#include <algorithm>
+#include <iterator>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#if __ANDROID__
+#include "android-base/logging.h"
+#else
+#include <iostream>
+#endif
+
+namespace android::idmap2 {
+
+class LogMessage {
+ public:
+ LogMessage() = default;
+
+ template <typename T>
+ LogMessage& operator<<(const T& value) {
+ stream_ << value;
+ return *this;
+ }
+
+ std::string GetString() const {
+ return stream_.str();
+ }
+
+ private:
+ std::stringstream stream_;
+};
+
+class LogInfo {
+ public:
+ LogInfo() = default;
+
+ inline void Info(const LogMessage& msg) {
+ lines_.push_back("I " + msg.GetString());
+ }
+
+ inline void Warning(const LogMessage& msg) {
+#ifdef __ANDROID__
+ LOG(WARNING) << msg.GetString();
+#else
+ std::cerr << "W " << msg.GetString() << std::endl;
+#endif
+ lines_.push_back("W " + msg.GetString());
+ }
+
+ inline std::string GetString() const {
+ std::ostringstream stream;
+ std::copy(lines_.begin(), lines_.end(), std::ostream_iterator<std::string>(stream, "\n"));
+ return stream.str();
+ }
+
+ private:
+ std::vector<std::string> lines_;
+};
+
+} // namespace android::idmap2
+
+#endif // IDMAP2_INCLUDE_IDMAP2_LOGINFO_H_
diff --git a/cmds/idmap2/include/idmap2/RawPrintVisitor.h b/cmds/idmap2/include/idmap2/RawPrintVisitor.h
index 76475ab58731..92c186453611 100644
--- a/cmds/idmap2/include/idmap2/RawPrintVisitor.h
+++ b/cmds/idmap2/include/idmap2/RawPrintVisitor.h
@@ -44,7 +44,7 @@ class RawPrintVisitor : public Visitor {
void print(uint8_t value, const char* fmt, ...);
void print(uint16_t value, const char* fmt, ...);
void print(uint32_t value, const char* fmt, ...);
- void print(const std::string& value, const char* fmt, ...);
+ void print(const std::string& value, size_t encoded_size, const char* fmt, ...);
void print_raw(uint32_t length, const char* fmt, ...);
std::ostream& stream_;
diff --git a/cmds/idmap2/include/idmap2/ResourceMapping.h b/cmds/idmap2/include/idmap2/ResourceMapping.h
index c3e1ef06c20f..86dfab20e448 100644
--- a/cmds/idmap2/include/idmap2/ResourceMapping.h
+++ b/cmds/idmap2/include/idmap2/ResourceMapping.h
@@ -22,6 +22,7 @@
#include <utility>
#include "androidfw/ApkAssets.h"
+#include "idmap2/LogInfo.h"
#include "idmap2/Policies.h"
#include "idmap2/ResourceUtils.h"
#include "idmap2/Result.h"
@@ -50,7 +51,7 @@ class ResourceMapping {
const ApkAssets& overlay_apk_assets,
const OverlayManifestInfo& overlay_info,
const PolicyBitmask& fulfilled_policies,
- bool enforce_overlayable);
+ bool enforce_overlayable, LogInfo& log_info);
// Retrieves the mapping of target resource id to overlay value.
inline TargetResourceMap GetTargetToOverlayMap() const {
@@ -100,7 +101,8 @@ class ResourceMapping {
const LoadedPackage* target_package,
const LoadedPackage* overlay_package,
size_t string_pool_offset,
- const XmlParser& overlay_parser);
+ const XmlParser& overlay_parser,
+ LogInfo& log_info);
// Generates a ResourceMapping that maps target resources to overlay resources by name. To overlay
// a target resource, a resource must exist in the overlay with the same type and entry name as
@@ -115,7 +117,7 @@ class ResourceMapping {
const LoadedPackage* target_package,
const LoadedPackage* overlay_package,
const OverlayManifestInfo& overlay_info,
- const PolicyBitmask& fulfilled_policies);
+ const PolicyBitmask& fulfilled_policies, LogInfo& log_info);
TargetResourceMap target_map_;
std::multimap<ResourceId, ResourceId> overlay_map_;
diff --git a/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp b/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp
index 3b0940ae06ef..362dcb36007a 100644
--- a/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp
+++ b/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp
@@ -42,13 +42,21 @@ void BinaryStreamVisitor::Write32(uint32_t value) {
stream_.write(reinterpret_cast<char*>(&x), sizeof(uint32_t));
}
-void BinaryStreamVisitor::WriteString(const StringPiece& value) {
+void BinaryStreamVisitor::WriteString256(const StringPiece& value) {
char buf[kIdmapStringLength];
memset(buf, 0, sizeof(buf));
memcpy(buf, value.data(), std::min(value.size(), sizeof(buf)));
stream_.write(buf, sizeof(buf));
}
+void BinaryStreamVisitor::WriteString(const std::string& value) {
+ // pad with null to nearest word boundary; include at least one terminating null
+ size_t padding_size = 4 - (value.size() % 4);
+ Write32(value.size() + padding_size);
+ stream_.write(value.c_str(), value.size());
+ stream_.write("\0\0\0\0", padding_size);
+}
+
void BinaryStreamVisitor::visit(const Idmap& idmap ATTRIBUTE_UNUSED) {
// nothing to do
}
@@ -58,8 +66,9 @@ void BinaryStreamVisitor::visit(const IdmapHeader& header) {
Write32(header.GetVersion());
Write32(header.GetTargetCrc());
Write32(header.GetOverlayCrc());
- WriteString(header.GetTargetPath());
- WriteString(header.GetOverlayPath());
+ WriteString256(header.GetTargetPath());
+ WriteString256(header.GetOverlayPath());
+ WriteString(header.GetDebugInfo());
}
void BinaryStreamVisitor::visit(const IdmapData& data) {
diff --git a/cmds/idmap2/libidmap2/Idmap.cpp b/cmds/idmap2/libidmap2/Idmap.cpp
index 5cb91d713db7..7f2cd9596c95 100644
--- a/cmds/idmap2/libidmap2/Idmap.cpp
+++ b/cmds/idmap2/libidmap2/Idmap.cpp
@@ -70,7 +70,7 @@ bool WARN_UNUSED ReadBuffer(std::istream& stream, std::unique_ptr<uint8_t[]>* ou
}
// a string is encoded as a kIdmapStringLength char array; the array is always null-terminated
-bool WARN_UNUSED ReadString(std::istream& stream, char out[kIdmapStringLength]) {
+bool WARN_UNUSED ReadString256(std::istream& stream, char out[kIdmapStringLength]) {
char buf[kIdmapStringLength];
memset(buf, 0, sizeof(buf));
if (!stream.read(buf, sizeof(buf))) {
@@ -83,6 +83,23 @@ bool WARN_UNUSED ReadString(std::istream& stream, char out[kIdmapStringLength])
return true;
}
+Result<std::string> ReadString(std::istream& stream) {
+ uint32_t size;
+ if (!Read32(stream, &size)) {
+ return Error("failed to read string size");
+ }
+ if (size == 0) {
+ return std::string("");
+ }
+ std::string buf(size, '\0');
+ if (!stream.read(buf.data(), size)) {
+ return Error("failed to read string of size %u", size);
+ }
+ // buf is guaranteed to be null terminated (with enough nulls to end on a word boundary)
+ buf.resize(strlen(buf.c_str()));
+ return buf;
+}
+
Result<uint32_t> GetCrc(const ZipFile& zip) {
const Result<uint32_t> a = zip.Crc("resources.arsc");
const Result<uint32_t> b = zip.Crc("AndroidManifest.xml");
@@ -98,10 +115,16 @@ std::unique_ptr<const IdmapHeader> IdmapHeader::FromBinaryStream(std::istream& s
if (!Read32(stream, &idmap_header->magic_) || !Read32(stream, &idmap_header->version_) ||
!Read32(stream, &idmap_header->target_crc_) || !Read32(stream, &idmap_header->overlay_crc_) ||
- !ReadString(stream, idmap_header->target_path_) ||
- !ReadString(stream, idmap_header->overlay_path_)) {
+ !ReadString256(stream, idmap_header->target_path_) ||
+ !ReadString256(stream, idmap_header->overlay_path_)) {
+ return nullptr;
+ }
+
+ auto debug_str = ReadString(stream);
+ if (!debug_str) {
return nullptr;
}
+ idmap_header->debug_info_ = std::move(*debug_str);
return std::move(idmap_header);
}
@@ -307,17 +330,15 @@ Result<std::unique_ptr<const Idmap>> Idmap::FromApkAssets(const ApkAssets& targe
memset(header->overlay_path_, 0, sizeof(header->overlay_path_));
memcpy(header->overlay_path_, overlay_apk_path.data(), overlay_apk_path.size());
- std::unique_ptr<Idmap> idmap(new Idmap());
- idmap->header_ = std::move(header);
-
auto overlay_info = utils::ExtractOverlayManifestInfo(overlay_apk_path);
if (!overlay_info) {
return overlay_info.GetError();
}
+ LogInfo log_info;
auto resource_mapping =
ResourceMapping::FromApkAssets(target_apk_assets, overlay_apk_assets, *overlay_info,
- fulfilled_policies, enforce_overlayable);
+ fulfilled_policies, enforce_overlayable, log_info);
if (!resource_mapping) {
return resource_mapping.GetError();
}
@@ -327,7 +348,11 @@ Result<std::unique_ptr<const Idmap>> Idmap::FromApkAssets(const ApkAssets& targe
return idmap_data.GetError();
}
+ std::unique_ptr<Idmap> idmap(new Idmap());
+ header->debug_info_ = log_info.GetString();
+ idmap->header_ = std::move(header);
idmap->data_.push_back(std::move(*idmap_data));
+
return {std::move(idmap)};
}
diff --git a/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp b/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp
index a662aa59b615..63ee8a648352 100644
--- a/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp
+++ b/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp
@@ -16,6 +16,7 @@
#include "idmap2/PrettyPrintVisitor.h"
+#include <istream>
#include <string>
#include "android-base/macros.h"
@@ -28,17 +29,30 @@ namespace android::idmap2 {
#define RESID(pkg, type, entry) (((pkg) << 24) | ((type) << 16) | (entry))
+#define TAB " "
+
void PrettyPrintVisitor::visit(const Idmap& idmap ATTRIBUTE_UNUSED) {
}
void PrettyPrintVisitor::visit(const IdmapHeader& header) {
- stream_ << "target apk path : " << header.GetTargetPath() << std::endl
- << "overlay apk path : " << header.GetOverlayPath() << std::endl;
+ stream_ << "Paths:" << std::endl
+ << TAB "target apk path : " << header.GetTargetPath() << std::endl
+ << TAB "overlay apk path : " << header.GetOverlayPath() << std::endl;
+ const std::string& debug = header.GetDebugInfo();
+ if (!debug.empty()) {
+ std::istringstream debug_stream(debug);
+ std::string line;
+ stream_ << "Debug info:" << std::endl;
+ while (std::getline(debug_stream, line)) {
+ stream_ << TAB << line << std::endl;
+ }
+ }
target_apk_ = ApkAssets::Load(header.GetTargetPath().to_string());
if (target_apk_) {
target_am_.SetApkAssets({target_apk_.get()});
}
+ stream_ << "Mapping:" << std::endl;
}
void PrettyPrintVisitor::visit(const IdmapData::Header& header ATTRIBUTE_UNUSED) {
@@ -51,7 +65,7 @@ void PrettyPrintVisitor::visit(const IdmapData& data) {
const size_t string_pool_offset = data.GetHeader()->GetStringPoolIndexOffset();
for (auto& target_entry : data.GetTargetEntries()) {
- stream_ << base::StringPrintf("0x%08x ->", target_entry.target_id);
+ stream_ << TAB << base::StringPrintf("0x%08x ->", target_entry.target_id);
if (target_entry.data_type != Res_value::TYPE_REFERENCE &&
target_entry.data_type != Res_value::TYPE_DYNAMIC_REFERENCE) {
diff --git a/cmds/idmap2/libidmap2/RawPrintVisitor.cpp b/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
index 13973d64fe68..751c60c4add4 100644
--- a/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
+++ b/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
@@ -16,6 +16,7 @@
#include "idmap2/RawPrintVisitor.h"
+#include <algorithm>
#include <cstdarg>
#include <string>
@@ -27,6 +28,15 @@
using android::ApkAssets;
+namespace {
+
+size_t StringSizeWhenEncoded(const std::string& s) {
+ size_t null_bytes = 4 - (s.size() % 4);
+ return sizeof(uint32_t) + s.size() + null_bytes;
+}
+
+} // namespace
+
namespace android::idmap2 {
// verbatim copy fomr PrettyPrintVisitor.cpp, move to common utils
@@ -40,8 +50,9 @@ void RawPrintVisitor::visit(const IdmapHeader& header) {
print(header.GetVersion(), "version");
print(header.GetTargetCrc(), "target crc");
print(header.GetOverlayCrc(), "overlay crc");
- print(header.GetTargetPath().to_string(), "target path");
- print(header.GetOverlayPath().to_string(), "overlay path");
+ print(header.GetTargetPath().to_string(), kIdmapStringLength, "target path");
+ print(header.GetOverlayPath().to_string(), kIdmapStringLength, "overlay path");
+ print("...", StringSizeWhenEncoded(header.GetDebugInfo()), "debug info");
target_apk_ = ApkAssets::Load(header.GetTargetPath().to_string());
if (target_apk_) {
@@ -164,7 +175,7 @@ void RawPrintVisitor::print(uint32_t value, const char* fmt, ...) {
}
// NOLINTNEXTLINE(cert-dcl50-cpp)
-void RawPrintVisitor::print(const std::string& value, const char* fmt, ...) {
+void RawPrintVisitor::print(const std::string& value, size_t encoded_size, const char* fmt, ...) {
va_list ap;
va_start(ap, fmt);
std::string comment;
@@ -174,7 +185,7 @@ void RawPrintVisitor::print(const std::string& value, const char* fmt, ...) {
stream_ << base::StringPrintf("%08zx: ", offset_) << "........ " << comment << ": " << value
<< std::endl;
- offset_ += kIdmapStringLength;
+ offset_ += encoded_size;
}
// NOLINTNEXTLINE(cert-dcl50-cpp)
diff --git a/cmds/idmap2/libidmap2/ResourceMapping.cpp b/cmds/idmap2/libidmap2/ResourceMapping.cpp
index 651d20fb7c68..229628c7dd8b 100644
--- a/cmds/idmap2/libidmap2/ResourceMapping.cpp
+++ b/cmds/idmap2/libidmap2/ResourceMapping.cpp
@@ -146,7 +146,8 @@ Result<ResourceMapping> ResourceMapping::CreateResourceMapping(const AssetManage
const LoadedPackage* target_package,
const LoadedPackage* overlay_package,
size_t string_pool_offset,
- const XmlParser& overlay_parser) {
+ const XmlParser& overlay_parser,
+ LogInfo& log_info) {
ResourceMapping resource_mapping;
auto root_it = overlay_parser.tree_iterator();
if (root_it->event() != XmlParser::Event::START_TAG || root_it->name() != "overlay") {
@@ -181,7 +182,8 @@ Result<ResourceMapping> ResourceMapping::CreateResourceMapping(const AssetManage
ResourceId target_id =
target_am->GetResourceId(*target_resource, "", target_package->GetPackageName());
if (target_id == 0U) {
- LOG(WARNING) << "failed to find resource \"" << *target_resource << "\" in target resources";
+ log_info.Warning(LogMessage() << "failed to find resource \"" << *target_resource
+ << "\" in target resources");
continue;
}
@@ -196,7 +198,7 @@ Result<ResourceMapping> ResourceMapping::CreateResourceMapping(const AssetManage
overlay_resource->dataType == Res_value::TYPE_DYNAMIC_REFERENCE)
? overlay_package_id == EXTRACT_PACKAGE(overlay_resource->data)
: false;
-
+
if (rewrite_overlay_reference) {
overlay_resource->dataType = Res_value::TYPE_DYNAMIC_REFERENCE;
}
@@ -239,7 +241,8 @@ void ResourceMapping::FilterOverlayableResources(const AssetManager2* target_am,
const LoadedPackage* target_package,
const LoadedPackage* overlay_package,
const OverlayManifestInfo& overlay_info,
- const PolicyBitmask& fulfilled_policies) {
+ const PolicyBitmask& fulfilled_policies,
+ LogInfo& log_info) {
std::set<ResourceId> remove_ids;
for (const auto& target_map : target_map_) {
const ResourceId target_resid = target_map.first;
@@ -256,9 +259,9 @@ void ResourceMapping::FilterOverlayableResources(const AssetManager2* target_am,
name = StringPrintf("0x%08x", target_resid);
}
- LOG(WARNING) << "overlay \"" << overlay_package->GetPackageName()
- << "\" is not allowed to overlay resource \"" << *name
- << "\" in target: " << success.GetErrorMessage();
+ log_info.Warning(LogMessage() << "overlay \"" << overlay_package->GetPackageName()
+ << "\" is not allowed to overlay resource \"" << *name
+ << "\" in target: " << success.GetErrorMessage());
remove_ids.insert(target_resid);
}
@@ -272,7 +275,15 @@ Result<ResourceMapping> ResourceMapping::FromApkAssets(const ApkAssets& target_a
const ApkAssets& overlay_apk_assets,
const OverlayManifestInfo& overlay_info,
const PolicyBitmask& fulfilled_policies,
- bool enforce_overlayable) {
+ bool enforce_overlayable,
+ LogInfo& log_info) {
+ if (enforce_overlayable) {
+ log_info.Info(LogMessage() << "fulfilled_policies="
+ << ConcatPolicies(BitmaskToPolicies(fulfilled_policies))
+ << " enforce_overlayable="
+ << (enforce_overlayable ? "true" : "false"));
+ }
+
AssetManager2 target_asset_manager;
if (!target_asset_manager.SetApkAssets({&target_apk_assets}, true /* invalidate_caches */,
false /* filter_incompatible_configs*/)) {
@@ -333,7 +344,7 @@ Result<ResourceMapping> ResourceMapping::FromApkAssets(const ApkAssets& target_a
string_pool_offset = overlay_arsc->GetStringPool()->size();
resource_mapping = CreateResourceMapping(&target_asset_manager, target_pkg, overlay_pkg,
- string_pool_offset, *(*parser));
+ string_pool_offset, *(*parser), log_info);
} else {
// If no file is specified using android:resourcesMap, it is assumed that the overlay only
// defines resources intended to override target resources of the same type and name.
@@ -349,7 +360,7 @@ Result<ResourceMapping> ResourceMapping::FromApkAssets(const ApkAssets& target_a
// Filter out resources the overlay is not allowed to override.
(*resource_mapping)
.FilterOverlayableResources(&target_asset_manager, target_pkg, overlay_pkg, overlay_info,
- fulfilled_policies);
+ fulfilled_policies, log_info);
}
resource_mapping->target_package_id_ = target_pkg->GetPackageId();
diff --git a/cmds/idmap2/tests/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp
index cd816ddea814..4bc625565144 100644
--- a/cmds/idmap2/tests/IdmapTests.cpp
+++ b/cmds/idmap2/tests/IdmapTests.cpp
@@ -30,6 +30,7 @@
#include "idmap2/BinaryStreamVisitor.h"
#include "idmap2/CommandLineOptions.h"
#include "idmap2/Idmap.h"
+#include "idmap2/LogInfo.h"
using android::Res_value;
using ::testing::IsNull;
@@ -57,11 +58,12 @@ TEST(IdmapTests, CreateIdmapHeaderFromBinaryStream) {
std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(stream);
ASSERT_THAT(header, NotNull());
ASSERT_EQ(header->GetMagic(), 0x504d4449U);
- ASSERT_EQ(header->GetVersion(), 0x02U);
+ ASSERT_EQ(header->GetVersion(), 0x03U);
ASSERT_EQ(header->GetTargetCrc(), 0x1234U);
ASSERT_EQ(header->GetOverlayCrc(), 0x5678U);
ASSERT_EQ(header->GetTargetPath().to_string(), "targetX.apk");
ASSERT_EQ(header->GetOverlayPath().to_string(), "overlayX.apk");
+ ASSERT_EQ(header->GetDebugInfo(), "debug");
}
TEST(IdmapTests, FailToCreateIdmapHeaderFromBinaryStreamIfPathTooLong) {
@@ -76,7 +78,7 @@ TEST(IdmapTests, FailToCreateIdmapHeaderFromBinaryStreamIfPathTooLong) {
}
TEST(IdmapTests, CreateIdmapDataHeaderFromBinaryStream) {
- const size_t offset = 0x210;
+ const size_t offset = 0x21c;
std::string raw(reinterpret_cast<const char*>(idmap_raw_data + offset),
idmap_raw_data_len - offset);
std::istringstream stream(raw);
@@ -88,7 +90,7 @@ TEST(IdmapTests, CreateIdmapDataHeaderFromBinaryStream) {
}
TEST(IdmapTests, CreateIdmapDataFromBinaryStream) {
- const size_t offset = 0x210;
+ const size_t offset = 0x21c;
std::string raw(reinterpret_cast<const char*>(idmap_raw_data + offset),
idmap_raw_data_len - offset);
std::istringstream stream(raw);
@@ -122,7 +124,7 @@ TEST(IdmapTests, CreateIdmapFromBinaryStream) {
ASSERT_THAT(idmap->GetHeader(), NotNull());
ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U);
- ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x02U);
+ ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x03U);
ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0x1234U);
ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), 0x5678U);
ASSERT_EQ(idmap->GetHeader()->GetTargetPath().to_string(), "targetX.apk");
@@ -174,7 +176,7 @@ TEST(IdmapTests, CreateIdmapHeaderFromApkAssets) {
ASSERT_THAT(idmap->GetHeader(), NotNull());
ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U);
- ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x02U);
+ ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x03U);
ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0x76a20829);
ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), 0xc054fb26);
ASSERT_EQ(idmap->GetHeader()->GetTargetPath().to_string(), target_apk_path);
@@ -197,8 +199,9 @@ Result<std::unique_ptr<const IdmapData>> TestIdmapDataFromApkAssets(
return Error(R"(Failed to load overlay apk "%s")", overlay_apk_path.data());
}
+ LogInfo log_info;
auto mapping = ResourceMapping::FromApkAssets(*target_apk, *overlay_apk, overlay_info,
- fulfilled_policies, enforce_overlayable);
+ fulfilled_policies, enforce_overlayable, log_info);
if (!mapping) {
return mapping.GetError();
diff --git a/cmds/idmap2/tests/RawPrintVisitorTests.cpp b/cmds/idmap2/tests/RawPrintVisitorTests.cpp
index d387880cb771..b22fdafb09bb 100644
--- a/cmds/idmap2/tests/RawPrintVisitorTests.cpp
+++ b/cmds/idmap2/tests/RawPrintVisitorTests.cpp
@@ -16,6 +16,7 @@
#include <cstdio> // fclose
#include <memory>
+#include <regex>
#include <sstream>
#include <string>
@@ -29,7 +30,16 @@ using ::testing::NotNull;
namespace android::idmap2 {
+#define ASSERT_CONTAINS_REGEX(pattern, str) \
+ do { \
+ ASSERT_TRUE(std::regex_search(str, std::regex(pattern))) \
+ << "pattern '" << pattern << "' not found in\n--------\n" \
+ << str << "--------"; \
+ } while (0)
+
TEST(RawPrintVisitorTests, CreateRawPrintVisitor) {
+ fclose(stderr); // silence expected warnings
+
const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
ASSERT_THAT(target_apk, NotNull());
@@ -46,22 +56,24 @@ TEST(RawPrintVisitorTests, CreateRawPrintVisitor) {
RawPrintVisitor visitor(stream);
(*idmap)->accept(&visitor);
- ASSERT_NE(stream.str().find("00000000: 504d4449 magic\n"), std::string::npos);
- ASSERT_NE(stream.str().find("00000004: 00000002 version\n"), std::string::npos);
- ASSERT_NE(stream.str().find("00000008: 76a20829 target crc\n"), std::string::npos);
- ASSERT_NE(stream.str().find("0000000c: c054fb26 overlay crc\n"), std::string::npos);
- ASSERT_NE(stream.str().find("00000210: 7f target package id\n"), std::string::npos);
- ASSERT_NE(stream.str().find("00000211: 7f overlay package id\n"), std::string::npos);
- ASSERT_NE(stream.str().find("00000212: 00000004 target entry count\n"), std::string::npos);
- ASSERT_NE(stream.str().find("00000216: 00000004 overlay entry count\n"), std::string::npos);
- ASSERT_NE(stream.str().find("0000021a: 00000008 string pool index offset\n"), std::string::npos);
- ASSERT_NE(stream.str().find("0000021e: 000000b4 string pool byte length\n"), std::string::npos);
- ASSERT_NE(stream.str().find("00000222: 7f010000 target id: integer/int1\n"), std::string::npos);
- ASSERT_NE(stream.str().find("00000226: 07 type: reference (dynamic)\n"),
- std::string::npos);
- ASSERT_NE(stream.str().find("00000227: 7f010000 value: integer/int1\n"), std::string::npos);
- ASSERT_NE(stream.str().find("00000246: 7f010000 overlay id: integer/int1\n"), std::string::npos);
- ASSERT_NE(stream.str().find("0000024a: 7f010000 target id: integer/int1\n"), std::string::npos);
+#define ADDRESS "[0-9a-f]{8}: "
+ ASSERT_CONTAINS_REGEX(ADDRESS "504d4449 magic\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS "00000003 version\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS "76a20829 target crc\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS "c054fb26 overlay crc\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS " 7f target package id\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS " 7f overlay package id\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS "00000004 target entry count\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS "00000004 overlay entry count\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS "00000004 overlay entry count\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS "00000008 string pool index offset\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS "000000b4 string pool byte length\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS "7f010000 target id: integer/int1\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS " 07 type: reference \\(dynamic\\)\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS "7f010000 value: integer/int1\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS "7f010000 overlay id: integer/int1\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS "7f010000 target id: integer/int1\n", stream.str());
+#undef ADDRESS
}
TEST(RawPrintVisitorTests, CreateRawPrintVisitorWithoutAccessToApks) {
@@ -78,21 +90,21 @@ TEST(RawPrintVisitorTests, CreateRawPrintVisitorWithoutAccessToApks) {
(*idmap)->accept(&visitor);
ASSERT_NE(stream.str().find("00000000: 504d4449 magic\n"), std::string::npos);
- ASSERT_NE(stream.str().find("00000004: 00000002 version\n"), std::string::npos);
+ ASSERT_NE(stream.str().find("00000004: 00000003 version\n"), std::string::npos);
ASSERT_NE(stream.str().find("00000008: 00001234 target crc\n"), std::string::npos);
ASSERT_NE(stream.str().find("0000000c: 00005678 overlay crc\n"), std::string::npos);
- ASSERT_NE(stream.str().find("00000210: 7f target package id\n"), std::string::npos);
- ASSERT_NE(stream.str().find("00000211: 7f overlay package id\n"), std::string::npos);
- ASSERT_NE(stream.str().find("00000212: 00000003 target entry count\n"), std::string::npos);
- ASSERT_NE(stream.str().find("00000216: 00000003 overlay entry count\n"), std::string::npos);
- ASSERT_NE(stream.str().find("0000021a: 00000000 string pool index offset\n"), std::string::npos);
- ASSERT_NE(stream.str().find("0000021e: 00000000 string pool byte length\n"), std::string::npos);
- ASSERT_NE(stream.str().find("00000222: 7f020000 target id\n"), std::string::npos);
- ASSERT_NE(stream.str().find("00000226: 01 type: reference\n"), std::string::npos);
- ASSERT_NE(stream.str().find("00000227: 7f020000 value\n"), std::string::npos);
-
- ASSERT_NE(stream.str().find("0000023d: 7f020000 overlay id\n"), std::string::npos);
- ASSERT_NE(stream.str().find("00000241: 7f020000 target id\n"), std::string::npos);
+ ASSERT_NE(stream.str().find("0000021c: 7f target package id\n"), std::string::npos);
+ ASSERT_NE(stream.str().find("0000021d: 7f overlay package id\n"), std::string::npos);
+ ASSERT_NE(stream.str().find("0000021e: 00000003 target entry count\n"), std::string::npos);
+ ASSERT_NE(stream.str().find("00000222: 00000003 overlay entry count\n"), std::string::npos);
+ ASSERT_NE(stream.str().find("00000226: 00000000 string pool index offset\n"), std::string::npos);
+ ASSERT_NE(stream.str().find("0000022a: 00000000 string pool byte length\n"), std::string::npos);
+ ASSERT_NE(stream.str().find("0000022e: 7f020000 target id\n"), std::string::npos);
+ ASSERT_NE(stream.str().find("00000232: 01 type: reference\n"), std::string::npos);
+ ASSERT_NE(stream.str().find("00000233: 7f020000 value\n"), std::string::npos);
+
+ ASSERT_NE(stream.str().find("00000249: 7f020000 overlay id\n"), std::string::npos);
+ ASSERT_NE(stream.str().find("0000024d: 7f020000 target id\n"), std::string::npos);
}
} // namespace android::idmap2
diff --git a/cmds/idmap2/tests/ResourceMappingTests.cpp b/cmds/idmap2/tests/ResourceMappingTests.cpp
index 64304f64d22c..39c4937b0930 100644
--- a/cmds/idmap2/tests/ResourceMappingTests.cpp
+++ b/cmds/idmap2/tests/ResourceMappingTests.cpp
@@ -25,6 +25,7 @@
#include "TestHelpers.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
+#include "idmap2/LogInfo.h"
#include "idmap2/ResourceMapping.h"
using android::Res_value;
@@ -55,8 +56,9 @@ Result<ResourceMapping> TestGetResourceMapping(const android::StringPiece& local
return Error(R"(Failed to load overlay apk "%s")", overlay_apk_path.data());
}
+ LogInfo log_info;
return ResourceMapping::FromApkAssets(*target_apk, *overlay_apk, overlay_info, fulfilled_policies,
- enforce_overlayable);
+ enforce_overlayable, log_info);
}
Result<ResourceMapping> TestGetResourceMapping(const android::StringPiece& local_target_apk_path,
diff --git a/cmds/idmap2/tests/TestHelpers.h b/cmds/idmap2/tests/TestHelpers.h
index 8868b5376796..e899589c7e61 100644
--- a/cmds/idmap2/tests/TestHelpers.h
+++ b/cmds/idmap2/tests/TestHelpers.h
@@ -30,7 +30,7 @@ const unsigned char idmap_raw_data[] = {
0x49, 0x44, 0x4d, 0x50,
// 0x4: version
- 0x02, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00,
// 0x8: target crc
0x34, 0x12, 0x00, 0x00,
@@ -74,64 +74,71 @@ const unsigned char idmap_raw_data[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // 0x210: debug string
+ // string length, including terminating null
+ 0x08, 0x00, 0x00, 0x00,
+
+ // string contents "debug\0\0\0" (padded to word alignment)
+ 0x64, 0x65, 0x62, 0x75, 0x67, 0x00, 0x00, 0x00,
+
// DATA HEADER
- // 0x210: target_package_id
+ // 0x21c: target_package_id
0x7f,
- // 0x211: overlay_package_id
+ // 0x21d: overlay_package_id
0x7f,
- // 0x212: target_entry_count
+ // 0x21e: target_entry_count
0x03, 0x00, 0x00, 0x00,
- // 0x216: overlay_entry_count
+ // 0x222: overlay_entry_count
0x03, 0x00, 0x00, 0x00,
- // 0x21a: string_pool_offset
+ // 0x226: string_pool_offset
0x00, 0x00, 0x00, 0x00,
- // 0x21e: string_pool_byte_length
+ // 0x22a: string_pool_byte_length
0x00, 0x00, 0x00, 0x00,
// TARGET ENTRIES
- // 0x222: 0x7f020000
+ // 0x22e: 0x7f020000
0x00, 0x00, 0x02, 0x7f,
- // 0x226: TYPE_REFERENCE
+ // 0x232: TYPE_REFERENCE
0x01,
- // 0x227: 0x7f020000
+ // 0x233: 0x7f020000
0x00, 0x00, 0x02, 0x7f,
- // 0x22b: 0x7f030000
+ // 0x237: 0x7f030000
0x00, 0x00, 0x03, 0x7f,
- // 0x22f: TYPE_REFERENCE
+ // 0x23b: TYPE_REFERENCE
0x01,
- // 0x230: 0x7f030000
+ // 0x23c: 0x7f030000
0x00, 0x00, 0x03, 0x7f,
- // 0x234: 0x7f030002
+ // 0x240: 0x7f030002
0x02, 0x00, 0x03, 0x7f,
- // 0x238: TYPE_REFERENCE
+ // 0x244: TYPE_REFERENCE
0x01,
- // 0x239: 0x7f030001
+ // 0x245: 0x7f030001
0x01, 0x00, 0x03, 0x7f,
// OVERLAY ENTRIES
- // 0x23d: 0x7f020000 -> 0x7f020000
+ // 0x249: 0x7f020000 -> 0x7f020000
0x00, 0x00, 0x02, 0x7f, 0x00, 0x00, 0x02, 0x7f,
- // 0x245: 0x7f030000 -> 0x7f030000
+ // 0x251: 0x7f030000 -> 0x7f030000
0x00, 0x00, 0x03, 0x7f, 0x00, 0x00, 0x03, 0x7f,
- // 0x24d: 0x7f030001 -> 0x7f030002
+ // 0x259: 0x7f030001 -> 0x7f030002
0x01, 0x00, 0x03, 0x7f, 0x02, 0x00, 0x03, 0x7f};
-const unsigned int idmap_raw_data_len = 0x255;
+const unsigned int idmap_raw_data_len = 0x261;
std::string GetTestDataPath();
diff --git a/cmds/incidentd/src/WorkDirectory.cpp b/cmds/incidentd/src/WorkDirectory.cpp
index 7e7c6421e23f..9963533c08ac 100644
--- a/cmds/incidentd/src/WorkDirectory.cpp
+++ b/cmds/incidentd/src/WorkDirectory.cpp
@@ -666,7 +666,7 @@ int64_t WorkDirectory::make_timestamp_ns_locked() {
clock_gettime(CLOCK_REALTIME, &spec);
timestampNs = int64_t(spec.tv_sec) * 1000 + spec.tv_nsec;
} while (file_exists_locked(timestampNs));
- return timestampNs;
+ return (timestampNs >= 0)? timestampNs : -timestampNs;
}
/**
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index afff61497157..7b96ce92e307 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -196,18 +196,6 @@ cc_library_shared {
"libcutils",
"libstatslog",
],
- target: {
- android: {
- shared_libs: [
- "libutils",
- ],
- },
- host: {
- static_libs: [
- "libutils",
- ],
- },
- },
}
@@ -409,7 +397,7 @@ cc_benchmark {
// ==== java proto device library (for test only) ==============================
java_library {
name: "statsdprotolite",
- sdk_version: "core_platform",
+ sdk_version: "core_current",
proto: {
type: "lite",
include_dirs: ["external/protobuf/src"],
diff --git a/cmds/statsd/src/FieldValue.cpp b/cmds/statsd/src/FieldValue.cpp
index a545fc5718d0..4385964f7f0e 100644
--- a/cmds/statsd/src/FieldValue.cpp
+++ b/cmds/statsd/src/FieldValue.cpp
@@ -435,6 +435,25 @@ bool equalDimensions(const std::vector<Matcher>& dimension_a,
return eq;
}
+bool subsetDimensions(const std::vector<Matcher>& dimension_a,
+ const std::vector<Matcher>& dimension_b) {
+ if (dimension_a.size() > dimension_b.size()) {
+ return false;
+ }
+ for (size_t i = 0; i < dimension_a.size(); ++i) {
+ bool found = false;
+ for (size_t j = 0; j < dimension_b.size(); ++j) {
+ if (dimension_a[i] == dimension_b[j]) {
+ found = true;
+ }
+ }
+ if (!found) {
+ return false;
+ }
+ }
+ return true;
+}
+
bool HasPositionANY(const FieldMatcher& matcher) {
if (matcher.has_position() && matcher.position() == Position::ANY) {
return true;
diff --git a/cmds/statsd/src/FieldValue.h b/cmds/statsd/src/FieldValue.h
index 0e033e06c203..6fc1e236c661 100644
--- a/cmds/statsd/src/FieldValue.h
+++ b/cmds/statsd/src/FieldValue.h
@@ -396,6 +396,10 @@ bool isUidField(const Field& field, const Value& value);
bool equalDimensions(const std::vector<Matcher>& dimension_a,
const std::vector<Matcher>& dimension_b);
+
+// Returns true if dimension_a is a subset of dimension_b.
+bool subsetDimensions(const std::vector<Matcher>& dimension_a,
+ const std::vector<Matcher>& dimension_b);
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/cmds/statsd/src/HashableDimensionKey.cpp b/cmds/statsd/src/HashableDimensionKey.cpp
index f9f11b267d5e..109785f649e4 100644
--- a/cmds/statsd/src/HashableDimensionKey.cpp
+++ b/cmds/statsd/src/HashableDimensionKey.cpp
@@ -152,6 +152,10 @@ bool LessThan(const vector<FieldValue>& s1, const vector<FieldValue>& s2) {
return false;
}
+bool HashableDimensionKey::operator!=(const HashableDimensionKey& that) const {
+ return !((*this) == that);
+}
+
bool HashableDimensionKey::operator==(const HashableDimensionKey& that) const {
if (mValues.size() != that.getValues().size()) {
return false;
diff --git a/cmds/statsd/src/HashableDimensionKey.h b/cmds/statsd/src/HashableDimensionKey.h
index b9b86ce13c8b..654e1358f2a1 100644
--- a/cmds/statsd/src/HashableDimensionKey.h
+++ b/cmds/statsd/src/HashableDimensionKey.h
@@ -71,6 +71,8 @@ public:
std::string toString() const;
+ bool operator!=(const HashableDimensionKey& that) const;
+
bool operator==(const HashableDimensionKey& that) const;
bool operator<(const HashableDimensionKey& that) const;
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index 68a51efb031a..c569bc1e33f7 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -284,6 +284,10 @@ private:
FRIEND_TEST(DurationMetricE2eTest, TestWithCondition);
FRIEND_TEST(DurationMetricE2eTest, TestWithSlicedCondition);
FRIEND_TEST(DurationMetricE2eTest, TestWithActivationAndSlicedCondition);
+
+ FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState);
+ FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithDimensions);
+ FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithIncorrectDimensions);
};
} // namespace statsd
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index 4d38ba03b1df..bb3a094af34a 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -1320,6 +1320,13 @@ Status StatsService::unregisterPullerCallback(int32_t atomTag, const String16& p
return Status::ok();
}
+Status StatsService::unregisterPullAtomCallback(int32_t uid, int32_t atomTag) {
+ ENFORCE_UID(AID_SYSTEM);
+ VLOG("StatsService::unregisterPullAtomCallback called.");
+ mPullerManager->UnregisterPullAtomCallback(uid, atomTag);
+ return Status::ok();
+}
+
Status StatsService::sendBinaryPushStateChangedAtom(const android::String16& trainNameIn,
const int64_t trainVersionCodeIn,
const int options,
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index 9abf415ad91f..de55ca9c38cd 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -199,6 +199,11 @@ public:
virtual Status unregisterPullerCallback(int32_t atomTag, const String16& packageName) override;
/**
+ * Binder call to unregister any existing callback for the given uid and atom.
+ */
+ virtual Status unregisterPullAtomCallback(int32_t uid, int32_t atomTag) override;
+
+ /**
* Binder call to log BinaryPushStateChanged atom.
*/
virtual Status sendBinaryPushStateChangedAtom(
diff --git a/cmds/statsd/src/atom_field_options.proto b/cmds/statsd/src/atom_field_options.proto
index 16c936c41559..6d2bd04756ac 100644
--- a/cmds/statsd/src/atom_field_options.proto
+++ b/cmds/statsd/src/atom_field_options.proto
@@ -85,5 +85,5 @@ extend google.protobuf.FieldOptions {
optional bool allow_from_any_uid = 50003 [default = false];
- optional string log_from_module = 50004;
-} \ No newline at end of file
+ optional string module = 50004;
+}
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index a20436d4bdda..815e3e668d31 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -112,9 +112,9 @@ message Atom {
TouchEventReported touch_event_reported = 34;
WakeupAlarmOccurred wakeup_alarm_occurred = 35;
KernelWakeupReported kernel_wakeup_reported = 36;
- WifiLockStateChanged wifi_lock_state_changed = 37 [(log_from_module) = "wifi"];
- WifiSignalStrengthChanged wifi_signal_strength_changed = 38 [(log_from_module) = "wifi"];
- WifiScanStateChanged wifi_scan_state_changed = 39 [(log_from_module) = "wifi"];
+ WifiLockStateChanged wifi_lock_state_changed = 37 [(module) = "wifi"];
+ WifiSignalStrengthChanged wifi_signal_strength_changed = 38 [(module) = "wifi"];
+ WifiScanStateChanged wifi_scan_state_changed = 39 [(module) = "wifi"];
PhoneSignalStrengthChanged phone_signal_strength_changed = 40;
SettingChanged setting_changed = 41;
ActivityForegroundStateChanged activity_foreground_state_changed = 42;
@@ -128,7 +128,7 @@ message Atom {
AppStartFullyDrawn app_start_fully_drawn = 50;
LmkKillOccurred lmk_kill_occurred = 51;
PictureInPictureStateChanged picture_in_picture_state_changed = 52;
- WifiMulticastLockStateChanged wifi_multicast_lock_state_changed = 53 [(log_from_module) = "wifi"];
+ WifiMulticastLockStateChanged wifi_multicast_lock_state_changed = 53 [(module) = "wifi"];
LmkStateChanged lmk_state_changed = 54;
AppStartMemoryStateCaptured app_start_memory_state_captured = 55;
ShutdownSequenceReported shutdown_sequence_reported = 56;
@@ -182,39 +182,27 @@ message Atom {
FlagFlipUpdateOccurred flag_flip_update_occurred = 101;
BinaryPushStateChanged binary_push_state_changed = 102;
DevicePolicyEvent device_policy_event = 103;
- DocsUIFileOperationCanceledReported docs_ui_file_op_canceled =
- 104 [(log_from_module) = "docsui"];
- DocsUIFileOperationCopyMoveModeReported
- docs_ui_file_op_copy_move_mode_reported =
- 105 [(log_from_module) = "docsui"];
- DocsUIFileOperationFailureReported docs_ui_file_op_failure =
- 106 [(log_from_module) = "docsui"];
- DocsUIFileOperationReported docs_ui_provider_file_op =
- 107 [(log_from_module) = "docsui"];
- DocsUIInvalidScopedAccessRequestReported
- docs_ui_invalid_scoped_access_request =
- 108 [(log_from_module) = "docsui"];
- DocsUILaunchReported docs_ui_launch_reported =
- 109 [(log_from_module) = "docsui"];
- DocsUIRootVisitedReported docs_ui_root_visited =
- 110 [(log_from_module) = "docsui"];
- DocsUIStartupMsReported docs_ui_startup_ms =
- 111 [(log_from_module) = "docsui"];
- DocsUIUserActionReported docs_ui_user_action_reported =
- 112 [(log_from_module) = "docsui"];
+ DocsUIFileOperationCanceledReported docs_ui_file_op_canceled = 104 [(module) = "docsui"];
+ DocsUIFileOperationCopyMoveModeReported docs_ui_file_op_copy_move_mode_reported =
+ 105 [(module) = "docsui"];
+ DocsUIFileOperationFailureReported docs_ui_file_op_failure = 106 [(module) = "docsui"];
+ DocsUIFileOperationReported docs_ui_provider_file_op = 107 [(module) = "docsui"];
+ DocsUIInvalidScopedAccessRequestReported docs_ui_invalid_scoped_access_request =
+ 108 [(module) = "docsui"];
+ DocsUILaunchReported docs_ui_launch_reported = 109 [(module) = "docsui"];
+ DocsUIRootVisitedReported docs_ui_root_visited = 110 [(module) = "docsui"];
+ DocsUIStartupMsReported docs_ui_startup_ms = 111 [(module) = "docsui"];
+ DocsUIUserActionReported docs_ui_user_action_reported = 112 [(module) = "docsui"];
WifiEnabledStateChanged wifi_enabled_state_changed = 113;
WifiRunningStateChanged wifi_running_state_changed = 114;
AppCompacted app_compacted = 115;
- NetworkDnsEventReported network_dns_event_reported = 116 [(log_from_module) = "resolv"];
+ NetworkDnsEventReported network_dns_event_reported = 116 [(module) = "resolv"];
DocsUIPickerLaunchedFromReported docs_ui_picker_launched_from_reported =
- 117 [(log_from_module) = "docsui"];
- DocsUIPickResultReported docs_ui_pick_result_reported =
- 118 [(log_from_module) = "docsui"];
- DocsUISearchModeReported docs_ui_search_mode_reported =
- 119 [(log_from_module) = "docsui"];
- DocsUISearchTypeReported docs_ui_search_type_reported =
- 120 [(log_from_module) = "docsui"];
- DataStallEvent data_stall_event = 121 [(log_from_module) = "network_stack"];
+ 117 [(module) = "docsui"];
+ DocsUIPickResultReported docs_ui_pick_result_reported = 118 [(module) = "docsui"];
+ DocsUISearchModeReported docs_ui_search_mode_reported = 119 [(module) = "docsui"];
+ DocsUISearchTypeReported docs_ui_search_type_reported = 120 [(module) = "docsui"];
+ DataStallEvent data_stall_event = 121 [(module) = "network_stack"];
RescuePartyResetReported rescue_party_reset_reported = 122;
SignedConfigReported signed_config_reported = 123;
GnssNiEventReported gnss_ni_event_reported = 124;
@@ -264,7 +252,7 @@ message Atom {
ScreenTimeoutExtensionReported screen_timeout_extension_reported = 168;
ProcessStartTime process_start_time = 169;
PermissionGrantRequestResultReported permission_grant_request_result_reported =
- 170 [(log_from_module) = "permissioncontroller"];
+ 170 [(module) = "permissioncontroller"];
BluetoothSocketConnectionStateChanged bluetooth_socket_connection_state_changed = 171;
DeviceIdentifierAccessDenied device_identifier_access_denied = 172;
BubbleDeveloperErrorReported bubble_developer_error_reported = 173;
@@ -273,21 +261,21 @@ message Atom {
AssistGestureProgressReported assist_gesture_progress_reported = 176;
TouchGestureClassified touch_gesture_classified = 177;
HiddenApiUsed hidden_api_used = 178 [(allow_from_any_uid) = true];
- StyleUIChanged style_ui_changed = 179 [(log_from_module) = "style"];
+ StyleUIChanged style_ui_changed = 179 [(module) = "style"];
PrivacyIndicatorsInteracted privacy_indicators_interacted =
- 180 [(log_from_module) = "permissioncontroller"];
+ 180 [(module) = "permissioncontroller"];
AppInstallOnExternalStorageReported app_install_on_external_storage_reported = 181;
- NetworkStackReported network_stack_reported = 182 [(log_from_module) = "network_stack"];
+ NetworkStackReported network_stack_reported = 182 [(module) = "network_stack"];
AppMovedStorageReported app_moved_storage_reported = 183;
BiometricEnrolled biometric_enrolled = 184;
SystemServerWatchdogOccurred system_server_watchdog_occurred = 185;
TombStoneOccurred tomb_stone_occurred = 186;
BluetoothClassOfDeviceReported bluetooth_class_of_device_reported = 187;
IntelligenceEventReported intelligence_event_reported =
- 188 [(log_from_module) = "intelligence"];
+ 188 [(module) = "intelligence"];
ThermalThrottlingSeverityStateChanged thermal_throttling_severity_state_changed = 189;
RoleRequestResultReported role_request_result_reported =
- 190 [(log_from_module) = "permissioncontroller"];
+ 190 [(module) = "permissioncontroller"];
MediametricsAudiopolicyReported mediametrics_audiopolicy_reported = 191;
MediametricsAudiorecordReported mediametrics_audiorecord_reported = 192;
MediametricsAudiothreadReported mediametrics_audiothread_reported = 193;
@@ -301,36 +289,32 @@ message Atom {
MediametricsDrmManagerReported mediametrics_drmmanager_reported = 201;
CarPowerStateChanged car_power_state_changed = 203;
GarageModeInfo garage_mode_info = 204;
- TestAtomReported test_atom_reported = 205 [(log_from_module) = "cts"];
+ TestAtomReported test_atom_reported = 205 [(module) = "cts"];
ContentCaptureCallerMismatchReported content_capture_caller_mismatch_reported = 206;
ContentCaptureServiceEvents content_capture_service_events = 207;
ContentCaptureSessionEvents content_capture_session_events = 208;
ContentCaptureFlushed content_capture_flushed = 209;
LocationManagerApiUsageReported location_manager_api_usage_reported = 210;
ReviewPermissionsFragmentResultReported review_permissions_fragment_result_reported =
- 211 [(log_from_module) = "permissioncontroller"];
+ 211 [(module) = "permissioncontroller"];
RuntimePermissionsUpgradeResult runtime_permissions_upgrade_result =
- 212 [(log_from_module) = "permissioncontroller"];
+ 212 [(module) = "permissioncontroller"];
GrantPermissionsActivityButtonActions grant_permissions_activity_button_actions =
- 213 [(log_from_module) = "permissioncontroller"];
+ 213 [(module) = "permissioncontroller"];
LocationAccessCheckNotificationAction location_access_check_notification_action =
- 214 [(log_from_module) = "permissioncontroller"];
+ 214 [(module) = "permissioncontroller"];
AppPermissionFragmentActionReported app_permission_fragment_action_reported =
- 215 [(log_from_module) = "permissioncontroller"];
+ 215 [(module) = "permissioncontroller"];
AppPermissionFragmentViewed app_permission_fragment_viewed =
- 216 [(log_from_module) = "permissioncontroller"];
+ 216 [(module) = "permissioncontroller"];
AppPermissionsFragmentViewed app_permissions_fragment_viewed =
- 217 [(log_from_module) = "permissioncontroller"];
+ 217 [(module) = "permissioncontroller"];
PermissionAppsFragmentViewed permission_apps_fragment_viewed =
- 218 [(log_from_module) = "permissioncontroller"];
- TextSelectionEvent text_selection_event =
- 219 [(log_from_module) = "textclassifier"];
- TextLinkifyEvent text_linkify_event =
- 220 [(log_from_module) = "textclassifier"];
- ConversationActionsEvent conversation_actions_event =
- 221 [(log_from_module) = "textclassifier"];
- LanguageDetectionEvent language_detection_event =
- 222 [(log_from_module) = "textclassifier"];
+ 218 [(module) = "permissioncontroller"];
+ TextSelectionEvent text_selection_event = 219 [(module) = "textclassifier"];
+ TextLinkifyEvent text_linkify_event = 220 [(module) = "textclassifier"];
+ ConversationActionsEvent conversation_actions_event = 221 [(module) = "textclassifier"];
+ LanguageDetectionEvent language_detection_event = 222 [(module) = "textclassifier"];
ExclusionRectStateChanged exclusion_rect_state_changed = 223;
BackGesture back_gesture_reported_reported = 224;
UpdateEngineUpdateAttemptReported update_engine_update_attempt_reported = 225;
@@ -338,25 +322,21 @@ message Atom {
CameraActionEvent camera_action_event = 227;
AppCompatibilityChangeReported app_compatibility_change_reported =
228 [(allow_from_any_uid) = true];
- PerfettoUploaded perfetto_uploaded =
- 229 [(log_from_module) = "perfetto"];
+ PerfettoUploaded perfetto_uploaded = 229 [(module) = "perfetto"];
VmsClientConnectionStateChanged vms_client_connection_state_changed = 230;
GpsLocationStatusReported gps_location_status_reported = 231;
GpsTimeToFirstFixReported gps_time_to_first_fix_reported = 232;
- MediaProviderScanEvent media_provider_scan_event =
- 233 [(log_from_module) = "mediaprovider"];
- MediaProviderDeletionEvent media_provider_deletion_event =
- 234 [(log_from_module) = "mediaprovider"];
+ MediaProviderScanEvent media_provider_scan_event = 233 [(module) = "mediaprovider"];
+ MediaProviderDeletionEvent media_provider_deletion_event = 234 [(module) = "mediaprovider"];
MediaProviderPermissionEvent media_provider_permission_event =
- 235 [(log_from_module) = "mediaprovider"];
- MediaProviderSchemaChange media_provider_schema_change =
- 236 [(log_from_module) = "mediaprovider"];
+ 235 [(module) = "mediaprovider"];
+ MediaProviderSchemaChange media_provider_schema_change = 236 [(module) = "mediaprovider"];
MediaProviderIdleMaintenance media_provider_idle_maintenance =
- 237 [(log_from_module) = "mediaprovider"];
+ 237 [(module) = "mediaprovider"];
}
// Pulled events will start at field 10000.
- // Next: 10067
+ // Next: 10068
oneof pulled {
WifiBytesTransfer wifi_bytes_transfer = 10000;
WifiBytesTransferByFgBg wifi_bytes_transfer_by_fg_bg = 10001;
@@ -424,6 +404,7 @@ message Atom {
ProcessMemorySnapshot process_memory_snapshot = 10064;
VmsClientStats vms_client_stats = 10065;
NotificationRemoteViews notification_remote_views = 10066;
+ DangerousPermissionStateSampled dangerous_permission_state_sampled = 10067;
}
// DO NOT USE field numbers above 100,000 in AOSP.
@@ -5994,6 +5975,14 @@ message PermissionGrantRequestResultReported {
USER_GRANTED_ONE_TIME = 10;
// user ignored request by leaving the request screen without choosing any option
USER_IGNORED = 11;
+ // user granted the permission after being linked to settings
+ USER_GRANTED_IN_SETTINGS = 12;
+ // user denied the permission after being linked to settings
+ USER_DENIED_IN_SETTINGS = 13;
+ // user denied the permission with prejudice after being linked to settings
+ USER_DENIED_WITH_PREJUDICE_IN_SETTINGS = 14;
+ // permission was automatically revoked after one-time permission expired
+ AUTO_ONE_TIME_PERMISSION_REVOKED = 15;
}
// The result of the permission grant
optional Result result = 6;
@@ -6490,7 +6479,8 @@ message MediametricsDrmManagerReported {
/**
* State of a dangerous permission requested by a package
- */
+ * Pulled from: StatsCompanionService
+*/
message DangerousPermissionState {
// Name of the permission
optional string permission_name = 1;
@@ -7541,3 +7531,22 @@ message VmsClientStats {
optional int64 dropped_bytes = 9;
optional int64 dropped_packets = 10;
}
+
+/**
+ * State of a dangerous permission requested by a package - sampled
+ * Pulled from: StatsCompanionService.java with data obtained from PackageManager API
+*/
+message DangerousPermissionStateSampled {
+ // Name of the permission
+ optional string permission_name = 1;
+
+ // Uid of the package
+ optional int32 uid = 2 [(is_uid) = true];
+
+ // If the permission is granted to the uid
+ optional bool is_granted = 3;
+
+ // Permission flags as per android.content.pm.PermissionFlags
+ optional int32 permission_flags = 4;
+}
+
diff --git a/cmds/statsd/src/external/StatsPuller.cpp b/cmds/statsd/src/external/StatsPuller.cpp
index 3c6bc2db1d62..883bd28a4d13 100644
--- a/cmds/statsd/src/external/StatsPuller.cpp
+++ b/cmds/statsd/src/external/StatsPuller.cpp
@@ -47,6 +47,7 @@ bool StatsPuller::Pull(std::vector<std::shared_ptr<LogEvent>>* data) {
if (mHasGoodData) {
(*data) = mCachedData;
StatsdStats::getInstance().notePullFromCache(mTagId);
+
}
return mHasGoodData;
}
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index 9ee627efa841..50896f84da43 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -284,12 +284,21 @@ std::map<PullerKey, PullAtomInfo> StatsPullerManager::kAllPullAtomInfo = {
// NotiifcationRemoteViews.
{{.atomTag = android::util::NOTIFICATION_REMOTE_VIEWS},
{.puller = new StatsCompanionServicePuller(android::util::NOTIFICATION_REMOTE_VIEWS)}},
+ // PermissionStateSampled.
+ {{.atomTag = android::util::DANGEROUS_PERMISSION_STATE_SAMPLED},
+ {.puller =
+ new StatsCompanionServicePuller(android::util::DANGEROUS_PERMISSION_STATE_SAMPLED)}},
};
StatsPullerManager::StatsPullerManager() : mNextPullTimeNs(NO_ALARM_UPDATE) {
}
bool StatsPullerManager::Pull(int tagId, vector<shared_ptr<LogEvent>>* data) {
+ AutoMutex _l(mLock);
+ return PullLocked(tagId, data);
+}
+
+bool StatsPullerManager::PullLocked(int tagId, vector<shared_ptr<LogEvent>>* data) {
VLOG("Initiating pulling %d", tagId);
if (kAllPullAtomInfo.find({.atomTag = tagId}) != kAllPullAtomInfo.end()) {
@@ -418,7 +427,7 @@ void StatsPullerManager::OnAlarmFired(int64_t elapsedTimeNs) {
for (const auto& pullInfo : needToPull) {
vector<shared_ptr<LogEvent>> data;
- bool pullSuccess = Pull(pullInfo.first, &data);
+ bool pullSuccess = PullLocked(pullInfo.first, &data);
if (pullSuccess) {
StatsdStats::getInstance().notePullDelay(
pullInfo.first, getElapsedRealtimeNs() - elapsedTimeNs);
@@ -518,6 +527,12 @@ void StatsPullerManager::UnregisterPullerCallback(int32_t atomTag) {
kAllPullAtomInfo.erase({.atomTag = atomTag});
}
+void StatsPullerManager::UnregisterPullAtomCallback(const int uid, const int32_t atomTag) {
+ AutoMutex _l(mLock);
+ StatsdStats::getInstance().notePullerCallbackRegistrationChanged(atomTag, /*registered=*/false);
+ kAllPullAtomInfo.erase({.atomTag = atomTag});
+}
+
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/cmds/statsd/src/external/StatsPullerManager.h b/cmds/statsd/src/external/StatsPullerManager.h
index 1bd9f92e4448..349fd47b6c9d 100644
--- a/cmds/statsd/src/external/StatsPullerManager.h
+++ b/cmds/statsd/src/external/StatsPullerManager.h
@@ -125,6 +125,8 @@ public:
void UnregisterPullerCallback(int32_t atomTag);
+ void UnregisterPullAtomCallback(const int uid, const int32_t atomTag);
+
static std::map<PullerKey, PullAtomInfo> kAllPullAtomInfo;
private:
@@ -139,6 +141,8 @@ private:
// mapping from simple matcher tagId to receivers
std::map<int, std::list<ReceiverInfo>> mReceivers;
+ bool PullLocked(int tagId, vector<std::shared_ptr<LogEvent>>* data);
+
// locks for data receiver and StatsCompanionService changes
Mutex mLock;
diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h
index 564b9ee8051c..692d91e1a82f 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.h
+++ b/cmds/statsd/src/guardrail/StatsdStats.h
@@ -181,6 +181,8 @@ public:
static const int64_t kInt64Max = 0x7fffffffffffffffLL;
+ static const int32_t kMaxLoggedBucketDropEvents = 10;
+
/**
* Report a new config has been received and report the static stats about the config.
*
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp
index c1f95ee58217..21ffff32f539 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp
@@ -277,8 +277,8 @@ bool CountMetricProducer::hitGuardRailLocked(const MetricDimensionKey& newKey) {
void CountMetricProducer::onMatchedLogEventInternalLocked(
const size_t matcherIndex, const MetricDimensionKey& eventKey,
- const ConditionKey& conditionKey, bool condition,
- const LogEvent& event) {
+ const ConditionKey& conditionKey, bool condition, const LogEvent& event,
+ const map<int, HashableDimensionKey>& statePrimaryKeys) {
int64_t eventTimeNs = event.GetElapsedTimestampNs();
flushIfNeededLocked(eventTimeNs);
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.h b/cmds/statsd/src/metrics/CountMetricProducer.h
index 7b6c7e0ef0be..a4711e8357f2 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.h
+++ b/cmds/statsd/src/metrics/CountMetricProducer.h
@@ -59,8 +59,8 @@ public:
protected:
void onMatchedLogEventInternalLocked(
const size_t matcherIndex, const MetricDimensionKey& eventKey,
- const ConditionKey& conditionKey, bool condition,
- const LogEvent& event) override;
+ const ConditionKey& conditionKey, bool condition, const LogEvent& event,
+ const std::map<int, HashableDimensionKey>& statePrimaryKeys) override;
private:
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index fee5e6e3cb46..35c6d373418e 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -541,8 +541,8 @@ void DurationMetricProducer::handleStartEvent(const MetricDimensionKey& eventKey
void DurationMetricProducer::onMatchedLogEventInternalLocked(
const size_t matcherIndex, const MetricDimensionKey& eventKey,
- const ConditionKey& conditionKeys, bool condition,
- const LogEvent& event) {
+ const ConditionKey& conditionKeys, bool condition, const LogEvent& event,
+ const map<int, HashableDimensionKey>& statePrimaryKeys) {
ALOGW("Not used in duration tracker.");
}
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.h b/cmds/statsd/src/metrics/DurationMetricProducer.h
index 7457d7fb2dd9..45908fb48f75 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.h
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.h
@@ -59,8 +59,8 @@ protected:
void onMatchedLogEventInternalLocked(
const size_t matcherIndex, const MetricDimensionKey& eventKey,
- const ConditionKey& conditionKeys, bool condition,
- const LogEvent& event) override;
+ const ConditionKey& conditionKeys, bool condition, const LogEvent& event,
+ const std::map<int, HashableDimensionKey>& statePrimaryKeys) override;
private:
void handleStartEvent(const MetricDimensionKey& eventKey, const ConditionKey& conditionKeys,
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.cpp b/cmds/statsd/src/metrics/EventMetricProducer.cpp
index 32eb077e1cf4..6833f8dd0114 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/EventMetricProducer.cpp
@@ -143,8 +143,8 @@ void EventMetricProducer::onConditionChangedLocked(const bool conditionMet,
void EventMetricProducer::onMatchedLogEventInternalLocked(
const size_t matcherIndex, const MetricDimensionKey& eventKey,
- const ConditionKey& conditionKey, bool condition,
- const LogEvent& event) {
+ const ConditionKey& conditionKey, bool condition, const LogEvent& event,
+ const map<int, HashableDimensionKey>& statePrimaryKeys) {
if (!condition) {
return;
}
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.h b/cmds/statsd/src/metrics/EventMetricProducer.h
index dca37e8790a4..e8f2119a170c 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.h
+++ b/cmds/statsd/src/metrics/EventMetricProducer.h
@@ -47,8 +47,8 @@ public:
private:
void onMatchedLogEventInternalLocked(
const size_t matcherIndex, const MetricDimensionKey& eventKey,
- const ConditionKey& conditionKey, bool condition,
- const LogEvent& event) override;
+ const ConditionKey& conditionKey, bool condition, const LogEvent& event,
+ const std::map<int, HashableDimensionKey>& statePrimaryKeys) override;
void onDumpReportLocked(const int64_t dumpTimeNs,
const bool include_current_partial_bucket,
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index 64344e837a51..4ab6fd48f1db 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -52,8 +52,13 @@ const int FIELD_ID_IS_ACTIVE = 14;
// for GaugeMetricDataWrapper
const int FIELD_ID_DATA = 1;
const int FIELD_ID_SKIPPED = 2;
+// for SkippedBuckets
const int FIELD_ID_SKIPPED_START_MILLIS = 3;
const int FIELD_ID_SKIPPED_END_MILLIS = 4;
+const int FIELD_ID_SKIPPED_DROP_EVENT = 5;
+// for DumpEvent Proto
+const int FIELD_ID_BUCKET_DROP_REASON = 1;
+const int FIELD_ID_DROP_TIME = 2;
// for GaugeMetricData
const int FIELD_ID_DIMENSION_IN_WHAT = 1;
const int FIELD_ID_BUCKET_INFO = 3;
@@ -193,7 +198,7 @@ void GaugeMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_ID, (long long)mMetricId);
protoOutput->write(FIELD_TYPE_BOOL | FIELD_ID_IS_ACTIVE, isActiveLocked());
- if (mPastBuckets.empty()) {
+ if (mPastBuckets.empty() && mSkippedBuckets.empty()) {
return;
}
@@ -212,13 +217,21 @@ void GaugeMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
uint64_t protoToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_GAUGE_METRICS);
- for (const auto& pair : mSkippedBuckets) {
+ for (const auto& skippedBucket : mSkippedBuckets) {
uint64_t wrapperToken =
protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_SKIPPED);
protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_SKIPPED_START_MILLIS,
- (long long)(NanoToMillis(pair.first)));
+ (long long)(NanoToMillis(skippedBucket.bucketStartTimeNs)));
protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_SKIPPED_END_MILLIS,
- (long long)(NanoToMillis(pair.second)));
+ (long long)(NanoToMillis(skippedBucket.bucketEndTimeNs)));
+
+ for (const auto& dropEvent : skippedBucket.dropEvents) {
+ uint64_t dropEventToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
+ FIELD_ID_SKIPPED_DROP_EVENT);
+ protoOutput->write(FIELD_TYPE_INT32 | FIELD_ID_BUCKET_DROP_REASON, dropEvent.reason);
+ protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_DROP_TIME, (long long) (NanoToMillis(dropEvent.dropTimeNs)));
+ protoOutput->end(dropEventToken);
+ }
protoOutput->end(wrapperToken);
}
@@ -436,8 +449,8 @@ bool GaugeMetricProducer::hitGuardRailLocked(const MetricDimensionKey& newKey) {
void GaugeMetricProducer::onMatchedLogEventInternalLocked(
const size_t matcherIndex, const MetricDimensionKey& eventKey,
- const ConditionKey& conditionKey, bool condition,
- const LogEvent& event) {
+ const ConditionKey& conditionKey, bool condition, const LogEvent& event,
+ const map<int, HashableDimensionKey>& statePrimaryKeys) {
if (condition == false) {
return;
}
@@ -545,7 +558,10 @@ void GaugeMetricProducer::flushCurrentBucketLocked(const int64_t& eventTimeNs,
info.mBucketEndNs = fullBucketEndTimeNs;
}
- if (info.mBucketEndNs - mCurrentBucketStartTimeNs >= mMinBucketSizeNs) {
+ // Add bucket to mPastBuckets if bucket is large enough.
+ // Otherwise, drop the bucket data and add bucket metadata to mSkippedBuckets.
+ bool isBucketLargeEnough = info.mBucketEndNs - mCurrentBucketStartTimeNs >= mMinBucketSizeNs;
+ if (isBucketLargeEnough) {
for (const auto& slice : *mCurrentSlicedBucket) {
info.mGaugeAtoms = slice.second;
auto& bucketList = mPastBuckets[slice.first];
@@ -554,7 +570,13 @@ void GaugeMetricProducer::flushCurrentBucketLocked(const int64_t& eventTimeNs,
slice.first.toString().c_str());
}
} else {
- mSkippedBuckets.emplace_back(info.mBucketStartNs, info.mBucketEndNs);
+ mCurrentSkippedBucket.bucketStartTimeNs = mCurrentBucketStartTimeNs;
+ mCurrentSkippedBucket.bucketEndTimeNs = eventTimeNs;
+ if (!maxDropEventsReached()) {
+ mCurrentSkippedBucket.dropEvents.emplace_back(
+ buildDropEvent(eventTimeNs, BucketDropReason::BUCKET_TOO_SMALL));
+ }
+ mSkippedBuckets.emplace_back(mCurrentSkippedBucket);
}
// If we have anomaly trackers, we need to update the partial bucket values.
@@ -573,6 +595,7 @@ void GaugeMetricProducer::flushCurrentBucketLocked(const int64_t& eventTimeNs,
StatsdStats::getInstance().noteBucketCount(mMetricId);
mCurrentSlicedBucket = std::make_shared<DimToGaugeAtomsMap>();
mCurrentBucketStartTimeNs = nextBucketStartTimeNs;
+ mCurrentSkippedBucket.reset();
}
size_t GaugeMetricProducer::byteSizeLocked() const {
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h
index 640a02a9a8ab..284bcc5d10aa 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.h
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h
@@ -95,8 +95,8 @@ public:
protected:
void onMatchedLogEventInternalLocked(
const size_t matcherIndex, const MetricDimensionKey& eventKey,
- const ConditionKey& conditionKey, bool condition,
- const LogEvent& event) override;
+ const ConditionKey& conditionKey, bool condition, const LogEvent& event,
+ const std::map<int, HashableDimensionKey>& statePrimaryKeys) override;
private:
void onDumpReportLocked(const int64_t dumpTimeNs,
@@ -158,9 +158,6 @@ private:
// this slice (ie, for partial buckets, we use the last partial bucket in this full bucket).
std::shared_ptr<DimToValMap> mCurrentSlicedBucketForAnomaly;
- // Pairs of (elapsed start, elapsed end) denoting buckets that were skipped.
- std::list<std::pair<int64_t, int64_t>> mSkippedBuckets;
-
const int64_t mMinBucketSizeNs;
// Translate Atom based bucket to single numeric value bucket for anomaly and updates the map
diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp
index 2c8f0e3d545f..5c29cb3c27fe 100644
--- a/cmds/statsd/src/metrics/MetricProducer.cpp
+++ b/cmds/statsd/src/metrics/MetricProducer.cpp
@@ -19,6 +19,7 @@
#include "MetricProducer.h"
+#include "../guardrail/StatsdStats.h"
#include "state/StateTracker.h"
using android::util::FIELD_COUNT_REPEATED;
@@ -132,8 +133,8 @@ void MetricProducer::onMatchedLogEventLocked(const size_t matcherIndex, const Lo
HashableDimensionKey dimensionInWhat;
filterValues(mDimensionsInWhat, event.getValues(), &dimensionInWhat);
MetricDimensionKey metricKey(dimensionInWhat, stateValuesKey);
- onMatchedLogEventInternalLocked(
- matcherIndex, metricKey, conditionKey, condition, event);
+ onMatchedLogEventInternalLocked(matcherIndex, metricKey, conditionKey, condition, event,
+ statePrimaryKeys);
}
bool MetricProducer::evaluateActiveStateLocked(int64_t elapsedTimestampNs) {
@@ -268,6 +269,7 @@ void MetricProducer::getMappedStateValue(const int32_t atomId, const HashableDim
FieldValue* value) {
if (!StateManager::getInstance().getStateValue(atomId, queryKey, value)) {
value->mValue = Value(StateTracker::kStateUnknown);
+ value->mField.setTag(atomId);
ALOGW("StateTracker not found for state atom %d", atomId);
return;
}
@@ -289,6 +291,17 @@ void MetricProducer::getMappedStateValue(const int32_t atomId, const HashableDim
}
}
+DropEvent MetricProducer::buildDropEvent(const int64_t dropTimeNs, const BucketDropReason reason) {
+ DropEvent event;
+ event.reason = reason;
+ event.dropTimeNs = dropTimeNs;
+ return event;
+}
+
+bool MetricProducer::maxDropEventsReached() {
+ return mCurrentSkippedBucket.dropEvents.size() >= StatsdStats::kMaxLoggedBucketDropEvents;
+}
+
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index 3512f180e9de..99f0c64bd47c 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -70,6 +70,22 @@ enum DumpLatency {
NO_TIME_CONSTRAINTS = 2
};
+// Keep this in sync with BucketDropReason enum in stats_log.proto
+enum BucketDropReason {
+ // For ValueMetric, a bucket is dropped during a dump report request iff
+ // current bucket should be included, a pull is needed (pulled metric and
+ // condition is true), and we are under fast time constraints.
+ DUMP_REPORT_REQUESTED = 1,
+ EVENT_IN_WRONG_BUCKET = 2,
+ CONDITION_UNKNOWN = 3,
+ PULL_FAILED = 4,
+ PULL_DELAYED = 5,
+ DIMENSION_GUARDRAIL_REACHED = 6,
+ MULTIPLE_BUCKETS_SKIPPED = 7,
+ // Not an invalid bucket case, but the bucket is dropped.
+ BUCKET_TOO_SMALL = 8
+};
+
struct Activation {
Activation(const ActivationType& activationType, const int64_t ttlNs)
: ttl_ns(ttlNs),
@@ -83,6 +99,28 @@ struct Activation {
const ActivationType activationType;
};
+struct DropEvent {
+ // Reason for dropping the bucket and/or marking the bucket invalid.
+ BucketDropReason reason;
+ // The timestamp of the drop event.
+ int64_t dropTimeNs;
+};
+
+struct SkippedBucket {
+ // Start time of the dropped bucket.
+ int64_t bucketStartTimeNs;
+ // End time of the dropped bucket.
+ int64_t bucketEndTimeNs;
+ // List of events that invalidated this bucket.
+ std::vector<DropEvent> dropEvents;
+
+ void reset() {
+ bucketStartTimeNs = 0;
+ bucketEndTimeNs = 0;
+ dropEvents.clear();
+ }
+};
+
// A MetricProducer is responsible for compute one single metrics, creating stats log report, and
// writing the report to dropbox. MetricProducers should respond to package changes as required in
// PackageInfoListener, but if none of the metrics are slicing by package name, then the update can
@@ -292,8 +330,8 @@ protected:
*/
virtual void onMatchedLogEventInternalLocked(
const size_t matcherIndex, const MetricDimensionKey& eventKey,
- const ConditionKey& conditionKey, bool condition,
- const LogEvent& event) = 0;
+ const ConditionKey& conditionKey, bool condition, const LogEvent& event,
+ const map<int, HashableDimensionKey>& statePrimaryKeys) = 0;
// Consume the parsed stats log entry that already matched the "what" of the metric.
virtual void onMatchedLogEventLocked(const size_t matcherIndex, const LogEvent& event);
@@ -342,6 +380,12 @@ protected:
void getMappedStateValue(const int32_t atomId, const HashableDimensionKey& queryKey,
FieldValue* value);
+ DropEvent buildDropEvent(const int64_t dropTimeNs, const BucketDropReason reason);
+
+ // Returns true if the number of drop events in the current bucket has
+ // exceeded the maximum number allowed, which is currently capped at 10.
+ bool maxDropEventsReached();
+
const int64_t mMetricId;
const ConfigKey mConfigKey;
@@ -403,6 +447,10 @@ protected:
// atom to fields in the "what" atom.
std::vector<Metric2State> mMetric2StateLinks;
+ SkippedBucket mCurrentSkippedBucket;
+ // Buckets that were invalidated and had their data dropped.
+ std::vector<SkippedBucket> mSkippedBuckets;
+
FRIEND_TEST(CountMetricE2eTest, TestSlicedState);
FRIEND_TEST(CountMetricE2eTest, TestSlicedStateWithMap);
FRIEND_TEST(CountMetricE2eTest, TestMultipleSlicedStates);
@@ -427,6 +475,10 @@ protected:
FRIEND_TEST(StatsLogProcessorTest,
TestActivationOnBootMultipleActivationsDifferentActivationTypes);
FRIEND_TEST(StatsLogProcessorTest, TestActivationsPersistAcrossSystemServerRestart);
+
+ FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState);
+ FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithDimensions);
+ FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithIncorrectDimensions);
};
} // namespace statsd
diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h
index 1fda6960b59b..6d20822fd54c 100644
--- a/cmds/statsd/src/metrics/MetricsManager.h
+++ b/cmds/statsd/src/metrics/MetricsManager.h
@@ -289,6 +289,10 @@ private:
FRIEND_TEST(DurationMetricE2eTest, TestWithCondition);
FRIEND_TEST(DurationMetricE2eTest, TestWithSlicedCondition);
FRIEND_TEST(DurationMetricE2eTest, TestWithActivationAndSlicedCondition);
+
+ FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState);
+ FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithDimensions);
+ FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithIncorrectDimensions);
};
} // namespace statsd
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index 2c9991125d89..d2db6e9c9ead 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -55,12 +55,18 @@ const int FIELD_ID_IS_ACTIVE = 14;
// for ValueMetricDataWrapper
const int FIELD_ID_DATA = 1;
const int FIELD_ID_SKIPPED = 2;
+// for SkippedBuckets
const int FIELD_ID_SKIPPED_START_MILLIS = 3;
const int FIELD_ID_SKIPPED_END_MILLIS = 4;
+const int FIELD_ID_SKIPPED_DROP_EVENT = 5;
+// for DumpEvent Proto
+const int FIELD_ID_BUCKET_DROP_REASON = 1;
+const int FIELD_ID_DROP_TIME = 2;
// for ValueMetricData
const int FIELD_ID_DIMENSION_IN_WHAT = 1;
const int FIELD_ID_BUCKET_INFO = 3;
const int FIELD_ID_DIMENSION_LEAF_IN_WHAT = 4;
+const int FIELD_ID_SLICE_BY_STATE = 6;
// for ValueBucketInfo
const int FIELD_ID_VALUE_INDEX = 1;
const int FIELD_ID_VALUE_LONG = 2;
@@ -141,6 +147,14 @@ ValueMetricProducer::ValueMetricProducer(
mConditionSliced = true;
}
+ for (const auto& stateLink : metric.state_link()) {
+ Metric2State ms;
+ ms.stateAtomId = stateLink.state_atom_id();
+ translateFieldMatcher(stateLink.fields_in_what(), &ms.metricFields);
+ translateFieldMatcher(stateLink.fields_in_state(), &ms.stateFields);
+ mMetric2StateLinks.push_back(ms);
+ }
+
int64_t numBucketsForward = calcBucketsForwardCount(startTimeNs);
mCurrentBucketNum += numBucketsForward;
@@ -176,6 +190,33 @@ ValueMetricProducer::~ValueMetricProducer() {
}
}
+void ValueMetricProducer::onStateChanged(int64_t eventTimeNs, int32_t atomId,
+ const HashableDimensionKey& primaryKey, int oldState,
+ int newState) {
+ VLOG("ValueMetric %lld onStateChanged time %lld, State %d, key %s, %d -> %d",
+ (long long)mMetricId, (long long)eventTimeNs, atomId, primaryKey.toString().c_str(),
+ oldState, newState);
+ // If condition is not true, we do not need to pull for this state change.
+ if (mCondition != ConditionState::kTrue) {
+ return;
+ }
+ bool isEventLate = eventTimeNs < mCurrentBucketStartTimeNs;
+ if (isEventLate) {
+ VLOG("Skip event due to late arrival: %lld vs %lld", (long long)eventTimeNs,
+ (long long)mCurrentBucketStartTimeNs);
+ invalidateCurrentBucket(eventTimeNs, BucketDropReason::EVENT_IN_WRONG_BUCKET);
+ return;
+ }
+ mStateChangePrimaryKey.first = atomId;
+ mStateChangePrimaryKey.second = primaryKey;
+ if (mIsPulled) {
+ pullAndMatchEventsLocked(eventTimeNs);
+ }
+ mStateChangePrimaryKey.first = 0;
+ mStateChangePrimaryKey.second = DEFAULT_DIMENSION_KEY;
+ flushIfNeededLocked(eventTimeNs);
+}
+
void ValueMetricProducer::onSlicedConditionMayChangeLocked(bool overallCondition,
const int64_t eventTime) {
VLOG("Metric %lld onSlicedConditionMayChange", (long long)mMetricId);
@@ -211,7 +252,7 @@ void ValueMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
if (pullNeeded) {
switch (dumpLatency) {
case FAST:
- invalidateCurrentBucket();
+ invalidateCurrentBucket(dumpTimeNs, BucketDropReason::DUMP_REPORT_REQUESTED);
break;
case NO_TIME_CONSTRAINTS:
pullAndMatchEventsLocked(dumpTimeNs);
@@ -240,13 +281,22 @@ void ValueMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
uint64_t protoToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_VALUE_METRICS);
- for (const auto& pair : mSkippedBuckets) {
+ for (const auto& skippedBucket : mSkippedBuckets) {
uint64_t wrapperToken =
protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_SKIPPED);
protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_SKIPPED_START_MILLIS,
- (long long)(NanoToMillis(pair.first)));
+ (long long)(NanoToMillis(skippedBucket.bucketStartTimeNs)));
protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_SKIPPED_END_MILLIS,
- (long long)(NanoToMillis(pair.second)));
+ (long long)(NanoToMillis(skippedBucket.bucketEndTimeNs)));
+ for (const auto& dropEvent : skippedBucket.dropEvents) {
+ uint64_t dropEventToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
+ FIELD_ID_SKIPPED_DROP_EVENT);
+ protoOutput->write(FIELD_TYPE_INT32 | FIELD_ID_BUCKET_DROP_REASON, dropEvent.reason);
+ protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_DROP_TIME,
+ (long long)(NanoToMillis(dropEvent.dropTimeNs)));
+ ;
+ protoOutput->end(dropEventToken);
+ }
protoOutput->end(wrapperToken);
}
@@ -267,6 +317,14 @@ void ValueMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
FIELD_ID_DIMENSION_LEAF_IN_WHAT, str_set, protoOutput);
}
+ // Then fill slice_by_state.
+ for (auto state : dimensionKey.getStateValuesKey().getValues()) {
+ uint64_t stateToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
+ FIELD_ID_SLICE_BY_STATE);
+ writeStateToProto(state, protoOutput);
+ protoOutput->end(stateToken);
+ }
+
// Then fill bucket_info (ValueBucketInfo).
for (const auto& bucket : pair.second) {
uint64_t bucketInfoToken = protoOutput->start(
@@ -286,7 +344,7 @@ void ValueMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_CONDITION_TRUE_NS,
(long long)bucket.mConditionTrueNs);
}
- for (int i = 0; i < (int)bucket.valueIndex.size(); i ++) {
+ for (int i = 0; i < (int)bucket.valueIndex.size(); i++) {
int index = bucket.valueIndex[i];
const Value& value = bucket.values[i];
uint64_t valueToken = protoOutput->start(
@@ -321,23 +379,33 @@ void ValueMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
}
}
-void ValueMetricProducer::invalidateCurrentBucketWithoutResetBase() {
+void ValueMetricProducer::invalidateCurrentBucketWithoutResetBase(const int64_t dropTimeNs,
+ const BucketDropReason reason) {
if (!mCurrentBucketIsInvalid) {
- // Only report once per invalid bucket.
+ // Only report to StatsdStats once per invalid bucket.
StatsdStats::getInstance().noteInvalidatedBucket(mMetricId);
+
+ mCurrentSkippedBucket.bucketStartTimeNs = mCurrentBucketStartTimeNs;
+ mCurrentSkippedBucket.bucketEndTimeNs = getCurrentBucketEndTimeNs();
+ }
+
+ if (!maxDropEventsReached()) {
+ mCurrentSkippedBucket.dropEvents.emplace_back(buildDropEvent(dropTimeNs, reason));
}
mCurrentBucketIsInvalid = true;
}
-void ValueMetricProducer::invalidateCurrentBucket() {
- invalidateCurrentBucketWithoutResetBase();
+void ValueMetricProducer::invalidateCurrentBucket(const int64_t dropTimeNs,
+ const BucketDropReason reason) {
+ invalidateCurrentBucketWithoutResetBase(dropTimeNs, reason);
resetBase();
}
void ValueMetricProducer::resetBase() {
- for (auto& slice : mCurrentSlicedBucket) {
- for (auto& interval : slice.second) {
- interval.hasBase = false;
+ for (auto& slice : mCurrentBaseInfo) {
+ for (auto& baseInfo : slice.second) {
+ baseInfo.hasBase = false;
+ baseInfo.hasCurrentState = false;
}
}
mHasGlobalBase = false;
@@ -351,7 +419,8 @@ void ValueMetricProducer::onActiveStateChangedLocked(const int64_t& eventTimeNs)
bool isEventTooLate = eventTimeNs < mCurrentBucketStartTimeNs;
if (isEventTooLate) {
// Drop bucket because event arrived too late, ie. we are missing data for this bucket.
- invalidateCurrentBucket();
+ StatsdStats::getInstance().noteLateLogEventSkipped(mMetricId);
+ invalidateCurrentBucket(eventTimeNs, BucketDropReason::EVENT_IN_WRONG_BUCKET);
}
// Call parent method once we've verified the validity of current bucket.
@@ -394,8 +463,9 @@ void ValueMetricProducer::onConditionChangedLocked(const bool condition,
if (isEventTooLate) {
VLOG("Skip event due to late arrival: %lld vs %lld", (long long)eventTimeNs,
(long long)mCurrentBucketStartTimeNs);
+ StatsdStats::getInstance().noteLateLogEventSkipped(mMetricId);
StatsdStats::getInstance().noteConditionChangeInNextBucket(mMetricId);
- invalidateCurrentBucket();
+ invalidateCurrentBucket(eventTimeNs, BucketDropReason::EVENT_IN_WRONG_BUCKET);
mCondition = ConditionState::kUnknown;
mConditionTimer.onConditionChanged(mCondition, eventTimeNs);
return;
@@ -408,7 +478,7 @@ void ValueMetricProducer::onConditionChangedLocked(const bool condition,
//
// We still want to pull to set the base.
if (mCondition == ConditionState::kUnknown) {
- invalidateCurrentBucket();
+ invalidateCurrentBucket(eventTimeNs, BucketDropReason::CONDITION_UNKNOWN);
}
// Pull and match for the following condition change cases:
@@ -445,7 +515,7 @@ void ValueMetricProducer::pullAndMatchEventsLocked(const int64_t timestampNs) {
vector<std::shared_ptr<LogEvent>> allData;
if (!mPullerManager->Pull(mPullTagId, &allData)) {
ALOGE("Stats puller failed for tag: %d at %lld", mPullTagId, (long long)timestampNs);
- invalidateCurrentBucket();
+ invalidateCurrentBucket(timestampNs, BucketDropReason::PULL_FAILED);
return;
}
@@ -465,7 +535,7 @@ void ValueMetricProducer::onDataPulled(const std::vector<std::shared_ptr<LogEven
if (mCondition == ConditionState::kTrue) {
// If the pull failed, we won't be able to compute a diff.
if (!pullSuccess) {
- invalidateCurrentBucket();
+ invalidateCurrentBucket(originalPullTimeNs, BucketDropReason::PULL_FAILED);
} else {
bool isEventLate = originalPullTimeNs < getCurrentBucketEndTimeNs();
if (isEventLate) {
@@ -502,11 +572,12 @@ void ValueMetricProducer::accumulateEvents(const std::vector<std::shared_ptr<Log
VLOG("Skip bucket end pull due to late arrival: %lld vs %lld",
(long long)eventElapsedTimeNs, (long long)mCurrentBucketStartTimeNs);
StatsdStats::getInstance().noteLateLogEventSkipped(mMetricId);
- invalidateCurrentBucket();
+ invalidateCurrentBucket(eventElapsedTimeNs, BucketDropReason::EVENT_IN_WRONG_BUCKET);
return;
}
- const int64_t pullDelayNs = getElapsedRealtimeNs() - originalPullTimeNs;
+ const int64_t elapsedRealtimeNs = getElapsedRealtimeNs();
+ const int64_t pullDelayNs = elapsedRealtimeNs - originalPullTimeNs;
StatsdStats::getInstance().notePullDelay(mPullTagId, pullDelayNs);
if (pullDelayNs > mMaxPullDelayNs) {
ALOGE("Pull finish too late for atom %d, longer than %lld", mPullTagId,
@@ -514,7 +585,7 @@ void ValueMetricProducer::accumulateEvents(const std::vector<std::shared_ptr<Log
StatsdStats::getInstance().notePullExceedMaxDelay(mPullTagId);
// We are missing one pull from the bucket which means we will not have a complete view of
// what's going on.
- invalidateCurrentBucket();
+ invalidateCurrentBucket(eventElapsedTimeNs, BucketDropReason::PULL_DELAYED);
return;
}
@@ -532,14 +603,20 @@ void ValueMetricProducer::accumulateEvents(const std::vector<std::shared_ptr<Log
onMatchedLogEventLocked(mWhatMatcherIndex, localCopy);
}
}
- // If the new pulled data does not contains some keys we track in our intervals, we need to
- // reset the base.
+ // If a key that is:
+ // 1. Tracked in mCurrentSlicedBucket and
+ // 2. A superset of the current mStateChangePrimaryKey
+ // was not found in the new pulled data (i.e. not in mMatchedDimensionInWhatKeys)
+ // then we need to reset the base.
for (auto& slice : mCurrentSlicedBucket) {
- bool presentInPulledData = mMatchedMetricDimensionKeys.find(slice.first)
- != mMatchedMetricDimensionKeys.end();
- if (!presentInPulledData) {
- for (auto& interval : slice.second) {
- interval.hasBase = false;
+ const auto& whatKey = slice.first.getDimensionKeyInWhat();
+ bool presentInPulledData =
+ mMatchedMetricDimensionKeys.find(whatKey) != mMatchedMetricDimensionKeys.end();
+ if (!presentInPulledData && whatKey.contains(mStateChangePrimaryKey.second)) {
+ auto it = mCurrentBaseInfo.find(whatKey);
+ for (auto& baseInfo : it->second) {
+ baseInfo.hasBase = false;
+ baseInfo.hasCurrentState = false;
}
}
}
@@ -553,7 +630,7 @@ void ValueMetricProducer::accumulateEvents(const std::vector<std::shared_ptr<Log
// incorrectly compute the diff when mUseZeroDefaultBase is true since an existing key
// might be missing from mCurrentSlicedBucket.
if (hasReachedGuardRailLimit()) {
- invalidateCurrentBucket();
+ invalidateCurrentBucket(eventElapsedTimeNs, BucketDropReason::DIMENSION_GUARDRAIL_REACHED);
mCurrentSlicedBucket.clear();
}
}
@@ -648,17 +725,30 @@ bool getDoubleOrLong(const LogEvent& event, const Matcher& matcher, Value& ret)
return false;
}
-void ValueMetricProducer::onMatchedLogEventInternalLocked(const size_t matcherIndex,
- const MetricDimensionKey& eventKey,
- const ConditionKey& conditionKey,
- bool condition, const LogEvent& event) {
+void ValueMetricProducer::onMatchedLogEventInternalLocked(
+ const size_t matcherIndex, const MetricDimensionKey& eventKey,
+ const ConditionKey& conditionKey, bool condition, const LogEvent& event,
+ const map<int, HashableDimensionKey>& statePrimaryKeys) {
+ auto whatKey = eventKey.getDimensionKeyInWhat();
+ auto stateKey = eventKey.getStateValuesKey();
+
+ // Skip this event if a state changed occurred for a different primary key.
+ auto it = statePrimaryKeys.find(mStateChangePrimaryKey.first);
+ // Check that both the atom id and the primary key are equal.
+ if (it != statePrimaryKeys.end() && it->second != mStateChangePrimaryKey.second) {
+ VLOG("ValueMetric skip event with primary key %s because state change primary key "
+ "is %s",
+ it->second.toString().c_str(), mStateChangePrimaryKey.second.toString().c_str());
+ return;
+ }
+
int64_t eventTimeNs = event.GetElapsedTimestampNs();
if (eventTimeNs < mCurrentBucketStartTimeNs) {
VLOG("Skip event due to late arrival: %lld vs %lld", (long long)eventTimeNs,
(long long)mCurrentBucketStartTimeNs);
return;
}
- mMatchedMetricDimensionKeys.insert(eventKey);
+ mMatchedMetricDimensionKeys.insert(whatKey);
if (!mIsPulled) {
// We cannot flush without doing a pull first.
@@ -683,10 +773,26 @@ void ValueMetricProducer::onMatchedLogEventInternalLocked(const size_t matcherIn
if (hitGuardRailLocked(eventKey)) {
return;
}
- vector<Interval>& multiIntervals = mCurrentSlicedBucket[eventKey];
- if (multiIntervals.size() < mFieldMatchers.size()) {
+ vector<BaseInfo>& baseInfos = mCurrentBaseInfo[whatKey];
+ if (baseInfos.size() < mFieldMatchers.size()) {
VLOG("Resizing number of intervals to %d", (int)mFieldMatchers.size());
- multiIntervals.resize(mFieldMatchers.size());
+ baseInfos.resize(mFieldMatchers.size());
+ }
+
+ for (auto baseInfo : baseInfos) {
+ if (!baseInfo.hasCurrentState) {
+ baseInfo.currentState = DEFAULT_DIMENSION_KEY;
+ baseInfo.hasCurrentState = true;
+ }
+ }
+
+ // We need to get the intervals stored with the previous state key so we can
+ // close these value intervals.
+ const auto oldStateKey = baseInfos[0].currentState;
+ vector<Interval>& intervals = mCurrentSlicedBucket[MetricDimensionKey(whatKey, oldStateKey)];
+ if (intervals.size() < mFieldMatchers.size()) {
+ VLOG("Resizing number of intervals to %d", (int)mFieldMatchers.size());
+ intervals.resize(mFieldMatchers.size());
}
// We only use anomaly detection under certain cases.
@@ -699,7 +805,8 @@ void ValueMetricProducer::onMatchedLogEventInternalLocked(const size_t matcherIn
for (int i = 0; i < (int)mFieldMatchers.size(); i++) {
const Matcher& matcher = mFieldMatchers[i];
- Interval& interval = multiIntervals[i];
+ BaseInfo& baseInfo = baseInfos[i];
+ Interval& interval = intervals[i];
interval.valueIndex = i;
Value value;
if (!getDoubleOrLong(event, matcher, value)) {
@@ -710,60 +817,61 @@ void ValueMetricProducer::onMatchedLogEventInternalLocked(const size_t matcherIn
interval.seenNewData = true;
if (mUseDiff) {
- if (!interval.hasBase) {
+ if (!baseInfo.hasBase) {
if (mHasGlobalBase && mUseZeroDefaultBase) {
// The bucket has global base. This key does not.
// Optionally use zero as base.
- interval.base = (value.type == LONG ? ZERO_LONG : ZERO_DOUBLE);
- interval.hasBase = true;
+ baseInfo.base = (value.type == LONG ? ZERO_LONG : ZERO_DOUBLE);
+ baseInfo.hasBase = true;
} else {
// no base. just update base and return.
- interval.base = value;
- interval.hasBase = true;
+ baseInfo.base = value;
+ baseInfo.hasBase = true;
// If we're missing a base, do not use anomaly detection on incomplete data
useAnomalyDetection = false;
- // Continue (instead of return) here in order to set interval.base and
- // interval.hasBase for other intervals
+ // Continue (instead of return) here in order to set baseInfo.base and
+ // baseInfo.hasBase for other baseInfos
continue;
}
}
+
Value diff;
switch (mValueDirection) {
case ValueMetric::INCREASING:
- if (value >= interval.base) {
- diff = value - interval.base;
+ if (value >= baseInfo.base) {
+ diff = value - baseInfo.base;
} else if (mUseAbsoluteValueOnReset) {
diff = value;
} else {
VLOG("Unexpected decreasing value");
StatsdStats::getInstance().notePullDataError(mPullTagId);
- interval.base = value;
+ baseInfo.base = value;
// If we've got bad data, do not use anomaly detection
useAnomalyDetection = false;
continue;
}
break;
case ValueMetric::DECREASING:
- if (interval.base >= value) {
- diff = interval.base - value;
+ if (baseInfo.base >= value) {
+ diff = baseInfo.base - value;
} else if (mUseAbsoluteValueOnReset) {
diff = value;
} else {
VLOG("Unexpected increasing value");
StatsdStats::getInstance().notePullDataError(mPullTagId);
- interval.base = value;
+ baseInfo.base = value;
// If we've got bad data, do not use anomaly detection
useAnomalyDetection = false;
continue;
}
break;
case ValueMetric::ANY:
- diff = value - interval.base;
+ diff = value - baseInfo.base;
break;
default:
break;
}
- interval.base = value;
+ baseInfo.base = value;
value = diff;
}
@@ -788,12 +896,13 @@ void ValueMetricProducer::onMatchedLogEventInternalLocked(const size_t matcherIn
interval.hasValue = true;
}
interval.sampleSize += 1;
+ baseInfo.currentState = stateKey;
}
// Only trigger the tracker if all intervals are correct
if (useAnomalyDetection) {
// TODO: propgate proper values down stream when anomaly support doubles
- long wholeBucketVal = multiIntervals[0].value.long_value;
+ long wholeBucketVal = intervals[0].value.long_value;
auto prev = mCurrentFullBucket.find(eventKey);
if (prev != mCurrentFullBucket.end()) {
wholeBucketVal += prev->second;
@@ -839,7 +948,8 @@ void ValueMetricProducer::flushCurrentBucketLocked(const int64_t& eventTimeNs,
StatsdStats::getInstance().noteSkippedForwardBuckets(mMetricId);
// Something went wrong. Maybe the device was sleeping for a long time. It is better
// to mark the current bucket as invalid. The last pull might have been successful through.
- invalidateCurrentBucketWithoutResetBase();
+ invalidateCurrentBucketWithoutResetBase(eventTimeNs,
+ BucketDropReason::MULTIPLE_BUCKETS_SKIPPED);
}
VLOG("finalizing bucket for %ld, dumping %d slices", (long)mCurrentBucketStartTimeNs,
@@ -849,6 +959,18 @@ void ValueMetricProducer::flushCurrentBucketLocked(const int64_t& eventTimeNs,
// Close the current bucket.
int64_t conditionTrueDuration = mConditionTimer.newBucketStart(bucketEndTime);
bool isBucketLargeEnough = bucketEndTime - mCurrentBucketStartTimeNs >= mMinBucketSizeNs;
+ if (!isBucketLargeEnough) {
+ // If the bucket is valid, this is the only drop reason and we need to
+ // set the skipped bucket start and end times.
+ if (!mCurrentBucketIsInvalid) {
+ mCurrentSkippedBucket.bucketStartTimeNs = mCurrentBucketStartTimeNs;
+ mCurrentSkippedBucket.bucketEndTimeNs = bucketEndTime;
+ }
+ if (!maxDropEventsReached()) {
+ mCurrentSkippedBucket.dropEvents.emplace_back(
+ buildDropEvent(eventTimeNs, BucketDropReason::BUCKET_TOO_SMALL));
+ }
+ }
if (isBucketLargeEnough && !mCurrentBucketIsInvalid) {
// The current bucket is large enough to keep.
for (const auto& slice : mCurrentSlicedBucket) {
@@ -861,7 +983,7 @@ void ValueMetricProducer::flushCurrentBucketLocked(const int64_t& eventTimeNs,
}
}
} else {
- mSkippedBuckets.emplace_back(mCurrentBucketStartTimeNs, bucketEndTime);
+ mSkippedBuckets.emplace_back(mCurrentSkippedBucket);
}
appendToFullBucket(eventTimeNs, fullBucketEndTimeNs);
@@ -914,9 +1036,12 @@ void ValueMetricProducer::initCurrentSlicedBucket(int64_t nextBucketStartTimeNs)
} else {
it++;
}
+ // TODO: remove mCurrentBaseInfo entries when obsolete
}
mCurrentBucketIsInvalid = false;
+ mCurrentSkippedBucket.reset();
+
// If we do not have a global base when the condition is true,
// we will have incomplete bucket for the next bucket.
if (mUseDiff && !mHasGlobalBase && mCondition) {
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index 2033a2a0cd02..19fb6942928f 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -83,11 +83,14 @@ public:
flushCurrentBucketLocked(eventTimeNs, eventTimeNs);
};
+ void onStateChanged(int64_t eventTimeNs, int32_t atomId, const HashableDimensionKey& primaryKey,
+ int oldState, int newState) override;
+
protected:
void onMatchedLogEventInternalLocked(
const size_t matcherIndex, const MetricDimensionKey& eventKey,
- const ConditionKey& conditionKey, bool condition,
- const LogEvent& event) override;
+ const ConditionKey& conditionKey, bool condition, const LogEvent& event,
+ const std::map<int, HashableDimensionKey>& statePrimaryKeys) override;
private:
void onDumpReportLocked(const int64_t dumpTimeNs,
@@ -130,8 +133,9 @@ private:
int64_t calcBucketsForwardCount(const int64_t& eventTimeNs) const;
// Mark the data as invalid.
- void invalidateCurrentBucket();
- void invalidateCurrentBucketWithoutResetBase();
+ void invalidateCurrentBucket(const int64_t dropTimeNs, const BucketDropReason reason);
+ void invalidateCurrentBucketWithoutResetBase(const int64_t dropTimeNs,
+ const BucketDropReason reason);
const int mWhatMatcherIndex;
@@ -143,7 +147,10 @@ private:
std::vector<Matcher> mFieldMatchers;
// Value fields for matching.
- std::set<MetricDimensionKey> mMatchedMetricDimensionKeys;
+ std::set<HashableDimensionKey> mMatchedMetricDimensionKeys;
+
+ // Holds the atom id, primary key pair from a state change.
+ pair<int32_t, HashableDimensionKey> mStateChangePrimaryKey;
// tagId for pulled data. -1 if this is not pulled
const int mPullTagId;
@@ -155,10 +162,6 @@ private:
typedef struct {
// Index in multi value aggregation.
int valueIndex;
- // Holds current base value of the dimension. Take diff and update if necessary.
- Value base;
- // Whether there is a base to diff to.
- bool hasBase;
// Current value, depending on the aggregation type.
Value value;
// Number of samples collected.
@@ -170,16 +173,26 @@ private:
bool seenNewData = false;
} Interval;
+ typedef struct {
+ // Holds current base value of the dimension. Take diff and update if necessary.
+ Value base;
+ // Whether there is a base to diff to.
+ bool hasBase;
+ // Last seen state value(s).
+ HashableDimensionKey currentState;
+ // Whether this dimensions in what key has a current state key.
+ bool hasCurrentState;
+ } BaseInfo;
+
std::unordered_map<MetricDimensionKey, std::vector<Interval>> mCurrentSlicedBucket;
+ std::unordered_map<HashableDimensionKey, std::vector<BaseInfo>> mCurrentBaseInfo;
+
std::unordered_map<MetricDimensionKey, int64_t> mCurrentFullBucket;
// Save the past buckets and we can clear when the StatsLogReport is dumped.
std::unordered_map<MetricDimensionKey, std::vector<ValueBucket>> mPastBuckets;
- // Pairs of (elapsed start, elapsed end) denoting buckets that were skipped.
- std::list<std::pair<int64_t, int64_t>> mSkippedBuckets;
-
const int64_t mMinBucketSizeNs;
// Util function to check whether the specified dimension hits the guardrail.
@@ -248,7 +261,6 @@ private:
FRIEND_TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition);
FRIEND_TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition);
FRIEND_TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition2);
- FRIEND_TEST(ValueMetricProducerTest, TestBucketIncludingUnknownConditionIsInvalid);
FRIEND_TEST(ValueMetricProducerTest, TestBucketInvalidIfGlobalBaseIsNotSet);
FRIEND_TEST(ValueMetricProducerTest, TestCalcPreviousBucketEndTime);
FRIEND_TEST(ValueMetricProducerTest, TestDataIsNotUpdatedWhenNoConditionChanged);
@@ -258,10 +270,6 @@ private:
FRIEND_TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition);
FRIEND_TEST(ValueMetricProducerTest, TestFirstBucket);
FRIEND_TEST(ValueMetricProducerTest, TestFullBucketResetWhenLastBucketInvalid);
- FRIEND_TEST(ValueMetricProducerTest, TestInvalidBucketWhenGuardRailHit);
- FRIEND_TEST(ValueMetricProducerTest, TestInvalidBucketWhenInitialPullFailed);
- FRIEND_TEST(ValueMetricProducerTest, TestInvalidBucketWhenLastPullFailed);
- FRIEND_TEST(ValueMetricProducerTest, TestInvalidBucketWhenOneConditionFailed);
FRIEND_TEST(ValueMetricProducerTest, TestLateOnDataPulledWithDiff);
FRIEND_TEST(ValueMetricProducerTest, TestLateOnDataPulledWithoutDiff);
FRIEND_TEST(ValueMetricProducerTest, TestPartialBucketCreated);
@@ -292,9 +300,19 @@ private:
FRIEND_TEST(ValueMetricProducerTest, TestResetBaseOnPullTooLate);
FRIEND_TEST(ValueMetricProducerTest, TestSkipZeroDiffOutput);
FRIEND_TEST(ValueMetricProducerTest, TestSkipZeroDiffOutputMultiValue);
+ FRIEND_TEST(ValueMetricProducerTest, TestSlicedState);
+ FRIEND_TEST(ValueMetricProducerTest, TestSlicedStateWithMap);
+ FRIEND_TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions);
FRIEND_TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey);
FRIEND_TEST(ValueMetricProducerTest, TestUseZeroDefaultBase);
FRIEND_TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures);
+
+ FRIEND_TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenOneConditionFailed);
+ FRIEND_TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenInitialPullFailed);
+ FRIEND_TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenLastPullFailed);
+ FRIEND_TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenGuardRailHit);
+ FRIEND_TEST(ValueMetricProducerTest_BucketDrop,
+ TestInvalidBucketWhenAccumulateEventWrongBucket);
friend class ValueMetricProducerTestHelper;
};
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.cpp b/cmds/statsd/src/metrics/metrics_manager_util.cpp
index 2ad8217c45d4..73c121242523 100644
--- a/cmds/statsd/src/metrics/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/metrics_manager_util.cpp
@@ -18,11 +18,12 @@
#include "Log.h"
#include "metrics_manager_util.h"
-#include "MetricProducer.h"
#include <inttypes.h>
#include "atoms_info.h"
+#include "FieldValue.h"
+#include "MetricProducer.h"
#include "condition/CombinationConditionTracker.h"
#include "condition/SimpleConditionTracker.h"
#include "condition/StateConditionTracker.h"
@@ -173,6 +174,14 @@ bool handleMetricWithStates(
return true;
}
+bool handleMetricWithStateLink(const FieldMatcher& stateMatcher,
+ const vector<Matcher>& dimensionsInWhat) {
+ vector<Matcher> stateMatchers;
+ translateFieldMatcher(stateMatcher, &stateMatchers);
+
+ return subsetDimensions(stateMatchers, dimensionsInWhat);
+}
+
// Validates a metricActivation and populates state.
// EventActivationMap and EventDeactivationMap are supplied to a MetricProducer
// to provide the producer with state about its activators and deactivators.
@@ -669,18 +678,41 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
}
}
+ std::vector<int> slicedStateAtoms;
+ unordered_map<int, unordered_map<int, int64_t>> stateGroupMap;
+ if (metric.slice_by_state_size() > 0) {
+ if (!handleMetricWithStates(config, metric.slice_by_state(), stateAtomIdMap,
+ allStateGroupMaps, slicedStateAtoms, stateGroupMap)) {
+ return false;
+ }
+ } else {
+ if (metric.state_link_size() > 0) {
+ ALOGW("ValueMetric has a MetricStateLink but doesn't have a sliced state");
+ return false;
+ }
+ }
+
+ // Check that all metric state links are a subset of dimensions_in_what fields.
+ std::vector<Matcher> dimensionsInWhat;
+ translateFieldMatcher(metric.dimensions_in_what(), &dimensionsInWhat);
+ for (const auto& stateLink : metric.state_link()) {
+ if (!handleMetricWithStateLink(stateLink.fields_in_what(), dimensionsInWhat)) {
+ return false;
+ }
+ }
+
unordered_map<int, shared_ptr<Activation>> eventActivationMap;
unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
- bool success = handleMetricActivation(config, metric.id(), metricIndex,
- metricToActivationMap, logTrackerMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, metricsWithActivation, eventActivationMap,
- eventDeactivationMap);
+ bool success = handleMetricActivation(
+ config, metric.id(), metricIndex, metricToActivationMap, logTrackerMap,
+ activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+ metricsWithActivation, eventActivationMap, eventDeactivationMap);
if (!success) return false;
sp<MetricProducer> valueProducer = new ValueMetricProducer(
key, metric, conditionIndex, wizard, trackerIndex, matcherWizard, pullTagId,
timeBaseTimeNs, currentTimeNs, pullerManager, eventActivationMap,
- eventDeactivationMap);
+ eventDeactivationMap, slicedStateAtoms, stateGroupMap);
allMetricProducers.push_back(valueProducer);
}
diff --git a/cmds/statsd/src/state/StateManager.cpp b/cmds/statsd/src/state/StateManager.cpp
index 80d398339ebb..ea776fae0583 100644
--- a/cmds/statsd/src/state/StateManager.cpp
+++ b/cmds/statsd/src/state/StateManager.cpp
@@ -28,13 +28,17 @@ StateManager& StateManager::getInstance() {
return sStateManager;
}
+void StateManager::clear() {
+ mStateTrackers.clear();
+}
+
void StateManager::onLogEvent(const LogEvent& event) {
if (mStateTrackers.find(event.GetTagId()) != mStateTrackers.end()) {
mStateTrackers[event.GetTagId()]->onLogEvent(event);
}
}
-bool StateManager::registerListener(int32_t atomId, wp<StateListener> listener) {
+bool StateManager::registerListener(const int32_t atomId, wp<StateListener> listener) {
// Check if state tracker already exists.
if (mStateTrackers.find(atomId) == mStateTrackers.end()) {
// Create a new state tracker iff atom is a state atom.
@@ -50,7 +54,7 @@ bool StateManager::registerListener(int32_t atomId, wp<StateListener> listener)
return true;
}
-void StateManager::unregisterListener(int32_t atomId, wp<StateListener> listener) {
+void StateManager::unregisterListener(const int32_t atomId, wp<StateListener> listener) {
std::unique_lock<std::mutex> lock(mMutex);
// Hold the sp<> until the lock is released so that ~StateTracker() is
@@ -74,7 +78,7 @@ void StateManager::unregisterListener(int32_t atomId, wp<StateListener> listener
lock.unlock();
}
-bool StateManager::getStateValue(int32_t atomId, const HashableDimensionKey& key,
+bool StateManager::getStateValue(const int32_t atomId, const HashableDimensionKey& key,
FieldValue* output) const {
auto it = mStateTrackers.find(atomId);
if (it != mStateTrackers.end()) {
diff --git a/cmds/statsd/src/state/StateManager.h b/cmds/statsd/src/state/StateManager.h
index a6053e6f317e..8bc24612be90 100644
--- a/cmds/statsd/src/state/StateManager.h
+++ b/cmds/statsd/src/state/StateManager.h
@@ -40,30 +40,33 @@ public:
// Returns a pointer to the single, shared StateManager object.
static StateManager& getInstance();
+ // Unregisters all listeners and removes all trackers from StateManager.
+ void clear();
+
// Notifies the correct StateTracker of an event.
void onLogEvent(const LogEvent& event);
// Returns true if atomId is being tracked and is associated with a state
// atom. StateManager notifies the correct StateTracker to register listener.
// If the correct StateTracker does not exist, a new StateTracker is created.
- bool registerListener(int32_t atomId, wp<StateListener> listener);
+ bool registerListener(const int32_t atomId, wp<StateListener> listener);
// Notifies the correct StateTracker to unregister a listener
// and removes the tracker if it no longer has any listeners.
- void unregisterListener(int32_t atomId, wp<StateListener> listener);
+ void unregisterListener(const int32_t atomId, wp<StateListener> listener);
// Returns true if the StateTracker exists and queries for the
// original state value mapped to the given query key. The state value is
// stored and output in a FieldValue class.
// Returns false if the StateTracker doesn't exist.
- bool getStateValue(int32_t atomId, const HashableDimensionKey& queryKey,
+ bool getStateValue(const int32_t atomId, const HashableDimensionKey& queryKey,
FieldValue* output) const;
inline int getStateTrackersCount() const {
return mStateTrackers.size();
}
- inline int getListenersCount(int32_t atomId) const {
+ inline int getListenersCount(const int32_t atomId) const {
auto it = mStateTrackers.find(atomId);
if (it != mStateTrackers.end()) {
return it->second->getListenersCount();
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index e45e24fe49d4..c45274e4a3de 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -147,12 +147,14 @@ message ValueBucketInfo {
message ValueMetricData {
optional DimensionsValue dimensions_in_what = 1;
- optional DimensionsValue dimensions_in_condition = 2 [deprecated = true];
+ repeated StateValue slice_by_state = 6;
repeated ValueBucketInfo bucket_info = 3;
repeated DimensionsValue dimension_leaf_values_in_what = 4;
+ optional DimensionsValue dimensions_in_condition = 2 [deprecated = true];
+
repeated DimensionsValue dimension_leaf_values_in_condition = 5 [deprecated = true];
}
@@ -191,11 +193,40 @@ message StatsLogReport {
// Fields 2 and 3 are reserved.
+ // Keep this in sync with BucketDropReason enum in MetricProducer.h.
+ enum BucketDropReason {
+ // For ValueMetric, a bucket is dropped during a dump report request iff
+ // current bucket should be included, a pull is needed (pulled metric and
+ // condition is true), and we are under fast time constraints.
+ DUMP_REPORT_REQUESTED = 1;
+ EVENT_IN_WRONG_BUCKET = 2;
+ CONDITION_UNKNOWN = 3;
+ PULL_FAILED = 4;
+ PULL_DELAYED = 5;
+ DIMENSION_GUARDRAIL_REACHED = 6;
+ MULTIPLE_BUCKETS_SKIPPED = 7;
+ // Not an invalid bucket case, but the bucket is dropped.
+ BUCKET_TOO_SMALL = 8;
+ };
+
+ message DropEvent {
+ optional BucketDropReason drop_reason = 1;
+
+ optional int64 drop_time_millis = 2;
+ }
+
message SkippedBuckets {
optional int64 start_bucket_elapsed_nanos = 1;
+
optional int64 end_bucket_elapsed_nanos = 2;
+
optional int64 start_bucket_elapsed_millis = 3;
+
optional int64 end_bucket_elapsed_millis = 4;
+
+ // The number of drop events is capped by StatsdStats::kMaxLoggedBucketDropEvents.
+ // The current maximum is 10 drop events.
+ repeated DropEvent drop_event = 5;
}
message EventMetricDataWrapper {
diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto
index a22805b6b525..736aa9be2fdb 100644
--- a/cmds/statsd/src/statsd_config.proto
+++ b/cmds/statsd/src/statsd_config.proto
@@ -290,12 +290,14 @@ message ValueMetric {
optional FieldMatcher dimensions_in_what = 5;
- optional FieldMatcher dimensions_in_condition = 9 [deprecated = true];
+ repeated int64 slice_by_state = 18;
optional TimeUnit bucket = 6;
repeated MetricConditionLink links = 7;
+ repeated MetricStateLink state_link = 19;
+
enum AggregationType {
SUM = 1;
MIN = 2;
@@ -325,6 +327,8 @@ message ValueMetric {
optional int32 max_pull_delay_sec = 16 [default = 10];
optional bool split_bucket_for_app_upgrade = 17 [default = true];
+
+ optional FieldMatcher dimensions_in_condition = 9 [deprecated = true];
}
message Alert {
diff --git a/cmds/statsd/tests/FieldValue_test.cpp b/cmds/statsd/tests/FieldValue_test.cpp
index f1cad92c336b..f4a59ed14d10 100644
--- a/cmds/statsd/tests/FieldValue_test.cpp
+++ b/cmds/statsd/tests/FieldValue_test.cpp
@@ -480,6 +480,137 @@ TEST(AtomMatcherTest, TestWriteAtomToProto) {
EXPECT_EQ(999, atom.num_results());
}
+/*
+ * Test two Matchers is not a subset of one Matcher.
+ * Test one Matcher is subset of two Matchers.
+ */
+TEST(AtomMatcherTest, TestSubsetDimensions1) {
+ // Initialize first set of matchers
+ FieldMatcher matcher1;
+ matcher1.set_field(10);
+
+ FieldMatcher* child = matcher1.add_child();
+ child->set_field(1);
+ child->set_position(Position::ALL);
+ child->add_child()->set_field(1);
+ child->add_child()->set_field(2);
+
+ vector<Matcher> matchers1;
+ translateFieldMatcher(matcher1, &matchers1);
+ EXPECT_EQ(2, matchers1.size());
+
+ // Initialize second set of matchers
+ FieldMatcher matcher2;
+ matcher2.set_field(10);
+
+ child = matcher2.add_child();
+ child->set_field(1);
+ child->set_position(Position::ALL);
+ child->add_child()->set_field(1);
+
+ vector<Matcher> matchers2;
+ translateFieldMatcher(matcher2, &matchers2);
+ EXPECT_EQ(1, matchers2.size());
+
+ EXPECT_FALSE(subsetDimensions(matchers1, matchers2));
+ EXPECT_TRUE(subsetDimensions(matchers2, matchers1));
+}
+/*
+ * Test not a subset with one matching Matcher, one non-matching Matcher.
+ */
+TEST(AtomMatcherTest, TestSubsetDimensions2) {
+ // Initialize first set of matchers
+ FieldMatcher matcher1;
+ matcher1.set_field(10);
+
+ FieldMatcher* child = matcher1.add_child();
+ child->set_field(1);
+
+ child = matcher1.add_child();
+ child->set_field(2);
+
+ vector<Matcher> matchers1;
+ translateFieldMatcher(matcher1, &matchers1);
+
+ // Initialize second set of matchers
+ FieldMatcher matcher2;
+ matcher2.set_field(10);
+
+ child = matcher2.add_child();
+ child->set_field(1);
+
+ child = matcher2.add_child();
+ child->set_field(3);
+
+ vector<Matcher> matchers2;
+ translateFieldMatcher(matcher2, &matchers2);
+
+ EXPECT_FALSE(subsetDimensions(matchers1, matchers2));
+}
+
+/*
+ * Test not a subset if parent field is not equal.
+ */
+TEST(AtomMatcherTest, TestSubsetDimensions3) {
+ // Initialize first set of matchers
+ FieldMatcher matcher1;
+ matcher1.set_field(10);
+
+ FieldMatcher* child = matcher1.add_child();
+ child->set_field(1);
+
+ vector<Matcher> matchers1;
+ translateFieldMatcher(matcher1, &matchers1);
+
+ // Initialize second set of matchers
+ FieldMatcher matcher2;
+ matcher2.set_field(5);
+
+ child = matcher2.add_child();
+ child->set_field(1);
+
+ vector<Matcher> matchers2;
+ translateFieldMatcher(matcher2, &matchers2);
+
+ EXPECT_FALSE(subsetDimensions(matchers1, matchers2));
+}
+
+/*
+ * Test is subset with two matching Matchers.
+ */
+TEST(AtomMatcherTest, TestSubsetDimensions4) {
+ // Initialize first set of matchers
+ FieldMatcher matcher1;
+ matcher1.set_field(10);
+
+ FieldMatcher* child = matcher1.add_child();
+ child->set_field(1);
+
+ child = matcher1.add_child();
+ child->set_field(2);
+
+ vector<Matcher> matchers1;
+ translateFieldMatcher(matcher1, &matchers1);
+
+ // Initialize second set of matchers
+ FieldMatcher matcher2;
+ matcher2.set_field(10);
+
+ child = matcher2.add_child();
+ child->set_field(1);
+
+ child = matcher2.add_child();
+ child->set_field(2);
+
+ child = matcher2.add_child();
+ child->set_field(3);
+
+ vector<Matcher> matchers2;
+ translateFieldMatcher(matcher2, &matchers2);
+
+ EXPECT_TRUE(subsetDimensions(matchers1, matchers2));
+ EXPECT_FALSE(subsetDimensions(matchers2, matchers1));
+}
} // namespace statsd
} // namespace os
diff --git a/cmds/statsd/tests/e2e/CountMetric_e2e_test.cpp b/cmds/statsd/tests/e2e/CountMetric_e2e_test.cpp
index 0f51c1b5a4ce..15fc468ffe57 100644
--- a/cmds/statsd/tests/e2e/CountMetric_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/CountMetric_e2e_test.cpp
@@ -27,9 +27,6 @@ namespace statsd {
#ifdef __ANDROID__
-const int SCREEN_STATE_ATOM_ID = android::util::SCREEN_STATE_CHANGED;
-const int UID_PROCESS_STATE_ATOM_ID = android::util::UID_PROCESS_STATE_CHANGED;
-
/**
* Test a count metric that has one slice_by_state with no primary fields.
*
diff --git a/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp b/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
index fb878dc7efed..e8d2ec514cad 100644
--- a/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
@@ -369,6 +369,168 @@ TEST(ValueMetricE2eTest, TestPulledEvents_WithActivation) {
EXPECT_EQ(1, bucketInfo.values_size());
}
+/**
+ * Test initialization of a simple value metric that is sliced by a state.
+ *
+ * ValueCpuUserTimePerScreenState
+ */
+TEST(ValueMetricE2eTest, TestInitWithSlicedState) {
+ // Create config.
+ StatsdConfig config;
+ config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+
+ auto pulledAtomMatcher =
+ CreateSimpleAtomMatcher("TestMatcher", android::util::SUBSYSTEM_SLEEP_STATE);
+ *config.add_atom_matcher() = pulledAtomMatcher;
+
+ auto screenState = CreateScreenState();
+ *config.add_state() = screenState;
+
+ // Create value metric that slices by screen state without a map.
+ int64_t metricId = 123456;
+ auto valueMetric = config.add_value_metric();
+ valueMetric->set_id(metricId);
+ valueMetric->set_bucket(TimeUnit::FIVE_MINUTES);
+ valueMetric->set_what(pulledAtomMatcher.id());
+ *valueMetric->mutable_value_field() =
+ CreateDimensions(android::util::CPU_TIME_PER_UID, {2 /* user_time_micros */});
+ valueMetric->add_slice_by_state(screenState.id());
+ valueMetric->set_max_pull_delay_sec(INT_MAX);
+
+ // Initialize StatsLogProcessor.
+ const uint64_t bucketStartTimeNs = 10000000000; // 0:10
+ const uint64_t bucketSizeNs =
+ TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000LL;
+ int uid = 12345;
+ int64_t cfgId = 98765;
+ ConfigKey cfgKey(uid, cfgId);
+
+ auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+
+ // Check that StateTrackers were initialized correctly.
+ EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
+ EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
+
+ // Check that ValueMetricProducer was initialized correctly.
+ EXPECT_EQ(1U, processor->mMetricsManagers.size());
+ sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
+ EXPECT_TRUE(metricsManager->isConfigValid());
+ EXPECT_EQ(1, metricsManager->mAllMetricProducers.size());
+ sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+ EXPECT_EQ(1, metricProducer->mSlicedStateAtoms.size());
+ EXPECT_EQ(SCREEN_STATE_ATOM_ID, metricProducer->mSlicedStateAtoms.at(0));
+ EXPECT_EQ(0, metricProducer->mStateGroupMap.size());
+}
+
+/**
+ * Test initialization of a value metric that is sliced by state and has
+ * dimensions_in_what.
+ *
+ * ValueCpuUserTimePerUidPerUidProcessState
+ */
+TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithDimensions) {
+ // Create config.
+ StatsdConfig config;
+ config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+
+ auto cpuTimePerUidMatcher =
+ CreateSimpleAtomMatcher("CpuTimePerUidMatcher", android::util::CPU_TIME_PER_UID);
+ *config.add_atom_matcher() = cpuTimePerUidMatcher;
+
+ auto uidProcessState = CreateUidProcessState();
+ *config.add_state() = uidProcessState;
+
+ // Create value metric that slices by screen state with a complete map.
+ int64_t metricId = 123456;
+ auto valueMetric = config.add_value_metric();
+ valueMetric->set_id(metricId);
+ valueMetric->set_bucket(TimeUnit::FIVE_MINUTES);
+ valueMetric->set_what(cpuTimePerUidMatcher.id());
+ *valueMetric->mutable_value_field() =
+ CreateDimensions(android::util::CPU_TIME_PER_UID, {2 /* user_time_micros */});
+ *valueMetric->mutable_dimensions_in_what() =
+ CreateDimensions(android::util::CPU_TIME_PER_UID, {1 /* uid */});
+ valueMetric->add_slice_by_state(uidProcessState.id());
+ MetricStateLink* stateLink = valueMetric->add_state_link();
+ stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
+ auto fieldsInWhat = stateLink->mutable_fields_in_what();
+ *fieldsInWhat = CreateDimensions(android::util::CPU_TIME_PER_UID, {1 /* uid */});
+ auto fieldsInState = stateLink->mutable_fields_in_state();
+ *fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
+ valueMetric->set_max_pull_delay_sec(INT_MAX);
+
+ // Initialize StatsLogProcessor.
+ const uint64_t bucketStartTimeNs = 10000000000; // 0:10
+ int uid = 12345;
+ int64_t cfgId = 98765;
+ ConfigKey cfgKey(uid, cfgId);
+
+ auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+
+ // Check that StateTrackers were initialized correctly.
+ EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
+ EXPECT_EQ(1, StateManager::getInstance().getListenersCount(UID_PROCESS_STATE_ATOM_ID));
+
+ // Check that ValueMetricProducer was initialized correctly.
+ EXPECT_EQ(1U, processor->mMetricsManagers.size());
+ sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
+ EXPECT_TRUE(metricsManager->isConfigValid());
+ EXPECT_EQ(1, metricsManager->mAllMetricProducers.size());
+ sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+ EXPECT_EQ(1, metricProducer->mSlicedStateAtoms.size());
+ EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, metricProducer->mSlicedStateAtoms.at(0));
+ EXPECT_EQ(0, metricProducer->mStateGroupMap.size());
+}
+
+/**
+ * Test initialization of a value metric that is sliced by state and has
+ * dimensions_in_what.
+ *
+ * ValueCpuUserTimePerUidPerUidProcessState
+ */
+TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithIncorrectDimensions) {
+ // Create config.
+ StatsdConfig config;
+ config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+
+ auto cpuTimePerUidMatcher =
+ CreateSimpleAtomMatcher("CpuTimePerUidMatcher", android::util::CPU_TIME_PER_UID);
+ *config.add_atom_matcher() = cpuTimePerUidMatcher;
+
+ auto uidProcessState = CreateUidProcessState();
+ *config.add_state() = uidProcessState;
+
+ // Create value metric that slices by screen state with a complete map.
+ int64_t metricId = 123456;
+ auto valueMetric = config.add_value_metric();
+ valueMetric->set_id(metricId);
+ valueMetric->set_bucket(TimeUnit::FIVE_MINUTES);
+ valueMetric->set_what(cpuTimePerUidMatcher.id());
+ *valueMetric->mutable_value_field() =
+ CreateDimensions(android::util::CPU_TIME_PER_UID, {2 /* user_time_micros */});
+ valueMetric->add_slice_by_state(uidProcessState.id());
+ MetricStateLink* stateLink = valueMetric->add_state_link();
+ stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
+ auto fieldsInWhat = stateLink->mutable_fields_in_what();
+ *fieldsInWhat = CreateDimensions(android::util::CPU_TIME_PER_UID, {1 /* uid */});
+ auto fieldsInState = stateLink->mutable_fields_in_state();
+ *fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
+ valueMetric->set_max_pull_delay_sec(INT_MAX);
+
+ // Initialize StatsLogProcessor.
+ const uint64_t bucketStartTimeNs = 10000000000; // 0:10
+ int uid = 12345;
+ int64_t cfgId = 98765;
+ ConfigKey cfgKey(uid, cfgId);
+ auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+
+ // No StateTrackers are initialized.
+ EXPECT_EQ(0, StateManager::getInstance().getStateTrackersCount());
+
+ // Config initialization fails.
+ EXPECT_EQ(0, processor->mMetricsManagers.size());
+}
+
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
diff --git a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
index b027e8e687db..308c43da426b 100644
--- a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
@@ -12,19 +12,22 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "src/matchers/SimpleLogMatchingTracker.h"
#include "src/metrics/GaugeMetricProducer.h"
-#include "src/stats_log_util.h"
-#include "logd/LogEvent.h"
-#include "metrics_test_helper.h"
-#include "tests/statsd_test_util.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <math.h>
#include <stdio.h>
+
#include <vector>
+#include "logd/LogEvent.h"
+#include "metrics_test_helper.h"
+#include "src/matchers/SimpleLogMatchingTracker.h"
+#include "src/metrics/MetricProducer.h"
+#include "src/stats_log_util.h"
+#include "tests/statsd_test_util.h"
+
using namespace testing;
using android::sp;
using std::set;
@@ -784,6 +787,70 @@ TEST(GaugeMetricProducerTest, TestRemoveDimensionInOutput) {
EXPECT_EQ(6, bucketIt->second.back().mGaugeAtoms[1].mFields->begin()->mValue.int_value);
}
+/*
+ * Test that BUCKET_TOO_SMALL dump reason is logged when a flushed bucket size
+ * is smaller than the "min_bucket_size_nanos" specified in the metric config.
+ */
+TEST(GaugeMetricProducerTest_BucketDrop, TestBucketDropWhenBucketTooSmall) {
+ GaugeMetric metric;
+ metric.set_id(metricId);
+ metric.set_bucket(FIVE_MINUTES);
+ metric.set_sampling_type(GaugeMetric::FIRST_N_SAMPLES);
+ metric.set_min_bucket_size_nanos(10000000000); // 10 seconds
+
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+
+ UidMap uidMap;
+ SimpleAtomMatcher atomMatcher;
+ atomMatcher.set_atom_id(tagId);
+ sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({
+ new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // Bucket start.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+ event->write("field1");
+ event->write(10);
+ event->init();
+ data->push_back(event);
+ return true;
+ }));
+
+ int triggerId = 5;
+ GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+ logEventMatcherIndex, eventMatcherWizard,
+ tagId, triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs,
+ pullerManager);
+
+ LogEvent trigger(triggerId, bucketStartTimeNs + 3);
+ trigger.init();
+ gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
+
+ // Check dump report.
+ ProtoOutputStream output;
+ std::set<string> strSet;
+ gaugeProducer.onDumpReport(bucketStartTimeNs + 9000000, true /* include recent buckets */,
+ true, FAST /* dump_latency */, &strSet, &output);
+
+ StatsLogReport report = outputStreamToProto(&output);
+ EXPECT_TRUE(report.has_gauge_metrics());
+ EXPECT_EQ(0, report.gauge_metrics().data_size());
+ EXPECT_EQ(1, report.gauge_metrics().skipped_size());
+
+ EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
+ report.gauge_metrics().skipped(0).start_bucket_elapsed_millis());
+ EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 9000000),
+ report.gauge_metrics().skipped(0).end_bucket_elapsed_millis());
+ EXPECT_EQ(1, report.gauge_metrics().skipped(0).drop_event_size());
+
+ auto dropEvent = report.gauge_metrics().skipped(0).drop_event(0);
+ EXPECT_EQ(BucketDropReason::BUCKET_TOO_SMALL, dropEvent.drop_reason());
+ EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 9000000), dropEvent.drop_time_millis());
+}
+
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
index 4b9d0c0ca718..92e8241d9ec2 100644
--- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
@@ -12,21 +12,23 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "src/matchers/SimpleLogMatchingTracker.h"
#include "src/metrics/ValueMetricProducer.h"
-#include "src/stats_log_util.h"
-#include "metrics_test_helper.h"
-#include "tests/statsd_test_util.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <math.h>
#include <stdio.h>
+
#include <vector>
+#include "metrics_test_helper.h"
+#include "src/matchers/SimpleLogMatchingTracker.h"
+#include "src/metrics/MetricProducer.h"
+#include "src/stats_log_util.h"
+#include "tests/statsd_test_util.h"
+
using namespace testing;
using android::sp;
-using android::util::ProtoReader;
using std::make_shared;
using std::set;
using std::shared_ptr;
@@ -128,6 +130,44 @@ class ValueMetricProducerTestHelper {
return valueProducer;
}
+ static sp<ValueMetricProducer> createValueProducerWithNoInitialCondition(
+ sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric) {
+ UidMap uidMap;
+ SimpleAtomMatcher atomMatcher;
+ atomMatcher.set_atom_id(tagId);
+ sp<EventMatcherWizard> eventMatcherWizard =
+ new EventMatcherWizard({new SimpleLogMatchingTracker(
+ atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+
+ sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
+ kConfigKey, metric, 1, wizard, logEventMatcherIndex, eventMatcherWizard, tagId,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ return valueProducer;
+ }
+
+ static sp<ValueMetricProducer> createValueProducerWithState(
+ sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric,
+ vector<int32_t> slicedStateAtoms,
+ unordered_map<int, unordered_map<int, int64_t>> stateGroupMap) {
+ UidMap uidMap;
+ SimpleAtomMatcher atomMatcher;
+ atomMatcher.set_atom_id(tagId);
+ sp<EventMatcherWizard> eventMatcherWizard =
+ new EventMatcherWizard({new SimpleLogMatchingTracker(
+ atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+ sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
+ kConfigKey, metric, -1 /* no condition */, wizard, logEventMatcherIndex,
+ eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager, {},
+ {}, slicedStateAtoms, stateGroupMap);
+ return valueProducer;
+ }
+
static ValueMetric createMetric() {
ValueMetric metric;
metric.set_id(metricId);
@@ -143,8 +183,13 @@ class ValueMetricProducerTestHelper {
metric.set_condition(StringToId("SCREEN_ON"));
return metric;
}
-};
+ static ValueMetric createMetricWithState(string state) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+ metric.add_slice_by_state(StringToId(state));
+ return metric;
+ }
+};
/*
* Tests that the first bucket works correctly
@@ -206,7 +251,7 @@ TEST(ValueMetricProducerTest, TestFirstBucket) {
* Tests pulled atoms with no conditions
*/
TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, Pull(tagId, _))
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
@@ -233,10 +278,12 @@ TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) {
valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
// has one slice
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ ValueMetricProducer::Interval curInterval =
+ valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(11, curInterval.base.long_value);
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(11, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(8, curInterval.value.long_value);
EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
@@ -253,9 +300,10 @@ TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) {
// has one slice
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(23, curInterval.base.long_value);
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(23, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(12, curInterval.value.long_value);
EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
@@ -274,9 +322,10 @@ TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) {
valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(36, curInterval.base.long_value);
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(36, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(13, curInterval.value.long_value);
EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
@@ -290,7 +339,7 @@ TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) {
}
TEST(ValueMetricProducerTest, TestPartialBucketCreated) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, Pull(tagId, _))
// Initialize bucket.
@@ -347,7 +396,7 @@ TEST(ValueMetricProducerTest, TestPartialBucketCreated) {
* Tests pulled atoms with filtering
*/
TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
@@ -374,9 +423,8 @@ TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering) {
}));
sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
- kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
- logEventMatcherIndex, eventMatcherWizard, tagId,
- bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, logEventMatcherIndex,
+ eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
vector<shared_ptr<LogEvent>> allData;
allData.clear();
@@ -391,9 +439,10 @@ TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering) {
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(11, curInterval.base.long_value);
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(11, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(8, curInterval.value.long_value);
EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
@@ -410,8 +459,8 @@ TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering) {
// No new data seen, so data has been cleared.
EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(11, curInterval.base.long_value);
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(11, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(8, curInterval.value.long_value);
EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
@@ -427,10 +476,11 @@ TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering) {
valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
// the base was reset
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(36, curInterval.base.long_value);
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(36, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
EXPECT_EQ(1UL, valueProducer->mPastBuckets.begin()->second.size());
@@ -462,9 +512,10 @@ TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset) {
// has one slice
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(11, curInterval.base.long_value);
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(11, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
@@ -478,8 +529,9 @@ TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset) {
// has one slice
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(10, curInterval.base.long_value);
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(10, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(10, curInterval.value.long_value);
EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
@@ -495,8 +547,9 @@ TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset) {
valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(36, curInterval.base.long_value);
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(36, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(26, curInterval.value.long_value);
EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
@@ -529,9 +582,10 @@ TEST(ValueMetricProducerTest, TestPulledEventsTakeZeroOnReset) {
// has one slice
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(11, curInterval.base.long_value);
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(11, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
@@ -545,8 +599,9 @@ TEST(ValueMetricProducerTest, TestPulledEventsTakeZeroOnReset) {
// has one slice
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(10, curInterval.base.long_value);
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(10, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
@@ -559,8 +614,9 @@ TEST(ValueMetricProducerTest, TestPulledEventsTakeZeroOnReset) {
valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(36, curInterval.base.long_value);
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(36, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(26, curInterval.value.long_value);
EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
@@ -613,9 +669,10 @@ TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) {
// has one slice
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
// startUpdated:false sum:0 start:100
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(100, curInterval.base.long_value);
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(100, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
@@ -632,8 +689,9 @@ TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) {
// has one slice
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(110, curInterval.base.long_value);
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(110, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(10, curInterval.value.long_value);
@@ -643,9 +701,10 @@ TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) {
// has one slice
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(true, curInterval.hasValue);
EXPECT_EQ(20, curInterval.value.long_value);
- EXPECT_EQ(false, curInterval.hasBase);
+ EXPECT_EQ(false, curBaseInfo.hasBase);
valueProducer->onConditionChanged(true, bucket3StartTimeNs + 1);
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10, 20}, {bucketSizeNs - 8, 1});
@@ -696,7 +755,7 @@ TEST(ValueMetricProducerTest, TestPushedEventsWithUpgrade) {
}
TEST(ValueMetricProducerTest, TestPulledValueWithUpgrade) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
@@ -859,6 +918,7 @@ TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition) {
// has one slice
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(10, curInterval.value.long_value);
EXPECT_EQ(true, curInterval.hasValue);
@@ -1026,7 +1086,7 @@ TEST(ValueMetricProducerTest, TestAnomalyDetection) {
// Test value metric no condition, the pull on bucket boundary come in time and too late
TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(true));
sp<ValueMetricProducer> valueProducer =
@@ -1046,10 +1106,11 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition) {
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
// startUpdated:true sum:0 start:11
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(11, curInterval.base.long_value);
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(11, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
@@ -1064,9 +1125,10 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition) {
// has one slice
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
// tartUpdated:false sum:12
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(23, curInterval.base.long_value);
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(23, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {12}, {bucketSizeNs});
@@ -1083,9 +1145,10 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition) {
valueProducer->onDataPulled(allData, /** succeed */ true, bucket6StartTimeNs);
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
// startUpdated:false sum:12
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(36, curInterval.base.long_value);
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(36, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {12}, {bucketSizeNs});
}
@@ -1128,16 +1191,18 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition) {
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(100, curInterval.base.long_value);
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(100, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
// pull on bucket boundary come late, condition change happens before it
valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1);
curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
- EXPECT_EQ(false, curInterval.hasBase);
+ EXPECT_EQ(false, curBaseInfo.hasBase);
// Now the alarm is delivered.
// since the condition turned to off before this pull finish, it has no effect
@@ -1147,7 +1212,8 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition) {
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(false, curInterval.hasBase);
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(false, curBaseInfo.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
}
@@ -1200,9 +1266,10 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition2) {
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
// startUpdated:false sum:0 start:100
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(100, curInterval.base.long_value);
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(100, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
@@ -1211,15 +1278,17 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition2) {
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(false, curInterval.hasBase);
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(false, curBaseInfo.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
// condition changed to true again, before the pull alarm is delivered
valueProducer->onConditionChanged(true, bucket2StartTimeNs + 25);
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(130, curInterval.base.long_value);
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(130, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
// Now the alarm is delivered, but it is considered late, the data will be used
@@ -1229,8 +1298,9 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition2) {
valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 50);
curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(140, curInterval.base.long_value);
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(140, curBaseInfo.base.long_value);
EXPECT_EQ(true, curInterval.hasValue);
EXPECT_EQ(10, curInterval.value.long_value);
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
@@ -1457,8 +1527,9 @@ TEST(ValueMetricProducerTest, TestSkipZeroDiffOutput) {
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
valueProducer.mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(10, curInterval.base.long_value);
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(10, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
@@ -1477,8 +1548,9 @@ TEST(ValueMetricProducerTest, TestSkipZeroDiffOutput) {
valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(15, curInterval.base.long_value);
+ curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(15, curBaseInfo.base.long_value);
EXPECT_EQ(true, curInterval.hasValue);
shared_ptr<LogEvent> event4 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 15);
@@ -1488,8 +1560,9 @@ TEST(ValueMetricProducerTest, TestSkipZeroDiffOutput) {
valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(15, curInterval.base.long_value);
+ curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(15, curBaseInfo.base.long_value);
EXPECT_EQ(true, curInterval.hasValue);
valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
@@ -1530,27 +1603,29 @@ TEST(ValueMetricProducerTest, TestSkipZeroDiffOutputMultiValue) {
valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
// has one slice
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval curInterval0 =
- valueProducer.mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::Interval curInterval1 =
- valueProducer.mCurrentSlicedBucket.begin()->second[1];
- EXPECT_EQ(true, curInterval0.hasBase);
- EXPECT_EQ(10, curInterval0.base.long_value);
- EXPECT_EQ(false, curInterval0.hasValue);
- EXPECT_EQ(true, curInterval1.hasBase);
- EXPECT_EQ(20, curInterval1.base.long_value);
- EXPECT_EQ(false, curInterval1.hasValue);
+ ValueMetricProducer::Interval curInterval =
+ valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(10, curBaseInfo.base.long_value);
+ EXPECT_EQ(false, curInterval.hasValue);
+ curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[1];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(20, curBaseInfo.base.long_value);
+ EXPECT_EQ(false, curInterval.hasValue);
valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
// has one slice
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval0 = valueProducer.mCurrentSlicedBucket.begin()->second[0];
- curInterval1 = valueProducer.mCurrentSlicedBucket.begin()->second[1];
- EXPECT_EQ(true, curInterval0.hasValue);
- EXPECT_EQ(5, curInterval0.value.long_value);
- EXPECT_EQ(true, curInterval1.hasValue);
- EXPECT_EQ(2, curInterval1.value.long_value);
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curInterval.hasValue);
+ EXPECT_EQ(5, curInterval.value.long_value);
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[1];
+ curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[1];
+ EXPECT_EQ(true, curInterval.hasValue);
+ EXPECT_EQ(2, curInterval.value.long_value);
// no change in first value field
shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10);
@@ -1560,14 +1635,17 @@ TEST(ValueMetricProducerTest, TestSkipZeroDiffOutputMultiValue) {
event3->init();
valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval0 = valueProducer.mCurrentSlicedBucket.begin()->second[0];
- curInterval1 = valueProducer.mCurrentSlicedBucket.begin()->second[1];
- EXPECT_EQ(true, curInterval0.hasBase);
- EXPECT_EQ(15, curInterval0.base.long_value);
- EXPECT_EQ(true, curInterval0.hasValue);
- EXPECT_EQ(true, curInterval1.hasBase);
- EXPECT_EQ(25, curInterval1.base.long_value);
- EXPECT_EQ(true, curInterval1.hasValue);
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(15, curBaseInfo.base.long_value);
+ EXPECT_EQ(true, curInterval.hasValue);
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[1];
+ curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[1];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(25, curBaseInfo.base.long_value);
+ EXPECT_EQ(true, curInterval.hasValue);
shared_ptr<LogEvent> event4 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 15);
event4->write(1);
@@ -1576,14 +1654,16 @@ TEST(ValueMetricProducerTest, TestSkipZeroDiffOutputMultiValue) {
event4->init();
valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval0 = valueProducer.mCurrentSlicedBucket.begin()->second[0];
- curInterval1 = valueProducer.mCurrentSlicedBucket.begin()->second[1];
- EXPECT_EQ(true, curInterval0.hasBase);
- EXPECT_EQ(15, curInterval0.base.long_value);
- EXPECT_EQ(true, curInterval0.hasValue);
- EXPECT_EQ(true, curInterval1.hasBase);
- EXPECT_EQ(29, curInterval1.base.long_value);
- EXPECT_EQ(true, curInterval1.hasValue);
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(15, curBaseInfo.base.long_value);
+ EXPECT_EQ(true, curInterval.hasValue);
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[1];
+ curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[1];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(29, curBaseInfo.base.long_value);
+ EXPECT_EQ(true, curInterval.hasValue);
valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
@@ -1630,9 +1710,11 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBase) {
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
auto iter = valueProducer->mCurrentSlicedBucket.begin();
auto& interval1 = iter->second[0];
+ auto iterBase = valueProducer->mCurrentBaseInfo.begin();
+ auto& baseInfo1 = iterBase->second[0];
EXPECT_EQ(1, iter->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
- EXPECT_EQ(true, interval1.hasBase);
- EXPECT_EQ(3, interval1.base.long_value);
+ EXPECT_EQ(true, baseInfo1.hasBase);
+ EXPECT_EQ(3, baseInfo1.base.long_value);
EXPECT_EQ(false, interval1.hasValue);
EXPECT_EQ(true, valueProducer->mHasGlobalBase);
EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
@@ -1652,8 +1734,8 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBase) {
valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
- EXPECT_EQ(true, interval1.hasBase);
- EXPECT_EQ(11, interval1.base.long_value);
+ EXPECT_EQ(true, baseInfo1.hasBase);
+ EXPECT_EQ(11, baseInfo1.base.long_value);
EXPECT_EQ(false, interval1.hasValue);
EXPECT_EQ(8, interval1.value.long_value);
@@ -1663,11 +1745,19 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBase) {
break;
}
}
+ auto itBase = valueProducer->mCurrentBaseInfo.begin();
+ for (; itBase != valueProducer->mCurrentBaseInfo.end(); it++) {
+ if (itBase != iterBase) {
+ break;
+ }
+ }
EXPECT_TRUE(it != iter);
+ EXPECT_TRUE(itBase != iterBase);
auto& interval2 = it->second[0];
+ auto& baseInfo2 = itBase->second[0];
EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
- EXPECT_EQ(true, interval2.hasBase);
- EXPECT_EQ(4, interval2.base.long_value);
+ EXPECT_EQ(true, baseInfo2.hasBase);
+ EXPECT_EQ(4, baseInfo2.base.long_value);
EXPECT_EQ(false, interval2.hasValue);
EXPECT_EQ(4, interval2.value.long_value);
@@ -1705,11 +1795,13 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) {
ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- auto iter = valueProducer->mCurrentSlicedBucket.begin();
- auto& interval1 = iter->second[0];
- EXPECT_EQ(1, iter->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
- EXPECT_EQ(true, interval1.hasBase);
- EXPECT_EQ(3, interval1.base.long_value);
+ auto it = valueProducer->mCurrentSlicedBucket.begin();
+ auto& interval1 = it->second[0];
+ auto& baseInfo1 =
+ valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat())->second[0];
+ EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+ EXPECT_EQ(true, baseInfo1.hasBase);
+ EXPECT_EQ(3, baseInfo1.base.long_value);
EXPECT_EQ(false, interval1.hasValue);
EXPECT_EQ(true, valueProducer->mHasGlobalBase);
EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
@@ -1729,22 +1821,31 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) {
valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
- EXPECT_EQ(true, interval1.hasBase);
- EXPECT_EQ(11, interval1.base.long_value);
+ EXPECT_EQ(true, baseInfo1.hasBase);
+ EXPECT_EQ(11, baseInfo1.base.long_value);
EXPECT_EQ(false, interval1.hasValue);
EXPECT_EQ(8, interval1.value.long_value);
- auto it = valueProducer->mCurrentSlicedBucket.begin();
- for (; it != valueProducer->mCurrentSlicedBucket.end(); it++) {
- if (it != iter) {
+ auto it2 = valueProducer->mCurrentSlicedBucket.begin();
+ for (; it2 != valueProducer->mCurrentSlicedBucket.end(); it2++) {
+ if (it2 != it) {
break;
}
}
- EXPECT_TRUE(it != iter);
- auto& interval2 = it->second[0];
- EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
- EXPECT_EQ(true, interval2.hasBase);
- EXPECT_EQ(4, interval2.base.long_value);
+ // auto itBase = valueProducer->mCurrentBaseInfo.begin();
+ // for (; itBase != valueProducer->mCurrentBaseInfo.end(); it++) {
+ // if (itBase != iterBase) {
+ // break;
+ // }
+ // }
+ EXPECT_TRUE(it2 != it);
+ // EXPECT_TRUE(itBase != iterBase);
+ auto& interval2 = it2->second[0];
+ auto& baseInfo2 =
+ valueProducer->mCurrentBaseInfo.find(it2->first.getDimensionKeyInWhat())->second[0];
+ EXPECT_EQ(2, it2->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+ EXPECT_EQ(true, baseInfo2.hasBase);
+ EXPECT_EQ(4, baseInfo2.base.long_value);
EXPECT_EQ(false, interval2.hasValue);
EXPECT_EQ(4, interval2.value.long_value);
EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
@@ -1759,8 +1860,8 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) {
valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- EXPECT_EQ(true, interval2.hasBase);
- EXPECT_EQ(5, interval2.base.long_value);
+ EXPECT_EQ(true, baseInfo2.hasBase);
+ EXPECT_EQ(5, baseInfo2.base.long_value);
EXPECT_EQ(false, interval2.hasValue);
EXPECT_EQ(true, valueProducer->mHasGlobalBase);
EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
@@ -1779,17 +1880,24 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) {
valueProducer->onDataPulled(allData, /** succeed */ true, bucket5StartTimeNs);
EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
- auto it1 = std::next(valueProducer->mCurrentSlicedBucket.begin())->second[0];
- EXPECT_EQ(true, it1.hasBase);
- EXPECT_EQ(13, it1.base.long_value);
- EXPECT_EQ(false, it1.hasValue);
- EXPECT_EQ(8, it1.value.long_value);
- auto it2 = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, it2.hasBase);
- EXPECT_EQ(5, it2.base.long_value);
- EXPECT_EQ(false, it2.hasValue);
- EXPECT_EQ(5, it2.value.long_value);
+ it = valueProducer->mCurrentSlicedBucket.begin();
+ it2 = std::next(valueProducer->mCurrentSlicedBucket.begin());
+ interval1 = it->second[0];
+ interval2 = it2->second[0];
+ baseInfo1 = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat())->second[0];
+ baseInfo2 = valueProducer->mCurrentBaseInfo.find(it2->first.getDimensionKeyInWhat())->second[0];
+
+ EXPECT_EQ(true, baseInfo1.hasBase);
+ EXPECT_EQ(5, baseInfo1.base.long_value);
+ EXPECT_EQ(false, interval1.hasValue);
+ EXPECT_EQ(5, interval1.value.long_value);
EXPECT_EQ(true, valueProducer->mHasGlobalBase);
+
+ EXPECT_EQ(true, baseInfo2.hasBase);
+ EXPECT_EQ(13, baseInfo2.base.long_value);
+ EXPECT_EQ(false, interval2.hasValue);
+ EXPECT_EQ(8, interval2.value.long_value);
+
EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
}
@@ -1819,9 +1927,11 @@ TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey) {
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
auto iter = valueProducer->mCurrentSlicedBucket.begin();
auto& interval1 = iter->second[0];
+ auto iterBase = valueProducer->mCurrentBaseInfo.begin();
+ auto& baseInfo1 = iterBase->second[0];
EXPECT_EQ(1, iter->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
- EXPECT_EQ(true, interval1.hasBase);
- EXPECT_EQ(3, interval1.base.long_value);
+ EXPECT_EQ(true, baseInfo1.hasBase);
+ EXPECT_EQ(3, baseInfo1.base.long_value);
EXPECT_EQ(false, interval1.hasValue);
EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
vector<shared_ptr<LogEvent>> allData;
@@ -1840,8 +1950,8 @@ TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey) {
valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
- EXPECT_EQ(true, interval1.hasBase);
- EXPECT_EQ(11, interval1.base.long_value);
+ EXPECT_EQ(true, baseInfo1.hasBase);
+ EXPECT_EQ(11, baseInfo1.base.long_value);
EXPECT_EQ(false, interval1.hasValue);
EXPECT_EQ(8, interval1.value.long_value);
EXPECT_FALSE(interval1.seenNewData);
@@ -1853,11 +1963,19 @@ TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey) {
break;
}
}
+ auto itBase = valueProducer->mCurrentBaseInfo.begin();
+ for (; itBase != valueProducer->mCurrentBaseInfo.end(); it++) {
+ if (itBase != iterBase) {
+ break;
+ }
+ }
EXPECT_TRUE(it != iter);
+ EXPECT_TRUE(itBase != iterBase);
auto& interval2 = it->second[0];
+ auto& baseInfo2 = itBase->second[0];
EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
- EXPECT_EQ(true, interval2.hasBase);
- EXPECT_EQ(4, interval2.base.long_value);
+ EXPECT_EQ(true, baseInfo2.hasBase);
+ EXPECT_EQ(4, baseInfo2.base.long_value);
EXPECT_EQ(false, interval2.hasValue);
EXPECT_FALSE(interval2.seenNewData);
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {8}, {bucketSizeNs});
@@ -1870,12 +1988,13 @@ TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey) {
event1->init();
allData.push_back(event1);
valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
- // Only one interval left. One was trimmed.
+ // Only one interval left. One was trimmed.
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
interval2 = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ baseInfo2 = valueProducer->mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
- EXPECT_EQ(true, interval2.hasBase);
- EXPECT_EQ(5, interval2.base.long_value);
+ EXPECT_EQ(true, baseInfo2.hasBase);
+ EXPECT_EQ(5, baseInfo2.base.long_value);
EXPECT_EQ(false, interval2.hasValue);
EXPECT_FALSE(interval2.seenNewData);
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {8}, {bucketSizeNs});
@@ -1889,8 +2008,9 @@ TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey) {
valueProducer->onDataPulled(allData, /** succeed */ true, bucket5StartTimeNs);
interval2 = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, interval2.hasBase);
- EXPECT_EQ(14, interval2.base.long_value);
+ baseInfo2 = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, baseInfo2.hasBase);
+ EXPECT_EQ(14, baseInfo2.base.long_value);
EXPECT_EQ(false, interval2.hasValue);
EXPECT_FALSE(interval2.seenNewData);
ASSERT_EQ(2UL, valueProducer->mPastBuckets.size());
@@ -1926,14 +2046,15 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange_EndOfB
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(100, curInterval.base.long_value);
+ ValueMetricProducer::BaseInfo& curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(100, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
vector<shared_ptr<LogEvent>> allData;
valueProducer->onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- EXPECT_EQ(false, curInterval.hasBase);
+ EXPECT_EQ(false, curBaseInfo.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(false, valueProducer->mHasGlobalBase);
}
@@ -1963,8 +2084,9 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange) {
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(100, curInterval.base.long_value);
+ ValueMetricProducer::BaseInfo& curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(100, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
@@ -1973,7 +2095,7 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange) {
// has one slice
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(false, curInterval.hasBase);
+ EXPECT_EQ(false, curBaseInfo.hasBase);
EXPECT_EQ(false, valueProducer->mHasGlobalBase);
}
@@ -2015,7 +2137,8 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullFailBeforeConditionChange) {
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(false, curInterval.hasBase);
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(false, curBaseInfo.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(false, valueProducer->mHasGlobalBase);
}
@@ -2098,13 +2221,17 @@ TEST(ValueMetricProducerTest, TestBaseSetOnConditionChange) {
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(100, curInterval.base.long_value);
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(100, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(true, valueProducer->mHasGlobalBase);
}
-TEST(ValueMetricProducerTest, TestInvalidBucketWhenOneConditionFailed) {
+/*
+ * Tests that a bucket is marked invalid when a condition change pull fails.
+ */
+TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenOneConditionFailed) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
@@ -2158,13 +2285,38 @@ TEST(ValueMetricProducerTest, TestInvalidBucketWhenOneConditionFailed) {
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(140, curInterval.base.long_value);
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(140, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(true, valueProducer->mHasGlobalBase);
+
+ // Check dump report.
+ ProtoOutputStream output;
+ std::set<string> strSet;
+ valueProducer->onDumpReport(bucket2StartTimeNs + 10, false /* include partial bucket */, true,
+ FAST /* dumpLatency */, &strSet, &output);
+
+ StatsLogReport report = outputStreamToProto(&output);
+ EXPECT_TRUE(report.has_value_metrics());
+ EXPECT_EQ(0, report.value_metrics().data_size());
+ EXPECT_EQ(1, report.value_metrics().skipped_size());
+
+ EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
+ report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+ EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
+ report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+ EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+
+ auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+ EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
+ EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 2), dropEvent.drop_time_millis());
}
-TEST(ValueMetricProducerTest, TestInvalidBucketWhenGuardRailHit) {
+/*
+ * Tests that a bucket is marked invalid when the guardrail is hit.
+ */
+TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenGuardRailHit) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.mutable_dimensions_in_what()->set_field(tagId);
metric.mutable_dimensions_in_what()->add_child()->set_field(1);
@@ -2175,7 +2327,8 @@ TEST(ValueMetricProducerTest, TestInvalidBucketWhenGuardRailHit) {
// First onConditionChanged
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
for (int i = 0; i < 2000; i++) {
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
+ shared_ptr<LogEvent> event =
+ make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
event->write(i);
event->write(i);
event->init();
@@ -2191,9 +2344,47 @@ TEST(ValueMetricProducerTest, TestInvalidBucketWhenGuardRailHit) {
valueProducer->onConditionChanged(true, bucketStartTimeNs + 2);
EXPECT_EQ(true, valueProducer->mCurrentBucketIsInvalid);
EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
+ EXPECT_EQ(0UL, valueProducer->mSkippedBuckets.size());
+
+ // Bucket 2 start.
+ vector<shared_ptr<LogEvent>> allData;
+ allData.clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+ event->write(1);
+ event->write(10);
+ event->init();
+ allData.push_back(event);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+
+ // First bucket added to mSkippedBuckets after flush.
+ EXPECT_EQ(1UL, valueProducer->mSkippedBuckets.size());
+
+ // Check dump report.
+ ProtoOutputStream output;
+ std::set<string> strSet;
+ valueProducer->onDumpReport(bucket2StartTimeNs + 10000, false /* include recent buckets */,
+ true, FAST /* dumpLatency */, &strSet, &output);
+
+ StatsLogReport report = outputStreamToProto(&output);
+ EXPECT_TRUE(report.has_value_metrics());
+ EXPECT_EQ(0, report.value_metrics().data_size());
+ EXPECT_EQ(1, report.value_metrics().skipped_size());
+
+ EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
+ report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+ EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
+ report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+ EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+
+ auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+ EXPECT_EQ(BucketDropReason::DIMENSION_GUARDRAIL_REACHED, dropEvent.drop_reason());
+ EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 2), dropEvent.drop_time_millis());
}
-TEST(ValueMetricProducerTest, TestInvalidBucketWhenInitialPullFailed) {
+/*
+ * Tests that a bucket is marked invalid when the bucket's initial pull fails.
+ */
+TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenInitialPullFailed) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
@@ -2253,13 +2444,39 @@ TEST(ValueMetricProducerTest, TestInvalidBucketWhenInitialPullFailed) {
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(140, curInterval.base.long_value);
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(140, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(true, valueProducer->mHasGlobalBase);
+
+ // Check dump report.
+ ProtoOutputStream output;
+ std::set<string> strSet;
+ valueProducer->onDumpReport(bucket2StartTimeNs + 10000, false /* include recent buckets */,
+ true, FAST /* dumpLatency */, &strSet, &output);
+
+ StatsLogReport report = outputStreamToProto(&output);
+ EXPECT_TRUE(report.has_value_metrics());
+ EXPECT_EQ(0, report.value_metrics().data_size());
+ EXPECT_EQ(1, report.value_metrics().skipped_size());
+
+ EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
+ report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+ EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
+ report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+ EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+
+ auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+ EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
+ EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 2), dropEvent.drop_time_millis());
}
-TEST(ValueMetricProducerTest, TestInvalidBucketWhenLastPullFailed) {
+/*
+ * Tests that a bucket is marked invalid when the bucket's final pull fails
+ * (i.e. failed pull on bucket boundary).
+ */
+TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenLastPullFailed) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
@@ -2300,8 +2517,6 @@ TEST(ValueMetricProducerTest, TestInvalidBucketWhenLastPullFailed) {
allData.push_back(event);
valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
- // This will fail and should invalidate the whole bucket since we do not have all the data
- // needed to compute the metric value when the screen was on.
valueProducer->onConditionChanged(false, bucketStartTimeNs + 2);
valueProducer->onConditionChanged(true, bucketStartTimeNs + 3);
@@ -2317,17 +2532,39 @@ TEST(ValueMetricProducerTest, TestInvalidBucketWhenLastPullFailed) {
valueProducer->flushIfNeededLocked(bucket2StartTimeNs + 1);
EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
- // Last pull failed so based has been reset.
+ // Last pull failed so base has been reset.
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(false, curInterval.hasBase);
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(false, curBaseInfo.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(false, valueProducer->mHasGlobalBase);
+
+ // Check dump report.
+ ProtoOutputStream output;
+ std::set<string> strSet;
+ valueProducer->onDumpReport(bucket2StartTimeNs + 10000, false /* include recent buckets */,
+ true, FAST /* dumpLatency */, &strSet, &output);
+
+ StatsLogReport report = outputStreamToProto(&output);
+ EXPECT_TRUE(report.has_value_metrics());
+ EXPECT_EQ(0, report.value_metrics().data_size());
+ EXPECT_EQ(1, report.value_metrics().skipped_size());
+
+ EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
+ report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+ EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
+ report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+ EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+
+ auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+ EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
+ EXPECT_EQ(NanoToMillis(bucket2StartTimeNs), dropEvent.drop_time_millis());
}
TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onDataPulled) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, Pull(tagId, _))
// Start bucket.
@@ -2394,7 +2631,8 @@ TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onConditionChanged) {
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(true, valueProducer->mHasGlobalBase);
@@ -2402,7 +2640,8 @@ TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onConditionChanged) {
valueProducer->onConditionChanged(false, bucketStartTimeNs + 10);
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(false, curInterval.hasBase);
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(false, curBaseInfo.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(false, valueProducer->mHasGlobalBase);
}
@@ -2450,7 +2689,8 @@ TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onBucketBoundary) {
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(true, curInterval.hasValue);
EXPECT_EQ(true, valueProducer->mHasGlobalBase);
@@ -2460,9 +2700,10 @@ TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onBucketBoundary) {
valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
// Data is empty, base should be reset.
- EXPECT_EQ(false, curInterval.hasBase);
- EXPECT_EQ(5, curInterval.base.long_value);
+ EXPECT_EQ(false, curBaseInfo.hasBase);
+ EXPECT_EQ(5, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(true, valueProducer->mHasGlobalBase);
@@ -2509,59 +2750,19 @@ TEST(ValueMetricProducerTest, TestPartialResetOnBucketBoundaries) {
// Key 1 should be reset since in not present in the most pull.
EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
auto iterator = valueProducer->mCurrentSlicedBucket.begin();
- EXPECT_EQ(true, iterator->second[0].hasBase);
- EXPECT_EQ(2, iterator->second[0].base.long_value);
+ auto baseInfoIter = valueProducer->mCurrentBaseInfo.begin();
+ EXPECT_EQ(true, baseInfoIter->second[0].hasBase);
+ EXPECT_EQ(2, baseInfoIter->second[0].base.long_value);
EXPECT_EQ(false, iterator->second[0].hasValue);
iterator++;
- EXPECT_EQ(false, iterator->second[0].hasBase);
- EXPECT_EQ(1, iterator->second[0].base.long_value);
+ baseInfoIter++;
+ EXPECT_EQ(false, baseInfoIter->second[0].hasBase);
+ EXPECT_EQ(1, baseInfoIter->second[0].base.long_value);
EXPECT_EQ(false, iterator->second[0].hasValue);
EXPECT_EQ(true, valueProducer->mHasGlobalBase);
}
-TEST(ValueMetricProducerTest, TestBucketIncludingUnknownConditionIsInvalid) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
- metric.mutable_dimensions_in_what()->set_field(tagId);
- metric.mutable_dimensions_in_what()->add_child()->set_field(1);
- metric.set_condition(StringToId("SCREEN_ON"));
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- // Second onConditionChanged.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
- event->write(tagId);
- event->write(2);
- event->write(2);
- event->init();
- data->push_back(event);
- return true;
- }));
-
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
- valueProducer->mCondition = ConditionState::kUnknown;
-
- valueProducer->onConditionChanged(false, bucketStartTimeNs + 10);
- valueProducer->onConditionChanged(true, bucketStartTimeNs + 20);
-
- // End of bucket
- vector<shared_ptr<LogEvent>> allData;
- allData.clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
- event->write(4);
- event->write(4);
- event->init();
- allData.push_back(event);
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-
- // Bucket is incomplete so it is mark as invalid, however the base is fine since the last pull
- // succeeded.
- EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
-}
-
TEST(ValueMetricProducerTest, TestFullBucketResetWhenLastBucketInvalid) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
@@ -2628,8 +2829,9 @@ TEST(ValueMetricProducerTest, TestBucketBoundariesOnConditionChange) {
valueProducer->onConditionChanged(true, bucket2StartTimeNs + 10);
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
auto curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(5, curInterval.base.long_value);
+ auto curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(5, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
valueProducer->onConditionChanged(false, bucket3StartTimeNs + 10);
@@ -2740,6 +2942,7 @@ TEST(ValueMetricProducerTest, TestDataIsNotUpdatedWhenNoConditionChanged) {
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
auto curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ auto curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(true, curInterval.hasValue);
EXPECT_EQ(2, curInterval.value.long_value);
@@ -2750,6 +2953,7 @@ TEST(ValueMetricProducerTest, TestDataIsNotUpdatedWhenNoConditionChanged) {
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {2}, {2});
}
+// TODO: b/145705635 fix or delete this test
TEST(ValueMetricProducerTest, TestBucketInvalidIfGlobalBaseIsNotSet) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
@@ -2797,25 +3001,8 @@ TEST(ValueMetricProducerTest, TestBucketInvalidIfGlobalBaseIsNotSet) {
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {}, {});
}
-static StatsLogReport outputStreamToProto(ProtoOutputStream* proto) {
- vector<uint8_t> bytes;
- bytes.resize(proto->size());
- size_t pos = 0;
- sp<ProtoReader> reader = proto->data();
- while (reader->readBuffer() != NULL) {
- size_t toRead = reader->currentToRead();
- std::memcpy(&((bytes)[pos]), reader->readBuffer(), toRead);
- pos += toRead;
- reader->move(toRead);
- }
-
- StatsLogReport report;
- report.ParseFromArray(bytes.data(), bytes.size());
- return report;
-}
-
TEST(ValueMetricProducerTest, TestPullNeededFastDump) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
@@ -2847,8 +3034,7 @@ TEST(ValueMetricProducerTest, TestPullNeededFastDump) {
ProtoOutputStream output;
std::set<string> strSet;
- valueProducer.onDumpReport(bucketStartTimeNs + 10,
- true /* include recent buckets */, true,
+ valueProducer.onDumpReport(bucketStartTimeNs + 10, true /* include recent buckets */, true,
FAST, &strSet, &output);
StatsLogReport report = outputStreamToProto(&output);
@@ -2857,7 +3043,7 @@ TEST(ValueMetricProducerTest, TestPullNeededFastDump) {
}
TEST(ValueMetricProducerTest, TestFastDumpWithoutCurrentBucket) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
@@ -2899,9 +3085,8 @@ TEST(ValueMetricProducerTest, TestFastDumpWithoutCurrentBucket) {
ProtoOutputStream output;
std::set<string> strSet;
- valueProducer.onDumpReport(bucket4StartTimeNs,
- false /* include recent buckets */, true,
- FAST, &strSet, &output);
+ valueProducer.onDumpReport(bucket4StartTimeNs, false /* include recent buckets */, true, FAST,
+ &strSet, &output);
StatsLogReport report = outputStreamToProto(&output);
// Previous bucket is part of the report.
@@ -2910,7 +3095,7 @@ TEST(ValueMetricProducerTest, TestFastDumpWithoutCurrentBucket) {
}
TEST(ValueMetricProducerTest, TestPullNeededNoTimeConstraints) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
@@ -2952,8 +3137,7 @@ TEST(ValueMetricProducerTest, TestPullNeededNoTimeConstraints) {
ProtoOutputStream output;
std::set<string> strSet;
- valueProducer.onDumpReport(bucketStartTimeNs + 10,
- true /* include recent buckets */, true,
+ valueProducer.onDumpReport(bucketStartTimeNs + 10, true /* include recent buckets */, true,
NO_TIME_CONSTRAINTS, &strSet, &output);
StatsLogReport report = outputStreamToProto(&output);
@@ -2987,15 +3171,15 @@ TEST(ValueMetricProducerTest, TestPulledData_noDiff_withMultipleConditionChanges
// condition becomes true
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
- data->push_back(ValueMetricProducerTestHelper::createEvent(
- bucketStartTimeNs + 30, 10));
+ data->push_back(
+ ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 30, 10));
return true;
}))
// condition becomes false
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
- data->push_back(ValueMetricProducerTestHelper::createEvent(
- bucketStartTimeNs + 50, 20));
+ data->push_back(
+ ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 50, 20));
return true;
}));
sp<ValueMetricProducer> valueProducer =
@@ -3008,11 +3192,11 @@ TEST(ValueMetricProducerTest, TestPulledData_noDiff_withMultipleConditionChanges
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(false, curInterval.hasBase);
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(false, curBaseInfo.hasBase);
EXPECT_EQ(true, curInterval.hasValue);
EXPECT_EQ(20, curInterval.value.long_value);
-
// Now the alarm is delivered. Condition is off though.
vector<shared_ptr<LogEvent>> allData;
allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 110));
@@ -3020,7 +3204,8 @@ TEST(ValueMetricProducerTest, TestPulledData_noDiff_withMultipleConditionChanges
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {50 - 8});
curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(false, curInterval.hasBase);
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(false, curBaseInfo.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
}
@@ -3033,8 +3218,8 @@ TEST(ValueMetricProducerTest, TestPulledData_noDiff_bucketBoundaryTrue) {
// condition becomes true
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
- data->push_back(ValueMetricProducerTestHelper::createEvent(
- bucketStartTimeNs + 30, 10));
+ data->push_back(
+ ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 30, 10));
return true;
}));
sp<ValueMetricProducer> valueProducer =
@@ -3051,7 +3236,8 @@ TEST(ValueMetricProducerTest, TestPulledData_noDiff_bucketBoundaryTrue) {
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {30}, {bucketSizeNs - 8});
ValueMetricProducer::Interval curInterval =
valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(false, curInterval.hasBase);
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(false, curBaseInfo.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
}
@@ -3082,8 +3268,8 @@ TEST(ValueMetricProducerTest, TestPulledData_noDiff_withFailure) {
// condition becomes true
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
- data->push_back(ValueMetricProducerTestHelper::createEvent(
- bucketStartTimeNs + 30, 10));
+ data->push_back(
+ ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 30, 10));
return true;
}))
.WillOnce(Return(false));
@@ -3103,6 +3289,1319 @@ TEST(ValueMetricProducerTest, TestPulledData_noDiff_withFailure) {
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {}, {});
}
+/*
+ * Test that DUMP_REPORT_REQUESTED dump reason is logged.
+ *
+ * For the bucket to be marked invalid during a dump report requested,
+ * three things must be true:
+ * - we want to include the current partial bucket
+ * - we need a pull (metric is pulled and condition is true)
+ * - the dump latency must be FAST
+ */
+TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenDumpReportRequested) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // Condition change to true.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
+ event->write("field1");
+ event->write(10);
+ event->init();
+ data->push_back(event);
+ return true;
+ }));
+
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+
+ // Condition change event.
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 20);
+
+ // Check dump report.
+ ProtoOutputStream output;
+ std::set<string> strSet;
+ valueProducer->onDumpReport(bucketStartTimeNs + 40, true /* include recent buckets */, true,
+ FAST /* dumpLatency */, &strSet, &output);
+
+ StatsLogReport report = outputStreamToProto(&output);
+ EXPECT_TRUE(report.has_value_metrics());
+ EXPECT_EQ(0, report.value_metrics().data_size());
+ EXPECT_EQ(1, report.value_metrics().skipped_size());
+
+ EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
+ report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+ EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
+ report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+ EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+
+ auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+ EXPECT_EQ(BucketDropReason::DUMP_REPORT_REQUESTED, dropEvent.drop_reason());
+ EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 40), dropEvent.drop_time_millis());
+}
+
+/*
+ * Test that EVENT_IN_WRONG_BUCKET dump reason is logged for a late condition
+ * change event (i.e. the condition change occurs in the wrong bucket).
+ */
+TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenConditionEventWrongBucket) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // Condition change to true.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 50);
+ event->write("field1");
+ event->write(10);
+ event->init();
+ data->push_back(event);
+ return true;
+ }));
+
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+
+ // Condition change event.
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
+
+ // Bucket boundary pull.
+ vector<shared_ptr<LogEvent>> allData;
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs);
+ event->write("field1");
+ event->write(15);
+ event->init();
+ allData.push_back(event);
+ valueProducer->onDataPulled(allData, /** succeeds */ true, bucket2StartTimeNs + 1);
+
+ // Late condition change event.
+ valueProducer->onConditionChanged(false, bucket2StartTimeNs - 100);
+
+ // Check dump report.
+ ProtoOutputStream output;
+ std::set<string> strSet;
+ valueProducer->onDumpReport(bucket2StartTimeNs + 100, true /* include recent buckets */, true,
+ NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
+
+ StatsLogReport report = outputStreamToProto(&output);
+ EXPECT_TRUE(report.has_value_metrics());
+ EXPECT_EQ(1, report.value_metrics().data_size());
+ EXPECT_EQ(1, report.value_metrics().skipped_size());
+
+ EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
+ report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+ EXPECT_EQ(NanoToMillis(bucket3StartTimeNs),
+ report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+ EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+
+ auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+ EXPECT_EQ(BucketDropReason::EVENT_IN_WRONG_BUCKET, dropEvent.drop_reason());
+ EXPECT_EQ(NanoToMillis(bucket2StartTimeNs - 100), dropEvent.drop_time_millis());
+}
+
+/*
+ * Test that EVENT_IN_WRONG_BUCKET dump reason is logged for a late accumulate
+ * event (i.e. the accumulate events call occurs in the wrong bucket).
+ */
+TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenAccumulateEventWrongBucket) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // Condition change to true.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 50);
+ event->write("field1");
+ event->write(10);
+ event->init();
+ data->push_back(event);
+ return true;
+ }))
+ // Dump report requested.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 100);
+ event->write("field1");
+ event->write(15);
+ event->init();
+ data->push_back(event);
+ return true;
+ }));
+
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+
+ // Condition change event.
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
+
+ // Bucket boundary pull.
+ vector<shared_ptr<LogEvent>> allData;
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs);
+ event->write("field1");
+ event->write(15);
+ event->init();
+ allData.push_back(event);
+ valueProducer->onDataPulled(allData, /** succeeds */ true, bucket2StartTimeNs + 1);
+
+ allData.clear();
+ event = make_shared<LogEvent>(tagId, bucket2StartTimeNs - 100);
+ event->write("field1");
+ event->write(20);
+ event->init();
+ allData.push_back(event);
+
+ // Late accumulateEvents event.
+ valueProducer->accumulateEvents(allData, bucket2StartTimeNs - 100, bucket2StartTimeNs - 100);
+
+ // Check dump report.
+ ProtoOutputStream output;
+ std::set<string> strSet;
+ valueProducer->onDumpReport(bucket2StartTimeNs + 100, true /* include recent buckets */, true,
+ NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
+
+ StatsLogReport report = outputStreamToProto(&output);
+ EXPECT_TRUE(report.has_value_metrics());
+ EXPECT_EQ(1, report.value_metrics().data_size());
+ EXPECT_EQ(1, report.value_metrics().skipped_size());
+
+ EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
+ report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+ EXPECT_EQ(NanoToMillis(bucket3StartTimeNs),
+ report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+ EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+
+ auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+ EXPECT_EQ(BucketDropReason::EVENT_IN_WRONG_BUCKET, dropEvent.drop_reason());
+ EXPECT_EQ(NanoToMillis(bucket2StartTimeNs - 100), dropEvent.drop_time_millis());
+}
+
+/*
+ * Test that CONDITION_UNKNOWN dump reason is logged due to an unknown condition
+ * when a metric is initialized.
+ */
+TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenConditionUnknown) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // Condition change to true.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 50);
+ event->write("field1");
+ event->write(10);
+ event->init();
+ data->push_back(event);
+ return true;
+ }))
+ // Dump report requested.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 100);
+ event->write("field1");
+ event->write(15);
+ event->init();
+ data->push_back(event);
+ return true;
+ }));
+
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithNoInitialCondition(pullerManager,
+ metric);
+
+ // Condition change event.
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
+
+ // Check dump report.
+ ProtoOutputStream output;
+ std::set<string> strSet;
+ valueProducer->onDumpReport(bucketStartTimeNs + 100, true /* include recent buckets */, true,
+ NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
+
+ StatsLogReport report = outputStreamToProto(&output);
+ EXPECT_TRUE(report.has_value_metrics());
+ EXPECT_EQ(0, report.value_metrics().data_size());
+ EXPECT_EQ(1, report.value_metrics().skipped_size());
+
+ EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
+ report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+ EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
+ report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+ EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+
+ auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+ EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, dropEvent.drop_reason());
+ EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 100), dropEvent.drop_time_millis());
+}
+
+/*
+ * Test that PULL_FAILED dump reason is logged due to a pull failure in
+ * #pullAndMatchEventsLocked.
+ */
+TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenPullFailed) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // Condition change to true.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 50);
+ event->write("field1");
+ event->write(10);
+ event->init();
+ data->push_back(event);
+ return true;
+ }))
+ // Dump report requested, pull fails.
+ .WillOnce(Return(false));
+
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+
+ // Condition change event.
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
+
+ // Check dump report.
+ ProtoOutputStream output;
+ std::set<string> strSet;
+ valueProducer->onDumpReport(bucketStartTimeNs + 100, true /* include recent buckets */, true,
+ NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
+
+ StatsLogReport report = outputStreamToProto(&output);
+ EXPECT_TRUE(report.has_value_metrics());
+ EXPECT_EQ(0, report.value_metrics().data_size());
+ EXPECT_EQ(1, report.value_metrics().skipped_size());
+
+ EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
+ report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+ EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
+ report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+ EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+
+ auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+ EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
+ EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 100), dropEvent.drop_time_millis());
+}
+
+/*
+ * Test that MULTIPLE_BUCKETS_SKIPPED dump reason is logged when a log event
+ * skips over more than one bucket.
+ */
+TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenMultipleBucketsSkipped) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // Condition change to true.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+ event->write("field1");
+ event->write(10);
+ event->init();
+ data->push_back(event);
+ return true;
+ }))
+ // Dump report requested.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event =
+ make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1000);
+ event->write("field1");
+ event->write(15);
+ event->init();
+ data->push_back(event);
+ return true;
+ }));
+
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+
+ // Condition change event.
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
+
+ // Condition change event that skips forward by three buckets.
+ valueProducer->onConditionChanged(false, bucket4StartTimeNs + 10);
+
+ // Check dump report.
+ ProtoOutputStream output;
+ std::set<string> strSet;
+ valueProducer->onDumpReport(bucket4StartTimeNs + 1000, true /* include recent buckets */, true,
+ NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
+
+ StatsLogReport report = outputStreamToProto(&output);
+ EXPECT_TRUE(report.has_value_metrics());
+ EXPECT_EQ(0, report.value_metrics().data_size());
+ EXPECT_EQ(1, report.value_metrics().skipped_size());
+
+ EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
+ report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+ EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
+ report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+ EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+
+ auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+ EXPECT_EQ(BucketDropReason::MULTIPLE_BUCKETS_SKIPPED, dropEvent.drop_reason());
+ EXPECT_EQ(NanoToMillis(bucket4StartTimeNs + 10), dropEvent.drop_time_millis());
+}
+
+/*
+ * Test that BUCKET_TOO_SMALL dump reason is logged when a flushed bucket size
+ * is smaller than the "min_bucket_size_nanos" specified in the metric config.
+ */
+TEST(ValueMetricProducerTest_BucketDrop, TestBucketDropWhenBucketTooSmall) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+ metric.set_min_bucket_size_nanos(10000000000); // 10 seconds
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // Condition change to true.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+ event->write("field1");
+ event->write(10);
+ event->init();
+ data->push_back(event);
+ return true;
+ }))
+ // Dump report requested.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event =
+ make_shared<LogEvent>(tagId, bucketStartTimeNs + 9000000);
+ event->write("field1");
+ event->write(15);
+ event->init();
+ data->push_back(event);
+ return true;
+ }));
+
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+
+ // Condition change event.
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
+
+ // Check dump report.
+ ProtoOutputStream output;
+ std::set<string> strSet;
+ valueProducer->onDumpReport(bucketStartTimeNs + 9000000, true /* include recent buckets */,
+ true, NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
+
+ StatsLogReport report = outputStreamToProto(&output);
+ EXPECT_TRUE(report.has_value_metrics());
+ EXPECT_EQ(0, report.value_metrics().data_size());
+ EXPECT_EQ(1, report.value_metrics().skipped_size());
+
+ EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
+ report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+ EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 9000000),
+ report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+ EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+
+ auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+ EXPECT_EQ(BucketDropReason::BUCKET_TOO_SMALL, dropEvent.drop_reason());
+ EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 9000000), dropEvent.drop_time_millis());
+}
+
+/*
+ * Test multiple bucket drop events in the same bucket.
+ */
+TEST(ValueMetricProducerTest_BucketDrop, TestMultipleBucketDropEvents) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // Condition change to true.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+ event->write("field1");
+ event->write(10);
+ event->init();
+ data->push_back(event);
+ return true;
+ }));
+
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithNoInitialCondition(pullerManager,
+ metric);
+
+ // Condition change event.
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
+
+ // Check dump report.
+ ProtoOutputStream output;
+ std::set<string> strSet;
+ valueProducer->onDumpReport(bucketStartTimeNs + 1000, true /* include recent buckets */, true,
+ FAST /* dumpLatency */, &strSet, &output);
+
+ StatsLogReport report = outputStreamToProto(&output);
+ EXPECT_TRUE(report.has_value_metrics());
+ EXPECT_EQ(0, report.value_metrics().data_size());
+ EXPECT_EQ(1, report.value_metrics().skipped_size());
+
+ EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
+ report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+ EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
+ report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+ EXPECT_EQ(2, report.value_metrics().skipped(0).drop_event_size());
+
+ auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+ EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, dropEvent.drop_reason());
+ EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 10), dropEvent.drop_time_millis());
+
+ dropEvent = report.value_metrics().skipped(0).drop_event(1);
+ EXPECT_EQ(BucketDropReason::DUMP_REPORT_REQUESTED, dropEvent.drop_reason());
+ EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 1000), dropEvent.drop_time_millis());
+}
+
+/*
+ * Test that the number of logged bucket drop events is capped at the maximum.
+ * The maximum is currently 10 and is set in MetricProducer::maxDropEventsReached().
+ */
+TEST(ValueMetricProducerTest_BucketDrop, TestMaxBucketDropEvents) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // First condition change event.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ for (int i = 0; i < 2000; i++) {
+ shared_ptr<LogEvent> event =
+ make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
+ event->write(i);
+ event->write(i);
+ event->init();
+ data->push_back(event);
+ }
+ return true;
+ }))
+ .WillOnce(Return(false))
+ .WillOnce(Return(false))
+ .WillOnce(Return(false))
+ .WillOnce(Return(false))
+ .WillOnce(Return(false))
+ .WillOnce(Return(false))
+ .WillOnce(Return(false))
+ .WillOnce(Return(false))
+ .WillOnce(Return(false))
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 220);
+ event->write("field1");
+ event->write(10);
+ event->init();
+ data->push_back(event);
+ return true;
+ }));
+
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithNoInitialCondition(pullerManager,
+ metric);
+
+ // First condition change event causes guardrail to be reached.
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
+
+ // 2-10 condition change events result in failed pulls.
+ valueProducer->onConditionChanged(false, bucketStartTimeNs + 30);
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
+ valueProducer->onConditionChanged(false, bucketStartTimeNs + 70);
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 90);
+ valueProducer->onConditionChanged(false, bucketStartTimeNs + 100);
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 150);
+ valueProducer->onConditionChanged(false, bucketStartTimeNs + 170);
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 190);
+ valueProducer->onConditionChanged(false, bucketStartTimeNs + 200);
+
+ // Condition change event 11
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 220);
+
+ // Check dump report.
+ ProtoOutputStream output;
+ std::set<string> strSet;
+ // Because we already have 10 dump events in the current bucket,
+ // this case should not be added to the list of dump events.
+ valueProducer->onDumpReport(bucketStartTimeNs + 1000, true /* include recent buckets */, true,
+ FAST /* dumpLatency */, &strSet, &output);
+
+ StatsLogReport report = outputStreamToProto(&output);
+ EXPECT_TRUE(report.has_value_metrics());
+ EXPECT_EQ(0, report.value_metrics().data_size());
+ EXPECT_EQ(1, report.value_metrics().skipped_size());
+
+ EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
+ report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+ EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
+ report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+ EXPECT_EQ(10, report.value_metrics().skipped(0).drop_event_size());
+
+ auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+ EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, dropEvent.drop_reason());
+ EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 10), dropEvent.drop_time_millis());
+
+ dropEvent = report.value_metrics().skipped(0).drop_event(1);
+ EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
+ EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 30), dropEvent.drop_time_millis());
+
+ dropEvent = report.value_metrics().skipped(0).drop_event(2);
+ EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
+ EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 50), dropEvent.drop_time_millis());
+
+ dropEvent = report.value_metrics().skipped(0).drop_event(3);
+ EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
+ EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 70), dropEvent.drop_time_millis());
+
+ dropEvent = report.value_metrics().skipped(0).drop_event(4);
+ EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
+ EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 90), dropEvent.drop_time_millis());
+
+ dropEvent = report.value_metrics().skipped(0).drop_event(5);
+ EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
+ EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 100), dropEvent.drop_time_millis());
+
+ dropEvent = report.value_metrics().skipped(0).drop_event(6);
+ EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
+ EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 150), dropEvent.drop_time_millis());
+
+ dropEvent = report.value_metrics().skipped(0).drop_event(7);
+ EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
+ EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 170), dropEvent.drop_time_millis());
+
+ dropEvent = report.value_metrics().skipped(0).drop_event(8);
+ EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
+ EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 190), dropEvent.drop_time_millis());
+
+ dropEvent = report.value_metrics().skipped(0).drop_event(9);
+ EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
+ EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 200), dropEvent.drop_time_millis());
+}
+
+/*
+ * Test metric with a simple sliced state
+ * - Increasing values
+ * - Using diff
+ * - Second field is value field
+ */
+TEST(ValueMetricProducerTest, TestSlicedState) {
+ // Set up ValueMetricProducer.
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("SCREEN_STATE");
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // ValueMetricProducer initialized.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+ event->write("field1");
+ event->write(3);
+ event->init();
+ data->push_back(event);
+ return true;
+ }))
+ // Screen state change to ON.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 5);
+ event->write("field1");
+ event->write(5);
+ event->init();
+ data->push_back(event);
+ return true;
+ }))
+ // Screen state change to OFF.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+ event->write("field1");
+ event->write(9);
+ event->init();
+ data->push_back(event);
+ return true;
+ }))
+ // Screen state change to ON.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 15);
+ event->write("field1");
+ event->write(21);
+ event->init();
+ data->push_back(event);
+ return true;
+ }))
+ // Dump report requested.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 50);
+ event->write("field1");
+ event->write(30);
+ event->init();
+ data->push_back(event);
+ return true;
+ }));
+
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithState(
+ pullerManager, metric, {android::util::SCREEN_STATE_CHANGED}, {});
+
+ // Set up StateManager and check that StateTrackers are initialized.
+ StateManager::getInstance().clear();
+ StateManager::getInstance().registerListener(SCREEN_STATE_ATOM_ID, valueProducer);
+ EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
+ EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
+
+ // Bucket status after metric initialized.
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ // Base for dimension key {}
+ auto it = valueProducer->mCurrentSlicedBucket.begin();
+ auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+ EXPECT_EQ(true, itBase->second[0].hasBase);
+ EXPECT_EQ(3, itBase->second[0].base.long_value);
+ // Value for dimension, state key {{}, kStateUnknown}
+ EXPECT_EQ(false, it->second[0].hasValue);
+
+ // Bucket status after screen state change kStateUnknown->ON.
+ auto screenEvent = CreateScreenStateChangedEvent(
+ android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + 5);
+ StateManager::getInstance().onLogEvent(*screenEvent);
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ // Base for dimension key {}
+ it = valueProducer->mCurrentSlicedBucket.begin();
+ itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+ EXPECT_EQ(true, itBase->second[0].hasBase);
+ EXPECT_EQ(5, itBase->second[0].base.long_value);
+ // Value for dimension, state key {{}, kStateUnknown}
+ EXPECT_EQ(true, it->second[0].hasValue);
+ EXPECT_EQ(2, it->second[0].value.long_value);
+
+ // Bucket status after screen state change ON->OFF.
+ screenEvent = CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+ bucketStartTimeNs + 10);
+ StateManager::getInstance().onLogEvent(*screenEvent);
+ EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+ // Base for dimension key {}
+ it = valueProducer->mCurrentSlicedBucket.begin();
+ itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+ EXPECT_EQ(true, itBase->second[0].hasBase);
+ EXPECT_EQ(9, itBase->second[0].base.long_value);
+ // Value for dimension, state key {{}, ON}
+ EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+ it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+ EXPECT_EQ(true, it->second[0].hasValue);
+ EXPECT_EQ(4, it->second[0].value.long_value);
+ // Value for dimension, state key {{}, kStateUnknown}
+ it++;
+ EXPECT_EQ(true, it->second[0].hasValue);
+ EXPECT_EQ(2, it->second[0].value.long_value);
+
+ // Bucket status after screen state change OFF->ON.
+ screenEvent = CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+ bucketStartTimeNs + 15);
+ StateManager::getInstance().onLogEvent(*screenEvent);
+ EXPECT_EQ(3UL, valueProducer->mCurrentSlicedBucket.size());
+ // Base for dimension key {}
+ it = valueProducer->mCurrentSlicedBucket.begin();
+ itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+ EXPECT_EQ(true, itBase->second[0].hasBase);
+ EXPECT_EQ(21, itBase->second[0].base.long_value);
+ // Value for dimension, state key {{}, OFF}
+ EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+ it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+ EXPECT_EQ(true, it->second[0].hasValue);
+ EXPECT_EQ(12, it->second[0].value.long_value);
+ // Value for dimension, state key {{}, ON}
+ it++;
+ EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+ it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+ EXPECT_EQ(true, it->second[0].hasValue);
+ EXPECT_EQ(4, it->second[0].value.long_value);
+ // Value for dimension, state key {{}, kStateUnknown}
+ it++;
+ EXPECT_EQ(true, it->second[0].hasValue);
+ EXPECT_EQ(2, it->second[0].value.long_value);
+
+ // Start dump report and check output.
+ ProtoOutputStream output;
+ std::set<string> strSet;
+ valueProducer->onDumpReport(bucketStartTimeNs + 50, true /* include recent buckets */, true,
+ NO_TIME_CONSTRAINTS, &strSet, &output);
+
+ StatsLogReport report = outputStreamToProto(&output);
+ EXPECT_TRUE(report.has_value_metrics());
+ EXPECT_EQ(3, report.value_metrics().data_size());
+
+ auto data = report.value_metrics().data(0);
+ EXPECT_EQ(1, data.bucket_info_size());
+ EXPECT_EQ(2, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
+
+ data = report.value_metrics().data(1);
+ EXPECT_EQ(1, report.value_metrics().data(1).bucket_info_size());
+ EXPECT_EQ(13, report.value_metrics().data(1).bucket_info(0).values(0).value_long());
+ EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+ EXPECT_TRUE(data.slice_by_state(0).has_value());
+ EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON, data.slice_by_state(0).value());
+
+ data = report.value_metrics().data(2);
+ EXPECT_EQ(1, report.value_metrics().data(2).bucket_info_size());
+ EXPECT_EQ(12, report.value_metrics().data(2).bucket_info(0).values(0).value_long());
+ EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+ EXPECT_TRUE(data.slice_by_state(0).has_value());
+ EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF, data.slice_by_state(0).value());
+}
+
+/*
+ * Test metric with sliced state with map
+ * - Increasing values
+ * - Using diff
+ * - Second field is value field
+ */
+TEST(ValueMetricProducerTest, TestSlicedStateWithMap) {
+ // Set up ValueMetricProducer.
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("SCREEN_STATE_ONOFF");
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // ValueMetricProducer initialized.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+ event->write("field1");
+ event->write(3);
+ event->init();
+ data->push_back(event);
+ return true;
+ }))
+ // Screen state change to ON.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 5);
+ event->write("field1");
+ event->write(5);
+ event->init();
+ data->push_back(event);
+ return true;
+ }))
+ // Screen state change to VR.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+ event->write("field1");
+ event->write(9);
+ event->init();
+ data->push_back(event);
+ return true;
+ }))
+ // Screen state change to OFF.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 15);
+ event->write("field1");
+ event->write(21);
+ event->init();
+ data->push_back(event);
+ return true;
+ }))
+ // Dump report requested.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 50);
+ event->write("field1");
+ event->write(30);
+ event->init();
+ data->push_back(event);
+ return true;
+ }));
+
+ const StateMap& stateMap = CreateScreenStateOnOffMap();
+ const StateMap_StateGroup screenOnGroup = stateMap.group(0);
+ const StateMap_StateGroup screenOffGroup = stateMap.group(1);
+
+ unordered_map<int, unordered_map<int, int64_t>> stateGroupMap;
+ for (auto group : stateMap.group()) {
+ for (auto value : group.value()) {
+ stateGroupMap[SCREEN_STATE_ATOM_ID][value] = group.group_id();
+ }
+ }
+
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithState(
+ pullerManager, metric, {android::util::SCREEN_STATE_CHANGED}, stateGroupMap);
+
+ // Set up StateManager and check that StateTrackers are initialized.
+ StateManager::getInstance().clear();
+ StateManager::getInstance().registerListener(SCREEN_STATE_ATOM_ID, valueProducer);
+ EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
+ EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
+
+ // Bucket status after metric initialized.
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ // Base for dimension key {}
+ auto it = valueProducer->mCurrentSlicedBucket.begin();
+ auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+ EXPECT_EQ(true, itBase->second[0].hasBase);
+ EXPECT_EQ(3, itBase->second[0].base.long_value);
+ // Value for dimension, state key {{}, {}}
+ EXPECT_EQ(false, it->second[0].hasValue);
+
+ // Bucket status after screen state change kStateUnknown->ON.
+ auto screenEvent = CreateScreenStateChangedEvent(
+ android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + 5);
+ StateManager::getInstance().onLogEvent(*screenEvent);
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ // Base for dimension key {}
+ it = valueProducer->mCurrentSlicedBucket.begin();
+ itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+ EXPECT_EQ(true, itBase->second[0].hasBase);
+ EXPECT_EQ(5, itBase->second[0].base.long_value);
+ // Value for dimension, state key {{}, kStateUnknown}
+ EXPECT_EQ(true, it->second[0].hasValue);
+ EXPECT_EQ(2, it->second[0].value.long_value);
+
+ // Bucket status after screen state change ON->VR (also ON).
+ screenEvent = CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_VR,
+ bucketStartTimeNs + 10);
+ StateManager::getInstance().onLogEvent(*screenEvent);
+ EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+ // Base for dimension key {}
+ it = valueProducer->mCurrentSlicedBucket.begin();
+ itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+ EXPECT_EQ(true, itBase->second[0].hasBase);
+ EXPECT_EQ(9, itBase->second[0].base.long_value);
+ // Value for dimension, state key {{}, ON GROUP}
+ EXPECT_EQ(screenOnGroup.group_id(),
+ it->first.getStateValuesKey().getValues()[0].mValue.long_value);
+ EXPECT_EQ(true, it->second[0].hasValue);
+ EXPECT_EQ(4, it->second[0].value.long_value);
+ // Value for dimension, state key {{}, kStateUnknown}
+ it++;
+ EXPECT_EQ(true, it->second[0].hasValue);
+ EXPECT_EQ(2, it->second[0].value.long_value);
+
+ // Bucket status after screen state change VR->OFF.
+ screenEvent = CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+ bucketStartTimeNs + 15);
+ StateManager::getInstance().onLogEvent(*screenEvent);
+ EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+ // Base for dimension key {}
+ it = valueProducer->mCurrentSlicedBucket.begin();
+ itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+ EXPECT_EQ(true, itBase->second[0].hasBase);
+ EXPECT_EQ(21, itBase->second[0].base.long_value);
+ // Value for dimension, state key {{}, ON GROUP}
+ EXPECT_EQ(screenOnGroup.group_id(),
+ it->first.getStateValuesKey().getValues()[0].mValue.long_value);
+ EXPECT_EQ(true, it->second[0].hasValue);
+ EXPECT_EQ(16, it->second[0].value.long_value);
+ // Value for dimension, state key {{}, kStateUnknown}
+ it++;
+ EXPECT_EQ(true, it->second[0].hasValue);
+ EXPECT_EQ(2, it->second[0].value.long_value);
+
+ // Start dump report and check output.
+ ProtoOutputStream output;
+ std::set<string> strSet;
+ valueProducer->onDumpReport(bucketStartTimeNs + 50, true /* include recent buckets */, true,
+ NO_TIME_CONSTRAINTS, &strSet, &output);
+
+ StatsLogReport report = outputStreamToProto(&output);
+ EXPECT_TRUE(report.has_value_metrics());
+ EXPECT_EQ(3, report.value_metrics().data_size());
+
+ auto data = report.value_metrics().data(0);
+ EXPECT_EQ(1, data.bucket_info_size());
+ EXPECT_EQ(2, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
+
+ data = report.value_metrics().data(1);
+ EXPECT_EQ(1, report.value_metrics().data(1).bucket_info_size());
+ EXPECT_EQ(16, report.value_metrics().data(1).bucket_info(0).values(0).value_long());
+ EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+ EXPECT_TRUE(data.slice_by_state(0).has_group_id());
+ EXPECT_EQ(screenOnGroup.group_id(), data.slice_by_state(0).group_id());
+
+ data = report.value_metrics().data(2);
+ EXPECT_EQ(1, report.value_metrics().data(2).bucket_info_size());
+ EXPECT_EQ(9, report.value_metrics().data(2).bucket_info(0).values(0).value_long());
+ EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+ EXPECT_TRUE(data.slice_by_state(0).has_group_id());
+ EXPECT_EQ(screenOffGroup.group_id(), data.slice_by_state(0).group_id());
+}
+
+/*
+ * Test metric that slices by state with a primary field and has dimensions
+ * - Increasing values
+ * - Using diff
+ * - Second field is value field
+ */
+TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) {
+ // Set up ValueMetricProducer.
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("UID_PROCESS_STATE");
+ metric.mutable_dimensions_in_what()->set_field(tagId);
+ metric.mutable_dimensions_in_what()->add_child()->set_field(1);
+
+ MetricStateLink* stateLink = metric.add_state_link();
+ stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
+ auto fieldsInWhat = stateLink->mutable_fields_in_what();
+ *fieldsInWhat = CreateDimensions(tagId, {1 /* uid */});
+ auto fieldsInState = stateLink->mutable_fields_in_state();
+ *fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // ValueMetricProducer initialized.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+ event->write(2 /* uid */);
+ event->write(7);
+ event->init();
+ data->push_back(event);
+
+ event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+ event->write(1 /* uid */);
+ event->write(3);
+ event->init();
+ data->push_back(event);
+ return true;
+ }))
+ // Uid 1 process state change from kStateUnknown -> Foreground
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
+ event->write(1 /* uid */);
+ event->write(6);
+ event->init();
+ data->push_back(event);
+
+ // This event should be skipped.
+ event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
+ event->write(2 /* uid */);
+ event->write(8);
+ event->init();
+ data->push_back(event);
+ return true;
+ }))
+ // Uid 2 process state change from kStateUnknown -> Background
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 40);
+ event->write(2 /* uid */);
+ event->write(9);
+ event->init();
+ data->push_back(event);
+
+ // This event should be skipped.
+ event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 40);
+ event->write(1 /* uid */);
+ event->write(12);
+ event->init();
+ data->push_back(event);
+ return true;
+ }))
+ // Uid 1 process state change from Foreground -> Background
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 20);
+ event->write(1 /* uid */);
+ event->write(13);
+ event->init();
+ data->push_back(event);
+
+ // This event should be skipped.
+ event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 20);
+ event->write(2 /* uid */);
+ event->write(11);
+ event->init();
+ data->push_back(event);
+ return true;
+ }))
+ // Uid 1 process state change from Background -> Foreground
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 40);
+ event->write(1 /* uid */);
+ event->write(17);
+ event->init();
+ data->push_back(event);
+
+ // This event should be skipped.
+ event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 40);
+ event->write(2 /* uid */);
+ event->write(15);
+ event->init();
+ data->push_back(event);
+ return true;
+ }))
+ // Dump report pull.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 50);
+ event->write(2 /* uid */);
+ event->write(20);
+ event->init();
+ data->push_back(event);
+
+ event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 50);
+ event->write(1 /* uid */);
+ event->write(21);
+ event->init();
+ data->push_back(event);
+ return true;
+ }));
+
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithState(
+ pullerManager, metric, {UID_PROCESS_STATE_ATOM_ID}, {});
+
+ // Set up StateManager and check that StateTrackers are initialized.
+ StateManager::getInstance().clear();
+ StateManager::getInstance().registerListener(UID_PROCESS_STATE_ATOM_ID, valueProducer);
+ EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
+ EXPECT_EQ(1, StateManager::getInstance().getListenersCount(UID_PROCESS_STATE_ATOM_ID));
+
+ // Bucket status after metric initialized.
+ EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+ // Base for dimension key {uid 1}.
+ auto it = valueProducer->mCurrentSlicedBucket.begin();
+ EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+ auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+ EXPECT_EQ(true, itBase->second[0].hasBase);
+ EXPECT_EQ(3, itBase->second[0].base.long_value);
+ // Value for dimension, state key {{uid 1}, kStateUnknown}
+ // TODO(tsaichristine): test equality of state values key
+ // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+ EXPECT_EQ(false, it->second[0].hasValue);
+ // Base for dimension key {uid 2}
+ it++;
+ EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+ itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+ EXPECT_EQ(true, itBase->second[0].hasBase);
+ EXPECT_EQ(7, itBase->second[0].base.long_value);
+ // Value for dimension, state key {{uid 2}, kStateUnknown}
+ // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+ EXPECT_EQ(false, it->second[0].hasValue);
+
+ // Bucket status after uid 1 process state change kStateUnknown -> Foreground.
+ auto uidProcessEvent = CreateUidProcessStateChangedEvent(
+ 1 /* uid */, android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, bucketStartTimeNs + 20);
+ StateManager::getInstance().onLogEvent(*uidProcessEvent);
+ EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+ // Base for dimension key {uid 1}.
+ it = valueProducer->mCurrentSlicedBucket.begin();
+ EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+ itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+ EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+ EXPECT_EQ(true, itBase->second[0].hasBase);
+ EXPECT_EQ(6, itBase->second[0].base.long_value);
+ // Value for key {uid 1, kStateUnknown}.
+ // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+ EXPECT_EQ(true, it->second[0].hasValue);
+ EXPECT_EQ(3, it->second[0].value.long_value);
+
+ // Base for dimension key {uid 2}
+ it++;
+ EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+ itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+ EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+ EXPECT_EQ(true, itBase->second[0].hasBase);
+ EXPECT_EQ(7, itBase->second[0].base.long_value);
+ // Value for key {uid 2, kStateUnknown}
+ EXPECT_EQ(false, it->second[0].hasValue);
+
+ // Bucket status after uid 2 process state change kStateUnknown -> Background.
+ uidProcessEvent = CreateUidProcessStateChangedEvent(
+ 2 /* uid */, android::app::PROCESS_STATE_IMPORTANT_BACKGROUND, bucketStartTimeNs + 40);
+ StateManager::getInstance().onLogEvent(*uidProcessEvent);
+ EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+ // Base for dimension key {uid 1}.
+ it = valueProducer->mCurrentSlicedBucket.begin();
+ EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+ itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+ EXPECT_EQ(true, itBase->second[0].hasBase);
+ EXPECT_EQ(6, itBase->second[0].base.long_value);
+ // Value for key {uid 1, kStateUnknown}.
+ EXPECT_EQ(true, it->second[0].hasValue);
+ EXPECT_EQ(3, it->second[0].value.long_value);
+
+ // Base for dimension key {uid 2}
+ it++;
+ EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+ itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+ EXPECT_EQ(true, itBase->second[0].hasBase);
+ EXPECT_EQ(9, itBase->second[0].base.long_value);
+ // Value for key {uid 2, kStateUnknown}
+ // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+ EXPECT_EQ(true, it->second[0].hasValue);
+ EXPECT_EQ(2, it->second[0].value.long_value);
+
+ // Pull at end of first bucket.
+ vector<shared_ptr<LogEvent>> allData;
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs);
+ event->write(1 /* uid */);
+ event->write(10);
+ event->init();
+ allData.push_back(event);
+
+ event = make_shared<LogEvent>(tagId, bucket2StartTimeNs);
+ event->write(2 /* uid */);
+ event->write(15);
+ event->init();
+ allData.push_back(event);
+
+ valueProducer->onDataPulled(allData, /** succeeds */ true, bucket2StartTimeNs + 1);
+
+ // Buckets flushed after end of first bucket.
+ // None of the buckets should have a value.
+ EXPECT_EQ(4UL, valueProducer->mCurrentSlicedBucket.size());
+ EXPECT_EQ(4UL, valueProducer->mPastBuckets.size());
+ EXPECT_EQ(2UL, valueProducer->mCurrentBaseInfo.size());
+ // Base for dimension key {uid 2}.
+ it = valueProducer->mCurrentSlicedBucket.begin();
+ EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+ itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+ EXPECT_EQ(true, itBase->second[0].hasBase);
+ EXPECT_EQ(15, itBase->second[0].base.long_value);
+ // Value for key {uid 2, BACKGROUND}.
+ EXPECT_EQ(1, it->first.getStateValuesKey().getValues().size());
+ EXPECT_EQ(1006, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+ EXPECT_EQ(false, it->second[0].hasValue);
+
+ // Base for dimension key {uid 1}
+ it++;
+ EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+ itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+ EXPECT_EQ(true, itBase->second[0].hasBase);
+ EXPECT_EQ(10, itBase->second[0].base.long_value);
+ // Value for key {uid 1, kStateUnknown}
+ EXPECT_EQ(0, it->first.getStateValuesKey().getValues().size());
+ // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+ EXPECT_EQ(false, it->second[0].hasValue);
+
+ // Value for key {uid 1, FOREGROUND}
+ it++;
+ EXPECT_EQ(1, it->first.getStateValuesKey().getValues().size());
+ EXPECT_EQ(1005, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+ EXPECT_EQ(false, it->second[0].hasValue);
+
+ // Value for key {uid 2, kStateUnknown}
+ it++;
+ EXPECT_EQ(false, it->second[0].hasValue);
+
+ // Bucket status after uid 1 process state change from Foreground -> Background.
+ uidProcessEvent = CreateUidProcessStateChangedEvent(
+ 1 /* uid */, android::app::PROCESS_STATE_IMPORTANT_BACKGROUND, bucket2StartTimeNs + 20);
+ StateManager::getInstance().onLogEvent(*uidProcessEvent);
+
+ EXPECT_EQ(4UL, valueProducer->mCurrentSlicedBucket.size());
+ EXPECT_EQ(4UL, valueProducer->mPastBuckets.size());
+ EXPECT_EQ(2UL, valueProducer->mCurrentBaseInfo.size());
+ // Base for dimension key {uid 2}.
+ it = valueProducer->mCurrentSlicedBucket.begin();
+ EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+ itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+ EXPECT_EQ(true, itBase->second[0].hasBase);
+ EXPECT_EQ(15, itBase->second[0].base.long_value);
+ // Value for key {uid 2, BACKGROUND}.
+ EXPECT_EQ(false, it->second[0].hasValue);
+ // Base for dimension key {uid 1}
+ it++;
+ EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+ itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+ EXPECT_EQ(true, itBase->second[0].hasBase);
+ EXPECT_EQ(13, itBase->second[0].base.long_value);
+ // Value for key {uid 1, kStateUnknown}
+ EXPECT_EQ(false, it->second[0].hasValue);
+ // Value for key {uid 1, FOREGROUND}
+ it++;
+ EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+ EXPECT_EQ(1005, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+ EXPECT_EQ(true, it->second[0].hasValue);
+ EXPECT_EQ(3, it->second[0].value.long_value);
+ // Value for key {uid 2, kStateUnknown}
+ it++;
+ EXPECT_EQ(false, it->second[0].hasValue);
+
+ // Bucket status after uid 1 process state change Background->Foreground.
+ uidProcessEvent = CreateUidProcessStateChangedEvent(
+ 1 /* uid */, android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, bucket2StartTimeNs + 40);
+ StateManager::getInstance().onLogEvent(*uidProcessEvent);
+
+ EXPECT_EQ(5UL, valueProducer->mCurrentSlicedBucket.size());
+ EXPECT_EQ(2UL, valueProducer->mCurrentBaseInfo.size());
+ // Base for dimension key {uid 2}
+ it = valueProducer->mCurrentSlicedBucket.begin();
+ EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+ itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+ EXPECT_EQ(true, itBase->second[0].hasBase);
+ EXPECT_EQ(15, itBase->second[0].base.long_value);
+ EXPECT_EQ(false, it->second[0].hasValue);
+
+ it++;
+ EXPECT_EQ(false, it->second[0].hasValue);
+
+ // Base for dimension key {uid 1}
+ it++;
+ EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+ itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+ EXPECT_EQ(17, itBase->second[0].base.long_value);
+ // Value for key {uid 1, BACKGROUND}
+ EXPECT_EQ(1006, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+ EXPECT_EQ(true, it->second[0].hasValue);
+ EXPECT_EQ(4, it->second[0].value.long_value);
+ // Value for key {uid 1, FOREGROUND}
+ it++;
+ EXPECT_EQ(1005, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+ EXPECT_EQ(true, it->second[0].hasValue);
+ EXPECT_EQ(3, it->second[0].value.long_value);
+
+ // Start dump report and check output.
+ ProtoOutputStream output;
+ std::set<string> strSet;
+ valueProducer->onDumpReport(bucket2StartTimeNs + 50, true /* include recent buckets */, true,
+ NO_TIME_CONSTRAINTS, &strSet, &output);
+
+ StatsLogReport report = outputStreamToProto(&output);
+ EXPECT_TRUE(report.has_value_metrics());
+ EXPECT_EQ(5, report.value_metrics().data_size());
+
+ auto data = report.value_metrics().data(0);
+ EXPECT_EQ(1, data.bucket_info_size());
+ EXPECT_EQ(4, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
+ EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+ EXPECT_TRUE(data.slice_by_state(0).has_value());
+ EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
+ data.slice_by_state(0).value());
+
+ data = report.value_metrics().data(1);
+ EXPECT_EQ(1, report.value_metrics().data(1).bucket_info_size());
+ EXPECT_EQ(2, report.value_metrics().data(1).bucket_info(0).values(0).value_long());
+
+ data = report.value_metrics().data(2);
+ EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+ EXPECT_TRUE(data.slice_by_state(0).has_value());
+ EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
+ data.slice_by_state(0).value());
+ EXPECT_EQ(2, report.value_metrics().data(2).bucket_info_size());
+ EXPECT_EQ(4, report.value_metrics().data(2).bucket_info(0).values(0).value_long());
+ EXPECT_EQ(7, report.value_metrics().data(2).bucket_info(1).values(0).value_long());
+
+ data = report.value_metrics().data(3);
+ EXPECT_EQ(1, report.value_metrics().data(3).bucket_info_size());
+ EXPECT_EQ(3, report.value_metrics().data(3).bucket_info(0).values(0).value_long());
+
+ data = report.value_metrics().data(4);
+ EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+ EXPECT_TRUE(data.slice_by_state(0).has_value());
+ EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
+ data.slice_by_state(0).value());
+ EXPECT_EQ(2, report.value_metrics().data(4).bucket_info_size());
+ EXPECT_EQ(6, report.value_metrics().data(4).bucket_info(0).values(0).value_long());
+ EXPECT_EQ(5, report.value_metrics().data(4).bucket_info(1).values(0).value_long());
+}
+
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/cmds/statsd/tests/state/StateTracker_test.cpp b/cmds/statsd/tests/state/StateTracker_test.cpp
index 395167b998d0..26a3733ed598 100644
--- a/cmds/statsd/tests/state/StateTracker_test.cpp
+++ b/cmds/statsd/tests/state/StateTracker_test.cpp
@@ -146,6 +146,7 @@ TEST(StateListenerTest, TestStateListenerWeakPointer) {
TEST(StateManagerTest, TestStateManagerGetInstance) {
sp<TestStateListener> listener1 = new TestStateListener();
StateManager& mgr = StateManager::getInstance();
+ mgr.clear();
mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener1);
EXPECT_EQ(1, mgr.getStateTrackersCount());
diff --git a/cmds/statsd/tests/statsd_test_util.cpp b/cmds/statsd/tests/statsd_test_util.cpp
index d154b1b9cad9..7b651dfed7fc 100644
--- a/cmds/statsd/tests/statsd_test_util.cpp
+++ b/cmds/statsd/tests/statsd_test_util.cpp
@@ -18,6 +18,23 @@ namespace android {
namespace os {
namespace statsd {
+StatsLogReport outputStreamToProto(ProtoOutputStream* proto) {
+ vector<uint8_t> bytes;
+ bytes.resize(proto->size());
+ size_t pos = 0;
+ sp<ProtoReader> reader = proto->data();
+
+ while (reader->readBuffer() != NULL) {
+ size_t toRead = reader->currentToRead();
+ std::memcpy(&((bytes)[pos]), reader->readBuffer(), toRead);
+ pos += toRead;
+ reader->move(toRead);
+ }
+
+ StatsLogReport report;
+ report.ParseFromArray(bytes.data(), bytes.size());
+ return report;
+}
AtomMatcher CreateSimpleAtomMatcher(const string& name, int atomId) {
AtomMatcher atom_matcher;
diff --git a/cmds/statsd/tests/statsd_test_util.h b/cmds/statsd/tests/statsd_test_util.h
index e1e134be6b81..9bdfeebe561f 100644
--- a/cmds/statsd/tests/statsd_test_util.h
+++ b/cmds/statsd/tests/statsd_test_util.h
@@ -27,8 +27,15 @@ namespace android {
namespace os {
namespace statsd {
+using android::util::ProtoReader;
using google::protobuf::RepeatedPtrField;
+const int SCREEN_STATE_ATOM_ID = android::util::SCREEN_STATE_CHANGED;
+const int UID_PROCESS_STATE_ATOM_ID = android::util::UID_PROCESS_STATE_CHANGED;
+
+// Converts a ProtoOutputStream to a StatsLogReport proto.
+StatsLogReport outputStreamToProto(ProtoOutputStream* proto);
+
// Create AtomMatcher proto to simply match a specific atom type.
AtomMatcher CreateSimpleAtomMatcher(const string& name, int atomId);
diff --git a/cmds/svc/src/com/android/commands/svc/DataCommand.java b/cmds/svc/src/com/android/commands/svc/DataCommand.java
deleted file mode 100644
index b4dbd1d41bc1..000000000000
--- a/cmds/svc/src/com/android/commands/svc/DataCommand.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.commands.svc;
-
-/**
- * @deprecated Please use adb shell cmd phone data enabled/disable instead.
- */
-@Deprecated
-public class DataCommand extends Svc.Command {
-
- private static final String DECPRECATED_MESSAGE =
- "adb shell svc data enable/disable is deprecated;"
- + "please use adb shell cmd phone data enable/disable instead.";
-
- public DataCommand() {
- super("data");
- }
-
- public String shortHelp() {
- return "Control mobile data connectivity";
- }
-
- public String longHelp() {
- return shortHelp() + "\n"
- + "\n"
- + DECPRECATED_MESSAGE;
- }
-
- public void run(String[] args) {
- System.err.println(DECPRECATED_MESSAGE);
- }
-}
diff --git a/cmds/svc/src/com/android/commands/svc/Svc.java b/cmds/svc/src/com/android/commands/svc/Svc.java
index e602e2abbe03..2ed2678bc877 100644
--- a/cmds/svc/src/com/android/commands/svc/Svc.java
+++ b/cmds/svc/src/com/android/commands/svc/Svc.java
@@ -93,7 +93,6 @@ public class Svc {
public static final Command[] COMMANDS = new Command[] {
COMMAND_HELP,
new PowerCommand(),
- new DataCommand(),
// `svc wifi` has been migrated to WifiShellCommand
new UsbCommand(),
new NfcCommand(),
diff --git a/cmds/svc/svc b/cmds/svc/svc
index 60c95c7ec855..95265e817c1b 100755
--- a/cmds/svc/svc
+++ b/cmds/svc/svc
@@ -19,6 +19,20 @@ if [ "x$1" == "xwifi" ]; then
exit 1
fi
+if [ "x$1" == "xdata" ]; then
+ if [ "x$2" == "xenable" ]; then
+ exec cmd phone data enable
+ elif [ "x$2" == "xdisable" ]; then
+ exec cmd phone data disable
+ else
+ echo "Enable/Disable Mobile Data Connectivity"
+ echo ""
+ echo "usage: svc data [enable|disable]"
+ echo ""
+ fi
+ exit 1
+fi
+
export CLASSPATH=/system/framework/svc.jar
exec app_process /system/bin com.android.commands.svc.Svc "$@"
diff --git a/core/java/android/accessibilityservice/AccessibilityButtonController.java b/core/java/android/accessibilityservice/AccessibilityButtonController.java
index af5af9cb9b17..2ccad1d2d224 100644
--- a/core/java/android/accessibilityservice/AccessibilityButtonController.java
+++ b/core/java/android/accessibilityservice/AccessibilityButtonController.java
@@ -23,7 +23,7 @@ import android.os.RemoteException;
import android.util.ArrayMap;
import android.util.Slog;
-import com.android.internal.util.Preconditions;
+import java.util.Objects;
/**
* Controller for the accessibility button within the system's navigation area
@@ -108,8 +108,8 @@ public final class AccessibilityButtonController {
*/
public void registerAccessibilityButtonCallback(@NonNull AccessibilityButtonCallback callback,
@NonNull Handler handler) {
- Preconditions.checkNotNull(callback);
- Preconditions.checkNotNull(handler);
+ Objects.requireNonNull(callback);
+ Objects.requireNonNull(handler);
synchronized (mLock) {
if (mCallbacks == null) {
mCallbacks = new ArrayMap<>();
@@ -127,7 +127,7 @@ public final class AccessibilityButtonController {
*/
public void unregisterAccessibilityButtonCallback(
@NonNull AccessibilityButtonCallback callback) {
- Preconditions.checkNotNull(callback);
+ Objects.requireNonNull(callback);
synchronized (mLock) {
if (mCallbacks == null) {
return;
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 0f619c8d1f76..c0fee6e9e5e9 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -21,8 +21,8 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
-import android.annotation.UnsupportedAppUsage;
import android.app.Service;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ParceledListSlice;
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index 7fd01dbf95fb..5e2c1faac156 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -22,9 +22,9 @@ import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledAfter;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
diff --git a/core/java/android/accounts/Account.java b/core/java/android/accounts/Account.java
index c822d20445ec..9a18880a353b 100644
--- a/core/java/android/accounts/Account.java
+++ b/core/java/android/accounts/Account.java
@@ -18,7 +18,7 @@ package android.accounts;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/accounts/AccountAndUser.java b/core/java/android/accounts/AccountAndUser.java
index b0d53438d97c..fd6739410ce2 100644
--- a/core/java/android/accounts/AccountAndUser.java
+++ b/core/java/android/accounts/AccountAndUser.java
@@ -16,7 +16,7 @@
package android.accounts;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* Used to store the Account and the UserId this account is associated with.
diff --git a/core/java/android/accounts/AccountAuthenticatorResponse.java b/core/java/android/accounts/AccountAuthenticatorResponse.java
index bb2e327a9be8..a2a57990297c 100644
--- a/core/java/android/accounts/AccountAuthenticatorResponse.java
+++ b/core/java/android/accounts/AccountAuthenticatorResponse.java
@@ -16,10 +16,10 @@
package android.accounts;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Bundle;
-import android.os.Parcelable;
import android.os.Parcel;
+import android.os.Parcelable;
import android.os.RemoteException;
import android.util.Log;
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index 0f10c3980021..8fe2f12a1023 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -25,8 +25,8 @@ import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.Size;
import android.annotation.SystemApi;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
import android.app.Activity;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
diff --git a/core/java/android/accounts/AuthenticatorDescription.java b/core/java/android/accounts/AuthenticatorDescription.java
index 555639445e85..b7bf11d4d5b6 100644
--- a/core/java/android/accounts/AuthenticatorDescription.java
+++ b/core/java/android/accounts/AuthenticatorDescription.java
@@ -16,10 +16,10 @@
package android.accounts;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
-import android.os.Parcelable;
import android.os.Parcel;
+import android.os.Parcelable;
/**
* A {@link Parcelable} value type that contains information about an account authenticator.
diff --git a/core/java/android/animation/Animator.java b/core/java/android/animation/Animator.java
index 17d54d2455fe..3cdd691fd5dd 100644
--- a/core/java/android/animation/Animator.java
+++ b/core/java/android/animation/Animator.java
@@ -17,7 +17,7 @@
package android.animation;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo.Config;
import android.content.res.ConstantState;
diff --git a/core/java/android/animation/ArgbEvaluator.java b/core/java/android/animation/ArgbEvaluator.java
index 5b69d18a8386..9519ddde86f4 100644
--- a/core/java/android/animation/ArgbEvaluator.java
+++ b/core/java/android/animation/ArgbEvaluator.java
@@ -16,7 +16,7 @@
package android.animation;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* This evaluator can be used to perform type interpolation between integer
diff --git a/core/java/android/animation/LayoutTransition.java b/core/java/android/animation/LayoutTransition.java
index c7537102d40c..21f0b6b2ae62 100644
--- a/core/java/android/animation/LayoutTransition.java
+++ b/core/java/android/animation/LayoutTransition.java
@@ -16,7 +16,7 @@
package android.animation;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.view.View;
import android.view.ViewGroup;
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index 764e5992fbd9..ca37e9b107a0 100644
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -19,7 +19,7 @@ package android.animation;
import android.annotation.CallSuper;
import android.annotation.IntDef;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Looper;
import android.os.Trace;
diff --git a/core/java/android/annotation/CallbackExecutor.java b/core/java/android/annotation/CallbackExecutor.java
index 5671a3d2b6d6..4258f730eb16 100644
--- a/core/java/android/annotation/CallbackExecutor.java
+++ b/core/java/android/annotation/CallbackExecutor.java
@@ -19,9 +19,6 @@ package android.annotation;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.SOURCE;
-import android.content.Context;
-import android.os.AsyncTask;
-
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.util.concurrent.Executor;
@@ -30,9 +27,10 @@ import java.util.concurrent.Executor;
* @paramDoc Callback and listener events are dispatched through this
* {@link Executor}, providing an easy way to control which thread is
* used. To dispatch events through the main thread of your
- * application, you can use {@link Context#getMainExecutor()}. To
- * dispatch events through a shared thread pool, you can use
- * {@link AsyncTask#THREAD_POOL_EXECUTOR}.
+ * application, you can use
+ * {@link android.content.Context#getMainExecutor() Context.getMainExecutor()}.
+ * To dispatch events through a shared thread pool, you can use
+ * {@link android.os.AsyncTask#THREAD_POOL_EXECUTOR AsyncTask#THREAD_POOL_EXECUTOR}.
* @hide
*/
@Retention(SOURCE)
diff --git a/core/java/android/annotation/RequiresPermission.java b/core/java/android/annotation/RequiresPermission.java
index 59d419f78ee0..1d89e31b2b99 100644
--- a/core/java/android/annotation/RequiresPermission.java
+++ b/core/java/android/annotation/RequiresPermission.java
@@ -15,11 +15,6 @@
*/
package android.annotation;
-import android.content.Intent;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.FIELD;
@@ -27,6 +22,9 @@ import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.SOURCE;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
/**
* Denotes that the annotated element requires (or may require) one or more permissions.
* <p/>
@@ -57,7 +55,8 @@ import static java.lang.annotation.RetentionPolicy.SOURCE;
* <p>
* When specified on a parameter, the annotation indicates that the method requires
* a permission which depends on the value of the parameter. For example, consider
- * {@link android.app.Activity#startActivity(Intent)}:
+ * {@link android.app.Activity#startActivity(android.content.Intent)
+ * Activity#startActivity(Intent)}:
* <pre>{@code
* public void startActivity(@RequiresPermission Intent intent) { ... }
* }</pre>
diff --git a/core/java/android/annotation/SystemApi.java b/core/java/android/annotation/SystemApi.java
index f589cc5704b4..2cb93e4f8cea 100644
--- a/core/java/android/annotation/SystemApi.java
+++ b/core/java/android/annotation/SystemApi.java
@@ -44,9 +44,24 @@ public @interface SystemApi {
enum Client {
/**
* Specifies that the intended clients of a SystemApi are privileged apps.
- * This is the default value for {@link #client}.
+ * This is the default value for {@link #client}. This implies
+ * MODULE_APPS and MODULE_LIBRARIES as well, which means that APIs will also
+ * be available to module apps and jars.
*/
PRIVILEGED_APPS,
+
+ /**
+ * Specifies that the intended clients of a SystemApi are modules implemented
+ * as apps, like the NetworkStack app. This implies MODULE_LIBRARIES as well,
+ * which means that APIs will also be available to module jars.
+ */
+ MODULE_APPS,
+
+ /**
+ * Specifies that the intended clients of a SystemApi are modules implemented
+ * as libraries, like the conscrypt.jar in the conscrypt APEX.
+ */
+ MODULE_LIBRARIES
}
enum Process {
@@ -55,6 +70,11 @@ public @interface SystemApi {
* This is the default value for {@link #process}.
*/
ALL,
+
+ /**
+ * Specifies that the SystemAPI is available only in the system server process.
+ */
+ SYSTEM_SERVER
}
/**
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java
index e57327991a82..504364c8c1d9 100644
--- a/core/java/android/app/ActionBar.java
+++ b/core/java/android/app/ActionBar.java
@@ -22,7 +22,7 @@ import android.annotation.LayoutRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringRes;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.TypedArray;
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 1e3b95070d69..070a4f80d4e2 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -33,10 +33,10 @@ import android.annotation.RequiresPermission;
import android.annotation.StyleRes;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.VoiceInteractor.Request;
import android.app.admin.DevicePolicyManager;
import android.app.assist.AssistContent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentCallbacks2;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -2837,6 +2837,17 @@ public class Activity extends ContextThemeWrapper
return getPackageManager().hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE);
}
+ /**
+ * Called by the system when picture in picture mode should be entered if supported.
+ */
+ public void onPictureInPictureRequested() {
+ // Previous recommendation was for apps to enter picture-in-picture in onUserLeaveHint()
+ // which is sent after onPause(). This new method allows the system to request the app to
+ // go into picture-in-picture decoupling it from life cycle events. For backwards
+ // compatibility we schedule the life cycle events if the app didn't override this method.
+ mMainThread.schedulePauseAndReturnToCurrentState(mToken);
+ }
+
void dispatchMovedToDisplay(int displayId, Configuration config) {
updateDisplay(displayId);
onMovedToDisplay(displayId, config);
@@ -7871,6 +7882,7 @@ public class Activity extends ContextThemeWrapper
mCurrentConfig = config;
mWindow.setColorMode(info.colorMode);
+ mWindow.setPreferMinimalPostProcessing(info.preferMinimalPostProcessing);
setAutofillOptions(application.getAutofillOptions());
setContentCaptureOptions(application.getContentCaptureOptions());
@@ -8674,7 +8686,6 @@ public class Activity extends ContextThemeWrapper
* @hide
*/
@RequiresPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS)
- @UnsupportedAppUsage
public void registerRemoteAnimations(RemoteAnimationDefinition definition) {
try {
ActivityTaskManager.getService().registerRemoteAnimations(mToken, definition);
@@ -8683,6 +8694,20 @@ public class Activity extends ContextThemeWrapper
}
}
+ /**
+ * Unregisters all remote animations for this activity.
+ *
+ * @hide
+ */
+ @RequiresPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS)
+ public void unregisterRemoteAnimations() {
+ try {
+ ActivityTaskManager.getService().unregisterRemoteAnimations(mToken);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
class HostCallbacks extends FragmentHostCallback<Activity> {
public HostCallbacks() {
super(Activity.this /*activity*/);
diff --git a/core/java/android/app/ActivityGroup.java b/core/java/android/app/ActivityGroup.java
index d4aa01b8f43e..cb06eea2059e 100644
--- a/core/java/android/app/ActivityGroup.java
+++ b/core/java/android/app/ActivityGroup.java
@@ -16,7 +16,7 @@
package android.app;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.os.Bundle;
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 795f51ac5454..3f9f7fbbe477 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -28,7 +28,7 @@ import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -1120,8 +1120,8 @@ public class ActivityManager {
}
/**
- * Copies this the values from another TaskDescription, but preserves the hidden fields
- * if they weren't set on {@code other}
+ * Copies values from another TaskDescription, but preserves the hidden fields if they
+ * weren't set on {@code other}. Public fields will be overwritten anyway.
* @hide
*/
public void copyFromPreserveHiddenFields(TaskDescription other) {
@@ -1130,6 +1130,7 @@ public class ActivityManager {
mIconRes = other.mIconRes;
mIconFilename = other.mIconFilename;
mColorPrimary = other.mColorPrimary;
+
if (other.mColorBackground != 0) {
mColorBackground = other.mColorBackground;
}
@@ -1139,12 +1140,20 @@ public class ActivityManager {
if (other.mNavigationBarColor != 0) {
mNavigationBarColor = other.mNavigationBarColor;
}
+
mEnsureStatusBarContrastWhenTransparent = other.mEnsureStatusBarContrastWhenTransparent;
mEnsureNavigationBarContrastWhenTransparent =
other.mEnsureNavigationBarContrastWhenTransparent;
- mResizeMode = other.mResizeMode;
- mMinWidth = other.mMinWidth;
- mMinHeight = other.mMinHeight;
+
+ if (other.mResizeMode != RESIZE_MODE_RESIZEABLE) {
+ mResizeMode = other.mResizeMode;
+ }
+ if (other.mMinWidth != -1) {
+ mMinWidth = other.mMinWidth;
+ }
+ if (other.mMinHeight != -1) {
+ mMinHeight = other.mMinHeight;
+ }
}
private TaskDescription(Parcel source) {
@@ -2097,6 +2106,113 @@ public class ActivityManager {
return new TaskSnapshot[size];
}
};
+
+ /** Builder for a {@link TaskSnapshot} object */
+ public static final class Builder {
+ private long mId;
+ private ComponentName mTopActivity;
+ private GraphicBuffer mSnapshot;
+ private ColorSpace mColorSpace;
+ private int mOrientation;
+ private Rect mContentInsets;
+ private boolean mReducedResolution;
+ private float mScaleFraction;
+ private boolean mIsRealSnapshot;
+ private int mWindowingMode;
+ private int mSystemUiVisibility;
+ private boolean mIsTranslucent;
+ private int mPixelFormat;
+
+ public Builder setId(long id) {
+ mId = id;
+ return this;
+ }
+
+ public Builder setTopActivityComponent(ComponentName name) {
+ mTopActivity = name;
+ return this;
+ }
+
+ public Builder setSnapshot(GraphicBuffer buffer) {
+ mSnapshot = buffer;
+ return this;
+ }
+
+ public Builder setColorSpace(ColorSpace colorSpace) {
+ mColorSpace = colorSpace;
+ return this;
+ }
+
+ public Builder setOrientation(int orientation) {
+ mOrientation = orientation;
+ return this;
+ }
+
+ public Builder setContentInsets(Rect contentInsets) {
+ mContentInsets = contentInsets;
+ return this;
+ }
+
+ public Builder setReducedResolution(boolean reducedResolution) {
+ mReducedResolution = reducedResolution;
+ return this;
+ }
+
+ public float getScaleFraction() {
+ return mScaleFraction;
+ }
+
+ public Builder setScaleFraction(float scaleFraction) {
+ mScaleFraction = scaleFraction;
+ return this;
+ }
+
+ public Builder setIsRealSnapshot(boolean realSnapshot) {
+ mIsRealSnapshot = realSnapshot;
+ return this;
+ }
+
+ public Builder setWindowingMode(int windowingMode) {
+ mWindowingMode = windowingMode;
+ return this;
+ }
+
+ public Builder setSystemUiVisibility(int systemUiVisibility) {
+ mSystemUiVisibility = systemUiVisibility;
+ return this;
+ }
+
+ public Builder setIsTranslucent(boolean isTranslucent) {
+ mIsTranslucent = isTranslucent;
+ return this;
+ }
+
+ public int getPixelFormat() {
+ return mPixelFormat;
+ }
+
+ public Builder setPixelFormat(int pixelFormat) {
+ mPixelFormat = pixelFormat;
+ return this;
+ }
+
+ public TaskSnapshot build() {
+ return new TaskSnapshot(
+ mId,
+ mTopActivity,
+ mSnapshot,
+ mColorSpace,
+ mOrientation,
+ mContentInsets,
+ mReducedResolution,
+ mScaleFraction,
+ mIsRealSnapshot,
+ mWindowingMode,
+ mSystemUiVisibility,
+ mIsTranslucent);
+
+ }
+ }
}
/** @hide */
@@ -4431,4 +4547,17 @@ public class ActivityManager {
throw e.rethrowFromSystemServer();
}
}
+
+ /**
+ * Method for the app to tell system that it's wedged and would like to trigger an ANR.
+ *
+ * @param reason The description of that what happened
+ */
+ public void appNotResponding(@NonNull final String reason) {
+ try {
+ getService().appNotResponding(reason);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 607ef185ae60..b9eb95739aa1 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -15,7 +15,7 @@
*/
package android.app;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.os.IBinder;
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index f91453ea0811..4aacf4879c43 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -25,7 +25,7 @@ import static android.view.Display.INVALID_DISPLAY;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/app/ActivityTaskManager.java b/core/java/android/app/ActivityTaskManager.java
index ac8c9f466f33..dd9a2bcf9c2c 100644
--- a/core/java/android/app/ActivityTaskManager.java
+++ b/core/java/android/app/ActivityTaskManager.java
@@ -16,10 +16,11 @@
package android.app;
+import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Resources;
@@ -433,4 +434,18 @@ public class ActivityTaskManager {
throw e.rethrowFromSystemServer();
}
}
+
+ /**
+ * Requests that an activity should enter picture-in-picture mode if possible.
+ * @hide
+ */
+ @TestApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
+ public void requestPictureInPictureMode(@NonNull IBinder token) {
+ try {
+ getService().requestPictureInPictureMode(token);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 5cdc50564787..08f873494cbc 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -32,7 +32,6 @@ import static com.android.internal.annotations.VisibleForTesting.Visibility.PACK
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.app.assist.AssistContent;
import android.app.assist.AssistStructure;
import android.app.backup.BackupAgent;
@@ -42,10 +41,13 @@ import android.app.servertransaction.ActivityRelaunchItem;
import android.app.servertransaction.ActivityResultItem;
import android.app.servertransaction.ClientTransaction;
import android.app.servertransaction.ClientTransactionItem;
+import android.app.servertransaction.PauseActivityItem;
import android.app.servertransaction.PendingTransactionActions;
import android.app.servertransaction.PendingTransactionActions.StopInfo;
+import android.app.servertransaction.ResumeActivityItem;
import android.app.servertransaction.TransactionExecutor;
import android.app.servertransaction.TransactionExecutorHelper;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.AutofillOptions;
import android.content.BroadcastReceiver;
import android.content.ComponentCallbacks2;
@@ -522,6 +524,8 @@ public final class ActivityThread extends ClientTransactionHandler {
boolean startsNotResumed;
public final boolean isForward;
int pendingConfigChanges;
+ // Whether we are in the process of performing on user leaving.
+ boolean mIsUserLeaving;
Window mPendingRemoveWindow;
WindowManager mPendingRemoveWindowManager;
@@ -3763,6 +3767,66 @@ public final class ActivityThread extends ClientTransactionHandler {
}
}
+ @Override
+ public void handlePictureInPictureRequested(IBinder token) {
+ final ActivityClientRecord r = mActivities.get(token);
+ if (r == null) {
+ Log.w(TAG, "Activity to request PIP to no longer exists");
+ return;
+ }
+
+ r.activity.onPictureInPictureRequested();
+ }
+
+ /**
+ * Cycle activity through onPause and onUserLeaveHint so that PIP is entered if supported, then
+ * return to its previous state. This allows activities that rely on onUserLeaveHint instead of
+ * onPictureInPictureRequested to enter picture-in-picture.
+ */
+ public void schedulePauseAndReturnToCurrentState(IBinder token) {
+ final ActivityClientRecord r = mActivities.get(token);
+ if (r == null) {
+ Log.w(TAG, "Activity to request pause with user leaving hint to no longer exists");
+ return;
+ }
+
+ if (r.mIsUserLeaving) {
+ // The activity is about to perform user leaving, so there's no need to cycle ourselves.
+ return;
+ }
+
+ final int prevState = r.getLifecycleState();
+ if (prevState != ON_RESUME && prevState != ON_PAUSE) {
+ return;
+ }
+
+ switch (prevState) {
+ case ON_RESUME:
+ // Schedule a PAUSE then return to RESUME.
+ schedulePauseWithUserLeavingHint(r);
+ scheduleResume(r);
+ break;
+ case ON_PAUSE:
+ // Schedule a RESUME then return to PAUSE.
+ scheduleResume(r);
+ schedulePauseWithUserLeavingHint(r);
+ break;
+ }
+ }
+
+ private void schedulePauseWithUserLeavingHint(ActivityClientRecord r) {
+ final ClientTransaction transaction = ClientTransaction.obtain(this.mAppThread, r.token);
+ transaction.setLifecycleStateRequest(PauseActivityItem.obtain(r.activity.isFinishing(),
+ /* userLeaving */ true, r.activity.mConfigChangeFlags, /* dontReport */ false));
+ executeTransaction(transaction);
+ }
+
+ private void scheduleResume(ActivityClientRecord r) {
+ final ClientTransaction transaction = ClientTransaction.obtain(this.mAppThread, r.token);
+ transaction.setLifecycleStateRequest(ResumeActivityItem.obtain(/* isForward */ false));
+ executeTransaction(transaction);
+ }
+
private void handleLocalVoiceInteractionStarted(IBinder token, IVoiceInteractor interactor) {
final ActivityClientRecord r = mActivities.get(token);
if (r != null) {
@@ -4483,6 +4547,7 @@ public final class ActivityThread extends ClientTransactionHandler {
if (r != null) {
if (userLeaving) {
performUserLeavingActivity(r);
+ r.mIsUserLeaving = false;
}
r.activity.mConfigChangeFlags |= configChanges;
@@ -4497,6 +4562,8 @@ public final class ActivityThread extends ClientTransactionHandler {
}
final void performUserLeavingActivity(ActivityClientRecord r) {
+ r.mIsUserLeaving = true;
+ mInstrumentation.callActivityOnPictureInPictureRequested(r.activity);
mInstrumentation.callActivityOnUserLeaving(r.activity);
}
diff --git a/core/java/android/app/AlarmManager.java b/core/java/android/app/AlarmManager.java
index d8ddf218c6d4..c03413c80aa0 100644
--- a/core/java/android/app/AlarmManager.java
+++ b/core/java/android/app/AlarmManager.java
@@ -21,7 +21,7 @@ import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SystemApi;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
diff --git a/core/java/android/app/AlertDialog.java b/core/java/android/app/AlertDialog.java
index bfc216a24c1b..4c347373d642 100644
--- a/core/java/android/app/AlertDialog.java
+++ b/core/java/android/app/AlertDialog.java
@@ -21,7 +21,7 @@ import android.annotation.AttrRes;
import android.annotation.DrawableRes;
import android.annotation.StringRes;
import android.annotation.StyleRes;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.ResourceId;
diff --git a/core/java/android/app/AppGlobals.java b/core/java/android/app/AppGlobals.java
index 8312327a8c1d..81e1565ee86c 100644
--- a/core/java/android/app/AppGlobals.java
+++ b/core/java/android/app/AppGlobals.java
@@ -16,7 +16,7 @@
package android.app;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.IPackageManager;
import android.permission.IPermissionManager;
diff --git a/core/java/android/app/AppOpsManager.aidl b/core/java/android/app/AppOpsManager.aidl
index 224030202e08..b4dee2e937cb 100644
--- a/core/java/android/app/AppOpsManager.aidl
+++ b/core/java/android/app/AppOpsManager.aidl
@@ -17,6 +17,9 @@
package android.app;
parcelable AppOpsManager.PackageOps;
+parcelable AppOpsManager.NoteOpEventProxyInfo;
+parcelable AppOpsManager.NoteOpEvent;
+parcelable AppOpsManager.OpFeatureEntry;
parcelable AppOpsManager.OpEntry;
parcelable AppOpsManager.HistoricalOp;
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index f2fa4fd6845c..86a5c762240f 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -26,8 +26,8 @@ import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.usage.UsageStatsManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -48,9 +48,9 @@ import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.UserManager;
import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.LongSparseArray;
import android.util.LongSparseLongArray;
-import android.util.Pair;
import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
@@ -63,6 +63,8 @@ import com.android.internal.app.IAppOpsService;
import com.android.internal.os.RuntimeInit;
import com.android.internal.os.ZygoteInit;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.DataClass;
+import com.android.internal.util.Parcelling;
import com.android.internal.util.Preconditions;
import java.lang.annotation.ElementType;
@@ -83,7 +85,6 @@ import java.util.Objects;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
import java.util.function.Supplier;
-import java.util.function.ToLongFunction;
/**
* API for interacting with "application operation" tracking.
@@ -138,7 +139,7 @@ public class AppOpsManager {
@GuardedBy("sLock")
private static @Nullable AppOpsCollector sNotedAppOpsCollector;
- static IBinder sToken;
+ static IBinder sClientId;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@@ -846,10 +847,12 @@ public class AppOpsManager {
public static final int OP_ACCESS_MEDIA_LOCATION = 90;
/** @hide Query all apps on device, regardless of declarations in the calling app manifest */
public static final int OP_QUERY_ALL_PACKAGES = 91;
+ /** @hide Access all external storage */
+ public static final int OP_MANAGE_EXTERNAL_STORAGE = 92;
/** @hide */
@UnsupportedAppUsage
- public static final int _NUM_OP = 92;
+ public static final int _NUM_OP = 93;
/** Access to coarse location information. */
public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -1135,6 +1138,10 @@ public class AppOpsManager {
public static final String OPSTR_READ_DEVICE_IDENTIFIERS = "android:read_device_identifiers";
/** @hide Query all packages on device */
public static final String OPSTR_QUERY_ALL_PACKAGES = "android:query_all_packages";
+ /** @hide Access all external storage */
+ @SystemApi
+ public static final String OPSTR_MANAGE_EXTERNAL_STORAGE =
+ "android:manage_external_storage";
/** {@link #sAppOpsToNote} not initialized yet for this op */
@@ -1317,6 +1324,7 @@ public class AppOpsManager {
OP_READ_DEVICE_IDENTIFIERS, // READ_DEVICE_IDENTIFIERS
OP_ACCESS_MEDIA_LOCATION, // ACCESS_MEDIA_LOCATION
OP_QUERY_ALL_PACKAGES, // QUERY_ALL_PACKAGES
+ OP_MANAGE_EXTERNAL_STORAGE, // MANAGE_EXTERNAL_STORAGE
};
/**
@@ -1415,6 +1423,7 @@ public class AppOpsManager {
OPSTR_READ_DEVICE_IDENTIFIERS,
OPSTR_ACCESS_MEDIA_LOCATION,
OPSTR_QUERY_ALL_PACKAGES,
+ OPSTR_MANAGE_EXTERNAL_STORAGE,
};
/**
@@ -1514,6 +1523,7 @@ public class AppOpsManager {
"READ_DEVICE_IDENTIFIERS",
"ACCESS_MEDIA_LOCATION",
"QUERY_ALL_PACKAGES",
+ "MANAGE_EXTERNAL_STORAGE"
};
/**
@@ -1614,6 +1624,7 @@ public class AppOpsManager {
null, // no direct permission for OP_READ_DEVICE_IDENTIFIERS
Manifest.permission.ACCESS_MEDIA_LOCATION,
null, // no permission for OP_QUERY_ALL_PACKAGES
+ null, // no permission for OP_MANAGE_EXTERNAL_STORAGE
};
/**
@@ -1714,6 +1725,7 @@ public class AppOpsManager {
null, // READ_DEVICE_IDENTIFIERS
null, // ACCESS_MEDIA_LOCATION
null, // QUERY_ALL_PACKAGES
+ null, // MANAGE_EXTERNAL_STORAGE
};
/**
@@ -1813,6 +1825,7 @@ public class AppOpsManager {
false, // READ_DEVICE_IDENTIFIERS
false, // ACCESS_MEDIA_LOCATION
false, // QUERY_ALL_PACKAGES
+ false, // MANAGE_EXTERNAL_STORAGE
};
/**
@@ -1911,6 +1924,7 @@ public class AppOpsManager {
AppOpsManager.MODE_ERRORED, // READ_DEVICE_IDENTIFIERS
AppOpsManager.MODE_ALLOWED, // ALLOW_MEDIA_LOCATION
AppOpsManager.MODE_DEFAULT, // QUERY_ALL_PACKAGES
+ AppOpsManager.MODE_DEFAULT, // MANAGE_EXTERNAL_STORAGE
};
/**
@@ -2013,6 +2027,7 @@ public class AppOpsManager {
false, // READ_DEVICE_IDENTIFIERS
false, // ACCESS_MEDIA_LOCATION
false, // QUERY_ALL_PACKAGES
+ false, // MANAGE_EXTERNAL_STORAGE
};
/**
@@ -2245,6 +2260,7 @@ public class AppOpsManager {
* Class holding all of the operation information associated with an app.
* @hide
*/
+ @TestApi
@SystemApi
public static final class PackageOps implements Parcelable {
private final String mPackageName;
@@ -2288,7 +2304,7 @@ public class AppOpsManager {
}
@Override
- public void writeToParcel(Parcel dest, int flags) {
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeString(mPackageName);
dest.writeInt(mUid);
dest.writeInt(mEntries.size());
@@ -2319,537 +2335,878 @@ public class AppOpsManager {
}
/**
- * Class holding the information about one unique operation of a
- * {@link Context#createFeatureContext(String) feature}.
+ * Proxy information for a {@link #noteOp} event
*
* @hide
*/
@TestApi
- @Immutable
@SystemApi
- public static final class OpFeatureEntry {
- private final @NonNull OpEntry mParent;
- private final boolean mRunning;
+ @Immutable
+ @DataClass(genHiddenConstructor = true)
+ public static final class OpEventProxyInfo implements Parcelable {
+ /** UID of the proxy app that noted the op */
+ private final @IntRange(from = 0) int mUid;
+ /** Package of the proxy that noted the op */
+ private final @Nullable String mPackageName;
+ /** ID of the feature of the proxy that noted the op */
+ private final @Nullable String mFeatureId;
+
+
+
+ // Code below generated by codegen v1.0.14.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/app/AppOpsManager.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
- private final @Nullable LongSparseLongArray mAccessTimes;
- private final @Nullable LongSparseLongArray mRejectTimes;
- private final @Nullable LongSparseLongArray mDurations;
- private final @Nullable LongSparseLongArray mProxyUids;
- private final @Nullable LongSparseArray<String> mProxyPackageNames;
- private final @Nullable LongSparseArray<String> mProxyFeatureIds;
/**
+ * Creates a new OpEventProxyInfo.
+ *
+ * @param uid
+ * UID of the proxy app that noted the op
+ * @param packageName
+ * Package of the proxy that noted the op
+ * @param featureId
+ * ID of the feature of the proxy that noted the op
* @hide
*/
- public OpFeatureEntry(@NonNull OpEntry parent, boolean running,
- @Nullable LongSparseLongArray accessTimes,
- @Nullable LongSparseLongArray rejectTimes,
- @Nullable LongSparseLongArray durations, @Nullable LongSparseLongArray proxyUids,
- @Nullable LongSparseArray<String> proxyPackageNames,
- @Nullable LongSparseArray<String> proxyFeatureIds) {
- mParent = Preconditions.checkNotNull(parent);
- mRunning = running;
- mAccessTimes = accessTimes;
- mRejectTimes = rejectTimes;
- mDurations = durations;
- mProxyUids = proxyUids;
- mProxyPackageNames = proxyPackageNames;
- mProxyFeatureIds = proxyFeatureIds;
+ @DataClass.Generated.Member
+ public OpEventProxyInfo(
+ @IntRange(from = 0) int uid,
+ @Nullable String packageName,
+ @Nullable String featureId) {
+ this.mUid = uid;
+ com.android.internal.util.AnnotationValidations.validate(
+ IntRange.class, null, mUid,
+ "from", 0);
+ this.mPackageName = packageName;
+ this.mFeatureId = featureId;
+
+ // onConstructed(); // You can define this method to get a callback
}
/**
- * Returns all keys for which we have mapped state in any of the data buckets -
- * access time, reject time, duration.
- * @hide */
- public @Nullable LongSparseArray<Object> collectKeys() {
- LongSparseArray<Object> result = AppOpsManager.collectKeys(mAccessTimes, null);
- result = AppOpsManager.collectKeys(mRejectTimes, result);
- result = AppOpsManager.collectKeys(mDurations, result);
- return result;
+ * UID of the proxy app that noted the op
+ */
+ @DataClass.Generated.Member
+ public @IntRange(from = 0) int getUid() {
+ return mUid;
+ }
+
+ /**
+ * Package of the proxy that noted the op
+ */
+ @DataClass.Generated.Member
+ public @Nullable String getPackageName() {
+ return mPackageName;
+ }
+
+ /**
+ * ID of the feature of the proxy that noted the op
+ */
+ @DataClass.Generated.Member
+ public @Nullable String getFeatureId() {
+ return mFeatureId;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ byte flg = 0;
+ if (mPackageName != null) flg |= 0x2;
+ if (mFeatureId != null) flg |= 0x4;
+ dest.writeByte(flg);
+ dest.writeInt(mUid);
+ if (mPackageName != null) dest.writeString(mPackageName);
+ if (mFeatureId != null) dest.writeString(mFeatureId);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ @DataClass.Generated.Member
+ /* package-private */ OpEventProxyInfo(@NonNull Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ byte flg = in.readByte();
+ int uid = in.readInt();
+ String packageName = (flg & 0x2) == 0 ? null : in.readString();
+ String featureId = (flg & 0x4) == 0 ? null : in.readString();
+
+ this.mUid = uid;
+ com.android.internal.util.AnnotationValidations.validate(
+ IntRange.class, null, mUid,
+ "from", 0);
+ this.mPackageName = packageName;
+ this.mFeatureId = featureId;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public static final @NonNull Parcelable.Creator<OpEventProxyInfo> CREATOR
+ = new Parcelable.Creator<OpEventProxyInfo>() {
+ @Override
+ public OpEventProxyInfo[] newArray(int size) {
+ return new OpEventProxyInfo[size];
+ }
+
+ @Override
+ public OpEventProxyInfo createFromParcel(@NonNull Parcel in) {
+ return new OpEventProxyInfo(in);
+ }
+ };
+
+ @DataClass.Generated(
+ time = 1576194071700L,
+ codegenVersion = "1.0.14",
+ sourceFile = "frameworks/base/core/java/android/app/AppOpsManager.java",
+ inputSignatures = "private final @android.annotation.IntRange(from=0L) int mUid\nprivate final @android.annotation.Nullable java.lang.String mPackageName\nprivate final @android.annotation.Nullable java.lang.String mFeatureId\nclass OpEventProxyInfo extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genHiddenConstructor=true)")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
+ }
+
+ /**
+ * Description of a {@link #noteOp} or {@link #startOp} event
+ *
+ * @hide
+ */
+ @Immutable
+ //@DataClass codegen verifier is broken
+ public static final class NoteOpEvent implements Parcelable {
+ /** Time of noteOp event */
+ public final @IntRange(from = 0) long noteTime;
+ /** The duration of this event (in case this is a startOp event, -1 otherwise). */
+ public final @IntRange(from = -1) long duration;
+ /** Proxy information of the noteOp event */
+ public final @Nullable OpEventProxyInfo proxy;
+
+
+ // Code below generated by codegen v1.0.14.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/app/AppOpsManager.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ /**
+ * Creates a new NoteOpEvent.
+ *
+ * @param noteTime
+ * Time of noteOp event
+ * @param duration
+ * The duration of this event (in case this is a startOp event, -1 otherwise).
+ * @param proxy
+ * Proxy information of the noteOp event
+ */
+ @DataClass.Generated.Member
+ public NoteOpEvent(
+ @IntRange(from = 0) long noteTime,
+ @IntRange(from = -1) long duration,
+ @Nullable OpEventProxyInfo proxy) {
+ this.noteTime = noteTime;
+ com.android.internal.util.AnnotationValidations.validate(
+ IntRange.class, null, noteTime,
+ "from", 0);
+ this.duration = duration;
+ com.android.internal.util.AnnotationValidations.validate(
+ IntRange.class, null, duration,
+ "from", -1);
+ this.proxy = proxy;
+
+ // onConstructed(); // You can define this method to get a callback
}
+ @Override
+ @DataClass.Generated.Member
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ byte flg = 0;
+ if (proxy != null) flg |= 0x4;
+ dest.writeByte(flg);
+ dest.writeLong(noteTime);
+ dest.writeLong(duration);
+ if (proxy != null) dest.writeTypedObject(proxy, flags);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ @DataClass.Generated.Member
+ /* package-private */ NoteOpEvent(@NonNull Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ byte flg = in.readByte();
+ long _noteTime = in.readLong();
+ long _duration = in.readLong();
+ OpEventProxyInfo _proxy = (flg & 0x4) == 0 ? null : (OpEventProxyInfo) in.readTypedObject(
+ OpEventProxyInfo.CREATOR);
+
+ this.noteTime = _noteTime;
+ com.android.internal.util.AnnotationValidations.validate(
+ IntRange.class, null, noteTime,
+ "from", 0);
+ this.duration = _duration;
+ com.android.internal.util.AnnotationValidations.validate(
+ IntRange.class, null, duration,
+ "from", -1);
+ this.proxy = _proxy;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public static final @NonNull Parcelable.Creator<NoteOpEvent> CREATOR
+ = new Parcelable.Creator<NoteOpEvent>() {
+ @Override
+ public NoteOpEvent[] newArray(int size) {
+ return new NoteOpEvent[size];
+ }
+
+ @Override
+ public NoteOpEvent createFromParcel(@NonNull Parcel in) {
+ return new NoteOpEvent(in);
+ }
+ };
+
+ /*
+ @DataClass.Generated(
+ time = 1574809856220L,
+ codegenVersion = "1.0.14",
+ sourceFile = "frameworks/base/core/java/android/app/AppOpsManager.java",
+ inputSignatures = "public final @android.annotation.IntRange(from=0L) long noteTime\npublic final @android.annotation.IntRange(from=-1) long duration\npublic final @android.annotation.Nullable android.app.NoteOpEventProxyInfo proxy\nclass NoteOpEvent extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass")
+ @Deprecated
+ private void __metadata() {}
+ */
+
+
+ //@formatter:on
+ // End of generated code
+
+ }
+
+ /**
+ * Last {@link #noteOp} and {@link #startOp} events performed for a single op and a specific
+ * {@link Context#createFeatureContext(String) feature} for all uidModes and opFlags.
+ *
+ * @hide
+ */
+ @TestApi
+ @SystemApi
+ @Immutable
+ // @DataClass(genHiddenConstructor = true) codegen verifier is broken
+ @DataClass.Suppress({"getAccessEvents", "getRejectEvents", "getOp"})
+ public static final class OpFeatureEntry implements Parcelable {
+ /** The code of the op */
+ private final @IntRange(from = 0, to = _NUM_OP - 1) int mOp;
+ /** Whether the op is running */
+ private final boolean mRunning;
+ /** The access events */
+ @DataClass.ParcelWith(LongSparseArrayParceling.class)
+ private final @Nullable LongSparseArray<NoteOpEvent> mAccessEvents;
+ /** The rejection events */
+ @DataClass.ParcelWith(LongSparseArrayParceling.class)
+ private final @Nullable LongSparseArray<NoteOpEvent> mRejectEvents;
+
/**
+ * Returns all keys for which we have events.
+ *
* @hide
*/
- public long getTime() {
- return getLastAccessTime(OP_FLAGS_ALL);
+ public @NonNull ArraySet<Long> collectKeys() {
+ ArraySet<Long> keys = new ArraySet<>();
+
+ if (mAccessEvents != null) {
+ int numEvents = mAccessEvents.size();
+ for (int i = 0; i < numEvents; i++) {
+ keys.add(mAccessEvents.keyAt(i));
+ }
+ }
+
+ if (mRejectEvents != null) {
+ int numEvents = mRejectEvents.size();
+ for (int i = 0; i < numEvents; i++) {
+ keys.add(mRejectEvents.keyAt(i));
+ }
+ }
+
+ return keys;
}
/**
- * Return the last wall clock time in milliseconds this op was accessed.
+ * Return the last access time.
*
- * @param flags The flags which are any combination of
- * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
- * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
- * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
- * for any flag.
- * @return the last access time in milliseconds since
- * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian).
+ * @param flags The op flags
+ *
+ * @return the last access time (in milliseconds since epoch start (January 1, 1970
+ * 00:00:00.000 GMT - Gregorian)) or {@code -1}
*
* @see #getLastAccessForegroundTime(int)
* @see #getLastAccessBackgroundTime(int)
* @see #getLastAccessTime(int, int, int)
+ * @see OpEntry#getLastAccessTime(int)
*/
public long getLastAccessTime(@OpFlags int flags) {
- return maxForFlagsInStates(mAccessTimes, MAX_PRIORITY_UID_STATE,
- MIN_PRIORITY_UID_STATE, flags);
+ return getLastAccessTime(MAX_PRIORITY_UID_STATE, MIN_PRIORITY_UID_STATE, flags);
}
/**
- * Return the last wall clock time in milliseconds this op was accessed
- * by the app while in the foreground.
+ * Return the last foreground access time.
*
- * @param flags The flags which are any combination of
- * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
- * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
- * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
- * for any flag.
- * @return the last foreground access time in milliseconds since
- * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian).
+ * @param flags The op flags
+ *
+ * @return the last access time (in milliseconds since epoch start (January 1, 1970
+ * 00:00:00.000 GMT - Gregorian)) or {@code -1}
*
- * @see #getLastAccessBackgroundTime(int)
* @see #getLastAccessTime(int)
+ * @see #getLastAccessBackgroundTime(int)
* @see #getLastAccessTime(int, int, int)
+ * @see OpEntry#getLastAccessForegroundTime(int)
*/
public long getLastAccessForegroundTime(@OpFlags int flags) {
- return maxForFlagsInStates(mAccessTimes, MAX_PRIORITY_UID_STATE,
- resolveFirstUnrestrictedUidState(mParent.mOp), flags);
+ return getLastAccessTime(MAX_PRIORITY_UID_STATE, resolveFirstUnrestrictedUidState(mOp),
+ flags);
}
/**
- * Return the last wall clock time in milliseconds this op was accessed
- * by the app while in the background.
+ * Return the last background access time.
*
- * @param flags The flags which are any combination of
- * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
- * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
- * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
- * for any flag.
- * @return the last foreground access time in milliseconds since
- * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian).
+ * @param flags The op flags
+ *
+ * @return the last access time (in milliseconds since epoch start (January 1, 1970
+ * 00:00:00.000 GMT - Gregorian)) or {@code -1}
*
- * @see #getLastAccessForegroundTime(int)
* @see #getLastAccessTime(int)
+ * @see #getLastAccessForegroundTime(int)
* @see #getLastAccessTime(int, int, int)
+ * @see OpEntry#getLastAccessBackgroundTime(int)
*/
public long getLastAccessBackgroundTime(@OpFlags int flags) {
- return maxForFlagsInStates(mAccessTimes, resolveLastRestrictedUidState(mParent.mOp),
- MIN_PRIORITY_UID_STATE, flags);
+ return getLastAccessTime(resolveLastRestrictedUidState(mOp), MIN_PRIORITY_UID_STATE,
+ flags);
}
/**
- * Return the last wall clock time in milliseconds this op was accessed
- * by the app for a given range of UID states.
+ * Return the last access event.
*
- * @param fromUidState The UID state for which to query. Could be one of
- * {@link #UID_STATE_PERSISTENT}, {@link #UID_STATE_TOP},
- * {@link #UID_STATE_FOREGROUND_SERVICE}, {@link #UID_STATE_FOREGROUND},
- * {@link #UID_STATE_BACKGROUND}, {@link #UID_STATE_CACHED}.
- * @param toUidState The UID state for which to query.
- * @param flags The flags which are any combination of
- * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
- * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
- * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
- * for any flag.
+ * @param flags The op flags
+ *
+ * @return the last access event of {@code null}
+ */
+ private @Nullable NoteOpEvent getLastAccessEvent(@UidState int fromUidState,
+ @UidState int toUidState, @OpFlags int flags) {
+ return getLastEvent(mAccessEvents, fromUidState, toUidState, flags);
+ }
+
+ /**
+ * Return the last access time.
+ *
+ * @param fromUidState The lowest UID state for which to query
+ * @param toUidState The highest UID state for which to query (inclusive)
+ * @param flags The op flags
*
- * @return the last foreground access time in milliseconds since
- * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian).
+ * @return the last access time (in milliseconds since epoch start (January 1, 1970
+ * 00:00:00.000 GMT - Gregorian)) or {@code -1}
*
+ * @see #getLastAccessTime(int)
* @see #getLastAccessForegroundTime(int)
* @see #getLastAccessBackgroundTime(int)
- * @see #getLastAccessTime(int)
+ * @see OpEntry#getLastAccessTime(int, int, int)
*/
public long getLastAccessTime(@UidState int fromUidState, @UidState int toUidState,
@OpFlags int flags) {
- return maxForFlagsInStates(mAccessTimes, fromUidState, toUidState, flags);
- }
+ NoteOpEvent lastEvent = getLastAccessEvent(fromUidState, toUidState, flags);
+ if (lastEvent == null) {
+ return -1;
+ }
- /**
- * @hide
- */
- public long getRejectTime() {
- return getLastRejectTime(OP_FLAGS_ALL);
+ return lastEvent.noteTime;
}
/**
- * Return the last wall clock time in milliseconds the app made an attempt
- * to access this op but was rejected.
+ * Return the last rejection time.
*
- * @param flags The flags which are any combination of
- * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
- * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
- * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
- * for any flag.
- * @return the last reject time in milliseconds since
- * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian).
+ * @param flags The op flags
+ *
+ * @return the last rejection time (in milliseconds since epoch start (January 1, 1970
+ * 00:00:00.000 GMT - Gregorian)) or {@code -1}
*
- * @see #getLastRejectBackgroundTime(int)
* @see #getLastRejectForegroundTime(int)
+ * @see #getLastRejectBackgroundTime(int)
* @see #getLastRejectTime(int, int, int)
+ * @see OpEntry#getLastRejectTime(int)
*/
public long getLastRejectTime(@OpFlags int flags) {
- return maxForFlagsInStates(mRejectTimes, MAX_PRIORITY_UID_STATE,
- MIN_PRIORITY_UID_STATE, flags);
+ return getLastRejectTime(MAX_PRIORITY_UID_STATE, MIN_PRIORITY_UID_STATE, flags);
}
/**
- * Return the last wall clock time in milliseconds the app made an attempt
- * to access this op while in the foreground but was rejected.
+ * Return the last foreground rejection time.
*
- * @param flags The flags which are any combination of
- * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
- * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
- * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
- * for any flag.
- * @return the last foreground reject time in milliseconds since
- * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian).
+ * @param flags The op flags
*
+ * @return the last rejection time (in milliseconds since epoch start (January 1, 1970
+ * 00:00:00.000 GMT - Gregorian)) or {@code -1}
+ *
+ * @see #getLastRejectTime(int)
* @see #getLastRejectBackgroundTime(int)
* @see #getLastRejectTime(int, int, int)
- * @see #getLastRejectTime(int)
+ * @see OpEntry#getLastRejectForegroundTime(int)
*/
public long getLastRejectForegroundTime(@OpFlags int flags) {
- return maxForFlagsInStates(mRejectTimes, MAX_PRIORITY_UID_STATE,
- resolveFirstUnrestrictedUidState(mParent.mOp), flags);
+ return getLastRejectTime(MAX_PRIORITY_UID_STATE, resolveFirstUnrestrictedUidState(mOp),
+ flags);
}
/**
- * Return the last wall clock time in milliseconds the app made an attempt
- * to access this op while in the background but was rejected.
+ * Return the last background rejection time.
*
- * @param flags The flags which are any combination of
- * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
- * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
- * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
- * for any flag.
- * @return the last background reject time in milliseconds since
- * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian).
+ * @param flags The op flags
*
+ * @return the last rejection time (in milliseconds since epoch start (January 1, 1970
+ * 00:00:00.000 GMT - Gregorian)) or {@code -1}
+ *
+ * @see #getLastRejectTime(int)
* @see #getLastRejectForegroundTime(int)
* @see #getLastRejectTime(int, int, int)
- * @see #getLastRejectTime(int)
+ * @see OpEntry#getLastRejectBackgroundTime(int)
*/
public long getLastRejectBackgroundTime(@OpFlags int flags) {
- return maxForFlagsInStates(mRejectTimes, resolveLastRestrictedUidState(mParent.mOp),
- MIN_PRIORITY_UID_STATE, flags);
+ return getLastRejectTime(resolveLastRestrictedUidState(mOp), MIN_PRIORITY_UID_STATE,
+ flags);
}
/**
- * Return the last wall clock time state in milliseconds the app made an
- * attempt to access this op for a given range of UID states.
+ * Return the last background rejection event.
*
- * @param fromUidState The UID state from which to query. Could be one of
- * {@link #UID_STATE_PERSISTENT}, {@link #UID_STATE_TOP},
- * {@link #UID_STATE_FOREGROUND_SERVICE}, {@link #UID_STATE_FOREGROUND},
- * {@link #UID_STATE_BACKGROUND}, {@link #UID_STATE_CACHED}.
- * @param toUidState The UID state to which to query.
- * @param flags The flags which are any combination of
- * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
- * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
- * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
- * for any flag.
- * @return the last foreground access time in milliseconds since
- * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian).
+ * @param flags The op flags
*
+ * @return the last rejection time (in milliseconds since epoch start (January 1, 1970
+ * 00:00:00.000 GMT - Gregorian)) or {@code -1}
+ *
+ * @see #getLastRejectTime(int)
* @see #getLastRejectForegroundTime(int)
* @see #getLastRejectBackgroundTime(int)
- * @see #getLastRejectTime(int)
+ * @see OpEntry#getLastRejectTime(int, int, int)
*/
- public long getLastRejectTime(@UidState int fromUidState, @UidState int toUidState,
- @OpFlags int flags) {
- return maxForFlagsInStates(mRejectTimes, fromUidState, toUidState, flags);
+ private @Nullable NoteOpEvent getLastRejectEvent(@UidState int fromUidState,
+ @UidState int toUidState, @OpFlags int flags) {
+ return getLastEvent(mRejectEvents, fromUidState, toUidState, flags);
}
/**
- * @return Whether the operation is running.
+ * Return the last rejection time.
+ *
+ * @param fromUidState The lowest UID state for which to query
+ * @param toUidState The highest UID state for which to query (inclusive)
+ * @param flags The op flags
+ *
+ * @return the last access time (in milliseconds since epoch) or {@code -1}
+ *
+ * @see #getLastRejectTime(int)
+ * @see #getLastRejectForegroundTime(int)
+ * @see #getLastRejectForegroundTime(int)
+ * @see #getLastRejectTime(int, int, int)
+ * @see OpEntry#getLastRejectTime(int, int, int)
*/
- public boolean isRunning() {
- return mRunning;
+ public long getLastRejectTime(@UidState int fromUidState, @UidState int toUidState,
+ @OpFlags int flags) {
+ NoteOpEvent lastEvent = getLastRejectEvent(fromUidState, toUidState, flags);
+ if (lastEvent == null) {
+ return -1;
+ }
+
+ return lastEvent.noteTime;
}
/**
- * @return The duration of the operation in milliseconds. The duration is in wall time.
+ * Return the duration in milliseconds of the last the access.
+ *
+ * @param flags The op flags
+ *
+ * @return the duration in milliseconds or {@code -1}
+ *
+ * @see #getLastForegroundDuration(int)
+ * @see #getLastBackgroundDuration(int)
+ * @see #getLastDuration(int, int, int)
+ * @see OpEntry#getLastDuration(int)
*/
- public long getDuration() {
- return getLastDuration(MAX_PRIORITY_UID_STATE, MIN_PRIORITY_UID_STATE, OP_FLAGS_ALL);
+ public long getLastDuration(@OpFlags int flags) {
+ return getLastDuration(MAX_PRIORITY_UID_STATE, MIN_PRIORITY_UID_STATE, flags);
}
/**
- * Return the duration in milliseconds the app accessed this op while
- * in the foreground. The duration is in wall time.
+ * Return the duration in milliseconds of the last foreground access.
*
- * @param flags The flags which are any combination of
- * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
- * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
- * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
- * for any flag.
- * @return the foreground access duration in milliseconds.
+ * @param flags The op flags
+ *
+ * @return the duration in milliseconds or {@code -1}
*
+ * @see #getLastDuration(int)
* @see #getLastBackgroundDuration(int)
* @see #getLastDuration(int, int, int)
+ * @see OpEntry#getLastForegroundDuration(int)
*/
public long getLastForegroundDuration(@OpFlags int flags) {
- return sumForFlagsInStates(mDurations, MAX_PRIORITY_UID_STATE,
- resolveFirstUnrestrictedUidState(mParent.mOp), flags);
+ return getLastDuration(MAX_PRIORITY_UID_STATE, resolveFirstUnrestrictedUidState(mOp),
+ flags);
}
/**
- * Return the duration in milliseconds the app accessed this op while
- * in the background. The duration is in wall time.
+ * Return the duration in milliseconds of the last background access.
*
- * @param flags The flags which are any combination of
- * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
- * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
- * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
- * for any flag.
- * @return the background access duration in milliseconds.
+ * @param flags The op flags
+ *
+ * @return the duration in milliseconds or {@code -1}
*
+ * @see #getLastDuration(int)
* @see #getLastForegroundDuration(int)
* @see #getLastDuration(int, int, int)
+ * @see OpEntry#getLastBackgroundDuration(int)
*/
public long getLastBackgroundDuration(@OpFlags int flags) {
- return sumForFlagsInStates(mDurations, resolveLastRestrictedUidState(mParent.mOp),
- MIN_PRIORITY_UID_STATE, flags);
+ return getLastDuration(resolveLastRestrictedUidState(mOp), MIN_PRIORITY_UID_STATE,
+ flags);
}
/**
- * Return the duration in milliseconds the app accessed this op for
- * a given range of UID states. The duration is in wall time.
+ * Return the duration in milliseconds of the last access.
*
- * @param fromUidState The UID state for which to query. Could be one of
- * {@link #UID_STATE_PERSISTENT}, {@link #UID_STATE_TOP},
- * {@link #UID_STATE_FOREGROUND_SERVICE}, {@link #UID_STATE_FOREGROUND},
- * {@link #UID_STATE_BACKGROUND}, {@link #UID_STATE_CACHED}.
- * @param toUidState The UID state for which to query.
- * @param flags The flags which are any combination of
- * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
- * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
- * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
- * for any flag.
- * @return the access duration in milliseconds.
+ * @param fromUidState The lowest UID state for which to query
+ * @param toUidState The highest UID state for which to query (inclusive)
+ * @param flags The op flags
+ *
+ * @return the duration in milliseconds or {@code -1}
+ *
+ * @see #getLastDuration(int)
+ * @see #getLastForegroundDuration(int)
+ * @see #getLastBackgroundDuration(int)
+ * @see #getLastDuration(int, int, int)
+ * @see OpEntry#getLastDuration(int, int, int)
*/
public long getLastDuration(@UidState int fromUidState, @UidState int toUidState,
@OpFlags int flags) {
- return sumForFlagsInStates(mDurations, fromUidState, toUidState, flags);
+ NoteOpEvent lastEvent = getLastAccessEvent(fromUidState, toUidState, flags);;
+ if (lastEvent == null) {
+ return -1;
+ }
+
+ return lastEvent.duration;
}
/**
- * Gets the UID of the app that performed the op on behalf of this app and
- * as a result blamed the op on this app or {@link Process#INVALID_UID} if
- * there is no proxy.
+ * Gets the proxy info of the app that performed the last access on behalf of this feature
+ * and as a result blamed the op on this app.
+ *
+ * @param flags The op flags
*
- * @return The proxy UID.
+ * @return The proxy name or {@code null}
+ *
+ * @see #getLastForegroundProxyInfo(int)
+ * @see #getLastBackgroundProxyInfo(int)
+ * @see #getLastProxyInfo(int, int, int)
+ * @see OpEntry#getLastProxyInfo(int)
*/
- public int getProxyUid() {
- return (int) findFirstNonNegativeForFlagsInStates(mProxyUids,
- MAX_PRIORITY_UID_STATE, MIN_PRIORITY_UID_STATE, OP_FLAGS_ALL);
+ public @Nullable OpEventProxyInfo getLastProxyInfo(@OpFlags int flags) {
+ return getLastProxyInfo(MAX_PRIORITY_UID_STATE, MIN_PRIORITY_UID_STATE, flags);
}
/**
- * Gets the UID of the app that performed the op on behalf of this app and
- * as a result blamed the op on this app or {@link Process#INVALID_UID} if
- * there is no proxy.
+ * Gets the proxy info of the app that performed the last foreground access on behalf of
+ * this feature and as a result blamed the op on this app.
*
- * @param uidState The UID state for which to query. Could be one of
- * {@link #UID_STATE_PERSISTENT}, {@link #UID_STATE_TOP},
- * {@link #UID_STATE_FOREGROUND_SERVICE}, {@link #UID_STATE_FOREGROUND},
- * {@link #UID_STATE_BACKGROUND}, {@link #UID_STATE_CACHED}.
- * @param flags The flags which are any combination of
- * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
- * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
- * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
- * for any flag.
+ * @param flags The op flags
+ *
+ * @return The proxy name or {@code null}
*
- * @return The proxy UID.
+ * @see #getLastProxyInfo(int)
+ * @see #getLastBackgroundProxyInfo(int)
+ * @see #getLastProxyInfo(int, int, int)
+ * @see OpEntry#getLastForegroundProxyInfo(int)
*/
- public int getProxyUid(@UidState int uidState, @OpFlags int flags) {
- return (int) findFirstNonNegativeForFlagsInStates(mProxyUids,
- uidState, uidState, flags);
+ public @Nullable OpEventProxyInfo getLastForegroundProxyInfo(@OpFlags int flags) {
+ return getLastProxyInfo(MAX_PRIORITY_UID_STATE, resolveFirstUnrestrictedUidState(mOp),
+ flags);
}
/**
- * Gets the package name of the app that performed the op on behalf of this
- * app and as a result blamed the op on this app or {@code null}
- * if there is no proxy.
+ * Gets the proxy info of the app that performed the last background access on behalf of
+ * this feature and as a result blamed the op on this app.
+ *
+ * @param flags The op flags
+ *
+ * @return The proxy name or {@code null}
*
- * @return The proxy package name.
+ * @see #getLastProxyInfo(int)
+ * @see #getLastForegroundProxyInfo(int)
+ * @see #getLastProxyInfo(int, int, int)
+ * @see OpEntry#getLastBackgroundProxyInfo(int)
*/
- public @Nullable String getProxyPackageName() {
- return findFirstNonNullForFlagsInStates(mProxyPackageNames, MAX_PRIORITY_UID_STATE,
- MIN_PRIORITY_UID_STATE, OP_FLAGS_ALL);
+ public @Nullable OpEventProxyInfo getLastBackgroundProxyInfo(@OpFlags int flags) {
+ return getLastProxyInfo(resolveLastRestrictedUidState(mOp), MIN_PRIORITY_UID_STATE,
+ flags);
}
/**
- * Gets the package name of the app that performed the op on behalf of this
- * app and as a result blamed the op on this app for a UID state or
- * {@code null} if there is no proxy.
+ * Gets the proxy info of the app that performed the last access on behalf of this feature
+ * and as a result blamed the op on this app.
*
- * @param uidState The UID state for which to query. Could be one of
- * {@link #UID_STATE_PERSISTENT}, {@link #UID_STATE_TOP},
- * {@link #UID_STATE_FOREGROUND_SERVICE}, {@link #UID_STATE_FOREGROUND},
- * {@link #UID_STATE_BACKGROUND}, {@link #UID_STATE_CACHED}.
- * @param flags The flags which are any combination of
- * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
- * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
- * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
- * for any flag.
- * @return The feature id.
+ * @param fromUidState The lowest UID state for which to query
+ * @param toUidState The highest UID state for which to query (inclusive)
+ * @param flags The op flags
+ *
+ * @return The proxy name or {@code null}
+ *
+ * @see #getLastProxyInfo(int)
+ * @see #getLastForegroundProxyInfo(int)
+ * @see #getLastBackgroundProxyInfo(int)
+ * @see OpEntry#getLastProxyInfo(int, int, int)
*/
- public @Nullable String getProxyPackageName(@UidState int uidState, @OpFlags int flags) {
- return findFirstNonNullForFlagsInStates(mProxyPackageNames, uidState, uidState, flags);
+ public @Nullable OpEventProxyInfo getLastProxyInfo(@UidState int fromUidState,
+ @UidState int toUidState, @OpFlags int flags) {
+ NoteOpEvent lastEvent = getLastAccessEvent(fromUidState, toUidState, flags);
+ if (lastEvent == null) {
+ return null;
+ }
+
+ return lastEvent.proxy;
}
- /**
- * Gets the feature of the app that performed the op on behalf of this
- * app and as a result blamed the op on this app or {@code null}
- * if there is no proxy.
- *
- * @return The proxy package name.
- */
- public @Nullable String getProxyFeatureId() {
- return findFirstNonNullForFlagsInStates(mProxyFeatureIds, MAX_PRIORITY_UID_STATE,
- MIN_PRIORITY_UID_STATE, OP_FLAGS_ALL);
+ private static class LongSparseArrayParceling implements
+ Parcelling<LongSparseArray<NoteOpEvent>> {
+ @Override
+ public void parcel(@Nullable LongSparseArray<NoteOpEvent> array, @NonNull Parcel dest,
+ int parcelFlags) {
+ if (array == null) {
+ dest.writeInt(-1);
+ return;
+ }
+
+ int numEntries = array.size();
+ dest.writeInt(numEntries);
+
+ for (int i = 0; i < numEntries; i++) {
+ dest.writeLong(array.keyAt(i));
+ dest.writeParcelable(array.valueAt(i), parcelFlags);
+ }
+ }
+
+ @Override
+ public @Nullable LongSparseArray<NoteOpEvent> unparcel(@NonNull Parcel source) {
+ int numEntries = source.readInt();
+ if (numEntries == -1) {
+ return null;
+ }
+
+ LongSparseArray<NoteOpEvent> array = new LongSparseArray<>(numEntries);
+
+ for (int i = 0; i < numEntries; i++) {
+ array.put(source.readLong(), source.readParcelable(null));
+ }
+
+ return array;
+ }
}
+
+
+ // Code below generated by codegen v1.0.14.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/app/AppOpsManager.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
/**
- * Gets the feature of the app that performed the op on behalf of this
- * app and as a result blamed the op on this app for a UID state or
- * {@code null} if there is no proxy.
+ * Creates a new OpFeatureEntry.
*
- * @param uidState The UID state for which to query. Could be one of
- * {@link #UID_STATE_PERSISTENT}, {@link #UID_STATE_TOP},
- * {@link #UID_STATE_FOREGROUND_SERVICE}, {@link #UID_STATE_FOREGROUND},
- * {@link #UID_STATE_BACKGROUND}, {@link #UID_STATE_CACHED}.
- * @param flags The flags which are any combination of
- * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
- * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
- * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
- * for any flag.
- * @return The feature id.
+ * @param op
+ * The code of the op
+ * @param running
+ * Whether the op is running
+ * @param accessEvents
+ * The access events
+ * @param rejectEvents
+ * The rejection events
+ * @hide
*/
- public @Nullable String getProxyFeatureId(@UidState int uidState, @OpFlags int flags) {
- return findFirstNonNullForFlagsInStates(mProxyFeatureIds, uidState, uidState, flags);
+ @DataClass.Generated.Member
+ public OpFeatureEntry(
+ @IntRange(from = 0, to = _NUM_OP - 1) int op,
+ boolean running,
+ @Nullable LongSparseArray<NoteOpEvent> accessEvents,
+ @Nullable LongSparseArray<NoteOpEvent> rejectEvents) {
+ this.mOp = op;
+ com.android.internal.util.AnnotationValidations.validate(
+ IntRange.class, null, mOp,
+ "from", 0,
+ "to", _NUM_OP - 1);
+ this.mRunning = running;
+ this.mAccessEvents = accessEvents;
+ this.mRejectEvents = rejectEvents;
+
+ // onConstructed(); // You can define this method to get a callback
}
/**
- * @hide
+ * Whether the op is running
*/
- public static class Builder {
- private final boolean mRunning;
-
- private final @Nullable LongSparseLongArray mAccessTimes;
- private final @Nullable LongSparseLongArray mRejectTimes;
- private final @Nullable LongSparseLongArray mDurations;
- private final @Nullable LongSparseLongArray mProxyUids;
- private final @Nullable LongSparseArray<String> mProxyPackageNames;
- private final @Nullable LongSparseArray<String> mProxyFeatureIds;
- private @NonNull OpEntry mParent;
-
- public Builder(boolean running, @Nullable LongSparseLongArray accessTimes,
- @Nullable LongSparseLongArray rejectTimes,
- @Nullable LongSparseLongArray durations,
- @Nullable LongSparseLongArray proxyUids,
- @Nullable LongSparseArray<String> proxyPackageNames,
- @Nullable LongSparseArray<String> proxyFeatureIds) {
- mRunning = running;
- mAccessTimes = accessTimes;
- mRejectTimes = rejectTimes;
- mDurations = durations;
- mProxyUids = proxyUids;
- mProxyPackageNames = proxyPackageNames;
- mProxyFeatureIds = proxyFeatureIds;
- }
-
- public Builder setParent(@NonNull OpEntry parent) {
- mParent = parent;
+ @DataClass.Generated.Member
+ public boolean isRunning() {
+ return mRunning;
+ }
- return this;
+ @DataClass.Generated.Member
+ static Parcelling<LongSparseArray<NoteOpEvent>> sParcellingForAccessEvents =
+ Parcelling.Cache.get(
+ LongSparseArrayParceling.class);
+ static {
+ if (sParcellingForAccessEvents == null) {
+ sParcellingForAccessEvents = Parcelling.Cache.put(
+ new LongSparseArrayParceling());
}
+ }
- /**
- * Create OpFeatureEntry from builder
- */
- public OpFeatureEntry build() {
- Preconditions.checkNotNull(mParent);
-
- return new OpFeatureEntry(mParent, mRunning, mAccessTimes, mRejectTimes,
- mDurations, mProxyUids, mProxyPackageNames, mProxyFeatureIds);
+ @DataClass.Generated.Member
+ static Parcelling<LongSparseArray<NoteOpEvent>> sParcellingForRejectEvents =
+ Parcelling.Cache.get(
+ LongSparseArrayParceling.class);
+ static {
+ if (sParcellingForRejectEvents == null) {
+ sParcellingForRejectEvents = Parcelling.Cache.put(
+ new LongSparseArrayParceling());
}
}
- /**
- * @hide
- */
+ @Override
+ @DataClass.Generated.Member
public void writeToParcel(@NonNull Parcel dest, int flags) {
- LongSparseLongArray.Parcelling longSparseLongArrayParcelling =
- LongSparseLongArray.Parcelling.Cache.getOrCreate(
- LongSparseLongArray.Parcelling.class);
- LongSparseArray.StringParcelling longSparseStringArrayParcelling =
- LongSparseArray.StringParcelling.Cache.getOrCreate(
- LongSparseArray.StringParcelling.class);
-
- dest.writeBoolean(mRunning);
- longSparseLongArrayParcelling.parcel(mAccessTimes, dest, flags);
- longSparseLongArrayParcelling.parcel(mRejectTimes, dest, flags);
- longSparseLongArrayParcelling.parcel(mDurations, dest, flags);
- longSparseLongArrayParcelling.parcel(mProxyUids, dest, flags);
- longSparseStringArrayParcelling.parcel(mProxyPackageNames, dest, flags);
- longSparseStringArrayParcelling.parcel(mProxyFeatureIds, dest, flags);
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ byte flg = 0;
+ if (mRunning) flg |= 0x2;
+ if (mAccessEvents != null) flg |= 0x4;
+ if (mRejectEvents != null) flg |= 0x8;
+ dest.writeByte(flg);
+ dest.writeInt(mOp);
+ sParcellingForAccessEvents.parcel(mAccessEvents, dest, flags);
+ sParcellingForRejectEvents.parcel(mRejectEvents, dest, flags);
}
- /**
- * @hide
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ @DataClass.Generated.Member
+ /* package-private */ OpFeatureEntry(@NonNull Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ byte flg = in.readByte();
+ boolean running = (flg & 0x2) != 0;
+ int op = in.readInt();
+ LongSparseArray<NoteOpEvent> accessEvents = sParcellingForAccessEvents.unparcel(in);
+ LongSparseArray<NoteOpEvent> rejectEvents = sParcellingForRejectEvents.unparcel(in);
+
+ this.mOp = op;
+ com.android.internal.util.AnnotationValidations.validate(
+ IntRange.class, null, mOp,
+ "from", 0,
+ "to", _NUM_OP - 1);
+ this.mRunning = running;
+ this.mAccessEvents = accessEvents;
+ this.mRejectEvents = rejectEvents;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public static final @NonNull Parcelable.Creator<OpFeatureEntry> CREATOR
+ = new Parcelable.Creator<OpFeatureEntry>() {
+ @Override
+ public OpFeatureEntry[] newArray(int size) {
+ return new OpFeatureEntry[size];
+ }
+
+ @Override
+ public OpFeatureEntry createFromParcel(@NonNull Parcel in) {
+ return new OpFeatureEntry(in);
+ }
+ };
+
+ /*
+ @DataClass.Generated(
+ time = 1574809856239L,
+ codegenVersion = "1.0.14",
+ sourceFile = "frameworks/base/core/java/android/app/AppOpsManager.java",
+ inputSignatures = "private final @android.annotation.IntRange(from=0L, to=_NUM_OP - 1) int mOp\nprivate final boolean mRunning\nprivate final @com.android.internal.util.DataClass.ParcelWith(android.app.OpFeatureEntry.LongSparseArrayParceling.class) @android.annotation.Nullable android.util.LongSparseArray<android.app.NoteOpEvent> mAccessEvents\nprivate final @com.android.internal.util.DataClass.ParcelWith(android.app.OpFeatureEntry.LongSparseArrayParceling.class) @android.annotation.Nullable android.util.LongSparseArray<android.app.NoteOpEvent> mRejectEvents\npublic @android.annotation.NonNull android.util.ArraySet<java.lang.Long> collectKeys()\npublic @android.app.UidState int getLastAccessUidState(int)\npublic @android.app.UidState int getLastForegroundAccessUidState(int)\npublic @android.app.UidState int getLastBackgroundAccessUidState(int)\npublic @android.app.UidState int getLastRejectUidState(int)\npublic @android.app.UidState int getLastForegroundRejectUidState(int)\npublic @android.app.UidState int getLastBackgroundRejectUidState(int)\npublic long getAccessTime(int,int)\npublic long getRejectTime(int,int)\npublic long getDuration(int,int)\npublic int getProxyUid(int,int)\npublic @android.annotation.Nullable java.lang.String getProxyPackageName(int,int)\npublic @android.annotation.Nullable java.lang.String getProxyFeatureId(int,int)\nclass OpFeatureEntry extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genHiddenConstructor=true)")
+ @Deprecated
+ private void __metadata() {}
*/
- public static OpFeatureEntry.Builder createFromParcel(@NonNull Parcel source) {
- LongSparseLongArray.Parcelling longSparseLongArrayParcelling =
- LongSparseLongArray.Parcelling.Cache.getOrCreate(
- LongSparseLongArray.Parcelling.class);
- LongSparseArray.StringParcelling longSparseStringArrayParcelling =
- LongSparseArray.StringParcelling.Cache.getOrCreate(
- LongSparseArray.StringParcelling.class);
- return new OpFeatureEntry.Builder(source.readBoolean(),
- longSparseLongArrayParcelling.unparcel(source),
- longSparseLongArrayParcelling.unparcel(source),
- longSparseLongArrayParcelling.unparcel(source),
- longSparseLongArrayParcelling.unparcel(source),
- longSparseStringArrayParcelling.unparcel(source),
- longSparseStringArrayParcelling.unparcel(source));
- }
+
+ //@formatter:on
+ // End of generated code
+
}
/**
- * Class holding the information about one unique operation of an application.
+ * Last {@link #noteOp} and {@link #startOp} events performed for a single op for all uidModes
+ * and opFlags.
+ *
* @hide
*/
@TestApi
@Immutable
@SystemApi
+ // @DataClass(genHiddenConstructor = true) codegen verifier is broken
public static final class OpEntry implements Parcelable {
+ /** The code of the op */
private final @IntRange(from = 0, to = _NUM_OP - 1) int mOp;
+ /** The mode of the op */
private final @Mode int mMode;
- private final @NonNull ArrayMap<String, OpFeatureEntry> mFeatures;
-
- /**
- * @hide
- */
- public OpEntry(@IntRange(from = 0, to = _NUM_OP - 1) int op, @Mode int mode,
- @NonNull Pair<String, OpFeatureEntry.Builder>[] featureBuilders) {
- mOp = Preconditions.checkArgumentInRange(op, 0, _NUM_OP - 1, "op");
- mMode = Preconditions.checkArgumentInRange(mode, 0, MODE_FOREGROUND, "mode");
-
- mFeatures = new ArrayMap<>(featureBuilders.length);
- for (Pair<String, OpFeatureEntry.Builder> feature : featureBuilders) {
- mFeatures.put(feature.first, feature.second.setParent(this).build());
- }
- }
-
- /**
- * @return The mapping from the feature ids to the feature state
- */
- public @NonNull Map<String, OpFeatureEntry> getFeatures() {
- return mFeatures;
- }
+ /** The features that have been used when checking the op */
+ private final @NonNull Map<String, OpFeatureEntry> mFeatures;
/**
* @hide
@@ -2868,16 +3225,9 @@ public class AppOpsManager {
}
/**
- * @return this entry's current mode, such as {@link #MODE_ALLOWED}.
- */
- public @Mode int getMode() {
- return mMode;
- }
-
- /**
- * @deprecated Use {@link OpEntry#getLastAccessTime(int)} instead
- *
* @hide
+ *
+ * @deprecated Use {@link #getLastAccessTime(int)} instead
*/
@Deprecated
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "{@code "
@@ -2886,130 +3236,112 @@ public class AppOpsManager {
return getLastAccessTime(OP_FLAGS_ALL);
}
- private long getMaxOfFeatures(@NonNull ToLongFunction<OpFeatureEntry> timeGetter) {
- long max = 0;
-
- int numFeatures = mFeatures.size();
- for (int i = 0; i < numFeatures; i++) {
- max = Math.max(max, timeGetter.applyAsLong(mFeatures.valueAt(i)));
- }
-
- return max;
- }
-
- private long getSumOfFeatures(@NonNull ToLongFunction<OpFeatureEntry> getter) {
- long sum = 0;
-
- int numFeatures = mFeatures.size();
- for (int i = 0; i < numFeatures; i++) {
- sum += getter.applyAsLong(mFeatures.valueAt(i));
- }
-
- return sum;
- }
-
/**
- * Return the last wall clock time in milliseconds this op was accessed
- * by the app for a given range of UID states.
+ * Return the last access time.
*
- * @param fromUidState The UID state for which to query. Could be one of
- * {@link #UID_STATE_PERSISTENT}, {@link #UID_STATE_TOP},
- * {@link #UID_STATE_FOREGROUND_SERVICE}, {@link #UID_STATE_FOREGROUND},
- * {@link #UID_STATE_BACKGROUND}, {@link #UID_STATE_CACHED}.
- * @param toUidState The UID state for which to query.
- * @param flags The flags which are any combination of
- * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
- * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
- * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
- * for any flag.
+ * @param flags The op flags
*
- * @return the last foreground access time in milliseconds since
- * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian).
+ * @return the last access time (in milliseconds since epoch start (January 1, 1970
+ * 00:00:00.000 GMT - Gregorian)) or {@code -1}
*
* @see #getLastAccessForegroundTime(int)
* @see #getLastAccessBackgroundTime(int)
- * @see #getLastAccessTime(int)
+ * @see #getLastAccessTime(int, int, int)
+ * @see OpFeatureEntry#getLastAccessTime(int)
*/
public long getLastAccessTime(@OpFlags int flags) {
- return getMaxOfFeatures(
- (featureEntry -> featureEntry.getLastAccessTime(flags)));
+ return getLastAccessTime(MAX_PRIORITY_UID_STATE, MIN_PRIORITY_UID_STATE, flags);
}
/**
- * Return the last wall clock time in milliseconds this op was accessed
- * by the app while in the foreground.
+ * Return the last foreground access time.
*
- * @param flags The flags which are any combination of
- * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
- * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
- * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
- * for any flag.
- * @return the last foreground access time in milliseconds since
- * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian).
+ * @param flags The op flags
+ *
+ * @return the last access time (in milliseconds since epoch start (January 1, 1970
+ * 00:00:00.000 GMT - Gregorian)) or {@code -1}
*
- * @see #getLastAccessBackgroundTime(int)
* @see #getLastAccessTime(int)
+ * @see #getLastAccessBackgroundTime(int)
* @see #getLastAccessTime(int, int, int)
+ * @see OpFeatureEntry#getLastAccessForegroundTime(int)
*/
public long getLastAccessForegroundTime(@OpFlags int flags) {
- return getMaxOfFeatures(
- (featureEntry -> featureEntry.getLastAccessForegroundTime(flags)));
+ return getLastAccessTime(MAX_PRIORITY_UID_STATE, resolveFirstUnrestrictedUidState(mOp),
+ flags);
}
/**
- * Return the last wall clock time in milliseconds this op was accessed
- * by the app while in the background.
+ * Return the last background access time.
*
- * @param flags The flags which are any combination of
- * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
- * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
- * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
- * for any flag.
- * @return the last foreground access time in milliseconds since
- * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian).
+ * @param flags The op flags
+ *
+ * @return the last access time (in milliseconds since epoch start (January 1, 1970
+ * 00:00:00.000 GMT - Gregorian)) or {@code -1}
*
- * @see #getLastAccessForegroundTime(int)
* @see #getLastAccessTime(int)
+ * @see #getLastAccessForegroundTime(int)
* @see #getLastAccessTime(int, int, int)
+ * @see OpFeatureEntry#getLastAccessBackgroundTime(int)
*/
public long getLastAccessBackgroundTime(@OpFlags int flags) {
- return getMaxOfFeatures(
- (featureEntry -> featureEntry.getLastAccessBackgroundTime(flags)));
+ return getLastAccessTime(resolveLastRestrictedUidState(mOp), MIN_PRIORITY_UID_STATE,
+ flags);
}
/**
- * Return the last wall clock time in milliseconds this op was accessed
- * by the app for a given range of UID states.
+ * Return the last access event.
*
- * @param fromUidState The UID state for which to query. Could be one of
- * {@link #UID_STATE_PERSISTENT}, {@link #UID_STATE_TOP},
- * {@link #UID_STATE_FOREGROUND_SERVICE}, {@link #UID_STATE_FOREGROUND},
- * {@link #UID_STATE_BACKGROUND}, {@link #UID_STATE_CACHED}.
- * @param toUidState The UID state for which to query.
- * @param flags The flags which are any combination of
- * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
- * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
- * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
- * for any flag.
+ * @param flags The op flags
+ *
+ * @return the last access event of {@code null}
+ */
+ private @Nullable NoteOpEvent getLastAccessEvent(@UidState int fromUidState,
+ @UidState int toUidState, @OpFlags int flags) {
+ NoteOpEvent lastAccessEvent = null;
+ for (OpFeatureEntry featureEntry : mFeatures.values()) {
+ NoteOpEvent lastFeatureAccessEvent = featureEntry.getLastAccessEvent(fromUidState,
+ toUidState, flags);
+
+ if (lastAccessEvent == null || (lastFeatureAccessEvent != null
+ && lastFeatureAccessEvent.noteTime > lastAccessEvent.noteTime)) {
+ lastAccessEvent = lastFeatureAccessEvent;
+ }
+ }
+
+ return lastAccessEvent;
+ }
+
+ /**
+ * Return the last access time.
+ *
+ * @param fromUidState the lowest uid state to query
+ * @param toUidState the highest uid state to query (inclusive)
+ * @param flags The op flags
*
- * @return the last foreground access time in milliseconds since
- * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian).
+ * @return the last access time (in milliseconds since epoch start (January 1, 1970
+ * 00:00:00.000 GMT - Gregorian)) or {@code -1}
*
+ * @see #getLastAccessTime(int)
* @see #getLastAccessForegroundTime(int)
* @see #getLastAccessBackgroundTime(int)
- * @see #getLastAccessTime(int)
+ * @see OpFeatureEntry#getLastAccessTime(int, int, int)
*/
public long getLastAccessTime(@UidState int fromUidState, @UidState int toUidState,
@OpFlags int flags) {
- return getMaxOfFeatures(
- (featureEntry -> featureEntry.getLastAccessTime(fromUidState,
- toUidState, flags)));
+ NoteOpEvent lastEvent = getLastAccessEvent(fromUidState, toUidState, flags);;
+
+ if (lastEvent == null) {
+ return -1;
+ }
+
+ return lastEvent.noteTime;
}
/**
- * @deprecated Use {@link OpEntry#getLastRejectTime(int)} instead
- *
* @hide
+ *
+ * @deprecated Use {@link #getLastRejectTime(int)} instead
*/
@Deprecated
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "{@code "
@@ -3019,107 +3351,113 @@ public class AppOpsManager {
}
/**
- * Return the last wall clock time in milliseconds the app made an attempt
- * to access this op but was rejected.
+ * Return the last rejection time.
*
- * @param flags The flags which are any combination of
- * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
- * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
- * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
- * for any flag.
- * @return the last reject time in milliseconds since
- * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian).
+ * @param flags The op flags
+ *
+ * @return the last rejection time (in milliseconds since epoch start (January 1, 1970
+ * 00:00:00.000 GMT - Gregorian)) or {@code -1}
*
- * @see #getLastRejectBackgroundTime(int)
* @see #getLastRejectForegroundTime(int)
+ * @see #getLastRejectBackgroundTime(int)
* @see #getLastRejectTime(int, int, int)
+ * @see OpFeatureEntry#getLastRejectTime(int)
*/
public long getLastRejectTime(@OpFlags int flags) {
- return getMaxOfFeatures(
- (featureEntry -> featureEntry.getLastRejectTime(flags)));
+ return getLastRejectTime(MAX_PRIORITY_UID_STATE, MIN_PRIORITY_UID_STATE, flags);
}
/**
- * Return the last wall clock time in milliseconds the app made an attempt
- * to access this op while in the foreground but was rejected.
+ * Return the last foreground rejection time.
*
- * @param flags The flags which are any combination of
- * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
- * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
- * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
- * for any flag.
- * @return the last foreground reject time in milliseconds since
- * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian).
+ * @param flags The op flags
+ *
+ * @return the last rejection time (in milliseconds since epoch start (January 1, 1970
+ * 00:00:00.000 GMT - Gregorian)) or {@code -1}
*
+ * @see #getLastRejectTime(int)
* @see #getLastRejectBackgroundTime(int)
* @see #getLastRejectTime(int, int, int)
- * @see #getLastRejectTime(int)
+ * @see OpFeatureEntry#getLastRejectForegroundTime(int)
*/
public long getLastRejectForegroundTime(@OpFlags int flags) {
- return getMaxOfFeatures(
- (featureEntry -> featureEntry.getLastRejectForegroundTime(flags)));
+ return getLastRejectTime(MAX_PRIORITY_UID_STATE, resolveFirstUnrestrictedUidState(mOp),
+ flags);
}
/**
- * Return the last wall clock time in milliseconds the app made an attempt
- * to access this op while in the background but was rejected.
+ * Return the last background rejection time.
*
- * @param flags The flags which are any combination of
- * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
- * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
- * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
- * for any flag.
- * @return the last background reject time in milliseconds since
- * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian).
+ * @param flags The op flags
*
+ * @return the last rejection time (in milliseconds since epoch start (January 1, 1970
+ * 00:00:00.000 GMT - Gregorian)) or {@code -1}
+ *
+ * @see #getLastRejectTime(int)
* @see #getLastRejectForegroundTime(int)
* @see #getLastRejectTime(int, int, int)
- * @see #getLastRejectTime(int)
+ * @see OpFeatureEntry#getLastRejectBackgroundTime(int)
*/
public long getLastRejectBackgroundTime(@OpFlags int flags) {
- return getMaxOfFeatures(
- (featureEntry -> featureEntry.getLastRejectBackgroundTime(flags)));
+ return getLastRejectTime(resolveLastRestrictedUidState(mOp), MIN_PRIORITY_UID_STATE,
+ flags);
}
/**
- * Return the last wall clock time state in milliseconds the app made an
- * attempt to access this op for a given range of UID states.
+ * Return the last rejection event.
*
- * @param fromUidState The UID state from which to query. Could be one of
- * {@link #UID_STATE_PERSISTENT}, {@link #UID_STATE_TOP},
- * {@link #UID_STATE_FOREGROUND_SERVICE}, {@link #UID_STATE_FOREGROUND},
- * {@link #UID_STATE_BACKGROUND}, {@link #UID_STATE_CACHED}.
- * @param toUidState The UID state to which to query.
- * @param flags The flags which are any combination of
- * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
- * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
- * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
- * for any flag.
- * @return the last foreground access time in milliseconds since
- * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian).
+ * @param flags The op flags
*
+ * @return the last reject event of {@code null}
+ */
+ private @Nullable NoteOpEvent getLastRejectEvent(@UidState int fromUidState,
+ @UidState int toUidState, @OpFlags int flags) {
+ NoteOpEvent lastAccessEvent = null;
+ for (OpFeatureEntry featureEntry : mFeatures.values()) {
+ NoteOpEvent lastFeatureAccessEvent = featureEntry.getLastRejectEvent(fromUidState,
+ toUidState, flags);
+
+ if (lastAccessEvent == null || (lastFeatureAccessEvent != null
+ && lastFeatureAccessEvent.noteTime > lastAccessEvent.noteTime)) {
+ lastAccessEvent = lastFeatureAccessEvent;
+ }
+ }
+
+ return lastAccessEvent;
+ }
+
+ /**
+ * Return the last rejection time.
+ *
+ * @param fromUidState the lowest uid state to query
+ * @param toUidState the highest uid state to query (inclusive)
+ * @param flags The op flags
+ *
+ * @return the last rejection time (in milliseconds since epoch start (January 1, 1970
+ * 00:00:00.000 GMT - Gregorian)) or {@code -1}
+ *
+ * @see #getLastRejectTime(int)
* @see #getLastRejectForegroundTime(int)
* @see #getLastRejectBackgroundTime(int)
- * @see #getLastRejectTime(int)
+ * @see #getLastRejectTime(int, int, int)
+ * @see OpFeatureEntry#getLastRejectTime(int, int, int)
*/
public long getLastRejectTime(@UidState int fromUidState, @UidState int toUidState,
@OpFlags int flags) {
- return getMaxOfFeatures(
- (featureEntry -> featureEntry.getLastRejectTime(fromUidState,
- toUidState, flags)));
+ NoteOpEvent lastEvent = getLastRejectEvent(fromUidState, toUidState, flags);
+ if (lastEvent == null) {
+ return -1;
+ }
+
+ return lastEvent.noteTime;
}
/**
* @return Whether the operation is running.
*/
public boolean isRunning() {
- int numFeatures = mFeatures.size();
- if (mFeatures.isEmpty()) {
- return false;
- }
-
- for (int i = 0; i < numFeatures; i++) {
- if (mFeatures.valueAt(i).mRunning) {
+ for (OpFeatureEntry opFeatureEntry : mFeatures.values()) {
+ if (opFeatureEntry.isRunning()) {
return true;
}
}
@@ -3128,257 +3466,349 @@ public class AppOpsManager {
}
/**
- * @return The duration of the operation in milliseconds. The duration is in wall time.
+ * @deprecated Use {@link #getLastDuration(int)} instead
*/
+ @Deprecated
public long getDuration() {
- return getLastDuration(MAX_PRIORITY_UID_STATE, MIN_PRIORITY_UID_STATE, OP_FLAGS_ALL);
+ return getLastDuration(OP_FLAGS_ALL);
}
/**
- * Return the duration in milliseconds the app accessed this op while
- * in the foreground. The duration is in wall time.
+ * Return the duration in milliseconds of the last the access.
*
- * @param flags The flags which are any combination of
- * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
- * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
- * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
- * for any flag.
- * @return the foreground access duration in milliseconds.
+ * @param flags The op flags
+ *
+ * @return the duration in milliseconds or {@code -1}
+ *
+ * @see #getLastForegroundDuration(int)
+ * @see #getLastBackgroundDuration(int)
+ * @see #getLastDuration(int, int, int)
+ * @see OpFeatureEntry#getLastDuration(int)
+ */
+ public long getLastDuration(@OpFlags int flags) {
+ return getLastDuration(MAX_PRIORITY_UID_STATE, MIN_PRIORITY_UID_STATE, flags);
+ }
+
+ /**
+ * Return the duration in milliseconds of the last foreground access.
*
+ * @param flags The op flags
+ *
+ * @return the duration in milliseconds or {@code -1}
+ *
+ * @see #getLastDuration(int)
* @see #getLastBackgroundDuration(int)
* @see #getLastDuration(int, int, int)
+ * @see OpFeatureEntry#getLastForegroundDuration(int)
*/
public long getLastForegroundDuration(@OpFlags int flags) {
- return getSumOfFeatures((featureEntry) ->
- featureEntry.getLastForegroundDuration(flags));
+ return getLastDuration(MAX_PRIORITY_UID_STATE, resolveFirstUnrestrictedUidState(mOp),
+ flags);
}
/**
- * Return the duration in milliseconds the app accessed this op while
- * in the background. The duration is in wall time.
+ * Return the duration in milliseconds of the last background access.
*
- * @param flags The flags which are any combination of
- * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
- * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
- * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
- * for any flag.
- * @return the background access duration in milliseconds.
+ * @param flags The op flags
+ *
+ * @return the duration in milliseconds or {@code -1}
*
+ * @see #getLastDuration(int)
* @see #getLastForegroundDuration(int)
* @see #getLastDuration(int, int, int)
+ * @see OpFeatureEntry#getLastBackgroundDuration(int)
*/
public long getLastBackgroundDuration(@OpFlags int flags) {
- return getSumOfFeatures((featureEntry) ->
- featureEntry.getLastBackgroundDuration(flags));
+ return getLastDuration(resolveLastRestrictedUidState(mOp), MIN_PRIORITY_UID_STATE,
+ flags);
}
/**
- * Return the duration in milliseconds the app accessed this op for
- * a given range of UID states. The duration is in wall time.
+ * Return the duration in milliseconds of the last access.
*
- * @param fromUidState The UID state for which to query. Could be one of
- * {@link #UID_STATE_PERSISTENT}, {@link #UID_STATE_TOP},
- * {@link #UID_STATE_FOREGROUND_SERVICE}, {@link #UID_STATE_FOREGROUND},
- * {@link #UID_STATE_BACKGROUND}, {@link #UID_STATE_CACHED}.
- * @param toUidState The UID state for which to query.
- * @param flags The flags which are any combination of
- * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
- * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
- * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
- * for any flag.
- * @return the access duration in milliseconds.
+ * @param fromUidState The lowest UID state for which to query
+ * @param toUidState The highest UID state for which to query (inclusive)
+ * @param flags The op flags
+ *
+ * @return the duration in milliseconds or {@code -1}
+ *
+ * @see #getLastDuration(int)
+ * @see #getLastForegroundDuration(int)
+ * @see #getLastBackgroundDuration(int)
+ * @see OpFeatureEntry#getLastDuration(int, int, int)
*/
public long getLastDuration(@UidState int fromUidState, @UidState int toUidState,
@OpFlags int flags) {
- return getSumOfFeatures((featureEntry) ->
- featureEntry.getLastDuration(fromUidState, toUidState, flags));
+ NoteOpEvent lastEvent = getLastAccessEvent(fromUidState, toUidState, flags);
+ if (lastEvent == null) {
+ return -1;
+ }
+
+ return lastEvent.duration;
}
/**
- * Like {@link #findFirstNonNegativeForFlagsInStates(LongSparseLongArray, int, int, int)}
- * but for all proxy uid in all features.
+ * @deprecated Use {@link #getLastProxyInfo(int)} instead
*/
- private long findFirstNonNegativeProxyUidInFeatureStates(@UidState int beginUidState,
- @UidState int endUidState, @OpFlags int flags) {
- int numFeatures = mFeatures.size();
-
- if (numFeatures == 0) {
- return -1;
+ @Deprecated
+ public int getProxyUid() {
+ OpEventProxyInfo proxy = getLastProxyInfo(OP_FLAGS_ALL);
+ if (proxy == null) {
+ return Process.INVALID_UID;
}
- while (flags != 0) {
- final int flag = 1 << Integer.numberOfTrailingZeros(flags);
- flags &= ~flag;
- for (int uidState : UID_STATES) {
- if (uidState < beginUidState || uidState > endUidState) {
- continue;
- }
-
- final long key = makeKey(uidState, flag);
-
- for (int i = 0; i < numFeatures; i++) {
- OpFeatureEntry featureEntry = mFeatures.valueAt(i);
-
- if (featureEntry.mProxyUids == null) {
- continue;
- }
+ return proxy.getUid();
+ }
- final long proxyUid = featureEntry.mProxyUids.get(key);
- if (proxyUid >= 0) {
- return proxyUid;
- }
- }
- }
+ /**
+ * @deprecated Use {@link #getLastProxyInfo(int)} instead
+ */
+ @Deprecated
+ public int getProxyUid(@UidState int uidState, @OpFlags int flags) {
+ OpEventProxyInfo proxy = getLastProxyInfo(uidState, uidState, flags);
+ if (proxy == null) {
+ return Process.INVALID_UID;
}
- return -1;
+ return proxy.getUid();
}
/**
- * Like {@link #findFirstNonNullForFlagsInStates(LongSparseArray, int, int, int)} but
- * for all proxyPackageNames in all features.
+ * @deprecated Use {@link #getLastProxyInfo(int)} instead
*/
- private @Nullable String findFirstNonNullProxyPackageNameInFeatureStates(
- @OpFlags int flags, @UidState int beginUidState, @UidState int endUidState) {
- int numFeatures = mFeatures.size();
-
- if (numFeatures == 0) {
+ @Deprecated
+ public @Nullable String getProxyPackageName() {
+ OpEventProxyInfo proxy = getLastProxyInfo(OP_FLAGS_ALL);
+ if (proxy == null) {
return null;
}
- while (flags != 0) {
- final int flag = 1 << Integer.numberOfTrailingZeros(flags);
- flags &= ~flag;
- for (int uidState : UID_STATES) {
- if (uidState < beginUidState || uidState > endUidState) {
- continue;
- }
- final long key = makeKey(uidState, flag);
-
- for (int i = 0; i < numFeatures; i++) {
- OpFeatureEntry featureEntry = mFeatures.valueAt(i);
-
- if (featureEntry.mProxyPackageNames == null) {
- continue;
- }
+ return proxy.getPackageName();
+ }
- final String proxyName = featureEntry.mProxyPackageNames.get(key);
- if (proxyName != null) {
- return proxyName;
- }
- }
- }
+ /**
+ * @deprecated Use {@link #getLastProxyInfo(int)} instead
+ */
+ @Deprecated
+ public @Nullable String getProxyPackageName(@UidState int uidState, @OpFlags int flags) {
+ OpEventProxyInfo proxy = getLastProxyInfo(uidState, uidState, flags);
+ if (proxy == null) {
+ return null;
}
- return null;
+
+ return proxy.getPackageName();
}
/**
- * @deprecated Use {@link #getProxyUid(int, int)} instead
+ * Gets the proxy info of the app that performed the last access on behalf of this app and
+ * as a result blamed the op on this app.
+ *
+ * @param flags The op flags
+ *
+ * @return The proxy name or {@code null}
+ *
+ * @see #getLastForegroundProxyInfo(int)
+ * @see #getLastBackgroundProxyInfo(int)
+ * @see #getLastProxyInfo(int, int, int)
+ * @see OpFeatureEntry#getLastProxyInfo(int)
*/
- @Deprecated
- public int getProxyUid() {
- return (int) findFirstNonNegativeProxyUidInFeatureStates(MAX_PRIORITY_UID_STATE,
- MIN_PRIORITY_UID_STATE, OP_FLAGS_ALL);
+ public @Nullable OpEventProxyInfo getLastProxyInfo(@OpFlags int flags) {
+ return getLastProxyInfo(MAX_PRIORITY_UID_STATE, MIN_PRIORITY_UID_STATE, flags);
}
/**
- * Gets the UID of the app that performed the op on behalf of this app and
- * as a result blamed the op on this app or {@link Process#INVALID_UID} if
- * there is no proxy.
+ * Gets the proxy info of the app that performed the last foreground access on behalf of
+ * this app and as a result blamed the op on this app.
*
- * @param uidState The UID state for which to query. Could be one of
- * {@link #UID_STATE_PERSISTENT}, {@link #UID_STATE_TOP},
- * {@link #UID_STATE_FOREGROUND_SERVICE}, {@link #UID_STATE_FOREGROUND},
- * {@link #UID_STATE_BACKGROUND}, {@link #UID_STATE_CACHED}.
- * @param flags The flags which are any combination of
- * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
- * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
- * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
- * for any flag.
+ * @param flags The op flags
*
- * @return The proxy UID.
+ * @return The proxy name or {@code null}
+ *
+ * @see #getLastProxyInfo(int)
+ * @see #getLastBackgroundProxyInfo(int)
+ * @see #getLastProxyInfo(int, int, int)
+ * @see OpFeatureEntry#getLastForegroundProxyInfo(int)
*/
- public int getProxyUid(@UidState int uidState, @OpFlags int flags) {
- return (int) findFirstNonNegativeProxyUidInFeatureStates(uidState, uidState, flags);
+ public @Nullable OpEventProxyInfo getLastForegroundProxyInfo(@OpFlags int flags) {
+ return getLastProxyInfo(MAX_PRIORITY_UID_STATE, resolveFirstUnrestrictedUidState(mOp),
+ flags);
}
/**
- * @deprecated Use {@link #getProxyPackageName(int, int)} instead
+ * Gets the proxy info of the app that performed the last background access on behalf of
+ * this app and as a result blamed the op on this app.
+ *
+ * @param flags The op flags
+ *
+ * @return The proxy name or {@code null}
+ *
+ * @see #getLastProxyInfo(int)
+ * @see #getLastForegroundProxyInfo(int)
+ * @see #getLastProxyInfo(int, int, int)
+ * @see OpFeatureEntry#getLastBackgroundProxyInfo(int)
*/
- @Deprecated
- public @Nullable String getProxyPackageName() {
- return findFirstNonNullProxyPackageNameInFeatureStates(MAX_PRIORITY_UID_STATE,
- MIN_PRIORITY_UID_STATE, OP_FLAGS_ALL);
+ public @Nullable OpEventProxyInfo getLastBackgroundProxyInfo(@OpFlags int flags) {
+ return getLastProxyInfo(resolveLastRestrictedUidState(mOp), MIN_PRIORITY_UID_STATE,
+ flags);
}
/**
- * Gets the package name of the app that performed the op on behalf of this
- * app and as a result blamed the op on this app for a UID state or
- * {@code null} if there is no proxy.
+ * Gets the proxy info of the app that performed the last access on behalf of this app and
+ * as a result blamed the op on this app.
*
- * @param uidState The UID state for which to query. Could be one of
- * {@link #UID_STATE_PERSISTENT}, {@link #UID_STATE_TOP},
- * {@link #UID_STATE_FOREGROUND_SERVICE}, {@link #UID_STATE_FOREGROUND},
- * {@link #UID_STATE_BACKGROUND}, {@link #UID_STATE_CACHED}.
- * @param flags The flags which are any combination of
- * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
- * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
- * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
- * for any flag.
- * @return The proxy package name.
+ * @param fromUidState The lowest UID state for which to query
+ * @param toUidState The highest UID state for which to query (inclusive)
+ * @param flags The op flags
+ *
+ * @return The proxy name or {@code null}
+ *
+ * @see #getLastProxyInfo(int)
+ * @see #getLastForegroundProxyInfo(int)
+ * @see #getLastBackgroundProxyInfo(int)
+ * @see OpFeatureEntry#getLastProxyInfo(int, int, int)
*/
- public @Nullable String getProxyPackageName(@UidState int uidState, @OpFlags int flags) {
- return findFirstNonNullProxyPackageNameInFeatureStates(uidState, uidState, flags);
+ public @Nullable OpEventProxyInfo getLastProxyInfo(@UidState int fromUidState,
+ @UidState int toUidState, @OpFlags int flags) {
+ NoteOpEvent lastEvent = getLastAccessEvent(fromUidState, toUidState, flags);
+ if (lastEvent == null) {
+ return null;
+ }
+
+ return lastEvent.proxy;
}
+
+
+ // Code below generated by codegen v1.0.14.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/app/AppOpsManager.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
/**
- * Create OpEntry from parcel.
+ * Creates a new OpEntry.
*
+ * @param op
+ * The code of the op
+ * @param mode
+ * The mode of the op
+ * @param features
+ * The features that have been used when checking the op
* @hide
*/
- public static OpEntry createFromParcel(@NonNull Parcel source) {
- int op = source.readInt();
- int mode = source.readInt();
-
- int numFeatures = source.readInt();
- Pair<String, OpFeatureEntry.Builder>[] features = new Pair[numFeatures];
- for (int i = 0; i < numFeatures; i++) {
- features[i] = new Pair<>(source.readString(),
- OpFeatureEntry.createFromParcel(source));
- }
+ @DataClass.Generated.Member
+ public OpEntry(
+ @IntRange(from = 0, to = _NUM_OP - 1) int op,
+ @Mode int mode,
+ @NonNull Map<String,OpFeatureEntry> features) {
+ this.mOp = op;
+ com.android.internal.util.AnnotationValidations.validate(
+ IntRange.class, null, mOp,
+ "from", 0,
+ "to", _NUM_OP - 1);
+ this.mMode = mode;
+ com.android.internal.util.AnnotationValidations.validate(
+ Mode.class, null, mMode);
+ this.mFeatures = features;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mFeatures);
+
+ // onConstructed(); // You can define this method to get a callback
+ }
- return new OpEntry(op, mode, features);
+ /**
+ * The mode of the op
+ */
+ @DataClass.Generated.Member
+ public @Mode int getMode() {
+ return mMode;
}
- @Override
- public int describeContents() {
- return 0;
+ /**
+ * The features that have been used when checking the op
+ */
+ @DataClass.Generated.Member
+ public @NonNull Map<String,OpFeatureEntry> getFeatures() {
+ return mFeatures;
}
@Override
+ @DataClass.Generated.Member
public void writeToParcel(Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
dest.writeInt(mOp);
dest.writeInt(mMode);
-
- int numFeatures = mFeatures.size();
- dest.writeInt(numFeatures);
- for (int i = 0; i < numFeatures; i++) {
- dest.writeString(mFeatures.keyAt(i));
- mFeatures.valueAt(i).writeToParcel(dest, flags);
- }
+ dest.writeMap(mFeatures);
}
- public static final @NonNull Creator<OpEntry> CREATOR = new Creator<OpEntry>() {
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ @DataClass.Generated.Member
+ /* package-private */ OpEntry(@NonNull Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ int op = in.readInt();
+ int mode = in.readInt();
+ Map<String,OpFeatureEntry> features = new java.util.LinkedHashMap<>();
+ in.readMap(features, OpFeatureEntry.class.getClassLoader());
+
+ this.mOp = op;
+ com.android.internal.util.AnnotationValidations.validate(
+ IntRange.class, null, mOp,
+ "from", 0,
+ "to", _NUM_OP - 1);
+ this.mMode = mode;
+ com.android.internal.util.AnnotationValidations.validate(
+ Mode.class, null, mMode);
+ this.mFeatures = features;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mFeatures);
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public static final @NonNull Parcelable.Creator<OpEntry> CREATOR
+ = new Parcelable.Creator<OpEntry>() {
@Override
- public @NonNull OpEntry createFromParcel(@NonNull Parcel parcel) {
- return OpEntry.createFromParcel(parcel);
+ public OpEntry[] newArray(int size) {
+ return new OpEntry[size];
}
@Override
- public @NonNull OpEntry[] newArray(int size) {
- return new OpEntry[size];
+ public OpEntry createFromParcel(@NonNull Parcel in) {
+ return new OpEntry(in);
}
};
+
+ /*
+ @DataClass.Generated(
+ time = 1574809856259L,
+ codegenVersion = "1.0.14",
+ sourceFile = "frameworks/base/core/java/android/app/AppOpsManager.java",
+ inputSignatures = "private final @android.annotation.IntRange(from=0L, to=_NUM_OP - 1) int mOp\nprivate final @android.app.Mode int mMode\nprivate final @android.annotation.NonNull java.util.Map<java.lang.String,android.app.OpFeatureEntry> mFeatures\npublic @android.annotation.UnsupportedAppUsage(maxTargetSdk=Build.VERSION_CODES.Q, publicAlternatives=\"{@code \" + \"#getOpStr()}\") int getOp()\npublic @android.annotation.NonNull java.lang.String getOpStr()\npublic @java.lang.Deprecated @android.annotation.UnsupportedAppUsage(maxTargetSdk=Build.VERSION_CODES.Q, publicAlternatives=\"{@code \" + \"#getAccessTime(int, int)}\") long getTime()\npublic @java.lang.Deprecated long getLastAccessTime(int)\npublic @java.lang.Deprecated long getLastAccessForegroundTime(int)\npublic @java.lang.Deprecated long getLastAccessBackgroundTime(int)\npublic @java.lang.Deprecated long getLastAccessTime(int,int,int)\npublic @java.lang.Deprecated @android.annotation.UnsupportedAppUsage(maxTargetSdk=Build.VERSION_CODES.Q, publicAlternatives=\"{@code \" + \"#getLastRejectTime(int, int, int)}\") long getRejectTime()\npublic @java.lang.Deprecated long getLastRejectTime(int)\npublic @java.lang.Deprecated long getLastRejectForegroundTime(int)\npublic @java.lang.Deprecated long getLastRejectBackgroundTime(int)\npublic @java.lang.Deprecated long getLastRejectTime(int,int,int)\npublic long getAccessTime(int,int)\npublic long getRejectTime(int,int)\npublic boolean isRunning()\nprivate android.app.NoteOpEvent getLastAccessEvent(int,int,int)\npublic @java.lang.Deprecated long getDuration()\npublic @java.lang.Deprecated long getLastForegroundDuration(int)\npublic @java.lang.Deprecated long getLastBackgroundDuration(int)\npublic @java.lang.Deprecated long getLastDuration(int,int,int)\npublic @java.lang.Deprecated int getProxyUid()\npublic @java.lang.Deprecated @android.annotation.Nullable java.lang.String getProxyPackageName()\nprivate @android.app.UidState int getLastAccessUidStateForFlagsInStatesOfAllFeatures(int,int,int)\npublic @android.app.UidState int getLastAccessUidState(int)\npublic @android.app.UidState int getLastForegroundAccessUidState(int)\npublic @android.app.UidState int getLastBackgroundAccessUidState(int)\nprivate @android.app.UidState int getLastRejectUidStateForFlagsInStatesOfAllFeatures(int,int,int)\npublic @android.app.UidState int getLastRejectUidState(int)\npublic @android.app.UidState int getLastForegroundRejectUidState(int)\npublic @android.app.UidState int getLastBackgroundRejectUidState(int)\npublic long getDuration(int,int)\npublic int getProxyUid(int,int)\nprivate int getProxyUid(int,int,int)\npublic @android.annotation.Nullable java.lang.String getProxyPackageName(int,int)\nprivate @android.annotation.Nullable java.lang.String getProxyPackageName(int,int,int)\nclass OpEntry extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genHiddenConstructor=true)")
+ @Deprecated
+ private void __metadata() {}
+ */
+
+
+ //@formatter:on
+ // End of generated code
+
}
/** @hide */
@@ -4890,71 +5320,6 @@ public class AppOpsManager {
}
/**
- * Finds the first non-negative value for the given flags in between the begin and
- * end UID states.
- *
- * @param counts The data array.
- * @param beginUidState The beginning UID state (inclusive).
- * @param endUidState The end UID state (inclusive).
- * @param flags The UID flags.
- * @return The non-negative value or -1.
- */
- private static long findFirstNonNegativeForFlagsInStates(@Nullable LongSparseLongArray counts,
- @UidState int beginUidState, @UidState int endUidState, @OpFlags int flags) {
- if (counts == null) {
- return -1;
- }
- while (flags != 0) {
- final int flag = 1 << Integer.numberOfTrailingZeros(flags);
- flags &= ~flag;
- for (int uidState : UID_STATES) {
- if (uidState < beginUidState || uidState > endUidState) {
- continue;
- }
- final long key = makeKey(uidState, flag);
- final long value = counts.get(key);
- if (value >= 0) {
- return value;
- }
- }
- }
- return -1;
- }
-
- /**
- * Finds the first non-null value for the given flags in between the begin and
- * end UID states.
- *
- * @param counts The data array.
- * @param beginUidState The beginning UID state (inclusive).
- * @param endUidState The end UID state (inclusive).
- * @param flags The UID flags.
- * @return The non-negative value or -1.
- */
- private static @Nullable String findFirstNonNullForFlagsInStates(
- @Nullable LongSparseArray<String> counts, @UidState int beginUidState,
- @UidState int endUidState, @OpFlags int flags) {
- if (counts == null) {
- return null;
- }
- while (flags != 0) {
- final int flag = 1 << Integer.numberOfTrailingZeros(flags);
- flags &= ~flag;
- for (int uidState : UID_STATES) {
- if (uidState < beginUidState || uidState > endUidState) {
- continue;
- }
- final long key = makeKey(uidState, flag);
- final String value = counts.get(key);
- if (value != null) {
- return value;
- }
- }
- }
- return null;
- }
-
- /**
* Callback for notification of changes to operation state.
*/
public interface OnOpChangedListener {
@@ -5112,6 +5477,7 @@ public class AppOpsManager {
*
* @hide
*/
+ @TestApi
@SystemApi
@RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS)
public @NonNull List<AppOpsManager.PackageOps> getOpsForPackage(int uid,
@@ -6135,23 +6501,29 @@ public class AppOpsManager {
}
}
- /** @hide */
- @UnsupportedAppUsage
+ /**
+ * @deprecated Use own local {@link android.os.Binder#Binder()}
+ *
+ * @hide
+ */
+ @Deprecated
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "Create own "
+ + "local {@link android.os.Binder}")
public static IBinder getToken(IAppOpsService service) {
+ return getClientId();
+ }
+
+ /** @hide */
+ public static IBinder getClientId() {
synchronized (AppOpsManager.class) {
- if (sToken != null) {
- return sToken;
+ if (sClientId == null) {
+ sClientId = new Binder();
}
- try {
- sToken = service.getToken(new Binder());
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- return sToken;
+
+ return sClientId;
}
}
-
/**
* @deprecated use {@link #startOp(String, int, String, String, String)} instead
*/
@@ -6207,7 +6579,7 @@ public class AppOpsManager {
* the package is not in the passed in UID.
*/
public int startOp(@NonNull String op, int uid, @Nullable String packageName,
- @NonNull String featureId, @Nullable String message) {
+ @Nullable String featureId, @Nullable String message) {
return startOp(strOpToOp(op), uid, packageName, false, featureId, message);
}
@@ -6231,7 +6603,7 @@ public class AppOpsManager {
* @hide
*/
public int startOp(int op, int uid, @Nullable String packageName, boolean startIfModeDefault,
- @NonNull String featureId, @Nullable String message) {
+ @Nullable String featureId, @Nullable String message) {
final int mode = startOpNoThrow(op, uid, packageName, startIfModeDefault, featureId,
message);
if (mode == MODE_ERRORED) {
@@ -6307,7 +6679,7 @@ public class AppOpsManager {
public int startOpNoThrow(int op, int uid, @NonNull String packageName,
boolean startIfModeDefault, @Nullable String featureId, @Nullable String message) {
try {
- int mode = mService.startOperation(getToken(mService), op, uid, packageName,
+ int mode = mService.startOperation(getClientId(), op, uid, packageName,
featureId, startIfModeDefault);
if (mode == MODE_ALLOWED) {
markAppOpNoted(uid, packageName, op, featureId, message);
@@ -6367,7 +6739,7 @@ public class AppOpsManager {
public void finishOp(int op, int uid, @NonNull String packageName,
@Nullable String featureId) {
try {
- mService.finishOperation(getToken(mService), op, uid, packageName, featureId);
+ mService.finishOperation(getClientId(), op, uid, packageName, featureId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -6932,22 +7304,23 @@ public class AppOpsManager {
}
/**
- * Computes the max for the given flags in between the begin and
- * end UID states.
+ * Gets the last of the event.
*
- * @param counts The data array.
- * @param flags The UID flags.
- * @param beginUidState The beginning UID state (exclusive).
- * @param endUidState The end UID state.
- * @return The sum.
+ * @param events The events
+ * @param flags The UID flags
+ * @param beginUidState The maximum UID state (inclusive)
+ * @param endUidState The minimum UID state (inclusive)
+ *
+ * @return The last event of {@code null}
*/
- private static long maxForFlagsInStates(@Nullable LongSparseLongArray counts,
- @UidState int beginUidState, @UidState int endUidState,
- @OpFlags int flags) {
- if (counts == null) {
- return 0;
+ private static @Nullable NoteOpEvent getLastEvent(
+ @Nullable LongSparseArray<NoteOpEvent> events, @UidState int beginUidState,
+ @UidState int endUidState, @OpFlags int flags) {
+ if (events == null) {
+ return null;
}
- long max = 0;
+
+ NoteOpEvent lastEvent = null;
while (flags != 0) {
final int flag = 1 << Integer.numberOfTrailingZeros(flags);
flags &= ~flag;
@@ -6956,12 +7329,16 @@ public class AppOpsManager {
continue;
}
final long key = makeKey(uidState, flag);
- max = Math.max(max, counts.get(key));
+
+ NoteOpEvent event = events.get(key);
+ if (lastEvent == null || event != null && event.noteTime > lastEvent.noteTime) {
+ lastEvent = event;
+ }
}
}
- return max;
- }
+ return lastEvent;
+ }
private static void writeLongSparseLongArrayToParcel(
@Nullable LongSparseLongArray array, @NonNull Parcel parcel) {
@@ -6990,33 +7367,6 @@ public class AppOpsManager {
return array;
}
- private static void writeLongSparseStringArrayToParcel(
- @Nullable LongSparseArray<String> array, @NonNull Parcel parcel) {
- if (array != null) {
- final int size = array.size();
- parcel.writeInt(size);
- for (int i = 0; i < size; i++) {
- parcel.writeLong(array.keyAt(i));
- parcel.writeString(array.valueAt(i));
- }
- } else {
- parcel.writeInt(-1);
- }
- }
-
- private static @Nullable LongSparseArray<String> readLongSparseStringArrayFromParcel(
- @NonNull Parcel parcel) {
- final int size = parcel.readInt();
- if (size < 0) {
- return null;
- }
- final LongSparseArray<String> array = new LongSparseArray<>(size);
- for (int i = 0; i < size; i++) {
- array.append(parcel.readLong(), parcel.readString());
- }
- return array;
- }
-
/**
* Collects the keys from an array to the result creating the result if needed.
*
diff --git a/core/java/android/app/Application.java b/core/java/android/app/Application.java
index e12942f248d4..941467fad736 100644
--- a/core/java/android/app/Application.java
+++ b/core/java/android/app/Application.java
@@ -19,7 +19,7 @@ package android.app;
import android.annotation.CallSuper;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentCallbacks;
import android.content.ComponentCallbacks2;
import android.content.Context;
diff --git a/core/java/android/app/ApplicationLoaders.java b/core/java/android/app/ApplicationLoaders.java
index 2e59b903f06d..bac432e42318 100644
--- a/core/java/android/app/ApplicationLoaders.java
+++ b/core/java/android/app/ApplicationLoaders.java
@@ -16,7 +16,7 @@
package android.app;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.SharedLibraryInfo;
import android.os.Build;
import android.os.GraphicsEnvironment;
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 034826a8d5fa..7f26565d760a 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -20,9 +20,9 @@ import android.annotation.DrawableRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringRes;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.UserIdInt;
import android.annotation.XmlRes;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
diff --git a/core/java/android/app/AsyncNotedAppOp.java b/core/java/android/app/AsyncNotedAppOp.java
index 958ebae003ea..0e1f92177e9d 100644
--- a/core/java/android/app/AsyncNotedAppOp.java
+++ b/core/java/android/app/AsyncNotedAppOp.java
@@ -285,7 +285,7 @@ public final class AsyncNotedAppOp implements Parcelable {
time = 1571327470155L,
codegenVersion = "1.0.9",
sourceFile = "frameworks/base/core/java/android/app/AsyncNotedAppOp.java",
- inputSignatures = "private final @android.annotation.IntRange(from=0L, to=91L) int mOpCode\nprivate final @android.annotation.IntRange(from=0L) int mNotingUid\nprivate final @android.annotation.Nullable java.lang.String mNotingPackageName\nprivate final @android.annotation.Nullable java.lang.String mFeatureId\nprivate final @android.annotation.NonNull java.lang.String mMessage\nprivate final @android.annotation.IntRange(from=0L) long mTime\npublic @android.annotation.NonNull java.lang.String getOp()\nclass AsyncNotedAppOp extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genAidl=true, genHiddenConstructor=true)")
+ inputSignatures = "private final @android.annotation.IntRange(from=0L, to=92L) int mOpCode\nprivate final @android.annotation.IntRange(from=0L) int mNotingUid\nprivate final @android.annotation.Nullable java.lang.String mNotingPackageName\nprivate final @android.annotation.Nullable java.lang.String mFeatureId\nprivate final @android.annotation.NonNull java.lang.String mMessage\nprivate final @android.annotation.IntRange(from=0L) long mTime\npublic @android.annotation.NonNull java.lang.String getOp()\nclass AsyncNotedAppOp extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genAidl=true, genHiddenConstructor=true)")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/app/ClientTransactionHandler.java b/core/java/android/app/ClientTransactionHandler.java
index d308adc52e15..f9a689a7e1de 100644
--- a/core/java/android/app/ClientTransactionHandler.java
+++ b/core/java/android/app/ClientTransactionHandler.java
@@ -158,6 +158,9 @@ public abstract class ClientTransactionHandler {
public abstract void handlePictureInPictureModeChanged(IBinder token, boolean isInPipMode,
Configuration overrideConfig);
+ /** Request that an activity enter picture-in-picture. */
+ public abstract void handlePictureInPictureRequested(IBinder token);
+
/** Update window visibility. */
public abstract void handleWindowVisibility(IBinder token, boolean show);
diff --git a/core/java/android/app/ContentProviderHolder.java b/core/java/android/app/ContentProviderHolder.java
index 004dca1a708f..3d745831ce1c 100644
--- a/core/java/android/app/ContentProviderHolder.java
+++ b/core/java/android/app/ContentProviderHolder.java
@@ -16,7 +16,7 @@
package android.app;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentProviderNative;
import android.content.IContentProvider;
import android.content.pm.ProviderInfo;
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 155e93f9be19..bd87fcd2565e 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -20,7 +20,7 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.AutofillOptions;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
diff --git a/core/java/android/app/DatePickerDialog.java b/core/java/android/app/DatePickerDialog.java
index 9d82ffa838ca..195c3e1c296a 100644
--- a/core/java/android/app/DatePickerDialog.java
+++ b/core/java/android/app/DatePickerDialog.java
@@ -19,7 +19,7 @@ package android.app;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StyleRes;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index 39f1e957cbfb..5e05506eb416 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -24,7 +24,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringRes;
import android.annotation.StyleRes;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.ContextWrapper;
diff --git a/core/java/android/app/DialogFragment.java b/core/java/android/app/DialogFragment.java
index bfc15c221702..e4c84d7e7997 100644
--- a/core/java/android/app/DialogFragment.java
+++ b/core/java/android/app/DialogFragment.java
@@ -16,7 +16,7 @@
package android.app;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java
index eb50581f3319..49c389a0c4a7 100644
--- a/core/java/android/app/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -22,7 +22,7 @@ import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.ContentUris;
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index 4f121aa35f7c..c6a0de458df0 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -21,7 +21,7 @@ import android.annotation.CallSuper;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringRes;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentCallbacks2;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/app/FragmentController.java b/core/java/android/app/FragmentController.java
index 9316be7a7968..f021f7690283 100644
--- a/core/java/android/app/FragmentController.java
+++ b/core/java/android/app/FragmentController.java
@@ -17,7 +17,7 @@
package android.app;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Configuration;
import android.os.Bundle;
diff --git a/core/java/android/app/FragmentHostCallback.java b/core/java/android/app/FragmentHostCallback.java
index 26b4a11f4c10..9e887b88c407 100644
--- a/core/java/android/app/FragmentHostCallback.java
+++ b/core/java/android/app/FragmentHostCallback.java
@@ -18,7 +18,7 @@ package android.app;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 68daf44b19a5..904c4735e0ff 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -22,7 +22,7 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.PropertyValuesHolder;
import android.animation.ValueAnimator;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.res.Configuration;
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 112bd303a8b3..e8494c4c5893 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -583,4 +583,9 @@ interface IActivityManager {
* unlockProgressListener can be null if monitoring progress is not necessary.
*/
boolean startUserInForegroundWithListener(int userid, IProgressListener unlockProgressListener);
+
+ /**
+ * Method for the app to tell system that it's wedged and would like to trigger an ANR.
+ */
+ void appNotResponding(String reason);
}
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index e2b1b8664d75..700b3c1b620e 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -333,6 +333,7 @@ interface IActivityTaskManager {
boolean isInPictureInPictureMode(in IBinder token);
boolean enterPictureInPictureMode(in IBinder token, in PictureInPictureParams params);
void setPictureInPictureParams(in IBinder token, in PictureInPictureParams params);
+ void requestPictureInPictureMode(in IBinder token);
int getMaxNumPictureInPictureActions(in IBinder token);
IBinder getUriPermissionOwnerForActivity(in IBinder activityToken);
@@ -437,6 +438,11 @@ interface IActivityTaskManager {
void registerRemoteAnimations(in IBinder token, in RemoteAnimationDefinition definition);
/**
+ * Unregisters all remote animations for a specific activity.
+ */
+ void unregisterRemoteAnimations(in IBinder token);
+
+ /**
* Registers a remote animation to be run for all activity starts from a certain package during
* a short predefined amount of time.
*/
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index 690e9567c1ef..62c905d8c2c6 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -19,7 +19,7 @@ package android.app;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
@@ -1519,6 +1519,16 @@ public class Instrumentation {
public void callActivityOnUserLeaving(Activity activity) {
activity.performUserLeaving();
}
+
+ /**
+ * Perform calling of an activity's {@link Activity#onPictureInPictureRequested} method.
+ * The default implementation simply calls through to that method.
+ *
+ * @param activity The activity being notified that picture-in-picture is being requested.
+ */
+ public void callActivityOnPictureInPictureRequested(@NonNull Activity activity) {
+ activity.onPictureInPictureRequested();
+ }
/*
* Starts allocation counting. This triggers a gc and resets the counts.
diff --git a/core/java/android/app/IntentService.java b/core/java/android/app/IntentService.java
index 74fb99a0909f..71b28fba6019 100644
--- a/core/java/android/app/IntentService.java
+++ b/core/java/android/app/IntentService.java
@@ -16,9 +16,9 @@
package android.app;
-import android.annotation.UnsupportedAppUsage;
-import android.annotation.WorkerThread;
import android.annotation.Nullable;
+import android.annotation.WorkerThread;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.os.Handler;
import android.os.HandlerThread;
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index b1565ab8a501..6518652f6e91 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -23,8 +23,8 @@ import android.annotation.RequiresFeature;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
import android.app.trust.ITrustManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -118,6 +118,16 @@ public class KeyguardManager {
public static final int RESULT_ALTERNATE = 1;
/**
+ *
+ * If this is set, check device policy for allowed biometrics when the user is authenticating.
+ * This should only be used in the context of managed profiles.
+ *
+ * @hide
+ */
+ public static final String EXTRA_DISALLOW_BIOMETRICS_IF_POLICY_EXISTS = "check_dpm";
+
+
+ /**
* Get an intent to prompt the user to confirm credentials (pin, pattern, password or biometrics
* if enrolled) for the current user of the device. The caller is expected to launch this
* activity using {@link android.app.Activity#startActivityForResult(Intent, int)} and check for
@@ -166,6 +176,28 @@ public class KeyguardManager {
/**
* Get an intent to prompt the user to confirm credentials (pin, pattern or password)
+ * for the given user. The caller is expected to launch this activity using
+ * {@link android.app.Activity#startActivityForResult(Intent, int)} and check for
+ * {@link android.app.Activity#RESULT_OK} if the user successfully completes the challenge.
+ *
+ * @param disallowBiometricsIfPolicyExists If true check if the Device Policy Manager has
+ * disabled biometrics on the device. If biometrics are disabled, fall back to PIN/pattern/pass.
+ *
+ * @return the intent for launching the activity or null if no password is required.
+ *
+ * @hide
+ */
+ public Intent createConfirmDeviceCredentialIntent(
+ CharSequence title, CharSequence description, int userId,
+ boolean disallowBiometricsIfPolicyExists) {
+ Intent intent = this.createConfirmDeviceCredentialIntent(title, description, userId);
+ intent.putExtra(EXTRA_DISALLOW_BIOMETRICS_IF_POLICY_EXISTS,
+ disallowBiometricsIfPolicyExists);
+ return intent;
+ }
+
+ /**
+ * Get an intent to prompt the user to confirm credentials (pin, pattern or password)
* for the previous owner of the device. The caller is expected to launch this activity using
* {@link android.app.Activity#startActivityForResult(Intent, int)} and check for
* {@link android.app.Activity#RESULT_OK} if the user successfully completes the challenge.
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index e858e6a976bc..775b1d165717 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -18,7 +18,7 @@ package android.app;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -46,7 +46,7 @@ import android.os.StrictMode;
import android.os.SystemProperties;
import android.os.Trace;
import android.os.UserHandle;
-import android.sysprop.ProductProperties;
+import android.sysprop.VndkProperties;
import android.text.TextUtils;
import android.util.AndroidRuntimeException;
import android.util.ArrayMap;
@@ -785,13 +785,12 @@ public final class LoadedApk {
// Similar to vendor apks, we should add /product/lib for apks from product partition
// when product apps are marked as unbundled. We cannot use the same way from vendor
// to check if lib path exists because there is possibility that /product/lib would not
- // exist from legacy device while product apks are bundled. To make this clear, new
- // property ("ro.product.apps.unbundled") is defined which should be true only when
- // product apks are unbundled.
+ // exist from legacy device while product apks are bundled. To make this clear, we use
+ // "ro.product.vndk.version" property. If the property is defined, we regard all product
+ // apks as unbundled.
if (mApplicationInfo.getCodePath() != null
- && mApplicationInfo.isProduct() && ProductProperties.unbundled_apps().orElse(false)
- // TODO(b/128557860): Change target SDK version when version code R is available.
- && getTargetSdkVersion() == Build.VERSION_CODES.CUR_DEVELOPMENT) {
+ && mApplicationInfo.isProduct()
+ && VndkProperties.product_vndk_version().isPresent()) {
isBundledApp = false;
}
diff --git a/core/java/android/app/LocalActivityManager.java b/core/java/android/app/LocalActivityManager.java
index 87b064d1edc7..4033aea32b55 100644
--- a/core/java/android/app/LocalActivityManager.java
+++ b/core/java/android/app/LocalActivityManager.java
@@ -16,9 +16,9 @@
package android.app;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread.ActivityClientRecord;
import android.app.servertransaction.PendingTransactionActions;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.os.Binder;
diff --git a/core/java/android/app/NativeActivity.java b/core/java/android/app/NativeActivity.java
index 25eb958b61e3..74bc9e215106 100644
--- a/core/java/android/app/NativeActivity.java
+++ b/core/java/android/app/NativeActivity.java
@@ -16,7 +16,7 @@
package android.app;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index e30714270d1d..6f63eea1163d 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -32,7 +32,7 @@ import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.LocusId;
diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java
index 1fc8a2b38f95..3eee1ae5c00c 100644
--- a/core/java/android/app/NotificationChannel.java
+++ b/core/java/android/app/NotificationChannel.java
@@ -18,8 +18,8 @@ package android.app;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.NotificationManager.Importance;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/app/NotificationChannelGroup.java b/core/java/android/app/NotificationChannelGroup.java
index c4c1e4f98dc8..403fb3e3727c 100644
--- a/core/java/android/app/NotificationChannelGroup.java
+++ b/core/java/android/app/NotificationChannelGroup.java
@@ -17,7 +17,7 @@ package android.app;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 850645dd81e2..fdbb8bb0d4c5 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -23,8 +23,8 @@ import android.annotation.SdkConstant;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.Notification.Builder;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/app/PackageDeleteObserver.java b/core/java/android/app/PackageDeleteObserver.java
index b7b0b192e7ae..d8803aa13e42 100644
--- a/core/java/android/app/PackageDeleteObserver.java
+++ b/core/java/android/app/PackageDeleteObserver.java
@@ -16,7 +16,7 @@
package android.app;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.content.pm.IPackageDeleteObserver2;
diff --git a/core/java/android/app/PackageInstallObserver.java b/core/java/android/app/PackageInstallObserver.java
index 50031e0e4d35..0820367db1f8 100644
--- a/core/java/android/app/PackageInstallObserver.java
+++ b/core/java/android/app/PackageInstallObserver.java
@@ -16,7 +16,7 @@
package android.app;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.content.pm.IPackageInstallObserver2;
import android.os.Bundle;
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index 0407a8a05609..b8348c7d4f22 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -19,7 +19,7 @@ package android.app;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.IIntentReceiver;
import android.content.IIntentSender;
diff --git a/core/java/android/app/Presentation.java b/core/java/android/app/Presentation.java
index cb72d4d5dc2c..f864fb57d00a 100644
--- a/core/java/android/app/Presentation.java
+++ b/core/java/android/app/Presentation.java
@@ -20,24 +20,24 @@ import static android.content.Context.DISPLAY_SERVICE;
import static android.content.Context.WINDOW_SERVICE;
import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Resources;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManager.DisplayListener;
import android.os.Binder;
+import android.os.Handler;
import android.os.IBinder;
+import android.os.Message;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.util.TypedValue;
import android.view.ContextThemeWrapper;
import android.view.Display;
import android.view.Gravity;
import android.view.Window;
import android.view.WindowManager;
import android.view.WindowManagerImpl;
-import android.os.Handler;
-import android.os.Message;
-import android.util.DisplayMetrics;
-import android.util.Log;
-import android.util.TypedValue;
/**
* Base class for presentations.
diff --git a/core/java/android/app/ProgressDialog.java b/core/java/android/app/ProgressDialog.java
index 3193eb89ac80..432fae5e9033 100644
--- a/core/java/android/app/ProgressDialog.java
+++ b/core/java/android/app/ProgressDialog.java
@@ -16,9 +16,7 @@
package android.app;
-import com.android.internal.R;
-
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
@@ -34,6 +32,8 @@ import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;
+import com.android.internal.R;
+
import java.text.NumberFormat;
/**
diff --git a/core/java/android/app/QueuedWork.java b/core/java/android/app/QueuedWork.java
index 76265390fe1a..82cc2c4daa0b 100644
--- a/core/java/android/app/QueuedWork.java
+++ b/core/java/android/app/QueuedWork.java
@@ -16,7 +16,7 @@
package android.app;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 08a28f56021b..aa115984b5e1 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -21,7 +21,7 @@ import static android.app.ActivityThread.DEBUG_CONFIGURATION;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.res.ApkAssets;
diff --git a/core/java/android/app/ResultInfo.java b/core/java/android/app/ResultInfo.java
index 9ee0f3126432..979d3dbf36a7 100644
--- a/core/java/android/app/ResultInfo.java
+++ b/core/java/android/app/ResultInfo.java
@@ -16,7 +16,7 @@
package android.app;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.os.Build;
import android.os.Parcel;
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index 8493fb25b8a5..9fe894b75455 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -17,7 +17,7 @@
package android.app;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index b10c3e2dd7df..95f55ab2fde9 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -19,7 +19,7 @@ package android.app;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.ContentResolver;
diff --git a/core/java/android/app/SearchableInfo.java b/core/java/android/app/SearchableInfo.java
index a01cec7aa944..83eb2ee1da14 100644
--- a/core/java/android/app/SearchableInfo.java
+++ b/core/java/android/app/SearchableInfo.java
@@ -16,17 +16,14 @@
package android.app;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
import android.annotation.StringRes;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
-import android.content.pm.ProviderInfo;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ProviderInfo;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.os.Parcel;
@@ -38,6 +35,9 @@ import android.util.Log;
import android.util.Xml;
import android.view.inputmethod.EditorInfo;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
import java.io.IOException;
import java.util.HashMap;
diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java
index 9b62e3b3af98..dc8269f900b7 100644
--- a/core/java/android/app/Service.java
+++ b/core/java/android/app/Service.java
@@ -21,7 +21,7 @@ import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MANIFEST;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentCallbacks2;
import android.content.ComponentName;
import android.content.Context;
diff --git a/core/java/android/app/SharedPreferencesImpl.java b/core/java/android/app/SharedPreferencesImpl.java
index 9f865b41afc6..abb0cfc73f35 100644
--- a/core/java/android/app/SharedPreferencesImpl.java
+++ b/core/java/android/app/SharedPreferencesImpl.java
@@ -17,10 +17,10 @@
package android.app;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.compat.Compatibility;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledAfter;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.FileUtils;
diff --git a/core/java/android/app/StatsManager.java b/core/java/android/app/StatsManager.java
index f6e9569f513c..b9893aaa66a4 100644
--- a/core/java/android/app/StatsManager.java
+++ b/core/java/android/app/StatsManager.java
@@ -27,6 +27,7 @@ import android.os.IBinder;
import android.os.IPullAtomCallback;
import android.os.IPullAtomResultReceiver;
import android.os.IStatsCompanionService;
+import android.os.IStatsManagerService;
import android.os.IStatsPullerCallback;
import android.os.IStatsd;
import android.os.RemoteException;
@@ -37,6 +38,7 @@ import android.util.StatsEvent;
import android.util.StatsEventParcel;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import java.util.ArrayList;
import java.util.List;
@@ -61,6 +63,9 @@ public final class StatsManager {
@GuardedBy("sLock")
private IStatsCompanionService mStatsCompanion;
+ @GuardedBy("sLock")
+ private IStatsManagerService mStatsManagerService;
+
/**
* Long extra of uid that added the relevant stats config.
*/
@@ -103,8 +108,31 @@ public final class StatsManager {
*/
public static final String ACTION_STATSD_STARTED = "android.app.action.STATSD_STARTED";
- private static final long DEFAULT_COOL_DOWN_NS = 1_000_000_000L; // 1 second.
- private static final long DEFAULT_TIMEOUT_NS = 10_000_000_000L; // 10 seconds.
+ // Pull atom callback return codes.
+ /**
+ * Value indicating that this pull was successful and that the result should be used.
+ *
+ * @hide
+ **/
+ public static final int PULL_SUCCESS = 0;
+
+ /**
+ * Value indicating that this pull was unsuccessful and that the result should not be used.
+ * @hide
+ **/
+ public static final int PULL_SKIP = 1;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final long DEFAULT_COOL_DOWN_NS = 1_000_000_000L; // 1 second.
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final long DEFAULT_TIMEOUT_NS = 10_000_000_000L; // 10 seconds.
/**
* Constructor for StatsManagerClient.
@@ -504,13 +532,11 @@ public final class StatsManager {
* additive fields for mapping isolated to host uids.
* @param callback The callback to be invoked when the stats service pulls the atom.
* @param executor The executor in which to run the callback
- * @throws RemoteException if unsuccessful due to failing to connect to system server.
*
* @hide
*/
public void registerPullAtomCallback(int atomTag, @Nullable PullAtomMetadata metadata,
- @NonNull StatsPullAtomCallback callback, @NonNull Executor executor)
- throws RemoteException, SecurityException {
+ @NonNull StatsPullAtomCallback callback, @NonNull Executor executor) {
long coolDownNs = metadata == null ? DEFAULT_COOL_DOWN_NS : metadata.mCoolDownNs;
long timeoutNs = metadata == null ? DEFAULT_TIMEOUT_NS : metadata.mTimeoutNs;
int[] additiveFields = metadata == null ? new int[0] : metadata.mAdditiveFields;
@@ -518,10 +544,34 @@ public final class StatsManager {
additiveFields = new int[0];
}
synchronized (sLock) {
- IStatsCompanionService service = getIStatsCompanionServiceLocked();
- PullAtomCallbackInternal rec =
+ try {
+ IStatsCompanionService service = getIStatsCompanionServiceLocked();
+ PullAtomCallbackInternal rec =
new PullAtomCallbackInternal(atomTag, callback, executor);
- service.registerPullAtomCallback(atomTag, coolDownNs, timeoutNs, additiveFields, rec);
+ service.registerPullAtomCallback(atomTag, coolDownNs, timeoutNs, additiveFields,
+ rec);
+ } catch (RemoteException e) {
+ throw new RuntimeException("Unable to register pull callback", e);
+ }
+ }
+ }
+
+ /**
+ * Unregisters a callback for an atom when that atom is to be pulled. Note that any ongoing
+ * pulls will still occur.
+ *
+ * @param atomTag The tag of the atom of which to unregister
+ *
+ * @hide
+ */
+ public void unregisterPullAtomCallback(int atomTag) {
+ synchronized (sLock) {
+ try {
+ IStatsCompanionService service = getIStatsCompanionServiceLocked();
+ service.unregisterPullAtomCallback(atomTag);
+ } catch (RemoteException e) {
+ throw new RuntimeException("Unable to unregister pull atom callback");
+ }
}
}
@@ -540,9 +590,11 @@ public final class StatsManager {
public void onPullAtom(int atomTag, IPullAtomResultReceiver resultReceiver) {
mExecutor.execute(() -> {
List<StatsEvent> data = new ArrayList<>();
- boolean success = mCallback.onPullAtom(atomTag, data);
+ int successInt = mCallback.onPullAtom(atomTag, data);
+ boolean success = successInt == PULL_SUCCESS;
StatsEventParcel[] parcels = new StatsEventParcel[data.size()];
for (int i = 0; i < data.size(); i++) {
+ parcels[i] = new StatsEventParcel();
parcels[i].buffer = data.get(i).getBytes();
}
try {
@@ -635,6 +687,30 @@ public final class StatsManager {
return new PullAtomMetadata(mCoolDownNs, mTimeoutNs, mAdditiveFields);
}
}
+
+ /**
+ * @hide
+ */
+ @VisibleForTesting
+ public long getCoolDownNs() {
+ return mCoolDownNs;
+ }
+
+ /**
+ * @hide
+ */
+ @VisibleForTesting
+ public long getTimeoutNs() {
+ return mTimeoutNs;
+ }
+
+ /**
+ * @hide
+ */
+ @VisibleForTesting
+ public int[] getAdditiveFields() {
+ return mAdditiveFields;
+ }
}
/**
@@ -645,9 +721,9 @@ public final class StatsManager {
public interface StatsPullAtomCallback {
/**
* Pull data for the specified atom tag, filling in the provided list of StatsEvent data.
- * @return if the pull was successful
+ * @return {@link #PULL_SUCCESS} if the pull was successful, or {@link #PULL_SKIP} if not.
*/
- boolean onPullAtom(int atomTag, List<StatsEvent> data);
+ int onPullAtom(int atomTag, List<StatsEvent> data);
}
private class StatsdDeathRecipient implements IBinder.DeathRecipient {
@@ -686,6 +762,16 @@ public final class StatsManager {
return mStatsCompanion;
}
+ @GuardedBy("sLock")
+ private IStatsManagerService getIStatsManagerServiceLocked() {
+ if (mStatsManagerService != null) {
+ return mStatsManagerService;
+ }
+ mStatsManagerService = IStatsManagerService.Stub.asInterface(
+ ServiceManager.getService(Context.STATS_MANAGER_SERVICE));
+ return mStatsManagerService;
+ }
+
/**
* Exception thrown when communication with the stats service fails (eg if it is not available).
* This might be thrown early during boot before the stats service has started or if it crashed.
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index 28413be29a1d..a1765c85d57b 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -23,7 +23,7 @@ import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Binder;
import android.os.IBinder;
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index ce21db335615..31c73b90aace 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -50,6 +50,8 @@ import android.content.ContentCaptureOptions;
import android.content.Context;
import android.content.IRestrictionsManager;
import android.content.RestrictionsManager;
+import android.content.integrity.AppIntegrityManager;
+import android.content.integrity.IAppIntegrityManager;
import android.content.om.IOverlayManager;
import android.content.om.OverlayManager;
import android.content.pm.CrossProfileApps;
@@ -116,12 +118,13 @@ import android.net.NetworkPolicyManager;
import android.net.NetworkScoreManager;
import android.net.NetworkWatchlistManager;
import android.net.TestNetworkManager;
+import android.net.TetheringManager;
import android.net.lowpan.ILowpanManager;
import android.net.lowpan.LowpanManager;
import android.net.nsd.INsdManager;
import android.net.nsd.NsdManager;
-import android.net.wifi.WifiCondManager;
import android.net.wifi.WifiFrameworkInitializer;
+import android.net.wifi.wificond.WifiCondManager;
import android.nfc.NfcManager;
import android.os.BatteryManager;
import android.os.BatteryStats;
@@ -159,6 +162,8 @@ import android.permission.PermissionControllerManager;
import android.permission.PermissionManager;
import android.print.IPrintManager;
import android.print.PrintManager;
+import android.security.FileIntegrityManager;
+import android.security.IFileIntegrityService;
import android.service.oemlock.IOemLockService;
import android.service.oemlock.OemLockManager;
import android.service.persistentdata.IPersistentDataBlockService;
@@ -339,6 +344,17 @@ public final class SystemServiceRegistry {
}
});
+ registerService(Context.TETHERING_SERVICE, TetheringManager.class,
+ new CachedServiceFetcher<TetheringManager>() {
+ @Override
+ public TetheringManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getService(Context.TETHERING_SERVICE);
+ if (b == null) return null;
+
+ return new TetheringManager(ctx, b);
+ }});
+
+
registerService(Context.IPSEC_SERVICE, IpSecManager.class,
new CachedServiceFetcher<IpSecManager>() {
@Override
@@ -1147,14 +1163,6 @@ public final class SystemServiceRegistry {
return new TimeZoneDetector();
}});
- registerService(Context.TELEPHONY_IMS_SERVICE, android.telephony.ims.ImsManager.class,
- new CachedServiceFetcher<android.telephony.ims.ImsManager>() {
- @Override
- public android.telephony.ims.ImsManager createService(ContextImpl ctx) {
- return new android.telephony.ims.ImsManager(ctx.getOuterContext());
- }
- });
-
registerService(Context.PERMISSION_SERVICE, PermissionManager.class,
new CachedServiceFetcher<PermissionManager>() {
@Override
@@ -1208,6 +1216,7 @@ public final class SystemServiceRegistry {
return new DynamicSystemManager(
IDynamicSystemService.Stub.asInterface(b));
}});
+
registerService(Context.BATTERY_STATS_SERVICE, BatteryStatsManager.class,
new CachedServiceFetcher<BatteryStatsManager>() {
@Override
@@ -1241,7 +1250,26 @@ public final class SystemServiceRegistry {
return new IncrementalManager(
IIncrementalManagerNative.Stub.asInterface(b));
}});
+
+ registerService(Context.FILE_INTEGRITY_SERVICE, FileIntegrityManager.class,
+ new CachedServiceFetcher<FileIntegrityManager>() {
+ @Override
+ public FileIntegrityManager createService(ContextImpl ctx)
+ throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(
+ Context.FILE_INTEGRITY_SERVICE);
+ return new FileIntegrityManager(
+ IFileIntegrityService.Stub.asInterface(b));
+ }});
//CHECKSTYLE:ON IndentationCheck
+ registerService(Context.APP_INTEGRITY_SERVICE, AppIntegrityManager.class,
+ new CachedServiceFetcher<AppIntegrityManager>() {
+ @Override
+ public AppIntegrityManager createService(ContextImpl ctx)
+ throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(Context.APP_INTEGRITY_SERVICE);
+ return new AppIntegrityManager(IAppIntegrityManager.Stub.asInterface(b));
+ }});
sInitializing = true;
try {
diff --git a/core/java/android/app/TaskEmbedder.java b/core/java/android/app/TaskEmbedder.java
index e5707bb4a498..93b1ea84adf7 100644
--- a/core/java/android/app/TaskEmbedder.java
+++ b/core/java/android/app/TaskEmbedder.java
@@ -423,7 +423,7 @@ public class TaskEmbedder {
return;
}
reportLocation(mHost.getScreenToTaskMatrix(), mHost.getPositionInWindow());
- applyTapExcludeRegion(mHost.getWindow(), hashCode(), mHost.getTapExcludeRegion());
+ applyTapExcludeRegion(mHost.getWindow(), mHost.getTapExcludeRegion());
}
/**
@@ -458,13 +458,12 @@ public class TaskEmbedder {
* {@link #updateLocationAndTapExcludeRegion()}. This method
* is provided as an optimization when managing multiple TaskSurfaces within a view.
*
- * @see IWindowSession#updateTapExcludeRegion(IWindow, int, Region)
+ * @see IWindowSession#updateTapExcludeRegion(IWindow, Region)
*/
- private void applyTapExcludeRegion(IWindow window, int regionId,
- @Nullable Region tapExcludeRegion) {
+ private void applyTapExcludeRegion(IWindow window, @Nullable Region tapExcludeRegion) {
try {
IWindowSession session = WindowManagerGlobal.getWindowSession();
- session.updateTapExcludeRegion(window, regionId, tapExcludeRegion);
+ session.updateTapExcludeRegion(window, tapExcludeRegion);
} catch (RemoteException e) {
e.rethrowAsRuntimeException();
}
@@ -486,7 +485,7 @@ public class TaskEmbedder {
Log.w(TAG, "clearTapExcludeRegion: not attached to window!");
return;
}
- applyTapExcludeRegion(mHost.getWindow(), hashCode(), null);
+ applyTapExcludeRegion(mHost.getWindow(), null);
}
/**
diff --git a/core/java/android/app/TaskInfo.java b/core/java/android/app/TaskInfo.java
index de64db9def64..fe9c64038909 100644
--- a/core/java/android/app/TaskInfo.java
+++ b/core/java/android/app/TaskInfo.java
@@ -18,7 +18,7 @@ package android.app;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Intent;
import android.content.res.Configuration;
diff --git a/core/java/android/app/TaskStackListener.java b/core/java/android/app/TaskStackListener.java
index 40d10b7d8768..343b3869d354 100644
--- a/core/java/android/app/TaskStackListener.java
+++ b/core/java/android/app/TaskStackListener.java
@@ -16,8 +16,8 @@
package android.app;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager.TaskSnapshot;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.os.Binder;
import android.os.IBinder;
diff --git a/core/java/android/app/TimePickerDialog.java b/core/java/android/app/TimePickerDialog.java
index 1b281d521957..c529297b14db 100644
--- a/core/java/android/app/TimePickerDialog.java
+++ b/core/java/android/app/TimePickerDialog.java
@@ -17,7 +17,7 @@
package android.app;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java
index 13d566c0e04b..18a3e6e89552 100644
--- a/core/java/android/app/UiAutomation.java
+++ b/core/java/android/app/UiAutomation.java
@@ -25,7 +25,7 @@ import android.accessibilityservice.IAccessibilityServiceConnection;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.graphics.Rect;
diff --git a/core/java/android/app/UiAutomationConnection.java b/core/java/android/app/UiAutomationConnection.java
index 1e9bbae91883..82e988109db8 100644
--- a/core/java/android/app/UiAutomationConnection.java
+++ b/core/java/android/app/UiAutomationConnection.java
@@ -19,6 +19,7 @@ package android.app;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.accessibilityservice.IAccessibilityServiceClient;
import android.annotation.Nullable;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Rect;
@@ -40,8 +41,6 @@ import android.view.WindowContentFrameStats;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.IAccessibilityManager;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
import libcore.io.IoUtils;
import java.io.FileInputStream;
diff --git a/core/java/android/app/UiModeManager.java b/core/java/android/app/UiModeManager.java
index d8c030d7aacf..363306483409 100644
--- a/core/java/android/app/UiModeManager.java
+++ b/core/java/android/app/UiModeManager.java
@@ -23,7 +23,7 @@ import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Configuration;
import android.os.RemoteException;
diff --git a/core/java/android/app/UserSwitchObserver.java b/core/java/android/app/UserSwitchObserver.java
index 2f8ee744bfd6..6abc4f09ba38 100644
--- a/core/java/android/app/UserSwitchObserver.java
+++ b/core/java/android/app/UserSwitchObserver.java
@@ -16,7 +16,7 @@
package android.app;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.IRemoteCallback;
import android.os.RemoteException;
diff --git a/core/java/android/app/VrManager.java b/core/java/android/app/VrManager.java
index c74f8c389c20..08a210b069b9 100644
--- a/core/java/android/app/VrManager.java
+++ b/core/java/android/app/VrManager.java
@@ -6,7 +6,7 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.os.RemoteException;
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 41604ec97867..2507991362a5 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -26,13 +26,14 @@ import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
import android.graphics.Bitmap;
@@ -40,6 +41,8 @@ import android.graphics.BitmapFactory;
import android.graphics.BitmapRegionDecoder;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
+import android.graphics.ColorSpace;
+import android.graphics.ImageDecoder;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
@@ -63,11 +66,15 @@ import android.os.SystemProperties;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
+import android.view.Display;
import android.view.WindowManagerGlobal;
+import com.android.internal.R;
+
import libcore.io.IoUtils;
import java.io.BufferedInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
@@ -76,7 +83,10 @@ import java.io.InputStream;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -193,7 +203,13 @@ public class WallpaperManager {
*/
public static final int FLAG_LOCK = 1 << 1;
+ private static final Object sSync = new Object[0];
+ @UnsupportedAppUsage
+ private static Globals sGlobals;
+
private final Context mContext;
+ private final boolean mWcgEnabled;
+ private final ColorManagementProxy mCmProxy;
/**
* Special drawable that draws a wallpaper as fast as possible. Assumes
@@ -388,13 +404,14 @@ public class WallpaperManager {
}
public Bitmap peekWallpaperBitmap(Context context, boolean returnDefault,
- @SetWallpaperFlags int which) {
+ @SetWallpaperFlags int which, ColorManagementProxy cmProxy) {
return peekWallpaperBitmap(context, returnDefault, which, context.getUserId(),
- false /* hardware */);
+ false /* hardware */, cmProxy);
}
public Bitmap peekWallpaperBitmap(Context context, boolean returnDefault,
- @SetWallpaperFlags int which, int userId, boolean hardware) {
+ @SetWallpaperFlags int which, int userId, boolean hardware,
+ ColorManagementProxy cmProxy) {
if (mService != null) {
try {
if (!mService.isWallpaperSupported(context.getOpPackageName())) {
@@ -412,7 +429,8 @@ public class WallpaperManager {
mCachedWallpaper = null;
mCachedWallpaperUserId = 0;
try {
- mCachedWallpaper = getCurrentWallpaperLocked(context, userId, hardware);
+ mCachedWallpaper = getCurrentWallpaperLocked(
+ context, userId, hardware, cmProxy);
mCachedWallpaperUserId = userId;
} catch (OutOfMemoryError e) {
Log.w(TAG, "Out of memory loading the current wallpaper: " + e);
@@ -450,7 +468,8 @@ public class WallpaperManager {
}
}
- private Bitmap getCurrentWallpaperLocked(Context context, int userId, boolean hardware) {
+ private Bitmap getCurrentWallpaperLocked(Context context, int userId, boolean hardware,
+ ColorManagementProxy cmProxy) {
if (mService == null) {
Log.w(TAG, "WallpaperService not running");
return null;
@@ -458,21 +477,29 @@ public class WallpaperManager {
try {
Bundle params = new Bundle();
- ParcelFileDescriptor fd = mService.getWallpaperWithFeature(
+ ParcelFileDescriptor pfd = mService.getWallpaperWithFeature(
context.getOpPackageName(), context.getFeatureId(), this, FLAG_SYSTEM,
params, userId);
- if (fd != null) {
- try {
- BitmapFactory.Options options = new BitmapFactory.Options();
- if (hardware) {
- options.inPreferredConfig = Bitmap.Config.HARDWARE;
+
+ if (pfd != null) {
+ try (BufferedInputStream bis = new BufferedInputStream(
+ new ParcelFileDescriptor.AutoCloseInputStream(pfd))) {
+ final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ int data;
+ while ((data = bis.read()) != -1) {
+ baos.write(data);
}
- return BitmapFactory.decodeFileDescriptor(
- fd.getFileDescriptor(), null, options);
- } catch (OutOfMemoryError e) {
+ ImageDecoder.Source src = ImageDecoder.createSource(baos.toByteArray());
+ return ImageDecoder.decodeBitmap(src, ((decoder, info, source) -> {
+ // Mutable and hardware config can't be set at the same time.
+ decoder.setMutableRequired(!hardware);
+ // Let's do color management
+ if (cmProxy != null) {
+ cmProxy.doColorManagement(decoder, info);
+ }
+ }));
+ } catch (OutOfMemoryError | IOException e) {
Log.w(TAG, "Can't decode file", e);
- } finally {
- IoUtils.closeQuietly(fd);
}
}
} catch (RemoteException e) {
@@ -497,10 +524,6 @@ public class WallpaperManager {
}
}
- private static final Object sSync = new Object[0];
- @UnsupportedAppUsage
- private static Globals sGlobals;
-
static void initGlobals(IWallpaperManager service, Looper looper) {
synchronized (sSync) {
if (sGlobals == null) {
@@ -514,6 +537,10 @@ public class WallpaperManager {
if (service != null) {
initGlobals(service, context.getMainLooper());
}
+ // Check if supports mixed color spaces composition in hardware.
+ mWcgEnabled = context.getResources().getConfiguration().isScreenWideColorGamut()
+ && context.getResources().getBoolean(R.bool.config_enableWcgMode);
+ mCmProxy = new ColorManagementProxy(context);
}
/**
@@ -531,6 +558,22 @@ public class WallpaperManager {
}
/**
+ * Indicate whether wcg (Wide Color Gamut) should be enabled.
+ * <p>
+ * Some devices lack of capability of mixed color spaces composition,
+ * enable wcg on such devices might cause memory or battery concern.
+ * <p>
+ * Therefore, in addition to {@link Configuration#isScreenWideColorGamut()},
+ * we also take mixed color spaces composition (config_enableWcgMode) into account.
+ *
+ * @see Configuration#isScreenWideColorGamut()
+ * @return True if wcg should be enabled for this device.
+ */
+ private boolean shouldEnableWideColorGamut() {
+ return mWcgEnabled;
+ }
+
+ /**
* Retrieve the current system wallpaper; if
* no wallpaper is set, the system built-in static wallpaper is returned.
* This is returned as an
@@ -546,7 +589,7 @@ public class WallpaperManager {
* is not able to access the wallpaper.
*/
public Drawable getDrawable() {
- Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, true, FLAG_SYSTEM);
+ Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, true, FLAG_SYSTEM, mCmProxy);
if (bm != null) {
Drawable dr = new BitmapDrawable(mContext.getResources(), bm);
dr.setDither(false);
@@ -777,7 +820,7 @@ public class WallpaperManager {
* null pointer if these is none.
*/
public Drawable peekDrawable() {
- Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, false, FLAG_SYSTEM);
+ Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, false, FLAG_SYSTEM, mCmProxy);
if (bm != null) {
Drawable dr = new BitmapDrawable(mContext.getResources(), bm);
dr.setDither(false);
@@ -801,7 +844,7 @@ public class WallpaperManager {
*/
@RequiresPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE)
public Drawable getFastDrawable() {
- Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, true, FLAG_SYSTEM);
+ Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, true, FLAG_SYSTEM, mCmProxy);
if (bm != null) {
return new FastBitmapDrawable(bm);
}
@@ -817,7 +860,7 @@ public class WallpaperManager {
*/
@RequiresPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE)
public Drawable peekFastDrawable() {
- Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, false, FLAG_SYSTEM);
+ Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, false, FLAG_SYSTEM, mCmProxy);
if (bm != null) {
return new FastBitmapDrawable(bm);
}
@@ -825,6 +868,27 @@ public class WallpaperManager {
}
/**
+ * Whether the wallpaper supports Wide Color Gamut or not.
+ * @param which The wallpaper whose image file is to be retrieved. Must be a single
+ * defined kind of wallpaper, either {@link #FLAG_SYSTEM} or {@link #FLAG_LOCK}.
+ * @return true when supported.
+ *
+ * @see #FLAG_LOCK
+ * @see #FLAG_SYSTEM
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE)
+ public boolean wallpaperSupportsWcg(int which) {
+ if (!shouldEnableWideColorGamut()) {
+ return false;
+ }
+ Bitmap bitmap = sGlobals.peekWallpaperBitmap(mContext, false, which, mCmProxy);
+ return bitmap != null && bitmap.getColorSpace() != null
+ && bitmap.getColorSpace() != ColorSpace.get(ColorSpace.Named.SRGB)
+ && mCmProxy.isSupportedColorSpace(bitmap.getColorSpace());
+ }
+
+ /**
* Like {@link #getDrawable()} but returns a Bitmap with default {@link Bitmap.Config}.
*
* @hide
@@ -852,7 +916,8 @@ public class WallpaperManager {
* @hide
*/
public Bitmap getBitmapAsUser(int userId, boolean hardware) {
- return sGlobals.peekWallpaperBitmap(mContext, true, FLAG_SYSTEM, userId, hardware);
+ return sGlobals.peekWallpaperBitmap(
+ mContext, true, FLAG_SYSTEM, userId, hardware, mCmProxy);
}
/**
@@ -1975,6 +2040,33 @@ public class WallpaperManager {
return false;
}
+ /**
+ * A private class to help Globals#getCurrentWallpaperLocked handle color management.
+ */
+ private static class ColorManagementProxy {
+ private final Set<ColorSpace> mSupportedColorSpaces = new HashSet<>();
+
+ ColorManagementProxy(Context context) {
+ // Get a list of supported wide gamut color spaces.
+ Display display = context.getDisplay();
+ if (display != null) {
+ mSupportedColorSpaces.addAll(Arrays.asList(display.getSupportedWideColorGamut()));
+ }
+ }
+
+ boolean isSupportedColorSpace(ColorSpace colorSpace) {
+ return colorSpace != null && (colorSpace == ColorSpace.get(ColorSpace.Named.SRGB)
+ || mSupportedColorSpaces.contains(colorSpace));
+ }
+
+ void doColorManagement(ImageDecoder decoder, ImageDecoder.ImageInfo info) {
+ if (!isSupportedColorSpace(info.getColorSpace())) {
+ decoder.setTargetColorSpace(ColorSpace.get(ColorSpace.Named.SRGB));
+ Log.w(TAG, "Not supported color space: " + info.getColorSpace());
+ }
+ }
+ }
+
// Private completion callback for setWallpaper() synchronization
private class WallpaperSetCompletion extends IWallpaperManagerCallback.Stub {
final CountDownLatch mLatch;
diff --git a/core/java/android/app/WindowConfiguration.java b/core/java/android/app/WindowConfiguration.java
index aa6492e9d098..6b40890e17c7 100644
--- a/core/java/android/app/WindowConfiguration.java
+++ b/core/java/android/app/WindowConfiguration.java
@@ -26,6 +26,7 @@ import static android.view.Surface.rotationToString;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.TestApi;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Parcel;
@@ -35,8 +36,6 @@ import android.util.proto.ProtoOutputStream;
import android.util.proto.WireTypeMismatchException;
import android.view.DisplayInfo;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
import java.io.IOException;
/**
@@ -51,7 +50,7 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu
/**
* bounds that can differ from app bounds, which may include things such as insets.
*
- * TODO: Investigate combining with {@link mAppBounds}. Can the latter be a product of the
+ * TODO: Investigate combining with {@link #mAppBounds}. Can the latter be a product of the
* former?
*/
private Rect mBounds = new Rect();
@@ -88,6 +87,7 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu
/** Always on-top (always visible). of other siblings in its parent container. */
public static final int WINDOWING_MODE_PINNED = 2;
/** The primary container driving the screen to be in split-screen mode. */
+ // TODO: Remove once split-screen is migrated to wm-shell.
public static final int WINDOWING_MODE_SPLIT_SCREEN_PRIMARY = 3;
/**
* The containers adjacent to the {@link #WINDOWING_MODE_SPLIT_SCREEN_PRIMARY} container in
@@ -98,6 +98,7 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu
* mode
* @see #WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY
*/
+ // TODO: Remove once split-screen is migrated to wm-shell.
public static final int WINDOWING_MODE_SPLIT_SCREEN_SECONDARY = 4;
/**
* Alias for {@link #WINDOWING_MODE_SPLIT_SCREEN_SECONDARY} that makes it clear that the usage
@@ -105,15 +106,20 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu
* will launch into fullscreen or split-screen secondary depending on if the device is currently
* in fullscreen mode or split-screen mode.
*/
+ // TODO: Remove once split-screen is migrated to wm-shell.
public static final int WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY =
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
/** Can be freely resized within its parent container. */
+ // TODO: Remove once freeform is migrated to wm-shell.
public static final int WINDOWING_MODE_FREEFORM = 5;
+ /** Generic multi-window with no presentation attribution from the window manager. */
+ public static final int WINDOWING_MODE_MULTI_WINDOW = 6;
/** @hide */
@IntDef(prefix = { "WINDOWING_MODE_" }, value = {
WINDOWING_MODE_UNDEFINED,
WINDOWING_MODE_FULLSCREEN,
+ WINDOWING_MODE_MULTI_WINDOW,
WINDOWING_MODE_PINNED,
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY,
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY,
@@ -670,7 +676,7 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu
* @hide
*/
public boolean hasWindowShadow() {
- return tasksAreFloating();
+ return mWindowingMode != WINDOWING_MODE_MULTI_WINDOW && tasksAreFloating();
}
/**
@@ -689,7 +695,8 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu
* @hide
*/
public boolean canResizeTask() {
- return mWindowingMode == WINDOWING_MODE_FREEFORM;
+ return mWindowingMode == WINDOWING_MODE_FREEFORM
+ || mWindowingMode == WINDOWING_MODE_MULTI_WINDOW;
}
/** Returns true if the task bounds should persist across power cycles.
@@ -739,8 +746,9 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu
* @hide
*/
public boolean isAlwaysOnTop() {
- return mWindowingMode == WINDOWING_MODE_PINNED
- || (mWindowingMode == WINDOWING_MODE_FREEFORM && mAlwaysOnTop == ALWAYS_ON_TOP_ON);
+ return mWindowingMode == WINDOWING_MODE_PINNED || (mAlwaysOnTop == ALWAYS_ON_TOP_ON
+ && (mWindowingMode == WINDOWING_MODE_FREEFORM
+ || mWindowingMode == WINDOWING_MODE_MULTI_WINDOW));
}
/**
@@ -798,6 +806,7 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu
switch (windowingMode) {
case WINDOWING_MODE_UNDEFINED: return "undefined";
case WINDOWING_MODE_FULLSCREEN: return "fullscreen";
+ case WINDOWING_MODE_MULTI_WINDOW: return "multi-window";
case WINDOWING_MODE_PINNED: return "pinned";
case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY: return "split-screen-primary";
case WINDOWING_MODE_SPLIT_SCREEN_SECONDARY: return "split-screen-secondary";
diff --git a/core/java/android/app/admin/DeviceAdminInfo.java b/core/java/android/app/admin/DeviceAdminInfo.java
index 63bc40b86aa7..a2f44149e853 100644
--- a/core/java/android/app/admin/DeviceAdminInfo.java
+++ b/core/java/android/app/admin/DeviceAdminInfo.java
@@ -17,7 +17,7 @@
package android.app.admin;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ActivityInfo;
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 7332978852c4..acdf919e66a6 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -33,13 +33,13 @@ import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.UserIdInt;
import android.annotation.WorkerThread;
import android.app.Activity;
import android.app.IServiceConnection;
import android.app.KeyguardManager;
import android.app.admin.SecurityLog.SecurityEvent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -5061,12 +5061,17 @@ public class DevicePolicyManager {
* owner. If Device ID attestation is requested (using {@link #ID_TYPE_SERIAL},
* {@link #ID_TYPE_IMEI} or {@link #ID_TYPE_MEID}), the caller must be the Device Owner
* or the Certificate Installer delegate.
- * @throws IllegalArgumentException if the alias in {@code keySpec} is empty, if the
- * algorithm specification in {@code keySpec} is not {@code RSAKeyGenParameterSpec}
- * or {@code ECGenParameterSpec}, or if Device ID attestation was requested but the
- * {@code keySpec} does not contain an attestation challenge.
- * @throws UnsupportedOperationException if Device ID attestation was requested but the
- * underlying hardware does not support it.
+ * @throws IllegalArgumentException in the following cases:
+ * <p>
+ * <ul>
+ * <li>The alias in {@code keySpec} is empty.</li>
+ * <li>The algorithm specification in {@code keySpec} is not
+ * {@code RSAKeyGenParameterSpec} or {@code ECGenParameterSpec}.</li>
+ * <li>Device ID attestation was requested but the {@code keySpec} does not contain an
+ * attestation challenge.</li>
+ * </ul>
+ * @throws UnsupportedOperationException if Device ID attestation or individual attestation
+ * was requested but the underlying hardware does not support it.
* @throws StrongBoxUnavailableException if the use of StrongBox for key generation was
* specified in {@code keySpec} but the device does not have one.
* @see KeyGenParameterSpec.Builder#setAttestationChallenge(byte[])
@@ -6759,8 +6764,9 @@ public class DevicePolicyManager {
*
* @hide
*/
- public boolean checkDeviceIdentifierAccess(String packageName, int pid, int uid) {
- throwIfParentInstance("checkDeviceIdentifierAccess");
+ @SystemApi
+ public boolean hasDeviceIdentifierAccess(@NonNull String packageName, int pid, int uid) {
+ throwIfParentInstance("hasDeviceIdentifierAccess");
if (packageName == null) {
return false;
}
diff --git a/core/java/android/app/admin/SecurityLog.java b/core/java/android/app/admin/SecurityLog.java
index 972762152d3a..f0b87a8e2561 100644
--- a/core/java/android/app/admin/SecurityLog.java
+++ b/core/java/android/app/admin/SecurityLog.java
@@ -18,7 +18,7 @@ package android.app.admin;
import android.annotation.IntDef;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/app/assist/AssistContent.java b/core/java/android/app/assist/AssistContent.java
index db6ae4f2260a..e5316bc05749 100644
--- a/core/java/android/app/assist/AssistContent.java
+++ b/core/java/android/app/assist/AssistContent.java
@@ -1,6 +1,6 @@
package android.app.assist;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ClipData;
import android.content.Intent;
import android.net.Uri;
diff --git a/core/java/android/app/backup/BackupDataInput.java b/core/java/android/app/backup/BackupDataInput.java
index 2a98ca715a26..d1383c8d0a6a 100644
--- a/core/java/android/app/backup/BackupDataInput.java
+++ b/core/java/android/app/backup/BackupDataInput.java
@@ -17,7 +17,7 @@
package android.app.backup;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import java.io.FileDescriptor;
import java.io.IOException;
diff --git a/core/java/android/app/backup/BackupDataInputStream.java b/core/java/android/app/backup/BackupDataInputStream.java
index 08880665d921..11a3d0c3d725 100644
--- a/core/java/android/app/backup/BackupDataInputStream.java
+++ b/core/java/android/app/backup/BackupDataInputStream.java
@@ -16,9 +16,10 @@
package android.app.backup;
-import android.annotation.UnsupportedAppUsage;
-import java.io.InputStream;
+import android.compat.annotation.UnsupportedAppUsage;
+
import java.io.IOException;
+import java.io.InputStream;
/**
* Provides an {@link java.io.InputStream}-like interface for accessing an
diff --git a/core/java/android/app/backup/BackupDataOutput.java b/core/java/android/app/backup/BackupDataOutput.java
index 01961e78777f..fb161d41acd2 100644
--- a/core/java/android/app/backup/BackupDataOutput.java
+++ b/core/java/android/app/backup/BackupDataOutput.java
@@ -17,7 +17,7 @@
package android.app.backup;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.ParcelFileDescriptor;
import java.io.FileDescriptor;
diff --git a/core/java/android/app/backup/BackupHelperDispatcher.java b/core/java/android/app/backup/BackupHelperDispatcher.java
index e9acdbfb61b9..6faa887206c1 100644
--- a/core/java/android/app/backup/BackupHelperDispatcher.java
+++ b/core/java/android/app/backup/BackupHelperDispatcher.java
@@ -16,7 +16,7 @@
package android.app.backup;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.ParcelFileDescriptor;
import android.util.Log;
diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java
index 93d1e7166708..beb444997fc7 100644
--- a/core/java/android/app/backup/BackupManager.java
+++ b/core/java/android/app/backup/BackupManager.java
@@ -21,7 +21,7 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/app/backup/FileBackupHelperBase.java b/core/java/android/app/backup/FileBackupHelperBase.java
index 0caab983448b..5ad5d0865e56 100644
--- a/core/java/android/app/backup/FileBackupHelperBase.java
+++ b/core/java/android/app/backup/FileBackupHelperBase.java
@@ -16,7 +16,7 @@
package android.app.backup;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.ParcelFileDescriptor;
import android.util.Log;
diff --git a/core/java/android/app/backup/FullBackup.java b/core/java/android/app/backup/FullBackup.java
index 9a595b2da59f..587e883edaf2 100644
--- a/core/java/android/app/backup/FullBackup.java
+++ b/core/java/android/app/backup/FullBackup.java
@@ -16,7 +16,7 @@
package android.app.backup;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.XmlResourceParser;
diff --git a/core/java/android/app/backup/FullBackupDataOutput.java b/core/java/android/app/backup/FullBackupDataOutput.java
index 0ce86534afdd..d8fa0f586b7a 100644
--- a/core/java/android/app/backup/FullBackupDataOutput.java
+++ b/core/java/android/app/backup/FullBackupDataOutput.java
@@ -1,6 +1,6 @@
package android.app.backup;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.ParcelFileDescriptor;
/**
diff --git a/core/java/android/app/role/RoleControllerService.java b/core/java/android/app/role/RoleControllerService.java
index 06623f93552a..d92c95691eea 100644
--- a/core/java/android/app/role/RoleControllerService.java
+++ b/core/java/android/app/role/RoleControllerService.java
@@ -35,6 +35,7 @@ import android.os.UserHandle;
import com.android.internal.util.Preconditions;
import com.android.internal.util.function.pooled.PooledLambda;
+import java.util.Objects;
import java.util.concurrent.Executor;
/**
@@ -82,7 +83,7 @@ public abstract class RoleControllerService extends Service {
public void grantDefaultRoles(RemoteCallback callback) {
enforceCallerSystemUid("grantDefaultRoles");
- Preconditions.checkNotNull(callback, "callback cannot be null");
+ Objects.requireNonNull(callback, "callback cannot be null");
mWorkerHandler.sendMessage(PooledLambda.obtainMessage(
RoleControllerService::grantDefaultRoles, RoleControllerService.this,
@@ -97,7 +98,7 @@ public abstract class RoleControllerService extends Service {
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
Preconditions.checkStringNotEmpty(packageName,
"packageName cannot be null or empty");
- Preconditions.checkNotNull(callback, "callback cannot be null");
+ Objects.requireNonNull(callback, "callback cannot be null");
mWorkerHandler.sendMessage(PooledLambda.obtainMessage(
RoleControllerService::onAddRoleHolder, RoleControllerService.this,
@@ -112,7 +113,7 @@ public abstract class RoleControllerService extends Service {
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
Preconditions.checkStringNotEmpty(packageName,
"packageName cannot be null or empty");
- Preconditions.checkNotNull(callback, "callback cannot be null");
+ Objects.requireNonNull(callback, "callback cannot be null");
mWorkerHandler.sendMessage(PooledLambda.obtainMessage(
RoleControllerService::onRemoveRoleHolder, RoleControllerService.this,
@@ -124,7 +125,7 @@ public abstract class RoleControllerService extends Service {
enforceCallerSystemUid("onClearRoleHolders");
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
- Preconditions.checkNotNull(callback, "callback cannot be null");
+ Objects.requireNonNull(callback, "callback cannot be null");
mWorkerHandler.sendMessage(PooledLambda.obtainMessage(
RoleControllerService::onClearRoleHolders, RoleControllerService.this,
@@ -146,7 +147,7 @@ public abstract class RoleControllerService extends Service {
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
Preconditions.checkStringNotEmpty(packageName,
"packageName cannot be null or empty");
- Preconditions.checkNotNull(callback, "callback cannot be null");
+ Objects.requireNonNull(callback, "callback cannot be null");
boolean qualified = onIsApplicationQualifiedForRole(roleName, packageName);
callback.sendResult(qualified ? Bundle.EMPTY : null);
@@ -160,7 +161,7 @@ public abstract class RoleControllerService extends Service {
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
Preconditions.checkStringNotEmpty(packageName,
"packageName cannot be null or empty");
- Preconditions.checkNotNull(callback, "callback cannot be null");
+ Objects.requireNonNull(callback, "callback cannot be null");
boolean visible = onIsApplicationVisibleForRole(roleName, packageName);
callback.sendResult(visible ? Bundle.EMPTY : null);
@@ -171,7 +172,7 @@ public abstract class RoleControllerService extends Service {
enforceCallingPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, null);
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
- Preconditions.checkNotNull(callback, "callback cannot be null");
+ Objects.requireNonNull(callback, "callback cannot be null");
boolean visible = onIsRoleVisible(roleName);
callback.sendResult(visible ? Bundle.EMPTY : null);
diff --git a/core/java/android/app/role/RoleManager.java b/core/java/android/app/role/RoleManager.java
index bb04a2e52712..61eeacc7fd86 100644
--- a/core/java/android/app/role/RoleManager.java
+++ b/core/java/android/app/role/RoleManager.java
@@ -42,6 +42,7 @@ import com.android.internal.util.Preconditions;
import com.android.internal.util.function.pooled.PooledLambda;
import java.util.List;
+import java.util.Objects;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
@@ -284,7 +285,7 @@ public final class RoleManager {
@TestApi
public List<String> getRoleHoldersAsUser(@NonNull String roleName, @NonNull UserHandle user) {
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
- Preconditions.checkNotNull(user, "user cannot be null");
+ Objects.requireNonNull(user, "user cannot be null");
try {
return mService.getRoleHoldersAsUser(roleName, user.getIdentifier());
} catch (RemoteException e) {
@@ -321,9 +322,9 @@ public final class RoleManager {
@CallbackExecutor @NonNull Executor executor, @NonNull Consumer<Boolean> callback) {
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
- Preconditions.checkNotNull(user, "user cannot be null");
- Preconditions.checkNotNull(executor, "executor cannot be null");
- Preconditions.checkNotNull(callback, "callback cannot be null");
+ Objects.requireNonNull(user, "user cannot be null");
+ Objects.requireNonNull(executor, "executor cannot be null");
+ Objects.requireNonNull(callback, "callback cannot be null");
try {
mService.addRoleHolderAsUser(roleName, packageName, flags, user.getIdentifier(),
createRemoteCallback(executor, callback));
@@ -360,9 +361,9 @@ public final class RoleManager {
@CallbackExecutor @NonNull Executor executor, @NonNull Consumer<Boolean> callback) {
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
- Preconditions.checkNotNull(user, "user cannot be null");
- Preconditions.checkNotNull(executor, "executor cannot be null");
- Preconditions.checkNotNull(callback, "callback cannot be null");
+ Objects.requireNonNull(user, "user cannot be null");
+ Objects.requireNonNull(executor, "executor cannot be null");
+ Objects.requireNonNull(callback, "callback cannot be null");
try {
mService.removeRoleHolderAsUser(roleName, packageName, flags, user.getIdentifier(),
createRemoteCallback(executor, callback));
@@ -397,9 +398,9 @@ public final class RoleManager {
@NonNull UserHandle user, @CallbackExecutor @NonNull Executor executor,
@NonNull Consumer<Boolean> callback) {
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
- Preconditions.checkNotNull(user, "user cannot be null");
- Preconditions.checkNotNull(executor, "executor cannot be null");
- Preconditions.checkNotNull(callback, "callback cannot be null");
+ Objects.requireNonNull(user, "user cannot be null");
+ Objects.requireNonNull(executor, "executor cannot be null");
+ Objects.requireNonNull(callback, "callback cannot be null");
try {
mService.clearRoleHoldersAsUser(roleName, flags, user.getIdentifier(),
createRemoteCallback(executor, callback));
@@ -442,9 +443,9 @@ public final class RoleManager {
@TestApi
public void addOnRoleHoldersChangedListenerAsUser(@CallbackExecutor @NonNull Executor executor,
@NonNull OnRoleHoldersChangedListener listener, @NonNull UserHandle user) {
- Preconditions.checkNotNull(executor, "executor cannot be null");
- Preconditions.checkNotNull(listener, "listener cannot be null");
- Preconditions.checkNotNull(user, "user cannot be null");
+ Objects.requireNonNull(executor, "executor cannot be null");
+ Objects.requireNonNull(listener, "listener cannot be null");
+ Objects.requireNonNull(user, "user cannot be null");
int userId = user.getIdentifier();
synchronized (mListenersLock) {
ArrayMap<OnRoleHoldersChangedListener, OnRoleHoldersChangedListenerDelegate> listeners =
@@ -488,8 +489,8 @@ public final class RoleManager {
@TestApi
public void removeOnRoleHoldersChangedListenerAsUser(
@NonNull OnRoleHoldersChangedListener listener, @NonNull UserHandle user) {
- Preconditions.checkNotNull(listener, "listener cannot be null");
- Preconditions.checkNotNull(user, "user cannot be null");
+ Objects.requireNonNull(listener, "listener cannot be null");
+ Objects.requireNonNull(user, "user cannot be null");
int userId = user.getIdentifier();
synchronized (mListenersLock) {
ArrayMap<OnRoleHoldersChangedListener, OnRoleHoldersChangedListenerDelegate> listeners =
@@ -529,7 +530,7 @@ public final class RoleManager {
@SystemApi
@TestApi
public void setRoleNamesFromController(@NonNull List<String> roleNames) {
- Preconditions.checkNotNull(roleNames, "roleNames cannot be null");
+ Objects.requireNonNull(roleNames, "roleNames cannot be null");
try {
mService.setRoleNamesFromController(roleNames);
} catch (RemoteException e) {
diff --git a/core/java/android/app/servertransaction/ActivityResultItem.java b/core/java/android/app/servertransaction/ActivityResultItem.java
index 52ec3e60a9c7..4e743caccad6 100644
--- a/core/java/android/app/servertransaction/ActivityResultItem.java
+++ b/core/java/android/app/servertransaction/ActivityResultItem.java
@@ -18,9 +18,9 @@ package android.app.servertransaction;
import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
-import android.annotation.UnsupportedAppUsage;
import android.app.ClientTransactionHandler;
import android.app.ResultInfo;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/app/servertransaction/ClientTransaction.java b/core/java/android/app/servertransaction/ClientTransaction.java
index b08e5973faa2..3d044376ee89 100644
--- a/core/java/android/app/servertransaction/ClientTransaction.java
+++ b/core/java/android/app/servertransaction/ClientTransaction.java
@@ -17,9 +17,9 @@
package android.app.servertransaction;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.app.ClientTransactionHandler;
import android.app.IApplicationThread;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
@@ -77,8 +77,9 @@ public class ClientTransaction implements Parcelable, ObjectPoolItem {
/** Get the list of callbacks. */
@Nullable
+ @VisibleForTesting
@UnsupportedAppUsage
- List<ClientTransactionItem> getCallbacks() {
+ public List<ClientTransactionItem> getCallbacks() {
return mActivityCallbacks;
}
diff --git a/core/java/android/app/servertransaction/EnterPipRequestedItem.java b/core/java/android/app/servertransaction/EnterPipRequestedItem.java
new file mode 100644
index 000000000000..b2a1276fa178
--- /dev/null
+++ b/core/java/android/app/servertransaction/EnterPipRequestedItem.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.servertransaction;
+
+import android.app.ClientTransactionHandler;
+import android.os.IBinder;
+import android.os.Parcel;
+
+/**
+ * Request an activity to enter picture-in-picture mode.
+ * @hide
+ */
+public final class EnterPipRequestedItem extends ClientTransactionItem {
+
+ @Override
+ public void execute(ClientTransactionHandler client, IBinder token,
+ PendingTransactionActions pendingActions) {
+ client.handlePictureInPictureRequested(token);
+ }
+
+ // ObjectPoolItem implementation
+
+ private EnterPipRequestedItem() {}
+
+ /** Obtain an instance initialized with provided params. */
+ public static EnterPipRequestedItem obtain() {
+ EnterPipRequestedItem instance = ObjectPool.obtain(EnterPipRequestedItem.class);
+ if (instance == null) {
+ instance = new EnterPipRequestedItem();
+ }
+ return instance;
+ }
+
+ @Override
+ public void recycle() {
+ ObjectPool.recycle(this);
+ }
+
+ // Parcelable implementation
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) { }
+
+ public static final @android.annotation.NonNull Creator<EnterPipRequestedItem> CREATOR =
+ new Creator<EnterPipRequestedItem>() {
+ public EnterPipRequestedItem createFromParcel(Parcel in) {
+ return new EnterPipRequestedItem();
+ }
+
+ public EnterPipRequestedItem[] newArray(int size) {
+ return new EnterPipRequestedItem[size];
+ }
+ };
+
+ @Override
+ public boolean equals(Object o) {
+ return this == o;
+ }
+
+ @Override
+ public String toString() {
+ return "EnterPipRequestedItem{}";
+ }
+}
diff --git a/core/java/android/app/servertransaction/LaunchActivityItem.java b/core/java/android/app/servertransaction/LaunchActivityItem.java
index 1236e0ac7401..6d674ae7df14 100644
--- a/core/java/android/app/servertransaction/LaunchActivityItem.java
+++ b/core/java/android/app/servertransaction/LaunchActivityItem.java
@@ -18,11 +18,11 @@ package android.app.servertransaction;
import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread.ActivityClientRecord;
import android.app.ClientTransactionHandler;
import android.app.ProfilerInfo;
import android.app.ResultInfo;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.CompatibilityInfo;
diff --git a/core/java/android/app/servertransaction/NewIntentItem.java b/core/java/android/app/servertransaction/NewIntentItem.java
index bb775fc4a5fb..6a4996da38ca 100644
--- a/core/java/android/app/servertransaction/NewIntentItem.java
+++ b/core/java/android/app/servertransaction/NewIntentItem.java
@@ -19,8 +19,8 @@ package android.app.servertransaction;
import static android.app.servertransaction.ActivityLifecycleItem.ON_RESUME;
import static android.app.servertransaction.ActivityLifecycleItem.UNDEFINED;
-import android.annotation.UnsupportedAppUsage;
import android.app.ClientTransactionHandler;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/app/trust/TrustManager.java b/core/java/android/app/trust/TrustManager.java
index 27abdcfbefc9..65b2775fd66b 100644
--- a/core/java/android/app/trust/TrustManager.java
+++ b/core/java/android/app/trust/TrustManager.java
@@ -19,7 +19,7 @@ package android.app.trust;
import android.Manifest;
import android.annotation.RequiresPermission;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.hardware.biometrics.BiometricSourceType;
import android.os.Handler;
diff --git a/core/java/android/app/usage/ConfigurationStats.java b/core/java/android/app/usage/ConfigurationStats.java
index da3b76972ced..8a7107de8363 100644
--- a/core/java/android/app/usage/ConfigurationStats.java
+++ b/core/java/android/app/usage/ConfigurationStats.java
@@ -15,7 +15,7 @@
*/
package android.app.usage;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.Configuration;
import android.os.Build;
import android.os.Parcel;
diff --git a/core/java/android/app/usage/IStorageStatsManager.aidl b/core/java/android/app/usage/IStorageStatsManager.aidl
index 7eacc8996bb9..b5036da33a95 100644
--- a/core/java/android/app/usage/IStorageStatsManager.aidl
+++ b/core/java/android/app/usage/IStorageStatsManager.aidl
@@ -18,6 +18,8 @@ package android.app.usage;
import android.app.usage.StorageStats;
import android.app.usage.ExternalStorageStats;
+import android.content.pm.ParceledListSlice;
+import android.os.storage.CrateInfo;
/** {@hide} */
interface IStorageStatsManager {
@@ -31,4 +33,10 @@ interface IStorageStatsManager {
StorageStats queryStatsForUid(String volumeUuid, int uid, String callingPackage);
StorageStats queryStatsForUser(String volumeUuid, int userId, String callingPackage);
ExternalStorageStats queryExternalStatsForUser(String volumeUuid, int userId, String callingPackage);
+ ParceledListSlice /* CrateInfo */ queryCratesForPackage(String volumeUuid, String packageName,
+ int userId, String callingPackage);
+ ParceledListSlice /* CrateInfo */ queryCratesForUid(String volumeUuid, int uid,
+ String callingPackage);
+ ParceledListSlice /* CrateInfo */ queryCratesForUser(String volumeUuid, int userId,
+ String callingPackage);
}
diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java
index 6bade901826a..74129702b487 100644
--- a/core/java/android/app/usage/NetworkStatsManager.java
+++ b/core/java/android/app/usage/NetworkStatsManager.java
@@ -21,8 +21,8 @@ import static com.android.internal.util.Preconditions.checkNotNull;
import android.annotation.Nullable;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.usage.NetworkStats.Bucket;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.DataUsageRequest;
diff --git a/core/java/android/app/usage/StorageStatsManager.java b/core/java/android/app/usage/StorageStatsManager.java
index a86c27a03358..eecf0920fd24 100644
--- a/core/java/android/app/usage/StorageStatsManager.java
+++ b/core/java/android/app/usage/StorageStatsManager.java
@@ -20,6 +20,7 @@ import static android.os.storage.StorageManager.convert;
import android.annotation.BytesLong;
import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
import android.annotation.SystemService;
import android.annotation.TestApi;
import android.annotation.WorkerThread;
@@ -27,15 +28,19 @@ import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.content.pm.ParceledListSlice;
import android.os.ParcelableException;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.os.storage.CrateInfo;
import android.os.storage.StorageManager;
import com.android.internal.util.Preconditions;
import java.io.File;
import java.io.IOException;
+import java.util.Collection;
+import java.util.Objects;
import java.util.UUID;
/**
@@ -347,4 +352,100 @@ public class StorageStatsManager {
throw e.rethrowFromSystemServer();
}
}
+
+ /**
+ * Return all of crate information for the specified storageUuid, packageName, and
+ * userHandle.
+ *
+ * @param storageUuid the UUID of the storage volume you're interested in,
+ * such as {@link StorageManager#UUID_DEFAULT}.
+ * @param uid the uid you're interested in.
+ * @return the collection of crate information.
+ * @throws PackageManager.NameNotFoundException when the package name is not found.
+ * @throws IOException cause by IO, not support, or the other reasons.
+ * @hide
+ */
+ @TestApi
+ @WorkerThread
+ @NonNull
+ public Collection<CrateInfo> queryCratesForUid(@NonNull UUID storageUuid,
+ int uid) throws IOException, PackageManager.NameNotFoundException {
+ try {
+ ParceledListSlice<CrateInfo> crateInfoList =
+ mService.queryCratesForUid(convert(storageUuid), uid,
+ mContext.getOpPackageName());
+ return Objects.requireNonNull(crateInfoList).getList();
+ } catch (ParcelableException e) {
+ e.maybeRethrow(PackageManager.NameNotFoundException.class);
+ e.maybeRethrow(IOException.class);
+ throw new RuntimeException(e);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Return all of crates information for the specified storageUuid, packageName, and
+ * userHandle.
+ *
+ * @param storageUuid the UUID of the storage volume you're interested in,
+ * such as {@link StorageManager#UUID_DEFAULT}.
+ * @param packageName the package name you're interested in.
+ * @param user the user you're interested in.
+ * @return the collection of crate information.
+ * @throws PackageManager.NameNotFoundException when the package name is not found.
+ * @throws IOException cause by IO, not support, or the other reasons.
+ * @hide
+ */
+ @WorkerThread
+ @TestApi
+ @NonNull
+ public Collection<CrateInfo> queryCratesForPackage(@NonNull UUID storageUuid,
+ @NonNull String packageName, @NonNull UserHandle user)
+ throws PackageManager.NameNotFoundException, IOException {
+ try {
+ ParceledListSlice<CrateInfo> crateInfoList =
+ mService.queryCratesForPackage(convert(storageUuid), packageName,
+ user.getIdentifier(), mContext.getOpPackageName());
+ return Objects.requireNonNull(crateInfoList).getList();
+ } catch (ParcelableException e) {
+ e.maybeRethrow(PackageManager.NameNotFoundException.class);
+ e.maybeRethrow(IOException.class);
+ throw new RuntimeException(e);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Return all of crate information for the specified storageUuid, packageName, and
+ * userHandle.
+ *
+ * @param storageUuid the UUID of the storage volume you're interested in,
+ * such as {@link StorageManager#UUID_DEFAULT}.
+ * @param user the user you're interested in.
+ * @return the collection of crate information.
+ * @throws PackageManager.NameNotFoundException when the package name is not found.
+ * @throws IOException cause by IO, not support, or the other reasons.
+ * @hide
+ */
+ @WorkerThread
+ @TestApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_CRATES)
+ @NonNull
+ public Collection<CrateInfo> queryCratesForUser(@NonNull UUID storageUuid,
+ @NonNull UserHandle user) throws PackageManager.NameNotFoundException, IOException {
+ try {
+ ParceledListSlice<CrateInfo> crateInfoList =
+ mService.queryCratesForUser(convert(storageUuid), user.getIdentifier(),
+ mContext.getOpPackageName());
+ return Objects.requireNonNull(crateInfoList).getList();
+ } catch (ParcelableException e) {
+ e.maybeRethrow(PackageManager.NameNotFoundException.class);
+ e.maybeRethrow(IOException.class);
+ throw new RuntimeException(e);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java
index 4bf9c04dfade..d840c1cc7248 100644
--- a/core/java/android/app/usage/UsageEvents.java
+++ b/core/java/android/app/usage/UsageEvents.java
@@ -18,7 +18,7 @@ package android.app.usage;
import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.Configuration;
import android.os.Build;
import android.os.Parcel;
diff --git a/core/java/android/app/usage/UsageStats.java b/core/java/android/app/usage/UsageStats.java
index 9d43dd34d558..d06baed1a35d 100644
--- a/core/java/android/app/usage/UsageStats.java
+++ b/core/java/android/app/usage/UsageStats.java
@@ -29,7 +29,7 @@ import static android.app.usage.UsageEvents.Event.FOREGROUND_SERVICE_STOP;
import static android.app.usage.UsageEvents.Event.ROLLOVER_FOREGROUND_SERVICE;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcel;
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index 419377c9e78b..176a181965ed 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -23,9 +23,9 @@ import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.Activity;
import android.app.PendingIntent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.ParceledListSlice;
import android.os.Build;
diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java
index c20cb253a6be..467b2fba1102 100644
--- a/core/java/android/appwidget/AppWidgetHost.java
+++ b/core/java/android/appwidget/AppWidgetHost.java
@@ -18,8 +18,8 @@ package android.appwidget;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.app.Activity;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.IntentSender;
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index 85f0e2342412..09d56ec70e56 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -16,9 +16,9 @@
package android.appwidget;
-import android.annotation.UnsupportedAppUsage;
import android.app.Activity;
import android.app.ActivityOptions;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.ContextWrapper;
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index dbc1c199cb4d..6dea1c69ce86 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -23,9 +23,9 @@ import android.annotation.RequiresFeature;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
import android.app.IServiceConnection;
import android.app.PendingIntent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/appwidget/AppWidgetProviderInfo.java b/core/java/android/appwidget/AppWidgetProviderInfo.java
index 2faa9007fc29..130a20dfb07b 100644
--- a/core/java/android/appwidget/AppWidgetProviderInfo.java
+++ b/core/java/android/appwidget/AppWidgetProviderInfo.java
@@ -18,8 +18,8 @@ package android.appwidget;
import android.annotation.IntDef;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
import android.app.PendingIntent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ActivityInfo;
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index 64df0e84f6dc..d8c653c6d0d5 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -24,7 +24,7 @@ import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Binder;
import android.os.Build;
diff --git a/core/java/android/bluetooth/BluetoothA2dpSink.java b/core/java/android/bluetooth/BluetoothA2dpSink.java
index c6957e14116b..8993de0939e6 100755
--- a/core/java/android/bluetooth/BluetoothA2dpSink.java
+++ b/core/java/android/bluetooth/BluetoothA2dpSink.java
@@ -21,7 +21,7 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Binder;
import android.os.IBinder;
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 8404705633c3..b1b6f0d61f9f 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -25,7 +25,6 @@ import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
import android.bluetooth.BluetoothProfile.ConnectionPolicy;
import android.bluetooth.le.BluetoothLeAdvertiser;
@@ -36,6 +35,7 @@ import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanRecord;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.BatteryStats;
import android.os.Binder;
diff --git a/core/java/android/bluetooth/BluetoothClass.java b/core/java/android/bluetooth/BluetoothClass.java
index 260e2fb1b80c..905b0ceec4ee 100755
--- a/core/java/android/bluetooth/BluetoothClass.java
+++ b/core/java/android/bluetooth/BluetoothClass.java
@@ -17,7 +17,7 @@
package android.bluetooth;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/bluetooth/BluetoothCodecConfig.java b/core/java/android/bluetooth/BluetoothCodecConfig.java
index 08d0797997b5..93e76fa5ba7d 100644
--- a/core/java/android/bluetooth/BluetoothCodecConfig.java
+++ b/core/java/android/bluetooth/BluetoothCodecConfig.java
@@ -19,7 +19,7 @@ package android.bluetooth;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 323c7d172033..9fe4dd66b874 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -24,7 +24,7 @@ import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Handler;
import android.os.Parcel;
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index d616b8f92d3a..f877f04626da 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -16,7 +16,7 @@
package android.bluetooth;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Handler;
import android.os.ParcelUuid;
diff --git a/core/java/android/bluetooth/BluetoothGattCharacteristic.java b/core/java/android/bluetooth/BluetoothGattCharacteristic.java
index edacf3e0b706..7066f470aa96 100644
--- a/core/java/android/bluetooth/BluetoothGattCharacteristic.java
+++ b/core/java/android/bluetooth/BluetoothGattCharacteristic.java
@@ -15,7 +15,7 @@
*/
package android.bluetooth;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.ParcelUuid;
import android.os.Parcelable;
diff --git a/core/java/android/bluetooth/BluetoothGattDescriptor.java b/core/java/android/bluetooth/BluetoothGattDescriptor.java
index 0783cd2b73cc..7cc2d6bc53fb 100644
--- a/core/java/android/bluetooth/BluetoothGattDescriptor.java
+++ b/core/java/android/bluetooth/BluetoothGattDescriptor.java
@@ -16,7 +16,7 @@
package android.bluetooth;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.ParcelUuid;
import android.os.Parcelable;
diff --git a/core/java/android/bluetooth/BluetoothGattService.java b/core/java/android/bluetooth/BluetoothGattService.java
index c20faf9db698..13d6d7021ec8 100644
--- a/core/java/android/bluetooth/BluetoothGattService.java
+++ b/core/java/android/bluetooth/BluetoothGattService.java
@@ -15,7 +15,7 @@
*/
package android.bluetooth;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.ParcelUuid;
import android.os.Parcelable;
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index 0955b103a8e8..1ba2bb5e31ad 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -23,7 +23,7 @@ import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.os.Binder;
diff --git a/core/java/android/bluetooth/BluetoothHeadsetClient.java b/core/java/android/bluetooth/BluetoothHeadsetClient.java
index 7ee29ff1c50b..6de1ffb6344e 100644
--- a/core/java/android/bluetooth/BluetoothHeadsetClient.java
+++ b/core/java/android/bluetooth/BluetoothHeadsetClient.java
@@ -19,7 +19,7 @@ package android.bluetooth;
import android.Manifest;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Binder;
import android.os.Bundle;
diff --git a/core/java/android/bluetooth/BluetoothHeadsetClientCall.java b/core/java/android/bluetooth/BluetoothHeadsetClientCall.java
index 7165dd56a213..d1a096e605dd 100644
--- a/core/java/android/bluetooth/BluetoothHeadsetClientCall.java
+++ b/core/java/android/bluetooth/BluetoothHeadsetClientCall.java
@@ -16,7 +16,7 @@
package android.bluetooth;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemClock;
diff --git a/core/java/android/bluetooth/BluetoothHearingAid.java b/core/java/android/bluetooth/BluetoothHearingAid.java
index b4521c623ec2..38498bc147b2 100644
--- a/core/java/android/bluetooth/BluetoothHearingAid.java
+++ b/core/java/android/bluetooth/BluetoothHearingAid.java
@@ -23,7 +23,7 @@ import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Binder;
import android.os.IBinder;
@@ -472,63 +472,6 @@ public final class BluetoothHearingAid implements BluetoothProfile {
}
/**
- * Get the volume of the device.
- *
- * <p> The volume is between -128 dB (mute) to 0 dB.
- *
- * @return volume of the hearing aid device.
- * @hide
- */
- @RequiresPermission(Manifest.permission.BLUETOOTH)
- public int getVolume() {
- if (VDBG) {
- log("getVolume()");
- }
- final IBluetoothHearingAid service = getService();
- try {
- if (service != null && isEnabled()) {
- return service.getVolume();
- }
- if (service == null) Log.w(TAG, "Proxy not attached to service");
- return 0;
- } catch (RemoteException e) {
- Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
- return 0;
- }
- }
-
- /**
- * Tells remote device to adjust volume. Uses the following values:
- * <ul>
- * <li>{@link AudioManager#ADJUST_LOWER}</li>
- * <li>{@link AudioManager#ADJUST_RAISE}</li>
- * <li>{@link AudioManager#ADJUST_MUTE}</li>
- * <li>{@link AudioManager#ADJUST_UNMUTE}</li>
- * </ul>
- *
- * @param direction One of the supported adjust values.
- * @hide
- */
- @RequiresPermission(Manifest.permission.BLUETOOTH)
- public void adjustVolume(int direction) {
- if (DBG) log("adjustVolume(" + direction + ")");
-
- final IBluetoothHearingAid service = getService();
- try {
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- return;
- }
-
- if (!isEnabled()) return;
-
- service.adjustVolume(direction);
- } catch (RemoteException e) {
- Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
- }
- }
-
- /**
* Tells remote device to set an absolute volume.
*
* @param volume Absolute volume to be set on remote
diff --git a/core/java/android/bluetooth/BluetoothMap.java b/core/java/android/bluetooth/BluetoothMap.java
index 979dfd4e3ba5..917e7fa04e4c 100644
--- a/core/java/android/bluetooth/BluetoothMap.java
+++ b/core/java/android/bluetooth/BluetoothMap.java
@@ -19,7 +19,7 @@ package android.bluetooth;
import android.Manifest;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Binder;
import android.os.IBinder;
diff --git a/core/java/android/bluetooth/BluetoothMapClient.java b/core/java/android/bluetooth/BluetoothMapClient.java
index 0ec473c85adc..0aa5aac5d8f6 100644
--- a/core/java/android/bluetooth/BluetoothMapClient.java
+++ b/core/java/android/bluetooth/BluetoothMapClient.java
@@ -19,8 +19,8 @@ package android.bluetooth;
import android.Manifest;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.PendingIntent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.net.Uri;
import android.os.Binder;
diff --git a/core/java/android/bluetooth/BluetoothPan.java b/core/java/android/bluetooth/BluetoothPan.java
index 4e9762737c07..42f27f2a9c98 100644
--- a/core/java/android/bluetooth/BluetoothPan.java
+++ b/core/java/android/bluetooth/BluetoothPan.java
@@ -23,7 +23,7 @@ import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Binder;
import android.os.IBinder;
diff --git a/core/java/android/bluetooth/BluetoothPbap.java b/core/java/android/bluetooth/BluetoothPbap.java
index df0289643ee0..c579fdf5048f 100644
--- a/core/java/android/bluetooth/BluetoothPbap.java
+++ b/core/java/android/bluetooth/BluetoothPbap.java
@@ -20,7 +20,7 @@ import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index 097a3677ac4b..638e6de06be7 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -22,7 +22,7 @@ import android.annotation.IntDef;
import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
diff --git a/core/java/android/bluetooth/BluetoothSap.java b/core/java/android/bluetooth/BluetoothSap.java
index 9b4dabcdcfdc..8bf1b588c89a 100644
--- a/core/java/android/bluetooth/BluetoothSap.java
+++ b/core/java/android/bluetooth/BluetoothSap.java
@@ -19,7 +19,7 @@ package android.bluetooth;
import android.Manifest;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Binder;
import android.os.IBinder;
diff --git a/core/java/android/bluetooth/BluetoothServerSocket.java b/core/java/android/bluetooth/BluetoothServerSocket.java
index 3a23808f3617..88c186c88aaf 100644
--- a/core/java/android/bluetooth/BluetoothServerSocket.java
+++ b/core/java/android/bluetooth/BluetoothServerSocket.java
@@ -16,7 +16,7 @@
package android.bluetooth;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Handler;
import android.os.ParcelUuid;
import android.util.Log;
diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java
index 760166bfcc5d..f77436965537 100644
--- a/core/java/android/bluetooth/BluetoothSocket.java
+++ b/core/java/android/bluetooth/BluetoothSocket.java
@@ -16,7 +16,7 @@
package android.bluetooth;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.LocalSocket;
import android.os.ParcelFileDescriptor;
import android.os.ParcelUuid;
diff --git a/core/java/android/bluetooth/BluetoothUuid.java b/core/java/android/bluetooth/BluetoothUuid.java
index 7e96c23af4b9..e274af1b5c5d 100644
--- a/core/java/android/bluetooth/BluetoothUuid.java
+++ b/core/java/android/bluetooth/BluetoothUuid.java
@@ -19,7 +19,7 @@ package android.bluetooth;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.ParcelUuid;
import java.nio.ByteBuffer;
diff --git a/core/java/android/bluetooth/le/ScanRecord.java b/core/java/android/bluetooth/le/ScanRecord.java
index 97e3f5221c72..c0c1aa1634ff 100644
--- a/core/java/android/bluetooth/le/ScanRecord.java
+++ b/core/java/android/bluetooth/le/ScanRecord.java
@@ -18,8 +18,8 @@ package android.bluetooth.le;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.bluetooth.BluetoothUuid;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.ParcelUuid;
import android.util.ArrayMap;
import android.util.Log;
diff --git a/core/java/android/companion/Association.aidl b/core/java/android/companion/Association.aidl
new file mode 100644
index 000000000000..2a28f1f094ad
--- /dev/null
+++ b/core/java/android/companion/Association.aidl
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.companion;
+
+parcelable Association;
diff --git a/core/java/android/companion/Association.java b/core/java/android/companion/Association.java
new file mode 100644
index 000000000000..3fa6a3e76634
--- /dev/null
+++ b/core/java/android/companion/Association.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.companion;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.DataClass;
+
+import java.util.Objects;
+
+/**
+ * A record indicating that a device with a given address was confirmed by the user to be
+ * associated to a given companion app
+ *
+ * @hide
+ */
+@DataClass(genEqualsHashCode = true, genToString = true)
+public class Association implements Parcelable {
+
+ public final int userId;
+ public final @NonNull String deviceAddress;
+ public final @NonNull String companionAppPackage;
+
+
+
+
+ // Code below generated by codegen v1.0.13.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/companion/Association.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ @DataClass.Generated.Member
+ public Association(
+ int userId,
+ @NonNull String deviceAddress,
+ @NonNull String companionAppPackage) {
+ this.userId = userId;
+ this.deviceAddress = deviceAddress;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, deviceAddress);
+ this.companionAppPackage = companionAppPackage;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, companionAppPackage);
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public String toString() {
+ // You can override field toString logic by defining methods like:
+ // String fieldNameToString() { ... }
+
+ return "Association { " +
+ "userId = " + userId + ", " +
+ "deviceAddress = " + deviceAddress + ", " +
+ "companionAppPackage = " + companionAppPackage +
+ " }";
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public boolean equals(@Nullable Object o) {
+ // You can override field equality logic by defining either of the methods like:
+ // boolean fieldNameEquals(Association other) { ... }
+ // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ @SuppressWarnings("unchecked")
+ Association that = (Association) o;
+ //noinspection PointlessBooleanExpression
+ return true
+ && userId == that.userId
+ && Objects.equals(deviceAddress, that.deviceAddress)
+ && Objects.equals(companionAppPackage, that.companionAppPackage);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int hashCode() {
+ // You can override field hashCode logic by defining methods like:
+ // int fieldNameHashCode() { ... }
+
+ int _hash = 1;
+ _hash = 31 * _hash + userId;
+ _hash = 31 * _hash + Objects.hashCode(deviceAddress);
+ _hash = 31 * _hash + Objects.hashCode(companionAppPackage);
+ return _hash;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ dest.writeInt(userId);
+ dest.writeString(deviceAddress);
+ dest.writeString(companionAppPackage);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ @DataClass.Generated.Member
+ protected Association(@NonNull Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ int _userId = in.readInt();
+ String _deviceAddress = in.readString();
+ String _companionAppPackage = in.readString();
+
+ this.userId = _userId;
+ this.deviceAddress = _deviceAddress;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, deviceAddress);
+ this.companionAppPackage = _companionAppPackage;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, companionAppPackage);
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public static final @NonNull Parcelable.Creator<Association> CREATOR
+ = new Parcelable.Creator<Association>() {
+ @Override
+ public Association[] newArray(int size) {
+ return new Association[size];
+ }
+
+ @Override
+ public Association createFromParcel(@NonNull Parcel in) {
+ return new Association(in);
+ }
+ };
+
+ @DataClass.Generated(
+ time = 1573767103332L,
+ codegenVersion = "1.0.13",
+ sourceFile = "frameworks/base/core/java/android/companion/Association.java",
+ inputSignatures = "public final int userId\npublic final @android.annotation.NonNull java.lang.String deviceAddress\npublic final @android.annotation.NonNull java.lang.String companionAppPackage\nclass Association extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true)")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
+}
diff --git a/core/java/android/companion/AssociationRequest.java b/core/java/android/companion/AssociationRequest.java
index ac40150376da..1f57c7d9d2f1 100644
--- a/core/java/android/companion/AssociationRequest.java
+++ b/core/java/android/companion/AssociationRequest.java
@@ -18,7 +18,7 @@ package android.companion;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.provider.OneTimeUseBuilder;
diff --git a/core/java/android/companion/BluetoothDeviceFilter.java b/core/java/android/companion/BluetoothDeviceFilter.java
index fe0123c56e57..2649fbee4246 100644
--- a/core/java/android/companion/BluetoothDeviceFilter.java
+++ b/core/java/android/companion/BluetoothDeviceFilter.java
@@ -25,8 +25,8 @@ import static android.companion.BluetoothDeviceFilterUtils.patternToString;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.bluetooth.BluetoothDevice;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.ParcelUuid;
import android.provider.OneTimeUseBuilder;
diff --git a/core/java/android/companion/BluetoothDeviceFilterUtils.java b/core/java/android/companion/BluetoothDeviceFilterUtils.java
index 0f67f6b50251..24be45cb20fe 100644
--- a/core/java/android/companion/BluetoothDeviceFilterUtils.java
+++ b/core/java/android/companion/BluetoothDeviceFilterUtils.java
@@ -21,9 +21,9 @@ import static android.text.TextUtils.firstNotEmpty;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.le.ScanFilter;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.wifi.ScanResult;
import android.os.ParcelUuid;
import android.os.Parcelable;
diff --git a/core/java/android/companion/BluetoothLeDeviceFilter.java b/core/java/android/companion/BluetoothLeDeviceFilter.java
index 2701619112c5..dccfb0346c9c 100644
--- a/core/java/android/companion/BluetoothLeDeviceFilter.java
+++ b/core/java/android/companion/BluetoothLeDeviceFilter.java
@@ -25,11 +25,11 @@ import static com.android.internal.util.Preconditions.checkState;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanRecord;
import android.bluetooth.le.ScanResult;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.provider.OneTimeUseBuilder;
import android.text.TextUtils;
@@ -340,7 +340,7 @@ public final class BluetoothLeDeviceFilter implements DeviceFilter<ScanResult> {
public Builder setRawDataFilter(@NonNull byte[] rawDataFilter,
@Nullable byte[] rawDataFilterMask) {
checkNotUsed();
- Preconditions.checkNotNull(rawDataFilter);
+ Objects.requireNonNull(rawDataFilter);
checkArgument(rawDataFilterMask == null ||
rawDataFilter.length == rawDataFilterMask.length,
"Mask and filter should be the same length");
diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java
index 28cc1f8fc107..3107c6302775 100644
--- a/core/java/android/companion/CompanionDeviceManager.java
+++ b/core/java/android/companion/CompanionDeviceManager.java
@@ -16,9 +16,6 @@
package android.companion;
-
-import static com.android.internal.util.Preconditions.checkNotNull;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -42,6 +39,7 @@ import android.util.Log;
import java.util.Collections;
import java.util.List;
+import java.util.Objects;
import java.util.function.BiConsumer;
/**
@@ -150,8 +148,8 @@ public final class CompanionDeviceManager {
if (!checkFeaturePresent()) {
return;
}
- checkNotNull(request, "Request cannot be null");
- checkNotNull(callback, "Callback cannot be null");
+ Objects.requireNonNull(request, "Request cannot be null");
+ Objects.requireNonNull(callback, "Callback cannot be null");
try {
mService.associate(
request,
@@ -278,9 +276,9 @@ public final class CompanionDeviceManager {
if (!checkFeaturePresent()) {
return false;
}
- checkNotNull(packageName, "package name cannot be null");
- checkNotNull(macAddress, "mac address cannot be null");
- checkNotNull(user, "user cannot be null");
+ Objects.requireNonNull(packageName, "package name cannot be null");
+ Objects.requireNonNull(macAddress, "mac address cannot be null");
+ Objects.requireNonNull(user, "user cannot be null");
try {
return mService.isDeviceAssociated(
packageName, macAddress.toString(), user.getIdentifier());
diff --git a/core/java/android/companion/DeviceFilter.java b/core/java/android/companion/DeviceFilter.java
index dc7cf82613e6..c9cb072904b4 100644
--- a/core/java/android/companion/DeviceFilter.java
+++ b/core/java/android/companion/DeviceFilter.java
@@ -19,7 +19,7 @@ package android.companion;
import android.annotation.IntDef;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcelable;
import java.lang.annotation.Retention;
diff --git a/core/java/android/companion/ICompanionDeviceDiscoveryService.aidl b/core/java/android/companion/ICompanionDeviceDiscoveryService.aidl
index 5398c3cea68d..5e3d46caae91 100644
--- a/core/java/android/companion/ICompanionDeviceDiscoveryService.aidl
+++ b/core/java/android/companion/ICompanionDeviceDiscoveryService.aidl
@@ -16,9 +16,10 @@
package android.companion;
+import android.companion.Association;
import android.companion.AssociationRequest;
-import android.companion.ICompanionDeviceDiscoveryServiceCallback;
import android.companion.IFindDeviceCallback;
+import com.android.internal.infra.AndroidFuture;
/** @hide */
@@ -27,5 +28,5 @@ interface ICompanionDeviceDiscoveryService {
in AssociationRequest request,
in String callingPackage,
in IFindDeviceCallback findCallback,
- in ICompanionDeviceDiscoveryServiceCallback serviceCallback);
+ in AndroidFuture<Association> serviceCallback);
}
diff --git a/core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl b/core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl
deleted file mode 100644
index c9dc019bd2f2..000000000000
--- a/core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing per missions and
- * limitations under the License.
- */
-
-package android.companion;
-
-/** @hide */
-interface ICompanionDeviceDiscoveryServiceCallback {
- @UnsupportedAppUsage
- oneway void onDeviceSelected(String packageName, int userId, String deviceAddress);
- @UnsupportedAppUsage
- oneway void onDeviceSelectionCancel();
-}
diff --git a/core/java/android/content/AsyncTaskLoader.java b/core/java/android/content/AsyncTaskLoader.java
index bb7d5e49ccfb..14c3387d47dc 100644
--- a/core/java/android/content/AsyncTaskLoader.java
+++ b/core/java/android/content/AsyncTaskLoader.java
@@ -16,7 +16,7 @@
package android.content;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.OperationCanceledException;
diff --git a/core/java/android/content/BroadcastReceiver.java b/core/java/android/content/BroadcastReceiver.java
index f73a376dfc69..1d4d30d87560 100644
--- a/core/java/android/content/BroadcastReceiver.java
+++ b/core/java/android/content/BroadcastReceiver.java
@@ -18,11 +18,11 @@ package android.content;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
import android.app.ActivityThread;
import android.app.IActivityManager;
import android.app.QueuedWork;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
diff --git a/core/java/android/content/ClipData.java b/core/java/android/content/ClipData.java
index 999ec372e9c5..9c806fa286bc 100644
--- a/core/java/android/content/ClipData.java
+++ b/core/java/android/content/ClipData.java
@@ -21,7 +21,7 @@ import static android.content.ContentResolver.SCHEME_ANDROID_RESOURCE;
import static android.content.ContentResolver.SCHEME_CONTENT;
import static android.content.ContentResolver.SCHEME_FILE;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.AssetFileDescriptor;
import android.graphics.Bitmap;
import android.net.Uri;
diff --git a/core/java/android/content/ClipboardManager.java b/core/java/android/content/ClipboardManager.java
index dc1c700f5d08..7f73238a41e3 100644
--- a/core/java/android/content/ClipboardManager.java
+++ b/core/java/android/content/ClipboardManager.java
@@ -19,15 +19,14 @@ package android.content;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Handler;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceManager.ServiceNotFoundException;
-import com.android.internal.util.Preconditions;
-
import java.util.ArrayList;
+import java.util.Objects;
/**
* Interface to the clipboard service, for placing and retrieving text in
@@ -101,7 +100,7 @@ public class ClipboardManager extends android.text.ClipboardManager {
*/
public void setPrimaryClip(@NonNull ClipData clip) {
try {
- Preconditions.checkNotNull(clip);
+ Objects.requireNonNull(clip);
clip.prepareToLeaveProcess(true);
mService.setPrimaryClip(clip, mContext.getOpPackageName(), mContext.getUserId());
} catch (RemoteException e) {
diff --git a/core/java/android/content/ComponentName.java b/core/java/android/content/ComponentName.java
index 33216d74b184..27960b0dd9f0 100644
--- a/core/java/android/content/ComponentName.java
+++ b/core/java/android/content/ComponentName.java
@@ -18,7 +18,7 @@ package android.content;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 2240823ebe92..393d48891d64 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -27,8 +27,8 @@ import static android.os.Trace.TRACE_TAG_DATABASE;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.app.AppOpsManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.PackageManager;
import android.content.pm.PathPermission;
import android.content.pm.ProviderInfo;
diff --git a/core/java/android/content/ContentProviderClient.java b/core/java/android/content/ContentProviderClient.java
index bb65aa013f72..a9b786217eef 100644
--- a/core/java/android/content/ContentProviderClient.java
+++ b/core/java/android/content/ContentProviderClient.java
@@ -22,7 +22,7 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.AssetFileDescriptor;
import android.database.CrossProcessCursorWrapper;
import android.database.Cursor;
@@ -41,7 +41,6 @@ import android.util.Log;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.Preconditions;
import dalvik.system.CloseGuard;
@@ -49,6 +48,7 @@ import libcore.io.IoUtils;
import java.io.FileNotFoundException;
import java.util.ArrayList;
+import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
/**
@@ -184,7 +184,7 @@ public class ContentProviderClient implements ContentInterface, AutoCloseable {
public @Nullable Cursor query(@NonNull Uri uri, @Nullable String[] projection,
Bundle queryArgs, @Nullable CancellationSignal cancellationSignal)
throws RemoteException {
- Preconditions.checkNotNull(uri, "url");
+ Objects.requireNonNull(uri, "url");
beforeRemote();
try {
@@ -213,7 +213,7 @@ public class ContentProviderClient implements ContentInterface, AutoCloseable {
/** See {@link ContentProvider#getType ContentProvider.getType} */
@Override
public @Nullable String getType(@NonNull Uri url) throws RemoteException {
- Preconditions.checkNotNull(url, "url");
+ Objects.requireNonNull(url, "url");
beforeRemote();
try {
@@ -232,8 +232,8 @@ public class ContentProviderClient implements ContentInterface, AutoCloseable {
@Override
public @Nullable String[] getStreamTypes(@NonNull Uri url, @NonNull String mimeTypeFilter)
throws RemoteException {
- Preconditions.checkNotNull(url, "url");
- Preconditions.checkNotNull(mimeTypeFilter, "mimeTypeFilter");
+ Objects.requireNonNull(url, "url");
+ Objects.requireNonNull(mimeTypeFilter, "mimeTypeFilter");
beforeRemote();
try {
@@ -251,7 +251,7 @@ public class ContentProviderClient implements ContentInterface, AutoCloseable {
/** See {@link ContentProvider#canonicalize} */
@Override
public final @Nullable Uri canonicalize(@NonNull Uri url) throws RemoteException {
- Preconditions.checkNotNull(url, "url");
+ Objects.requireNonNull(url, "url");
beforeRemote();
try {
@@ -269,7 +269,7 @@ public class ContentProviderClient implements ContentInterface, AutoCloseable {
/** See {@link ContentProvider#uncanonicalize} */
@Override
public final @Nullable Uri uncanonicalize(@NonNull Uri url) throws RemoteException {
- Preconditions.checkNotNull(url, "url");
+ Objects.requireNonNull(url, "url");
beforeRemote();
try {
@@ -288,7 +288,7 @@ public class ContentProviderClient implements ContentInterface, AutoCloseable {
@Override
public boolean refresh(Uri url, @Nullable Bundle extras,
@Nullable CancellationSignal cancellationSignal) throws RemoteException {
- Preconditions.checkNotNull(url, "url");
+ Objects.requireNonNull(url, "url");
beforeRemote();
try {
@@ -314,7 +314,7 @@ public class ContentProviderClient implements ContentInterface, AutoCloseable {
@Override
public int checkUriPermission(@NonNull Uri uri, int uid, @Intent.AccessUriMode int modeFlags)
throws RemoteException {
- Preconditions.checkNotNull(uri, "uri");
+ Objects.requireNonNull(uri, "uri");
beforeRemote();
try {
@@ -340,7 +340,7 @@ public class ContentProviderClient implements ContentInterface, AutoCloseable {
@Override
public @Nullable Uri insert(@NonNull Uri url, @Nullable ContentValues initialValues,
@Nullable Bundle extras) throws RemoteException {
- Preconditions.checkNotNull(url, "url");
+ Objects.requireNonNull(url, "url");
beforeRemote();
try {
@@ -359,8 +359,8 @@ public class ContentProviderClient implements ContentInterface, AutoCloseable {
@Override
public int bulkInsert(@NonNull Uri url, @NonNull ContentValues[] initialValues)
throws RemoteException {
- Preconditions.checkNotNull(url, "url");
- Preconditions.checkNotNull(initialValues, "initialValues");
+ Objects.requireNonNull(url, "url");
+ Objects.requireNonNull(initialValues, "initialValues");
beforeRemote();
try {
@@ -384,7 +384,7 @@ public class ContentProviderClient implements ContentInterface, AutoCloseable {
/** See {@link ContentProvider#delete ContentProvider.delete} */
@Override
public int delete(@NonNull Uri url, @Nullable Bundle extras) throws RemoteException {
- Preconditions.checkNotNull(url, "url");
+ Objects.requireNonNull(url, "url");
beforeRemote();
try {
@@ -409,7 +409,7 @@ public class ContentProviderClient implements ContentInterface, AutoCloseable {
@Override
public int update(@NonNull Uri url, @Nullable ContentValues values, @Nullable Bundle extras)
throws RemoteException {
- Preconditions.checkNotNull(url, "url");
+ Objects.requireNonNull(url, "url");
beforeRemote();
try {
@@ -446,8 +446,8 @@ public class ContentProviderClient implements ContentInterface, AutoCloseable {
@Override
public @Nullable ParcelFileDescriptor openFile(@NonNull Uri url, @NonNull String mode,
@Nullable CancellationSignal signal) throws RemoteException, FileNotFoundException {
- Preconditions.checkNotNull(url, "url");
- Preconditions.checkNotNull(mode, "mode");
+ Objects.requireNonNull(url, "url");
+ Objects.requireNonNull(mode, "mode");
beforeRemote();
try {
@@ -491,8 +491,8 @@ public class ContentProviderClient implements ContentInterface, AutoCloseable {
@Override
public @Nullable AssetFileDescriptor openAssetFile(@NonNull Uri url, @NonNull String mode,
@Nullable CancellationSignal signal) throws RemoteException, FileNotFoundException {
- Preconditions.checkNotNull(url, "url");
- Preconditions.checkNotNull(mode, "mode");
+ Objects.requireNonNull(url, "url");
+ Objects.requireNonNull(mode, "mode");
beforeRemote();
try {
@@ -532,8 +532,8 @@ public class ContentProviderClient implements ContentInterface, AutoCloseable {
public final @Nullable AssetFileDescriptor openTypedAssetFile(@NonNull Uri uri,
@NonNull String mimeTypeFilter, @Nullable Bundle opts,
@Nullable CancellationSignal signal) throws RemoteException, FileNotFoundException {
- Preconditions.checkNotNull(uri, "uri");
- Preconditions.checkNotNull(mimeTypeFilter, "mimeTypeFilter");
+ Objects.requireNonNull(uri, "uri");
+ Objects.requireNonNull(mimeTypeFilter, "mimeTypeFilter");
beforeRemote();
try {
@@ -567,7 +567,7 @@ public class ContentProviderClient implements ContentInterface, AutoCloseable {
public @NonNull ContentProviderResult[] applyBatch(@NonNull String authority,
@NonNull ArrayList<ContentProviderOperation> operations)
throws RemoteException, OperationApplicationException {
- Preconditions.checkNotNull(operations, "operations");
+ Objects.requireNonNull(operations, "operations");
beforeRemote();
try {
@@ -592,8 +592,8 @@ public class ContentProviderClient implements ContentInterface, AutoCloseable {
@Override
public @Nullable Bundle call(@NonNull String authority, @NonNull String method,
@Nullable String arg, @Nullable Bundle extras) throws RemoteException {
- Preconditions.checkNotNull(authority, "authority");
- Preconditions.checkNotNull(method, "method");
+ Objects.requireNonNull(authority, "authority");
+ Objects.requireNonNull(method, "method");
beforeRemote();
try {
diff --git a/core/java/android/content/ContentProviderNative.java b/core/java/android/content/ContentProviderNative.java
index dfa71f88fa0a..45ace4010961 100644
--- a/core/java/android/content/ContentProviderNative.java
+++ b/core/java/android/content/ContentProviderNative.java
@@ -17,7 +17,7 @@
package android.content;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.AssetFileDescriptor;
import android.database.BulkCursorDescriptor;
import android.database.BulkCursorToCursorAdaptor;
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index d4280f8992c2..1d3c6505f677 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -25,12 +25,12 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.ActivityThread;
import android.app.AppGlobals;
import android.app.UriGrantsManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.AssetFileDescriptor;
@@ -68,7 +68,6 @@ import android.util.Size;
import android.util.SparseArray;
import com.android.internal.util.MimeIconUtils;
-import com.android.internal.util.Preconditions;
import dalvik.system.CloseGuard;
@@ -711,7 +710,7 @@ public abstract class ContentResolver implements ContentInterface {
/** {@hide} */
public static @NonNull ContentResolver wrap(@NonNull ContentInterface wrapped) {
- Preconditions.checkNotNull(wrapped);
+ Objects.requireNonNull(wrapped);
return new ContentResolver(null, wrapped) {
@Override
@@ -796,7 +795,7 @@ public abstract class ContentResolver implements ContentInterface {
*/
@Override
public final @Nullable String getType(@NonNull Uri url) {
- Preconditions.checkNotNull(url, "url");
+ Objects.requireNonNull(url, "url");
try {
if (mWrapped != null) return mWrapped.getType(url);
@@ -856,8 +855,8 @@ public abstract class ContentResolver implements ContentInterface {
*/
@Override
public @Nullable String[] getStreamTypes(@NonNull Uri url, @NonNull String mimeTypeFilter) {
- Preconditions.checkNotNull(url, "url");
- Preconditions.checkNotNull(mimeTypeFilter, "mimeTypeFilter");
+ Objects.requireNonNull(url, "url");
+ Objects.requireNonNull(mimeTypeFilter, "mimeTypeFilter");
try {
if (mWrapped != null) return mWrapped.getStreamTypes(url, mimeTypeFilter);
@@ -998,7 +997,7 @@ public abstract class ContentResolver implements ContentInterface {
public final @Nullable Cursor query(final @RequiresPermission.Read @NonNull Uri uri,
@Nullable String[] projection, @Nullable Bundle queryArgs,
@Nullable CancellationSignal cancellationSignal) {
- Preconditions.checkNotNull(uri, "uri");
+ Objects.requireNonNull(uri, "uri");
try {
if (mWrapped != null) {
@@ -1112,7 +1111,7 @@ public abstract class ContentResolver implements ContentInterface {
*/
@Override
public final @Nullable Uri canonicalize(@NonNull Uri url) {
- Preconditions.checkNotNull(url, "url");
+ Objects.requireNonNull(url, "url");
try {
if (mWrapped != null) return mWrapped.canonicalize(url);
@@ -1156,7 +1155,7 @@ public abstract class ContentResolver implements ContentInterface {
*/
@Override
public final @Nullable Uri uncanonicalize(@NonNull Uri url) {
- Preconditions.checkNotNull(url, "url");
+ Objects.requireNonNull(url, "url");
try {
if (mWrapped != null) return mWrapped.uncanonicalize(url);
@@ -1202,7 +1201,7 @@ public abstract class ContentResolver implements ContentInterface {
@Override
public final boolean refresh(@NonNull Uri url, @Nullable Bundle extras,
@Nullable CancellationSignal cancellationSignal) {
- Preconditions.checkNotNull(url, "url");
+ Objects.requireNonNull(url, "url");
try {
if (mWrapped != null) return mWrapped.refresh(url, extras, cancellationSignal);
@@ -1236,7 +1235,7 @@ public abstract class ContentResolver implements ContentInterface {
/** {@hide} */
@Override
public int checkUriPermission(@NonNull Uri uri, int uid, @Intent.AccessUriMode int modeFlags) {
- Preconditions.checkNotNull(uri, "uri");
+ Objects.requireNonNull(uri, "uri");
try {
if (mWrapped != null) return mWrapped.checkUriPermission(uri, uid, modeFlags);
@@ -1272,7 +1271,7 @@ public abstract class ContentResolver implements ContentInterface {
*/
public final @Nullable InputStream openInputStream(@NonNull Uri uri)
throws FileNotFoundException {
- Preconditions.checkNotNull(uri, "uri");
+ Objects.requireNonNull(uri, "uri");
String scheme = uri.getScheme();
if (SCHEME_ANDROID_RESOURCE.equals(scheme)) {
// Note: left here to avoid breaking compatibility. May be removed
@@ -1579,8 +1578,8 @@ public abstract class ContentResolver implements ContentInterface {
public final @Nullable AssetFileDescriptor openAssetFileDescriptor(@NonNull Uri uri,
@NonNull String mode, @Nullable CancellationSignal cancellationSignal)
throws FileNotFoundException {
- Preconditions.checkNotNull(uri, "uri");
- Preconditions.checkNotNull(mode, "mode");
+ Objects.requireNonNull(uri, "uri");
+ Objects.requireNonNull(mode, "mode");
try {
if (mWrapped != null) return mWrapped.openAssetFile(uri, mode, cancellationSignal);
@@ -1764,8 +1763,8 @@ public abstract class ContentResolver implements ContentInterface {
public final @Nullable AssetFileDescriptor openTypedAssetFileDescriptor(@NonNull Uri uri,
@NonNull String mimeType, @Nullable Bundle opts,
@Nullable CancellationSignal cancellationSignal) throws FileNotFoundException {
- Preconditions.checkNotNull(uri, "uri");
- Preconditions.checkNotNull(mimeType, "mimeType");
+ Objects.requireNonNull(uri, "uri");
+ Objects.requireNonNull(mimeType, "mimeType");
try {
if (mWrapped != null) return mWrapped.openTypedAssetFile(uri, mimeType, opts, cancellationSignal);
@@ -1933,7 +1932,7 @@ public abstract class ContentResolver implements ContentInterface {
@Override
public final @Nullable Uri insert(@RequiresPermission.Write @NonNull Uri url,
@Nullable ContentValues values, @Nullable Bundle extras) {
- Preconditions.checkNotNull(url, "url");
+ Objects.requireNonNull(url, "url");
try {
if (mWrapped != null) return mWrapped.insert(url, values, extras);
@@ -1980,8 +1979,8 @@ public abstract class ContentResolver implements ContentInterface {
public @NonNull ContentProviderResult[] applyBatch(@NonNull String authority,
@NonNull ArrayList<ContentProviderOperation> operations)
throws RemoteException, OperationApplicationException {
- Preconditions.checkNotNull(authority, "authority");
- Preconditions.checkNotNull(operations, "operations");
+ Objects.requireNonNull(authority, "authority");
+ Objects.requireNonNull(operations, "operations");
try {
if (mWrapped != null) return mWrapped.applyBatch(authority, operations);
@@ -2013,8 +2012,8 @@ public abstract class ContentResolver implements ContentInterface {
@Override
public final int bulkInsert(@RequiresPermission.Write @NonNull Uri url,
@NonNull ContentValues[] values) {
- Preconditions.checkNotNull(url, "url");
- Preconditions.checkNotNull(values, "values");
+ Objects.requireNonNull(url, "url");
+ Objects.requireNonNull(values, "values");
try {
if (mWrapped != null) return mWrapped.bulkInsert(url, values);
@@ -2068,7 +2067,7 @@ public abstract class ContentResolver implements ContentInterface {
*/
@Override
public final int delete(@RequiresPermission.Write @NonNull Uri url, @Nullable Bundle extras) {
- Preconditions.checkNotNull(url, "url");
+ Objects.requireNonNull(url, "url");
try {
if (mWrapped != null) return mWrapped.delete(url, extras);
@@ -2130,7 +2129,7 @@ public abstract class ContentResolver implements ContentInterface {
@Override
public final int update(@RequiresPermission.Write @NonNull Uri uri,
@Nullable ContentValues values, @Nullable Bundle extras) {
- Preconditions.checkNotNull(uri, "uri");
+ Objects.requireNonNull(uri, "uri");
try {
if (mWrapped != null) return mWrapped.update(uri, values, extras);
@@ -2179,8 +2178,8 @@ public abstract class ContentResolver implements ContentInterface {
@Override
public final @Nullable Bundle call(@NonNull String authority, @NonNull String method,
@Nullable String arg, @Nullable Bundle extras) {
- Preconditions.checkNotNull(authority, "authority");
- Preconditions.checkNotNull(method, "method");
+ Objects.requireNonNull(authority, "authority");
+ Objects.requireNonNull(method, "method");
try {
if (mWrapped != null) return mWrapped.call(authority, method, arg, extras);
@@ -2297,7 +2296,7 @@ public abstract class ContentResolver implements ContentInterface {
* that services the content at uri or null if there isn't one.
*/
public final @Nullable ContentProviderClient acquireContentProviderClient(@NonNull Uri uri) {
- Preconditions.checkNotNull(uri, "uri");
+ Objects.requireNonNull(uri, "uri");
IContentProvider provider = acquireProvider(uri);
if (provider != null) {
return new ContentProviderClient(this, provider, uri.getAuthority(), true);
@@ -2318,7 +2317,7 @@ public abstract class ContentResolver implements ContentInterface {
*/
public final @Nullable ContentProviderClient acquireContentProviderClient(
@NonNull String name) {
- Preconditions.checkNotNull(name, "name");
+ Objects.requireNonNull(name, "name");
IContentProvider provider = acquireProvider(name);
if (provider != null) {
return new ContentProviderClient(this, provider, name, true);
@@ -2345,7 +2344,7 @@ public abstract class ContentResolver implements ContentInterface {
*/
public final @Nullable ContentProviderClient acquireUnstableContentProviderClient(
@NonNull Uri uri) {
- Preconditions.checkNotNull(uri, "uri");
+ Objects.requireNonNull(uri, "uri");
IContentProvider provider = acquireUnstableProvider(uri);
if (provider != null) {
return new ContentProviderClient(this, provider, uri.getAuthority(), false);
@@ -2372,7 +2371,7 @@ public abstract class ContentResolver implements ContentInterface {
*/
public final @Nullable ContentProviderClient acquireUnstableContentProviderClient(
@NonNull String name) {
- Preconditions.checkNotNull(name, "name");
+ Objects.requireNonNull(name, "name");
IContentProvider provider = acquireUnstableProvider(name);
if (provider != null) {
return new ContentProviderClient(this, provider, name, false);
@@ -2401,8 +2400,8 @@ public abstract class ContentResolver implements ContentInterface {
*/
public final void registerContentObserver(@NonNull Uri uri, boolean notifyForDescendants,
@NonNull ContentObserver observer) {
- Preconditions.checkNotNull(uri, "uri");
- Preconditions.checkNotNull(observer, "observer");
+ Objects.requireNonNull(uri, "uri");
+ Objects.requireNonNull(observer, "observer");
registerContentObserver(
ContentProvider.getUriWithoutUserId(uri),
notifyForDescendants,
@@ -2429,7 +2428,7 @@ public abstract class ContentResolver implements ContentInterface {
* @see #registerContentObserver
*/
public final void unregisterContentObserver(@NonNull ContentObserver observer) {
- Preconditions.checkNotNull(observer, "observer");
+ Objects.requireNonNull(observer, "observer");
try {
IContentObserver contentObserver = observer.releaseContentObserver();
if (contentObserver != null) {
@@ -2523,7 +2522,7 @@ public abstract class ContentResolver implements ContentInterface {
*/
public void notifyChange(@NonNull Uri uri, @Nullable ContentObserver observer,
@NotifyFlags int flags) {
- Preconditions.checkNotNull(uri, "uri");
+ Objects.requireNonNull(uri, "uri");
notifyChange(
ContentProvider.getUriWithoutUserId(uri),
observer,
@@ -2557,7 +2556,7 @@ public abstract class ContentResolver implements ContentInterface {
*/
public void notifyChange(@NonNull Iterable<Uri> uris, @Nullable ContentObserver observer,
@NotifyFlags int flags) {
- Preconditions.checkNotNull(uris, "uris");
+ Objects.requireNonNull(uris, "uris");
// Cluster based on user ID
final SparseArray<ArrayList<Uri>> clusteredByUser = new SparseArray<>();
@@ -2628,7 +2627,7 @@ public abstract class ContentResolver implements ContentInterface {
*/
public void takePersistableUriPermission(@NonNull Uri uri,
@Intent.AccessUriMode int modeFlags) {
- Preconditions.checkNotNull(uri, "uri");
+ Objects.requireNonNull(uri, "uri");
try {
UriGrantsManager.getService().takePersistableUriPermission(
ContentProvider.getUriWithoutUserId(uri), modeFlags, /* toPackage= */ null,
@@ -2644,8 +2643,8 @@ public abstract class ContentResolver implements ContentInterface {
@UnsupportedAppUsage
public void takePersistableUriPermission(@NonNull String toPackage, @NonNull Uri uri,
@Intent.AccessUriMode int modeFlags) {
- Preconditions.checkNotNull(toPackage, "toPackage");
- Preconditions.checkNotNull(uri, "uri");
+ Objects.requireNonNull(toPackage, "toPackage");
+ Objects.requireNonNull(uri, "uri");
try {
UriGrantsManager.getService().takePersistableUriPermission(
ContentProvider.getUriWithoutUserId(uri), modeFlags, toPackage,
@@ -2665,7 +2664,7 @@ public abstract class ContentResolver implements ContentInterface {
*/
public void releasePersistableUriPermission(@NonNull Uri uri,
@Intent.AccessUriMode int modeFlags) {
- Preconditions.checkNotNull(uri, "uri");
+ Objects.requireNonNull(uri, "uri");
try {
UriGrantsManager.getService().releasePersistableUriPermission(
ContentProvider.getUriWithoutUserId(uri), modeFlags, /* toPackage= */ null,
diff --git a/core/java/android/content/ContentValues.java b/core/java/android/content/ContentValues.java
index bdd1f4ce815f..f9f4c5dc0d62 100644
--- a/core/java/android/content/ContentValues.java
+++ b/core/java/android/content/ContentValues.java
@@ -16,9 +16,8 @@
package android.content;
-import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.ArrayMap;
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 24b5061bf27b..4815d7847115 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -32,12 +32,12 @@ import android.annotation.StyleRes;
import android.annotation.StyleableRes;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.IApplicationThread;
import android.app.IServiceConnection;
import android.app.VrManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
@@ -3932,6 +3932,15 @@ public abstract class Context {
public static final String NETWORK_STACK_SERVICE = "network_stack";
/**
+ * Use with {@link android.os.ServiceManager.getService()} to retrieve a
+ * {@link ITetheringConnector} IBinder for communicating with the tethering service
+ * @hide
+ * @see TetheringClient
+ */
+ @SystemApi
+ public static final String TETHERING_SERVICE = "tethering";
+
+ /**
* Use with {@link #getSystemService(String)} to retrieve a
* {@link android.net.IpSecManager} for encrypting Sockets or Networks with
* IPSec.
@@ -4828,6 +4837,12 @@ public abstract class Context {
public static final String INCIDENT_COMPANION_SERVICE = "incidentcompanion";
/**
+ * Service to assist {@link android.app.StatsManager} that lives in system server.
+ * @hide
+ */
+ public static final String STATS_MANAGER_SERVICE = "statsmanager";
+
+ /**
* Service to assist statsd in obtaining general stats.
* @hide
*/
@@ -5030,6 +5045,14 @@ public abstract class Context {
public static final String INCREMENTAL_SERVICE = "incremental_service";
/**
+ * Use with {@link #getSystemService(String)} to retrieve an
+ * {@link android.security.FileIntegrityManager}.
+ * @see #getSystemService(String)
+ * @see android.security.FileIntegrityManager
+ */
+ public static final String FILE_INTEGRITY_SERVICE = "file_integrity";
+
+ /**
* Determine whether the given permission is allowed for a particular
* process and user ID running in the system.
*
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index d1b5135e959d..6fe11873d327 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -21,9 +21,9 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.IApplicationThread;
import android.app.IServiceConnection;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
diff --git a/core/java/android/content/CursorEntityIterator.java b/core/java/android/content/CursorEntityIterator.java
index 2c630d29621b..952366d1cd75 100644
--- a/core/java/android/content/CursorEntityIterator.java
+++ b/core/java/android/content/CursorEntityIterator.java
@@ -16,7 +16,7 @@
package android.content;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.database.Cursor;
import android.os.RemoteException;
diff --git a/core/java/android/content/CursorLoader.java b/core/java/android/content/CursorLoader.java
index 4ccafab741d8..4ff5ccabbcb7 100644
--- a/core/java/android/content/CursorLoader.java
+++ b/core/java/android/content/CursorLoader.java
@@ -16,7 +16,7 @@
package android.content;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.database.Cursor;
import android.net.Uri;
import android.os.CancellationSignal;
diff --git a/core/java/android/content/Entity.java b/core/java/android/content/Entity.java
index ff4f15006280..13137c48e7f2 100644
--- a/core/java/android/content/Entity.java
+++ b/core/java/android/content/Entity.java
@@ -16,7 +16,7 @@
package android.content;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.Uri;
import android.os.Build;
diff --git a/core/java/android/content/IContentProvider.java b/core/java/android/content/IContentProvider.java
index 1fb29586e15b..6f477ff17c67 100644
--- a/core/java/android/content/IContentProvider.java
+++ b/core/java/android/content/IContentProvider.java
@@ -17,7 +17,7 @@
package android.content;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.net.Uri;
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 47fb3759f224..7967708ce19a 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -28,8 +28,8 @@ import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.AppGlobals;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.ComponentInfo;
@@ -11050,6 +11050,7 @@ public class Intent implements Parcelable, Cloneable {
case ACTION_MEDIA_SCANNER_FINISHED:
case ACTION_MEDIA_SCANNER_SCAN_FILE:
case ACTION_PACKAGE_NEEDS_VERIFICATION:
+ case ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION:
case ACTION_PACKAGE_VERIFIED:
case ACTION_PACKAGE_ENABLE_ROLLBACK:
// Ignore legacy actions
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index 93390bd9f750..73c1e2fb9f38 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -18,7 +18,7 @@ package android.content;
import android.annotation.IntDef;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.Uri;
import android.os.Build;
import android.os.Parcel;
diff --git a/core/java/android/content/IntentSender.java b/core/java/android/content/IntentSender.java
index ec0bac486c65..f40dc298d560 100644
--- a/core/java/android/content/IntentSender.java
+++ b/core/java/android/content/IntentSender.java
@@ -16,14 +16,14 @@
package android.content;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Bundle;
-import android.os.RemoteException;
import android.os.Handler;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.RemoteException;
import android.os.UserHandle;
import android.util.AndroidException;
diff --git a/core/java/android/content/RestrictionsManager.java b/core/java/android/content/RestrictionsManager.java
index bbdab048207b..885eb708d92c 100644
--- a/core/java/android/content/RestrictionsManager.java
+++ b/core/java/android/content/RestrictionsManager.java
@@ -17,9 +17,9 @@
package android.content;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
import android.app.Activity;
import android.app.admin.DevicePolicyManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
diff --git a/core/java/android/content/SearchRecentSuggestionsProvider.java b/core/java/android/content/SearchRecentSuggestionsProvider.java
index 8ee7b9e403b4..fc3ddf6148de 100644
--- a/core/java/android/content/SearchRecentSuggestionsProvider.java
+++ b/core/java/android/content/SearchRecentSuggestionsProvider.java
@@ -16,8 +16,8 @@
package android.content;
-import android.annotation.UnsupportedAppUsage;
import android.app.SearchManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
diff --git a/core/java/android/content/SyncAdapterType.java b/core/java/android/content/SyncAdapterType.java
index 8c8fe5a06888..7bcdbfd1085c 100644
--- a/core/java/android/content/SyncAdapterType.java
+++ b/core/java/android/content/SyncAdapterType.java
@@ -17,11 +17,11 @@
package android.content;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
-import android.text.TextUtils;
-import android.os.Parcelable;
import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
/**
* Value type that represents a SyncAdapterType. This object overrides {@link #equals} and
diff --git a/core/java/android/content/SyncAdaptersCache.java b/core/java/android/content/SyncAdaptersCache.java
index d4e52175f9b5..58445a7f9242 100644
--- a/core/java/android/content/SyncAdaptersCache.java
+++ b/core/java/android/content/SyncAdaptersCache.java
@@ -16,7 +16,7 @@
package android.content;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.RegisteredServicesCache;
import android.content.pm.XmlSerializerAndParser;
import android.content.res.Resources;
@@ -29,8 +29,8 @@ import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlSerializer;
import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
import java.io.IOException;
import java.util.ArrayList;
diff --git a/core/java/android/content/SyncContext.java b/core/java/android/content/SyncContext.java
index 50d1dc96fc0a..4a9f66c474db 100644
--- a/core/java/android/content/SyncContext.java
+++ b/core/java/android/content/SyncContext.java
@@ -16,10 +16,10 @@
package android.content;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
+import android.os.IBinder;
import android.os.RemoteException;
import android.os.SystemClock;
-import android.os.IBinder;
public class SyncContext {
private ISyncContext mSyncContext;
diff --git a/core/java/android/content/SyncInfo.java b/core/java/android/content/SyncInfo.java
index d3f2eed8126f..017a92b1e8bb 100644
--- a/core/java/android/content/SyncInfo.java
+++ b/core/java/android/content/SyncInfo.java
@@ -17,7 +17,7 @@
package android.content;
import android.accounts.Account;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/content/SyncRequest.java b/core/java/android/content/SyncRequest.java
index 5f1f18016e0d..9e568a40e0ee 100644
--- a/core/java/android/content/SyncRequest.java
+++ b/core/java/android/content/SyncRequest.java
@@ -17,7 +17,7 @@
package android.content;
import android.accounts.Account;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcel;
diff --git a/core/java/android/content/SyncStatusInfo.java b/core/java/android/content/SyncStatusInfo.java
index 0eea47a248af..b72eb040ea92 100644
--- a/core/java/android/content/SyncStatusInfo.java
+++ b/core/java/android/content/SyncStatusInfo.java
@@ -16,7 +16,7 @@
package android.content;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
diff --git a/core/java/android/content/UndoManager.java b/core/java/android/content/UndoManager.java
index f9c58d624a2f..ed9cd86927ae 100644
--- a/core/java/android/content/UndoManager.java
+++ b/core/java/android/content/UndoManager.java
@@ -16,7 +16,7 @@
package android.content;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.text.TextUtils;
import android.util.ArrayMap;
diff --git a/core/java/android/content/UndoOperation.java b/core/java/android/content/UndoOperation.java
index a425486e5739..235d72123ff6 100644
--- a/core/java/android/content/UndoOperation.java
+++ b/core/java/android/content/UndoOperation.java
@@ -16,7 +16,7 @@
package android.content;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/content/UriMatcher.java b/core/java/android/content/UriMatcher.java
index 208bc01aef9d..7fa48f0e9a78 100644
--- a/core/java/android/content/UriMatcher.java
+++ b/core/java/android/content/UriMatcher.java
@@ -16,7 +16,7 @@
package android.content;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.Uri;
import java.util.ArrayList;
diff --git a/core/java/android/content/integrity/AppInstallMetadata.java b/core/java/android/content/integrity/AppInstallMetadata.java
index c9634758f63f..85af8813fa94 100644
--- a/core/java/android/content/integrity/AppInstallMetadata.java
+++ b/core/java/android/content/integrity/AppInstallMetadata.java
@@ -16,15 +16,14 @@
package android.content.integrity;
-import static com.android.internal.util.Preconditions.checkArgument;
-import static com.android.internal.util.Preconditions.checkNotNull;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import com.android.internal.annotations.VisibleForTesting;
+import java.util.Objects;
+
/**
* The app install metadata.
*
@@ -86,6 +85,19 @@ public final class AppInstallMetadata {
return mIsPreInstalled;
}
+ @Override
+ public String toString() {
+ return String.format(
+ "AppInstallMetadata { PackageName = %s, AppCert = %s, InstallerName = %s,"
+ + " InstallerCert = %s, VersionCode = %d, PreInstalled = %b }",
+ mPackageName,
+ mAppCertificate,
+ mInstallerName == null ? "null" : mInstallerName,
+ mInstallerCertificate == null ? "null" : mInstallerCertificate,
+ mVersionCode,
+ mIsPreInstalled);
+ }
+
/** Builder class for constructing {@link AppInstallMetadata} objects. */
public static final class Builder {
private String mPackageName;
@@ -102,7 +114,7 @@ public final class AppInstallMetadata {
*/
@NonNull
public Builder setPackageName(@NonNull String packageName) {
- this.mPackageName = checkNotNull(packageName);
+ this.mPackageName = Objects.requireNonNull(packageName);
return this;
}
@@ -116,7 +128,7 @@ public final class AppInstallMetadata {
*/
@NonNull
public Builder setAppCertificate(@NonNull String appCertificate) {
- this.mAppCertificate = checkNotNull(appCertificate);
+ this.mAppCertificate = Objects.requireNonNull(appCertificate);
return this;
}
@@ -127,7 +139,7 @@ public final class AppInstallMetadata {
*/
@NonNull
public Builder setInstallerName(@NonNull String installerName) {
- this.mInstallerName = checkNotNull(installerName);
+ this.mInstallerName = Objects.requireNonNull(installerName);
return this;
}
@@ -141,7 +153,7 @@ public final class AppInstallMetadata {
*/
@NonNull
public Builder setInstallerCertificate(@NonNull String installerCertificate) {
- this.mInstallerCertificate = checkNotNull(installerCertificate);
+ this.mInstallerCertificate = Objects.requireNonNull(installerCertificate);
return this;
}
@@ -174,8 +186,8 @@ public final class AppInstallMetadata {
*/
@NonNull
public AppInstallMetadata build() {
- checkArgument(mPackageName != null);
- checkArgument(mAppCertificate != null);
+ Objects.requireNonNull(mPackageName);
+ Objects.requireNonNull(mAppCertificate);
return new AppInstallMetadata(this);
}
}
diff --git a/core/java/android/content/integrity/Rule.java b/core/java/android/content/integrity/Rule.java
index 39a0909321d0..77587851b18c 100644
--- a/core/java/android/content/integrity/Rule.java
+++ b/core/java/android/content/integrity/Rule.java
@@ -17,7 +17,6 @@
package android.content.integrity;
import static com.android.internal.util.Preconditions.checkArgument;
-import static com.android.internal.util.Preconditions.checkNotNull;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -65,7 +64,7 @@ public final class Rule implements Parcelable {
public Rule(@NonNull Formula formula, @Effect int effect) {
checkArgument(isValidEffect(effect), String.format("Unknown effect: %d", effect));
- this.mFormula = checkNotNull(formula);
+ this.mFormula = Objects.requireNonNull(formula);
this.mEffect = effect;
}
diff --git a/core/java/android/content/integrity/RuleSet.java b/core/java/android/content/integrity/RuleSet.java
index a78f8c97d553..b423b54a7d92 100644
--- a/core/java/android/content/integrity/RuleSet.java
+++ b/core/java/android/content/integrity/RuleSet.java
@@ -16,14 +16,13 @@
package android.content.integrity;
-import static com.android.internal.util.Preconditions.checkNotNull;
-
import android.annotation.NonNull;
import android.annotation.SystemApi;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Objects;
/**
* Immutable data class encapsulating all parameters of a rule set.
@@ -85,7 +84,7 @@ public class RuleSet {
*/
@NonNull
public RuleSet build() {
- checkNotNull(mVersion);
+ Objects.requireNonNull(mVersion);
return new RuleSet(mVersion, mRules);
}
}
diff --git a/core/java/android/content/om/OverlayInfo.java b/core/java/android/content/om/OverlayInfo.java
index 1a78f793c008..a3487be3cb81 100644
--- a/core/java/android/content/om/OverlayInfo.java
+++ b/core/java/android/content/om/OverlayInfo.java
@@ -20,8 +20,8 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.UserIdInt;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 26193f6ebb3d..e5daaca4aa52 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -18,7 +18,7 @@ package android.content.pm;
import android.annotation.IntDef;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Intent;
import android.content.res.Configuration;
@@ -290,6 +290,34 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
public int colorMode = COLOR_MODE_DEFAULT;
/**
+ * Indicates whether the activity wants the connected display to do minimal post processing on
+ * the produced image or video frames. This will only be requested if this activity's main
+ * window is visible on the screen.
+ *
+ * <p>This setting should be used when low latency has a higher priority than image enhancement
+ * processing (e.g. for games or video conferencing).
+ *
+ * <p>If the Display sink is connected via HDMI, the device will begin to send infoframes with
+ * Auto Low Latency Mode enabled and Game Content Type. This will switch the connected display
+ * to a minimal image processing mode (if available), which reduces latency, improving the user
+ * experience for gaming or video conferencing applications. For more information, see HDMI 2.1
+ * specification.
+ *
+ * <p>If the Display sink has an internal connection or uses some other protocol than HDMI,
+ * effects may be similar but implementation-defined.
+ *
+ * <p>The ability to switch to a mode with minimal post proessing may be disabled by a user
+ * setting in the system settings menu. In that case, this field is ignored and the display will
+ * remain in its current mode.
+ *
+ * <p>Set from attribute {@link android.R.attr#preferMinimalPostProcessing}.
+ *
+ * @see android.view.WindowManager.LayoutParams#preferMinimalPostProcessing
+ * @see android.view.Display#isMinimalPostProcessingSupported
+ */
+ public boolean preferMinimalPostProcessing = false;
+
+ /**
* Bit in {@link #flags} indicating whether this activity is able to
* run in multiple processes. If
* true, the system may instantiate it in the some process as the
@@ -1004,6 +1032,7 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
requestedVrComponent = orig.requestedVrComponent;
rotationAnimation = orig.rotationAnimation;
colorMode = orig.colorMode;
+ preferMinimalPostProcessing = orig.preferMinimalPostProcessing;
maxAspectRatio = orig.maxAspectRatio;
minAspectRatio = orig.minAspectRatio;
}
@@ -1231,6 +1260,7 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
dest.writeInt(colorMode);
dest.writeFloat(maxAspectRatio);
dest.writeFloat(minAspectRatio);
+ dest.writeBoolean(preferMinimalPostProcessing);
}
/**
@@ -1349,6 +1379,7 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
colorMode = source.readInt();
maxAspectRatio = source.readFloat();
minAspectRatio = source.readFloat();
+ preferMinimalPostProcessing = source.readBoolean();
}
/**
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 552c8ac03071..1aed9772700b 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -22,7 +22,7 @@ import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
diff --git a/core/java/android/content/pm/BaseParceledListSlice.java b/core/java/android/content/pm/BaseParceledListSlice.java
index ffbca1609557..bd847bfdb719 100644
--- a/core/java/android/content/pm/BaseParceledListSlice.java
+++ b/core/java/android/content/pm/BaseParceledListSlice.java
@@ -16,7 +16,7 @@
package android.content.pm;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Binder;
import android.os.IBinder;
import android.os.Parcel;
diff --git a/core/java/android/content/pm/ComponentInfo.java b/core/java/android/content/pm/ComponentInfo.java
index 10f0df7a7c42..8b41c04b3549 100644
--- a/core/java/android/content/pm/ComponentInfo.java
+++ b/core/java/android/content/pm/ComponentInfo.java
@@ -16,7 +16,7 @@
package android.content.pm;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.graphics.drawable.Drawable;
import android.os.Parcel;
diff --git a/core/java/android/content/pm/DataLoaderParams.java b/core/java/android/content/pm/DataLoaderParams.java
new file mode 100644
index 000000000000..60d7bb3c5918
--- /dev/null
+++ b/core/java/android/content/pm/DataLoaderParams.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.content.ComponentName;
+import android.os.ParcelFileDescriptor;
+
+import java.util.Arrays;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * This class represents the parameters used to configure a Data Loader.
+ *
+ * WARNING: This is a system API to aid internal development.
+ * Use at your own risk. It will change or be removed without warning.
+ * @hide
+ */
+@SystemApi
+public class DataLoaderParams {
+ @NonNull
+ private final DataLoaderParamsParcel mData;
+
+ /**
+ * Creates and populates set of Data Loader parameters for Streaming installation.
+ *
+ * @param componentName Data Loader component supporting Streaming installation.
+ * @param arguments free form installation arguments
+ */
+ public static final @NonNull DataLoaderParams forStreaming(@NonNull ComponentName componentName,
+ @NonNull String arguments) {
+ return new DataLoaderParams(DataLoaderType.STREAMING, componentName, arguments, null);
+ }
+
+ /**
+ * Creates and populates set of Data Loader parameters for Incremental installation.
+ *
+ * @param componentName Data Loader component supporting Incremental installation.
+ * @param arguments free form installation arguments
+ * @param namedFds TODO(b/146080380) remove
+ */
+ public static final @NonNull DataLoaderParams forIncremental(
+ @NonNull ComponentName componentName, @NonNull String arguments,
+ @Nullable Map<String, ParcelFileDescriptor> namedFds) {
+ return new DataLoaderParams(DataLoaderType.INCREMENTAL, componentName, arguments, namedFds);
+ }
+
+ /** @hide */
+ public DataLoaderParams(@NonNull @DataLoaderType int type, @NonNull ComponentName componentName,
+ @NonNull String arguments, @Nullable Map<String, ParcelFileDescriptor> namedFds) {
+ DataLoaderParamsParcel data = new DataLoaderParamsParcel();
+ data.type = type;
+ data.packageName = componentName.getPackageName();
+ data.className = componentName.getClassName();
+ data.arguments = arguments;
+ if (namedFds == null || namedFds.isEmpty()) {
+ data.dynamicArgs = new NamedParcelFileDescriptor[0];
+ } else {
+ data.dynamicArgs = new NamedParcelFileDescriptor[namedFds.size()];
+ int i = 0;
+ for (Map.Entry<String, ParcelFileDescriptor> namedFd : namedFds.entrySet()) {
+ data.dynamicArgs[i] = new NamedParcelFileDescriptor();
+ data.dynamicArgs[i].name = namedFd.getKey();
+ data.dynamicArgs[i].fd = namedFd.getValue();
+ i += 1;
+ }
+ }
+ mData = data;
+ }
+
+ /** @hide */
+ DataLoaderParams(@NonNull DataLoaderParamsParcel data) {
+ mData = data;
+ }
+
+ /** @hide */
+ public final @NonNull DataLoaderParamsParcel getData() {
+ return mData;
+ }
+
+ /**
+ * @return data loader type
+ */
+ public final @NonNull @DataLoaderType int getType() {
+ return mData.type;
+ }
+
+ /**
+ * @return data loader's component name
+ */
+ public final @NonNull ComponentName getComponentName() {
+ return new ComponentName(mData.packageName, mData.className);
+ }
+
+ /**
+ * @return data loader's arguments
+ */
+ public final @NonNull String getArguments() {
+ return mData.arguments;
+ }
+
+ /**
+ * @return data loader's dynamic arguments such as file descriptors TODO: remove
+ */
+ public final @NonNull Map<String, ParcelFileDescriptor> getDynamicArgs() {
+ return Arrays.stream(mData.dynamicArgs).collect(
+ Collectors.toMap(p -> p.name, p -> p.fd));
+ }
+}
diff --git a/core/java/android/os/incremental/IncrementalDataLoaderParamsParcel.aidl b/core/java/android/content/pm/DataLoaderParamsParcel.aidl
index cd988dcace5b..e05843b4d4e9 100644
--- a/core/java/android/os/incremental/IncrementalDataLoaderParamsParcel.aidl
+++ b/core/java/android/content/pm/DataLoaderParamsParcel.aidl
@@ -14,16 +14,19 @@
* limitations under the License.
*/
-package android.os.incremental;
+package android.content.pm;
-import android.os.incremental.NamedParcelFileDescriptor;
+import android.content.pm.DataLoaderType;
+import android.content.pm.NamedParcelFileDescriptor;
/**
* Class for holding data loader configuration parameters.
* @hide
*/
-parcelable IncrementalDataLoaderParamsParcel {
+parcelable DataLoaderParamsParcel {
+ DataLoaderType type;
@utf8InCpp String packageName;
- @utf8InCpp String staticArgs;
+ @utf8InCpp String className;
+ @utf8InCpp String arguments;
NamedParcelFileDescriptor[] dynamicArgs;
}
diff --git a/core/java/android/content/pm/DataLoaderType.aidl b/core/java/android/content/pm/DataLoaderType.aidl
new file mode 100644
index 000000000000..7d726f5ddd6f
--- /dev/null
+++ b/core/java/android/content/pm/DataLoaderType.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+/**
+ * Types of Data Loader for an installation session.
+ * @hide
+ */
+@Backing(type="int")
+enum DataLoaderType {
+ /**
+ * Default value, legacy installation.
+ */
+ NONE = 0,
+ /**
+ * Streaming installation using data loader.
+ */
+ STREAMING = 1,
+ /**
+ * Streaming installation using Incremental FileSystem.
+ */
+ INCREMENTAL = 2,
+}
diff --git a/core/java/android/content/pm/FileSystemControlParcel.aidl b/core/java/android/content/pm/FileSystemControlParcel.aidl
new file mode 100644
index 000000000000..f00feaeb2f5a
--- /dev/null
+++ b/core/java/android/content/pm/FileSystemControlParcel.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+import android.content.pm.IPackageInstallerSessionFileSystemConnector;
+import android.os.incremental.IncrementalFileSystemControlParcel;
+
+/**
+ * Wraps info needed for DataLoader to provide data.
+ * @hide
+ */
+parcelable FileSystemControlParcel {
+ // Incremental FS control descriptors.
+ @nullable IncrementalFileSystemControlParcel incremental;
+ // Callback-based installation connector.
+ @nullable IPackageInstallerSessionFileSystemConnector callback;
+}
diff --git a/core/java/android/content/pm/IDataLoader.aidl b/core/java/android/content/pm/IDataLoader.aidl
index 60cc9ba9e141..b5baa9379d16 100644
--- a/core/java/android/content/pm/IDataLoader.aidl
+++ b/core/java/android/content/pm/IDataLoader.aidl
@@ -27,8 +27,9 @@ import java.util.List;
*/
oneway interface IDataLoader {
void create(int id, in Bundle params, IDataLoaderStatusListener listener);
- void start(in List<InstallationFile> fileInfos);
+ void start();
void stop();
void destroy();
- void onFileCreated(long inode, in byte[] metadata);
+
+ void prepareImage(in List<InstallationFile> addedFiles, in List<String> removedFiles);
}
diff --git a/core/java/android/content/pm/IDataLoaderStatusListener.aidl b/core/java/android/content/pm/IDataLoaderStatusListener.aidl
index a60d6ee2d28a..5011faafa2f7 100644
--- a/core/java/android/content/pm/IDataLoaderStatusListener.aidl
+++ b/core/java/android/content/pm/IDataLoaderStatusListener.aidl
@@ -22,13 +22,18 @@ package android.content.pm;
*/
oneway interface IDataLoaderStatusListener {
/** Data loader status */
- const int DATA_LOADER_READY = 0;
- const int DATA_LOADER_NOT_READY = 1;
- const int DATA_LOADER_RUNNING = 2;
+ const int DATA_LOADER_CREATED = 0;
+ const int DATA_LOADER_DESTROYED = 1;
+
+ const int DATA_LOADER_STARTED = 2;
const int DATA_LOADER_STOPPED = 3;
- const int DATA_LOADER_SLOW_CONNECTION = 4;
- const int DATA_LOADER_NO_CONNECTION = 5;
- const int DATA_LOADER_CONNECTION_OK = 6;
+
+ const int DATA_LOADER_IMAGE_READY = 4;
+ const int DATA_LOADER_IMAGE_NOT_READY = 5;
+
+ const int DATA_LOADER_SLOW_CONNECTION = 6;
+ const int DATA_LOADER_NO_CONNECTION = 7;
+ const int DATA_LOADER_CONNECTION_OK = 8;
/** Data loader status callback */
void onStatusChanged(in int dataLoaderId, in int status);
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/BgHandler.java b/core/java/android/content/pm/IPackageInstallerSessionFileSystemConnector.aidl
index bc6b83ba1def..4b2f29e5ae78 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/BgHandler.java
+++ b/core/java/android/content/pm/IPackageInstallerSessionFileSystemConnector.aidl
@@ -14,17 +14,11 @@
* limitations under the License.
*/
-package com.android.systemui.dagger.qualifiers;
+package android.content.pm;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import android.os.ParcelFileDescriptor;
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-
-import javax.inject.Qualifier;
-
-@Qualifier
-@Documented
-@Retention(RUNTIME)
-public @interface BgHandler {
+/** {@hide} */
+interface IPackageInstallerSessionFileSystemConnector {
+ void writeData(String name, long offsetBytes, long lengthBytes, in ParcelFileDescriptor fd);
}
diff --git a/core/java/android/content/pm/LauncherActivityInfo.java b/core/java/android/content/pm/LauncherActivityInfo.java
index 1451431b7852..67deb82f1fbb 100644
--- a/core/java/android/content/pm/LauncherActivityInfo.java
+++ b/core/java/android/content/pm/LauncherActivityInfo.java
@@ -16,7 +16,7 @@
package android.content.pm;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager.NameNotFoundException;
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index d2a40304e078..ed958b118650 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -25,10 +25,10 @@ import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
@@ -62,8 +62,6 @@ import android.os.UserManager;
import android.util.DisplayMetrics;
import android.util.Log;
-import com.android.internal.util.Preconditions;
-
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -72,6 +70,7 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
+import java.util.Objects;
import java.util.concurrent.Executor;
/**
@@ -766,8 +765,8 @@ public class LauncherApps {
*/
public boolean shouldHideFromSuggestions(@NonNull String packageName,
@NonNull UserHandle user) {
- Preconditions.checkNotNull(packageName, "packageName");
- Preconditions.checkNotNull(user, "user");
+ Objects.requireNonNull(packageName, "packageName");
+ Objects.requireNonNull(user, "user");
try {
return mService.shouldHideFromSuggestions(packageName, user);
} catch (RemoteException re) {
@@ -789,8 +788,8 @@ public class LauncherApps {
public ApplicationInfo getApplicationInfo(@NonNull String packageName,
@ApplicationInfoFlags int flags, @NonNull UserHandle user)
throws PackageManager.NameNotFoundException {
- Preconditions.checkNotNull(packageName, "packageName");
- Preconditions.checkNotNull(user, "user");
+ Objects.requireNonNull(packageName, "packageName");
+ Objects.requireNonNull(user, "user");
logErrorForInvalidProfileAccess(user);
try {
final ApplicationInfo ai = mService
diff --git a/core/java/android/os/incremental/NamedParcelFileDescriptor.aidl b/core/java/android/content/pm/NamedParcelFileDescriptor.aidl
index 038ced1744a1..68dd5f54654b 100644
--- a/core/java/android/os/incremental/NamedParcelFileDescriptor.aidl
+++ b/core/java/android/content/pm/NamedParcelFileDescriptor.aidl
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.os.incremental;
+package android.content.pm;
import android.os.ParcelFileDescriptor;
diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java
index aa0002df2c3a..36fa5728b34e 100644
--- a/core/java/android/content/pm/PackageInfo.java
+++ b/core/java/android/content/pm/PackageInfo.java
@@ -17,7 +17,7 @@
package android.content.pm;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/content/pm/PackageInfoLite.java b/core/java/android/content/pm/PackageInfoLite.java
index f5442ec48d19..6743a3f86944 100644
--- a/core/java/android/content/pm/PackageInfoLite.java
+++ b/core/java/android/content/pm/PackageInfoLite.java
@@ -16,7 +16,7 @@
package android.content.pm;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 898631e9a3b1..7a280221eb08 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -26,9 +26,9 @@ import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
import android.app.AppGlobals;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.IIntentReceiver;
import android.content.IIntentSender;
import android.content.Intent;
@@ -50,15 +50,12 @@ import android.os.ParcelableException;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.os.UserHandle;
-import android.os.incremental.IncrementalDataLoaderParams;
-import android.os.incremental.IncrementalDataLoaderParamsParcel;
import android.system.ErrnoException;
import android.system.Os;
import android.util.ArraySet;
import android.util.ExceptionUtils;
import com.android.internal.util.IndentingPrintWriter;
-import com.android.internal.util.Preconditions;
import com.android.internal.util.function.pooled.PooledLambda;
import java.io.Closeable;
@@ -72,6 +69,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
+import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
@@ -636,7 +634,7 @@ public class PackageInstaller {
Manifest.permission.REQUEST_DELETE_PACKAGES})
public void uninstall(@NonNull VersionedPackage versionedPackage, @DeleteFlags int flags,
@NonNull IntentSender statusReceiver) {
- Preconditions.checkNotNull(versionedPackage, "versionedPackage cannot be null");
+ Objects.requireNonNull(versionedPackage, "versionedPackage cannot be null");
try {
mInstaller.uninstall(versionedPackage, mInstallerPackageName,
flags, statusReceiver, mUserId);
@@ -663,7 +661,7 @@ public class PackageInstaller {
public void installExistingPackage(@NonNull String packageName,
@InstallReason int installReason,
@Nullable IntentSender statusReceiver) {
- Preconditions.checkNotNull(packageName, "packageName cannot be null");
+ Objects.requireNonNull(packageName, "packageName cannot be null");
try {
mInstaller.installExistingPackage(packageName,
PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS, installReason,
@@ -1084,8 +1082,12 @@ public class PackageInstaller {
* @throws SecurityException if called after the session has been
* sealed or abandoned
* @throws IllegalStateException if called for non-callback session
+ *
+ * WARNING: This is a system API to aid internal development.
+ * Use at your own risk. It will change or be removed without warning.
* {@hide}
*/
+ @SystemApi
public void addFile(@NonNull String name, long lengthBytes, @NonNull byte[] metadata) {
try {
mSession.addFile(name, lengthBytes, metadata);
@@ -1200,8 +1202,8 @@ public class PackageInstaller {
*/
public void transfer(@NonNull String packageName, @NonNull IntentSender statusReceiver)
throws PackageManager.NameNotFoundException {
- Preconditions.checkNotNull(statusReceiver);
- Preconditions.checkNotNull(packageName);
+ Objects.requireNonNull(statusReceiver);
+ Objects.requireNonNull(packageName);
try {
mSession.transfer(packageName, statusReceiver);
@@ -1229,7 +1231,7 @@ public class PackageInstaller {
*/
public void transfer(@NonNull String packageName)
throws PackageManager.NameNotFoundException {
- Preconditions.checkNotNull(packageName);
+ Objects.requireNonNull(packageName);
CompletableFuture<Intent> intentFuture = new CompletableFuture<Intent>();
try {
@@ -1459,10 +1461,9 @@ public class PackageInstaller {
/** {@hide} */
public long requiredInstalledVersionCode = PackageManager.VERSION_CODE_HIGHEST;
/** {@hide} */
- public IncrementalDataLoaderParams incrementalParams;
- /** TODO(b/146080380): add a class name to make it fully compatible with ComponentName.
- * {@hide} */
- public String dataLoaderPackageName;
+ public DataLoaderParams dataLoaderParams;
+ /** {@hide} */
+ public int rollbackDataPolicy = PackageManager.RollbackDataPolicy.RESTORE;
/**
* Construct parameters for a new package install session.
@@ -1496,13 +1497,12 @@ public class PackageInstaller {
isMultiPackage = source.readBoolean();
isStaged = source.readBoolean();
requiredInstalledVersionCode = source.readLong();
- IncrementalDataLoaderParamsParcel dataLoaderParamsParcel = source.readParcelable(
- IncrementalDataLoaderParamsParcel.class.getClassLoader());
+ DataLoaderParamsParcel dataLoaderParamsParcel = source.readParcelable(
+ DataLoaderParamsParcel.class.getClassLoader());
if (dataLoaderParamsParcel != null) {
- incrementalParams = new IncrementalDataLoaderParams(
- dataLoaderParamsParcel);
+ dataLoaderParams = new DataLoaderParams(dataLoaderParamsParcel);
}
- dataLoaderPackageName = source.readString();
+ rollbackDataPolicy = source.readInt();
}
/** {@hide} */
@@ -1526,8 +1526,8 @@ public class PackageInstaller {
ret.isMultiPackage = isMultiPackage;
ret.isStaged = isStaged;
ret.requiredInstalledVersionCode = requiredInstalledVersionCode;
- ret.incrementalParams = incrementalParams;
- ret.dataLoaderPackageName = dataLoaderPackageName;
+ ret.dataLoaderParams = dataLoaderParams;
+ ret.rollbackDataPolicy = rollbackDataPolicy;
return ret;
}
@@ -1684,12 +1684,14 @@ public class PackageInstaller {
}
/**
- * Request that rollbacks be enabled or disabled for the given upgrade.
+ * Request that rollbacks be enabled or disabled for the given upgrade with rollback data
+ * policy set to RESTORE.
*
* <p>If the parent session is staged or has rollback enabled, all children sessions
* must have the same properties.
*
* @param enable set to {@code true} to enable, {@code false} to disable
+ * @see SessionParams#setEnableRollback(boolean, int)
* @hide
*/
@SystemApi @TestApi
@@ -1699,8 +1701,35 @@ public class PackageInstaller {
} else {
installFlags &= ~PackageManager.INSTALL_ENABLE_ROLLBACK;
}
+ rollbackDataPolicy = PackageManager.RollbackDataPolicy.RESTORE;
+ }
+
+ /**
+ * Request that rollbacks be enabled or disabled for the given upgrade.
+ *
+ * <p>If the parent session is staged or has rollback enabled, all children sessions
+ * must have the same properties.
+ *
+ * <p> For a multi-package install, this method must be called on each child session to
+ * specify rollback data policies explicitly. Note each child session is allowed to have
+ * different policies.
+ *
+ * @param enable set to {@code true} to enable, {@code false} to disable
+ * @param dataPolicy the rollback data policy for this session
+ * @hide
+ */
+ @SystemApi @TestApi
+ public void setEnableRollback(boolean enable,
+ @PackageManager.RollbackDataPolicy int dataPolicy) {
+ if (enable) {
+ installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK;
+ } else {
+ installFlags &= ~PackageManager.INSTALL_ENABLE_ROLLBACK;
+ }
+ rollbackDataPolicy = dataPolicy;
}
+
/**
* @deprecated use {@link #setRequestDowngrade(boolean)}.
* {@hide}
@@ -1858,27 +1887,18 @@ public class PackageInstaller {
}
/**
- * Set Incremental data loader params.
- *
- * {@hide}
- */
- @RequiresPermission(Manifest.permission.INSTALL_PACKAGES)
- public void setIncrementalParams(@NonNull IncrementalDataLoaderParams incrementalParams) {
- this.incrementalParams = incrementalParams;
- }
-
- /**
- * Set the data provider params for the session.
- * This also switches installation into callback mode and disallow direct writes into
+ * Set the data loader params for the session.
+ * This also switches installation into data provider mode and disallow direct writes into
* staging folder.
- * TODO(b/146080380): unify dataprovider params with Incremental.
*
- * @param dataLoaderPackageName name of the dataLoader package
+ * WARNING: This is a system API to aid internal development.
+ * Use at your own risk. It will change or be removed without warning.
* {@hide}
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.INSTALL_PACKAGES)
- public void setDataLoaderPackageName(String dataLoaderPackageName) {
- this.dataLoaderPackageName = dataLoaderPackageName;
+ public void setDataLoaderParams(@NonNull DataLoaderParams dataLoaderParams) {
+ this.dataLoaderParams = dataLoaderParams;
}
/** {@hide} */
@@ -1901,7 +1921,8 @@ public class PackageInstaller {
pw.printPair("isMultiPackage", isMultiPackage);
pw.printPair("isStaged", isStaged);
pw.printPair("requiredInstalledVersionCode", requiredInstalledVersionCode);
- pw.printPair("dataLoaderPackageName", dataLoaderPackageName);
+ pw.printPair("dataLoaderParams", dataLoaderParams);
+ pw.printPair("rollbackDataPolicy", rollbackDataPolicy);
pw.println();
}
@@ -1931,12 +1952,12 @@ public class PackageInstaller {
dest.writeBoolean(isMultiPackage);
dest.writeBoolean(isStaged);
dest.writeLong(requiredInstalledVersionCode);
- if (incrementalParams != null) {
- dest.writeParcelable(incrementalParams.getData(), flags);
+ if (dataLoaderParams != null) {
+ dest.writeParcelable(dataLoaderParams.getData(), flags);
} else {
dest.writeParcelable(null, flags);
}
- dest.writeString(dataLoaderPackageName);
+ dest.writeInt(rollbackDataPolicy);
}
public static final Parcelable.Creator<SessionParams>
@@ -2074,6 +2095,9 @@ public class PackageInstaller {
public long updatedMillis;
/** {@hide} */
+ public int rollbackDataPolicy;
+
+ /** {@hide} */
@UnsupportedAppUsage
public SessionInfo() {
}
@@ -2116,6 +2140,7 @@ public class PackageInstaller {
mStagedSessionErrorCode = source.readInt();
mStagedSessionErrorMessage = source.readString();
isCommitted = source.readBoolean();
+ rollbackDataPolicy = source.readInt();
}
/**
@@ -2433,6 +2458,17 @@ public class PackageInstaller {
}
/**
+ * Return the data policy associated with the rollback for the given upgrade.
+ *
+ * @hide
+ */
+ @SystemApi @TestApi
+ @PackageManager.RollbackDataPolicy
+ public int getRollbackDataPolicy() {
+ return rollbackDataPolicy;
+ }
+
+ /**
* Returns {@code true} if this session is an active staged session.
*
* We consider a session active if it has been committed and it is either pending
@@ -2594,6 +2630,7 @@ public class PackageInstaller {
dest.writeInt(mStagedSessionErrorCode);
dest.writeString(mStagedSessionErrorMessage);
dest.writeBoolean(isCommitted);
+ dest.writeInt(rollbackDataPolicy);
}
public static final Parcelable.Creator<SessionInfo>
diff --git a/core/java/android/content/pm/PackageItemInfo.java b/core/java/android/content/pm/PackageItemInfo.java
index 50a2f0072160..7fd5531bf20d 100644
--- a/core/java/android/content/pm/PackageItemInfo.java
+++ b/core/java/android/content/pm/PackageItemInfo.java
@@ -33,10 +33,10 @@ import android.text.TextUtils;
import android.util.Printer;
import android.util.proto.ProtoOutputStream;
-import com.android.internal.util.Preconditions;
import java.text.Collator;
import java.util.Comparator;
+import java.util.Objects;
/**
* Base class containing information common to all package items held by
@@ -240,7 +240,7 @@ public class PackageItemInfo {
@SystemApi
public @NonNull CharSequence loadSafeLabel(@NonNull PackageManager pm,
@FloatRange(from = 0) float ellipsizeDip, @TextUtils.SafeStringFlags int flags) {
- Preconditions.checkNotNull(pm);
+ Objects.requireNonNull(pm);
return makeSafeForPresentation(loadUnsafeLabel(pm).toString(), MAX_SAFE_LABEL_LENGTH,
ellipsizeDip, flags);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 0d1f4046e70e..f792127bc075 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -29,7 +29,6 @@ import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.StringRes;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.UserIdInt;
import android.annotation.XmlRes;
import android.app.ActivityManager;
@@ -40,6 +39,7 @@ import android.app.admin.DevicePolicyManager;
import android.app.usage.StorageStatsManager;
import android.compat.annotation.ChangeId;
import android.compat.annotation.Disabled;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -710,6 +710,29 @@ public abstract class PackageManager {
public static final int COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED = 4;
/** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {
+ RollbackDataPolicy.RESTORE,
+ RollbackDataPolicy.WIPE,
+ RollbackDataPolicy.RETAIN
+ })
+ public @interface RollbackDataPolicy {
+ /**
+ * User data will be backed up during install and restored during rollback.
+ */
+ int RESTORE = 0;
+ /**
+ * User data won't be backed up during install but will be wiped out during rollback.
+ */
+ int WIPE = 1;
+ /**
+ * User data won't be backed up during install and won't be restored during rollback.
+ * TODO: Not implemented yet.
+ */
+ int RETAIN = 2;
+ }
+
+ /** @hide */
@IntDef(flag = true, prefix = { "INSTALL_" }, value = {
INSTALL_REPLACE_EXISTING,
INSTALL_ALLOW_TEST,
@@ -3243,6 +3266,15 @@ public abstract class PackageManager {
public static final int FLAG_PERMISSION_REVOKED_COMPAT = FLAG_PERMISSION_REVOKE_ON_UPGRADE;
/**
+ * Permission flag: The permission is one-time and should be revoked automatically on app
+ * inactivity
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int FLAG_PERMISSION_ONE_TIME = 1 << 16;
+
+ /**
* Permission flags: Bitwise or of all permission flags allowing an
* exemption for a restricted permission.
* @hide
@@ -3283,7 +3315,8 @@ public abstract class PackageManager {
| FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT
| FLAG_PERMISSION_APPLY_RESTRICTION
| FLAG_PERMISSION_GRANTED_BY_ROLE
- | FLAG_PERMISSION_REVOKED_COMPAT;
+ | FLAG_PERMISSION_REVOKED_COMPAT
+ | FLAG_PERMISSION_ONE_TIME;
/**
* Injected activity in app that forwards user to setting activity of that app.
@@ -4063,7 +4096,8 @@ public abstract class PackageManager {
FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT,
FLAG_PERMISSION_APPLY_RESTRICTION,
FLAG_PERMISSION_GRANTED_BY_ROLE,
- FLAG_PERMISSION_REVOKED_COMPAT
+ FLAG_PERMISSION_REVOKED_COMPAT,
+ FLAG_PERMISSION_ONE_TIME
})
@Retention(RetentionPolicy.SOURCE)
public @interface PermissionFlags {}
@@ -7164,6 +7198,7 @@ public abstract class PackageManager {
case FLAG_PERMISSION_APPLY_RESTRICTION: return "APPLY_RESTRICTION";
case FLAG_PERMISSION_GRANTED_BY_ROLE: return "GRANTED_BY_ROLE";
case FLAG_PERMISSION_REVOKED_COMPAT: return "REVOKED_COMPAT";
+ case FLAG_PERMISSION_ONE_TIME: return "ONE_TIME";
default: return Integer.toString(flag);
}
}
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 65ee1e5f0370..47edf2e6fd3a 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -47,11 +47,11 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringRes;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.apex.ApexInfo;
import android.app.ActivityTaskManager;
import android.app.ActivityThread;
import android.app.ResourcesManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentFilter;
diff --git a/core/java/android/content/pm/PackageStats.java b/core/java/android/content/pm/PackageStats.java
index b0fecfac2471..7c1252737f09 100644
--- a/core/java/android/content/pm/PackageStats.java
+++ b/core/java/android/content/pm/PackageStats.java
@@ -16,8 +16,8 @@
package android.content.pm;
-import android.annotation.UnsupportedAppUsage;
import android.app.usage.StorageStatsManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java
index 55574c3cb880..f0f6753fc93e 100644
--- a/core/java/android/content/pm/PackageUserState.java
+++ b/core/java/android/content/pm/PackageUserState.java
@@ -27,7 +27,7 @@ import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
import static android.content.pm.PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS;
import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.parsing.ComponentParseUtils;
import android.os.BaseBundle;
import android.os.Debug;
diff --git a/core/java/android/content/pm/ParceledListSlice.java b/core/java/android/content/pm/ParceledListSlice.java
index dccc52494f59..73119e05095b 100644
--- a/core/java/android/content/pm/ParceledListSlice.java
+++ b/core/java/android/content/pm/ParceledListSlice.java
@@ -16,7 +16,7 @@
package android.content.pm;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java
index c77c53f387e2..a0f089b2df41 100644
--- a/core/java/android/content/pm/PermissionInfo.java
+++ b/core/java/android/content/pm/PermissionInfo.java
@@ -22,7 +22,7 @@ import android.annotation.Nullable;
import android.annotation.StringRes;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
@@ -248,6 +248,17 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
@TestApi
public static final int PROTECTION_FLAG_TELEPHONY = 0x400000;
+ /**
+ * Additional flag for {@link #protectionLevel}, corresponding
+ * to the <code>companion</code> value of
+ * {@link android.R.attr#protectionLevel}.
+ *
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ public static final int PROTECTION_FLAG_COMPANION = 0x800000;
+
/** @hide */
@IntDef(flag = true, prefix = { "PROTECTION_FLAG_" }, value = {
PROTECTION_FLAG_PRIVILEGED,
@@ -270,6 +281,7 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
PROTECTION_FLAG_INCIDENT_REPORT_APPROVER,
PROTECTION_FLAG_APP_PREDICTOR,
PROTECTION_FLAG_TELEPHONY,
+ PROTECTION_FLAG_COMPANION,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ProtectionFlags {}
diff --git a/core/java/android/content/pm/RegisteredServicesCache.java b/core/java/android/content/pm/RegisteredServicesCache.java
index 23fbefb73c50..bd909c7a3f59 100644
--- a/core/java/android/content/pm/RegisteredServicesCache.java
+++ b/core/java/android/content/pm/RegisteredServicesCache.java
@@ -17,7 +17,7 @@
package android.content.pm;
import android.Manifest;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -43,11 +43,11 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
+import libcore.io.IoUtils;
+
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
-import libcore.io.IoUtils;
-
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
diff --git a/core/java/android/content/pm/ResolveInfo.java b/core/java/android/content/pm/ResolveInfo.java
index 4d3e1f72676b..55846adf2f1f 100644
--- a/core/java/android/content/pm/ResolveInfo.java
+++ b/core/java/android/content/pm/ResolveInfo.java
@@ -17,7 +17,7 @@
package android.content.pm;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.IntentFilter;
import android.graphics.drawable.Drawable;
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index 5a80079695d3..d5fb848c2692 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -20,11 +20,11 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.UserIdInt;
import android.app.Notification;
import android.app.Person;
import android.app.TaskStackBuilder;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -51,6 +51,7 @@ import com.android.internal.util.Preconditions;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
+import java.util.Objects;
import java.util.Set;
/**
@@ -519,12 +520,12 @@ public final class ShortcutInfo implements Parcelable {
public void enforceMandatoryFields(boolean forPinned) {
Preconditions.checkStringNotEmpty(mId, "Shortcut ID must be provided");
if (!forPinned) {
- Preconditions.checkNotNull(mActivity, "Activity must be provided");
+ Objects.requireNonNull(mActivity, "Activity must be provided");
}
if (mTitle == null && mTitleResId == 0) {
throw new IllegalArgumentException("Short label must be provided");
}
- Preconditions.checkNotNull(mIntents, "Shortcut Intent must be provided");
+ Objects.requireNonNull(mIntents, "Shortcut Intent must be provided");
Preconditions.checkArgument(mIntents.length > 0, "Shortcut Intent must be provided");
}
@@ -1008,7 +1009,7 @@ public final class ShortcutInfo implements Parcelable {
*/
@NonNull
public Builder setLocusId(@NonNull LocusId locusId) {
- mLocusId = Preconditions.checkNotNull(locusId, "locusId cannot be null");
+ mLocusId = Objects.requireNonNull(locusId, "locusId cannot be null");
return this;
}
@@ -1039,7 +1040,7 @@ public final class ShortcutInfo implements Parcelable {
*/
@NonNull
public Builder setActivity(@NonNull ComponentName activity) {
- mActivity = Preconditions.checkNotNull(activity, "activity cannot be null");
+ mActivity = Objects.requireNonNull(activity, "activity cannot be null");
return this;
}
@@ -1229,11 +1230,11 @@ public final class ShortcutInfo implements Parcelable {
*/
@NonNull
public Builder setIntents(@NonNull Intent[] intents) {
- Preconditions.checkNotNull(intents, "intents cannot be null");
- Preconditions.checkNotNull(intents.length, "intents cannot be empty");
+ Objects.requireNonNull(intents, "intents cannot be null");
+ Objects.requireNonNull(intents.length, "intents cannot be empty");
for (Intent intent : intents) {
- Preconditions.checkNotNull(intent, "intents cannot contain null");
- Preconditions.checkNotNull(intent.getAction(), "intent's action must be set");
+ Objects.requireNonNull(intent, "intents cannot contain null");
+ Objects.requireNonNull(intent.getAction(), "intent's action must be set");
}
// Make sure always clone incoming intents.
mIntents = cloneIntents(intents);
@@ -1267,10 +1268,10 @@ public final class ShortcutInfo implements Parcelable {
*/
@NonNull
public Builder setPersons(@NonNull Person[] persons) {
- Preconditions.checkNotNull(persons, "persons cannot be null");
- Preconditions.checkNotNull(persons.length, "persons cannot be empty");
+ Objects.requireNonNull(persons, "persons cannot be null");
+ Objects.requireNonNull(persons.length, "persons cannot be empty");
for (Person person : persons) {
- Preconditions.checkNotNull(person, "persons cannot contain null");
+ Objects.requireNonNull(person, "persons cannot contain null");
}
mPersons = clonePersons(persons);
return this;
@@ -1979,7 +1980,7 @@ public final class ShortcutInfo implements Parcelable {
* @hide
*/
public void setIntents(Intent[] intents) throws IllegalArgumentException {
- Preconditions.checkNotNull(intents);
+ Objects.requireNonNull(intents);
Preconditions.checkArgument(intents.length > 0);
mIntents = cloneIntents(intents);
diff --git a/core/java/android/content/pm/ShortcutManager.java b/core/java/android/content/pm/ShortcutManager.java
index f85179942938..dde8865467a1 100644
--- a/core/java/android/content/pm/ShortcutManager.java
+++ b/core/java/android/content/pm/ShortcutManager.java
@@ -22,9 +22,9 @@ import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.UserIdInt;
import android.app.usage.UsageStatsManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/content/pm/Signature.java b/core/java/android/content/pm/Signature.java
index 25a4dca4d815..3b84ae775ad1 100644
--- a/core/java/android/content/pm/Signature.java
+++ b/core/java/android/content/pm/Signature.java
@@ -16,7 +16,7 @@
package android.content.pm;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index fff9cf399b67..008cfa5e9423 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -18,8 +18,8 @@ package android.content.pm;
import android.annotation.IntDef;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.UserIdInt;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.UserHandle;
diff --git a/core/java/android/content/pm/VerifierInfo.java b/core/java/android/content/pm/VerifierInfo.java
index 224ca628cf27..5f8855572ef0 100644
--- a/core/java/android/content/pm/VerifierInfo.java
+++ b/core/java/android/content/pm/VerifierInfo.java
@@ -16,7 +16,7 @@
package android.content.pm;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/content/pm/XmlSerializerAndParser.java b/core/java/android/content/pm/XmlSerializerAndParser.java
index 6d24800edb07..5dce83902f78 100644
--- a/core/java/android/content/pm/XmlSerializerAndParser.java
+++ b/core/java/android/content/pm/XmlSerializerAndParser.java
@@ -16,11 +16,12 @@
package android.content.pm;
-import org.xmlpull.v1.XmlSerializer;
+import android.compat.annotation.UnsupportedAppUsage;
+
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
-import android.annotation.UnsupportedAppUsage;
import java.io.IOException;
/** @hide */
diff --git a/core/java/android/content/pm/parsing/AndroidPackage.java b/core/java/android/content/pm/parsing/AndroidPackage.java
index 35df47431a91..0562dffc551e 100644
--- a/core/java/android/content/pm/parsing/AndroidPackage.java
+++ b/core/java/android/content/pm/parsing/AndroidPackage.java
@@ -403,6 +403,8 @@ public interface AndroidPackage extends Parcelable {
boolean isEnabled();
+ boolean isCrossProfile();
+
boolean isEncryptionAware();
boolean isExternal();
diff --git a/core/java/android/content/pm/parsing/ApkParseUtils.java b/core/java/android/content/pm/parsing/ApkParseUtils.java
index 773231682fe4..3f2296729891 100644
--- a/core/java/android/content/pm/parsing/ApkParseUtils.java
+++ b/core/java/android/content/pm/parsing/ApkParseUtils.java
@@ -2070,6 +2070,9 @@ public class ApkParseUtils {
sa.getBoolean(R.styleable.AndroidManifestApplication_enabled,
true));
+ parsingPackage.setCrossProfile(
+ sa.getBoolean(R.styleable.AndroidManifestApplication_crossProfile, false));
+
parsingPackage.setIsGame(sa.getBoolean(
R.styleable.AndroidManifestApplication_isGame, false));
diff --git a/core/java/android/content/pm/parsing/PackageImpl.java b/core/java/android/content/pm/parsing/PackageImpl.java
index 0e736d522c10..18dee23dc690 100644
--- a/core/java/android/content/pm/parsing/PackageImpl.java
+++ b/core/java/android/content/pm/parsing/PackageImpl.java
@@ -240,6 +240,7 @@ public final class PackageImpl implements ParsingPackage, ParsedPackage, Android
private int descriptionRes;
private String deviceProtectedDataDir;
private boolean enabled;
+ private boolean crossProfile;
private int flags;
private int fullBackupContent;
private boolean hiddenUntilInstalled;
@@ -1636,6 +1637,12 @@ public final class PackageImpl implements ParsingPackage, ParsedPackage, Android
}
@Override
+ public PackageImpl setCrossProfile(boolean crossProfile) {
+ this.crossProfile = crossProfile;
+ return this;
+ }
+
+ @Override
public PackageImpl setUiOptions(int uiOptions) {
this.uiOptions = uiOptions;
return this;
@@ -2835,6 +2842,11 @@ public final class PackageImpl implements ParsingPackage, ParsedPackage, Android
}
@Override
+ public boolean isCrossProfile() {
+ return crossProfile;
+ }
+
+ @Override
public String getManageSpaceActivityName() {
return manageSpaceActivityName;
}
@@ -3042,6 +3054,7 @@ public final class PackageImpl implements ParsingPackage, ParsedPackage, Android
dest.writeInt(this.descriptionRes);
dest.writeString(this.deviceProtectedDataDir);
dest.writeBoolean(this.enabled);
+ dest.writeBoolean(this.crossProfile);
dest.writeInt(this.flags);
dest.writeInt(this.fullBackupContent);
dest.writeBoolean(this.hiddenUntilInstalled);
@@ -3194,6 +3207,7 @@ public final class PackageImpl implements ParsingPackage, ParsedPackage, Android
this.descriptionRes = in.readInt();
this.deviceProtectedDataDir = in.readString();
this.enabled = in.readBoolean();
+ this.crossProfile = in.readBoolean();
this.flags = in.readInt();
this.fullBackupContent = in.readInt();
this.hiddenUntilInstalled = in.readBoolean();
diff --git a/core/java/android/content/pm/parsing/ParsingPackage.java b/core/java/android/content/pm/parsing/ParsingPackage.java
index aff1b2e05eaf..47dac5584c89 100644
--- a/core/java/android/content/pm/parsing/ParsingPackage.java
+++ b/core/java/android/content/pm/parsing/ParsingPackage.java
@@ -229,6 +229,8 @@ public interface ParsingPackage extends AndroidPackage {
ParsingPackage setEnabled(boolean enabled);
+ ParsingPackage setCrossProfile(boolean crossProfile);
+
ParsingPackage setFullBackupContent(int fullBackupContent);
ParsingPackage setHasDomainUrls(boolean hasDomainUrls);
diff --git a/core/java/android/content/res/ApkAssets.java b/core/java/android/content/res/ApkAssets.java
index ad375552837d..8db278579cc1 100644
--- a/core/java/android/content/res/ApkAssets.java
+++ b/core/java/android/content/res/ApkAssets.java
@@ -17,16 +17,16 @@ package android.content.res;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.om.OverlayableInfo;
import android.content.res.loader.ResourcesProvider;
import android.text.TextUtils;
import com.android.internal.annotations.GuardedBy;
-import com.android.internal.util.Preconditions;
import java.io.FileDescriptor;
import java.io.IOException;
+import java.util.Objects;
/**
* The loaded, immutable, in-memory representation of an APK.
@@ -193,7 +193,7 @@ public final class ApkAssets {
private ApkAssets(@NonNull String path, boolean system, boolean forceSharedLib, boolean overlay,
boolean arscOnly, boolean forLoader) throws IOException {
mForLoader = forLoader;
- Preconditions.checkNotNull(path, "path");
+ Objects.requireNonNull(path, "path");
mNativePtr = arscOnly ? nativeLoadArsc(path, forLoader)
: nativeLoad(path, system, forceSharedLib, overlay, forLoader);
mStringBlock = new StringBlock(nativeGetStringBlock(mNativePtr), true /*useSparse*/);
@@ -202,8 +202,8 @@ public final class ApkAssets {
private ApkAssets(@NonNull FileDescriptor fd, @NonNull String friendlyName, boolean system,
boolean forceSharedLib, boolean arscOnly, boolean forLoader) throws IOException {
mForLoader = forLoader;
- Preconditions.checkNotNull(fd, "fd");
- Preconditions.checkNotNull(friendlyName, "friendlyName");
+ Objects.requireNonNull(fd, "fd");
+ Objects.requireNonNull(friendlyName, "friendlyName");
mNativePtr = arscOnly ? nativeLoadArscFromFd(fd, friendlyName, forLoader)
: nativeLoadFromFd(fd, friendlyName, system, forceSharedLib, forLoader);
mStringBlock = new StringBlock(nativeGetStringBlock(mNativePtr), true /*useSparse*/);
@@ -240,7 +240,7 @@ public final class ApkAssets {
* @throws IOException if the file was not found or an error occurred retrieving it.
*/
public @NonNull XmlResourceParser openXml(@NonNull String fileName) throws IOException {
- Preconditions.checkNotNull(fileName, "fileName");
+ Objects.requireNonNull(fileName, "fileName");
synchronized (this) {
long nativeXmlPtr = nativeOpenXml(mNativePtr, fileName);
try (XmlBlock block = new XmlBlock(null, nativeXmlPtr)) {
diff --git a/core/java/android/content/res/AssetFileDescriptor.java b/core/java/android/content/res/AssetFileDescriptor.java
index 2ba55798d665..e93ec00468f5 100644
--- a/core/java/android/content/res/AssetFileDescriptor.java
+++ b/core/java/android/content/res/AssetFileDescriptor.java
@@ -16,7 +16,7 @@
package android.content.res;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Bundle;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index 168eae65ddf2..96fbe9109c18 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -24,7 +24,7 @@ import android.annotation.Nullable;
import android.annotation.StringRes;
import android.annotation.StyleRes;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration.NativeConfig;
import android.content.res.loader.ResourceLoader;
@@ -39,7 +39,6 @@ import android.util.TypedValue;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.Preconditions;
import java.io.FileDescriptor;
import java.io.FileNotFoundException;
@@ -52,6 +51,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.Objects;
/**
* Provides access to an application's raw asset files; see {@link Resources}
@@ -273,7 +273,7 @@ public final class AssetManager implements AutoCloseable {
* @hide
*/
public void setApkAssets(@NonNull ApkAssets[] apkAssets, boolean invalidateCaches) {
- Preconditions.checkNotNull(apkAssets, "apkAssets");
+ Objects.requireNonNull(apkAssets, "apkAssets");
ApkAssets[] newApkAssets = new ApkAssets[sSystemApkAssets.length + apkAssets.length];
@@ -352,7 +352,7 @@ public final class AssetManager implements AutoCloseable {
* @hide
*/
public int findCookieForPath(@NonNull String path) {
- Preconditions.checkNotNull(path, "path");
+ Objects.requireNonNull(path, "path");
synchronized (this) {
ensureValidLocked();
final int count = mApkAssets.length;
@@ -396,7 +396,7 @@ public final class AssetManager implements AutoCloseable {
}
private int addAssetPathInternal(String path, boolean overlay, boolean appAsLib) {
- Preconditions.checkNotNull(path, "path");
+ Objects.requireNonNull(path, "path");
synchronized (this) {
ensureOpenLocked();
final int count = mApkAssets.length;
@@ -471,7 +471,7 @@ public final class AssetManager implements AutoCloseable {
@UnsupportedAppUsage
boolean getResourceValue(@AnyRes int resId, int densityDpi, @NonNull TypedValue outValue,
boolean resolveRefs) {
- Preconditions.checkNotNull(outValue, "outValue");
+ Objects.requireNonNull(outValue, "outValue");
synchronized (this) {
ensureValidLocked();
final int cookie = nativeGetResourceValue(
@@ -568,7 +568,7 @@ public final class AssetManager implements AutoCloseable {
* @see TypedArray#STYLE_DENSITY
*/
int getResourceArray(@ArrayRes int resId, @NonNull int[] outData) {
- Preconditions.checkNotNull(outData, "outData");
+ Objects.requireNonNull(outData, "outData");
synchronized (this) {
ensureValidLocked();
return nativeGetResourceArray(mObject, resId, outData);
@@ -652,7 +652,7 @@ public final class AssetManager implements AutoCloseable {
*/
boolean getThemeValue(long theme, @AnyRes int resId, @NonNull TypedValue outValue,
boolean resolveRefs) {
- Preconditions.checkNotNull(outValue, "outValue");
+ Objects.requireNonNull(outValue, "outValue");
synchronized (this) {
ensureValidLocked();
final int cookie = nativeThemeGetAttributeValue(mObject, theme, resId, outValue,
@@ -791,7 +791,7 @@ public final class AssetManager implements AutoCloseable {
* @see #list
*/
public @NonNull InputStream open(@NonNull String fileName, int accessMode) throws IOException {
- Preconditions.checkNotNull(fileName, "fileName");
+ Objects.requireNonNull(fileName, "fileName");
synchronized (this) {
ensureOpenLocked();
@@ -822,7 +822,7 @@ public final class AssetManager implements AutoCloseable {
* @return An open AssetFileDescriptor.
*/
public @NonNull AssetFileDescriptor openFd(@NonNull String fileName) throws IOException {
- Preconditions.checkNotNull(fileName, "fileName");
+ Objects.requireNonNull(fileName, "fileName");
synchronized (this) {
ensureOpenLocked();
@@ -853,7 +853,7 @@ public final class AssetManager implements AutoCloseable {
* @see #open
*/
public @Nullable String[] list(@NonNull String path) throws IOException {
- Preconditions.checkNotNull(path, "path");
+ Objects.requireNonNull(path, "path");
synchronized (this) {
ensureValidLocked();
return nativeList(mObject, path);
@@ -922,7 +922,7 @@ public final class AssetManager implements AutoCloseable {
@UnsupportedAppUsage
public @NonNull InputStream openNonAsset(int cookie, @NonNull String fileName, int accessMode)
throws IOException {
- Preconditions.checkNotNull(fileName, "fileName");
+ Objects.requireNonNull(fileName, "fileName");
synchronized (this) {
ensureOpenLocked();
@@ -967,7 +967,7 @@ public final class AssetManager implements AutoCloseable {
*/
public @NonNull AssetFileDescriptor openNonAssetFd(int cookie, @NonNull String fileName)
throws IOException {
- Preconditions.checkNotNull(fileName, "fileName");
+ Objects.requireNonNull(fileName, "fileName");
synchronized (this) {
ensureOpenLocked();
@@ -1034,7 +1034,7 @@ public final class AssetManager implements AutoCloseable {
* @hide
*/
@NonNull XmlBlock openXmlBlockAsset(int cookie, @NonNull String fileName) throws IOException {
- Preconditions.checkNotNull(fileName, "fileName");
+ Objects.requireNonNull(fileName, "fileName");
synchronized (this) {
ensureOpenLocked();
@@ -1145,7 +1145,7 @@ public final class AssetManager implements AutoCloseable {
void applyStyle(long themePtr, @AttrRes int defStyleAttr, @StyleRes int defStyleRes,
@Nullable XmlBlock.Parser parser, @NonNull int[] inAttrs, long outValuesAddress,
long outIndicesAddress) {
- Preconditions.checkNotNull(inAttrs, "inAttrs");
+ Objects.requireNonNull(inAttrs, "inAttrs");
synchronized (this) {
// Need to synchronize on AssetManager because we will be accessing
// the native implementation of AssetManager.
@@ -1168,9 +1168,9 @@ public final class AssetManager implements AutoCloseable {
boolean resolveAttrs(long themePtr, @AttrRes int defStyleAttr, @StyleRes int defStyleRes,
@Nullable int[] inValues, @NonNull int[] inAttrs, @NonNull int[] outValues,
@NonNull int[] outIndices) {
- Preconditions.checkNotNull(inAttrs, "inAttrs");
- Preconditions.checkNotNull(outValues, "outValues");
- Preconditions.checkNotNull(outIndices, "outIndices");
+ Objects.requireNonNull(inAttrs, "inAttrs");
+ Objects.requireNonNull(outValues, "outValues");
+ Objects.requireNonNull(outIndices, "outIndices");
synchronized (this) {
// Need to synchronize on AssetManager because we will be accessing
// the native implementation of AssetManager.
@@ -1183,10 +1183,10 @@ public final class AssetManager implements AutoCloseable {
@UnsupportedAppUsage
boolean retrieveAttributes(@NonNull XmlBlock.Parser parser, @NonNull int[] inAttrs,
@NonNull int[] outValues, @NonNull int[] outIndices) {
- Preconditions.checkNotNull(parser, "parser");
- Preconditions.checkNotNull(inAttrs, "inAttrs");
- Preconditions.checkNotNull(outValues, "outValues");
- Preconditions.checkNotNull(outIndices, "outIndices");
+ Objects.requireNonNull(parser, "parser");
+ Objects.requireNonNull(inAttrs, "inAttrs");
+ Objects.requireNonNull(outValues, "outValues");
+ Objects.requireNonNull(outIndices, "outIndices");
synchronized (this) {
// Need to synchronize on AssetManager because we will be accessing
// the native implementation of AssetManager.
@@ -1290,14 +1290,14 @@ public final class AssetManager implements AutoCloseable {
@Override
public final int read(@NonNull byte[] b) throws IOException {
ensureOpen();
- Preconditions.checkNotNull(b, "b");
+ Objects.requireNonNull(b, "b");
return nativeAssetRead(mAssetNativePtr, b, 0, b.length);
}
@Override
public final int read(@NonNull byte[] b, int off, int len) throws IOException {
ensureOpen();
- Preconditions.checkNotNull(b, "b");
+ Objects.requireNonNull(b, "b");
return nativeAssetRead(mAssetNativePtr, b, off, len);
}
diff --git a/core/java/android/content/res/ColorStateList.java b/core/java/android/content/res/ColorStateList.java
index b5b097b33ef3..f23c802d98e2 100644
--- a/core/java/android/content/res/ColorStateList.java
+++ b/core/java/android/content/res/ColorStateList.java
@@ -19,9 +19,18 @@ package android.content.res;
import android.annotation.ColorInt;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo.Config;
import android.content.res.Resources.Theme;
import android.graphics.Color;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.MathUtils;
+import android.util.SparseArray;
+import android.util.StateSet;
+import android.util.Xml;
import com.android.internal.R;
import com.android.internal.util.ArrayUtils;
@@ -30,16 +39,6 @@ import com.android.internal.util.GrowingArrayUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
-import android.annotation.UnsupportedAppUsage;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.MathUtils;
-import android.util.SparseArray;
-import android.util.StateSet;
-import android.util.Xml;
-import android.os.Parcel;
-import android.os.Parcelable;
-
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.Arrays;
diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java
index f3b7553577ca..c66c70a20729 100644
--- a/core/java/android/content/res/CompatibilityInfo.java
+++ b/core/java/android/content/res/CompatibilityInfo.java
@@ -16,7 +16,7 @@
package android.content.res;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ApplicationInfo;
import android.graphics.Canvas;
import android.graphics.PointF;
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index fa5ad39789dd..8c358cc522d6 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -45,8 +45,8 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.WindowConfiguration;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.LocaleProto;
import android.content.pm.ActivityInfo;
import android.content.pm.ActivityInfo.Config;
diff --git a/core/java/android/content/res/ConfigurationBoundResourceCache.java b/core/java/android/content/res/ConfigurationBoundResourceCache.java
index 848790f46734..5e10a5768358 100644
--- a/core/java/android/content/res/ConfigurationBoundResourceCache.java
+++ b/core/java/android/content/res/ConfigurationBoundResourceCache.java
@@ -16,7 +16,7 @@
package android.content.res;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo.Config;
/**
diff --git a/core/java/android/content/res/DrawableCache.java b/core/java/android/content/res/DrawableCache.java
index 90604b8d536a..5497e61fa2e9 100644
--- a/core/java/android/content/res/DrawableCache.java
+++ b/core/java/android/content/res/DrawableCache.java
@@ -16,7 +16,7 @@
package android.content.res;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.drawable.Drawable;
/**
diff --git a/core/java/android/content/res/ObbInfo.java b/core/java/android/content/res/ObbInfo.java
index 8af27ca825d0..c477abcea8ba 100644
--- a/core/java/android/content/res/ObbInfo.java
+++ b/core/java/android/content/res/ObbInfo.java
@@ -16,7 +16,7 @@
package android.content.res;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index c698267b956b..4725e0af4eec 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -40,9 +40,9 @@ import android.annotation.RawRes;
import android.annotation.StringRes;
import android.annotation.StyleRes;
import android.annotation.StyleableRes;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.XmlRes;
import android.app.ResourcesManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo;
import android.content.pm.ActivityInfo.Config;
import android.content.res.loader.ResourceLoader;
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
index e4a4a1a771b2..acdd47a4d61e 100644
--- a/core/java/android/content/res/ResourcesImpl.java
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -27,7 +27,7 @@ import android.annotation.PluralsRes;
import android.annotation.RawRes;
import android.annotation.StyleRes;
import android.annotation.StyleableRes;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo;
import android.content.pm.ActivityInfo.Config;
import android.content.res.AssetManager.AssetInputStream;
diff --git a/core/java/android/content/res/ResourcesKey.java b/core/java/android/content/res/ResourcesKey.java
index 1db2dd85fb37..a29fea09c5ce 100644
--- a/core/java/android/content/res/ResourcesKey.java
+++ b/core/java/android/content/res/ResourcesKey.java
@@ -18,7 +18,7 @@ package android.content.res;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.text.TextUtils;
import java.util.Arrays;
diff --git a/core/java/android/content/res/StringBlock.java b/core/java/android/content/res/StringBlock.java
index d43bd36b4c74..8f3f77b99739 100644
--- a/core/java/android/content/res/StringBlock.java
+++ b/core/java/android/content/res/StringBlock.java
@@ -16,7 +16,7 @@
package android.content.res;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
diff --git a/core/java/android/content/res/ThemedResourceCache.java b/core/java/android/content/res/ThemedResourceCache.java
index 968ab401ccba..3270944ce7e3 100644
--- a/core/java/android/content/res/ThemedResourceCache.java
+++ b/core/java/android/content/res/ThemedResourceCache.java
@@ -18,7 +18,7 @@ package android.content.res;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo.Config;
import android.content.res.Resources.Theme;
import android.content.res.Resources.ThemeKey;
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index 38df317575d7..29c5c935c1bf 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -20,7 +20,7 @@ import android.annotation.AnyRes;
import android.annotation.ColorInt;
import android.annotation.Nullable;
import android.annotation.StyleableRes;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo;
import android.content.pm.ActivityInfo.Config;
import android.graphics.Typeface;
diff --git a/core/java/android/content/res/XmlBlock.java b/core/java/android/content/res/XmlBlock.java
index 626bf77046bf..cb93cbfcbfc9 100644
--- a/core/java/android/content/res/XmlBlock.java
+++ b/core/java/android/content/res/XmlBlock.java
@@ -20,7 +20,7 @@ import static android.content.res.Resources.ID_NULL;
import android.annotation.AnyRes;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.TypedValue;
import com.android.internal.util.XmlUtils;
diff --git a/core/java/android/content/rollback/PackageRollbackInfo.java b/core/java/android/content/rollback/PackageRollbackInfo.java
index c89796d4b1da..6378db0ebbbd 100644
--- a/core/java/android/content/rollback/PackageRollbackInfo.java
+++ b/core/java/android/content/rollback/PackageRollbackInfo.java
@@ -19,6 +19,7 @@ package android.content.rollback;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.annotation.TestApi;
+import android.content.pm.PackageManager;
import android.content.pm.VersionedPackage;
import android.os.Parcel;
import android.os.Parcelable;
@@ -88,6 +89,11 @@ public final class PackageRollbackInfo implements Parcelable {
private final SparseLongArray mCeSnapshotInodes;
/**
+ * The userdata policy to execute when a rollback for this package is committed.
+ */
+ private final int mRollbackDataPolicy;
+
+ /**
* Returns the name of the package to roll back from.
*/
@NonNull
@@ -148,6 +154,11 @@ public final class PackageRollbackInfo implements Parcelable {
}
/** @hide */
+ public @PackageManager.RollbackDataPolicy int getRollbackDataPolicy() {
+ return mRollbackDataPolicy;
+ }
+
+ /** @hide */
public IntArray getSnapshottedUsers() {
return mSnapshottedUsers;
}
@@ -181,11 +192,23 @@ public final class PackageRollbackInfo implements Parcelable {
@NonNull IntArray pendingBackups, @NonNull ArrayList<RestoreInfo> pendingRestores,
boolean isApex, @NonNull IntArray snapshottedUsers,
@NonNull SparseLongArray ceSnapshotInodes) {
+ this(packageRolledBackFrom, packageRolledBackTo, pendingBackups, pendingRestores, isApex,
+ snapshottedUsers, ceSnapshotInodes, PackageManager.RollbackDataPolicy.RESTORE);
+ }
+
+ /** @hide */
+ public PackageRollbackInfo(VersionedPackage packageRolledBackFrom,
+ VersionedPackage packageRolledBackTo,
+ @NonNull IntArray pendingBackups, @NonNull ArrayList<RestoreInfo> pendingRestores,
+ boolean isApex, @NonNull IntArray snapshottedUsers,
+ @NonNull SparseLongArray ceSnapshotInodes,
+ @PackageManager.RollbackDataPolicy int rollbackDataPolicy) {
this.mVersionRolledBackFrom = packageRolledBackFrom;
this.mVersionRolledBackTo = packageRolledBackTo;
this.mPendingBackups = pendingBackups;
this.mPendingRestores = pendingRestores;
this.mIsApex = isApex;
+ this.mRollbackDataPolicy = rollbackDataPolicy;
this.mSnapshottedUsers = snapshottedUsers;
this.mCeSnapshotInodes = ceSnapshotInodes;
}
@@ -198,6 +221,7 @@ public final class PackageRollbackInfo implements Parcelable {
this.mPendingBackups = null;
this.mSnapshottedUsers = null;
this.mCeSnapshotInodes = null;
+ this.mRollbackDataPolicy = PackageManager.RollbackDataPolicy.RESTORE;
}
@Override
diff --git a/core/java/android/database/sqlite/SQLiteQueryBuilder.java b/core/java/android/database/sqlite/SQLiteQueryBuilder.java
index 39c1daca1bfd..f71377052a71 100644
--- a/core/java/android/database/sqlite/SQLiteQueryBuilder.java
+++ b/core/java/android/database/sqlite/SQLiteQueryBuilder.java
@@ -782,59 +782,42 @@ public class SQLiteQueryBuilder {
private void enforceStrictGrammar(@Nullable String selection, @Nullable String groupBy,
@Nullable String having, @Nullable String sortOrder, @Nullable String limit) {
SQLiteTokenizer.tokenize(selection, SQLiteTokenizer.OPTION_NONE,
- this::enforceStrictGrammarWhereHaving);
+ this::enforceStrictToken);
SQLiteTokenizer.tokenize(groupBy, SQLiteTokenizer.OPTION_NONE,
- this::enforceStrictGrammarGroupBy);
+ this::enforceStrictToken);
SQLiteTokenizer.tokenize(having, SQLiteTokenizer.OPTION_NONE,
- this::enforceStrictGrammarWhereHaving);
+ this::enforceStrictToken);
SQLiteTokenizer.tokenize(sortOrder, SQLiteTokenizer.OPTION_NONE,
- this::enforceStrictGrammarOrderBy);
+ this::enforceStrictToken);
SQLiteTokenizer.tokenize(limit, SQLiteTokenizer.OPTION_NONE,
- this::enforceStrictGrammarLimit);
+ this::enforceStrictToken);
}
- private void enforceStrictGrammarWhereHaving(@NonNull String token) {
+ private void enforceStrictToken(@NonNull String token) {
if (isTableOrColumn(token)) return;
if (SQLiteTokenizer.isFunction(token)) return;
if (SQLiteTokenizer.isType(token)) return;
- // NOTE: we explicitly don't allow SELECT subqueries, since they could
- // leak data that should have been filtered by the trusted where clause
+ // Carefully block any tokens that are attempting to jump across query
+ // clauses or create subqueries, since they could leak data that should
+ // have been filtered by the trusted where clause
+ boolean isAllowedKeyword = SQLiteTokenizer.isKeyword(token);
switch (token.toUpperCase(Locale.US)) {
- case "AND": case "AS": case "BETWEEN": case "BINARY":
- case "CASE": case "CAST": case "COLLATE": case "DISTINCT":
- case "ELSE": case "END": case "ESCAPE": case "EXISTS":
- case "GLOB": case "IN": case "IS": case "ISNULL":
- case "LIKE": case "MATCH": case "NOCASE": case "NOT":
- case "NOTNULL": case "NULL": case "OR": case "REGEXP":
- case "RTRIM": case "THEN": case "WHEN":
- return;
+ case "SELECT":
+ case "FROM":
+ case "WHERE":
+ case "GROUP":
+ case "HAVING":
+ case "WINDOW":
+ case "VALUES":
+ case "ORDER":
+ case "LIMIT":
+ isAllowedKeyword = false;
+ break;
}
- throw new IllegalArgumentException("Invalid token " + token);
- }
-
- private void enforceStrictGrammarGroupBy(@NonNull String token) {
- if (isTableOrColumn(token)) return;
- throw new IllegalArgumentException("Invalid token " + token);
- }
-
- private void enforceStrictGrammarOrderBy(@NonNull String token) {
- if (isTableOrColumn(token)) return;
- switch (token.toUpperCase(Locale.US)) {
- case "COLLATE": case "ASC": case "DESC":
- case "BINARY": case "RTRIM": case "NOCASE":
- case "LOCALIZED": case "UNICODE":
- return;
- }
- throw new IllegalArgumentException("Invalid token " + token);
- }
-
- private void enforceStrictGrammarLimit(@NonNull String token) {
- switch (token.toUpperCase(Locale.US)) {
- case "OFFSET":
- return;
+ if (!isAllowedKeyword) {
+ throw new IllegalArgumentException("Invalid token " + token);
}
- throw new IllegalArgumentException("Invalid token " + token);
}
/**
diff --git a/core/java/android/hardware/biometrics/BiometricManager.java b/core/java/android/hardware/biometrics/BiometricManager.java
index 7e1506f61a51..4c114fdc5f10 100644
--- a/core/java/android/hardware/biometrics/BiometricManager.java
+++ b/core/java/android/hardware/biometrics/BiometricManager.java
@@ -90,19 +90,19 @@ public class BiometricManager {
* @hide
*/
@SystemApi
- int EMPTY_SET = 0x0;
+ int EMPTY_SET = 0x0000;
/**
* Placeholder for the theoretical strongest biometric security tier.
* @hide
*/
- int BIOMETRIC_MAX_STRENGTH = 0x001;
+ int BIOMETRIC_MAX_STRENGTH = 0x0001;
/**
* Any biometric (e.g. fingerprint, iris, or face) on the device that meets or exceeds the
* requirements for <strong>Strong</strong>, as defined by the Android CDD.
*/
- int BIOMETRIC_STRONG = 0x00F;
+ int BIOMETRIC_STRONG = 0x000F;
/**
* Any biometric (e.g. fingerprint, iris, or face) on the device that meets or exceeds the
@@ -111,7 +111,7 @@ public class BiometricManager {
* <p>Note that this is a superset of {@link #BIOMETRIC_STRONG} and is defined such that
* <code>BIOMETRIC_STRONG | BIOMETRIC_WEAK == BIOMETRIC_WEAK</code>.
*/
- int BIOMETRIC_WEAK = 0x0FF;
+ int BIOMETRIC_WEAK = 0x00FF;
/**
* Any biometric (e.g. fingerprint, iris, or face) on the device that meets or exceeds the
@@ -121,7 +121,7 @@ public class BiometricManager {
* @hide
*/
@SystemApi
- int BIOMETRIC_CONVENIENCE = 0xFFF;
+ int BIOMETRIC_CONVENIENCE = 0x0FFF;
/**
* Placeholder for the theoretical weakest biometric security tier.
diff --git a/core/java/android/hardware/biometrics/BiometricPrompt.java b/core/java/android/hardware/biometrics/BiometricPrompt.java
index 6f9c9e6db025..cb8fc8b1cbb1 100644
--- a/core/java/android/hardware/biometrics/BiometricPrompt.java
+++ b/core/java/android/hardware/biometrics/BiometricPrompt.java
@@ -87,6 +87,11 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
* @hide
*/
public static final String KEY_AUTHENTICATORS_ALLOWED = "authenticators_allowed";
+ /**
+ * If this is set, check the Device Policy Manager for allowed biometrics.
+ * @hide
+ */
+ public static final String EXTRA_DISALLOW_BIOMETRICS_IF_POLICY_EXISTS = "check_dpm";
/**
* Error/help message will show for this amount of time.
@@ -326,6 +331,20 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
}
/**
+ * If set check the Device Policy Manager for disabled biometrics.
+ *
+ * @param checkDevicePolicyManager
+ * @return This builder.
+ * @hide
+ */
+ @NonNull
+ public Builder setDisallowBiometricsIfPolicyExists(boolean checkDevicePolicyManager) {
+ mBundle.putBoolean(EXTRA_DISALLOW_BIOMETRICS_IF_POLICY_EXISTS,
+ checkDevicePolicyManager);
+ return this;
+ }
+
+ /**
* Creates a {@link BiometricPrompt}.
*
* @return An instance of {@link BiometricPrompt}.
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index c84c4a762796..b60586655dc8 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -1125,8 +1125,8 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
new Key<android.util.Range<Integer>>("android.control.postRawSensitivityBoostRange", new TypeReference<android.util.Range<Integer>>() {{ }});
/**
- * <p>The list of bokeh modes that are supported by this camera device, and each bokeh mode's
- * maximum streaming (non-stall) size with bokeh effect.</p>
+ * <p>The list of bokeh modes for {@link CaptureRequest#CONTROL_BOKEH_MODE android.control.bokehMode} that are supported by this camera
+ * device, and each bokeh mode's maximum streaming (non-stall) size with bokeh effect.</p>
* <p>For OFF mode, the camera behaves normally with no bokeh effect.</p>
* <p>For STILL_CAPTURE mode, the maximum streaming dimension specifies the limit under which
* bokeh is effective when capture intent is PREVIEW. Note that when capture intent is
@@ -1148,12 +1148,86 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
* Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the
* {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key</p>
*
+ * @see CaptureRequest#CONTROL_BOKEH_MODE
+ * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
+ * @hide
+ */
+ public static final Key<int[]> CONTROL_AVAILABLE_BOKEH_MAX_SIZES =
+ new Key<int[]>("android.control.availableBokehMaxSizes", int[].class);
+
+ /**
+ * <p>The ranges of supported zoom ratio for non-OFF {@link CaptureRequest#CONTROL_BOKEH_MODE android.control.bokehMode}.</p>
+ * <p>When bokeh mode is enabled, the camera device may have limited range of zoom ratios
+ * compared to when bokeh mode is disabled. This tag lists the zoom ratio ranges for all
+ * supported non-OFF bokeh modes, in the same order as in
+ * {@link CameraCharacteristics#CONTROL_AVAILABLE_BOKEH_CAPABILITIES android.control.availableBokehCapabilities}.</p>
+ * <p>Range [1.0, 1.0] means that no zoom (optical or digital) is supported.</p>
+ * <p><b>Units</b>: (minZoom, maxZoom)</p>
+ * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
+ * <p><b>Limited capability</b> -
+ * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the
+ * {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key</p>
+ *
+ * @see CameraCharacteristics#CONTROL_AVAILABLE_BOKEH_CAPABILITIES
+ * @see CaptureRequest#CONTROL_BOKEH_MODE
+ * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
+ * @hide
+ */
+ public static final Key<float[]> CONTROL_AVAILABLE_BOKEH_ZOOM_RATIO_RANGES =
+ new Key<float[]>("android.control.availableBokehZoomRatioRanges", float[].class);
+
+ /**
+ * <p>The list of bokeh modes for {@link CaptureRequest#CONTROL_BOKEH_MODE android.control.bokehMode} that are supported by
+ * this camera device, and each bokeh mode's capabilities such as maximum streaming size
+ * with bokeh effect, and supported zoom ratio ranges.</p>
+ * <p>For OFF mode, the camera behaves normally with no bokeh effect.</p>
+ * <p>For STILL_CAPTURE mode, the maximum streaming dimension specifies the limit under which
+ * bokeh is effective when capture intent is PREVIEW. Note that when capture intent is
+ * PREVIEW, the bokeh effect may not be as high quality compared to STILL_CAPTURE intent
+ * in order to maintain reasonable frame rate. The maximum streaming dimension must be one
+ * of the YUV_420_888 or PRIVATE resolutions in availableStreamConfigurations, or (0, 0)
+ * if preview bokeh is not supported. If the application configures a stream larger than
+ * the maximum streaming dimension, bokeh effect may not be applied for this stream for
+ * PREVIEW intent.</p>
+ * <p>For CONTINUOUS mode, the maximum streaming dimension specifies the limit under which
+ * bokeh is effective. This dimension must be one of the YUV_420_888 or PRIVATE resolutions
+ * in availableStreamConfigurations, and if the sensor maximum resolution is larger than or
+ * equal to 1080p, the maximum streaming dimension must be at least 1080p. If the
+ * application configures a stream with larger dimension, the stream may not have bokeh
+ * effect applied.</p>
+ * <p>When bokeh mode is enabled, the camera device may have limited range of zoom ratios
+ * compared to when bokeh mode is disabled. availableBokehCapabilities lists the zoom
+ * ranges for all supported bokeh modes. A range of (1.0, 1.0) means that no zoom
+ * (optical or digital) is supported.</p>
+ * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
+ *
+ * @see CaptureRequest#CONTROL_BOKEH_MODE
+ */
+ @PublicKey
+ @NonNull
+ @SyntheticKey
+ public static final Key<android.hardware.camera2.params.Capability[]> CONTROL_AVAILABLE_BOKEH_CAPABILITIES =
+ new Key<android.hardware.camera2.params.Capability[]>("android.control.availableBokehCapabilities", android.hardware.camera2.params.Capability[].class);
+
+ /**
+ * <p>Minimum and maximum zoom ratios supported by this camera device.</p>
+ * <p>If the camera device supports zoom-out from 1x zoom, minZoom will be less than 1.0, and
+ * setting android.control.zoomRation to values less than 1.0 increases the camera's field
+ * of view.</p>
+ * <p><b>Units</b>: A pair of zoom ratio in floating points: (minZoom, maxZoom)</p>
+ * <p><b>Range of valid values:</b><br></p>
+ * <p>maxZoom &gt;= 1.0 &gt;= minZoom</p>
+ * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
+ * <p><b>Limited capability</b> -
+ * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the
+ * {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key</p>
+ *
* @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
*/
@PublicKey
@NonNull
- public static final Key<android.hardware.camera2.params.CapabilityAndMaxSize[]> CONTROL_AVAILABLE_BOKEH_CAPABILITIES =
- new Key<android.hardware.camera2.params.CapabilityAndMaxSize[]>("android.control.availableBokehCapabilities", android.hardware.camera2.params.CapabilityAndMaxSize[].class);
+ public static final Key<android.util.Range<Float>> CONTROL_ZOOM_RATIO_RANGE =
+ new Key<android.util.Range<Float>>("android.control.zoomRatioRange", new TypeReference<android.util.Range<Float>>() {{ }});
/**
* <p>List of edge enhancement modes for {@link CaptureRequest#EDGE_MODE android.edge.mode} that are supported by this camera
@@ -2215,11 +2289,16 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
* <p>Crop regions that have a width or height that is smaller
* than this ratio allows will be rounded up to the minimum
* allowed size by the camera device.</p>
+ * <p>Starting from API level 30, when using {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} to zoom in or out,
+ * the application must use {@link CameraCharacteristics#CONTROL_ZOOM_RATIO_RANGE android.control.zoomRatioRange} to query both the minimum and
+ * maximum zoom ratio.</p>
* <p><b>Units</b>: Zoom scale factor</p>
* <p><b>Range of valid values:</b><br>
* &gt;=1</p>
* <p>This key is available on all devices.</p>
*
+ * @see CaptureRequest#CONTROL_ZOOM_RATIO
+ * @see CameraCharacteristics#CONTROL_ZOOM_RATIO_RANGE
* @see CaptureRequest#SCALER_CROP_REGION
*/
@PublicKey
@@ -2667,6 +2746,21 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
* <p>Camera devices that support FREEFORM cropping will support any crop region that
* is inside of the active array. The camera device will apply the same crop region and
* return the final used crop region in capture result metadata {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}.</p>
+ * <p>Starting from API level 30,</p>
+ * <ul>
+ * <li>If the camera device supports FREEFORM cropping, in order to do FREEFORM cropping, the
+ * application must set {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} to 1.0, and use {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}
+ * for zoom.</li>
+ * <li>To do CENTER_ONLY zoom, the application has below 2 options:<ol>
+ * <li>Set {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} to 1.0; adjust zoom by {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}.</li>
+ * <li>Adjust zoom by {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio}; use {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} to crop
+ * the field of view vertically (letterboxing) or horizontally (pillarboxing), but not
+ * windowboxing.</li>
+ * </ol>
+ * </li>
+ * <li>Setting {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} to values different than 1.0 and
+ * {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} to be windowboxing at the same time is undefined behavior.</li>
+ * </ul>
* <p>LEGACY capability devices will only support CENTER_ONLY cropping.</p>
* <p><b>Possible values:</b>
* <ul>
@@ -2675,6 +2769,7 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
* </ul></p>
* <p>This key is available on all devices.</p>
*
+ * @see CaptureRequest#CONTROL_ZOOM_RATIO
* @see CaptureRequest#SCALER_CROP_REGION
* @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
* @see #SCALER_CROPPING_TYPE_CENTER_ONLY
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index b61b1efed125..9b58578e3811 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -1076,6 +1076,10 @@ public final class CameraManager {
}
public String[] getCameraIdListNoLazy() {
+ if (sCameraServiceDisabled) {
+ return new String[] {};
+ }
+
CameraStatus[] cameraStatuses;
ICameraServiceListener.Stub testListener = new ICameraServiceListener.Stub() {
@Override
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index f2a7abd60d85..8e0a46d52dd6 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -764,6 +764,7 @@ public abstract class CameraMetadata<TKey> {
* <li>{@link CaptureRequest#CONTROL_AWB_REGIONS android.control.awbRegions}</li>
* <li>{@link CaptureRequest#CONTROL_AF_TRIGGER android.control.afTrigger}</li>
* <li>{@link CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER android.control.aePrecaptureTrigger}</li>
+ * <li>{@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio}</li>
* </ul>
* <p>Outside of android.control.*, the following controls will work:</p>
* <ul>
@@ -812,6 +813,7 @@ public abstract class CameraMetadata<TKey> {
* @see CaptureRequest#CONTROL_AWB_REGIONS
* @see CaptureRequest#CONTROL_EFFECT_MODE
* @see CaptureRequest#CONTROL_MODE
+ * @see CaptureRequest#CONTROL_ZOOM_RATIO
* @see CaptureRequest#FLASH_MODE
* @see CaptureRequest#LENS_OPTICAL_STABILIZATION_MODE
* @see CaptureRequest#SCALER_CROP_REGION
@@ -2316,6 +2318,7 @@ public abstract class CameraMetadata<TKey> {
* <li>{@link CaptureRequest#CONTROL_AWB_REGIONS android.control.awbRegions}</li>
* <li>{@link CaptureRequest#CONTROL_AF_TRIGGER android.control.afTrigger}</li>
* <li>{@link CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER android.control.aePrecaptureTrigger}</li>
+ * <li>{@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio}</li>
* </ul>
* <p>Outside of android.control.*, the following controls will work:</p>
* <ul>
@@ -2362,6 +2365,7 @@ public abstract class CameraMetadata<TKey> {
* @see CaptureRequest#CONTROL_AWB_REGIONS
* @see CaptureRequest#CONTROL_EFFECT_MODE
* @see CaptureRequest#CONTROL_MODE
+ * @see CaptureRequest#CONTROL_ZOOM_RATIO
* @see CaptureRequest#FLASH_MODE
* @see CaptureRequest#LENS_OPTICAL_STABILIZATION_MODE
* @see CaptureRequest#SCALER_CROP_REGION
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 5c76dff85a84..6bf57834ae6c 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -1376,6 +1376,16 @@ 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>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
+ * {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} represent different parts of the scene. The aeRegions
+ * coordinates are relative to the activeArray/preCorrectionActiveArray representing the
+ * zoomed field of view. If {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} is set to 1.0 (default), the same
+ * aeRegions at different {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} still represent the same parts of the
+ * scene as they do before. See {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} for details. Whether to use
+ * activeArraySize or preCorrectionActiveArraySize still depends on distortion correction
+ * mode.</p>
* <p><b>Units</b>: Pixel coordinates within {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} or
* {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} depending on
* distortion correction capability and mode</p>
@@ -1386,6 +1396,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>>
* <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
*
* @see CameraCharacteristics#CONTROL_MAX_REGIONS_AE
+ * @see CaptureRequest#CONTROL_ZOOM_RATIO
* @see CaptureRequest#DISTORTION_CORRECTION_MODE
* @see CaptureRequest#SCALER_CROP_REGION
* @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
@@ -1575,6 +1586,16 @@ 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>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
+ * {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} represent different parts of the scene. The afRegions
+ * coordinates are relative to the activeArray/preCorrectionActiveArray representing the
+ * zoomed field of view. If {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} is set to 1.0 (default), the same
+ * afRegions at different {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} still represent the same parts of the
+ * scene as they do before. See {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} for details. Whether to use
+ * activeArraySize or preCorrectionActiveArraySize still depends on distortion correction
+ * mode.</p>
* <p><b>Units</b>: Pixel coordinates within {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} or
* {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} depending on
* distortion correction capability and mode</p>
@@ -1585,6 +1606,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>>
* <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
*
* @see CameraCharacteristics#CONTROL_MAX_REGIONS_AF
+ * @see CaptureRequest#CONTROL_ZOOM_RATIO
* @see CaptureRequest#DISTORTION_CORRECTION_MODE
* @see CaptureRequest#SCALER_CROP_REGION
* @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
@@ -1767,6 +1789,16 @@ 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>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
+ * {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} represent different parts of the scene. The awbRegions
+ * coordinates are relative to the activeArray/preCorrectionActiveArray representing the
+ * zoomed field of view. If {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} is set to 1.0 (default), the same
+ * awbRegions at different {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} still represent the same parts of
+ * the scene as they do before. See {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} for details. Whether to use
+ * activeArraySize or preCorrectionActiveArraySize still depends on distortion correction
+ * mode.</p>
* <p><b>Units</b>: Pixel coordinates within {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} or
* {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} depending on
* distortion correction capability and mode</p>
@@ -1777,6 +1809,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>>
* <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
*
* @see CameraCharacteristics#CONTROL_MAX_REGIONS_AWB
+ * @see CaptureRequest#CONTROL_ZOOM_RATIO
* @see CaptureRequest#DISTORTION_CORRECTION_MODE
* @see CaptureRequest#SCALER_CROP_REGION
* @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
@@ -2140,6 +2173,56 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>>
new Key<Integer>("android.control.bokehMode", int.class);
/**
+ * <p>The desired zoom ratio</p>
+ * <p>Instead of using {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} with dual purposes of crop and zoom, the
+ * application can now choose to use this tag to specify the desired zoom level. The
+ * {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} can still be used to specify the horizontal or vertical
+ * crop to achieve aspect ratios different than the native camera sensor.</p>
+ * <p>By using this control, the application gains a simpler way to control zoom, which can
+ * be a combination of optical and digital zoom. More specifically, for a logical
+ * multi-camera with more than one focal length, using a floating point zoom ratio offers
+ * more zoom precision when a telephoto lens is used, as well as allowing zoom ratio of
+ * less than 1.0 to zoom out to a wide field of view.</p>
+ * <p>Note that the coordinate system of cropRegion, AE/AWB/AF regions, and faces now changes
+ * to the effective after-zoom field-of-view represented by rectangle of (0, 0,
+ * activeArrayWidth, activeArrayHeight).</p>
+ * <p>For example, if {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} is 4032*3024, and the preview stream
+ * is configured to the same 4:3 aspect ratio, the application can achieve 2.0x zoom in
+ * one of two ways:</p>
+ * <ul>
+ * <li>zoomRatio = 2.0, scaler.cropRegion = (0, 0, 4032, 3024)</li>
+ * <li>zoomRatio = 1.0 (default), scaler.cropRegion = (1008, 756, 3024, 2268)</li>
+ * </ul>
+ * <p>If the application intends to set aeRegions to be top-left quarter of the preview
+ * field-of-view, the {@link CaptureRequest#CONTROL_AE_REGIONS android.control.aeRegions} should be set to (0, 0, 2016, 1512) with
+ * zoomRatio set to 2.0. Alternatively, the application can set aeRegions to the equivalent
+ * region of (1008, 756, 2016, 1512) for zoomRatio of 1.0. If the application doesn't
+ * explicitly set {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio}, its value defaults to 1.0.</p>
+ * <p>This coordinate system change isn't applicable to RAW capture and its related metadata
+ * such as intrinsicCalibration and lensShadingMap.</p>
+ * <p>One limitation of controlling zoom using zoomRatio is that the {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}
+ * must only be used for letterboxing or pillarboxing of the sensor active array, and no
+ * FREEFORM cropping can be used with {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} other than 1.0.</p>
+ * <p><b>Range of valid values:</b><br>
+ * {@link CameraCharacteristics#CONTROL_ZOOM_RATIO_RANGE android.control.zoomRatioRange}</p>
+ * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
+ * <p><b>Limited capability</b> -
+ * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the
+ * {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key</p>
+ *
+ * @see CaptureRequest#CONTROL_AE_REGIONS
+ * @see CaptureRequest#CONTROL_ZOOM_RATIO
+ * @see CameraCharacteristics#CONTROL_ZOOM_RATIO_RANGE
+ * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
+ * @see CaptureRequest#SCALER_CROP_REGION
+ * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
+ */
+ @PublicKey
+ @NonNull
+ public static final Key<Float> CONTROL_ZOOM_RATIO =
+ new Key<Float>("android.control.zoomRatio", float.class);
+
+ /**
* <p>Operation mode for edge
* enhancement.</p>
* <p>Edge enhancement improves sharpness and details in the captured image. OFF means
@@ -2697,12 +2780,21 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>>
* for rounding and other hardware requirements; the final
* crop region used will be included in the output capture
* result.</p>
+ * <p>Starting from API level 30, it's strongly recommended to use {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio}
+ * to take advantage of better support for zoom with logical multi-camera. The benefits
+ * include better precision with optical-digital zoom combination, and ability to do
+ * zoom-out from 1.0x. When using {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} for zoom, the crop region in
+ * the capture request must be either letterboxing or pillarboxing (but not both). The
+ * coordinate system is post-zoom, meaning that the activeArraySize or
+ * preCorrectionActiveArraySize covers the camera device's field of view "after" zoom.
+ * See {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} for details.</p>
* <p><b>Units</b>: Pixel coordinates relative to
* {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} or
* {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} depending on distortion correction
* capability and mode</p>
* <p>This key is available on all devices.</p>
*
+ * @see CaptureRequest#CONTROL_ZOOM_RATIO
* @see CaptureRequest#DISTORTION_CORRECTION_MODE
* @see CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM
* @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 2d0ec6d19286..c9956231f34c 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -780,6 +780,16 @@ 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>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
+ * {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} represent different parts of the scene. The aeRegions
+ * coordinates are relative to the activeArray/preCorrectionActiveArray representing the
+ * zoomed field of view. If {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} is set to 1.0 (default), the same
+ * aeRegions at different {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} still represent the same parts of the
+ * scene as they do before. See {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} for details. Whether to use
+ * activeArraySize or preCorrectionActiveArraySize still depends on distortion correction
+ * mode.</p>
* <p><b>Units</b>: Pixel coordinates within {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} or
* {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} depending on
* distortion correction capability and mode</p>
@@ -790,6 +800,7 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> {
* <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
*
* @see CameraCharacteristics#CONTROL_MAX_REGIONS_AE
+ * @see CaptureRequest#CONTROL_ZOOM_RATIO
* @see CaptureRequest#DISTORTION_CORRECTION_MODE
* @see CaptureRequest#SCALER_CROP_REGION
* @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
@@ -1228,6 +1239,16 @@ 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>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
+ * {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} represent different parts of the scene. The afRegions
+ * coordinates are relative to the activeArray/preCorrectionActiveArray representing the
+ * zoomed field of view. If {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} is set to 1.0 (default), the same
+ * afRegions at different {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} still represent the same parts of the
+ * scene as they do before. See {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} for details. Whether to use
+ * activeArraySize or preCorrectionActiveArraySize still depends on distortion correction
+ * mode.</p>
* <p><b>Units</b>: Pixel coordinates within {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} or
* {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} depending on
* distortion correction capability and mode</p>
@@ -1238,6 +1259,7 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> {
* <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
*
* @see CameraCharacteristics#CONTROL_MAX_REGIONS_AF
+ * @see CaptureRequest#CONTROL_ZOOM_RATIO
* @see CaptureRequest#DISTORTION_CORRECTION_MODE
* @see CaptureRequest#SCALER_CROP_REGION
* @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
@@ -1830,6 +1852,16 @@ 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>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
+ * {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} represent different parts of the scene. The awbRegions
+ * coordinates are relative to the activeArray/preCorrectionActiveArray representing the
+ * zoomed field of view. If {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} is set to 1.0 (default), the same
+ * awbRegions at different {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} still represent the same parts of
+ * the scene as they do before. See {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} for details. Whether to use
+ * activeArraySize or preCorrectionActiveArraySize still depends on distortion correction
+ * mode.</p>
* <p><b>Units</b>: Pixel coordinates within {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} or
* {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} depending on
* distortion correction capability and mode</p>
@@ -1840,6 +1872,7 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> {
* <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
*
* @see CameraCharacteristics#CONTROL_MAX_REGIONS_AWB
+ * @see CaptureRequest#CONTROL_ZOOM_RATIO
* @see CaptureRequest#DISTORTION_CORRECTION_MODE
* @see CaptureRequest#SCALER_CROP_REGION
* @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
@@ -2370,6 +2403,56 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> {
new Key<Integer>("android.control.bokehMode", int.class);
/**
+ * <p>The desired zoom ratio</p>
+ * <p>Instead of using {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} with dual purposes of crop and zoom, the
+ * application can now choose to use this tag to specify the desired zoom level. The
+ * {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} can still be used to specify the horizontal or vertical
+ * crop to achieve aspect ratios different than the native camera sensor.</p>
+ * <p>By using this control, the application gains a simpler way to control zoom, which can
+ * be a combination of optical and digital zoom. More specifically, for a logical
+ * multi-camera with more than one focal length, using a floating point zoom ratio offers
+ * more zoom precision when a telephoto lens is used, as well as allowing zoom ratio of
+ * less than 1.0 to zoom out to a wide field of view.</p>
+ * <p>Note that the coordinate system of cropRegion, AE/AWB/AF regions, and faces now changes
+ * to the effective after-zoom field-of-view represented by rectangle of (0, 0,
+ * activeArrayWidth, activeArrayHeight).</p>
+ * <p>For example, if {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} is 4032*3024, and the preview stream
+ * is configured to the same 4:3 aspect ratio, the application can achieve 2.0x zoom in
+ * one of two ways:</p>
+ * <ul>
+ * <li>zoomRatio = 2.0, scaler.cropRegion = (0, 0, 4032, 3024)</li>
+ * <li>zoomRatio = 1.0 (default), scaler.cropRegion = (1008, 756, 3024, 2268)</li>
+ * </ul>
+ * <p>If the application intends to set aeRegions to be top-left quarter of the preview
+ * field-of-view, the {@link CaptureRequest#CONTROL_AE_REGIONS android.control.aeRegions} should be set to (0, 0, 2016, 1512) with
+ * zoomRatio set to 2.0. Alternatively, the application can set aeRegions to the equivalent
+ * region of (1008, 756, 2016, 1512) for zoomRatio of 1.0. If the application doesn't
+ * explicitly set {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio}, its value defaults to 1.0.</p>
+ * <p>This coordinate system change isn't applicable to RAW capture and its related metadata
+ * such as intrinsicCalibration and lensShadingMap.</p>
+ * <p>One limitation of controlling zoom using zoomRatio is that the {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}
+ * must only be used for letterboxing or pillarboxing of the sensor active array, and no
+ * FREEFORM cropping can be used with {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} other than 1.0.</p>
+ * <p><b>Range of valid values:</b><br>
+ * {@link CameraCharacteristics#CONTROL_ZOOM_RATIO_RANGE android.control.zoomRatioRange}</p>
+ * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
+ * <p><b>Limited capability</b> -
+ * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the
+ * {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key</p>
+ *
+ * @see CaptureRequest#CONTROL_AE_REGIONS
+ * @see CaptureRequest#CONTROL_ZOOM_RATIO
+ * @see CameraCharacteristics#CONTROL_ZOOM_RATIO_RANGE
+ * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
+ * @see CaptureRequest#SCALER_CROP_REGION
+ * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
+ */
+ @PublicKey
+ @NonNull
+ public static final Key<Float> CONTROL_ZOOM_RATIO =
+ new Key<Float>("android.control.zoomRatio", float.class);
+
+ /**
* <p>Operation mode for edge
* enhancement.</p>
* <p>Edge enhancement improves sharpness and details in the captured image. OFF means
@@ -3336,12 +3419,21 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> {
* for rounding and other hardware requirements; the final
* crop region used will be included in the output capture
* result.</p>
+ * <p>Starting from API level 30, it's strongly recommended to use {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio}
+ * to take advantage of better support for zoom with logical multi-camera. The benefits
+ * include better precision with optical-digital zoom combination, and ability to do
+ * zoom-out from 1.0x. When using {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} for zoom, the crop region in
+ * the capture request must be either letterboxing or pillarboxing (but not both). The
+ * coordinate system is post-zoom, meaning that the activeArraySize or
+ * preCorrectionActiveArraySize covers the camera device's field of view "after" zoom.
+ * See {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} for details.</p>
* <p><b>Units</b>: Pixel coordinates relative to
* {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} or
* {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} depending on distortion correction
* capability and mode</p>
* <p>This key is available on all devices.</p>
*
+ * @see CaptureRequest#CONTROL_ZOOM_RATIO
* @see CaptureRequest#DISTORTION_CORRECTION_MODE
* @see CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM
* @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
@@ -3877,10 +3969,21 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> {
* When the distortion correction mode is not OFF, the coordinate system follows
* {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with
* <code>(0, 0)</code> being the top-left pixel of the active array.</p>
- * <p>Only available if {@link CaptureRequest#STATISTICS_FACE_DETECT_MODE android.statistics.faceDetectMode} == FULL
- * This key is available on all devices.</p>
+ * <p>Only available if {@link CaptureRequest#STATISTICS_FACE_DETECT_MODE android.statistics.faceDetectMode} == FULL.</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-zoomRatio field of view. This means that if the relative position of faces and
+ * the camera device doesn't change, when zooming in by increasing
+ * {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio}, the face landmarks move farther away from the center of the
+ * activeArray or preCorrectionActiveArray. If {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} is set to 1.0
+ * (default), the face landmarks coordinates won't change as {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}
+ * changes. See {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} for details. Whether to use activeArraySize or
+ * preCorrectionActiveArraySize still depends on distortion correction mode.</p>
+ * <p>This key is available on all devices.</p>
*
+ * @see CaptureRequest#CONTROL_ZOOM_RATIO
* @see CaptureRequest#DISTORTION_CORRECTION_MODE
+ * @see CaptureRequest#SCALER_CROP_REGION
* @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
* @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
* @see CaptureRequest#STATISTICS_FACE_DETECT_MODE
@@ -3903,10 +4006,21 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> {
* When the distortion correction mode is not OFF, the coordinate system follows
* {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with
* <code>(0, 0)</code> being the top-left pixel of the active array.</p>
- * <p>Only available if {@link CaptureRequest#STATISTICS_FACE_DETECT_MODE android.statistics.faceDetectMode} != OFF
- * This key is available on all devices.</p>
+ * <p>Only available if {@link CaptureRequest#STATISTICS_FACE_DETECT_MODE android.statistics.faceDetectMode} != OFF.</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-zoomRatio field of view. This means that if the relative position of faces and
+ * the camera device doesn't change, when zooming in by increasing
+ * {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio}, the face rectangles grow larger and move farther away from
+ * the center of the activeArray or preCorrectionActiveArray. If {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio}
+ * is set to 1.0 (default), the face rectangles won't change as {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}
+ * changes. See {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} for details. Whether to use activeArraySize or
+ * preCorrectionActiveArraySize still depends on distortion correction mode.</p>
+ * <p>This key is available on all devices.</p>
*
+ * @see CaptureRequest#CONTROL_ZOOM_RATIO
* @see CaptureRequest#DISTORTION_CORRECTION_MODE
+ * @see CaptureRequest#SCALER_CROP_REGION
* @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
* @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
* @see CaptureRequest#STATISTICS_FACE_DETECT_MODE
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
index 7c1ddad5fe12..6f90db424847 100644
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
+++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
@@ -30,7 +30,6 @@ import android.hardware.camera2.marshal.MarshalRegistry;
import android.hardware.camera2.marshal.Marshaler;
import android.hardware.camera2.marshal.impl.MarshalQueryableArray;
import android.hardware.camera2.marshal.impl.MarshalQueryableBlackLevelPattern;
-import android.hardware.camera2.marshal.impl.MarshalQueryableCapabilityAndMaxSize;
import android.hardware.camera2.marshal.impl.MarshalQueryableBoolean;
import android.hardware.camera2.marshal.impl.MarshalQueryableColorSpaceTransform;
import android.hardware.camera2.marshal.impl.MarshalQueryableEnum;
@@ -50,7 +49,7 @@ import android.hardware.camera2.marshal.impl.MarshalQueryableSizeF;
import android.hardware.camera2.marshal.impl.MarshalQueryableStreamConfiguration;
import android.hardware.camera2.marshal.impl.MarshalQueryableStreamConfigurationDuration;
import android.hardware.camera2.marshal.impl.MarshalQueryableString;
-import android.hardware.camera2.params.CapabilityAndMaxSize;
+import android.hardware.camera2.params.Capability;
import android.hardware.camera2.params.Face;
import android.hardware.camera2.params.HighSpeedVideoConfiguration;
import android.hardware.camera2.params.LensShadingMap;
@@ -71,6 +70,7 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.os.ServiceSpecificException;
import android.util.Log;
+import android.util.Range;
import android.util.Size;
import com.android.internal.util.Preconditions;
@@ -240,6 +240,11 @@ public class CameraMetadataNative implements Parcelable {
*
* <p>This value is looked up the first time, and cached subsequently.</p>
*
+ * <p>This function may be called without cacheTag() if this is not a vendor key.
+ * If this is a vendor key, cacheTag() must be called first before getTag() can
+ * be called. Otherwise, mVendorId could be default (Long.MAX_VALUE) and vendor
+ * tag lookup could fail.</p>
+ *
* @return The tag numeric value corresponding to the string
*/
@UnsupportedAppUsage
@@ -252,6 +257,27 @@ public class CameraMetadataNative implements Parcelable {
}
/**
+ * Whether this key's tag is cached.
+ *
+ * @hide
+ */
+ @UnsupportedAppUsage
+ public final boolean hasTag() {
+ return mHasTag;
+ }
+
+ /**
+ * Cache this key's tag.
+ *
+ * @hide
+ */
+ @UnsupportedAppUsage
+ public final void cacheTag(int tag) {
+ mHasTag = true;
+ mTag = tag;
+ }
+
+ /**
* Get the raw class backing the type {@code T} for this key.
*
* <p>The distinction is only important if {@code T} is a generic, e.g.
@@ -523,7 +549,13 @@ public class CameraMetadataNative implements Parcelable {
}
private <T> T getBase(Key<T> key) {
- int tag = nativeGetTagFromKeyLocal(key.getName());
+ int tag;
+ if (key.hasTag()) {
+ tag = key.getTag();
+ } else {
+ tag = nativeGetTagFromKeyLocal(key.getName());
+ key.cacheTag(tag);
+ }
byte[] values = readValues(tag);
if (values == null) {
// If the key returns null, use the fallback key if exists.
@@ -1385,22 +1417,57 @@ public class CameraMetadataNative implements Parcelable {
return samples;
}
- private CapabilityAndMaxSize[] getBokehCapabilities() {
- CapabilityAndMaxSize[] bcs = getBase(
- CameraCharacteristics.CONTROL_AVAILABLE_BOKEH_CAPABILITIES);
+ private Capability[] getBokehCapabilities() {
+ int[] bokehMaxSizes = getBase(CameraCharacteristics.CONTROL_AVAILABLE_BOKEH_MAX_SIZES);
+ float[] bokehZoomRanges = getBase(
+ CameraCharacteristics.CONTROL_AVAILABLE_BOKEH_ZOOM_RATIO_RANGES);
+ Range<Float> zoomRange = getBase(CameraCharacteristics.CONTROL_ZOOM_RATIO_RANGE);
+ float maxDigitalZoom = getBase(CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM);
- if (bcs != null) {
- for (CapabilityAndMaxSize bc : bcs) {
- if (bc.getMode() < CameraMetadata.CONTROL_BOKEH_MODE_OFF ||
- bc.getMode() > CameraMetadata.CONTROL_BOKEH_MODE_CONTINUOUS) {
- throw new AssertionError(String.format(
- "bokehMode %d is out of valid range [%d, %d]", bc.getMode(),
- CameraMetadata.CONTROL_BOKEH_MODE_OFF,
- CameraMetadata.CONTROL_BOKEH_MODE_CONTINUOUS));
- }
+ if (bokehMaxSizes == null) {
+ return null;
+ }
+ if (bokehMaxSizes.length % 3 != 0) {
+ throw new AssertionError("availableBokehMaxSizes must be tuples of " +
+ "[mode, width, height]");
+ }
+ int numBokehModes = bokehMaxSizes.length / 3;
+ int numBokehZoomRanges = 0;
+ if (bokehZoomRanges != null) {
+ if (bokehZoomRanges.length % 2 != 0) {
+ throw new AssertionError("availableBokehZoomRanges must be tuples of " +
+ "[minZoom, maxZoom]");
+ }
+ numBokehZoomRanges = bokehZoomRanges.length / 2;
+ if (numBokehModes - numBokehZoomRanges != 1) {
+ throw new AssertionError("Number of bokeh zoom ranges must be 1 less than " +
+ "number of supported bokeh modes");
}
}
- return bcs;
+
+ float bokehOffMinZoomRatio = 1.0f;
+ float bokehOffMaxZoomRatio = maxDigitalZoom;
+ if (zoomRange != null) {
+ bokehOffMinZoomRatio = zoomRange.getLower();
+ bokehOffMaxZoomRatio = zoomRange.getUpper();
+ }
+
+ Capability[] capabilities = new Capability[numBokehModes];
+ for (int i = 0, j = 0; i < numBokehModes; i++) {
+ int mode = bokehMaxSizes[3 * i];
+ int width = bokehMaxSizes[3 * i + 1];
+ int height = bokehMaxSizes[3 * i + 2];
+ if (mode != CameraMetadata.CONTROL_BOKEH_MODE_OFF && j < numBokehZoomRanges) {
+ capabilities[i] = new Capability(mode, width, height, bokehZoomRanges[2 * j],
+ bokehZoomRanges[2 * j + 1]);
+ j++;
+ } else {
+ capabilities[i] = new Capability(mode, width, height, bokehOffMinZoomRatio,
+ bokehOffMaxZoomRatio);
+ }
+ }
+
+ return capabilities;
}
private <T> void setBase(CameraCharacteristics.Key<T> key, T value) {
@@ -1416,7 +1483,13 @@ public class CameraMetadataNative implements Parcelable {
}
private <T> void setBase(Key<T> key, T value) {
- int tag = nativeGetTagFromKeyLocal(key.getName());
+ int tag;
+ if (key.hasTag()) {
+ tag = key.getTag();
+ } else {
+ tag = nativeGetTagFromKeyLocal(key.getName());
+ key.cacheTag(tag);
+ }
if (value == null) {
// Erase the entry
writeValues(tag, /*src*/null);
@@ -1780,7 +1853,6 @@ public class CameraMetadataNative implements Parcelable {
new MarshalQueryableBlackLevelPattern(),
new MarshalQueryableHighSpeedVideoConfiguration(),
new MarshalQueryableRecommendedStreamConfiguration(),
- new MarshalQueryableCapabilityAndMaxSize(),
// generic parcelable marshaler (MUST BE LAST since it has lowest priority)
new MarshalQueryableParcelable(),
diff --git a/core/java/android/hardware/camera2/marshal/impl/MarshalQueryableCapabilityAndMaxSize.java b/core/java/android/hardware/camera2/marshal/impl/MarshalQueryableCapabilityAndMaxSize.java
deleted file mode 100644
index 5c1f301369e1..000000000000
--- a/core/java/android/hardware/camera2/marshal/impl/MarshalQueryableCapabilityAndMaxSize.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.hardware.camera2.marshal.impl;
-
-import android.hardware.camera2.marshal.MarshalQueryable;
-import android.hardware.camera2.marshal.Marshaler;
-import android.hardware.camera2.params.CapabilityAndMaxSize;
-import android.hardware.camera2.utils.TypeReference;
-import android.util.Size;
-
-import java.nio.ByteBuffer;
-
-import static android.hardware.camera2.impl.CameraMetadataNative.TYPE_INT32;
-import static android.hardware.camera2.marshal.MarshalHelpers.SIZEOF_INT32;
-
-/**
- * Marshal {@link CapabilityAndMaxSize} to/from {@link #TYPE_INT32} {@code x CapabilityAndMaxSize.COUNT}
- */
-public class MarshalQueryableCapabilityAndMaxSize implements MarshalQueryable<CapabilityAndMaxSize> {
- private static final int SIZE = SIZEOF_INT32 * CapabilityAndMaxSize.COUNT;
-
- private class MarshalerCapabilityAndMaxSize extends Marshaler<CapabilityAndMaxSize> {
- protected MarshalerCapabilityAndMaxSize(TypeReference<CapabilityAndMaxSize> typeReference,
- int nativeType) {
- super(MarshalQueryableCapabilityAndMaxSize.this, typeReference, nativeType);
- }
-
- @Override
- public void marshal(CapabilityAndMaxSize value, ByteBuffer buffer) {
- Size maxStreamingSize = value.getMaxStreamingSize();
-
- buffer.putInt(value.getMode());
- buffer.putInt(maxStreamingSize.getWidth());
- buffer.putInt(maxStreamingSize.getHeight());
- }
-
- @Override
- public CapabilityAndMaxSize unmarshal(ByteBuffer buffer) {
- int mode = buffer.getInt();
- int maxWidth = buffer.getInt();
- int maxHeight = buffer.getInt();
-
- return new CapabilityAndMaxSize(mode, maxWidth, maxHeight);
- }
-
- @Override
- public int getNativeSize() {
- return SIZE;
- }
- }
-
- @Override
- public Marshaler<CapabilityAndMaxSize> createMarshaler(
- TypeReference<CapabilityAndMaxSize> managedType, int nativeType) {
- return new MarshalerCapabilityAndMaxSize(managedType, nativeType);
- }
-
- @Override
- public boolean isTypeMappingSupported(
- TypeReference<CapabilityAndMaxSize> managedType, int nativeType) {
- return nativeType == TYPE_INT32 &&
- (CapabilityAndMaxSize.class.equals(managedType.getType()));
- }
-}
diff --git a/core/java/android/hardware/camera2/params/CapabilityAndMaxSize.java b/core/java/android/hardware/camera2/params/Capability.java
index be0829934a4b..367690c37960 100644
--- a/core/java/android/hardware/camera2/params/CapabilityAndMaxSize.java
+++ b/core/java/android/hardware/camera2/params/Capability.java
@@ -23,16 +23,17 @@ import android.annotation.NonNull;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.utils.HashCodeHelpers;
+import android.util.Range;
import android.util.Size;
/**
- * Immutable class to store the available camera capability and its
- * corresponding maximum streaming dimensions.
+ * Immutable class to store the camera capability, its corresponding maximum
+ * streaming dimension and zoom range.
*
* @see CameraCharacteristics#CONTROL_AVAILABLE_BOKEH_CAPABILITIES
*/
-public final class CapabilityAndMaxSize {
+public final class Capability {
/**
* @hide
*/
@@ -41,22 +42,31 @@ public final class CapabilityAndMaxSize {
private final int mMode;
private final int mMaxStreamingWidth;
private final int mMaxStreamingHeight;
+ private final float mMinZoomRatio;
+ private final float mMaxZoomRatio;
/**
- * Create a new CapabilityAndMaxSize object.
+ * Create a new Capability object.
*
* @param mode supported mode for a camera capability.
- * @param maxStreamingWidth width >= 0
- * @param maxStreamingHeight height >= 0
+ * @param maxStreamingWidth The width of the maximum streaming size for this mode
+ * @param maxStreamingHeight The height of the maximum streaming size for this mode
+ * @param minZoomRatio the minimum zoom ratio this mode supports
+ * @param maxZoomRatio the maximum zoom ratio this mode supports
*
+ * @throws IllegalArgumentException if any of the argument is not valid
* @hide
*/
- public CapabilityAndMaxSize(int mode, int maxStreamingWidth, int maxStreamingHeight) {
+ public Capability(int mode, int maxStreamingWidth, int maxStreamingHeight,
+ float minZoomRatio, float maxZoomRatio) {
mMode = mode;
mMaxStreamingWidth = checkArgumentNonnegative(maxStreamingWidth,
"maxStreamingWidth must be nonnegative");
mMaxStreamingHeight = checkArgumentNonnegative(maxStreamingHeight,
"maxStreamingHeight must be nonnegative");
+ mMinZoomRatio = checkArgumentInRange(minZoomRatio, 0.0f, 1.0f,
+ "minZoomRatio must be between 0.0f and 1.0f");
+ mMaxZoomRatio = maxZoomRatio;
}
/**
@@ -81,11 +91,22 @@ public final class CapabilityAndMaxSize {
}
/**
- * Compare two CapabilityAndMaxSize objects to see if they are equal.
+ * Return the zoom ratio range of this capability.
*
- * @param obj Another CapabilityAndMaxSize object
+ * @return The supported zoom ratio range supported by this capability
+ */
+ public @NonNull Range<Float> getZoomRatioRange() {
+ return new Range<Float>(mMinZoomRatio, mMaxZoomRatio);
+ }
+
+
+ /**
+ * Compare two Capability objects to see if they are equal.
+ *
+ * @param obj Another Capability object
*
- * @return {@code true} if the mode and max size are equal, {@code false} otherwise
+ * @return {@code true} if the mode, max size and zoom ratio range are equal,
+ * {@code false} otherwise
*/
@Override
public boolean equals(final Object obj) {
@@ -95,11 +116,13 @@ public final class CapabilityAndMaxSize {
if (this == obj) {
return true;
}
- if (obj instanceof CapabilityAndMaxSize) {
- final CapabilityAndMaxSize other = (CapabilityAndMaxSize) obj;
+ if (obj instanceof Capability) {
+ final Capability other = (Capability) obj;
return (mMode == other.mMode
&& mMaxStreamingWidth == other.mMaxStreamingWidth
- && mMaxStreamingHeight == other.mMaxStreamingHeight);
+ && mMaxStreamingHeight == other.mMaxStreamingHeight
+ && mMinZoomRatio == other.mMinZoomRatio
+ && mMaxZoomRatio == other.mMaxZoomRatio);
}
return false;
}
@@ -109,18 +132,20 @@ public final class CapabilityAndMaxSize {
*/
@Override
public int hashCode() {
- return HashCodeHelpers.hashCode(mMode, mMaxStreamingWidth, mMaxStreamingHeight);
+ return HashCodeHelpers.hashCode(mMode, mMaxStreamingWidth, mMaxStreamingHeight,
+ mMinZoomRatio, mMaxZoomRatio);
}
/**
- * Return the CapabilityAndMaxSize as a string representation
- * {@code "(mode:%d, maxStreamingSize:%d x %d)"}.
+ * Return the Capability as a string representation
+ * {@code "(mode:%d, maxStreamingSize:%d x %d, zoomRatio: %f-%f)"}.
*
* @return string representation of the capability and max streaming size.
*/
@Override
public String toString() {
- return String.format("(mode:%d, maxStreamingSize:%d x %d)",
- mMode, mMaxStreamingWidth, mMaxStreamingHeight);
+ return String.format("(mode:%d, maxStreamingSize:%d x %d, zoomRatio: %f-%f)",
+ mMode, mMaxStreamingWidth, mMaxStreamingHeight, mMinZoomRatio,
+ mMaxZoomRatio);
}
}
diff --git a/core/java/android/hardware/display/BrightnessConfiguration.java b/core/java/android/hardware/display/BrightnessConfiguration.java
index 139be8ee4d7b..0a385389e2cf 100644
--- a/core/java/android/hardware/display/BrightnessConfiguration.java
+++ b/core/java/android/hardware/display/BrightnessConfiguration.java
@@ -16,6 +16,7 @@
package android.hardware.display;
+import android.annotation.FloatRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
@@ -56,6 +57,16 @@ public final class BrightnessConfiguration implements Parcelable {
private static final String ATTR_PACKAGE_NAME = "package-name";
private static final String ATTR_CATEGORY = "category";
private static final String ATTR_COLLECT_COLOR = "collect-color";
+ private static final String ATTR_MODEL_TIMEOUT = "model-timeout";
+ private static final String ATTR_MODEL_LOWER_BOUND = "model-lower-bound";
+ private static final String ATTR_MODEL_UPPER_BOUND = "model-upper-bound";
+ /**
+ * Returned from {@link #getShortTermModelTimeout()} if no timeout has been set.
+ * In this case the device will use the default timeout available in the
+ * {@link BrightnessConfiguration} returned from
+ * {@link DisplayManager#getDefaultBrightnessConfiguration()}.
+ */
+ public static final long SHORT_TERM_TIMEOUT_UNSET = -1;
private final float[] mLux;
private final float[] mNits;
@@ -63,17 +74,26 @@ public final class BrightnessConfiguration implements Parcelable {
private final Map<Integer, BrightnessCorrection> mCorrectionsByCategory;
private final String mDescription;
private final boolean mShouldCollectColorSamples;
+ private final long mShortTermModelTimeout;
+ private final float mShortTermModelLowerLuxMultiplier;
+ private final float mShortTermModelUpperLuxMultiplier;
private BrightnessConfiguration(float[] lux, float[] nits,
Map<String, BrightnessCorrection> correctionsByPackageName,
Map<Integer, BrightnessCorrection> correctionsByCategory, String description,
- boolean shouldCollectColorSamples) {
+ boolean shouldCollectColorSamples,
+ long shortTermModelTimeout,
+ float shortTermModelLowerLuxMultiplier,
+ float shortTermModelUpperLuxMultiplier) {
mLux = lux;
mNits = nits;
mCorrectionsByPackageName = correctionsByPackageName;
mCorrectionsByCategory = correctionsByCategory;
mDescription = description;
mShouldCollectColorSamples = shouldCollectColorSamples;
+ mShortTermModelTimeout = shortTermModelTimeout;
+ mShortTermModelLowerLuxMultiplier = shortTermModelLowerLuxMultiplier;
+ mShortTermModelUpperLuxMultiplier = shortTermModelUpperLuxMultiplier;
}
/**
@@ -132,6 +152,42 @@ public final class BrightnessConfiguration implements Parcelable {
return mShouldCollectColorSamples;
}
+ /**
+ * Returns the timeout for the short term model in milliseconds.
+ *
+ * If the screen is inactive for this timeout then the short term model
+ * will check the lux range defined by {@link #getShortTermModelLowerLuxMultiplier()} and
+ * {@link #getShortTermModelUpperLuxMultiplier()} to decide whether to keep any adjustment
+ * the user has made to adaptive brightness.
+ */
+ public long getShortTermModelTimeout() {
+ return mShortTermModelTimeout;
+ }
+
+ /**
+ * Returns the multiplier used to calculate the upper bound for which
+ * a users adaptive brightness is considered valid.
+ *
+ * For example if a user changes the brightness when the ambient light level
+ * is 100 lux, the adjustment will be kept if the current ambient light level
+ * is {@code <= 100 + (100 * getShortTermModelUpperLuxMultiplier())}.
+ */
+ public float getShortTermModelUpperLuxMultiplier() {
+ return mShortTermModelUpperLuxMultiplier;
+ }
+
+ /**
+ * Returns the multiplier used to calculate the lower bound for which
+ * a users adaptive brightness is considered valid.
+ *
+ * For example if a user changes the brightness when the ambient light level
+ * is 100 lux, the adjustment will be kept if the current ambient light level
+ * is {@code >= 100 - (100 * getShortTermModelLowerLuxMultiplier())}.
+ */
+ public float getShortTermModelLowerLuxMultiplier() {
+ return mShortTermModelLowerLuxMultiplier;
+ }
+
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeFloatArray(mLux);
@@ -152,6 +208,9 @@ public final class BrightnessConfiguration implements Parcelable {
}
dest.writeString(mDescription);
dest.writeBoolean(mShouldCollectColorSamples);
+ dest.writeLong(mShortTermModelTimeout);
+ dest.writeFloat(mShortTermModelLowerLuxMultiplier);
+ dest.writeFloat(mShortTermModelUpperLuxMultiplier);
}
@Override
@@ -182,6 +241,15 @@ public final class BrightnessConfiguration implements Parcelable {
sb.append(mDescription);
}
sb.append(", shouldCollectColorSamples = " + mShouldCollectColorSamples);
+ if (mShortTermModelTimeout >= 0) {
+ sb.append(", shortTermModelTimeout = " + mShortTermModelTimeout);
+ }
+ if (!Float.isNaN(mShortTermModelLowerLuxMultiplier)) {
+ sb.append(", shortTermModelLowerLuxMultiplier = " + mShortTermModelLowerLuxMultiplier);
+ }
+ if (!Float.isNaN(mShortTermModelLowerLuxMultiplier)) {
+ sb.append(", shortTermModelUpperLuxMultiplier = " + mShortTermModelUpperLuxMultiplier);
+ }
sb.append("'}");
return sb.toString();
}
@@ -197,6 +265,9 @@ public final class BrightnessConfiguration implements Parcelable {
result = result * 31 + mDescription.hashCode();
}
result = result * 31 + Boolean.hashCode(mShouldCollectColorSamples);
+ result = result * 31 + Long.hashCode(mShortTermModelTimeout);
+ result = result * 31 + Float.hashCode(mShortTermModelLowerLuxMultiplier);
+ result = result * 31 + Float.hashCode(mShortTermModelUpperLuxMultiplier);
return result;
}
@@ -213,7 +284,19 @@ public final class BrightnessConfiguration implements Parcelable {
&& mCorrectionsByPackageName.equals(other.mCorrectionsByPackageName)
&& mCorrectionsByCategory.equals(other.mCorrectionsByCategory)
&& Objects.equals(mDescription, other.mDescription)
- && mShouldCollectColorSamples == other.mShouldCollectColorSamples;
+ && mShouldCollectColorSamples == other.mShouldCollectColorSamples
+ && mShortTermModelTimeout == other.mShortTermModelTimeout
+ && checkFloatEquals(mShortTermModelLowerLuxMultiplier,
+ other.mShortTermModelLowerLuxMultiplier)
+ && checkFloatEquals(mShortTermModelUpperLuxMultiplier,
+ other.mShortTermModelUpperLuxMultiplier);
+ }
+
+ private boolean checkFloatEquals(float one, float two) {
+ if (Float.isNaN(one) && Float.isNaN(two)) {
+ return true;
+ }
+ return one == two;
}
public static final @android.annotation.NonNull Creator<BrightnessConfiguration> CREATOR =
@@ -243,6 +326,9 @@ public final class BrightnessConfiguration implements Parcelable {
builder.setDescription(description);
final boolean shouldCollectColorSamples = in.readBoolean();
builder.setShouldCollectColorSamples(shouldCollectColorSamples);
+ builder.setShortTermModelTimeout(in.readLong());
+ builder.setShortTermModelLowerLuxMultiplier(in.readFloat());
+ builder.setShortTermModelUpperLuxMultiplier(in.readFloat());
return builder.build();
}
@@ -296,6 +382,18 @@ public final class BrightnessConfiguration implements Parcelable {
if (mShouldCollectColorSamples) {
serializer.attribute(null, ATTR_COLLECT_COLOR, Boolean.toString(true));
}
+ if (mShortTermModelTimeout >= 0) {
+ serializer.attribute(null, ATTR_MODEL_TIMEOUT,
+ Long.toString(mShortTermModelTimeout));
+ }
+ if (!Float.isNaN(mShortTermModelLowerLuxMultiplier)) {
+ serializer.attribute(null, ATTR_MODEL_LOWER_BOUND,
+ Float.toString(mShortTermModelLowerLuxMultiplier));
+ }
+ if (!Float.isNaN(mShortTermModelUpperLuxMultiplier)) {
+ serializer.attribute(null, ATTR_MODEL_UPPER_BOUND,
+ Float.toString(mShortTermModelUpperLuxMultiplier));
+ }
serializer.endTag(null, TAG_BRIGHTNESS_PARAMS);
}
@@ -320,6 +418,9 @@ public final class BrightnessConfiguration implements Parcelable {
Map<String, BrightnessCorrection> correctionsByPackageName = new HashMap<>();
Map<Integer, BrightnessCorrection> correctionsByCategory = new HashMap<>();
boolean shouldCollectColorSamples = false;
+ long shortTermModelTimeout = SHORT_TERM_TIMEOUT_UNSET;
+ float shortTermModelLowerLuxMultiplier = Float.NaN;
+ float shortTermModelUpperLuxMultiplier = Float.NaN;
final int configDepth = parser.getDepth();
while (XmlUtils.nextElementWithin(parser, configDepth)) {
if (TAG_BRIGHTNESS_CURVE.equals(parser.getName())) {
@@ -357,6 +458,12 @@ public final class BrightnessConfiguration implements Parcelable {
} else if (TAG_BRIGHTNESS_PARAMS.equals(parser.getName())) {
shouldCollectColorSamples =
Boolean.parseBoolean(parser.getAttributeValue(null, ATTR_COLLECT_COLOR));
+ Long timeout = loadLongFromXml(parser, ATTR_MODEL_TIMEOUT);
+ if (timeout != null) {
+ shortTermModelTimeout = timeout;
+ }
+ shortTermModelLowerLuxMultiplier = loadFloatFromXml(parser, ATTR_MODEL_LOWER_BOUND);
+ shortTermModelUpperLuxMultiplier = loadFloatFromXml(parser, ATTR_MODEL_UPPER_BOUND);
}
}
final int n = luxList.size();
@@ -380,6 +487,9 @@ public final class BrightnessConfiguration implements Parcelable {
builder.addCorrectionByCategory(category, correction);
}
builder.setShouldCollectColorSamples(shouldCollectColorSamples);
+ builder.setShortTermModelTimeout(shortTermModelTimeout);
+ builder.setShortTermModelLowerLuxMultiplier(shortTermModelLowerLuxMultiplier);
+ builder.setShortTermModelUpperLuxMultiplier(shortTermModelUpperLuxMultiplier);
return builder.build();
}
@@ -392,6 +502,16 @@ public final class BrightnessConfiguration implements Parcelable {
}
}
+ private static Long loadLongFromXml(XmlPullParser parser, String attribute) {
+ final String string = parser.getAttributeValue(null, attribute);
+ try {
+ return Long.parseLong(string);
+ } catch (NullPointerException | NumberFormatException e) {
+ // Ignoring
+ }
+ return null;
+ }
+
/**
* A builder class for {@link BrightnessConfiguration}s.
*/
@@ -405,6 +525,9 @@ public final class BrightnessConfiguration implements Parcelable {
private Map<Integer, BrightnessCorrection> mCorrectionsByCategory;
private String mDescription;
private boolean mShouldCollectColorSamples;
+ private long mShortTermModelTimeout = SHORT_TERM_TIMEOUT_UNSET;
+ private float mShortTermModelLowerLuxMultiplier = Float.NaN;
+ private float mShortTermModelUpperLuxMultiplier = Float.NaN;
/**
* Constructs the builder with the control points for the brightness curve.
@@ -542,6 +665,60 @@ public final class BrightnessConfiguration implements Parcelable {
}
/**
+ * Sets the timeout for the short term model in milliseconds.
+ *
+ * If the screen is inactive for this timeout then the short term model
+ * will check the lux range defined by {@link #setShortTermModelLowerLuxMultiplier(float))}
+ * and {@link #setShortTermModelUpperLuxMultiplier(float)} to decide whether to keep any
+ * adjustment the user has made to adaptive brightness.
+ */
+ @NonNull
+ public Builder setShortTermModelTimeout(long shortTermModelTimeout) {
+ mShortTermModelTimeout = shortTermModelTimeout;
+ return this;
+ }
+
+ /**
+ * Sets the multiplier used to calculate the upper bound for which
+ * a users adaptive brightness is considered valid.
+ *
+ * For example if a user changes the brightness when the ambient light level
+ * is 100 lux, the adjustment will be kept if the current ambient light level
+ * is {@code <= 100 + (100 * shortTermModelUpperLuxMultiplier)}.
+ *
+ * @throws IllegalArgumentException if shortTermModelUpperLuxMultiplier is negative.
+ */
+ @NonNull
+ public Builder setShortTermModelUpperLuxMultiplier(
+ @FloatRange(from = 0.0f) float shortTermModelUpperLuxMultiplier) {
+ if (shortTermModelUpperLuxMultiplier < 0.0f) {
+ throw new IllegalArgumentException("Negative lux multiplier");
+ }
+ mShortTermModelUpperLuxMultiplier = shortTermModelUpperLuxMultiplier;
+ return this;
+ }
+
+ /**
+ * Returns the multiplier used to calculate the lower bound for which
+ * a users adaptive brightness is considered valid.
+ *
+ * For example if a user changes the brightness when the ambient light level
+ * is 100 lux, the adjustment will be kept if the current ambient light level
+ * is {@code >= 100 - (100 * shortTermModelLowerLuxMultiplier)}.
+ *
+ * @throws IllegalArgumentException if shortTermModelUpperLuxMultiplier is negative.
+ */
+ @NonNull
+ public Builder setShortTermModelLowerLuxMultiplier(
+ @FloatRange(from = 0.0f) float shortTermModelLowerLuxMultiplier) {
+ if (shortTermModelLowerLuxMultiplier < 0.0f) {
+ throw new IllegalArgumentException("Negative lux multiplier");
+ }
+ mShortTermModelLowerLuxMultiplier = shortTermModelLowerLuxMultiplier;
+ return this;
+ }
+
+ /**
* Builds the {@link BrightnessConfiguration}.
*/
@NonNull
@@ -550,7 +727,9 @@ public final class BrightnessConfiguration implements Parcelable {
throw new IllegalStateException("A curve must be set!");
}
return new BrightnessConfiguration(mCurveLux, mCurveNits, mCorrectionsByPackageName,
- mCorrectionsByCategory, mDescription, mShouldCollectColorSamples);
+ mCorrectionsByCategory, mDescription, mShouldCollectColorSamples,
+ mShortTermModelTimeout, mShortTermModelLowerLuxMultiplier,
+ mShortTermModelUpperLuxMultiplier);
}
private static void checkMonotonic(float[] vals, boolean strictlyIncreasing, String name) {
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index c9551378c190..79a339fa27aa 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -24,7 +24,6 @@ import android.util.IntArray;
import android.util.SparseArray;
import android.view.Display;
import android.view.DisplayInfo;
-import android.view.Surface;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
@@ -151,11 +150,15 @@ public abstract class DisplayManagerInternal {
* has a preference.
* @param requestedModeId The preferred mode id for the top-most visible window that has a
* preference.
+ * @param requestedMinimalPostProcessing The preferred minimal post processing setting for the
+ * display. This is true when there is at least one visible window that wants minimal post
+ * processng on.
* @param inTraversal True if called from WindowManagerService during a window traversal
* prior to call to performTraversalInTransactionFromWindowManager.
*/
public abstract void setDisplayProperties(int displayId, boolean hasContent,
- float requestedRefreshRate, int requestedModeId, boolean inTraversal);
+ float requestedRefreshRate, int requestedModeId, boolean requestedMinimalPostProcessing,
+ boolean inTraversal);
/**
* Applies an offset to the contents of a display, for example to avoid burn-in.
diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java
index 2295d2b7d546..65a8e15ba340 100644
--- a/core/java/android/hardware/hdmi/HdmiControlManager.java
+++ b/core/java/android/hardware/hdmi/HdmiControlManager.java
@@ -36,10 +36,10 @@ import android.util.ArrayMap;
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
-import com.android.internal.util.Preconditions;
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
/**
* The {@link HdmiControlManager} class is used to send HDMI control messages
@@ -532,7 +532,7 @@ public final class HdmiControlManager {
*/
@SystemApi
public void powerOffDevice(@NonNull HdmiDeviceInfo deviceInfo) {
- Preconditions.checkNotNull(deviceInfo);
+ Objects.requireNonNull(deviceInfo);
try {
mService.powerOffRemoteDevice(
deviceInfo.getLogicalAddress(), deviceInfo.getDevicePowerStatus());
@@ -549,7 +549,7 @@ public final class HdmiControlManager {
@Deprecated
@SystemApi
public void powerOffRemoteDevice(@NonNull HdmiDeviceInfo deviceInfo) {
- Preconditions.checkNotNull(deviceInfo);
+ Objects.requireNonNull(deviceInfo);
try {
mService.powerOffRemoteDevice(
deviceInfo.getLogicalAddress(), deviceInfo.getDevicePowerStatus());
@@ -569,7 +569,7 @@ public final class HdmiControlManager {
* @hide
*/
public void powerOnDevice(HdmiDeviceInfo deviceInfo) {
- Preconditions.checkNotNull(deviceInfo);
+ Objects.requireNonNull(deviceInfo);
try {
mService.powerOnRemoteDevice(
deviceInfo.getLogicalAddress(), deviceInfo.getDevicePowerStatus());
@@ -586,7 +586,7 @@ public final class HdmiControlManager {
@Deprecated
@SystemApi
public void powerOnRemoteDevice(HdmiDeviceInfo deviceInfo) {
- Preconditions.checkNotNull(deviceInfo);
+ Objects.requireNonNull(deviceInfo);
try {
mService.powerOnRemoteDevice(
deviceInfo.getLogicalAddress(), deviceInfo.getDevicePowerStatus());
@@ -610,7 +610,7 @@ public final class HdmiControlManager {
*/
@SystemApi
public void setActiveSource(@NonNull HdmiDeviceInfo deviceInfo) {
- Preconditions.checkNotNull(deviceInfo);
+ Objects.requireNonNull(deviceInfo);
try {
mService.askRemoteDeviceToBecomeActiveSource(deviceInfo.getPhysicalAddress());
} catch (RemoteException e) {
@@ -626,7 +626,7 @@ public final class HdmiControlManager {
@Deprecated
@SystemApi
public void requestRemoteDeviceToBecomeActiveSource(@NonNull HdmiDeviceInfo deviceInfo) {
- Preconditions.checkNotNull(deviceInfo);
+ Objects.requireNonNull(deviceInfo);
try {
mService.askRemoteDeviceToBecomeActiveSource(deviceInfo.getPhysicalAddress());
} catch (RemoteException e) {
@@ -689,7 +689,7 @@ public final class HdmiControlManager {
*/
@SystemApi
public boolean isDeviceConnected(@NonNull HdmiDeviceInfo targetDevice) {
- Preconditions.checkNotNull(targetDevice);
+ Objects.requireNonNull(targetDevice);
int physicalAddress = getLocalPhysicalAddress();
if (physicalAddress == INVALID_PHYSICAL_ADDRESS) {
return false;
@@ -710,7 +710,7 @@ public final class HdmiControlManager {
@Deprecated
@SystemApi
public boolean isRemoteDeviceConnected(@NonNull HdmiDeviceInfo targetDevice) {
- Preconditions.checkNotNull(targetDevice);
+ Objects.requireNonNull(targetDevice);
int physicalAddress = getLocalPhysicalAddress();
if (physicalAddress == INVALID_PHYSICAL_ADDRESS) {
return false;
diff --git a/core/java/android/hardware/hdmi/HdmiSwitchClient.java b/core/java/android/hardware/hdmi/HdmiSwitchClient.java
index 6a72a4aaed53..7833653e41b0 100644
--- a/core/java/android/hardware/hdmi/HdmiSwitchClient.java
+++ b/core/java/android/hardware/hdmi/HdmiSwitchClient.java
@@ -23,10 +23,9 @@ import android.os.Binder;
import android.os.RemoteException;
import android.util.Log;
-import com.android.internal.util.Preconditions;
-
import java.util.Collections;
import java.util.List;
+import java.util.Objects;
import java.util.concurrent.Executor;
/**
@@ -70,7 +69,7 @@ public class HdmiSwitchClient extends HdmiClient {
* @hide
*/
public void selectDevice(int logicalAddress, @NonNull OnSelectListener listener) {
- Preconditions.checkNotNull(listener);
+ Objects.requireNonNull(listener);
try {
mService.deviceSelect(logicalAddress, getCallbackWrapper(listener));
} catch (RemoteException e) {
@@ -91,7 +90,7 @@ public class HdmiSwitchClient extends HdmiClient {
*/
@SystemApi
public void selectPort(int portId, @NonNull OnSelectListener listener) {
- Preconditions.checkNotNull(listener);
+ Objects.requireNonNull(listener);
try {
mService.portSelect(portId, getCallbackWrapper(listener));
} catch (RemoteException e) {
@@ -114,7 +113,7 @@ public class HdmiSwitchClient extends HdmiClient {
int logicalAddress,
@NonNull @CallbackExecutor Executor executor,
@NonNull OnSelectListener listener) {
- Preconditions.checkNotNull(listener);
+ Objects.requireNonNull(listener);
try {
mService.deviceSelect(logicalAddress,
new IHdmiControlCallback.Stub() {
@@ -146,7 +145,7 @@ public class HdmiSwitchClient extends HdmiClient {
int portId,
@NonNull @CallbackExecutor Executor executor,
@NonNull OnSelectListener listener) {
- Preconditions.checkNotNull(listener);
+ Objects.requireNonNull(listener);
try {
mService.portSelect(portId,
new IHdmiControlCallback.Stub() {
diff --git a/core/java/android/hardware/location/ContextHubClient.java b/core/java/android/hardware/location/ContextHubClient.java
index a83a33eac1fb..c6a5dd0d048d 100644
--- a/core/java/android/hardware/location/ContextHubClient.java
+++ b/core/java/android/hardware/location/ContextHubClient.java
@@ -20,12 +20,12 @@ import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.app.PendingIntent;
import android.os.RemoteException;
-
-import com.android.internal.util.Preconditions;
+import android.util.Log;
import dalvik.system.CloseGuard;
import java.io.Closeable;
+import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
/**
@@ -38,6 +38,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
*/
@SystemApi
public class ContextHubClient implements Closeable {
+ private static final String TAG = "ContextHubClient";
+
/*
* The proxy to the client interface at the service.
*/
@@ -77,7 +79,7 @@ public class ContextHubClient implements Closeable {
* @param clientProxy the proxy of the client at the service
*/
/* package */ void setClientProxy(IContextHubClient clientProxy) {
- Preconditions.checkNotNull(clientProxy, "IContextHubClient cannot be null");
+ Objects.requireNonNull(clientProxy, "IContextHubClient cannot be null");
if (mClientProxy != null) {
throw new IllegalStateException("Cannot change client proxy multiple times");
}
@@ -137,7 +139,15 @@ public class ContextHubClient implements Closeable {
@RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
@ContextHubTransaction.Result
public int sendMessageToNanoApp(@NonNull NanoAppMessage message) {
- Preconditions.checkNotNull(message, "NanoAppMessage cannot be null");
+ Objects.requireNonNull(message, "NanoAppMessage cannot be null");
+
+ int maxPayloadBytes = mAttachedHub.getMaxPacketLengthBytes();
+ byte[] payload = message.getMessageBody();
+ if (payload != null && payload.length > maxPayloadBytes) {
+ Log.e(TAG, "Message (" + payload.length + " bytes) exceeds max payload length ("
+ + maxPayloadBytes + " bytes)");
+ return ContextHubTransaction.RESULT_FAILED_BAD_PARAMS;
+ }
try {
return mClientProxy.sendMessageToNanoApp(message);
diff --git a/core/java/android/hardware/location/ContextHubIntentEvent.java b/core/java/android/hardware/location/ContextHubIntentEvent.java
index 754327a17dc7..917f62bc6cbf 100644
--- a/core/java/android/hardware/location/ContextHubIntentEvent.java
+++ b/core/java/android/hardware/location/ContextHubIntentEvent.java
@@ -21,7 +21,7 @@ import android.annotation.SystemApi;
import android.app.PendingIntent;
import android.content.Intent;
-import com.android.internal.util.Preconditions;
+import java.util.Objects;
/**
* A helper class to retrieve information about a Intent event received for a PendingIntent
@@ -89,7 +89,7 @@ public class ContextHubIntentEvent {
*/
@NonNull
public static ContextHubIntentEvent fromIntent(@NonNull Intent intent) {
- Preconditions.checkNotNull(intent, "Intent cannot be null");
+ Objects.requireNonNull(intent, "Intent cannot be null");
hasExtraOrThrow(intent, ContextHubManager.EXTRA_CONTEXT_HUB_INFO);
ContextHubInfo info = intent.getParcelableExtra(ContextHubManager.EXTRA_CONTEXT_HUB_INFO);
diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java
index 76393022ef2f..a51d2c929a2c 100644
--- a/core/java/android/hardware/location/ContextHubManager.java
+++ b/core/java/android/hardware/location/ContextHubManager.java
@@ -34,11 +34,10 @@ import android.os.ServiceManager;
import android.os.ServiceManager.ServiceNotFoundException;
import android.util.Log;
-import com.android.internal.util.Preconditions;
-
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
+import java.util.Objects;
import java.util.concurrent.Executor;
/**
@@ -470,8 +469,8 @@ public final class ContextHubManager {
@RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
@NonNull public ContextHubTransaction<Void> loadNanoApp(
@NonNull ContextHubInfo hubInfo, @NonNull NanoAppBinary appBinary) {
- Preconditions.checkNotNull(hubInfo, "ContextHubInfo cannot be null");
- Preconditions.checkNotNull(appBinary, "NanoAppBinary cannot be null");
+ Objects.requireNonNull(hubInfo, "ContextHubInfo cannot be null");
+ Objects.requireNonNull(appBinary, "NanoAppBinary cannot be null");
ContextHubTransaction<Void> transaction =
new ContextHubTransaction<>(ContextHubTransaction.TYPE_LOAD_NANOAPP);
@@ -499,7 +498,7 @@ public final class ContextHubManager {
@RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
@NonNull public ContextHubTransaction<Void> unloadNanoApp(
@NonNull ContextHubInfo hubInfo, long nanoAppId) {
- Preconditions.checkNotNull(hubInfo, "ContextHubInfo cannot be null");
+ Objects.requireNonNull(hubInfo, "ContextHubInfo cannot be null");
ContextHubTransaction<Void> transaction =
new ContextHubTransaction<>(ContextHubTransaction.TYPE_UNLOAD_NANOAPP);
@@ -527,7 +526,7 @@ public final class ContextHubManager {
@RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
@NonNull public ContextHubTransaction<Void> enableNanoApp(
@NonNull ContextHubInfo hubInfo, long nanoAppId) {
- Preconditions.checkNotNull(hubInfo, "ContextHubInfo cannot be null");
+ Objects.requireNonNull(hubInfo, "ContextHubInfo cannot be null");
ContextHubTransaction<Void> transaction =
new ContextHubTransaction<>(ContextHubTransaction.TYPE_ENABLE_NANOAPP);
@@ -555,7 +554,7 @@ public final class ContextHubManager {
@RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
@NonNull public ContextHubTransaction<Void> disableNanoApp(
@NonNull ContextHubInfo hubInfo, long nanoAppId) {
- Preconditions.checkNotNull(hubInfo, "ContextHubInfo cannot be null");
+ Objects.requireNonNull(hubInfo, "ContextHubInfo cannot be null");
ContextHubTransaction<Void> transaction =
new ContextHubTransaction<>(ContextHubTransaction.TYPE_DISABLE_NANOAPP);
@@ -582,7 +581,7 @@ public final class ContextHubManager {
@RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
@NonNull public ContextHubTransaction<List<NanoAppState>> queryNanoApps(
@NonNull ContextHubInfo hubInfo) {
- Preconditions.checkNotNull(hubInfo, "ContextHubInfo cannot be null");
+ Objects.requireNonNull(hubInfo, "ContextHubInfo cannot be null");
ContextHubTransaction<List<NanoAppState>> transaction =
new ContextHubTransaction<>(ContextHubTransaction.TYPE_QUERY_NANOAPPS);
@@ -729,9 +728,9 @@ public final class ContextHubManager {
@NonNull public ContextHubClient createClient(
@NonNull ContextHubInfo hubInfo, @NonNull ContextHubClientCallback callback,
@NonNull @CallbackExecutor Executor executor) {
- Preconditions.checkNotNull(callback, "Callback cannot be null");
- Preconditions.checkNotNull(hubInfo, "ContextHubInfo cannot be null");
- Preconditions.checkNotNull(executor, "Executor cannot be null");
+ Objects.requireNonNull(callback, "Callback cannot be null");
+ Objects.requireNonNull(hubInfo, "ContextHubInfo cannot be null");
+ Objects.requireNonNull(executor, "Executor cannot be null");
ContextHubClient client = new ContextHubClient(hubInfo, false /* persistent */);
IContextHubClientCallback clientInterface = createClientCallback(
@@ -808,8 +807,8 @@ public final class ContextHubManager {
@RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
@NonNull public ContextHubClient createClient(
@NonNull ContextHubInfo hubInfo, @NonNull PendingIntent pendingIntent, long nanoAppId) {
- Preconditions.checkNotNull(pendingIntent);
- Preconditions.checkNotNull(hubInfo);
+ Objects.requireNonNull(pendingIntent);
+ Objects.requireNonNull(hubInfo);
ContextHubClient client = new ContextHubClient(hubInfo, true /* persistent */);
diff --git a/core/java/android/hardware/location/ContextHubTransaction.java b/core/java/android/hardware/location/ContextHubTransaction.java
index bc7efef55bcf..d11e0a9b6081 100644
--- a/core/java/android/hardware/location/ContextHubTransaction.java
+++ b/core/java/android/hardware/location/ContextHubTransaction.java
@@ -22,10 +22,9 @@ import android.annotation.SystemApi;
import android.os.Handler;
import android.os.HandlerExecutor;
-import com.android.internal.util.Preconditions;
-
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
@@ -291,8 +290,8 @@ public class ContextHubTransaction<T> {
@NonNull ContextHubTransaction.OnCompleteListener<T> listener,
@NonNull @CallbackExecutor Executor executor) {
synchronized (this) {
- Preconditions.checkNotNull(listener, "OnCompleteListener cannot be null");
- Preconditions.checkNotNull(executor, "Executor cannot be null");
+ Objects.requireNonNull(listener, "OnCompleteListener cannot be null");
+ Objects.requireNonNull(executor, "Executor cannot be null");
if (mListener != null) {
throw new IllegalStateException(
"Cannot set ContextHubTransaction listener multiple times");
@@ -340,7 +339,7 @@ public class ContextHubTransaction<T> {
*/
/* package */ void setResponse(ContextHubTransaction.Response<T> response) {
synchronized (this) {
- Preconditions.checkNotNull(response, "Response cannot be null");
+ Objects.requireNonNull(response, "Response cannot be null");
if (mIsResponseSet) {
throw new IllegalStateException(
"Cannot set response of ContextHubTransaction multiple times");
diff --git a/core/java/android/hardware/location/NanoApp.java b/core/java/android/hardware/location/NanoApp.java
index 6a734f369730..242c9e20c8fc 100644
--- a/core/java/android/hardware/location/NanoApp.java
+++ b/core/java/android/hardware/location/NanoApp.java
@@ -21,7 +21,7 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
-import com.android.internal.util.Preconditions;
+import java.util.Objects;
/** A class describing nano apps.
* A nano app is a piece of executable code that can be
@@ -198,12 +198,12 @@ public class NanoApp implements Parcelable {
* needed Sensors
*/
public void setNeededSensors(int[] neededSensors) {
- Preconditions.checkNotNull(neededSensors, "neededSensors must not be null");
+ Objects.requireNonNull(neededSensors, "neededSensors must not be null");
mNeededSensors = neededSensors;
}
public void setOutputEvents(int[] outputEvents) {
- Preconditions.checkNotNull(outputEvents, "outputEvents must not be null");
+ Objects.requireNonNull(outputEvents, "outputEvents must not be null");
mOutputEvents = outputEvents;
}
@@ -213,7 +213,7 @@ public class NanoApp implements Parcelable {
* @param appBinary generated events
*/
public void setAppBinary(byte[] appBinary) {
- Preconditions.checkNotNull(appBinary, "appBinary must not be null");
+ Objects.requireNonNull(appBinary, "appBinary must not be null");
mAppBinary = appBinary;
}
diff --git a/core/java/android/hardware/usb/UsbAccessory.java b/core/java/android/hardware/usb/UsbAccessory.java
index a76e4ad2416e..a725205d7b5c 100644
--- a/core/java/android/hardware/usb/UsbAccessory.java
+++ b/core/java/android/hardware/usb/UsbAccessory.java
@@ -24,6 +24,7 @@ import android.os.Parcelable;
import android.os.RemoteException;
import com.android.internal.util.Preconditions;
+import java.util.Objects;
/**
* A class representing a USB accessory, which is an external hardware component
@@ -79,8 +80,8 @@ public class UsbAccessory implements Parcelable {
public UsbAccessory(@NonNull String manufacturer, @NonNull String model,
@Nullable String description, @Nullable String version, @Nullable String uri,
@NonNull IUsbSerialReader serialNumberReader) {
- mManufacturer = Preconditions.checkNotNull(manufacturer);
- mModel = Preconditions.checkNotNull(model);
+ mManufacturer = Objects.requireNonNull(manufacturer);
+ mModel = Objects.requireNonNull(model);
mDescription = description;
mVersion = version;
mUri = uri;
diff --git a/core/java/android/hardware/usb/UsbDevice.java b/core/java/android/hardware/usb/UsbDevice.java
index ee2e2622b314..67e05c8aabb7 100644
--- a/core/java/android/hardware/usb/UsbDevice.java
+++ b/core/java/android/hardware/usb/UsbDevice.java
@@ -25,6 +25,7 @@ import android.os.Parcelable;
import android.os.RemoteException;
import com.android.internal.util.Preconditions;
+import java.util.Objects;
/**
* This class represents a USB device attached to the android device with the android device
@@ -81,7 +82,7 @@ public class UsbDevice implements Parcelable {
@NonNull IUsbSerialReader serialNumberReader,
boolean hasAudioPlayback, boolean hasAudioCapture, boolean hasMidi,
boolean hasVideoPlayback, boolean hasVideoCapture) {
- mName = Preconditions.checkNotNull(name);
+ mName = Objects.requireNonNull(name);
mVendorId = vendorId;
mProductId = productId;
mClass = Class;
@@ -91,7 +92,7 @@ public class UsbDevice implements Parcelable {
mProductName = productName;
mVersion = Preconditions.checkStringNotEmpty(version);
mConfigurations = Preconditions.checkArrayElementsNotNull(configurations, "configurations");
- mSerialNumberReader = Preconditions.checkNotNull(serialNumberReader);
+ mSerialNumberReader = Objects.requireNonNull(serialNumberReader);
mHasAudioPlayback = hasAudioPlayback;
mHasAudioCapture = hasAudioCapture;
mHasMidi = hasMidi;
@@ -441,7 +442,7 @@ public class UsbDevice implements Parcelable {
@Nullable String serialNumber,
boolean hasAudioPlayback, boolean hasAudioCapture, boolean hasMidi,
boolean hasVideoPlayback, boolean hasVideoCapture) {
- mName = Preconditions.checkNotNull(name);
+ mName = Objects.requireNonNull(name);
mVendorId = vendorId;
mProductId = productId;
mClass = Class;
diff --git a/core/java/android/hardware/usb/UsbPort.java b/core/java/android/hardware/usb/UsbPort.java
index 506230ecec86..274e23fff292 100644
--- a/core/java/android/hardware/usb/UsbPort.java
+++ b/core/java/android/hardware/usb/UsbPort.java
@@ -42,6 +42,8 @@ import android.hardware.usb.V1_0.Constants;
import com.android.internal.util.Preconditions;
+import java.util.Objects;
+
/**
* Represents a physical USB port and describes its characteristics.
*
@@ -67,7 +69,7 @@ public final class UsbPort {
int supportedContaminantProtectionModes,
boolean supportsEnableContaminantPresenceProtection,
boolean supportsEnableContaminantPresenceDetection) {
- Preconditions.checkNotNull(id);
+ Objects.requireNonNull(id);
Preconditions.checkFlagsArgument(supportedModes,
MODE_DFP | MODE_UFP | MODE_AUDIO_ACCESSORY | MODE_DEBUG_ACCESSORY);
diff --git a/core/java/android/hardware/usb/UsbRequest.java b/core/java/android/hardware/usb/UsbRequest.java
index cc4ba08af875..d464ab51e0e4 100644
--- a/core/java/android/hardware/usb/UsbRequest.java
+++ b/core/java/android/hardware/usb/UsbRequest.java
@@ -27,6 +27,7 @@ import dalvik.system.CloseGuard;
import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
+import java.util.Objects;
/**
* A class representing USB request packet.
@@ -96,7 +97,7 @@ public class UsbRequest {
*/
public boolean initialize(UsbDeviceConnection connection, UsbEndpoint endpoint) {
mEndpoint = endpoint;
- mConnection = Preconditions.checkNotNull(connection, "connection");
+ mConnection = Objects.requireNonNull(connection, "connection");
boolean wasInitialized = native_init(connection, endpoint.getAddress(),
endpoint.getAttributes(), endpoint.getMaxPacketSize(), endpoint.getInterval());
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 7da7dc120dcb..a45f70316953 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -450,9 +450,6 @@ public class InputMethodService extends AbstractInputMethodService {
@Nullable
private InlineSuggestionsRequestInfo mInlineSuggestionsRequestInfo = null;
- @Nullable
- private InlineSuggestionsResponseCallbackImpl mInlineSuggestionsResponseCallback = null;
-
private final Handler mHandler = new Handler(Looper.getMainLooper(), null, true);
final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsComputer = info -> {
@@ -752,14 +749,12 @@ public class InputMethodService extends AbstractInputMethodService {
Log.w(TAG, "onCreateInlineSuggestionsRequest() returned null request");
requestCallback.onInlineSuggestionsUnsupported();
} else {
- if (mInlineSuggestionsResponseCallback == null) {
- mInlineSuggestionsResponseCallback =
- new InlineSuggestionsResponseCallbackImpl(this,
- mInlineSuggestionsRequestInfo.mComponentName,
- mInlineSuggestionsRequestInfo.mFocusedId);
- }
+ final IInlineSuggestionsResponseCallback inlineSuggestionsResponseCallback =
+ new InlineSuggestionsResponseCallbackImpl(this,
+ mInlineSuggestionsRequestInfo.mComponentName,
+ mInlineSuggestionsRequestInfo.mFocusedId);
requestCallback.onInlineSuggestionsRequest(request,
- mInlineSuggestionsResponseCallback);
+ inlineSuggestionsResponseCallback);
}
} catch (RemoteException e) {
Log.w(TAG, "makeInlinedSuggestionsRequest() remote exception:" + e);
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index d95da91d2009..3ed51d7f13e4 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -50,6 +50,7 @@ import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ServiceManager;
import android.os.ServiceSpecificException;
+import android.os.SystemClock;
import android.provider.Settings;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
@@ -57,7 +58,6 @@ import android.util.ArrayMap;
import android.util.Log;
import android.util.SparseIntArray;
-import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Preconditions;
import com.android.internal.util.Protocol;
@@ -802,6 +802,7 @@ public class ConnectivityManager {
private INetworkManagementService mNMService;
private INetworkPolicyManager mNPManager;
+ private TetheringManager mTetheringManager;
/**
* Tests if a given integer represents a valid network type.
@@ -2339,6 +2340,28 @@ public class ConnectivityManager {
return getInstanceOrNull();
}
+ private static final int TETHERING_TIMEOUT_MS = 60_000;
+ private final Object mTetheringLock = new Object();
+
+ private TetheringManager getTetheringManager() {
+ synchronized (mTetheringLock) {
+ if (mTetheringManager != null) {
+ return mTetheringManager;
+ }
+ final long before = System.currentTimeMillis();
+ while ((mTetheringManager = (TetheringManager) mContext.getSystemService(
+ Context.TETHERING_SERVICE)) == null) {
+ if (System.currentTimeMillis() - before > TETHERING_TIMEOUT_MS) {
+ Log.e(TAG, "Timeout waiting tethering service not ready yet");
+ throw new IllegalStateException("No tethering service yet");
+ }
+ SystemClock.sleep(100);
+ }
+
+ return mTetheringManager;
+ }
+ }
+
/**
* Get the set of tetherable, available interfaces. This list is limited by
* device configuration and current interface existence.
@@ -2350,11 +2373,7 @@ public class ConnectivityManager {
@RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
@UnsupportedAppUsage
public String[] getTetherableIfaces() {
- try {
- return mService.getTetherableIfaces();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return getTetheringManager().getTetherableIfaces();
}
/**
@@ -2367,11 +2386,7 @@ public class ConnectivityManager {
@RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
@UnsupportedAppUsage
public String[] getTetheredIfaces() {
- try {
- return mService.getTetheredIfaces();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return getTetheringManager().getTetheredIfaces();
}
/**
@@ -2390,11 +2405,7 @@ public class ConnectivityManager {
@RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
@UnsupportedAppUsage
public String[] getTetheringErroredIfaces() {
- try {
- return mService.getTetheringErroredIfaces();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return getTetheringManager().getTetheringErroredIfaces();
}
/**
@@ -2405,11 +2416,7 @@ public class ConnectivityManager {
*/
@RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
public String[] getTetheredDhcpRanges() {
- try {
- return mService.getTetheredDhcpRanges();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return getTetheringManager().getTetheredDhcpRanges();
}
/**
@@ -2438,13 +2445,7 @@ public class ConnectivityManager {
*/
@UnsupportedAppUsage
public int tether(String iface) {
- try {
- String pkgName = mContext.getOpPackageName();
- Log.i(TAG, "tether caller:" + pkgName);
- return mService.tether(iface, pkgName);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return getTetheringManager().tether(iface);
}
/**
@@ -2467,13 +2468,7 @@ public class ConnectivityManager {
*/
@UnsupportedAppUsage
public int untether(String iface) {
- try {
- String pkgName = mContext.getOpPackageName();
- Log.i(TAG, "untether caller:" + pkgName);
- return mService.untether(iface, pkgName);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return getTetheringManager().untether(iface);
}
/**
@@ -2498,16 +2493,7 @@ public class ConnectivityManager {
@RequiresPermission(anyOf = {android.Manifest.permission.TETHER_PRIVILEGED,
android.Manifest.permission.WRITE_SETTINGS})
public boolean isTetheringSupported() {
- String pkgName = mContext.getOpPackageName();
- try {
- return mService.isTetheringSupported(pkgName);
- } catch (SecurityException e) {
- // This API is not available to this caller, but for backward-compatibility
- // this will just return false instead of throwing.
- return false;
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return getTetheringManager().isTetheringSupported();
}
/**
@@ -2576,14 +2562,7 @@ public class ConnectivityManager {
}
};
- try {
- String pkgName = mContext.getOpPackageName();
- Log.i(TAG, "startTethering caller:" + pkgName);
- mService.startTethering(type, wrappedCallback, showProvisioningUi, pkgName);
- } catch (RemoteException e) {
- Log.e(TAG, "Exception trying to start tethering.", e);
- wrappedCallback.send(TETHER_ERROR_SERVICE_UNAVAIL, null);
- }
+ getTetheringManager().startTethering(type, wrappedCallback, showProvisioningUi);
}
/**
@@ -2599,13 +2578,7 @@ public class ConnectivityManager {
@SystemApi
@RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
public void stopTethering(int type) {
- try {
- String pkgName = mContext.getOpPackageName();
- Log.i(TAG, "stopTethering caller:" + pkgName);
- mService.stopTethering(type, pkgName);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ getTetheringManager().stopTethering(type);
}
/**
@@ -2627,10 +2600,6 @@ public class ConnectivityManager {
public void onUpstreamChanged(@Nullable Network network) {}
}
- @GuardedBy("mTetheringEventCallbacks")
- private final ArrayMap<OnTetheringEventCallback, ITetheringEventCallback>
- mTetheringEventCallbacks = new ArrayMap<>();
-
/**
* Start listening to tethering change events. Any new added callback will receive the last
* tethering status right away. If callback is registered when tethering has no upstream or
@@ -2648,27 +2617,7 @@ public class ConnectivityManager {
@NonNull final OnTetheringEventCallback callback) {
Preconditions.checkNotNull(callback, "OnTetheringEventCallback cannot be null.");
- synchronized (mTetheringEventCallbacks) {
- Preconditions.checkArgument(!mTetheringEventCallbacks.containsKey(callback),
- "callback was already registered.");
- ITetheringEventCallback remoteCallback = new ITetheringEventCallback.Stub() {
- @Override
- public void onUpstreamChanged(Network network) throws RemoteException {
- Binder.withCleanCallingIdentity(() ->
- executor.execute(() -> {
- callback.onUpstreamChanged(network);
- }));
- }
- };
- try {
- String pkgName = mContext.getOpPackageName();
- Log.i(TAG, "registerTetheringUpstreamCallback:" + pkgName);
- mService.registerTetheringEventCallback(remoteCallback, pkgName);
- mTetheringEventCallbacks.put(callback, remoteCallback);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
+ getTetheringManager().registerTetheringEventCallback(executor, callback);
}
/**
@@ -2682,17 +2631,7 @@ public class ConnectivityManager {
@RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
public void unregisterTetheringEventCallback(
@NonNull final OnTetheringEventCallback callback) {
- synchronized (mTetheringEventCallbacks) {
- ITetheringEventCallback remoteCallback = mTetheringEventCallbacks.remove(callback);
- Preconditions.checkNotNull(remoteCallback, "callback was not registered.");
- try {
- String pkgName = mContext.getOpPackageName();
- Log.i(TAG, "unregisterTetheringEventCallback:" + pkgName);
- mService.unregisterTetheringEventCallback(remoteCallback, pkgName);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
+ getTetheringManager().unregisterTetheringEventCallback(callback);
}
@@ -2709,11 +2648,7 @@ public class ConnectivityManager {
@RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
@UnsupportedAppUsage
public String[] getTetherableUsbRegexs() {
- try {
- return mService.getTetherableUsbRegexs();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return getTetheringManager().getTetherableUsbRegexs();
}
/**
@@ -2729,11 +2664,7 @@ public class ConnectivityManager {
@RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
@UnsupportedAppUsage
public String[] getTetherableWifiRegexs() {
- try {
- return mService.getTetherableWifiRegexs();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return getTetheringManager().getTetherableWifiRegexs();
}
/**
@@ -2749,11 +2680,7 @@ public class ConnectivityManager {
@RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
@UnsupportedAppUsage
public String[] getTetherableBluetoothRegexs() {
- try {
- return mService.getTetherableBluetoothRegexs();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return getTetheringManager().getTetherableBluetoothRegexs();
}
/**
@@ -2775,13 +2702,7 @@ public class ConnectivityManager {
*/
@UnsupportedAppUsage
public int setUsbTethering(boolean enable) {
- try {
- String pkgName = mContext.getOpPackageName();
- Log.i(TAG, "setUsbTethering caller:" + pkgName);
- return mService.setUsbTethering(enable, pkgName);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return getTetheringManager().setUsbTethering(enable);
}
/** {@hide} */
@@ -2829,11 +2750,7 @@ public class ConnectivityManager {
@RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
@UnsupportedAppUsage
public int getLastTetherError(String iface) {
- try {
- return mService.getLastTetherError(iface);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return getTetheringManager().getLastTetherError(iface);
}
/** @hide */
@@ -2899,14 +2816,8 @@ public class ConnectivityManager {
}
};
- try {
- String pkgName = mContext.getOpPackageName();
- Log.i(TAG, "getLatestTetheringEntitlementResult:" + pkgName);
- mService.getLatestTetheringEntitlementResult(type, wrappedListener,
- showEntitlementUi, pkgName);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ getTetheringManager().requestLatestTetheringEntitlementResult(type, wrappedListener,
+ showEntitlementUi);
}
/**
@@ -4331,6 +4242,7 @@ public class ConnectivityManager {
public void factoryReset() {
try {
mService.factoryReset();
+ getTetheringManager().stopAllTethering();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 5f662f914919..09c02efbcfc4 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -19,7 +19,6 @@ package android.net;
import android.app.PendingIntent;
import android.net.ConnectionInfo;
import android.net.LinkProperties;
-import android.net.ITetheringEventCallback;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
@@ -78,41 +77,31 @@ interface IConnectivityManager
boolean requestRouteToHostAddress(int networkType, in byte[] hostAddress);
- int tether(String iface, String callerPkg);
-
- int untether(String iface, String callerPkg);
-
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = 29,
+ publicAlternatives = "Use {@code TetheringManager#getLastTetherError} as alternative")
int getLastTetherError(String iface);
- boolean isTetheringSupported(String callerPkg);
-
- void startTethering(int type, in ResultReceiver receiver, boolean showProvisioningUi,
- String callerPkg);
-
- void stopTethering(int type, String callerPkg);
-
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = 29,
+ publicAlternatives = "Use {@code TetheringManager#getTetherableIfaces} as alternative")
String[] getTetherableIfaces();
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = 29,
+ publicAlternatives = "Use {@code TetheringManager#getTetheredIfaces} as alternative")
String[] getTetheredIfaces();
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = 29,
+ publicAlternatives = "Use {@code TetheringManager#getTetheringErroredIfaces} "
+ + "as Alternative")
String[] getTetheringErroredIfaces();
- String[] getTetheredDhcpRanges();
-
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = 29,
+ publicAlternatives = "Use {@code TetheringManager#getTetherableUsbRegexs} as alternative")
String[] getTetherableUsbRegexs();
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = 29,
+ publicAlternatives = "Use {@code TetheringManager#getTetherableWifiRegexs} as alternative")
String[] getTetherableWifiRegexs();
- String[] getTetherableBluetoothRegexs();
-
- int setUsbTethering(boolean enable, String callerPkg);
-
@UnsupportedAppUsage(maxTargetSdk = 28)
void reportInetCondition(int networkType, int percentage);
@@ -217,11 +206,5 @@ interface IConnectivityManager
boolean isCallerCurrentAlwaysOnVpnApp();
boolean isCallerCurrentAlwaysOnVpnLockdownApp();
- void getLatestTetheringEntitlementResult(int type, in ResultReceiver receiver,
- boolean showEntitlementUi, String callerPkg);
-
- void registerTetheringEventCallback(ITetheringEventCallback callback, String callerPkg);
- void unregisterTetheringEventCallback(ITetheringEventCallback callback, String callerPkg);
-
IBinder startOrGetTestNetworkService();
}
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 8e1834113486..ed509cb3da34 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -74,6 +74,8 @@ public final class LinkProperties implements Parcelable {
private static final int MIN_MTU_V6 = 1280;
private static final int MAX_MTU = 10000;
+ private static final int INET6_ADDR_LENGTH = 16;
+
// Stores the properties of links that are "stacked" above this link.
// Indexed by interface name to allow modification and to prevent duplicates being added.
private Hashtable<String, LinkProperties> mStackedLinks = new Hashtable<>();
@@ -227,7 +229,7 @@ public final class LinkProperties implements Parcelable {
/**
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public @NonNull List<String> getAllInterfaceNames() {
List<String> interfaceNames = new ArrayList<>(mStackedLinks.size() + 1);
if (mIfaceName != null) interfaceNames.add(mIfaceName);
@@ -247,7 +249,7 @@ public final class LinkProperties implements Parcelable {
* @return An unmodifiable {@link List} of {@link InetAddress} for this link.
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public @NonNull List<InetAddress> getAddresses() {
final List<InetAddress> addresses = new ArrayList<>();
for (LinkAddress linkAddress : mLinkAddresses) {
@@ -342,8 +344,8 @@ public final class LinkProperties implements Parcelable {
* Returns all the addresses on this link and all the links stacked above it.
* @hide
*/
- @UnsupportedAppUsage
- public List<LinkAddress> getAllLinkAddresses() {
+ @SystemApi
+ public @NonNull List<LinkAddress> getAllLinkAddresses() {
List<LinkAddress> addresses = new ArrayList<>(mLinkAddresses);
for (LinkProperties stacked: mStackedLinks.values()) {
addresses.addAll(stacked.getAllLinkAddresses());
@@ -542,6 +544,7 @@ public final class LinkProperties implements Parcelable {
* @return true if the PCSCF server was added, false otherwise.
* @hide
*/
+ @SystemApi
public boolean addPcscfServer(@NonNull InetAddress pcscfServer) {
if (pcscfServer != null && !mPcscfs.contains(pcscfServer)) {
mPcscfs.add(pcscfServer);
@@ -729,7 +732,7 @@ public final class LinkProperties implements Parcelable {
* Returns all the routes on this link and all the links stacked above it.
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public @NonNull List<RouteInfo> getAllRoutes() {
List<RouteInfo> routes = new ArrayList<>(mRoutes);
for (LinkProperties stacked: mStackedLinks.values()) {
@@ -1025,7 +1028,7 @@ public final class LinkProperties implements Parcelable {
* @return {@code true} if there is an IPv4 default route, {@code false} otherwise.
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public boolean hasIpv4DefaultRoute() {
for (RouteInfo r : mRoutes) {
if (r.isIPv4Default()) {
@@ -1082,7 +1085,7 @@ public final class LinkProperties implements Parcelable {
* @return {@code true} if there is an IPv4 DNS server, {@code false} otherwise.
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public boolean hasIpv4DnsServer() {
for (InetAddress ia : mDnses) {
if (ia instanceof Inet4Address) {
@@ -1110,7 +1113,7 @@ public final class LinkProperties implements Parcelable {
* @return {@code true} if there is an IPv6 DNS server, {@code false} otherwise.
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public boolean hasIpv6DnsServer() {
for (InetAddress ia : mDnses) {
if (ia instanceof Inet6Address) {
@@ -1626,20 +1629,11 @@ public final class LinkProperties implements Parcelable {
dest.writeParcelable(linkAddress, flags);
}
- dest.writeInt(mDnses.size());
- for (InetAddress d : mDnses) {
- dest.writeByteArray(d.getAddress());
- }
- dest.writeInt(mValidatedPrivateDnses.size());
- for (InetAddress d : mValidatedPrivateDnses) {
- dest.writeByteArray(d.getAddress());
- }
+ writeAddresses(dest, mDnses);
+ writeAddresses(dest, mValidatedPrivateDnses);
dest.writeBoolean(mUsePrivateDns);
dest.writeString(mPrivateDnsServerName);
- dest.writeInt(mPcscfs.size());
- for (InetAddress d : mPcscfs) {
- dest.writeByteArray(d.getAddress());
- }
+ writeAddresses(dest, mPcscfs);
dest.writeString(mDomains);
dest.writeInt(mMtu);
dest.writeString(mTcpBufferSizes);
@@ -1662,6 +1656,35 @@ public final class LinkProperties implements Parcelable {
dest.writeBoolean(mWakeOnLanSupported);
}
+ private static void writeAddresses(@NonNull Parcel dest, @NonNull List<InetAddress> list) {
+ dest.writeInt(list.size());
+ for (InetAddress d : list) {
+ writeAddress(dest, d);
+ }
+ }
+
+ private static void writeAddress(@NonNull Parcel dest, @NonNull InetAddress addr) {
+ dest.writeByteArray(addr.getAddress());
+ if (addr instanceof Inet6Address) {
+ final Inet6Address v6Addr = (Inet6Address) addr;
+ final boolean hasScopeId = v6Addr.getScopeId() != 0;
+ dest.writeBoolean(hasScopeId);
+ if (hasScopeId) dest.writeInt(v6Addr.getScopeId());
+ }
+ }
+
+ @NonNull
+ private static InetAddress readAddress(@NonNull Parcel p) throws UnknownHostException {
+ final byte[] addr = p.createByteArray();
+ if (addr.length == INET6_ADDR_LENGTH) {
+ final boolean hasScopeId = p.readBoolean();
+ final int scopeId = hasScopeId ? p.readInt() : 0;
+ return Inet6Address.getByAddress(null /* host */, addr, scopeId);
+ }
+
+ return InetAddress.getByAddress(addr);
+ }
+
/**
* Implement the Parcelable interface.
*/
@@ -1681,14 +1704,13 @@ public final class LinkProperties implements Parcelable {
addressCount = in.readInt();
for (int i = 0; i < addressCount; i++) {
try {
- netProp.addDnsServer(InetAddress.getByAddress(in.createByteArray()));
+ netProp.addDnsServer(readAddress(in));
} catch (UnknownHostException e) { }
}
addressCount = in.readInt();
for (int i = 0; i < addressCount; i++) {
try {
- netProp.addValidatedPrivateDnsServer(
- InetAddress.getByAddress(in.createByteArray()));
+ netProp.addValidatedPrivateDnsServer(readAddress(in));
} catch (UnknownHostException e) { }
}
netProp.setUsePrivateDns(in.readBoolean());
@@ -1696,7 +1718,7 @@ public final class LinkProperties implements Parcelable {
addressCount = in.readInt();
for (int i = 0; i < addressCount; i++) {
try {
- netProp.addPcscfServer(InetAddress.getByAddress(in.createByteArray()));
+ netProp.addPcscfServer(readAddress(in));
} catch (UnknownHostException e) { }
}
netProp.setDomains(in.readString());
diff --git a/core/java/android/net/MatchAllNetworkSpecifier.java b/core/java/android/net/MatchAllNetworkSpecifier.java
index ab4f627a291b..68a39355198b 100644
--- a/core/java/android/net/MatchAllNetworkSpecifier.java
+++ b/core/java/android/net/MatchAllNetworkSpecifier.java
@@ -16,6 +16,8 @@
package android.net;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -27,10 +29,12 @@ import android.os.Parcelable;
*
* @hide
*/
+@SystemApi
public final class MatchAllNetworkSpecifier extends NetworkSpecifier implements Parcelable {
/**
* Utility method which verifies that the ns argument is not a MatchAllNetworkSpecifier and
* throws an IllegalArgumentException if it is.
+ * @hide
*/
public static void checkNotMatchAllNetworkSpecifier(NetworkSpecifier ns) {
if (ns instanceof MatchAllNetworkSpecifier) {
@@ -38,6 +42,7 @@ public final class MatchAllNetworkSpecifier extends NetworkSpecifier implements
}
}
+ /** @hide */
public boolean satisfiedBy(NetworkSpecifier other) {
/*
* The method is called by a NetworkRequest to see if it is satisfied by a proposed
@@ -64,11 +69,11 @@ public final class MatchAllNetworkSpecifier extends NetworkSpecifier implements
}
@Override
- public void writeToParcel(Parcel dest, int flags) {
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
// Nothing to write.
}
- public static final @android.annotation.NonNull Parcelable.Creator<MatchAllNetworkSpecifier> CREATOR =
+ public static final @NonNull Parcelable.Creator<MatchAllNetworkSpecifier> CREATOR =
new Parcelable.Creator<MatchAllNetworkSpecifier>() {
public MatchAllNetworkSpecifier createFromParcel(Parcel in) {
return new MatchAllNetworkSpecifier();
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index db20dbd06340..4cee5f3e1fb3 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -60,10 +60,6 @@ public final class NetworkCapabilities implements Parcelable {
// Set to true when private DNS is broken.
private boolean mPrivateDnsBroken;
- /**
- * @hide
- */
- @UnsupportedAppUsage
public NetworkCapabilities() {
clearAll();
mNetworkCapabilities = DEFAULT_CAPABILITIES;
@@ -78,7 +74,6 @@ public final class NetworkCapabilities implements Parcelable {
/**
* Completely clears the contents of this object, removing even the capabilities that are set
* by default when the object is constructed.
- * @hide
*/
public void clearAll() {
mNetworkCapabilities = mTransportTypes = mUnwantedNetworkCapabilities = 0;
@@ -402,16 +397,15 @@ public final class NetworkCapabilities implements Parcelable {
* Adds the given capability to this {@code NetworkCapability} instance.
* Multiple capabilities may be applied sequentially. Note that when searching
* for a network to satisfy a request, all capabilities requested must be satisfied.
- * <p>
- * If the given capability was previously added to the list of unwanted capabilities
- * then the capability will also be removed from the list of unwanted capabilities.
*
* @param capability the capability to be added.
* @return This NetworkCapabilities instance, to facilitate chaining.
- * @hide
*/
- @UnsupportedAppUsage
public @NonNull NetworkCapabilities addCapability(@NetCapability int capability) {
+ // If the given capability was previously added to the list of unwanted capabilities
+ // then the capability will also be removed from the list of unwanted capabilities.
+ // TODO: Consider adding unwanted capabilities to the public API and mention this
+ // in the documentation.
checkValidCapability(capability);
mNetworkCapabilities |= 1 << capability;
mUnwantedNetworkCapabilities &= ~(1 << capability); // remove from unwanted capability list
@@ -439,16 +433,13 @@ public final class NetworkCapabilities implements Parcelable {
/**
* Removes (if found) the given capability from this {@code NetworkCapability} instance.
- * <p>
- * Note that this method removes capabilities that were added via {@link #addCapability(int)},
- * {@link #addUnwantedCapability(int)} or {@link #setCapabilities(int[], int[])} .
*
* @param capability the capability to be removed.
* @return This NetworkCapabilities instance, to facilitate chaining.
- * @hide
*/
- @UnsupportedAppUsage
public @NonNull NetworkCapabilities removeCapability(@NetCapability int capability) {
+ // Note that this method removes capabilities that were added via addCapability(int),
+ // addUnwantedCapability(int) or setCapabilities(int[], int[]).
checkValidCapability(capability);
final long mask = ~(1 << capability);
mNetworkCapabilities &= mask;
@@ -460,7 +451,6 @@ public final class NetworkCapabilities implements Parcelable {
* Sets (or clears) the given capability on this {@link NetworkCapabilities}
* instance.
*
- * @hide
*/
public @NonNull NetworkCapabilities setCapability(@NetCapability int capability,
boolean value) {
@@ -722,9 +712,7 @@ public final class NetworkCapabilities implements Parcelable {
*
* @param transportType the transport type to be added.
* @return This NetworkCapabilities instance, to facilitate chaining.
- * @hide
*/
- @UnsupportedAppUsage
public @NonNull NetworkCapabilities addTransportType(@Transport int transportType) {
checkValidTransportType(transportType);
mTransportTypes |= 1 << transportType;
@@ -863,7 +851,6 @@ public final class NetworkCapabilities implements Parcelable {
* fast backhauls and slow backhauls.
*
* @param upKbps the estimated first hop upstream (device to network) bandwidth.
- * @hide
*/
public @NonNull NetworkCapabilities setLinkUpstreamBandwidthKbps(int upKbps) {
mLinkUpBandwidthKbps = upKbps;
@@ -893,7 +880,6 @@ public final class NetworkCapabilities implements Parcelable {
* fast backhauls and slow backhauls.
*
* @param downKbps the estimated first hop downstream (network to device) bandwidth.
- * @hide
*/
public @NonNull NetworkCapabilities setLinkDownstreamBandwidthKbps(int downKbps) {
mLinkDownBandwidthKbps = downKbps;
@@ -952,9 +938,9 @@ public final class NetworkCapabilities implements Parcelable {
* @param networkSpecifier A concrete, parcelable framework class that extends
* NetworkSpecifier.
* @return This NetworkCapabilities instance, to facilitate chaining.
- * @hide
*/
- public @NonNull NetworkCapabilities setNetworkSpecifier(NetworkSpecifier networkSpecifier) {
+ public @NonNull NetworkCapabilities setNetworkSpecifier(
+ @NonNull NetworkSpecifier networkSpecifier) {
if (networkSpecifier != null && Long.bitCount(mTransportTypes) != 1) {
throw new IllegalStateException("Must have a single transport specified to use " +
"setNetworkSpecifier");
@@ -973,7 +959,8 @@ public final class NetworkCapabilities implements Parcelable {
* @return This NetworkCapabilities instance, to facilitate chaining.
* @hide
*/
- public @NonNull NetworkCapabilities setTransportInfo(TransportInfo transportInfo) {
+ @SystemApi
+ public @NonNull NetworkCapabilities setTransportInfo(@NonNull TransportInfo transportInfo) {
mTransportInfo = transportInfo;
return this;
}
@@ -983,9 +970,7 @@ public final class NetworkCapabilities implements Parcelable {
*
* @return The optional {@link NetworkSpecifier} specifying the bearer specific network
* specifier or {@code null}. See {@link #setNetworkSpecifier}.
- * @hide
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
public @Nullable NetworkSpecifier getNetworkSpecifier() {
return mNetworkSpecifier;
}
@@ -1054,9 +1039,7 @@ public final class NetworkCapabilities implements Parcelable {
* effect when requesting a callback.
*
* @param signalStrength the bearer-specific signal strength.
- * @hide
*/
- @UnsupportedAppUsage
public @NonNull NetworkCapabilities setSignalStrength(int signalStrength) {
mSignalStrength = signalStrength;
return this;
@@ -1282,6 +1265,7 @@ public final class NetworkCapabilities implements Parcelable {
* Sets the SSID of this network.
* @hide
*/
+ @SystemApi
public @NonNull NetworkCapabilities setSSID(@Nullable String ssid) {
mSSID = ssid;
return this;
diff --git a/core/java/android/net/StringNetworkSpecifier.java b/core/java/android/net/StringNetworkSpecifier.java
index 21dee55eb0fb..83dbc637fb65 100644
--- a/core/java/android/net/StringNetworkSpecifier.java
+++ b/core/java/android/net/StringNetworkSpecifier.java
@@ -16,7 +16,8 @@
package android.net;
-import android.annotation.UnsupportedAppUsage;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
@@ -26,18 +27,20 @@ import com.android.internal.util.Preconditions;
import java.util.Objects;
/** @hide */
+@SystemApi
public final class StringNetworkSpecifier extends NetworkSpecifier implements Parcelable {
/**
* Arbitrary string used to pass (additional) information to the network factory.
*/
- @UnsupportedAppUsage
+ @NonNull
public final String specifier;
- public StringNetworkSpecifier(String specifier) {
+ public StringNetworkSpecifier(@NonNull String specifier) {
Preconditions.checkStringNotEmpty(specifier);
this.specifier = specifier;
}
+ /** @hide */
@Override
public boolean satisfiedBy(NetworkSpecifier other) {
return equals(other);
@@ -65,11 +68,11 @@ public final class StringNetworkSpecifier extends NetworkSpecifier implements Pa
}
@Override
- public void writeToParcel(Parcel dest, int flags) {
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeString(specifier);
}
- public static final @android.annotation.NonNull Parcelable.Creator<StringNetworkSpecifier> CREATOR =
+ public static final @NonNull Parcelable.Creator<StringNetworkSpecifier> CREATOR =
new Parcelable.Creator<StringNetworkSpecifier>() {
public StringNetworkSpecifier createFromParcel(Parcel in) {
return new StringNetworkSpecifier(in.readString());
diff --git a/core/java/android/net/nsd/NsdServiceInfo.java b/core/java/android/net/nsd/NsdServiceInfo.java
index 459b1409807b..0946499f164f 100644
--- a/core/java/android/net/nsd/NsdServiceInfo.java
+++ b/core/java/android/net/nsd/NsdServiceInfo.java
@@ -17,13 +17,13 @@
package android.net.nsd;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
-import android.os.Parcelable;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
+import android.os.Parcelable;
import android.text.TextUtils;
+import android.util.ArrayMap;
import android.util.Base64;
import android.util.Log;
-import android.util.ArrayMap;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
diff --git a/core/java/android/nfc/ErrorCodes.java b/core/java/android/nfc/ErrorCodes.java
index 98e31ad53be3..d2c81cd27d90 100644
--- a/core/java/android/nfc/ErrorCodes.java
+++ b/core/java/android/nfc/ErrorCodes.java
@@ -16,7 +16,7 @@
package android.nfc;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* This class defines all the error codes that can be returned by the service
diff --git a/core/java/android/nfc/INfcCardEmulation.aidl b/core/java/android/nfc/INfcCardEmulation.aidl
index dd2c0d4f9ee5..848b6d52c47f 100644
--- a/core/java/android/nfc/INfcCardEmulation.aidl
+++ b/core/java/android/nfc/INfcCardEmulation.aidl
@@ -39,4 +39,5 @@ interface INfcCardEmulation
boolean setPreferredService(in ComponentName service);
boolean unsetPreferredService();
boolean supportsAidPrefixRegistration();
+ ApduServiceInfo getPreferredPaymentService(int userHandle);
}
diff --git a/core/java/android/nfc/NdefRecord.java b/core/java/android/nfc/NdefRecord.java
index 5044a860b50c..fe316c45fb55 100644
--- a/core/java/android/nfc/NdefRecord.java
+++ b/core/java/android/nfc/NdefRecord.java
@@ -16,7 +16,7 @@
package android.nfc;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.net.Uri;
import android.os.Parcel;
diff --git a/core/java/android/nfc/NfcActivityManager.java b/core/java/android/nfc/NfcActivityManager.java
index abfa133a2f39..935374d15d9b 100644
--- a/core/java/android/nfc/NfcActivityManager.java
+++ b/core/java/android/nfc/NfcActivityManager.java
@@ -16,9 +16,9 @@
package android.nfc;
-import android.annotation.UnsupportedAppUsage;
import android.app.Activity;
import android.app.Application;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentProvider;
import android.content.Intent;
import android.net.Uri;
@@ -26,7 +26,6 @@ import android.nfc.NfcAdapter.ReaderCallback;
import android.os.Binder;
import android.os.Bundle;
import android.os.RemoteException;
-import android.os.UserHandle;
import android.util.Log;
import java.util.ArrayList;
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index 875d17a436a9..d320f61a3657 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -21,11 +21,11 @@ import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.Activity;
import android.app.ActivityThread;
import android.app.OnActivityPausedListener;
import android.app.PendingIntent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.IntentFilter;
import android.content.pm.IPackageManager;
@@ -164,6 +164,18 @@ public final class NfcAdapter {
"android.nfc.action.TRANSACTION_DETECTED";
/**
+ * Broadcast Action: Intent to notify if the preferred payment service changed.
+ *
+ * <p>This intent will only be sent to the application has requested permission for
+ * {@link android.Manifest.permission#NFC_PREFERRED_PAYMENT_INFO} and if the application
+ * has the necessary access to Secure Element which witnessed the particular event.
+ */
+ @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO)
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_PREFERRED_PAYMENT_CHANGED =
+ "android.nfc.action.PREFERRED_PAYMENT_CHANGED";
+
+ /**
* Broadcast to only the activity that handles ACTION_TAG_DISCOVERED
* @hide
*/
@@ -231,6 +243,17 @@ public final class NfcAdapter {
*/
public static final String EXTRA_SECURE_ELEMENT_NAME = "android.nfc.extra.SECURE_ELEMENT_NAME";
+ /**
+ * Mandatory String extra field in {@link #ACTION_PREFERRED_PAYMENT_CHANGED}
+ * Indicates the condition when trigger this event.
+ */
+ public static final String EXTRA_PREFERRED_PAYMENT_CHANGED_REASON =
+ "android.nfc.extra.PREFERRED_PAYMENT_CHANGED_REASON";
+
+ public static final int PREFERRED_PAYMENT_LOADED = 1;
+ public static final int PREFERRED_PAYMENT_CHANGED = 2;
+ public static final int PREFERRED_PAYMENT_UPDATED = 3;
+
public static final int STATE_OFF = 1;
public static final int STATE_TURNING_ON = 2;
public static final int STATE_ON = 3;
@@ -1410,7 +1433,7 @@ public final class NfcAdapter {
/**
* Enable foreground dispatch to the given Activity.
*
- * <p>This will give give priority to the foreground activity when
+ * <p>This will give priority to the foreground activity when
* dispatching a discovered {@link Tag} to an application.
*
* <p>If any IntentFilters are provided to this method they are used to match dispatch Intents
diff --git a/core/java/android/nfc/NfcManager.java b/core/java/android/nfc/NfcManager.java
index 030066eb80a4..644e3122774b 100644
--- a/core/java/android/nfc/NfcManager.java
+++ b/core/java/android/nfc/NfcManager.java
@@ -17,7 +17,7 @@
package android.nfc;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Build;
diff --git a/core/java/android/nfc/Tag.java b/core/java/android/nfc/Tag.java
index 5a4c465f76d8..8bb2df0bba58 100644
--- a/core/java/android/nfc/Tag.java
+++ b/core/java/android/nfc/Tag.java
@@ -16,7 +16,7 @@
package android.nfc;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.nfc.tech.IsoDep;
import android.nfc.tech.MifareClassic;
diff --git a/core/java/android/nfc/cardemulation/AidGroup.java b/core/java/android/nfc/cardemulation/AidGroup.java
index 77b5552cd27b..c4f5e0b2ddf2 100644
--- a/core/java/android/nfc/cardemulation/AidGroup.java
+++ b/core/java/android/nfc/cardemulation/AidGroup.java
@@ -16,18 +16,18 @@
package android.nfc.cardemulation;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
+import android.compat.annotation.UnsupportedAppUsage;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
-import android.annotation.UnsupportedAppUsage;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.Log;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
/**
* The AidGroup class represents a group of Application Identifiers (AIDs).
diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.java b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
index d9000e43be0b..8da9db17252f 100644
--- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java
+++ b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
@@ -16,7 +16,7 @@
package android.nfc.cardemulation;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
diff --git a/core/java/android/nfc/cardemulation/CardEmulation.java b/core/java/android/nfc/cardemulation/CardEmulation.java
index aa93611062f5..f1c74a6331c4 100644
--- a/core/java/android/nfc/cardemulation/CardEmulation.java
+++ b/core/java/android/nfc/cardemulation/CardEmulation.java
@@ -17,6 +17,7 @@
package android.nfc.cardemulation;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
@@ -657,6 +658,109 @@ public final class CardEmulation {
}
/**
+ * Retrieves the registered AIDs for the preferred payment service.
+ *
+ * @return The list of AIDs registered for this category, or null if it couldn't be found.
+ */
+ @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO)
+ @Nullable
+ public List<String> getAidsForPreferredPaymentService() {
+ try {
+ ApduServiceInfo serviceInfo = sService.getPreferredPaymentService(mContext.getUserId());
+ return (serviceInfo != null ? serviceInfo.getAids() : null);
+ } catch (RemoteException e) {
+ recoverService();
+ if (sService == null) {
+ Log.e(TAG, "Failed to recover CardEmulationService.");
+ return null;
+ }
+ try {
+ ApduServiceInfo serviceInfo =
+ sService.getPreferredPaymentService(mContext.getUserId());
+ return (serviceInfo != null ? serviceInfo.getAids() : null);
+ } catch (RemoteException ee) {
+ Log.e(TAG, "Failed to recover CardEmulationService.");
+ return null;
+ }
+ }
+ }
+
+ /**
+ * Retrieves the route destination for the preferred payment service.
+ *
+ * @return The route destination secure element name of the preferred payment service.
+ * HCE payment: "Host"
+ * OffHost payment: prefix SIM or prefix eSE string.
+ * "OffHost" if the payment service does not specify secure element
+ * name.
+ */
+ @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO)
+ @Nullable
+ public String getRouteDestinationForPreferredPaymentService() {
+ try {
+ ApduServiceInfo serviceInfo = sService.getPreferredPaymentService(mContext.getUserId());
+ if (serviceInfo != null) {
+ if (!serviceInfo.isOnHost()) {
+ return serviceInfo.getOffHostSecureElement() == null ?
+ "OffHost" : serviceInfo.getOffHostSecureElement();
+ }
+ return "Host";
+ }
+ return null;
+ } catch (RemoteException e) {
+ recoverService();
+ if (sService == null) {
+ Log.e(TAG, "Failed to recover CardEmulationService.");
+ return null;
+ }
+ try {
+ ApduServiceInfo serviceInfo =
+ sService.getPreferredPaymentService(mContext.getUserId());
+ if (serviceInfo != null) {
+ if (!serviceInfo.isOnHost()) {
+ return serviceInfo.getOffHostSecureElement() == null ?
+ "Offhost" : serviceInfo.getOffHostSecureElement();
+ }
+ return "Host";
+ }
+ return null;
+
+ } catch (RemoteException ee) {
+ Log.e(TAG, "Failed to recover CardEmulationService.");
+ return null;
+ }
+ }
+ }
+
+ /**
+ * Returns a user-visible description of the preferred payment service.
+ *
+ * @return the preferred payment service description
+ */
+ @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO)
+ @Nullable
+ public String getDescriptionForPreferredPaymentService() {
+ try {
+ ApduServiceInfo serviceInfo = sService.getPreferredPaymentService(mContext.getUserId());
+ return (serviceInfo != null ? serviceInfo.getDescription() : null);
+ } catch (RemoteException e) {
+ recoverService();
+ if (sService == null) {
+ Log.e(TAG, "Failed to recover CardEmulationService.");
+ return null;
+ }
+ try {
+ ApduServiceInfo serviceInfo =
+ sService.getPreferredPaymentService(mContext.getUserId());
+ return (serviceInfo != null ? serviceInfo.getDescription() : null);
+ } catch (RemoteException ee) {
+ Log.e(TAG, "Failed to recover CardEmulationService.");
+ return null;
+ }
+ }
+ }
+
+ /**
* @hide
*/
public boolean setDefaultServiceForCategory(ComponentName service, String category) {
diff --git a/core/java/android/os/AsyncResult.java b/core/java/android/os/AsyncResult.java
index 58a27015f2df..e80528b10aaf 100644
--- a/core/java/android/os/AsyncResult.java
+++ b/core/java/android/os/AsyncResult.java
@@ -16,8 +16,7 @@
package android.os;
-import android.annotation.UnsupportedAppUsage;
-import android.os.Message;
+import android.compat.annotation.UnsupportedAppUsage;
/** @hide */
public class AsyncResult
diff --git a/core/java/android/os/AsyncTask.java b/core/java/android/os/AsyncTask.java
index b37e176ddb6e..e1dabd345027 100644
--- a/core/java/android/os/AsyncTask.java
+++ b/core/java/android/os/AsyncTask.java
@@ -18,8 +18,8 @@ package android.os;
import android.annotation.MainThread;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.WorkerThread;
+import android.compat.annotation.UnsupportedAppUsage;
import java.util.ArrayDeque;
import java.util.concurrent.Callable;
diff --git a/core/java/android/os/BaseBundle.java b/core/java/android/os/BaseBundle.java
index 9d9c683ee794..6453af802623 100644
--- a/core/java/android/os/BaseBundle.java
+++ b/core/java/android/os/BaseBundle.java
@@ -18,7 +18,7 @@ package android.os;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.ArrayMap;
import android.util.Log;
import android.util.MathUtils;
diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java
index 5ced86c9e79a..12ec0a0c21d5 100644
--- a/core/java/android/os/BatteryManager.java
+++ b/core/java/android/os/BatteryManager.java
@@ -21,7 +21,7 @@ import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.hardware.health.V1_0.Constants;
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 53ea936ea972..fbe6a5052f3d 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -21,9 +21,9 @@ import static android.os.BatteryStatsManager.NUM_WIFI_STATES;
import static android.os.BatteryStatsManager.NUM_WIFI_SUPPL_STATES;
import android.annotation.IntDef;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
import android.app.job.JobParameters;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.os.BatteryStatsManager.WifiState;
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index a9c5a9118a31..a90ab8564100 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -19,8 +19,8 @@ package android.os;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.AppOpsManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.ExceptionUtils;
import android.util.Log;
import android.util.Slog;
diff --git a/core/java/android/os/Broadcaster.java b/core/java/android/os/Broadcaster.java
index 6ac7f1a9c970..d1a953f23f7f 100644
--- a/core/java/android/os/Broadcaster.java
+++ b/core/java/android/os/Broadcaster.java
@@ -16,7 +16,7 @@
package android.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/** @hide */
public class Broadcaster
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 6eaea99d5c49..a29173469ffb 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -22,9 +22,9 @@ import android.annotation.RequiresPermission;
import android.annotation.SuppressAutoDoc;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
import android.app.Application;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.sysprop.TelephonyProperties;
import android.text.TextUtils;
diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java
index c5b422230c73..f8f8bf746afd 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -17,7 +17,7 @@
package android.os;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.ArrayMap;
import android.util.Size;
import android.util.SizeF;
diff --git a/core/java/android/os/CancellationSignal.java b/core/java/android/os/CancellationSignal.java
index 99fb9982e706..260f7ade8ab7 100644
--- a/core/java/android/os/CancellationSignal.java
+++ b/core/java/android/os/CancellationSignal.java
@@ -16,9 +16,7 @@
package android.os;
-import android.os.ICancellationSignal;
-
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* Provides the ability to cancel an operation in progress.
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index 563492925ff0..3d449446af82 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -18,8 +18,8 @@ package android.os;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.app.AppGlobals;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.util.Log;
@@ -1938,8 +1938,14 @@ public final class Debug
public static final int MEMINFO_PAGE_TABLES = 13;
/** @hide */
public static final int MEMINFO_KERNEL_STACK = 14;
+ /**
+ * Note: MEMINFO_KRECLAIMABLE includes MEMINFO_SLAB_RECLAIMABLE (see KReclaimable field
+ * description in kernel documentation).
+ * @hide
+ */
+ public static final int MEMINFO_KRECLAIMABLE = 15;
/** @hide */
- public static final int MEMINFO_COUNT = 15;
+ public static final int MEMINFO_COUNT = 16;
/**
* Retrieves /proc/meminfo. outSizes is filled with fields
@@ -2561,4 +2567,35 @@ public final class Debug
* @hide
*/
public static native long getZramFreeKb();
+
+ /**
+ * Return memory size in kilobytes allocated for ION heaps.
+ *
+ * @hide
+ */
+ public static native long getIonHeapsSizeKb();
+
+ /**
+ * Return memory size in kilobytes allocated for ION pools.
+ *
+ * @hide
+ */
+ public static native long getIonPoolsSizeKb();
+
+ /**
+ * Return ION memory mapped by processes in kB.
+ * Notes:
+ * * Warning: Might impact performance as it reads /proc/<pid>/maps files for each process.
+ *
+ * @hide
+ */
+ public static native long getIonMappedSizeKb();
+
+ /**
+ * Return whether virtually-mapped kernel stacks are enabled (CONFIG_VMAP_STACK).
+ * Note: caller needs config_gz read sepolicy permission
+ *
+ * @hide
+ */
+ public static native boolean isVmapStack();
}
diff --git a/core/java/android/os/DropBoxManager.java b/core/java/android/os/DropBoxManager.java
index b7cccc66294a..18ba5a8a4a34 100644
--- a/core/java/android/os/DropBoxManager.java
+++ b/core/java/android/os/DropBoxManager.java
@@ -24,7 +24,7 @@ import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.util.Log;
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 61da5e67e57b..44f12a6adf60 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -20,10 +20,10 @@ import android.Manifest;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.AppGlobals;
import android.app.AppOpsManager;
import android.app.admin.DevicePolicyManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
diff --git a/core/java/android/os/FileObserver.java b/core/java/android/os/FileObserver.java
index 5b715c0dcb3c..ca303d973235 100644
--- a/core/java/android/os/FileObserver.java
+++ b/core/java/android/os/FileObserver.java
@@ -19,7 +19,7 @@ package android.os;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.Log;
import java.io.File;
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 2ac3def3a3f9..a47fbbaab9dd 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -40,7 +40,7 @@ import static android.system.OsConstants.W_OK;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
import android.provider.DocumentsContract.Document;
import android.system.ErrnoException;
diff --git a/core/java/android/os/Handler.java b/core/java/android/os/Handler.java
index 928df3c4ff97..af776d154c8f 100644
--- a/core/java/android/os/Handler.java
+++ b/core/java/android/os/Handler.java
@@ -18,7 +18,7 @@ package android.os;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.Log;
import android.util.Printer;
diff --git a/core/java/android/os/HwBinder.java b/core/java/android/os/HwBinder.java
index 09afdc7f934e..7c42c36e7747 100644
--- a/core/java/android/os/HwBinder.java
+++ b/core/java/android/os/HwBinder.java
@@ -18,7 +18,7 @@ package android.os;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import libcore.util.NativeAllocationRegistry;
diff --git a/core/java/android/os/HwParcel.java b/core/java/android/os/HwParcel.java
index 9786f16bebaa..fb36e6f6978f 100644
--- a/core/java/android/os/HwParcel.java
+++ b/core/java/android/os/HwParcel.java
@@ -21,7 +21,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import dalvik.annotation.optimization.FastNative;
diff --git a/core/java/android/os/HwRemoteBinder.java b/core/java/android/os/HwRemoteBinder.java
index 72ec958ca6d6..756202e88518 100644
--- a/core/java/android/os/HwRemoteBinder.java
+++ b/core/java/android/os/HwRemoteBinder.java
@@ -16,7 +16,8 @@
package android.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
+
import libcore.util.NativeAllocationRegistry;
/** @hide */
diff --git a/core/java/android/os/IBinder.java b/core/java/android/os/IBinder.java
index ed980f3049b3..f336fdab5941 100644
--- a/core/java/android/os/IBinder.java
+++ b/core/java/android/os/IBinder.java
@@ -18,7 +18,7 @@ package android.os;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import java.io.FileDescriptor;
diff --git a/core/java/android/os/IVibratorService.aidl b/core/java/android/os/IVibratorService.aidl
index 1456ff7e6c5e..6b881fecad56 100644
--- a/core/java/android/os/IVibratorService.aidl
+++ b/core/java/android/os/IVibratorService.aidl
@@ -24,6 +24,7 @@ interface IVibratorService
{
boolean hasVibrator();
boolean hasAmplitudeControl();
+ boolean setAlwaysOnEffect(int id, in VibrationEffect effect, in AudioAttributes attributes);
void vibrate(int uid, String opPkg, in VibrationEffect effect, in AudioAttributes attributes,
String reason, IBinder token);
void cancelVibrate(IBinder token);
diff --git a/core/java/android/os/LocaleList.java b/core/java/android/os/LocaleList.java
index 0de09efad8ea..0bf387e6d0a6 100644
--- a/core/java/android/os/LocaleList.java
+++ b/core/java/android/os/LocaleList.java
@@ -20,7 +20,7 @@ import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Size;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.icu.util.ULocale;
import com.android.internal.annotations.GuardedBy;
diff --git a/core/java/android/os/Looper.java b/core/java/android/os/Looper.java
index df16ffee7549..b478dbe2555d 100644
--- a/core/java/android/os/Looper.java
+++ b/core/java/android/os/Looper.java
@@ -18,7 +18,7 @@ package android.os;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.Log;
import android.util.Printer;
import android.util.Slog;
diff --git a/core/java/android/os/MemoryFile.java b/core/java/android/os/MemoryFile.java
index 5a1e3d429830..f84f9f05b13e 100644
--- a/core/java/android/os/MemoryFile.java
+++ b/core/java/android/os/MemoryFile.java
@@ -16,7 +16,7 @@
package android.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.system.ErrnoException;
import java.io.FileDescriptor;
diff --git a/core/java/android/os/Message.java b/core/java/android/os/Message.java
index 9d101e51afbf..c62df407ca77 100644
--- a/core/java/android/os/Message.java
+++ b/core/java/android/os/Message.java
@@ -16,7 +16,7 @@
package android.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
diff --git a/core/java/android/os/MessageQueue.java b/core/java/android/os/MessageQueue.java
index b5f4bc693d3f..a72795daf7e5 100644
--- a/core/java/android/os/MessageQueue.java
+++ b/core/java/android/os/MessageQueue.java
@@ -19,8 +19,7 @@ package android.os;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
-import android.os.MessageQueueProto;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.Log;
import android.util.Printer;
import android.util.SparseArray;
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 339397b90afa..c9ebed3bd0a2 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -19,8 +19,8 @@ package android.os;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.AppOpsManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java
index fdb44e7050e1..983053bbe7fd 100644
--- a/core/java/android/os/ParcelFileDescriptor.java
+++ b/core/java/android/os/ParcelFileDescriptor.java
@@ -32,7 +32,7 @@ import static android.system.OsConstants.S_ISREG;
import static android.system.OsConstants.S_IWOTH;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.ContentProvider;
import android.content.ContentResolver;
diff --git a/core/java/android/os/ParcelUuid.java b/core/java/android/os/ParcelUuid.java
index cc50c8996ba7..0b52c7501d5b 100644
--- a/core/java/android/os/ParcelUuid.java
+++ b/core/java/android/os/ParcelUuid.java
@@ -16,7 +16,7 @@
package android.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import java.util.UUID;
diff --git a/core/java/android/os/ParcelableParcel.java b/core/java/android/os/ParcelableParcel.java
index 61f39686c9e6..38d980ecb0f1 100644
--- a/core/java/android/os/ParcelableParcel.java
+++ b/core/java/android/os/ParcelableParcel.java
@@ -16,7 +16,7 @@
package android.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.MathUtils;
/**
diff --git a/core/java/android/os/PerformanceCollector.java b/core/java/android/os/PerformanceCollector.java
index 33c86b8b05b9..27de48d40188 100644
--- a/core/java/android/os/PerformanceCollector.java
+++ b/core/java/android/os/PerformanceCollector.java
@@ -17,7 +17,8 @@
package android.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
+
import java.util.ArrayList;
/**
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 5e478b555fca..82b04a661b54 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -20,12 +20,13 @@ import android.Manifest.permission;
import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.service.dreams.Sandman;
import android.util.ArrayMap;
@@ -552,6 +553,13 @@ public final class PowerManager {
public static final String REBOOT_SAFE_MODE = "safemode";
/**
+ * The 'reason' value used for rebooting userspace.
+ * @hide
+ */
+ @SystemApi
+ public static final String REBOOT_USERSPACE = "userspace";
+
+ /**
* The 'reason' value used when rebooting the device without turning on the screen.
* @hide
*/
@@ -1326,6 +1334,14 @@ public final class PowerManager {
}
/**
+ * Returns {@code true} if this device supports rebooting userspace.
+ */
+ // TODO(b/138605180): add link to documentation once it's ready.
+ public boolean isRebootingUserspaceSupported() {
+ return SystemProperties.getBoolean("ro.init.userspace_reboot.is_supported", false);
+ }
+
+ /**
* Reboot the device. Will not return if the reboot is successful.
* <p>
* Requires the {@link android.Manifest.permission#REBOOT} permission.
@@ -1333,8 +1349,14 @@ public final class PowerManager {
*
* @param reason code to pass to the kernel (e.g., "recovery") to
* request special boot modes, or null.
+ * @throws UnsupportedOperationException if userspace reboot was requested on a device that
+ * doesn't support it.
*/
- public void reboot(String reason) {
+ public void reboot(@Nullable String reason) {
+ if (REBOOT_USERSPACE.equals(reason) && !isRebootingUserspaceSupported()) {
+ throw new UnsupportedOperationException(
+ "Attempted userspace reboot on a device that doesn't support it");
+ }
try {
mService.reboot(false, reason, true);
} catch (RemoteException e) {
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index ebb2071ead7e..94623bc71346 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -19,13 +19,16 @@ package android.os;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.system.Os;
import android.system.OsConstants;
+import android.util.Pair;
import android.webkit.WebViewZygote;
import dalvik.system.VMRuntime;
+import java.util.Map;
+
/**
* Tools for managing OS processes.
*/
@@ -521,6 +524,8 @@ public class Process {
* @param isTopApp whether the process starts for high priority application.
* @param disabledCompatChanges null-ok list of disabled compat changes for the process being
* started.
+ * @param pkgDataInfoMap Map from related package names to private data directory
+ * volume UUID and inode number.
* @param zygoteArgs Additional arguments to supply to the zygote process.
* @return An object that describes the result of the attempt to start the process.
* @throws RuntimeException on fatal start failure
@@ -541,11 +546,14 @@ public class Process {
@Nullable String packageName,
boolean isTopApp,
@Nullable long[] disabledCompatChanges,
+ @Nullable Map<String, Pair<String, Long>>
+ pkgDataInfoMap,
@Nullable String[] zygoteArgs) {
return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, packageName,
- /*useUsapPool=*/ true, isTopApp, disabledCompatChanges, zygoteArgs);
+ /*useUsapPool=*/ true, isTopApp, disabledCompatChanges,
+ pkgDataInfoMap, zygoteArgs);
}
/** @hide */
@@ -563,10 +571,13 @@ public class Process {
@Nullable String packageName,
@Nullable long[] disabledCompatChanges,
@Nullable String[] zygoteArgs) {
+ // Webview zygote can't access app private data files, so doesn't need to know its data
+ // info.
return WebViewZygote.getProcess().start(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, packageName,
- /*useUsapPool=*/ false, /*isTopApp=*/ false, disabledCompatChanges, zygoteArgs);
+ /*useUsapPool=*/ false, /*isTopApp=*/ false, disabledCompatChanges,
+ /* pkgDataInfoMap */ null, zygoteArgs);
}
/**
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index e3f6e120d9c6..190182072356 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -22,8 +22,8 @@ import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
import android.app.PendingIntent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
diff --git a/core/java/android/os/Registrant.java b/core/java/android/os/Registrant.java
index 572b975fbafd..d6afd049f156 100644
--- a/core/java/android/os/Registrant.java
+++ b/core/java/android/os/Registrant.java
@@ -16,9 +16,7 @@
package android.os;
-import android.annotation.UnsupportedAppUsage;
-import android.os.Handler;
-import android.os.Message;
+import android.compat.annotation.UnsupportedAppUsage;
import java.lang.ref.WeakReference;
diff --git a/core/java/android/os/RegistrantList.java b/core/java/android/os/RegistrantList.java
index 9c017dfff967..98f949bbfd84 100644
--- a/core/java/android/os/RegistrantList.java
+++ b/core/java/android/os/RegistrantList.java
@@ -16,7 +16,7 @@
package android.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import java.util.ArrayList;
diff --git a/core/java/android/os/RemoteCallback.java b/core/java/android/os/RemoteCallback.java
index da58d0fac160..373060f4ff4b 100644
--- a/core/java/android/os/RemoteCallback.java
+++ b/core/java/android/os/RemoteCallback.java
@@ -20,8 +20,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* @hide
diff --git a/core/java/android/os/RemoteCallbackList.java b/core/java/android/os/RemoteCallbackList.java
index 6165146ece0a..df4ade09753b 100644
--- a/core/java/android/os/RemoteCallbackList.java
+++ b/core/java/android/os/RemoteCallbackList.java
@@ -16,7 +16,7 @@
package android.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.ArrayMap;
import android.util.Slog;
diff --git a/core/java/android/os/SELinux.java b/core/java/android/os/SELinux.java
index 34809e76c91b..f64a81177ce2 100644
--- a/core/java/android/os/SELinux.java
+++ b/core/java/android/os/SELinux.java
@@ -16,7 +16,7 @@
package android.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.Slog;
import java.io.File;
diff --git a/core/java/android/os/ServiceManager.java b/core/java/android/os/ServiceManager.java
index 3c0997b3f4ea..74ff310ad3af 100644
--- a/core/java/android/os/ServiceManager.java
+++ b/core/java/android/os/ServiceManager.java
@@ -16,7 +16,7 @@
package android.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.ArrayMap;
import android.util.Log;
diff --git a/core/java/android/os/ServiceManagerNative.java b/core/java/android/os/ServiceManagerNative.java
index 124b6c6f7377..39ddcb2af3c2 100644
--- a/core/java/android/os/ServiceManagerNative.java
+++ b/core/java/android/os/ServiceManagerNative.java
@@ -16,7 +16,7 @@
package android.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* Native implementation of the service manager. Most clients will only
@@ -90,6 +90,15 @@ class ServiceManagerProxy implements IServiceManager {
throw new RemoteException();
}
+ public void registerClientCallback(String name, IBinder service, IClientCallback cb)
+ throws RemoteException {
+ throw new RemoteException();
+ }
+
+ public void tryUnregisterService(String name, IBinder service) throws RemoteException {
+ throw new RemoteException();
+ }
+
/**
* Same as mServiceManager but used by apps.
*
diff --git a/core/java/android/os/SharedMemory.java b/core/java/android/os/SharedMemory.java
index 57a88012a31a..26d9c7d687eb 100644
--- a/core/java/android/os/SharedMemory.java
+++ b/core/java/android/os/SharedMemory.java
@@ -18,7 +18,7 @@ package android.os;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
diff --git a/core/java/android/os/ShellCommand.java b/core/java/android/os/ShellCommand.java
index f3a6869687dc..0be3d681c80a 100644
--- a/core/java/android/os/ShellCommand.java
+++ b/core/java/android/os/ShellCommand.java
@@ -16,7 +16,7 @@
package android.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.Slog;
import com.android.internal.util.FastPrintWriter;
diff --git a/core/java/android/os/StatFs.java b/core/java/android/os/StatFs.java
index 881d0b4d9c8e..6d1a1164abb4 100644
--- a/core/java/android/os/StatFs.java
+++ b/core/java/android/os/StatFs.java
@@ -16,7 +16,7 @@
package android.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.system.ErrnoException;
import android.system.Os;
import android.system.StructStatVfs;
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index 0bf634e799cd..3faaff73a0ea 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -20,10 +20,10 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
import android.app.ActivityThread;
import android.app.IActivityManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/os/SystemClock.java b/core/java/android/os/SystemClock.java
index c104abdcb097..fd68c2b9b5fd 100644
--- a/core/java/android/os/SystemClock.java
+++ b/core/java/android/os/SystemClock.java
@@ -17,8 +17,8 @@
package android.os;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
import android.app.IAlarmManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.location.ILocationManager;
import android.location.LocationTime;
diff --git a/core/java/android/os/SystemProperties.java b/core/java/android/os/SystemProperties.java
index e7a271cbbb8e..c5e5cc40d54e 100644
--- a/core/java/android/os/SystemProperties.java
+++ b/core/java/android/os/SystemProperties.java
@@ -20,7 +20,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.Log;
import android.util.MutableInt;
diff --git a/core/java/android/os/SystemService.java b/core/java/android/os/SystemService.java
index 968c761c5ff0..5871d2d9b58f 100644
--- a/core/java/android/os/SystemService.java
+++ b/core/java/android/os/SystemService.java
@@ -16,9 +16,10 @@
package android.os;
+import android.compat.annotation.UnsupportedAppUsage;
+
import com.google.android.collect.Maps;
-import android.annotation.UnsupportedAppUsage;
import java.util.HashMap;
import java.util.concurrent.TimeoutException;
diff --git a/core/java/android/os/SystemVibrator.java b/core/java/android/os/SystemVibrator.java
index a5188e7cd58d..f585c75b6bb7 100644
--- a/core/java/android/os/SystemVibrator.java
+++ b/core/java/android/os/SystemVibrator.java
@@ -16,7 +16,7 @@
package android.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.media.AudioAttributes;
import android.util.Log;
@@ -70,6 +70,20 @@ public class SystemVibrator extends Vibrator {
}
@Override
+ public boolean setAlwaysOnEffect(int id, VibrationEffect effect, AudioAttributes attributes) {
+ if (mService == null) {
+ Log.w(TAG, "Failed to set always-on effect; no vibrator service.");
+ return false;
+ }
+ try {
+ return mService.setAlwaysOnEffect(id, effect, attributes);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to set always-on effect.", e);
+ }
+ return false;
+ }
+
+ @Override
public void vibrate(int uid, String opPkg, VibrationEffect effect,
String reason, AudioAttributes attributes) {
if (mService == null) {
diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java
index e132c11d6c8e..25584f156084 100644
--- a/core/java/android/os/Trace.java
+++ b/core/java/android/os/Trace.java
@@ -17,9 +17,7 @@
package android.os;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
-
-import com.android.internal.os.Zygote;
+import android.compat.annotation.UnsupportedAppUsage;
import dalvik.annotation.optimization.CriticalNative;
import dalvik.annotation.optimization.FastNative;
diff --git a/core/java/android/os/UEventObserver.java b/core/java/android/os/UEventObserver.java
index dc98c4267a37..fa30e509f8cc 100644
--- a/core/java/android/os/UEventObserver.java
+++ b/core/java/android/os/UEventObserver.java
@@ -16,7 +16,7 @@
package android.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.Log;
import java.util.ArrayList;
diff --git a/core/java/android/os/UpdateLock.java b/core/java/android/os/UpdateLock.java
index ea273cea8835..036d0951c19a 100644
--- a/core/java/android/os/UpdateLock.java
+++ b/core/java/android/os/UpdateLock.java
@@ -16,7 +16,7 @@
package android.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.util.Log;
diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java
index 62e83aa192aa..b92fb47d1112 100644
--- a/core/java/android/os/UserHandle.java
+++ b/core/java/android/os/UserHandle.java
@@ -20,8 +20,8 @@ import android.annotation.AppIdInt;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.UserIdInt;
+import android.compat.annotation.UnsupportedAppUsage;
import java.io.PrintWriter;
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index d099629f735d..fa9569bbe0ef 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -28,12 +28,12 @@ import android.annotation.StringDef;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.UserIdInt;
import android.annotation.WorkerThread;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.admin.DevicePolicyManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -442,7 +442,13 @@ public class UserManager {
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
* @see #getUserRestrictions()
+ * @deprecated As the ability to have a managed profile on a fully-managed device has been
+ * removed from the platform, this restriction will be silently ignored when applied by the
+ * device owner.
+ * When the device is provisioned with a managed profile on an organization-owned device,
+ * the managed profile could not be removed anyway.
*/
+ @Deprecated
public static final String DISALLOW_REMOVE_MANAGED_PROFILE = "no_remove_managed_profile";
/**
@@ -589,7 +595,11 @@ public class UserManager {
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
* @see #getUserRestrictions()
+ * @deprecated As the ability to have a managed profile on a fully-managed device has been
+ * removed from the platform, this restriction will be silently ignored when applied by the
+ * device owner.
*/
+ @Deprecated
public static final String DISALLOW_ADD_MANAGED_PROFILE = "no_add_managed_profile";
/**
@@ -1540,6 +1550,9 @@ public class UserManager {
* set by the user and is not a placeholder string provided by the system.
* @hide
*/
+ @SystemApi
+ @RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
+ Manifest.permission.GET_ACCOUNTS_PRIVILEGED})
public boolean isUserNameSet() {
try {
return mService.isUserNameSet(getUserHandle());
diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java
index 5769c34c6d20..75b4724c7d26 100644
--- a/core/java/android/os/VibrationEffect.java
+++ b/core/java/android/os/VibrationEffect.java
@@ -20,6 +20,7 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
import android.content.Context;
import android.hardware.vibrator.V1_0.EffectStrength;
@@ -27,8 +28,6 @@ import android.hardware.vibrator.V1_3.Effect;
import android.net.Uri;
import android.util.MathUtils;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java
index 28909c88a734..ccbb0f191f6f 100644
--- a/core/java/android/os/Vibrator.java
+++ b/core/java/android/os/Vibrator.java
@@ -17,10 +17,11 @@
package android.os;
import android.annotation.IntDef;
+import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.media.AudioAttributes;
import android.util.Log;
@@ -152,6 +153,24 @@ public abstract class Vibrator {
public abstract boolean hasAmplitudeControl();
/**
+ * Configure an always-on haptics effect.
+ *
+ * @param id The board-specific always-on ID to configure.
+ * @param effect Vibration effect to assign to always-on id. Passing null will disable it.
+ * @param attributes {@link AudioAttributes} corresponding to the vibration. For example,
+ * specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or
+ * {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for
+ * vibrations associated with incoming calls. May only be null when effect is null.
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.VIBRATE_ALWAYS_ON)
+ public boolean setAlwaysOnEffect(int id, @Nullable VibrationEffect effect,
+ @Nullable AudioAttributes attributes) {
+ Log.w(TAG, "Always-on effects aren't supported");
+ return false;
+ }
+
+ /**
* Vibrate constantly for the specified period of time.
*
* @param milliseconds The number of milliseconds to vibrate.
diff --git a/core/java/android/os/VintfObject.java b/core/java/android/os/VintfObject.java
index 1c78b081120a..7af8f71aa4aa 100644
--- a/core/java/android/os/VintfObject.java
+++ b/core/java/android/os/VintfObject.java
@@ -17,6 +17,7 @@
package android.os;
import android.annotation.TestApi;
+import android.util.Slog;
import java.util.Map;
@@ -28,6 +29,8 @@ import java.util.Map;
@TestApi
public class VintfObject {
+ private static final String LOG_TAG = "VintfObject";
+
/**
* Slurps all device information (both manifests and both matrices)
* and report them.
@@ -46,12 +49,33 @@ public class VintfObject {
* @param packageInfo a list of serialized form of HalManifest's /
* CompatibilityMatri'ces (XML).
* @return = 0 if success (compatible)
- * > 0 if incompatible
- * < 0 if any error (mount partition fails, illformed XML, etc.)
+ * &gt; 0 if incompatible
+ * &lt; 0 if any error (mount partition fails, illformed XML, etc.)
+ *
+ * @deprecated Checking compatibility against an OTA package is no longer
+ * supported because the format of VINTF metadata in the OTA package may not
+ * be recognized by the current system.
+ *
+ * <p>
+ * <ul>
+ * <li>This function always returns 0 for non-empty {@code packageInfo}.
+ * </li>
+ * <li>This function returns the result of {@link #verifyWithoutAvb} for
+ * null or empty {@code packageInfo}.</li>
+ * </ul>
*
* @hide
*/
- public static native int verify(String[] packageInfo);
+ @Deprecated
+ public static int verify(String[] packageInfo) {
+ if (packageInfo != null && packageInfo.length > 0) {
+ Slog.w(LOG_TAG, "VintfObject.verify() with non-empty packageInfo is deprecated. "
+ + "Skipping compatibility checks for update package.");
+ return 0;
+ }
+ Slog.w(LOG_TAG, "VintfObject.verify() is deprecated. Call verifyWithoutAvb() instead.");
+ return verifyWithoutAvb();
+ }
/**
* Verify Vintf compatibility on the device without checking AVB
diff --git a/core/java/android/os/WorkSource.java b/core/java/android/os/WorkSource.java
index 397c2a96c48e..7161b07cee3c 100644
--- a/core/java/android/os/WorkSource.java
+++ b/core/java/android/os/WorkSource.java
@@ -4,9 +4,8 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
-import android.os.WorkSourceProto;
import android.provider.Settings;
import android.provider.Settings.Global;
import android.util.Log;
diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java
index d17a5e026880..62b8953b158a 100644
--- a/core/java/android/os/ZygoteProcess.java
+++ b/core/java/android/os/ZygoteProcess.java
@@ -18,11 +18,12 @@ package android.os;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ApplicationInfo;
import android.net.LocalSocket;
import android.net.LocalSocketAddress;
import android.util.Log;
+import android.util.Pair;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
@@ -39,6 +40,7 @@ import java.util.Arrays;
import java.util.Base64;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
import java.util.UUID;
/*package*/ class ZygoteStartFailedEx extends Exception {
@@ -310,6 +312,8 @@ public class ZygoteProcess {
* started.
* @param zygoteArgs Additional arguments to supply to the zygote process.
* @param isTopApp Whether the process starts for high priority application.
+ * @param pkgDataInfoMap Map from related package names to private data directory
+ * volume UUID and inode number.
*
* @return An object that describes the result of the attempt to start the process.
* @throws RuntimeException on fatal start failure
@@ -328,6 +332,8 @@ public class ZygoteProcess {
boolean useUsapPool,
boolean isTopApp,
@Nullable long[] disabledCompatChanges,
+ @Nullable Map<String, Pair<String, Long>>
+ pkgDataInfoMap,
@Nullable String[] zygoteArgs) {
// TODO (chriswailes): Is there a better place to check this value?
if (fetchUsapPoolEnabledPropWithMinInterval()) {
@@ -338,7 +344,8 @@ public class ZygoteProcess {
return startViaZygote(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/ false,
- packageName, useUsapPool, isTopApp, disabledCompatChanges, zygoteArgs);
+ packageName, useUsapPool, isTopApp, disabledCompatChanges,
+ pkgDataInfoMap, zygoteArgs);
} catch (ZygoteStartFailedEx ex) {
Log.e(LOG_TAG,
"Starting VM process through Zygote failed");
@@ -539,6 +546,8 @@ public class ZygoteProcess {
* @param packageName null-ok the name of the package this process belongs to.
* @param isTopApp Whether the process starts for high priority application.
* @param disabledCompatChanges a list of disabled compat changes for the process being started.
+ * @param pkgDataInfoMap Map from related package names to private data directory volume UUID
+ * and inode number.
* @param extraArgs Additional arguments to supply to the zygote process.
* @return An object that describes the result of the attempt to start the process.
* @throws ZygoteStartFailedEx if process start failed for any reason
@@ -559,6 +568,8 @@ public class ZygoteProcess {
boolean useUsapPool,
boolean isTopApp,
@Nullable long[] disabledCompatChanges,
+ @Nullable Map<String, Pair<String, Long>>
+ pkgDataInfoMap,
@Nullable String[] extraArgs)
throws ZygoteStartFailedEx {
ArrayList<String> argsForZygote = new ArrayList<>();
@@ -635,6 +646,24 @@ public class ZygoteProcess {
if (isTopApp) {
argsForZygote.add(Zygote.START_AS_TOP_APP_ARG);
}
+ if (pkgDataInfoMap != null && pkgDataInfoMap.size() > 0) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(Zygote.PKG_DATA_INFO_MAP);
+ sb.append("=");
+ boolean started = false;
+ for (Map.Entry<String, Pair<String, Long>> entry : pkgDataInfoMap.entrySet()) {
+ if (started) {
+ sb.append(',');
+ }
+ started = true;
+ sb.append(entry.getKey());
+ sb.append(',');
+ sb.append(entry.getValue().first);
+ sb.append(',');
+ sb.append(entry.getValue().second);
+ }
+ argsForZygote.add(sb.toString());
+ }
if (disabledCompatChanges != null && disabledCompatChanges.length > 0) {
StringBuilder sb = new StringBuilder();
@@ -1182,12 +1211,14 @@ public class ZygoteProcess {
Process.ProcessStartResult result;
try {
+ // As app zygote is for generating isolated process, at the end it can't access
+ // apps data, so doesn't need to its data info.
result = startViaZygote(processClass, niceName, uid, gid,
gids, runtimeFlags, 0 /* mountExternal */, 0 /* targetSdkVersion */, seInfo,
abi, instructionSet, null /* appDataDir */, null /* invokeWith */,
true /* startChildZygote */, null /* packageName */,
false /* useUsapPool */, false /* isTopApp */,
- null /* disabledCompatChanges */, extraArgs);
+ null /* disabledCompatChanges */, null /* pkgDataInfoMap */, extraArgs);
} catch (ZygoteStartFailedEx ex) {
throw new RuntimeException("Starting child-zygote through Zygote failed", ex);
}
diff --git a/core/java/android/os/health/HealthStatsParceler.java b/core/java/android/os/health/HealthStatsParceler.java
index 384342c894d5..f28a9747bc44 100644
--- a/core/java/android/os/health/HealthStatsParceler.java
+++ b/core/java/android/os/health/HealthStatsParceler.java
@@ -17,11 +17,10 @@
package android.os.health;
import android.annotation.TestApi;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
/**
* Class to allow sending the HealthStats through aidl generated glue.
*
diff --git a/core/java/android/os/health/SystemHealthManager.java b/core/java/android/os/health/SystemHealthManager.java
index a92e28a47660..6e259ea2642c 100644
--- a/core/java/android/os/health/SystemHealthManager.java
+++ b/core/java/android/os/health/SystemHealthManager.java
@@ -17,14 +17,13 @@
package android.os.health;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.BatteryStats;
import android.os.Build;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.os.ServiceManager.ServiceNotFoundException;
import com.android.internal.app.IBatteryStats;
diff --git a/core/java/android/os/incremental/IIncrementalManager.aidl b/core/java/android/os/incremental/IIncrementalManager.aidl
index f84d7efe06b1..17a310a5beb0 100644
--- a/core/java/android/os/incremental/IIncrementalManager.aidl
+++ b/core/java/android/os/incremental/IIncrementalManager.aidl
@@ -16,8 +16,8 @@
package android.os.incremental;
-import android.os.incremental.IncrementalFileSystemControlParcel;
-import android.os.incremental.IncrementalDataLoaderParamsParcel;
+import android.content.pm.FileSystemControlParcel;
+import android.content.pm.DataLoaderParamsParcel;
import android.content.pm.IDataLoaderStatusListener;
/**
@@ -27,8 +27,8 @@ import android.content.pm.IDataLoaderStatusListener;
*/
interface IIncrementalManager {
boolean prepareDataLoader(int mountId,
- in IncrementalFileSystemControlParcel control,
- in IncrementalDataLoaderParamsParcel params,
+ in FileSystemControlParcel control,
+ in DataLoaderParamsParcel params,
in IDataLoaderStatusListener listener);
boolean startDataLoader(int mountId);
void showHealthBlockedUI(int mountId);
diff --git a/core/java/android/os/incremental/IIncrementalManagerNative.aidl b/core/java/android/os/incremental/IIncrementalManagerNative.aidl
index d9c7c6b5cc21..14215b1ea84d 100644
--- a/core/java/android/os/incremental/IIncrementalManagerNative.aidl
+++ b/core/java/android/os/incremental/IIncrementalManagerNative.aidl
@@ -16,7 +16,7 @@
package android.os.incremental;
-import android.os.incremental.IncrementalDataLoaderParamsParcel;
+import android.content.pm.DataLoaderParamsParcel;
/** @hide */
interface IIncrementalManagerNative {
@@ -32,7 +32,7 @@ interface IIncrementalManagerNative {
* Opens or creates a storage given a target path and data loader params. Returns the storage ID.
*/
int openStorage(in @utf8InCpp String path);
- int createStorage(in @utf8InCpp String path, in IncrementalDataLoaderParamsParcel params, int createMode);
+ int createStorage(in @utf8InCpp String path, in DataLoaderParamsParcel params, int createMode);
int createLinkedStorage(in @utf8InCpp String path, int otherStorageId, int createMode);
/**
diff --git a/core/java/android/os/incremental/IncrementalDataLoaderParams.java b/core/java/android/os/incremental/IncrementalDataLoaderParams.java
deleted file mode 100644
index 701f1cc8de02..000000000000
--- a/core/java/android/os/incremental/IncrementalDataLoaderParams.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os.incremental;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.ParcelFileDescriptor;
-
-import java.util.Arrays;
-import java.util.Map;
-import java.util.stream.Collectors;
-
-/**
- * This class represents the parameters used to configure an Incremental Data Loader.
- * Hide for now.
- * @hide
- */
-public class IncrementalDataLoaderParams {
- @NonNull private final IncrementalDataLoaderParamsParcel mData;
-
- public IncrementalDataLoaderParams(@NonNull String url, @NonNull String packageName,
- @Nullable Map<String, ParcelFileDescriptor> namedFds) {
- IncrementalDataLoaderParamsParcel data = new IncrementalDataLoaderParamsParcel();
- data.staticArgs = url;
- data.packageName = packageName;
- if (namedFds == null || namedFds.isEmpty()) {
- data.dynamicArgs = new NamedParcelFileDescriptor[0];
- } else {
- data.dynamicArgs = new NamedParcelFileDescriptor[namedFds.size()];
- int i = 0;
- for (Map.Entry<String, ParcelFileDescriptor> namedFd : namedFds.entrySet()) {
- data.dynamicArgs[i] = new NamedParcelFileDescriptor();
- data.dynamicArgs[i].name = namedFd.getKey();
- data.dynamicArgs[i].fd = namedFd.getValue();
- i += 1;
- }
- }
- mData = data;
- }
-
- public IncrementalDataLoaderParams(@NonNull IncrementalDataLoaderParamsParcel data) {
- mData = data;
- }
-
- /**
- * @return static server's URL
- */
- public final @NonNull String getStaticArgs() {
- return mData.staticArgs;
- }
-
- /**
- * @return data loader's package name
- */
- public final @NonNull String getPackageName() {
- return mData.packageName;
- }
-
- public final @NonNull IncrementalDataLoaderParamsParcel getData() {
- return mData;
- }
-
- /**
- * @return data loader's dynamic arguments such as file descriptors
- */
- public final @NonNull Map<String, ParcelFileDescriptor> getDynamicArgs() {
- return Arrays.stream(mData.dynamicArgs).collect(
- Collectors.toMap(p->p.name, p->p.fd));
- }
-}
diff --git a/core/java/android/os/incremental/IncrementalFileStorages.java b/core/java/android/os/incremental/IncrementalFileStorages.java
index 5bd0748b8d97..2138d553102e 100644
--- a/core/java/android/os/incremental/IncrementalFileStorages.java
+++ b/core/java/android/os/incremental/IncrementalFileStorages.java
@@ -35,6 +35,7 @@ import static dalvik.system.VMRuntime.getInstructionSet;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.content.pm.DataLoaderParams;
import android.content.pm.InstallationFile;
import android.os.IVold;
import android.os.RemoteException;
@@ -82,12 +83,12 @@ public final class IncrementalFileStorages {
public IncrementalFileStorages(@NonNull String packageName,
@NonNull File stageDir,
@NonNull IncrementalManager incrementalManager,
- @NonNull IncrementalDataLoaderParams incrementalDataLoaderParams) {
+ @NonNull DataLoaderParams dataLoaderParams) {
mPackageName = packageName;
mStageDir = stageDir;
mIncrementalManager = incrementalManager;
- if (incrementalDataLoaderParams.getPackageName().equals("local")) {
- final String incrementalPath = incrementalDataLoaderParams.getStaticArgs();
+ if (dataLoaderParams.getComponentName().getPackageName().equals("local")) {
+ final String incrementalPath = dataLoaderParams.getArguments();
mDefaultStorage = mIncrementalManager.openStorage(incrementalPath);
mDefaultDir = incrementalPath;
return;
@@ -97,7 +98,7 @@ public final class IncrementalFileStorages {
return;
}
mDefaultStorage = mIncrementalManager.createStorage(mDefaultDir,
- incrementalDataLoaderParams,
+ dataLoaderParams,
IncrementalManager.CREATE_MODE_CREATE
| IncrementalManager.CREATE_MODE_TEMPORARY_BIND, false);
}
@@ -265,7 +266,7 @@ public final class IncrementalFileStorages {
}
private String getTempDir() {
- final String tmpDirRoot = "/data/tmp";
+ final String tmpDirRoot = "/data/incremental/tmp";
final Random random = new Random();
final Path tmpDir =
Paths.get(tmpDirRoot, String.valueOf(random.nextInt(Integer.MAX_VALUE - 1)));
diff --git a/core/java/android/os/incremental/IncrementalManager.java b/core/java/android/os/incremental/IncrementalManager.java
index c30f5589a835..9c6672d8ab68 100644
--- a/core/java/android/os/incremental/IncrementalManager.java
+++ b/core/java/android/os/incremental/IncrementalManager.java
@@ -21,6 +21,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemService;
import android.content.Context;
+import android.content.pm.DataLoaderParams;
import android.os.RemoteException;
import android.system.ErrnoException;
import android.system.Os;
@@ -104,7 +105,7 @@ public final class IncrementalManager {
*/
@Nullable
public IncrementalStorage createStorage(@NonNull String path,
- @NonNull IncrementalDataLoaderParams params, @CreateMode int createMode,
+ @NonNull DataLoaderParams params, @CreateMode int createMode,
boolean autoStartDataLoader) {
try {
final int id = mNativeService.createStorage(path, params.getData(), createMode);
@@ -327,7 +328,9 @@ public final class IncrementalManager {
* Checks if path is mounted on Incremental File System.
*/
public static boolean isIncrementalPath(@NonNull String path) {
- // TODO(b/136132412): add jni implementation
- return false;
+ return nativeIsIncrementalPath(path);
}
+
+ /* Native methods */
+ private static native boolean nativeIsIncrementalPath(@NonNull String path);
}
diff --git a/core/java/android/os/storage/CrateInfo.aidl b/core/java/android/os/storage/CrateInfo.aidl
new file mode 100644
index 000000000000..dd910532c0a7
--- /dev/null
+++ b/core/java/android/os/storage/CrateInfo.aidl
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.os.storage;
+
+/**
+ * @hide
+ */
+parcelable CrateInfo;
diff --git a/core/java/android/os/storage/CrateInfo.java b/core/java/android/os/storage/CrateInfo.java
new file mode 100644
index 000000000000..418d39e0c495
--- /dev/null
+++ b/core/java/android/os/storage/CrateInfo.java
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os.storage;
+
+import android.annotation.CurrentTimeMillisLong;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.TestApi;
+import android.app.usage.StorageStatsManager;
+import android.content.Context;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.UserHandle;
+import android.text.TextUtils;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.UUID;
+
+/**
+ * The CrateInfo describe the crate information.
+ * <p>
+ * It describe the following items.
+ * <ul>
+ * <li>The crate id that is the name of the child directory in
+ * {@link Context#getCrateDir(String)}</li>
+ * <li>Label to provide human readable text for the users.</li>
+ * <li>Expiration information. When the crate is expired and the run .</li>
+ *
+ * </ul>for the directory
+ * </p>
+ * @hide
+ */
+@TestApi
+public final class CrateInfo implements Parcelable {
+ private static final String TAG = "CrateInfo";
+
+ /**
+ * The following member fields whose value are set by apps and retrieved by system_server.
+ */
+ private CharSequence mLabel;
+ @CurrentTimeMillisLong
+ private long mExpiration;
+
+ /**
+ * The following member fields whose value are retrieved by installd.
+ * <p>{@link android.app.usage.StorageStatsManager#queryCratesForUser(UUID, UserHandle)} query
+ * all of crates for the specified UserHandle. That means the return crate list whose elements
+ * may have the same userId but different package name. Each crate needs the information to tell
+ * the caller from where package comes.
+ * </p>
+ */
+ private int mUid;
+
+ /**
+ * The following member fields whose value are retrieved by installd.
+ * <p>Both {@link StorageStatsManager#queryCratesForUid(UUID, int)} and
+ * {@link android.app.usage.StorageStatsManager#queryCratesForUser(UUID, UserHandle)} query
+ * all of crates for the specified uid or userId. That means the return crate list whose
+ * elements may have the same uid or userId but different package name. Each crate needs the
+ * information to tell the caller from where package comes.
+ * </p>
+ */
+ @Nullable
+ private String mPackageName;
+
+ /**
+ * The following member fields whose value are retrieved by system_server.
+ * <p>
+ * The child directories in {@link Context#getCrateDir(String)} are crates. Each directories
+ * is a crate. The folder name is the crate id.
+ * </p><p>
+ * Can't apply check if the path is validated or not because it need pass through the
+ * parcel.
+ * </p>
+ */
+ @Nullable
+ private String mId;
+
+ private CrateInfo() {
+ mExpiration = 0;
+ }
+
+ /**
+ * To create the crateInfo by passing validated label.
+ * @param label a display name for the crate
+ * @param expiration It's positive integer. if current time is larger than the expiration, the
+ * files under this crate will be considered to be deleted. Default value is 0.
+ * @throws IllegalArgumentException cause IllegalArgumentException when label is null
+ * or empty string
+ */
+ public CrateInfo(@NonNull CharSequence label, @CurrentTimeMillisLong long expiration) {
+ Preconditions.checkStringNotEmpty(label,
+ "Label should not be either null or empty string");
+ Preconditions.checkArgumentNonnegative(expiration,
+ "Expiration should be non negative number");
+
+ mLabel = label;
+ mExpiration = expiration;
+ }
+
+ /**
+ * To create the crateInfo by passing validated label.
+ * @param label a display name for the crate
+ * @throws IllegalArgumentException cause IllegalArgumentException when label is null
+ * or empty string
+ */
+ public CrateInfo(@NonNull CharSequence label) {
+ this(label, 0);
+ }
+
+ /**
+ * To get the meaningful text of the crate for the users.
+ * @return the meaningful text
+ */
+ @NonNull
+ public CharSequence getLabel() {
+ if (TextUtils.isEmpty(mLabel)) {
+ return mId;
+ }
+ return mLabel;
+ }
+
+
+ /**
+ * To return the expiration time.
+ * <p>
+ * If the current time is larger than expiration time, the crate files are considered to be
+ * deleted.
+ * </p>
+ * @return the expiration time
+ */
+ @CurrentTimeMillisLong
+ public long getExpirationMillis() {
+ return mExpiration;
+ }
+
+ /**
+ * To set the expiration time.
+ * @param expiration the expiration time
+ * @hide
+ */
+ public void setExpiration(@CurrentTimeMillisLong long expiration) {
+ Preconditions.checkArgumentNonnegative(expiration);
+ mExpiration = expiration;
+ }
+
+ @Override
+ public int hashCode() {
+ return super.hashCode();
+ }
+
+ /**
+ * To compare with crateinfo when selves' mId is validated.
+ * <p>The validated crateinfo.mId must be validated the following items.
+ * <ul>
+ * <li>mId is not null</li>
+ * <li>mId is not empty string</li>
+ * </ul>
+ * </p>
+ * @param obj the reference object with which to compare.
+ * @return true when selves's mId is validated and equal to crateinfo.mId.
+ */
+ @Override
+ public boolean equals(@Nullable Object obj) {
+ if (obj == null) {
+ return false;
+ }
+
+ if (obj instanceof CrateInfo) {
+ CrateInfo crateInfo = (CrateInfo) obj;
+ if (!TextUtils.isEmpty(mId)
+ && TextUtils.equals(mId, crateInfo.mId)) {
+ return true;
+ }
+ }
+
+ return super.equals(obj);
+ }
+
+
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@Nullable Parcel dest, int flags) {
+ if (dest == null) {
+ return;
+ }
+
+ dest.writeCharSequence(mLabel);
+ dest.writeLong(mExpiration);
+
+ dest.writeInt(mUid);
+ dest.writeString(mPackageName);
+ dest.writeString(mId);
+ }
+
+ /**
+ * To read the data from parcel.
+ * <p>
+ * It's called by StorageStatsService.
+ * </p>
+ * @hide
+ */
+ public void readFromParcel(@Nullable Parcel in) {
+ if (in == null) {
+ return;
+ }
+
+ mLabel = in.readCharSequence();
+ mExpiration = in.readLong();
+
+ mUid = in.readInt();
+ mPackageName = in.readString();
+ mId = in.readString();
+ }
+
+ @NonNull
+ public static final Creator<CrateInfo> CREATOR = new Creator<CrateInfo>() {
+ @NonNull
+ @Override
+ public CrateInfo createFromParcel(@NonNull Parcel in) {
+ CrateInfo crateInfo = new CrateInfo();
+ crateInfo.readFromParcel(in);
+ return crateInfo;
+ }
+
+ @NonNull
+ @Override
+ public CrateInfo[] newArray(int size) {
+ return new CrateInfo[size];
+ }
+ };
+
+ /**
+ * To copy the information from service into crateinfo.
+ * <p>
+ * This function is called in system_server. The copied information includes
+ * <ul>
+ * <li>uid</li>
+ * <li>package name</li>
+ * <li>crate id</li>
+ * </ul>
+ * </p>
+ * @param uid the uid that the crate belong to
+ * @param packageName the package name that the crate belong to
+ * @param id the crate dir
+ * @return the CrateInfo instance
+ * @hide
+ */
+ @TestApi
+ @Nullable
+ public static CrateInfo copyFrom(int uid, @Nullable String packageName, @Nullable String id) {
+ if (!UserHandle.isApp(uid) || TextUtils.isEmpty(packageName) || TextUtils.isEmpty(id)) {
+ return null;
+ }
+
+ CrateInfo crateInfo = new CrateInfo(id /* default label = id */, 0);
+ crateInfo.mUid = uid;
+ crateInfo.mPackageName = packageName;
+ crateInfo.mId = id;
+ return crateInfo;
+ }
+}
diff --git a/core/java/android/os/storage/DiskInfo.java b/core/java/android/os/storage/DiskInfo.java
index b797324c8007..df3c4d55d979 100644
--- a/core/java/android/os/storage/DiskInfo.java
+++ b/core/java/android/os/storage/DiskInfo.java
@@ -18,7 +18,7 @@ package android.os.storage;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.Resources;
import android.os.Build;
import android.os.Parcel;
diff --git a/core/java/android/os/storage/StorageEventListener.java b/core/java/android/os/storage/StorageEventListener.java
index 39d5b4529745..9fd9e4e4067d 100644
--- a/core/java/android/os/storage/StorageEventListener.java
+++ b/core/java/android/os/storage/StorageEventListener.java
@@ -16,7 +16,7 @@
package android.os.storage;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* Used for receiving notifications from the StorageManager
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 2e9f27e74544..8959fcf7ac18 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -40,12 +40,12 @@ import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.WorkerThread;
import android.app.Activity;
import android.app.ActivityThread;
import android.app.AppGlobals;
import android.app.AppOpsManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/os/storage/StorageVolume.java b/core/java/android/os/storage/StorageVolume.java
index 560d6171d5ee..2ab226f81bb4 100644
--- a/core/java/android/os/storage/StorageVolume.java
+++ b/core/java/android/os/storage/StorageVolume.java
@@ -19,7 +19,7 @@ package android.os.storage;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java
index d6ec52fac8a5..fb9065568e9b 100644
--- a/core/java/android/os/storage/VolumeInfo.java
+++ b/core/java/android/os/storage/VolumeInfo.java
@@ -18,7 +18,7 @@ package android.os.storage;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
diff --git a/core/java/android/os/storage/VolumeRecord.java b/core/java/android/os/storage/VolumeRecord.java
index 99b45d60c319..60df9819f591 100644
--- a/core/java/android/os/storage/VolumeRecord.java
+++ b/core/java/android/os/storage/VolumeRecord.java
@@ -16,7 +16,7 @@
package android.os.storage;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Environment;
import android.os.Parcel;
diff --git a/core/java/android/permission/IPermissionController.aidl b/core/java/android/permission/IPermissionController.aidl
index 26c1ec170834..0483514e6297 100644
--- a/core/java/android/permission/IPermissionController.aidl
+++ b/core/java/android/permission/IPermissionController.aidl
@@ -43,4 +43,5 @@ oneway interface IPermissionController {
String permission, int grantState, in AndroidFuture callback);
void grantOrUpgradeDefaultRuntimePermissions(in AndroidFuture callback);
void updateUserSensitive(in AndroidFuture callback);
+ void notifyOneTimePermissionSessionTimeout(String packageName);
}
diff --git a/core/java/android/permission/IPermissionManager.aidl b/core/java/android/permission/IPermissionManager.aidl
index 60c88116f804..2615c98a6d5e 100644
--- a/core/java/android/permission/IPermissionManager.aidl
+++ b/core/java/android/permission/IPermissionManager.aidl
@@ -20,6 +20,7 @@ import android.content.pm.ParceledListSlice;
import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
import android.content.pm.permission.SplitPermissionInfoParcelable;
+import android.os.UserHandle;
import android.permission.IOnPermissionsChangeListener;
/**
@@ -100,4 +101,9 @@ interface IPermissionManager {
boolean isPermissionRevokedByPolicy(String permName, String packageName, int userId);
List<SplitPermissionInfoParcelable> getSplitPermissions();
+
+ void startOneTimePermissionSession(String packageName, int userId, long timeout,
+ int importanceToResetTimer, int importanceToKeepSessionAlive);
+
+ void stopOneTimePermissionSession(String packageName, int userId);
}
diff --git a/core/java/android/permission/PermissionControllerManager.java b/core/java/android/permission/PermissionControllerManager.java
index 421e29ed0542..2a1857fd0027 100644
--- a/core/java/android/permission/PermissionControllerManager.java
+++ b/core/java/android/permission/PermissionControllerManager.java
@@ -636,4 +636,18 @@ public final class PermissionControllerManager {
return future;
});
}
+
+ /**
+ * Called when a package that has permissions registered as "one-time" is considered
+ * inactive.
+ *
+ * @param packageName The package which became inactive
+ *
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.REVOKE_RUNTIME_PERMISSIONS)
+ public void notifyOneTimePermissionSessionTimeout(@NonNull String packageName) {
+ mRemoteService.run(
+ service -> service.notifyOneTimePermissionSessionTimeout(packageName));
+ }
}
diff --git a/core/java/android/permission/PermissionControllerService.java b/core/java/android/permission/PermissionControllerService.java
index f9146637c8cb..5d4561c21e55 100644
--- a/core/java/android/permission/PermissionControllerService.java
+++ b/core/java/android/permission/PermissionControllerService.java
@@ -240,6 +240,18 @@ public abstract class PermissionControllerService extends Service {
@NonNull String permission, @PermissionGrantState int grantState,
@NonNull Consumer<Boolean> callback);
+ /**
+ * Called when a package is considered inactive based on the criteria given by
+ * {@link PermissionManager#startOneTimePermissionSession(String, long, int, int)}.
+ * This method is called at the end of a one-time permission session
+ *
+ * @param packageName The package that has been inactive
+ */
+ @BinderThread
+ public void onOneTimePermissionSessionTimeout(@NonNull String packageName) {
+ throw new AbstractMethodError("Must be overridden in implementing class");
+ }
+
@Override
public final @NonNull IBinder onBind(Intent intent) {
return new IPermissionController.Stub() {
@@ -452,6 +464,15 @@ public abstract class PermissionControllerService extends Service {
onUpdateUserSensitivePermissionFlags();
callback.complete(null);
}
+
+ @Override
+ public void notifyOneTimePermissionSessionTimeout(String packageName) {
+ enforceSomePermissionsGrantedToCaller(
+ Manifest.permission.REVOKE_RUNTIME_PERMISSIONS);
+ packageName = Preconditions.checkNotNull(packageName,
+ "packageName cannot be null");
+ onOneTimePermissionSessionTimeout(packageName);
+ }
};
}
}
diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java
index 09286feee6b9..a3215a47fd62 100644
--- a/core/java/android/permission/PermissionManager.java
+++ b/core/java/android/permission/PermissionManager.java
@@ -25,6 +25,7 @@ import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
+import android.app.ActivityManager;
import android.app.ActivityThread;
import android.content.Context;
import android.content.pm.IPackageManager;
@@ -284,4 +285,69 @@ public final class PermissionManager {
mSplitPermissionInfoParcelable = parcelable;
}
}
+
+ /**
+ * Starts a one-time permission session for a given package. A one-time permission session is
+ * ended if app becomes inactive. Inactivity is defined as the package's uid importance level
+ * staying > importanceToResetTimer for timeoutMillis milliseconds. If the package's uid
+ * importance level goes <= importanceToResetTimer then the timer is reset and doesn't start
+ * until going > importanceToResetTimer.
+ * <p>
+ * When this timeoutMillis is reached if the importance level is <= importanceToKeepSessionAlive
+ * then the session is extended until either the importance goes above
+ * importanceToKeepSessionAlive which will end the session or <= importanceToResetTimer which
+ * will continue the session and reset the timer.
+ * </p>
+ * <p>
+ * Importance levels are defined in {@link android.app.ActivityManager.RunningAppProcessInfo}.
+ * </p>
+ * <p>
+ * Once the session ends
+ * {@link PermissionControllerService#onOneTimePermissionSessionTimeout(String)} is invoked.
+ * </p>
+ * <p>
+ * Note that if there is currently an active session for a package a new one isn't created and
+ * the existing one isn't changed.
+ * </p>
+ * @param packageName The package to start a one-time permission session for
+ * @param timeoutMillis Number of milliseconds for an app to be in an inactive state
+ * @param importanceToResetTimer The least important level to uid must be to reset the timer
+ * @param importanceToKeepSessionAlive The least important level the uid must be to keep the
+ * session alive
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(allOf = {Manifest.permission.REVOKE_RUNTIME_PERMISSIONS,
+ Manifest.permission.PACKAGE_USAGE_STATS})
+ public void startOneTimePermissionSession(@NonNull String packageName, long timeoutMillis,
+ @ActivityManager.RunningAppProcessInfo.Importance int importanceToResetTimer,
+ @ActivityManager.RunningAppProcessInfo.Importance int importanceToKeepSessionAlive) {
+ try {
+ mPermissionManager.startOneTimePermissionSession(packageName, mContext.getUserId(),
+ timeoutMillis, importanceToResetTimer, importanceToKeepSessionAlive);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Stops the one-time permission session for the package. The callback to the end of session is
+ * not invoked. If there is no one-time session for the package then nothing happens.
+ *
+ * @param packageName Package to stop the one-time permission session for
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(allOf = {Manifest.permission.REVOKE_RUNTIME_PERMISSIONS,
+ Manifest.permission.PACKAGE_USAGE_STATS})
+ public void stopOneTimePermissionSession(@NonNull String packageName) {
+ try {
+ mPermissionManager.stopOneTimePermissionSession(packageName,
+ mContext.getUserId());
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/core/java/android/preference/DialogPreference.java b/core/java/android/preference/DialogPreference.java
index 32511e9afbea..dfdb57c4e3f8 100644
--- a/core/java/android/preference/DialogPreference.java
+++ b/core/java/android/preference/DialogPreference.java
@@ -21,9 +21,9 @@ import android.annotation.CallSuper;
import android.annotation.DrawableRes;
import android.annotation.Nullable;
import android.annotation.StringRes;
-import android.annotation.UnsupportedAppUsage;
import android.app.AlertDialog;
import android.app.Dialog;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
diff --git a/core/java/android/preference/EditTextPreference.java b/core/java/android/preference/EditTextPreference.java
index 74c5e3e49d63..af6f18416870 100644
--- a/core/java/android/preference/EditTextPreference.java
+++ b/core/java/android/preference/EditTextPreference.java
@@ -17,7 +17,7 @@
package android.preference;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.TypedArray;
diff --git a/core/java/android/preference/ListPreference.java b/core/java/android/preference/ListPreference.java
index 830de52576d8..0b648094150f 100644
--- a/core/java/android/preference/ListPreference.java
+++ b/core/java/android/preference/ListPreference.java
@@ -17,8 +17,8 @@
package android.preference;
import android.annotation.ArrayRes;
-import android.annotation.UnsupportedAppUsage;
import android.app.AlertDialog.Builder;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.TypedArray;
diff --git a/core/java/android/preference/Preference.java b/core/java/android/preference/Preference.java
index e82e60dfe1c4..f508dda00c55 100644
--- a/core/java/android/preference/Preference.java
+++ b/core/java/android/preference/Preference.java
@@ -21,7 +21,7 @@ import android.annotation.DrawableRes;
import android.annotation.LayoutRes;
import android.annotation.Nullable;
import android.annotation.StringRes;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java
index 47509713d335..ae4a626cdd5d 100644
--- a/core/java/android/preference/PreferenceActivity.java
+++ b/core/java/android/preference/PreferenceActivity.java
@@ -19,13 +19,13 @@ package android.preference;
import android.animation.LayoutTransition;
import android.annotation.Nullable;
import android.annotation.StringRes;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.XmlRes;
import android.app.Fragment;
import android.app.FragmentBreadCrumbs;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.app.ListActivity;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
diff --git a/core/java/android/preference/PreferenceFragment.java b/core/java/android/preference/PreferenceFragment.java
index d6c069f07d22..3f6e5051a3f8 100644
--- a/core/java/android/preference/PreferenceFragment.java
+++ b/core/java/android/preference/PreferenceFragment.java
@@ -17,10 +17,10 @@
package android.preference;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.XmlRes;
import android.app.Activity;
import android.app.Fragment;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.TypedArray;
diff --git a/core/java/android/preference/PreferenceGroupAdapter.java b/core/java/android/preference/PreferenceGroupAdapter.java
index dcc5d4c58784..b263f5041fd6 100644
--- a/core/java/android/preference/PreferenceGroupAdapter.java
+++ b/core/java/android/preference/PreferenceGroupAdapter.java
@@ -16,7 +16,7 @@
package android.preference;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.preference.Preference.OnPreferenceChangeInternalListener;
diff --git a/core/java/android/preference/PreferenceManager.java b/core/java/android/preference/PreferenceManager.java
index f741bd686beb..9d3f349320ad 100644
--- a/core/java/android/preference/PreferenceManager.java
+++ b/core/java/android/preference/PreferenceManager.java
@@ -18,9 +18,9 @@ package android.preference;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.XmlRes;
import android.app.Activity;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
diff --git a/core/java/android/preference/PreferenceScreen.java b/core/java/android/preference/PreferenceScreen.java
index a353dbc8af1b..01fe2f3f6b3a 100644
--- a/core/java/android/preference/PreferenceScreen.java
+++ b/core/java/android/preference/PreferenceScreen.java
@@ -16,8 +16,8 @@
package android.preference;
-import android.annotation.UnsupportedAppUsage;
import android.app.Dialog;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.TypedArray;
diff --git a/core/java/android/preference/RingtonePreference.java b/core/java/android/preference/RingtonePreference.java
index 025aad0fcaac..c6d8c08c9141 100644
--- a/core/java/android/preference/RingtonePreference.java
+++ b/core/java/android/preference/RingtonePreference.java
@@ -16,7 +16,7 @@
package android.preference;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.res.TypedArray;
diff --git a/core/java/android/preference/SeekBarDialogPreference.java b/core/java/android/preference/SeekBarDialogPreference.java
index 32ef82103f6c..46be12211fe4 100644
--- a/core/java/android/preference/SeekBarDialogPreference.java
+++ b/core/java/android/preference/SeekBarDialogPreference.java
@@ -16,7 +16,7 @@
package android.preference;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
diff --git a/core/java/android/preference/SeekBarPreference.java b/core/java/android/preference/SeekBarPreference.java
index 99ab9dbeb280..a2852bc2cce3 100644
--- a/core/java/android/preference/SeekBarPreference.java
+++ b/core/java/android/preference/SeekBarPreference.java
@@ -16,7 +16,7 @@
package android.preference;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Parcel;
diff --git a/core/java/android/preference/SeekBarVolumizer.java b/core/java/android/preference/SeekBarVolumizer.java
index 4dd9baba3e5f..0cdad9f8de93 100644
--- a/core/java/android/preference/SeekBarVolumizer.java
+++ b/core/java/android/preference/SeekBarVolumizer.java
@@ -17,8 +17,8 @@
package android.preference;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
import android.app.NotificationManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/preference/SwitchPreference.java b/core/java/android/preference/SwitchPreference.java
index 9dea1c829713..baa023e41aad 100644
--- a/core/java/android/preference/SwitchPreference.java
+++ b/core/java/android/preference/SwitchPreference.java
@@ -17,7 +17,7 @@
package android.preference;
import android.annotation.StringRes;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
diff --git a/core/java/android/preference/TwoStatePreference.java b/core/java/android/preference/TwoStatePreference.java
index bb771d721d83..5eb5d17d9bc8 100644
--- a/core/java/android/preference/TwoStatePreference.java
+++ b/core/java/android/preference/TwoStatePreference.java
@@ -17,7 +17,7 @@
package android.preference;
import android.annotation.StringRes;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.TypedArray;
diff --git a/core/java/android/preference/VolumePreference.java b/core/java/android/preference/VolumePreference.java
index a2d5a2312047..6eb524a3886c 100644
--- a/core/java/android/preference/VolumePreference.java
+++ b/core/java/android/preference/VolumePreference.java
@@ -16,8 +16,8 @@
package android.preference;
-import android.annotation.UnsupportedAppUsage;
import android.app.Dialog;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Parcel;
diff --git a/core/java/android/print/PrintDocumentAdapter.java b/core/java/android/print/PrintDocumentAdapter.java
index d1b6efc70a2a..7ea5655169e9 100644
--- a/core/java/android/print/PrintDocumentAdapter.java
+++ b/core/java/android/print/PrintDocumentAdapter.java
@@ -16,7 +16,7 @@
package android.print;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.ParcelFileDescriptor;
diff --git a/core/java/android/print/PrintJobInfo.java b/core/java/android/print/PrintJobInfo.java
index 25f383c09ad1..63f38f8a7b4c 100644
--- a/core/java/android/print/PrintJobInfo.java
+++ b/core/java/android/print/PrintJobInfo.java
@@ -23,7 +23,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringRes;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.os.Bundle;
diff --git a/core/java/android/print/PrintManager.java b/core/java/android/print/PrintManager.java
index e1ede93a9ac5..9abce5d46ac6 100644
--- a/core/java/android/print/PrintManager.java
+++ b/core/java/android/print/PrintManager.java
@@ -22,9 +22,9 @@ import android.annotation.RequiresFeature;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
import android.app.Activity;
import android.app.Application.ActivityLifecycleCallbacks;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.IntentSender;
diff --git a/core/java/android/print/PrinterId.java b/core/java/android/print/PrinterId.java
index 42570c69650f..75ca7507450f 100644
--- a/core/java/android/print/PrinterId.java
+++ b/core/java/android/print/PrinterId.java
@@ -17,7 +17,7 @@
package android.print;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/provider/Browser.java b/core/java/android/provider/Browser.java
index 30021b488dc5..afa7b80f58a0 100644
--- a/core/java/android/provider/Browser.java
+++ b/core/java/android/provider/Browser.java
@@ -16,10 +16,8 @@
package android.provider;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
-import android.content.ContentUris;
-import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
@@ -30,8 +28,6 @@ import android.net.Uri;
import android.provider.BrowserContract.Bookmarks;
import android.provider.BrowserContract.Combined;
import android.provider.BrowserContract.History;
-import android.provider.BrowserContract.Searches;
-import android.util.Log;
import android.webkit.WebIconDatabase;
public class Browser {
diff --git a/core/java/android/provider/BrowserContract.java b/core/java/android/provider/BrowserContract.java
index 57dde6693001..5083b8b254ab 100644
--- a/core/java/android/provider/BrowserContract.java
+++ b/core/java/android/provider/BrowserContract.java
@@ -17,7 +17,7 @@
package android.provider;
import android.accounts.Account;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentProviderClient;
import android.content.ContentProviderOperation;
import android.content.ContentResolver;
diff --git a/core/java/android/provider/CalendarContract.java b/core/java/android/provider/CalendarContract.java
index 7285166cdd5f..9c6c92ace483 100644
--- a/core/java/android/provider/CalendarContract.java
+++ b/core/java/android/provider/CalendarContract.java
@@ -20,11 +20,11 @@ import android.annotation.NonNull;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.admin.DevicePolicyManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index 30db6382fcd6..a0e92b398c4e 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -17,7 +17,7 @@
package android.provider;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentValues;
diff --git a/core/java/android/provider/Column.java b/core/java/android/provider/Column.java
deleted file mode 100644
index 1364fb86cbd6..000000000000
--- a/core/java/android/provider/Column.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.provider;
-
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import android.content.ContentProvider;
-import android.content.ContentValues;
-import android.database.Cursor;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/**
- * Denotes that a field is a {@link ContentProvider} column. It can be used as a
- * key for {@link ContentValues} when inserting or updating data, or as a
- * projection when querying.
- *
- * @hide
- */
-@Documented
-@Retention(RUNTIME)
-@Target({FIELD})
-public @interface Column {
- /**
- * The {@link Cursor#getType(int)} of the data stored in this column.
- */
- int value();
-
- /**
- * This column is read-only and cannot be defined during insert or updates.
- */
- boolean readOnly() default false;
-}
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index c86c83cec377..e383a371eb41 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -23,8 +23,8 @@ import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.Activity;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentProviderClient;
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
deleted file mode 100644
index 63204d36f396..000000000000
--- a/core/java/android/provider/MediaStore.java
+++ /dev/null
@@ -1,3832 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.provider;
-
-import android.annotation.BytesLong;
-import android.annotation.CurrentTimeMillisLong;
-import android.annotation.CurrentTimeSecondsLong;
-import android.annotation.DurationMillisLong;
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.SuppressLint;
-import android.annotation.SystemApi;
-import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
-import android.app.Activity;
-import android.app.PendingIntent;
-import android.content.ClipData;
-import android.content.ContentProviderClient;
-import android.content.ContentResolver;
-import android.content.ContentUris;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.Intent;
-import android.content.UriPermission;
-import android.database.Cursor;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.ImageDecoder;
-import android.graphics.PostProcessor;
-import android.media.ExifInterface;
-import android.media.MediaFormat;
-import android.media.MediaMetadataRetriever;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.CancellationSignal;
-import android.os.Environment;
-import android.os.OperationCanceledException;
-import android.os.RemoteException;
-import android.os.storage.StorageManager;
-import android.os.storage.StorageVolume;
-import android.text.TextUtils;
-import android.text.format.DateUtils;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-import android.util.Log;
-import android.util.Size;
-
-import libcore.util.HexEncoding;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.text.Collator;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-import java.util.Objects;
-import java.util.Set;
-import java.util.regex.Pattern;
-
-/**
- * The contract between the media provider and applications. Contains
- * definitions for the supported URIs and columns.
- * <p>
- * The media provider provides an indexed collection of common media types, such
- * as {@link Audio}, {@link Video}, and {@link Images}, from any attached
- * storage devices. Each collection is organized based on the primary MIME type
- * of the underlying content; for example, {@code image/*} content is indexed
- * under {@link Images}. The {@link Files} collection provides a broad view
- * across all collections, and does not filter by MIME type.
- */
-public final class MediaStore {
- private final static String TAG = "MediaStore";
-
- /** The authority for the media provider */
- public static final String AUTHORITY = "media";
- /** A content:// style uri to the authority for the media provider */
- public static final @NonNull Uri AUTHORITY_URI =
- Uri.parse("content://" + AUTHORITY);
-
- /** @hide */
- public static final String AUTHORITY_LEGACY = "media_legacy";
- /** @hide */
- public static final @NonNull Uri AUTHORITY_LEGACY_URI =
- Uri.parse("content://" + AUTHORITY_LEGACY);
-
- /**
- * Synthetic volume name that provides a view of all content across the
- * "internal" storage of the device.
- * <p>
- * This synthetic volume provides a merged view of all media distributed
- * with the device, such as built-in ringtones and wallpapers.
- * <p>
- * Because this is a synthetic volume, you can't insert new content into
- * this volume.
- */
- public static final String VOLUME_INTERNAL = "internal";
-
- /**
- * Synthetic volume name that provides a view of all content across the
- * "external" storage of the device.
- * <p>
- * This synthetic volume provides a merged view of all media across all
- * currently attached external storage devices.
- * <p>
- * Because this is a synthetic volume, you can't insert new content into
- * this volume. Instead, you can insert content into a specific storage
- * volume obtained from {@link #getExternalVolumeNames(Context)}.
- */
- public static final String VOLUME_EXTERNAL = "external";
-
- /**
- * Specific volume name that represents the primary external storage device
- * at {@link Environment#getExternalStorageDirectory()}.
- * <p>
- * This volume may not always be available, such as when the user has
- * ejected the device. You can find a list of all specific volume names
- * using {@link #getExternalVolumeNames(Context)}.
- */
- public static final String VOLUME_EXTERNAL_PRIMARY = "external_primary";
-
- /** {@hide} */
- public static final String WAIT_FOR_IDLE_CALL = "wait_for_idle";
- /** {@hide} */
- public static final String SCAN_FILE_CALL = "scan_file";
- /** {@hide} */
- public static final String SCAN_VOLUME_CALL = "scan_volume";
- /** {@hide} */
- public static final String CREATE_WRITE_REQUEST_CALL = "create_write_request";
- /** {@hide} */
- public static final String CREATE_TRASH_REQUEST_CALL = "create_trash_request";
- /** {@hide} */
- public static final String CREATE_FAVORITE_REQUEST_CALL = "create_favorite_request";
- /** {@hide} */
- public static final String CREATE_DELETE_REQUEST_CALL = "create_delete_request";
-
-
- /** {@hide} */
- public static final String GET_VERSION_CALL = "get_version";
-
- /** {@hide} */
- public static final String GET_DOCUMENT_URI_CALL = "get_document_uri";
- /** {@hide} */
- public static final String GET_MEDIA_URI_CALL = "get_media_uri";
-
- /** {@hide} */
- public static final String EXTRA_URI = "uri";
- /** {@hide} */
- public static final String EXTRA_URI_PERMISSIONS = "uriPermissions";
-
- /** {@hide} */
- public static final String EXTRA_CLIP_DATA = "clip_data";
- /** {@hide} */
- public static final String EXTRA_CONTENT_VALUES = "content_values";
- /** {@hide} */
- public static final String EXTRA_RESULT = "result";
-
- /**
- * This is for internal use by the media scanner only.
- * Name of the (optional) Uri parameter that determines whether to skip deleting
- * the file pointed to by the _data column, when deleting the database entry.
- * The only appropriate value for this parameter is "false", in which case the
- * delete will be skipped. Note especially that setting this to true, or omitting
- * the parameter altogether, will perform the default action, which is different
- * for different types of media.
- * @hide
- */
- public static final String PARAM_DELETE_DATA = "deletedata";
-
- /** {@hide} */
- @Deprecated
- public static final String PARAM_INCLUDE_PENDING = "includePending";
- /** {@hide} */
- @Deprecated
- public static final String PARAM_INCLUDE_TRASHED = "includeTrashed";
- /** {@hide} */
- public static final String PARAM_PROGRESS = "progress";
- /** {@hide} */
- public static final String PARAM_REQUIRE_ORIGINAL = "requireOriginal";
- /** {@hide} */
- public static final String PARAM_LIMIT = "limit";
-
- /**
- * Activity Action: Launch a music player.
- * The activity should be able to play, browse, or manipulate music files stored on the device.
- *
- * @deprecated Use {@link android.content.Intent#CATEGORY_APP_MUSIC} instead.
- */
- @Deprecated
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String INTENT_ACTION_MUSIC_PLAYER = "android.intent.action.MUSIC_PLAYER";
-
- /**
- * Activity Action: Perform a search for media.
- * Contains at least the {@link android.app.SearchManager#QUERY} extra.
- * May also contain any combination of the following extras:
- * EXTRA_MEDIA_ARTIST, EXTRA_MEDIA_ALBUM, EXTRA_MEDIA_TITLE, EXTRA_MEDIA_FOCUS
- *
- * @see android.provider.MediaStore#EXTRA_MEDIA_ARTIST
- * @see android.provider.MediaStore#EXTRA_MEDIA_ALBUM
- * @see android.provider.MediaStore#EXTRA_MEDIA_TITLE
- * @see android.provider.MediaStore#EXTRA_MEDIA_FOCUS
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String INTENT_ACTION_MEDIA_SEARCH = "android.intent.action.MEDIA_SEARCH";
-
- /**
- * An intent to perform a search for music media and automatically play content from the
- * result when possible. This can be fired, for example, by the result of a voice recognition
- * command to listen to music.
- * <p>This intent always includes the {@link android.provider.MediaStore#EXTRA_MEDIA_FOCUS}
- * and {@link android.app.SearchManager#QUERY} extras. The
- * {@link android.provider.MediaStore#EXTRA_MEDIA_FOCUS} extra determines the search mode, and
- * the value of the {@link android.app.SearchManager#QUERY} extra depends on the search mode.
- * For more information about the search modes for this intent, see
- * <a href="{@docRoot}guide/components/intents-common.html#PlaySearch">Play music based
- * on a search query</a> in <a href="{@docRoot}guide/components/intents-common.html">Common
- * Intents</a>.</p>
- *
- * <p>This intent makes the most sense for apps that can support large-scale search of music,
- * such as services connected to an online database of music which can be streamed and played
- * on the device.</p>
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH =
- "android.media.action.MEDIA_PLAY_FROM_SEARCH";
-
- /**
- * An intent to perform a search for readable media and automatically play content from the
- * result when possible. This can be fired, for example, by the result of a voice recognition
- * command to read a book or magazine.
- * <p>
- * Contains the {@link android.app.SearchManager#QUERY} extra, which is a string that can
- * contain any type of unstructured text search, like the name of a book or magazine, an author
- * a genre, a publisher, or any combination of these.
- * <p>
- * Because this intent includes an open-ended unstructured search string, it makes the most
- * sense for apps that can support large-scale search of text media, such as services connected
- * to an online database of books and/or magazines which can be read on the device.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String INTENT_ACTION_TEXT_OPEN_FROM_SEARCH =
- "android.media.action.TEXT_OPEN_FROM_SEARCH";
-
- /**
- * An intent to perform a search for video media and automatically play content from the
- * result when possible. This can be fired, for example, by the result of a voice recognition
- * command to play movies.
- * <p>
- * Contains the {@link android.app.SearchManager#QUERY} extra, which is a string that can
- * contain any type of unstructured video search, like the name of a movie, one or more actors,
- * a genre, or any combination of these.
- * <p>
- * Because this intent includes an open-ended unstructured search string, it makes the most
- * sense for apps that can support large-scale search of video, such as services connected to an
- * online database of videos which can be streamed and played on the device.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String INTENT_ACTION_VIDEO_PLAY_FROM_SEARCH =
- "android.media.action.VIDEO_PLAY_FROM_SEARCH";
-
- /**
- * The name of the Intent-extra used to define the artist
- */
- public static final String EXTRA_MEDIA_ARTIST = "android.intent.extra.artist";
- /**
- * The name of the Intent-extra used to define the album
- */
- public static final String EXTRA_MEDIA_ALBUM = "android.intent.extra.album";
- /**
- * The name of the Intent-extra used to define the song title
- */
- public static final String EXTRA_MEDIA_TITLE = "android.intent.extra.title";
- /**
- * The name of the Intent-extra used to define the genre.
- */
- public static final String EXTRA_MEDIA_GENRE = "android.intent.extra.genre";
- /**
- * The name of the Intent-extra used to define the playlist.
- */
- public static final String EXTRA_MEDIA_PLAYLIST = "android.intent.extra.playlist";
- /**
- * The name of the Intent-extra used to define the radio channel.
- */
- public static final String EXTRA_MEDIA_RADIO_CHANNEL = "android.intent.extra.radio_channel";
- /**
- * The name of the Intent-extra used to define the search focus. The search focus
- * indicates whether the search should be for things related to the artist, album
- * or song that is identified by the other extras.
- */
- public static final String EXTRA_MEDIA_FOCUS = "android.intent.extra.focus";
-
- /**
- * The name of the Intent-extra used to control the orientation of a ViewImage or a MovieView.
- * This is an int property that overrides the activity's requestedOrientation.
- * @see android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED
- */
- public static final String EXTRA_SCREEN_ORIENTATION = "android.intent.extra.screenOrientation";
-
- /**
- * The name of an Intent-extra used to control the UI of a ViewImage.
- * This is a boolean property that overrides the activity's default fullscreen state.
- */
- public static final String EXTRA_FULL_SCREEN = "android.intent.extra.fullScreen";
-
- /**
- * The name of an Intent-extra used to control the UI of a ViewImage.
- * This is a boolean property that specifies whether or not to show action icons.
- */
- public static final String EXTRA_SHOW_ACTION_ICONS = "android.intent.extra.showActionIcons";
-
- /**
- * The name of the Intent-extra used to control the onCompletion behavior of a MovieView.
- * This is a boolean property that specifies whether or not to finish the MovieView activity
- * when the movie completes playing. The default value is true, which means to automatically
- * exit the movie player activity when the movie completes playing.
- */
- public static final String EXTRA_FINISH_ON_COMPLETION = "android.intent.extra.finishOnCompletion";
-
- /**
- * The name of the Intent action used to launch a camera in still image mode.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String INTENT_ACTION_STILL_IMAGE_CAMERA = "android.media.action.STILL_IMAGE_CAMERA";
-
- /**
- * Name under which an activity handling {@link #INTENT_ACTION_STILL_IMAGE_CAMERA} or
- * {@link #INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE} publishes the service name for its prewarm
- * service.
- * <p>
- * This meta-data should reference the fully qualified class name of the prewarm service
- * extending {@code CameraPrewarmService}.
- * <p>
- * The prewarm service will get bound and receive a prewarm signal
- * {@code CameraPrewarmService#onPrewarm()} when a camera launch intent fire might be imminent.
- * An application implementing a prewarm service should do the absolute minimum amount of work
- * to initialize the camera in order to reduce startup time in likely case that shortly after a
- * camera launch intent would be sent.
- */
- public static final String META_DATA_STILL_IMAGE_CAMERA_PREWARM_SERVICE =
- "android.media.still_image_camera_preview_service";
-
- /**
- * The name of the Intent action used to launch a camera in still image mode
- * for use when the device is secured (e.g. with a pin, password, pattern,
- * or face unlock). Applications responding to this intent must not expose
- * any personal content like existing photos or videos on the device. The
- * applications should be careful not to share any photo or video with other
- * applications or internet. The activity should use {@link
- * Activity#setShowWhenLocked} to display
- * on top of the lock screen while secured. There is no activity stack when
- * this flag is used, so launching more than one activity is strongly
- * discouraged.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE =
- "android.media.action.STILL_IMAGE_CAMERA_SECURE";
-
- /**
- * The name of the Intent action used to launch a camera in video mode.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String INTENT_ACTION_VIDEO_CAMERA = "android.media.action.VIDEO_CAMERA";
-
- /**
- * Standard Intent action that can be sent to have the camera application
- * capture an image and return it.
- * <p>
- * The caller may pass an extra EXTRA_OUTPUT to control where this image will be written.
- * If the EXTRA_OUTPUT is not present, then a small sized image is returned as a Bitmap
- * object in the extra field. This is useful for applications that only need a small image.
- * If the EXTRA_OUTPUT is present, then the full-sized image will be written to the Uri
- * value of EXTRA_OUTPUT.
- * As of {@link android.os.Build.VERSION_CODES#LOLLIPOP}, this uri can also be supplied through
- * {@link android.content.Intent#setClipData(ClipData)}. If using this approach, you still must
- * supply the uri through the EXTRA_OUTPUT field for compatibility with old applications.
- * If you don't set a ClipData, it will be copied there for you when calling
- * {@link Context#startActivity(Intent)}.
- *
- * <p>Note: if you app targets {@link android.os.Build.VERSION_CODES#M M} and above
- * and declares as using the {@link android.Manifest.permission#CAMERA} permission which
- * is not granted, then attempting to use this action will result in a {@link
- * java.lang.SecurityException}.
- *
- * @see #EXTRA_OUTPUT
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public final static String ACTION_IMAGE_CAPTURE = "android.media.action.IMAGE_CAPTURE";
-
- /**
- * Intent action that can be sent to have the camera application capture an image and return
- * it when the device is secured (e.g. with a pin, password, pattern, or face unlock).
- * Applications responding to this intent must not expose any personal content like existing
- * photos or videos on the device. The applications should be careful not to share any photo
- * or video with other applications or Internet. The activity should use {@link
- * Activity#setShowWhenLocked} to display on top of the
- * lock screen while secured. There is no activity stack when this flag is used, so
- * launching more than one activity is strongly discouraged.
- * <p>
- * The caller may pass an extra EXTRA_OUTPUT to control where this image will be written.
- * If the EXTRA_OUTPUT is not present, then a small sized image is returned as a Bitmap
- * object in the extra field. This is useful for applications that only need a small image.
- * If the EXTRA_OUTPUT is present, then the full-sized image will be written to the Uri
- * value of EXTRA_OUTPUT.
- * As of {@link android.os.Build.VERSION_CODES#LOLLIPOP}, this uri can also be supplied through
- * {@link android.content.Intent#setClipData(ClipData)}. If using this approach, you still must
- * supply the uri through the EXTRA_OUTPUT field for compatibility with old applications.
- * If you don't set a ClipData, it will be copied there for you when calling
- * {@link Context#startActivity(Intent)}.
- *
- * @see #ACTION_IMAGE_CAPTURE
- * @see #EXTRA_OUTPUT
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_IMAGE_CAPTURE_SECURE =
- "android.media.action.IMAGE_CAPTURE_SECURE";
-
- /**
- * Standard Intent action that can be sent to have the camera application
- * capture a video and return it.
- * <p>
- * The caller may pass in an extra EXTRA_VIDEO_QUALITY to control the video quality.
- * <p>
- * The caller may pass in an extra EXTRA_OUTPUT to control
- * where the video is written. If EXTRA_OUTPUT is not present the video will be
- * written to the standard location for videos, and the Uri of that location will be
- * returned in the data field of the Uri.
- * As of {@link android.os.Build.VERSION_CODES#LOLLIPOP}, this uri can also be supplied through
- * {@link android.content.Intent#setClipData(ClipData)}. If using this approach, you still must
- * supply the uri through the EXTRA_OUTPUT field for compatibility with old applications.
- * If you don't set a ClipData, it will be copied there for you when calling
- * {@link Context#startActivity(Intent)}.
- *
- * <p>Note: if you app targets {@link android.os.Build.VERSION_CODES#M M} and above
- * and declares as using the {@link android.Manifest.permission#CAMERA} permission which
- * is not granted, then atempting to use this action will result in a {@link
- * java.lang.SecurityException}.
- *
- * @see #EXTRA_OUTPUT
- * @see #EXTRA_VIDEO_QUALITY
- * @see #EXTRA_SIZE_LIMIT
- * @see #EXTRA_DURATION_LIMIT
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public final static String ACTION_VIDEO_CAPTURE = "android.media.action.VIDEO_CAPTURE";
-
- /**
- * Standard action that can be sent to review the given media file.
- * <p>
- * The launched application is expected to provide a large-scale view of the
- * given media file, while allowing the user to quickly access other
- * recently captured media files.
- * <p>
- * Input: {@link Intent#getData} is URI of the primary media item to
- * initially display.
- *
- * @see #ACTION_REVIEW_SECURE
- * @see #EXTRA_BRIGHTNESS
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public final static String ACTION_REVIEW = "android.provider.action.REVIEW";
-
- /**
- * Standard action that can be sent to review the given media file when the
- * device is secured (e.g. with a pin, password, pattern, or face unlock).
- * The applications should be careful not to share any media with other
- * applications or Internet. The activity should use
- * {@link Activity#setShowWhenLocked} to display on top of the lock screen
- * while secured. There is no activity stack when this flag is used, so
- * launching more than one activity is strongly discouraged.
- * <p>
- * The launched application is expected to provide a large-scale view of the
- * given primary media file, while only allowing the user to quickly access
- * other media from an explicit secondary list.
- * <p>
- * Input: {@link Intent#getData} is URI of the primary media item to
- * initially display. {@link Intent#getClipData} is the limited list of
- * secondary media items that the user is allowed to review. If
- * {@link Intent#getClipData} is undefined, then no other media access
- * should be allowed.
- *
- * @see #EXTRA_BRIGHTNESS
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public final static String ACTION_REVIEW_SECURE = "android.provider.action.REVIEW_SECURE";
-
- /**
- * When defined, the launched application is requested to set the given
- * brightness value via
- * {@link android.view.WindowManager.LayoutParams#screenBrightness} to help
- * ensure a smooth transition when launching {@link #ACTION_REVIEW} or
- * {@link #ACTION_REVIEW_SECURE} intents.
- */
- public final static String EXTRA_BRIGHTNESS = "android.provider.extra.BRIGHTNESS";
-
- /**
- * The name of the Intent-extra used to control the quality of a recorded video. This is an
- * integer property. Currently value 0 means low quality, suitable for MMS messages, and
- * value 1 means high quality. In the future other quality levels may be added.
- */
- public final static String EXTRA_VIDEO_QUALITY = "android.intent.extra.videoQuality";
-
- /**
- * Specify the maximum allowed size.
- */
- public final static String EXTRA_SIZE_LIMIT = "android.intent.extra.sizeLimit";
-
- /**
- * Specify the maximum allowed recording duration in seconds.
- */
- public final static String EXTRA_DURATION_LIMIT = "android.intent.extra.durationLimit";
-
- /**
- * The name of the Intent-extra used to indicate a content resolver Uri to be used to
- * store the requested image or video.
- */
- public final static String EXTRA_OUTPUT = "output";
-
- /**
- * The string that is used when a media attribute is not known. For example,
- * if an audio file does not have any meta data, the artist and album columns
- * will be set to this value.
- */
- public static final String UNKNOWN_STRING = "<unknown>";
-
- /**
- * Specify a {@link Uri} that is "related" to the current operation being
- * performed.
- * <p>
- * This is typically used to allow an operation that may normally be
- * rejected, such as making a copy of a pre-existing image located under a
- * {@link MediaColumns#RELATIVE_PATH} where new images are not allowed.
- * <p>
- * It's strongly recommended that when making a copy of pre-existing content
- * that you define the "original document ID" GUID as defined by the <em>XMP
- * Media Management</em> standard.
- * <p>
- * This key can be placed in a {@link Bundle} of extras and passed to
- * {@link ContentResolver#insert}.
- */
- public static final String QUERY_ARG_RELATED_URI = "android:query-arg-related-uri";
-
- /**
- * Specify how {@link MediaColumns#IS_PENDING} items should be filtered when
- * performing a {@link MediaStore} operation.
- * <p>
- * This key can be placed in a {@link Bundle} of extras and passed to
- * {@link ContentResolver#query}, {@link ContentResolver#update}, or
- * {@link ContentResolver#delete}.
- * <p>
- * By default, pending items are filtered away from operations.
- */
- @Match
- public static final String QUERY_ARG_MATCH_PENDING = "android:query-arg-match-pending";
-
- /**
- * Specify how {@link MediaColumns#IS_TRASHED} items should be filtered when
- * performing a {@link MediaStore} operation.
- * <p>
- * This key can be placed in a {@link Bundle} of extras and passed to
- * {@link ContentResolver#query}, {@link ContentResolver#update}, or
- * {@link ContentResolver#delete}.
- * <p>
- * By default, trashed items are filtered away from operations.
- *
- * @see MediaColumns#IS_TRASHED
- * @see MediaStore#QUERY_ARG_MATCH_TRASHED
- * @see MediaStore#createTrashRequest
- */
- @Match
- public static final String QUERY_ARG_MATCH_TRASHED = "android:query-arg-match-trashed";
-
- /**
- * Specify how {@link MediaColumns#IS_FAVORITE} items should be filtered
- * when performing a {@link MediaStore} operation.
- * <p>
- * This key can be placed in a {@link Bundle} of extras and passed to
- * {@link ContentResolver#query}, {@link ContentResolver#update}, or
- * {@link ContentResolver#delete}.
- * <p>
- * By default, favorite items are <em>not</em> filtered away from
- * operations.
- *
- * @see MediaColumns#IS_FAVORITE
- * @see MediaStore#QUERY_ARG_MATCH_FAVORITE
- * @see MediaStore#createFavoriteRequest
- */
- @Match
- public static final String QUERY_ARG_MATCH_FAVORITE = "android:query-arg-match-favorite";
-
- /** @hide */
- @IntDef(flag = true, prefix = { "MATCH_" }, value = {
- MATCH_DEFAULT,
- MATCH_INCLUDE,
- MATCH_EXCLUDE,
- MATCH_ONLY,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface Match {}
-
- /**
- * Value indicating that the default matching behavior should be used, as
- * defined by the key documentation.
- */
- public static final int MATCH_DEFAULT = 0;
-
- /**
- * Value indicating that operations should include items matching the
- * criteria defined by this key.
- * <p>
- * Note that items <em>not</em> matching the criteria <em>may</em> also be
- * included depending on the default behavior documented by the key. If you
- * want to operate exclusively on matching items, use {@link #MATCH_ONLY}.
- */
- public static final int MATCH_INCLUDE = 1;
-
- /**
- * Value indicating that operations should exclude items matching the
- * criteria defined by this key.
- */
- public static final int MATCH_EXCLUDE = 2;
-
- /**
- * Value indicating that operations should only operate on items explicitly
- * matching the criteria defined by this key.
- */
- public static final int MATCH_ONLY = 3;
-
- /**
- * Update the given {@link Uri} to also include any pending media items from
- * calls such as
- * {@link ContentResolver#query(Uri, String[], Bundle, CancellationSignal)}.
- * By default no pending items are returned.
- *
- * @see MediaColumns#IS_PENDING
- * @see MediaStore#getIncludePending(Uri)
- * @deprecated consider migrating to {@link #QUERY_ARG_MATCH_PENDING} which
- * is more expressive.
- */
- @Deprecated
- public static @NonNull Uri setIncludePending(@NonNull Uri uri) {
- return setIncludePending(uri.buildUpon()).build();
- }
-
- /** @hide */
- @Deprecated
- public static @NonNull Uri.Builder setIncludePending(@NonNull Uri.Builder uriBuilder) {
- return uriBuilder.appendQueryParameter(PARAM_INCLUDE_PENDING, "1");
- }
-
- /**
- * Return if any pending media items should be included in calls such as
- * {@link ContentResolver#query(Uri, String[], Bundle, CancellationSignal)}.
- *
- * @see MediaColumns#IS_PENDING
- * @see MediaStore#setIncludePending(Uri)
- * @deprecated consider migrating to {@link #QUERY_ARG_MATCH_PENDING} which
- * is more expressive.
- * @removed
- */
- @Deprecated
- public static boolean getIncludePending(@NonNull Uri uri) {
- return parseBoolean(uri.getQueryParameter(MediaStore.PARAM_INCLUDE_PENDING));
- }
-
- /**
- * Update the given {@link Uri} to also include any trashed media items from
- * calls such as
- * {@link ContentResolver#query(Uri, String[], Bundle, CancellationSignal)}.
- * By default no trashed items are returned.
- *
- * @see MediaColumns#IS_TRASHED
- * @see MediaStore#setIncludeTrashed(Uri)
- * @see MediaStore#trash(Context, Uri)
- * @see MediaStore#untrash(Context, Uri)
- * @deprecated consider migrating to {@link #QUERY_ARG_MATCH_TRASHED} which
- * is more expressive.
- * @removed
- */
- @Deprecated
- public static @NonNull Uri setIncludeTrashed(@NonNull Uri uri) {
- return uri.buildUpon().appendQueryParameter(PARAM_INCLUDE_TRASHED, "1").build();
- }
-
- /**
- * Update the given {@link Uri} to indicate that the caller requires the
- * original file contents when calling
- * {@link ContentResolver#openFileDescriptor(Uri, String)}.
- * <p>
- * This can be useful when the caller wants to ensure they're backing up the
- * exact bytes of the underlying media, without any Exif redaction being
- * performed.
- * <p>
- * If the original file contents cannot be provided, a
- * {@link UnsupportedOperationException} will be thrown when the returned
- * {@link Uri} is used, such as when the caller doesn't hold
- * {@link android.Manifest.permission#ACCESS_MEDIA_LOCATION}.
- *
- * @see MediaStore#getRequireOriginal(Uri)
- */
- public static @NonNull Uri setRequireOriginal(@NonNull Uri uri) {
- return uri.buildUpon().appendQueryParameter(PARAM_REQUIRE_ORIGINAL, "1").build();
- }
-
- /**
- * Return if the caller requires the original file contents when calling
- * {@link ContentResolver#openFileDescriptor(Uri, String)}.
- *
- * @see MediaStore#setRequireOriginal(Uri)
- */
- public static boolean getRequireOriginal(@NonNull Uri uri) {
- return parseBoolean(uri.getQueryParameter(MediaStore.PARAM_REQUIRE_ORIGINAL));
- }
-
- /**
- * Mark the given item as being "trashed", meaning it should be deleted at
- * some point in the future. This is a more gentle operation than simply
- * calling {@link ContentResolver#delete(Uri, String, String[])}, which
- * would take effect immediately.
- * <p>
- * This method preserves trashed items for at least 48 hours before erasing
- * them, giving the user a chance to untrash the item.
- *
- * @see MediaColumns#IS_TRASHED
- * @see MediaStore#setIncludeTrashed(Uri)
- * @see MediaStore#trash(Context, Uri)
- * @see MediaStore#untrash(Context, Uri)
- * @removed
- */
- @Deprecated
- public static void trash(@NonNull Context context, @NonNull Uri uri) {
- trash(context, uri, 48 * DateUtils.HOUR_IN_MILLIS);
- }
-
- /**
- * Mark the given item as being "trashed", meaning it should be deleted at
- * some point in the future. This is a more gentle operation than simply
- * calling {@link ContentResolver#delete(Uri, String, String[])}, which
- * would take effect immediately.
- * <p>
- * This method preserves trashed items for at least the given timeout before
- * erasing them, giving the user a chance to untrash the item.
- *
- * @see MediaColumns#IS_TRASHED
- * @see MediaStore#setIncludeTrashed(Uri)
- * @see MediaStore#trash(Context, Uri)
- * @see MediaStore#untrash(Context, Uri)
- * @removed
- */
- @Deprecated
- public static void trash(@NonNull Context context, @NonNull Uri uri,
- @DurationMillisLong long timeoutMillis) {
- if (timeoutMillis < 0) {
- throw new IllegalArgumentException();
- }
-
- final ContentValues values = new ContentValues();
- values.put(MediaColumns.IS_TRASHED, 1);
- values.put(MediaColumns.DATE_EXPIRES,
- (System.currentTimeMillis() + timeoutMillis) / 1000);
- context.getContentResolver().update(uri, values, null, null);
- }
-
- /**
- * Mark the given item as being "untrashed", meaning it should no longer be
- * deleted as previously requested through {@link #trash(Context, Uri)}.
- *
- * @see MediaColumns#IS_TRASHED
- * @see MediaStore#setIncludeTrashed(Uri)
- * @see MediaStore#trash(Context, Uri)
- * @see MediaStore#untrash(Context, Uri)
- * @removed
- */
- @Deprecated
- public static void untrash(@NonNull Context context, @NonNull Uri uri) {
- final ContentValues values = new ContentValues();
- values.put(MediaColumns.IS_TRASHED, 0);
- values.putNull(MediaColumns.DATE_EXPIRES);
- context.getContentResolver().update(uri, values, null, null);
- }
-
- /**
- * Rewrite the given {@link Uri} to point at
- * {@link MediaStore#AUTHORITY_LEGACY}.
- *
- * @hide
- */
- public static @NonNull Uri rewriteToLegacy(@NonNull Uri uri) {
- return uri.buildUpon().authority(MediaStore.AUTHORITY_LEGACY).build();
- }
-
- private static @NonNull PendingIntent createRequest(@NonNull ContentResolver resolver,
- @NonNull String method, @NonNull Collection<Uri> uris, @Nullable ContentValues values) {
- Objects.requireNonNull(resolver);
- Objects.requireNonNull(uris);
-
- final Iterator<Uri> it = uris.iterator();
- final ClipData clipData = ClipData.newRawUri(null, it.next());
- while (it.hasNext()) {
- clipData.addItem(new ClipData.Item(it.next()));
- }
-
- final Bundle extras = new Bundle();
- extras.putParcelable(EXTRA_CLIP_DATA, clipData);
- extras.putParcelable(EXTRA_CONTENT_VALUES, values);
- return resolver.call(AUTHORITY, method, null, extras).getParcelable(EXTRA_RESULT);
- }
-
- /**
- * Create a {@link PendingIntent} that will prompt the user to grant your
- * app write access for the requested media items.
- * <p>
- * This call only generates the request for a prompt; to display the prompt,
- * call {@link Activity#startIntentSenderForResult} with
- * {@link PendingIntent#getIntentSender()}. You can then determine if the
- * user granted your request by testing for {@link Activity#RESULT_OK} in
- * {@link Activity#onActivityResult}.
- * <p>
- * Permissions granted through this mechanism are tied to the lifecycle of
- * the {@link Activity} that requests them. If you need to retain
- * longer-term access for background actions, you can place items into a
- * {@link ClipData} or {@link Intent} which can then be passed to
- * {@link Context#startService} or
- * {@link android.app.job.JobInfo.Builder#setClipData}. Be sure to include
- * any relevant access modes you want to retain, such as
- * {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION}.
- * <p>
- * The displayed prompt will reflect all the media items you're requesting,
- * including those for which you already hold write access. If you want to
- * determine if you already hold write access before requesting access, use
- * {@code ContentResolver#checkUriPermission(Uri, int, int)} with
- * {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION}.
- * <p>
- * For security and performance reasons this method does not support
- * {@link Intent#FLAG_GRANT_PERSISTABLE_URI_PERMISSION} or
- * {@link Intent#FLAG_GRANT_PREFIX_URI_PERMISSION}.
- *
- * @param resolver Used to connect with {@link MediaStore#AUTHORITY}.
- * Typically this value is {@link Context#getContentResolver()},
- * but if you need more explicit lifecycle controls, you can
- * obtain a {@link ContentProviderClient} and wrap it using
- * {@link ContentResolver#wrap(ContentProviderClient)}.
- * @param uris The set of media items to include in this request. Each item
- * must be hosted by {@link MediaStore#AUTHORITY} and must
- * reference a specific media item by {@link BaseColumns#_ID}.
- */
- public static @NonNull PendingIntent createWriteRequest(@NonNull ContentResolver resolver,
- @NonNull Collection<Uri> uris) {
- return createRequest(resolver, CREATE_WRITE_REQUEST_CALL, uris, null);
- }
-
- /**
- * Create a {@link PendingIntent} that will prompt the user to trash the
- * requested media items. When the user approves this request,
- * {@link MediaColumns#IS_TRASHED} is set on these items.
- * <p>
- * This call only generates the request for a prompt; to display the prompt,
- * call {@link Activity#startIntentSenderForResult} with
- * {@link PendingIntent#getIntentSender()}. You can then determine if the
- * user granted your request by testing for {@link Activity#RESULT_OK} in
- * {@link Activity#onActivityResult}.
- * <p>
- * The displayed prompt will reflect all the media items you're requesting,
- * including those for which you already hold write access. If you want to
- * determine if you already hold write access before requesting access, use
- * {@code ContentResolver#checkUriPermission(Uri, int, int)} with
- * {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION}.
- *
- * @param resolver Used to connect with {@link MediaStore#AUTHORITY}.
- * Typically this value is {@link Context#getContentResolver()},
- * but if you need more explicit lifecycle controls, you can
- * obtain a {@link ContentProviderClient} and wrap it using
- * {@link ContentResolver#wrap(ContentProviderClient)}.
- * @param uris The set of media items to include in this request. Each item
- * must be hosted by {@link MediaStore#AUTHORITY} and must
- * reference a specific media item by {@link BaseColumns#_ID}.
- * @param value The {@link MediaColumns#IS_TRASHED} value to apply.
- * @see MediaColumns#IS_TRASHED
- * @see MediaStore#QUERY_ARG_MATCH_TRASHED
- */
- public static @NonNull PendingIntent createTrashRequest(@NonNull ContentResolver resolver,
- @NonNull Collection<Uri> uris, boolean value) {
- final ContentValues values = new ContentValues();
- if (value) {
- values.put(MediaColumns.IS_TRASHED, 1);
- values.put(MediaColumns.DATE_EXPIRES,
- (System.currentTimeMillis() + DateUtils.WEEK_IN_MILLIS) / 1000);
- } else {
- values.put(MediaColumns.IS_TRASHED, 0);
- values.putNull(MediaColumns.DATE_EXPIRES);
- }
- return createRequest(resolver, CREATE_TRASH_REQUEST_CALL, uris, values);
- }
-
- /**
- * Create a {@link PendingIntent} that will prompt the user to favorite the
- * requested media items. When the user approves this request,
- * {@link MediaColumns#IS_FAVORITE} is set on these items.
- * <p>
- * This call only generates the request for a prompt; to display the prompt,
- * call {@link Activity#startIntentSenderForResult} with
- * {@link PendingIntent#getIntentSender()}. You can then determine if the
- * user granted your request by testing for {@link Activity#RESULT_OK} in
- * {@link Activity#onActivityResult}.
- * <p>
- * The displayed prompt will reflect all the media items you're requesting,
- * including those for which you already hold write access. If you want to
- * determine if you already hold write access before requesting access, use
- * {@code ContentResolver#checkUriPermission(Uri, int, int)} with
- * {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION}.
- *
- * @param resolver Used to connect with {@link MediaStore#AUTHORITY}.
- * Typically this value is {@link Context#getContentResolver()},
- * but if you need more explicit lifecycle controls, you can
- * obtain a {@link ContentProviderClient} and wrap it using
- * {@link ContentResolver#wrap(ContentProviderClient)}.
- * @param uris The set of media items to include in this request. Each item
- * must be hosted by {@link MediaStore#AUTHORITY} and must
- * reference a specific media item by {@link BaseColumns#_ID}.
- * @param value The {@link MediaColumns#IS_FAVORITE} value to apply.
- * @see MediaColumns#IS_FAVORITE
- * @see MediaStore#QUERY_ARG_MATCH_FAVORITE
- */
- public static @NonNull PendingIntent createFavoriteRequest(@NonNull ContentResolver resolver,
- @NonNull Collection<Uri> uris, boolean value) {
- final ContentValues values = new ContentValues();
- if (value) {
- values.put(MediaColumns.IS_FAVORITE, 1);
- } else {
- values.put(MediaColumns.IS_FAVORITE, 0);
- }
- return createRequest(resolver, CREATE_FAVORITE_REQUEST_CALL, uris, values);
- }
-
- /**
- * Create a {@link PendingIntent} that will prompt the user to permanently
- * delete the requested media items. When the user approves this request,
- * {@link ContentResolver#delete} will be called on these items.
- * <p>
- * This call only generates the request for a prompt; to display the prompt,
- * call {@link Activity#startIntentSenderForResult} with
- * {@link PendingIntent#getIntentSender()}. You can then determine if the
- * user granted your request by testing for {@link Activity#RESULT_OK} in
- * {@link Activity#onActivityResult}.
- * <p>
- * The displayed prompt will reflect all the media items you're requesting,
- * including those for which you already hold write access. If you want to
- * determine if you already hold write access before requesting access, use
- * {@code ContentResolver#checkUriPermission(Uri, int, int)} with
- * {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION}.
- *
- * @param resolver Used to connect with {@link MediaStore#AUTHORITY}.
- * Typically this value is {@link Context#getContentResolver()},
- * but if you need more explicit lifecycle controls, you can
- * obtain a {@link ContentProviderClient} and wrap it using
- * {@link ContentResolver#wrap(ContentProviderClient)}.
- * @param uris The set of media items to include in this request. Each item
- * must be hosted by {@link MediaStore#AUTHORITY} and must
- * reference a specific media item by {@link BaseColumns#_ID}.
- */
- public static @NonNull PendingIntent createDeleteRequest(@NonNull ContentResolver resolver,
- @NonNull Collection<Uri> uris) {
- return createRequest(resolver, CREATE_DELETE_REQUEST_CALL, uris, null);
- }
-
- /**
- * Common media metadata columns.
- */
- public interface MediaColumns extends BaseColumns {
- /**
- * Absolute filesystem path to the media item on disk.
- * <p>
- * Note that apps may not have filesystem permissions to directly access
- * this path. Instead of trying to open this path directly, apps should
- * use {@link ContentResolver#openFileDescriptor(Uri, String)} to gain
- * access.
- *
- * @deprecated Apps may not have filesystem permissions to directly
- * access this path. Instead of trying to open this path
- * directly, apps should use
- * {@link ContentResolver#openFileDescriptor(Uri, String)}
- * to gain access.
- */
- @Deprecated
- @Column(Cursor.FIELD_TYPE_STRING)
- public static final String DATA = "_data";
-
- /**
- * Indexed value of {@link File#length()} extracted from this media
- * item.
- */
- @BytesLong
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String SIZE = "_size";
-
- /**
- * The display name of the media item.
- * <p>
- * For example, an item stored at
- * {@code /storage/0000-0000/DCIM/Vacation/IMG1024.JPG} would have a
- * display name of {@code IMG1024.JPG}.
- */
- @Column(Cursor.FIELD_TYPE_STRING)
- public static final String DISPLAY_NAME = "_display_name";
-
- /**
- * The time the media item was first added.
- */
- @CurrentTimeSecondsLong
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String DATE_ADDED = "date_added";
-
- /**
- * Indexed value of {@link File#lastModified()} extracted from this
- * media item.
- */
- @CurrentTimeSecondsLong
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String DATE_MODIFIED = "date_modified";
-
- /**
- * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_DATE} or
- * {@link ExifInterface#TAG_DATETIME_ORIGINAL} extracted from this media
- * item.
- * <p>
- * Note that images must define both
- * {@link ExifInterface#TAG_DATETIME_ORIGINAL} and
- * {@code ExifInterface#TAG_OFFSET_TIME_ORIGINAL} to reliably determine
- * this value in relation to the epoch.
- */
- @CurrentTimeMillisLong
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String DATE_TAKEN = "datetaken";
-
- /**
- * The MIME type of the media item.
- * <p>
- * This is typically defined based on the file extension of the media
- * item. However, it may be the value of the {@code format} attribute
- * defined by the <em>Dublin Core Media Initiative</em> standard,
- * extracted from any XMP metadata contained within this media item.
- * <p class="note">
- * Note: the {@code format} attribute may be ignored if the top-level
- * MIME type disagrees with the file extension. For example, it's
- * reasonable for an {@code image/jpeg} file to declare a {@code format}
- * of {@code image/vnd.google.panorama360+jpg}, but declaring a
- * {@code format} of {@code audio/ogg} would be ignored.
- * <p>
- * This is a read-only column that is automatically computed.
- */
- @Column(Cursor.FIELD_TYPE_STRING)
- public static final String MIME_TYPE = "mime_type";
-
- /**
- * Non-zero if the media file is drm-protected
- * @hide
- */
- @UnsupportedAppUsage
- @Deprecated
- @Column(Cursor.FIELD_TYPE_INTEGER)
- public static final String IS_DRM = "is_drm";
-
- /**
- * Flag indicating if a media item is pending, and still being inserted
- * by its owner. While this flag is set, only the owner of the item can
- * open the underlying file; requests from other apps will be rejected.
- * <p>
- * Pending items are retained either until they are published by setting
- * the field to {@code 0}, or until they expire as defined by
- * {@link #DATE_EXPIRES}.
- *
- * @see MediaStore#QUERY_ARG_MATCH_PENDING
- */
- @Column(Cursor.FIELD_TYPE_INTEGER)
- public static final String IS_PENDING = "is_pending";
-
- /**
- * Flag indicating if a media item is trashed.
- * <p>
- * Trashed items are retained until they expire as defined by
- * {@link #DATE_EXPIRES}.
- *
- * @see MediaColumns#IS_TRASHED
- * @see MediaStore#QUERY_ARG_MATCH_TRASHED
- * @see MediaStore#createTrashRequest
- */
- @Column(Cursor.FIELD_TYPE_INTEGER)
- public static final String IS_TRASHED = "is_trashed";
-
- /**
- * The time the media item should be considered expired. Typically only
- * meaningful in the context of {@link #IS_PENDING} or
- * {@link #IS_TRASHED}.
- */
- @CurrentTimeSecondsLong
- @Column(Cursor.FIELD_TYPE_INTEGER)
- public static final String DATE_EXPIRES = "date_expires";
-
- /**
- * Indexed value of
- * {@link MediaMetadataRetriever#METADATA_KEY_VIDEO_WIDTH},
- * {@link MediaMetadataRetriever#METADATA_KEY_IMAGE_WIDTH} or
- * {@link ExifInterface#TAG_IMAGE_WIDTH} extracted from this media item.
- */
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String WIDTH = "width";
-
- /**
- * Indexed value of
- * {@link MediaMetadataRetriever#METADATA_KEY_VIDEO_HEIGHT},
- * {@link MediaMetadataRetriever#METADATA_KEY_IMAGE_HEIGHT} or
- * {@link ExifInterface#TAG_IMAGE_LENGTH} extracted from this media
- * item.
- */
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String HEIGHT = "height";
-
- /**
- * Calculated value that combines {@link #WIDTH} and {@link #HEIGHT}
- * into a user-presentable string.
- */
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
- public static final String RESOLUTION = "resolution";
-
- /**
- * Package name that contributed this media. The value may be
- * {@code NULL} if ownership cannot be reliably determined.
- */
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
- public static final String OWNER_PACKAGE_NAME = "owner_package_name";
-
- /**
- * Volume name of the specific storage device where this media item is
- * persisted. The value is typically one of the volume names returned
- * from {@link MediaStore#getExternalVolumeNames(Context)}.
- * <p>
- * This is a read-only column that is automatically computed.
- */
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
- public static final String VOLUME_NAME = "volume_name";
-
- /**
- * Relative path of this media item within the storage device where it
- * is persisted. For example, an item stored at
- * {@code /storage/0000-0000/DCIM/Vacation/IMG1024.JPG} would have a
- * path of {@code DCIM/Vacation/}.
- * <p>
- * This value should only be used for organizational purposes, and you
- * should not attempt to construct or access a raw filesystem path using
- * this value. If you need to open a media item, use an API like
- * {@link ContentResolver#openFileDescriptor(Uri, String)}.
- * <p>
- * When this value is set to {@code NULL} during an
- * {@link ContentResolver#insert} operation, the newly created item will
- * be placed in a relevant default location based on the type of media
- * being inserted. For example, a {@code image/jpeg} item will be placed
- * under {@link Environment#DIRECTORY_PICTURES}.
- * <p>
- * You can modify this column during an {@link ContentResolver#update}
- * call, which will move the underlying file on disk.
- * <p>
- * In both cases above, content must be placed under a top-level
- * directory that is relevant to the media type. For example, attempting
- * to place a {@code audio/mpeg} file under
- * {@link Environment#DIRECTORY_PICTURES} will be rejected.
- */
- @Column(Cursor.FIELD_TYPE_STRING)
- public static final String RELATIVE_PATH = "relative_path";
-
- /**
- * The primary bucket ID of this media item. This can be useful to
- * present the user a first-level clustering of related media items.
- * This is a read-only column that is automatically computed.
- */
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String BUCKET_ID = "bucket_id";
-
- /**
- * The primary bucket display name of this media item. This can be
- * useful to present the user a first-level clustering of related
- * media items. This is a read-only column that is automatically
- * computed.
- */
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
- public static final String BUCKET_DISPLAY_NAME = "bucket_display_name";
-
- /**
- * The group ID of this media item. This can be useful to present
- * the user a grouping of related media items, such a burst of
- * images, or a {@code JPG} and {@code DNG} version of the same
- * image.
- * <p>
- * This is a read-only column that is automatically computed based
- * on the first portion of the filename. For example,
- * {@code IMG1024.BURST001.JPG} and {@code IMG1024.BURST002.JPG}
- * will have the same {@link #GROUP_ID} because the first portion of
- * their filenames is identical.
- *
- * @removed
- */
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- @Deprecated
- public static final String GROUP_ID = "group_id";
-
- /**
- * The "document ID" GUID as defined by the <em>XMP Media
- * Management</em> standard, extracted from any XMP metadata contained
- * within this media item. The value is {@code null} when no metadata
- * was found.
- * <p>
- * Each "document ID" is created once for each new resource. Different
- * renditions of that resource are expected to have different IDs.
- */
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
- public static final String DOCUMENT_ID = "document_id";
-
- /**
- * The "instance ID" GUID as defined by the <em>XMP Media
- * Management</em> standard, extracted from any XMP metadata contained
- * within this media item. The value is {@code null} when no metadata
- * was found.
- * <p>
- * This "instance ID" changes with each save operation of a specific
- * "document ID".
- */
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
- public static final String INSTANCE_ID = "instance_id";
-
- /**
- * The "original document ID" GUID as defined by the <em>XMP Media
- * Management</em> standard, extracted from any XMP metadata contained
- * within this media item.
- * <p>
- * This "original document ID" links a resource to its original source.
- * For example, when you save a PSD document as a JPEG, then convert the
- * JPEG to GIF format, the "original document ID" of both the JPEG and
- * GIF files is the "document ID" of the original PSD file.
- */
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
- public static final String ORIGINAL_DOCUMENT_ID = "original_document_id";
-
- /**
- * Indexed value of
- * {@link MediaMetadataRetriever#METADATA_KEY_VIDEO_ROTATION},
- * {@link MediaMetadataRetriever#METADATA_KEY_IMAGE_ROTATION}, or
- * {@link ExifInterface#TAG_ORIENTATION} extracted from this media item.
- * <p>
- * For consistency the indexed value is expressed in degrees, such as 0,
- * 90, 180, or 270.
- */
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String ORIENTATION = "orientation";
-
- /**
- * Flag indicating if the media item has been marked as being a
- * "favorite" by the user.
- *
- * @see MediaColumns#IS_FAVORITE
- * @see MediaStore#QUERY_ARG_MATCH_FAVORITE
- * @see MediaStore#createFavoriteRequest
- */
- @Column(Cursor.FIELD_TYPE_INTEGER)
- public static final String IS_FAVORITE = "is_favorite";
-
- // =======================================
- // ==== MediaMetadataRetriever values ====
- // =======================================
-
- /**
- * Indexed value of
- * {@link MediaMetadataRetriever#METADATA_KEY_CD_TRACK_NUMBER} extracted
- * from this media item.
- */
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
- public static final String CD_TRACK_NUMBER = "cd_track_number";
-
- /**
- * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_ALBUM}
- * extracted from this media item.
- */
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
- public static final String ALBUM = "album";
-
- /**
- * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_ARTIST}
- * or {@link ExifInterface#TAG_ARTIST} extracted from this media item.
- */
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
- public static final String ARTIST = "artist";
-
- /**
- * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_AUTHOR}
- * extracted from this media item.
- */
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
- public static final String AUTHOR = "author";
-
- /**
- * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_COMPOSER}
- * extracted from this media item.
- */
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
- public static final String COMPOSER = "composer";
-
- // METADATA_KEY_DATE is DATE_TAKEN
-
- /**
- * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_GENRE}
- * extracted from this media item.
- */
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
- public static final String GENRE = "genre";
-
- /**
- * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_TITLE}
- * extracted from this media item.
- */
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
- public static final String TITLE = "title";
-
- /**
- * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_YEAR}
- * extracted from this media item.
- */
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String YEAR = "year";
-
- /**
- * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_DURATION}
- * extracted from this media item.
- */
- @DurationMillisLong
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String DURATION = "duration";
-
- /**
- * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_NUM_TRACKS}
- * extracted from this media item.
- */
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String NUM_TRACKS = "num_tracks";
-
- /**
- * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_WRITER}
- * extracted from this media item.
- */
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
- public static final String WRITER = "writer";
-
- // METADATA_KEY_MIMETYPE is MIME_TYPE
-
- /**
- * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_ALBUMARTIST}
- * extracted from this media item.
- */
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
- public static final String ALBUM_ARTIST = "album_artist";
-
- /**
- * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_DISC_NUMBER}
- * extracted from this media item.
- */
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
- public static final String DISC_NUMBER = "disc_number";
-
- /**
- * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_COMPILATION}
- * extracted from this media item.
- */
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
- public static final String COMPILATION = "compilation";
-
- // HAS_AUDIO is ignored
- // HAS_VIDEO is ignored
- // VIDEO_WIDTH is WIDTH
- // VIDEO_HEIGHT is HEIGHT
-
- /**
- * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_BITRATE}
- * extracted from this media item.
- */
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String BITRATE = "bitrate";
-
- // TIMED_TEXT_LANGUAGES is ignored
- // IS_DRM is ignored
- // LOCATION is LATITUDE and LONGITUDE
- // VIDEO_ROTATION is ORIENTATION
-
- /**
- * Indexed value of
- * {@link MediaMetadataRetriever#METADATA_KEY_CAPTURE_FRAMERATE}
- * extracted from this media item.
- */
- @Column(value = Cursor.FIELD_TYPE_FLOAT, readOnly = true)
- public static final String CAPTURE_FRAMERATE = "capture_framerate";
-
- // HAS_IMAGE is ignored
- // IMAGE_COUNT is ignored
- // IMAGE_PRIMARY is ignored
- // IMAGE_WIDTH is WIDTH
- // IMAGE_HEIGHT is HEIGHT
- // IMAGE_ROTATION is ORIENTATION
- // VIDEO_FRAME_COUNT is ignored
- // EXIF_OFFSET is ignored
- // EXIF_LENGTH is ignored
- // COLOR_STANDARD is ignored
- // COLOR_TRANSFER is ignored
- // COLOR_RANGE is ignored
- // SAMPLERATE is ignored
- // BITS_PER_SAMPLE is ignored
- }
-
- /**
- * Media provider table containing an index of all files in the media storage,
- * including non-media files. This should be used by applications that work with
- * non-media file types (text, HTML, PDF, etc) as well as applications that need to
- * work with multiple media file types in a single query.
- */
- public static final class Files {
- /** @hide */
- public static final String TABLE = "files";
-
- /** @hide */
- public static final Uri EXTERNAL_CONTENT_URI = getContentUri(VOLUME_EXTERNAL);
-
- /**
- * Get the content:// style URI for the files table on the
- * given volume.
- *
- * @param volumeName the name of the volume to get the URI for
- * @return the URI to the files table on the given volume
- */
- public static Uri getContentUri(String volumeName) {
- return AUTHORITY_URI.buildUpon().appendPath(volumeName).appendPath("file").build();
- }
-
- /**
- * Get the content:// style URI for a single row in the files table on the
- * given volume.
- *
- * @param volumeName the name of the volume to get the URI for
- * @param rowId the file to get the URI for
- * @return the URI to the files table on the given volume
- */
- public static final Uri getContentUri(String volumeName,
- long rowId) {
- return ContentUris.withAppendedId(getContentUri(volumeName), rowId);
- }
-
- /** {@hide} */
- @UnsupportedAppUsage
- public static Uri getMtpObjectsUri(@NonNull String volumeName) {
- return MediaStore.Files.getContentUri(volumeName);
- }
-
- /** {@hide} */
- @UnsupportedAppUsage
- public static final Uri getMtpObjectsUri(@NonNull String volumeName, long fileId) {
- return MediaStore.Files.getContentUri(volumeName, fileId);
- }
-
- /** {@hide} */
- @UnsupportedAppUsage
- public static final Uri getMtpReferencesUri(@NonNull String volumeName, long fileId) {
- return MediaStore.Files.getContentUri(volumeName, fileId);
- }
-
- /**
- * Used to trigger special logic for directories.
- * @hide
- */
- public static final Uri getDirectoryUri(String volumeName) {
- return AUTHORITY_URI.buildUpon().appendPath(volumeName).appendPath("dir").build();
- }
-
- /** @hide */
- public static final Uri getContentUriForPath(String path) {
- return getContentUri(getVolumeName(new File(path)));
- }
-
- /**
- * File metadata columns.
- */
- public interface FileColumns extends MediaColumns {
- /**
- * The MTP storage ID of the file
- * @hide
- */
- @UnsupportedAppUsage
- @Deprecated
- // @Column(Cursor.FIELD_TYPE_INTEGER)
- public static final String STORAGE_ID = "storage_id";
-
- /**
- * The MTP format code of the file
- * @hide
- */
- @UnsupportedAppUsage
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String FORMAT = "format";
-
- /**
- * The index of the parent directory of the file
- */
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String PARENT = "parent";
-
- /**
- * The MIME type of the media item.
- * <p>
- * This is typically defined based on the file extension of the media
- * item. However, it may be the value of the {@code format} attribute
- * defined by the <em>Dublin Core Media Initiative</em> standard,
- * extracted from any XMP metadata contained within this media item.
- * <p class="note">
- * Note: the {@code format} attribute may be ignored if the top-level
- * MIME type disagrees with the file extension. For example, it's
- * reasonable for an {@code image/jpeg} file to declare a {@code format}
- * of {@code image/vnd.google.panorama360+jpg}, but declaring a
- * {@code format} of {@code audio/ogg} would be ignored.
- * <p>
- * This is a read-only column that is automatically computed.
- */
- @Column(Cursor.FIELD_TYPE_STRING)
- public static final String MIME_TYPE = "mime_type";
-
- /** @removed promoted to parent interface */
- public static final String TITLE = "title";
-
- /**
- * The media type (audio, video, image or playlist)
- * of the file, or 0 for not a media file
- */
- @Column(Cursor.FIELD_TYPE_INTEGER)
- public static final String MEDIA_TYPE = "media_type";
-
- /**
- * Constant for the {@link #MEDIA_TYPE} column indicating that file
- * is not an audio, image, video, playlist, or subtitles file.
- */
- public static final int MEDIA_TYPE_NONE = 0;
-
- /**
- * Constant for the {@link #MEDIA_TYPE} column indicating that file
- * is an image file.
- */
- public static final int MEDIA_TYPE_IMAGE = 1;
-
- /**
- * Constant for the {@link #MEDIA_TYPE} column indicating that file
- * is an audio file.
- */
- public static final int MEDIA_TYPE_AUDIO = 2;
-
- /**
- * Constant for the {@link #MEDIA_TYPE} column indicating that file
- * is a video file.
- */
- public static final int MEDIA_TYPE_VIDEO = 3;
-
- /**
- * Constant for the {@link #MEDIA_TYPE} column indicating that file
- * is a playlist file.
- */
- public static final int MEDIA_TYPE_PLAYLIST = 4;
-
- /**
- * Constant for the {@link #MEDIA_TYPE} column indicating that file
- * is a subtitles or lyrics file.
- */
- public static final int MEDIA_TYPE_SUBTITLE = 5;
-
- /**
- * Column indicating if the file is part of Downloads collection.
- * @hide
- */
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String IS_DOWNLOAD = "is_download";
- }
- }
-
- /** @hide */
- public static class ThumbnailConstants {
- public static final int MINI_KIND = 1;
- public static final int FULL_SCREEN_KIND = 2;
- public static final int MICRO_KIND = 3;
-
- public static final Size MINI_SIZE = new Size(512, 384);
- public static final Size FULL_SCREEN_SIZE = new Size(1024, 786);
- public static final Size MICRO_SIZE = new Size(96, 96);
-
- public static @NonNull Size getKindSize(int kind) {
- if (kind == ThumbnailConstants.MICRO_KIND) {
- return ThumbnailConstants.MICRO_SIZE;
- } else if (kind == ThumbnailConstants.FULL_SCREEN_KIND) {
- return ThumbnailConstants.FULL_SCREEN_SIZE;
- } else if (kind == ThumbnailConstants.MINI_KIND) {
- return ThumbnailConstants.MINI_SIZE;
- } else {
- throw new IllegalArgumentException("Unsupported kind: " + kind);
- }
- }
- }
-
- /**
- * Download metadata columns.
- */
- public interface DownloadColumns extends MediaColumns {
- /**
- * Uri indicating where the item has been downloaded from.
- */
- @Column(Cursor.FIELD_TYPE_STRING)
- String DOWNLOAD_URI = "download_uri";
-
- /**
- * Uri indicating HTTP referer of {@link #DOWNLOAD_URI}.
- */
- @Column(Cursor.FIELD_TYPE_STRING)
- String REFERER_URI = "referer_uri";
-
- /**
- * The description of the download.
- *
- * @removed
- */
- @Deprecated
- @Column(Cursor.FIELD_TYPE_STRING)
- String DESCRIPTION = "description";
- }
-
- /**
- * Collection of downloaded items.
- */
- public static final class Downloads implements DownloadColumns {
- private Downloads() {}
-
- /**
- * The content:// style URI for the internal storage.
- */
- @NonNull
- public static final Uri INTERNAL_CONTENT_URI =
- getContentUri("internal");
-
- /**
- * The content:// style URI for the "primary" external storage
- * volume.
- */
- @NonNull
- public static final Uri EXTERNAL_CONTENT_URI =
- getContentUri("external");
-
- /**
- * The MIME type for this table.
- */
- public static final String CONTENT_TYPE = "vnd.android.cursor.dir/download";
-
- /**
- * Regex that matches paths that needs to be considered part of downloads collection.
- * @hide
- */
- public static final Pattern PATTERN_DOWNLOADS_FILE = Pattern.compile(
- "(?i)^/storage/[^/]+/(?:[0-9]+/)?(?:Android/sandbox/[^/]+/)?Download/.+");
- private static final Pattern PATTERN_DOWNLOADS_DIRECTORY = Pattern.compile(
- "(?i)^/storage/[^/]+/(?:[0-9]+/)?(?:Android/sandbox/[^/]+/)?Download/?");
-
- /**
- * Get the content:// style URI for the downloads table on the
- * given volume.
- *
- * @param volumeName the name of the volume to get the URI for
- * @return the URI to the image media table on the given volume
- */
- public static @NonNull Uri getContentUri(@NonNull String volumeName) {
- return AUTHORITY_URI.buildUpon().appendPath(volumeName)
- .appendPath("downloads").build();
- }
-
- /**
- * Get the content:// style URI for a single row in the downloads table
- * on the given volume.
- *
- * @param volumeName the name of the volume to get the URI for
- * @param id the download to get the URI for
- * @return the URI to the downloads table on the given volume
- */
- public static @NonNull Uri getContentUri(@NonNull String volumeName, long id) {
- return ContentUris.withAppendedId(getContentUri(volumeName), id);
- }
-
- /** @hide */
- public static @NonNull Uri getContentUriForPath(@NonNull String path) {
- return getContentUri(getVolumeName(new File(path)));
- }
-
- /** @hide */
- public static boolean isDownload(@NonNull String path) {
- return PATTERN_DOWNLOADS_FILE.matcher(path).matches();
- }
-
- /** @hide */
- public static boolean isDownloadDir(@NonNull String path) {
- return PATTERN_DOWNLOADS_DIRECTORY.matcher(path).matches();
- }
- }
-
- /**
- * @deprecated since this method doesn't have a {@link Context}, we can't
- * find the actual {@link StorageVolume} for the given path, so
- * only a vague guess is returned. Callers should use
- * {@link StorageManager#getStorageVolume(File)} instead.
- * @hide
- */
- @Deprecated
- public static @NonNull String getVolumeName(@NonNull File path) {
- // Ideally we'd find the relevant StorageVolume, but we don't have a
- // Context to obtain it from, so the best we can do is assume
- if (path.getAbsolutePath()
- .startsWith(Environment.getStorageDirectory().getAbsolutePath())) {
- return MediaStore.VOLUME_EXTERNAL;
- } else {
- return MediaStore.VOLUME_INTERNAL;
- }
- }
-
- /**
- * This class is used internally by Images.Thumbnails and Video.Thumbnails, it's not intended
- * to be accessed elsewhere.
- */
- @Deprecated
- private static class InternalThumbnails implements BaseColumns {
- /**
- * Currently outstanding thumbnail requests that can be cancelled.
- */
- // @GuardedBy("sPending")
- private static ArrayMap<Uri, CancellationSignal> sPending = new ArrayMap<>();
-
- /**
- * Make a blocking request to obtain the given thumbnail, generating it
- * if needed.
- *
- * @see #cancelThumbnail(ContentResolver, Uri)
- */
- @Deprecated
- static @Nullable Bitmap getThumbnail(@NonNull ContentResolver cr, @NonNull Uri uri,
- int kind, @Nullable BitmapFactory.Options opts) {
- final Size size = ThumbnailConstants.getKindSize(kind);
-
- CancellationSignal signal = null;
- synchronized (sPending) {
- signal = sPending.get(uri);
- if (signal == null) {
- signal = new CancellationSignal();
- sPending.put(uri, signal);
- }
- }
-
- try {
- return cr.loadThumbnail(uri, size, signal);
- } catch (IOException e) {
- Log.w(TAG, "Failed to obtain thumbnail for " + uri, e);
- return null;
- } finally {
- synchronized (sPending) {
- sPending.remove(uri);
- }
- }
- }
-
- /**
- * This method cancels the thumbnail request so clients waiting for
- * {@link #getThumbnail} will be interrupted and return immediately.
- * Only the original process which made the request can cancel their own
- * requests.
- */
- @Deprecated
- static void cancelThumbnail(@NonNull ContentResolver cr, @NonNull Uri uri) {
- synchronized (sPending) {
- final CancellationSignal signal = sPending.get(uri);
- if (signal != null) {
- signal.cancel();
- }
- }
- }
- }
-
- /**
- * Collection of all media with MIME type of {@code image/*}.
- */
- public static final class Images {
- /**
- * Image metadata columns.
- */
- public interface ImageColumns extends MediaColumns {
- /**
- * The picasa id of the image
- *
- * @deprecated this value was only relevant for images hosted on
- * Picasa, which are no longer supported.
- */
- @Deprecated
- @Column(Cursor.FIELD_TYPE_STRING)
- public static final String PICASA_ID = "picasa_id";
-
- /**
- * Whether the video should be published as public or private
- */
- @Column(Cursor.FIELD_TYPE_INTEGER)
- public static final String IS_PRIVATE = "isprivate";
-
- /**
- * The latitude where the image was captured.
- *
- * @deprecated location details are no longer indexed for privacy
- * reasons, and this value is now always {@code null}.
- * You can still manually obtain location metadata using
- * {@link ExifInterface#getLatLong(float[])}.
- */
- @Deprecated
- @Column(value = Cursor.FIELD_TYPE_FLOAT, readOnly = true)
- public static final String LATITUDE = "latitude";
-
- /**
- * The longitude where the image was captured.
- *
- * @deprecated location details are no longer indexed for privacy
- * reasons, and this value is now always {@code null}.
- * You can still manually obtain location metadata using
- * {@link ExifInterface#getLatLong(float[])}.
- */
- @Deprecated
- @Column(value = Cursor.FIELD_TYPE_FLOAT, readOnly = true)
- public static final String LONGITUDE = "longitude";
-
- /** @removed promoted to parent interface */
- public static final String DATE_TAKEN = "datetaken";
- /** @removed promoted to parent interface */
- public static final String ORIENTATION = "orientation";
-
- /**
- * The mini thumb id.
- *
- * @deprecated all thumbnails should be obtained via
- * {@link MediaStore.Images.Thumbnails#getThumbnail}, as this
- * value is no longer supported.
- */
- @Deprecated
- @Column(Cursor.FIELD_TYPE_INTEGER)
- public static final String MINI_THUMB_MAGIC = "mini_thumb_magic";
-
- /** @removed promoted to parent interface */
- public static final String BUCKET_ID = "bucket_id";
- /** @removed promoted to parent interface */
- public static final String BUCKET_DISPLAY_NAME = "bucket_display_name";
- /** @removed promoted to parent interface */
- public static final String GROUP_ID = "group_id";
-
- /**
- * Indexed value of {@link ExifInterface#TAG_IMAGE_DESCRIPTION}
- * extracted from this media item.
- */
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
- public static final String DESCRIPTION = "description";
-
- /**
- * Indexed value of {@link ExifInterface#TAG_EXPOSURE_TIME}
- * extracted from this media item.
- */
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
- public static final String EXPOSURE_TIME = "exposure_time";
-
- /**
- * Indexed value of {@link ExifInterface#TAG_F_NUMBER}
- * extracted from this media item.
- */
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
- public static final String F_NUMBER = "f_number";
-
- /**
- * Indexed value of {@link ExifInterface#TAG_ISO_SPEED_RATINGS}
- * extracted from this media item.
- */
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String ISO = "iso";
- }
-
- public static final class Media implements ImageColumns {
- /**
- * @deprecated all queries should be performed through
- * {@link ContentResolver} directly, which offers modern
- * features like {@link CancellationSignal}.
- */
- @Deprecated
- public static final Cursor query(ContentResolver cr, Uri uri, String[] projection) {
- return cr.query(uri, projection, null, null, DEFAULT_SORT_ORDER);
- }
-
- /**
- * @deprecated all queries should be performed through
- * {@link ContentResolver} directly, which offers modern
- * features like {@link CancellationSignal}.
- */
- @Deprecated
- public static final Cursor query(ContentResolver cr, Uri uri, String[] projection,
- String where, String orderBy) {
- return cr.query(uri, projection, where,
- null, orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
- }
-
- /**
- * @deprecated all queries should be performed through
- * {@link ContentResolver} directly, which offers modern
- * features like {@link CancellationSignal}.
- */
- @Deprecated
- public static final Cursor query(ContentResolver cr, Uri uri, String[] projection,
- String selection, String [] selectionArgs, String orderBy) {
- return cr.query(uri, projection, selection,
- selectionArgs, orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
- }
-
- /**
- * Retrieves an image for the given url as a {@link Bitmap}.
- *
- * @param cr The content resolver to use
- * @param url The url of the image
- * @deprecated loading of images should be performed through
- * {@link ImageDecoder#createSource(ContentResolver, Uri)},
- * which offers modern features like
- * {@link PostProcessor}.
- */
- @Deprecated
- public static final Bitmap getBitmap(ContentResolver cr, Uri url)
- throws FileNotFoundException, IOException {
- InputStream input = cr.openInputStream(url);
- Bitmap bitmap = BitmapFactory.decodeStream(input);
- input.close();
- return bitmap;
- }
-
- /**
- * Insert an image and create a thumbnail for it.
- *
- * @param cr The content resolver to use
- * @param imagePath The path to the image to insert
- * @param name The name of the image
- * @param description The description of the image
- * @return The URL to the newly created image
- * @deprecated inserting of images should be performed using
- * {@link MediaColumns#IS_PENDING}, which offers richer
- * control over lifecycle.
- */
- @Deprecated
- public static final String insertImage(ContentResolver cr, String imagePath,
- String name, String description) throws FileNotFoundException {
- final Bitmap source;
- try {
- source = ImageDecoder
- .decodeBitmap(ImageDecoder.createSource(new File(imagePath)));
- } catch (IOException e) {
- throw new FileNotFoundException(e.getMessage());
- }
- return insertImage(cr, source, name, description);
- }
-
- /**
- * Insert an image and create a thumbnail for it.
- *
- * @param cr The content resolver to use
- * @param source The stream to use for the image
- * @param title The name of the image
- * @param description The description of the image
- * @return The URL to the newly created image, or <code>null</code> if the image failed to be stored
- * for any reason.
- * @deprecated inserting of images should be performed using
- * {@link MediaColumns#IS_PENDING}, which offers richer
- * control over lifecycle.
- */
- @Deprecated
- public static final String insertImage(ContentResolver cr, Bitmap source, String title,
- String description) {
- if (TextUtils.isEmpty(title)) title = "Image";
-
- final long now = System.currentTimeMillis();
- final ContentValues values = new ContentValues();
- values.put(MediaColumns.DISPLAY_NAME, title);
- values.put(MediaColumns.MIME_TYPE, "image/jpeg");
- values.put(MediaColumns.DATE_ADDED, now / 1000);
- values.put(MediaColumns.DATE_MODIFIED, now / 1000);
- values.put(MediaColumns.DATE_EXPIRES, (now + DateUtils.DAY_IN_MILLIS) / 1000);
- values.put(MediaColumns.IS_PENDING, 1);
-
- final Uri uri = cr.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
- try {
- try (OutputStream out = cr.openOutputStream(uri)) {
- source.compress(Bitmap.CompressFormat.JPEG, 90, out);
- }
-
- // Everything went well above, publish it!
- values.clear();
- values.put(MediaColumns.IS_PENDING, 0);
- values.putNull(MediaColumns.DATE_EXPIRES);
- cr.update(uri, values, null, null);
- return uri.toString();
- } catch (Exception e) {
- Log.w(TAG, "Failed to insert image", e);
- cr.delete(uri, null, null);
- return null;
- }
- }
-
- /**
- * Get the content:// style URI for the image media table on the
- * given volume.
- *
- * @param volumeName the name of the volume to get the URI for
- * @return the URI to the image media table on the given volume
- */
- public static Uri getContentUri(String volumeName) {
- return AUTHORITY_URI.buildUpon().appendPath(volumeName).appendPath("images")
- .appendPath("media").build();
- }
-
- /**
- * Get the content:// style URI for a single row in the images table
- * on the given volume.
- *
- * @param volumeName the name of the volume to get the URI for
- * @param id the image to get the URI for
- * @return the URI to the images table on the given volume
- */
- public static @NonNull Uri getContentUri(@NonNull String volumeName, long id) {
- return ContentUris.withAppendedId(getContentUri(volumeName), id);
- }
-
- /**
- * The content:// style URI for the internal storage.
- */
- public static final Uri INTERNAL_CONTENT_URI =
- getContentUri("internal");
-
- /**
- * The content:// style URI for the "primary" external storage
- * volume.
- */
- public static final Uri EXTERNAL_CONTENT_URI =
- getContentUri("external");
-
- /**
- * The MIME type of of this directory of
- * images. Note that each entry in this directory will have a standard
- * image MIME type as appropriate -- for example, image/jpeg.
- */
- public static final String CONTENT_TYPE = "vnd.android.cursor.dir/image";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = ImageColumns.BUCKET_DISPLAY_NAME;
- }
-
- /**
- * This class provides utility methods to obtain thumbnails for various
- * {@link Images} items.
- *
- * @deprecated Callers should migrate to using
- * {@link ContentResolver#loadThumbnail}, since it offers
- * richer control over requested thumbnail sizes and
- * cancellation behavior.
- */
- @Deprecated
- public static class Thumbnails implements BaseColumns {
- /**
- * @deprecated all queries should be performed through
- * {@link ContentResolver} directly, which offers modern
- * features like {@link CancellationSignal}.
- */
- @Deprecated
- public static final Cursor query(ContentResolver cr, Uri uri, String[] projection) {
- return cr.query(uri, projection, null, null, DEFAULT_SORT_ORDER);
- }
-
- /**
- * @deprecated all queries should be performed through
- * {@link ContentResolver} directly, which offers modern
- * features like {@link CancellationSignal}.
- */
- @Deprecated
- public static final Cursor queryMiniThumbnails(ContentResolver cr, Uri uri, int kind,
- String[] projection) {
- return cr.query(uri, projection, "kind = " + kind, null, DEFAULT_SORT_ORDER);
- }
-
- /**
- * @deprecated all queries should be performed through
- * {@link ContentResolver} directly, which offers modern
- * features like {@link CancellationSignal}.
- */
- @Deprecated
- public static final Cursor queryMiniThumbnail(ContentResolver cr, long origId, int kind,
- String[] projection) {
- return cr.query(EXTERNAL_CONTENT_URI, projection,
- IMAGE_ID + " = " + origId + " AND " + KIND + " = " +
- kind, null, null);
- }
-
- /**
- * Cancel any outstanding {@link #getThumbnail} requests, causing
- * them to return by throwing a {@link OperationCanceledException}.
- * <p>
- * This method has no effect on
- * {@link ContentResolver#loadThumbnail} calls, since they provide
- * their own {@link CancellationSignal}.
- *
- * @deprecated Callers should migrate to using
- * {@link ContentResolver#loadThumbnail}, since it
- * offers richer control over requested thumbnail sizes
- * and cancellation behavior.
- */
- @Deprecated
- public static void cancelThumbnailRequest(ContentResolver cr, long origId) {
- final Uri uri = ContentUris.withAppendedId(
- Images.Media.EXTERNAL_CONTENT_URI, origId);
- InternalThumbnails.cancelThumbnail(cr, uri);
- }
-
- /**
- * Return thumbnail representing a specific image item. If a
- * thumbnail doesn't exist, this method will block until it's
- * generated. Callers are responsible for their own in-memory
- * caching of returned values.
- *
- * As of {@link android.os.Build.VERSION_CODES#Q}, this output
- * of the thumbnail has correct rotation, don't need to rotate
- * it again.
- *
- * @param imageId the image item to obtain a thumbnail for.
- * @param kind optimal thumbnail size desired.
- * @return decoded thumbnail, or {@code null} if problem was
- * encountered.
- * @deprecated Callers should migrate to using
- * {@link ContentResolver#loadThumbnail}, since it
- * offers richer control over requested thumbnail sizes
- * and cancellation behavior.
- */
- @Deprecated
- public static Bitmap getThumbnail(ContentResolver cr, long imageId, int kind,
- BitmapFactory.Options options) {
- final Uri uri = ContentUris.withAppendedId(
- Images.Media.EXTERNAL_CONTENT_URI, imageId);
- return InternalThumbnails.getThumbnail(cr, uri, kind, options);
- }
-
- /**
- * Cancel any outstanding {@link #getThumbnail} requests, causing
- * them to return by throwing a {@link OperationCanceledException}.
- * <p>
- * This method has no effect on
- * {@link ContentResolver#loadThumbnail} calls, since they provide
- * their own {@link CancellationSignal}.
- *
- * @deprecated Callers should migrate to using
- * {@link ContentResolver#loadThumbnail}, since it
- * offers richer control over requested thumbnail sizes
- * and cancellation behavior.
- */
- @Deprecated
- public static void cancelThumbnailRequest(ContentResolver cr, long origId,
- long groupId) {
- cancelThumbnailRequest(cr, origId);
- }
-
- /**
- * Return thumbnail representing a specific image item. If a
- * thumbnail doesn't exist, this method will block until it's
- * generated. Callers are responsible for their own in-memory
- * caching of returned values.
- *
- * As of {@link android.os.Build.VERSION_CODES#Q}, this output
- * of the thumbnail has correct rotation, don't need to rotate
- * it again.
- *
- * @param imageId the image item to obtain a thumbnail for.
- * @param kind optimal thumbnail size desired.
- * @return decoded thumbnail, or {@code null} if problem was
- * encountered.
- * @deprecated Callers should migrate to using
- * {@link ContentResolver#loadThumbnail}, since it
- * offers richer control over requested thumbnail sizes
- * and cancellation behavior.
- */
- @Deprecated
- public static Bitmap getThumbnail(ContentResolver cr, long imageId, long groupId,
- int kind, BitmapFactory.Options options) {
- return getThumbnail(cr, imageId, kind, options);
- }
-
- /**
- * Get the content:// style URI for the image media table on the
- * given volume.
- *
- * @param volumeName the name of the volume to get the URI for
- * @return the URI to the image media table on the given volume
- */
- public static Uri getContentUri(String volumeName) {
- return AUTHORITY_URI.buildUpon().appendPath(volumeName).appendPath("images")
- .appendPath("thumbnails").build();
- }
-
- /**
- * The content:// style URI for the internal storage.
- */
- public static final Uri INTERNAL_CONTENT_URI =
- getContentUri("internal");
-
- /**
- * The content:// style URI for the "primary" external storage
- * volume.
- */
- public static final Uri EXTERNAL_CONTENT_URI =
- getContentUri("external");
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = "image_id ASC";
-
- /**
- * Path to the thumbnail file on disk.
- * <p>
- * Note that apps may not have filesystem permissions to directly
- * access this path. Instead of trying to open this path directly,
- * apps should use
- * {@link ContentResolver#openFileDescriptor(Uri, String)} to gain
- * access.
- *
- * As of {@link android.os.Build.VERSION_CODES#Q}, this thumbnail
- * has correct rotation, don't need to rotate it again.
- *
- * @deprecated Apps may not have filesystem permissions to directly
- * access this path. Instead of trying to open this path
- * directly, apps should use
- * {@link ContentResolver#loadThumbnail}
- * to gain access.
- */
- @Deprecated
- @Column(Cursor.FIELD_TYPE_STRING)
- public static final String DATA = "_data";
-
- /**
- * The original image for the thumbnal
- */
- @Column(Cursor.FIELD_TYPE_INTEGER)
- public static final String IMAGE_ID = "image_id";
-
- /**
- * The kind of the thumbnail
- */
- @Column(Cursor.FIELD_TYPE_INTEGER)
- public static final String KIND = "kind";
-
- public static final int MINI_KIND = ThumbnailConstants.MINI_KIND;
- public static final int FULL_SCREEN_KIND = ThumbnailConstants.FULL_SCREEN_KIND;
- public static final int MICRO_KIND = ThumbnailConstants.MICRO_KIND;
-
- /**
- * Return the typical {@link Size} (in pixels) used internally when
- * the given thumbnail kind is requested.
- */
- public static @NonNull Size getKindSize(int kind) {
- return ThumbnailConstants.getKindSize(kind);
- }
-
- /**
- * The blob raw data of thumbnail
- *
- * @deprecated this column never existed internally, and could never
- * have returned valid data.
- */
- @Deprecated
- @Column(Cursor.FIELD_TYPE_BLOB)
- public static final String THUMB_DATA = "thumb_data";
-
- /**
- * The width of the thumbnal
- */
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String WIDTH = "width";
-
- /**
- * The height of the thumbnail
- */
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String HEIGHT = "height";
- }
- }
-
- /**
- * Collection of all media with MIME type of {@code audio/*}.
- */
- public static final class Audio {
- /**
- * Audio metadata columns.
- */
- public interface AudioColumns extends MediaColumns {
-
- /**
- * A non human readable key calculated from the TITLE, used for
- * searching, sorting and grouping
- *
- * @see Audio#keyFor(String)
- * @deprecated These keys are generated using
- * {@link java.util.Locale#ROOT}, which means they don't
- * reflect locale-specific sorting preferences. To apply
- * locale-specific sorting preferences, use
- * {@link ContentResolver#QUERY_ARG_SQL_SORT_ORDER} with
- * {@code COLLATE LOCALIZED}, or
- * {@link ContentResolver#QUERY_ARG_SORT_LOCALE}.
- */
- @Deprecated
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
- public static final String TITLE_KEY = "title_key";
-
- /** @removed promoted to parent interface */
- public static final String DURATION = "duration";
-
- /**
- * The position within the audio item at which playback should be
- * resumed.
- */
- @DurationMillisLong
- @Column(Cursor.FIELD_TYPE_INTEGER)
- public static final String BOOKMARK = "bookmark";
-
- /**
- * The id of the artist who created the audio file, if any
- */
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String ARTIST_ID = "artist_id";
-
- /** @removed promoted to parent interface */
- public static final String ARTIST = "artist";
-
- /**
- * The artist credited for the album that contains the audio file
- * @hide
- */
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
- public static final String ALBUM_ARTIST = "album_artist";
-
- /**
- * A non human readable key calculated from the ARTIST, used for
- * searching, sorting and grouping
- *
- * @see Audio#keyFor(String)
- * @deprecated These keys are generated using
- * {@link java.util.Locale#ROOT}, which means they don't
- * reflect locale-specific sorting preferences. To apply
- * locale-specific sorting preferences, use
- * {@link ContentResolver#QUERY_ARG_SQL_SORT_ORDER} with
- * {@code COLLATE LOCALIZED}, or
- * {@link ContentResolver#QUERY_ARG_SORT_LOCALE}.
- */
- @Deprecated
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
- public static final String ARTIST_KEY = "artist_key";
-
- /** @removed promoted to parent interface */
- public static final String COMPOSER = "composer";
-
- /**
- * The id of the album the audio file is from, if any
- */
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String ALBUM_ID = "album_id";
-
- /** @removed promoted to parent interface */
- public static final String ALBUM = "album";
-
- /**
- * A non human readable key calculated from the ALBUM, used for
- * searching, sorting and grouping
- *
- * @see Audio#keyFor(String)
- * @deprecated These keys are generated using
- * {@link java.util.Locale#ROOT}, which means they don't
- * reflect locale-specific sorting preferences. To apply
- * locale-specific sorting preferences, use
- * {@link ContentResolver#QUERY_ARG_SQL_SORT_ORDER} with
- * {@code COLLATE LOCALIZED}, or
- * {@link ContentResolver#QUERY_ARG_SORT_LOCALE}.
- */
- @Deprecated
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
- public static final String ALBUM_KEY = "album_key";
-
- /**
- * The track number of this song on the album, if any.
- * This number encodes both the track number and the
- * disc number. For multi-disc sets, this number will
- * be 1xxx for tracks on the first disc, 2xxx for tracks
- * on the second disc, etc.
- */
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String TRACK = "track";
-
- /**
- * The year the audio file was recorded, if any
- */
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String YEAR = "year";
-
- /**
- * Non-zero if the audio file is music
- */
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String IS_MUSIC = "is_music";
-
- /**
- * Non-zero if the audio file is a podcast
- */
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String IS_PODCAST = "is_podcast";
-
- /**
- * Non-zero if the audio file may be a ringtone
- */
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String IS_RINGTONE = "is_ringtone";
-
- /**
- * Non-zero if the audio file may be an alarm
- */
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String IS_ALARM = "is_alarm";
-
- /**
- * Non-zero if the audio file may be a notification sound
- */
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String IS_NOTIFICATION = "is_notification";
-
- /**
- * Non-zero if the audio file is an audiobook
- */
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String IS_AUDIOBOOK = "is_audiobook";
-
- /**
- * The id of the genre the audio file is from, if any
- */
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String GENRE_ID = "genre_id";
-
- /**
- * The genre of the audio file, if any.
- */
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
- public static final String GENRE = "genre";
-
- /**
- * A non human readable key calculated from the GENRE, used for
- * searching, sorting and grouping
- *
- * @see Audio#keyFor(String)
- * @deprecated These keys are generated using
- * {@link java.util.Locale#ROOT}, which means they don't
- * reflect locale-specific sorting preferences. To apply
- * locale-specific sorting preferences, use
- * {@link ContentResolver#QUERY_ARG_SQL_SORT_ORDER} with
- * {@code COLLATE LOCALIZED}, or
- * {@link ContentResolver#QUERY_ARG_SORT_LOCALE}.
- */
- @Deprecated
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
- public static final String GENRE_KEY = "genre_key";
-
- /**
- * The resource URI of a localized title, if any.
- * <p>
- * Conforms to this pattern:
- * <ul>
- * <li>Scheme: {@link ContentResolver#SCHEME_ANDROID_RESOURCE}
- * <li>Authority: Package Name of ringtone title provider
- * <li>First Path Segment: Type of resource (must be "string")
- * <li>Second Path Segment: Resource ID of title
- * </ul>
- */
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
- public static final String TITLE_RESOURCE_URI = "title_resource_uri";
- }
-
- private static final Pattern PATTERN_TRIM_BEFORE = Pattern.compile(
- "(?i)(^(the|an|a) |,\\s*(the|an|a)$|[^\\w\\s]|^\\s+|\\s+$)");
- private static final Pattern PATTERN_TRIM_AFTER = Pattern.compile(
- "(^(00)+|(00)+$)");
-
- /**
- * Converts a user-visible string into a "key" that can be used for
- * grouping, sorting, and searching.
- *
- * @return Opaque token that should not be parsed or displayed to users.
- * @deprecated These keys are generated using
- * {@link java.util.Locale#ROOT}, which means they don't
- * reflect locale-specific sorting preferences. To apply
- * locale-specific sorting preferences, use
- * {@link ContentResolver#QUERY_ARG_SQL_SORT_ORDER} with
- * {@code COLLATE LOCALIZED}, or
- * {@link ContentResolver#QUERY_ARG_SORT_LOCALE}.
- */
- @Deprecated
- public static @Nullable String keyFor(@Nullable String name) {
- if (TextUtils.isEmpty(name)) return null;
-
- if (UNKNOWN_STRING.equals(name)) {
- return "01";
- }
-
- final boolean sortFirst = name.startsWith("\001");
-
- name = PATTERN_TRIM_BEFORE.matcher(name).replaceAll("");
- if (TextUtils.isEmpty(name)) return null;
-
- final Collator c = Collator.getInstance(Locale.ROOT);
- c.setStrength(Collator.PRIMARY);
- name = HexEncoding.encodeToString(c.getCollationKey(name).toByteArray(), false);
-
- name = PATTERN_TRIM_AFTER.matcher(name).replaceAll("");
- if (sortFirst) {
- name = "01" + name;
- }
- return name;
- }
-
- public static final class Media implements AudioColumns {
- /**
- * Get the content:// style URI for the audio media table on the
- * given volume.
- *
- * @param volumeName the name of the volume to get the URI for
- * @return the URI to the audio media table on the given volume
- */
- public static Uri getContentUri(String volumeName) {
- return AUTHORITY_URI.buildUpon().appendPath(volumeName).appendPath("audio")
- .appendPath("media").build();
- }
-
- /**
- * Get the content:// style URI for a single row in the audio table
- * on the given volume.
- *
- * @param volumeName the name of the volume to get the URI for
- * @param id the audio to get the URI for
- * @return the URI to the audio table on the given volume
- */
- public static @NonNull Uri getContentUri(@NonNull String volumeName, long id) {
- return ContentUris.withAppendedId(getContentUri(volumeName), id);
- }
-
- /**
- * Get the content:// style URI for the given audio media file.
- *
- * @deprecated Apps may not have filesystem permissions to directly
- * access this path.
- */
- @Deprecated
- public static @Nullable Uri getContentUriForPath(@NonNull String path) {
- return getContentUri(getVolumeName(new File(path)));
- }
-
- /**
- * The content:// style URI for the internal storage.
- */
- public static final Uri INTERNAL_CONTENT_URI =
- getContentUri("internal");
-
- /**
- * The content:// style URI for the "primary" external storage
- * volume.
- */
- public static final Uri EXTERNAL_CONTENT_URI =
- getContentUri("external");
-
- /**
- * The MIME type for this table.
- */
- public static final String CONTENT_TYPE = "vnd.android.cursor.dir/audio";
-
- /**
- * The MIME type for an audio track.
- */
- public static final String ENTRY_CONTENT_TYPE = "vnd.android.cursor.item/audio";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = TITLE_KEY;
-
- /**
- * Activity Action: Start SoundRecorder application.
- * <p>Input: nothing.
- * <p>Output: An uri to the recorded sound stored in the Media Library
- * if the recording was successful.
- * May also contain the extra EXTRA_MAX_BYTES.
- * @see #EXTRA_MAX_BYTES
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String RECORD_SOUND_ACTION =
- "android.provider.MediaStore.RECORD_SOUND";
-
- /**
- * The name of the Intent-extra used to define a maximum file size for
- * a recording made by the SoundRecorder application.
- *
- * @see #RECORD_SOUND_ACTION
- */
- public static final String EXTRA_MAX_BYTES =
- "android.provider.MediaStore.extra.MAX_BYTES";
- }
-
- /**
- * Audio genre metadata columns.
- */
- public interface GenresColumns {
- /**
- * The name of the genre
- */
- @Column(Cursor.FIELD_TYPE_STRING)
- public static final String NAME = "name";
- }
-
- /**
- * Contains all genres for audio files
- */
- public static final class Genres implements BaseColumns, GenresColumns {
- /**
- * Get the content:// style URI for the audio genres table on the
- * given volume.
- *
- * @param volumeName the name of the volume to get the URI for
- * @return the URI to the audio genres table on the given volume
- */
- public static Uri getContentUri(String volumeName) {
- return AUTHORITY_URI.buildUpon().appendPath(volumeName).appendPath("audio")
- .appendPath("genres").build();
- }
-
- /**
- * Get the content:// style URI for querying the genres of an audio file.
- *
- * @param volumeName the name of the volume to get the URI for
- * @param audioId the ID of the audio file for which to retrieve the genres
- * @return the URI to for querying the genres for the audio file
- * with the given the volume and audioID
- */
- public static Uri getContentUriForAudioId(String volumeName, int audioId) {
- return ContentUris.withAppendedId(Audio.Media.getContentUri(volumeName), audioId)
- .buildUpon().appendPath("genres").build();
- }
-
- /**
- * The content:// style URI for the internal storage.
- */
- public static final Uri INTERNAL_CONTENT_URI =
- getContentUri("internal");
-
- /**
- * The content:// style URI for the "primary" external storage
- * volume.
- */
- public static final Uri EXTERNAL_CONTENT_URI =
- getContentUri("external");
-
- /**
- * The MIME type for this table.
- */
- public static final String CONTENT_TYPE = "vnd.android.cursor.dir/genre";
-
- /**
- * The MIME type for entries in this table.
- */
- public static final String ENTRY_CONTENT_TYPE = "vnd.android.cursor.item/genre";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = NAME;
-
- /**
- * Sub-directory of each genre containing all members.
- */
- public static final class Members implements AudioColumns {
-
- public static final Uri getContentUri(String volumeName, long genreId) {
- return ContentUris
- .withAppendedId(Audio.Genres.getContentUri(volumeName), genreId)
- .buildUpon().appendPath("members").build();
- }
-
- /**
- * A subdirectory of each genre containing all member audio files.
- */
- public static final String CONTENT_DIRECTORY = "members";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = TITLE_KEY;
-
- /**
- * The ID of the audio file
- */
- @Column(Cursor.FIELD_TYPE_INTEGER)
- public static final String AUDIO_ID = "audio_id";
-
- /**
- * The ID of the genre
- */
- @Column(Cursor.FIELD_TYPE_INTEGER)
- public static final String GENRE_ID = "genre_id";
- }
- }
-
- /**
- * Audio playlist metadata columns.
- */
- public interface PlaylistsColumns {
- /**
- * The name of the playlist
- */
- @Column(Cursor.FIELD_TYPE_STRING)
- public static final String NAME = "name";
-
- /**
- * Path to the playlist file on disk.
- * <p>
- * Note that apps may not have filesystem permissions to directly
- * access this path. Instead of trying to open this path directly,
- * apps should use
- * {@link ContentResolver#openFileDescriptor(Uri, String)} to gain
- * access.
- *
- * @deprecated Apps may not have filesystem permissions to directly
- * access this path. Instead of trying to open this path
- * directly, apps should use
- * {@link ContentResolver#openFileDescriptor(Uri, String)}
- * to gain access.
- */
- @Deprecated
- @Column(Cursor.FIELD_TYPE_STRING)
- public static final String DATA = "_data";
-
- /**
- * The time the media item was first added.
- */
- @CurrentTimeSecondsLong
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String DATE_ADDED = "date_added";
-
- /**
- * The time the media item was last modified.
- */
- @CurrentTimeSecondsLong
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String DATE_MODIFIED = "date_modified";
- }
-
- /**
- * Contains playlists for audio files
- */
- public static final class Playlists implements BaseColumns,
- PlaylistsColumns {
- /**
- * Get the content:// style URI for the audio playlists table on the
- * given volume.
- *
- * @param volumeName the name of the volume to get the URI for
- * @return the URI to the audio playlists table on the given volume
- */
- public static Uri getContentUri(String volumeName) {
- return AUTHORITY_URI.buildUpon().appendPath(volumeName).appendPath("audio")
- .appendPath("playlists").build();
- }
-
- /**
- * The content:// style URI for the internal storage.
- */
- public static final Uri INTERNAL_CONTENT_URI =
- getContentUri("internal");
-
- /**
- * The content:// style URI for the "primary" external storage
- * volume.
- */
- public static final Uri EXTERNAL_CONTENT_URI =
- getContentUri("external");
-
- /**
- * The MIME type for this table.
- */
- public static final String CONTENT_TYPE = "vnd.android.cursor.dir/playlist";
-
- /**
- * The MIME type for entries in this table.
- */
- public static final String ENTRY_CONTENT_TYPE = "vnd.android.cursor.item/playlist";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = NAME;
-
- /**
- * Sub-directory of each playlist containing all members.
- */
- public static final class Members implements AudioColumns {
- public static final Uri getContentUri(String volumeName, long playlistId) {
- return ContentUris
- .withAppendedId(Audio.Playlists.getContentUri(volumeName), playlistId)
- .buildUpon().appendPath("members").build();
- }
-
- /**
- * Convenience method to move a playlist item to a new location
- * @param res The content resolver to use
- * @param playlistId The numeric id of the playlist
- * @param from The position of the item to move
- * @param to The position to move the item to
- * @return true on success
- */
- public static final boolean moveItem(ContentResolver res,
- long playlistId, int from, int to) {
- Uri uri = MediaStore.Audio.Playlists.Members.getContentUri("external",
- playlistId)
- .buildUpon()
- .appendEncodedPath(String.valueOf(from))
- .appendQueryParameter("move", "true")
- .build();
- ContentValues values = new ContentValues();
- values.put(MediaStore.Audio.Playlists.Members.PLAY_ORDER, to);
- return res.update(uri, values, null, null) != 0;
- }
-
- /**
- * The ID within the playlist.
- */
- @Column(Cursor.FIELD_TYPE_INTEGER)
- public static final String _ID = "_id";
-
- /**
- * A subdirectory of each playlist containing all member audio
- * files.
- */
- public static final String CONTENT_DIRECTORY = "members";
-
- /**
- * The ID of the audio file
- */
- @Column(Cursor.FIELD_TYPE_INTEGER)
- public static final String AUDIO_ID = "audio_id";
-
- /**
- * The ID of the playlist
- */
- @Column(Cursor.FIELD_TYPE_INTEGER)
- public static final String PLAYLIST_ID = "playlist_id";
-
- /**
- * The order of the songs in the playlist
- */
- @Column(Cursor.FIELD_TYPE_INTEGER)
- public static final String PLAY_ORDER = "play_order";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = PLAY_ORDER;
- }
- }
-
- /**
- * Audio artist metadata columns.
- */
- public interface ArtistColumns {
- /**
- * The artist who created the audio file, if any
- */
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
- public static final String ARTIST = "artist";
-
- /**
- * A non human readable key calculated from the ARTIST, used for
- * searching, sorting and grouping
- *
- * @see Audio#keyFor(String)
- * @deprecated These keys are generated using
- * {@link java.util.Locale#ROOT}, which means they don't
- * reflect locale-specific sorting preferences. To apply
- * locale-specific sorting preferences, use
- * {@link ContentResolver#QUERY_ARG_SQL_SORT_ORDER} with
- * {@code COLLATE LOCALIZED}, or
- * {@link ContentResolver#QUERY_ARG_SORT_LOCALE}.
- */
- @Deprecated
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
- public static final String ARTIST_KEY = "artist_key";
-
- /**
- * The number of albums in the database for this artist
- */
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String NUMBER_OF_ALBUMS = "number_of_albums";
-
- /**
- * The number of albums in the database for this artist
- */
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String NUMBER_OF_TRACKS = "number_of_tracks";
- }
-
- /**
- * Contains artists for audio files
- */
- public static final class Artists implements BaseColumns, ArtistColumns {
- /**
- * Get the content:// style URI for the artists table on the
- * given volume.
- *
- * @param volumeName the name of the volume to get the URI for
- * @return the URI to the audio artists table on the given volume
- */
- public static Uri getContentUri(String volumeName) {
- return AUTHORITY_URI.buildUpon().appendPath(volumeName).appendPath("audio")
- .appendPath("artists").build();
- }
-
- /**
- * The content:// style URI for the internal storage.
- */
- public static final Uri INTERNAL_CONTENT_URI =
- getContentUri("internal");
-
- /**
- * The content:// style URI for the "primary" external storage
- * volume.
- */
- public static final Uri EXTERNAL_CONTENT_URI =
- getContentUri("external");
-
- /**
- * The MIME type for this table.
- */
- public static final String CONTENT_TYPE = "vnd.android.cursor.dir/artists";
-
- /**
- * The MIME type for entries in this table.
- */
- public static final String ENTRY_CONTENT_TYPE = "vnd.android.cursor.item/artist";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = ARTIST_KEY;
-
- /**
- * Sub-directory of each artist containing all albums on which
- * a song by the artist appears.
- */
- public static final class Albums implements AlbumColumns {
- public static final Uri getContentUri(String volumeName,long artistId) {
- return ContentUris
- .withAppendedId(Audio.Artists.getContentUri(volumeName), artistId)
- .buildUpon().appendPath("albums").build();
- }
- }
- }
-
- /**
- * Audio album metadata columns.
- */
- public interface AlbumColumns {
-
- /**
- * The id for the album
- */
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String ALBUM_ID = "album_id";
-
- /**
- * The album on which the audio file appears, if any
- */
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
- public static final String ALBUM = "album";
-
- /**
- * The ID of the artist whose songs appear on this album.
- */
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String ARTIST_ID = "artist_id";
-
- /**
- * The name of the artist whose songs appear on this album.
- */
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
- public static final String ARTIST = "artist";
-
- /**
- * A non human readable key calculated from the ARTIST, used for
- * searching, sorting and grouping
- *
- * @see Audio#keyFor(String)
- * @deprecated These keys are generated using
- * {@link java.util.Locale#ROOT}, which means they don't
- * reflect locale-specific sorting preferences. To apply
- * locale-specific sorting preferences, use
- * {@link ContentResolver#QUERY_ARG_SQL_SORT_ORDER} with
- * {@code COLLATE LOCALIZED}, or
- * {@link ContentResolver#QUERY_ARG_SORT_LOCALE}.
- */
- @Deprecated
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
- public static final String ARTIST_KEY = "artist_key";
-
- /**
- * The number of songs on this album
- */
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String NUMBER_OF_SONGS = "numsongs";
-
- /**
- * This column is available when getting album info via artist,
- * and indicates the number of songs on the album by the given
- * artist.
- */
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String NUMBER_OF_SONGS_FOR_ARTIST = "numsongs_by_artist";
-
- /**
- * The year in which the earliest songs
- * on this album were released. This will often
- * be the same as {@link #LAST_YEAR}, but for compilation albums
- * they might differ.
- */
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String FIRST_YEAR = "minyear";
-
- /**
- * The year in which the latest songs
- * on this album were released. This will often
- * be the same as {@link #FIRST_YEAR}, but for compilation albums
- * they might differ.
- */
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String LAST_YEAR = "maxyear";
-
- /**
- * A non human readable key calculated from the ALBUM, used for
- * searching, sorting and grouping
- *
- * @see Audio#keyFor(String)
- * @deprecated These keys are generated using
- * {@link java.util.Locale#ROOT}, which means they don't
- * reflect locale-specific sorting preferences. To apply
- * locale-specific sorting preferences, use
- * {@link ContentResolver#QUERY_ARG_SQL_SORT_ORDER} with
- * {@code COLLATE LOCALIZED}, or
- * {@link ContentResolver#QUERY_ARG_SORT_LOCALE}.
- */
- @Deprecated
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
- public static final String ALBUM_KEY = "album_key";
-
- /**
- * Cached album art.
- *
- * @deprecated Apps may not have filesystem permissions to directly
- * access this path. Instead of trying to open this path
- * directly, apps should use
- * {@link ContentResolver#loadThumbnail}
- * to gain access.
- */
- @Deprecated
- @Column(Cursor.FIELD_TYPE_STRING)
- public static final String ALBUM_ART = "album_art";
- }
-
- /**
- * Contains artists for audio files
- */
- public static final class Albums implements BaseColumns, AlbumColumns {
- /**
- * Get the content:// style URI for the albums table on the
- * given volume.
- *
- * @param volumeName the name of the volume to get the URI for
- * @return the URI to the audio albums table on the given volume
- */
- public static Uri getContentUri(String volumeName) {
- return AUTHORITY_URI.buildUpon().appendPath(volumeName).appendPath("audio")
- .appendPath("albums").build();
- }
-
- /**
- * The content:// style URI for the internal storage.
- */
- public static final Uri INTERNAL_CONTENT_URI =
- getContentUri("internal");
-
- /**
- * The content:// style URI for the "primary" external storage
- * volume.
- */
- public static final Uri EXTERNAL_CONTENT_URI =
- getContentUri("external");
-
- /**
- * The MIME type for this table.
- */
- public static final String CONTENT_TYPE = "vnd.android.cursor.dir/albums";
-
- /**
- * The MIME type for entries in this table.
- */
- public static final String ENTRY_CONTENT_TYPE = "vnd.android.cursor.item/album";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = ALBUM_KEY;
- }
-
- public static final class Radio {
- /**
- * The MIME type for entries in this table.
- */
- public static final String ENTRY_CONTENT_TYPE = "vnd.android.cursor.item/radio";
-
- // Not instantiable.
- private Radio() { }
- }
-
- /**
- * This class provides utility methods to obtain thumbnails for various
- * {@link Audio} items.
- *
- * @deprecated Callers should migrate to using
- * {@link ContentResolver#loadThumbnail}, since it offers
- * richer control over requested thumbnail sizes and
- * cancellation behavior.
- * @hide
- */
- @Deprecated
- public static class Thumbnails implements BaseColumns {
- /**
- * Path to the thumbnail file on disk.
- * <p>
- * Note that apps may not have filesystem permissions to directly
- * access this path. Instead of trying to open this path directly,
- * apps should use
- * {@link ContentResolver#openFileDescriptor(Uri, String)} to gain
- * access.
- *
- * @deprecated Apps may not have filesystem permissions to directly
- * access this path. Instead of trying to open this path
- * directly, apps should use
- * {@link ContentResolver#loadThumbnail}
- * to gain access.
- */
- @Deprecated
- @Column(Cursor.FIELD_TYPE_STRING)
- public static final String DATA = "_data";
-
- @Column(Cursor.FIELD_TYPE_INTEGER)
- public static final String ALBUM_ID = "album_id";
- }
- }
-
- /**
- * Collection of all media with MIME type of {@code video/*}.
- */
- public static final class Video {
-
- /**
- * The default sort order for this table.
- */
- public static final String DEFAULT_SORT_ORDER = MediaColumns.DISPLAY_NAME;
-
- /**
- * @deprecated all queries should be performed through
- * {@link ContentResolver} directly, which offers modern
- * features like {@link CancellationSignal}.
- */
- @Deprecated
- public static final Cursor query(ContentResolver cr, Uri uri, String[] projection) {
- return cr.query(uri, projection, null, null, DEFAULT_SORT_ORDER);
- }
-
- /**
- * Video metadata columns.
- */
- public interface VideoColumns extends MediaColumns {
- /** @removed promoted to parent interface */
- public static final String DURATION = "duration";
- /** @removed promoted to parent interface */
- public static final String ARTIST = "artist";
- /** @removed promoted to parent interface */
- public static final String ALBUM = "album";
- /** @removed promoted to parent interface */
- public static final String RESOLUTION = "resolution";
-
- /**
- * The description of the video recording
- */
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
- public static final String DESCRIPTION = "description";
-
- /**
- * Whether the video should be published as public or private
- */
- @Column(Cursor.FIELD_TYPE_INTEGER)
- public static final String IS_PRIVATE = "isprivate";
-
- /**
- * The user-added tags associated with a video
- */
- @Column(Cursor.FIELD_TYPE_STRING)
- public static final String TAGS = "tags";
-
- /**
- * The YouTube category of the video
- */
- @Column(Cursor.FIELD_TYPE_STRING)
- public static final String CATEGORY = "category";
-
- /**
- * The language of the video
- */
- @Column(Cursor.FIELD_TYPE_STRING)
- public static final String LANGUAGE = "language";
-
- /**
- * The latitude where the video was captured.
- *
- * @deprecated location details are no longer indexed for privacy
- * reasons, and this value is now always {@code null}.
- * You can still manually obtain location metadata using
- * {@link ExifInterface#getLatLong(float[])}.
- */
- @Deprecated
- @Column(value = Cursor.FIELD_TYPE_FLOAT, readOnly = true)
- public static final String LATITUDE = "latitude";
-
- /**
- * The longitude where the video was captured.
- *
- * @deprecated location details are no longer indexed for privacy
- * reasons, and this value is now always {@code null}.
- * You can still manually obtain location metadata using
- * {@link ExifInterface#getLatLong(float[])}.
- */
- @Deprecated
- @Column(value = Cursor.FIELD_TYPE_FLOAT, readOnly = true)
- public static final String LONGITUDE = "longitude";
-
- /** @removed promoted to parent interface */
- public static final String DATE_TAKEN = "datetaken";
-
- /**
- * The mini thumb id.
- *
- * @deprecated all thumbnails should be obtained via
- * {@link MediaStore.Images.Thumbnails#getThumbnail}, as this
- * value is no longer supported.
- */
- @Deprecated
- @Column(Cursor.FIELD_TYPE_INTEGER)
- public static final String MINI_THUMB_MAGIC = "mini_thumb_magic";
-
- /** @removed promoted to parent interface */
- public static final String BUCKET_ID = "bucket_id";
- /** @removed promoted to parent interface */
- public static final String BUCKET_DISPLAY_NAME = "bucket_display_name";
- /** @removed promoted to parent interface */
- public static final String GROUP_ID = "group_id";
-
- /**
- * The position within the video item at which playback should be
- * resumed.
- */
- @DurationMillisLong
- @Column(Cursor.FIELD_TYPE_INTEGER)
- public static final String BOOKMARK = "bookmark";
-
- /**
- * The color standard of this media file, if available.
- *
- * @see MediaFormat#COLOR_STANDARD_BT709
- * @see MediaFormat#COLOR_STANDARD_BT601_PAL
- * @see MediaFormat#COLOR_STANDARD_BT601_NTSC
- * @see MediaFormat#COLOR_STANDARD_BT2020
- */
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String COLOR_STANDARD = "color_standard";
-
- /**
- * The color transfer of this media file, if available.
- *
- * @see MediaFormat#COLOR_TRANSFER_LINEAR
- * @see MediaFormat#COLOR_TRANSFER_SDR_VIDEO
- * @see MediaFormat#COLOR_TRANSFER_ST2084
- * @see MediaFormat#COLOR_TRANSFER_HLG
- */
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String COLOR_TRANSFER = "color_transfer";
-
- /**
- * The color range of this media file, if available.
- *
- * @see MediaFormat#COLOR_RANGE_LIMITED
- * @see MediaFormat#COLOR_RANGE_FULL
- */
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String COLOR_RANGE = "color_range";
- }
-
- public static final class Media implements VideoColumns {
- /**
- * Get the content:// style URI for the video media table on the
- * given volume.
- *
- * @param volumeName the name of the volume to get the URI for
- * @return the URI to the video media table on the given volume
- */
- public static Uri getContentUri(String volumeName) {
- return AUTHORITY_URI.buildUpon().appendPath(volumeName).appendPath("video")
- .appendPath("media").build();
- }
-
- /**
- * Get the content:// style URI for a single row in the videos table
- * on the given volume.
- *
- * @param volumeName the name of the volume to get the URI for
- * @param id the video to get the URI for
- * @return the URI to the videos table on the given volume
- */
- public static @NonNull Uri getContentUri(@NonNull String volumeName, long id) {
- return ContentUris.withAppendedId(getContentUri(volumeName), id);
- }
-
- /**
- * The content:// style URI for the internal storage.
- */
- public static final Uri INTERNAL_CONTENT_URI =
- getContentUri("internal");
-
- /**
- * The content:// style URI for the "primary" external storage
- * volume.
- */
- public static final Uri EXTERNAL_CONTENT_URI =
- getContentUri("external");
-
- /**
- * The MIME type for this table.
- */
- public static final String CONTENT_TYPE = "vnd.android.cursor.dir/video";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = TITLE;
- }
-
- /**
- * This class provides utility methods to obtain thumbnails for various
- * {@link Video} items.
- *
- * @deprecated Callers should migrate to using
- * {@link ContentResolver#loadThumbnail}, since it offers
- * richer control over requested thumbnail sizes and
- * cancellation behavior.
- */
- @Deprecated
- public static class Thumbnails implements BaseColumns {
- /**
- * Cancel any outstanding {@link #getThumbnail} requests, causing
- * them to return by throwing a {@link OperationCanceledException}.
- * <p>
- * This method has no effect on
- * {@link ContentResolver#loadThumbnail} calls, since they provide
- * their own {@link CancellationSignal}.
- *
- * @deprecated Callers should migrate to using
- * {@link ContentResolver#loadThumbnail}, since it
- * offers richer control over requested thumbnail sizes
- * and cancellation behavior.
- */
- @Deprecated
- public static void cancelThumbnailRequest(ContentResolver cr, long origId) {
- final Uri uri = ContentUris.withAppendedId(
- Video.Media.EXTERNAL_CONTENT_URI, origId);
- InternalThumbnails.cancelThumbnail(cr, uri);
- }
-
- /**
- * Return thumbnail representing a specific video item. If a
- * thumbnail doesn't exist, this method will block until it's
- * generated. Callers are responsible for their own in-memory
- * caching of returned values.
- *
- * @param videoId the video item to obtain a thumbnail for.
- * @param kind optimal thumbnail size desired.
- * @return decoded thumbnail, or {@code null} if problem was
- * encountered.
- * @deprecated Callers should migrate to using
- * {@link ContentResolver#loadThumbnail}, since it
- * offers richer control over requested thumbnail sizes
- * and cancellation behavior.
- */
- @Deprecated
- public static Bitmap getThumbnail(ContentResolver cr, long videoId, int kind,
- BitmapFactory.Options options) {
- final Uri uri = ContentUris.withAppendedId(
- Video.Media.EXTERNAL_CONTENT_URI, videoId);
- return InternalThumbnails.getThumbnail(cr, uri, kind, options);
- }
-
- /**
- * Cancel any outstanding {@link #getThumbnail} requests, causing
- * them to return by throwing a {@link OperationCanceledException}.
- * <p>
- * This method has no effect on
- * {@link ContentResolver#loadThumbnail} calls, since they provide
- * their own {@link CancellationSignal}.
- *
- * @deprecated Callers should migrate to using
- * {@link ContentResolver#loadThumbnail}, since it
- * offers richer control over requested thumbnail sizes
- * and cancellation behavior.
- */
- @Deprecated
- public static void cancelThumbnailRequest(ContentResolver cr, long videoId,
- long groupId) {
- cancelThumbnailRequest(cr, videoId);
- }
-
- /**
- * Return thumbnail representing a specific video item. If a
- * thumbnail doesn't exist, this method will block until it's
- * generated. Callers are responsible for their own in-memory
- * caching of returned values.
- *
- * @param videoId the video item to obtain a thumbnail for.
- * @param kind optimal thumbnail size desired.
- * @return decoded thumbnail, or {@code null} if problem was
- * encountered.
- * @deprecated Callers should migrate to using
- * {@link ContentResolver#loadThumbnail}, since it
- * offers richer control over requested thumbnail sizes
- * and cancellation behavior.
- */
- @Deprecated
- public static Bitmap getThumbnail(ContentResolver cr, long videoId, long groupId,
- int kind, BitmapFactory.Options options) {
- return getThumbnail(cr, videoId, kind, options);
- }
-
- /**
- * Get the content:// style URI for the image media table on the
- * given volume.
- *
- * @param volumeName the name of the volume to get the URI for
- * @return the URI to the image media table on the given volume
- */
- public static Uri getContentUri(String volumeName) {
- return AUTHORITY_URI.buildUpon().appendPath(volumeName).appendPath("video")
- .appendPath("thumbnails").build();
- }
-
- /**
- * The content:// style URI for the internal storage.
- */
- public static final Uri INTERNAL_CONTENT_URI =
- getContentUri("internal");
-
- /**
- * The content:// style URI for the "primary" external storage
- * volume.
- */
- public static final Uri EXTERNAL_CONTENT_URI =
- getContentUri("external");
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = "video_id ASC";
-
- /**
- * Path to the thumbnail file on disk.
- *
- * @deprecated Apps may not have filesystem permissions to directly
- * access this path. Instead of trying to open this path
- * directly, apps should use
- * {@link ContentResolver#openFileDescriptor(Uri, String)}
- * to gain access.
- */
- @Deprecated
- @Column(Cursor.FIELD_TYPE_STRING)
- public static final String DATA = "_data";
-
- /**
- * The original image for the thumbnal
- */
- @Column(Cursor.FIELD_TYPE_INTEGER)
- public static final String VIDEO_ID = "video_id";
-
- /**
- * The kind of the thumbnail
- */
- @Column(Cursor.FIELD_TYPE_INTEGER)
- public static final String KIND = "kind";
-
- public static final int MINI_KIND = ThumbnailConstants.MINI_KIND;
- public static final int FULL_SCREEN_KIND = ThumbnailConstants.FULL_SCREEN_KIND;
- public static final int MICRO_KIND = ThumbnailConstants.MICRO_KIND;
-
- /**
- * Return the typical {@link Size} (in pixels) used internally when
- * the given thumbnail kind is requested.
- */
- public static @NonNull Size getKindSize(int kind) {
- return ThumbnailConstants.getKindSize(kind);
- }
-
- /**
- * The width of the thumbnal
- */
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String WIDTH = "width";
-
- /**
- * The height of the thumbnail
- */
- @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String HEIGHT = "height";
- }
- }
-
- /** @removed */
- @Deprecated
- public static @NonNull Set<String> getAllVolumeNames(@NonNull Context context) {
- return getExternalVolumeNames(context);
- }
-
- /**
- * Return list of all specific volume names that make up
- * {@link #VOLUME_EXTERNAL}. This includes a unique volume name for each
- * shared storage device that is currently attached, which typically
- * includes {@link MediaStore#VOLUME_EXTERNAL_PRIMARY}.
- * <p>
- * Each specific volume name can be passed to APIs like
- * {@link MediaStore.Images.Media#getContentUri(String)} to interact with
- * media on that storage device.
- */
- public static @NonNull Set<String> getExternalVolumeNames(@NonNull Context context) {
- final StorageManager sm = context.getSystemService(StorageManager.class);
- final Set<String> res = new ArraySet<>();
- for (StorageVolume sv : sm.getStorageVolumes()) {
- switch (sv.getState()) {
- case Environment.MEDIA_MOUNTED:
- case Environment.MEDIA_MOUNTED_READ_ONLY: {
- final String volumeName = sv.getMediaStoreVolumeName();
- if (volumeName != null) {
- res.add(volumeName);
- }
- break;
- }
- }
- }
- return res;
- }
-
- /**
- * Return list of all recent volume names that have been part of
- * {@link #VOLUME_EXTERNAL}.
- * <p>
- * These volume names are not currently mounted, but they're likely to
- * reappear in the future, so apps are encouraged to preserve any indexed
- * metadata related to these volumes to optimize user experiences.
- * <p>
- * Each specific volume name can be passed to APIs like
- * {@link MediaStore.Images.Media#getContentUri(String)} to interact with
- * media on that storage device.
- */
- public static @NonNull Set<String> getRecentExternalVolumeNames(@NonNull Context context) {
- final StorageManager sm = context.getSystemService(StorageManager.class);
- final Set<String> res = new ArraySet<>();
- for (StorageVolume sv : sm.getRecentStorageVolumes()) {
- final String volumeName = sv.getMediaStoreVolumeName();
- if (volumeName != null) {
- res.add(volumeName);
- }
- }
- return res;
- }
-
- /**
- * Return the volume name that the given {@link Uri} references.
- */
- public static @NonNull String getVolumeName(@NonNull Uri uri) {
- final List<String> segments = uri.getPathSegments();
- switch (uri.getAuthority()) {
- case AUTHORITY:
- case AUTHORITY_LEGACY: {
- if (segments != null && segments.size() > 0) {
- return segments.get(0);
- }
- }
- }
- throw new IllegalArgumentException("Missing volume name: " + uri);
- }
-
- /** {@hide} */
- public static @NonNull String checkArgumentVolumeName(@NonNull String volumeName) {
- if (TextUtils.isEmpty(volumeName)) {
- throw new IllegalArgumentException();
- }
-
- if (VOLUME_INTERNAL.equals(volumeName)) {
- return volumeName;
- } else if (VOLUME_EXTERNAL.equals(volumeName)) {
- return volumeName;
- } else if (VOLUME_EXTERNAL_PRIMARY.equals(volumeName)) {
- return volumeName;
- }
-
- // When not one of the well-known values above, it must be a hex UUID
- for (int i = 0; i < volumeName.length(); i++) {
- final char c = volumeName.charAt(i);
- if (('a' <= c && c <= 'f') || ('0' <= c && c <= '9') || (c == '-')) {
- continue;
- } else {
- throw new IllegalArgumentException("Invalid volume name: " + volumeName);
- }
- }
- return volumeName;
- }
-
- private static boolean parseBoolean(@Nullable String value) {
- if (value == null) return false;
- if ("1".equals(value)) return true;
- if ("true".equalsIgnoreCase(value)) return true;
- return false;
- }
-
- /**
- * Uri for querying the state of the media scanner.
- */
- public static Uri getMediaScannerUri() {
- return AUTHORITY_URI.buildUpon().appendPath("none").appendPath("media_scanner").build();
- }
-
- /**
- * Name of current volume being scanned by the media scanner.
- */
- public static final String MEDIA_SCANNER_VOLUME = "volume";
-
- /**
- * Name of the file signaling the media scanner to ignore media in the containing directory
- * and its subdirectories. Developers should use this to avoid application graphics showing
- * up in the Gallery and likewise prevent application sounds and music from showing up in
- * the Music app.
- */
- public static final String MEDIA_IGNORE_FILENAME = ".nomedia";
-
- /**
- * Return an opaque version string describing the {@link MediaStore} state.
- * <p>
- * Applications that import data from {@link MediaStore} into their own
- * caches can use this to detect that {@link MediaStore} has undergone
- * substantial changes, and that data should be rescanned.
- * <p>
- * No other assumptions should be made about the meaning of the version.
- * <p>
- * This method returns the version for
- * {@link MediaStore#VOLUME_EXTERNAL_PRIMARY}; to obtain a version for a
- * different volume, use {@link #getVersion(Context, String)}.
- */
- public static @NonNull String getVersion(@NonNull Context context) {
- return getVersion(context, VOLUME_EXTERNAL_PRIMARY);
- }
-
- /**
- * Return an opaque version string describing the {@link MediaStore} state.
- * <p>
- * Applications that import data from {@link MediaStore} into their own
- * caches can use this to detect that {@link MediaStore} has undergone
- * substantial changes, and that data should be rescanned.
- * <p>
- * No other assumptions should be made about the meaning of the version.
- *
- * @param volumeName specific volume to obtain an opaque version string for.
- * Must be one of the values returned from
- * {@link #getExternalVolumeNames(Context)}.
- */
- public static @NonNull String getVersion(@NonNull Context context, @NonNull String volumeName) {
- final ContentResolver resolver = context.getContentResolver();
- try (ContentProviderClient client = resolver.acquireContentProviderClient(AUTHORITY)) {
- final Bundle in = new Bundle();
- in.putString(Intent.EXTRA_TEXT, volumeName);
- final Bundle out = client.call(GET_VERSION_CALL, null, in);
- return out.getString(Intent.EXTRA_TEXT);
- } catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
- }
- }
-
- /**
- * Return a {@link DocumentsProvider} Uri that is an equivalent to the given
- * {@link MediaStore} Uri.
- * <p>
- * This allows apps with Storage Access Framework permissions to convert
- * between {@link MediaStore} and {@link DocumentsProvider} Uris that refer
- * to the same underlying item. Note that this method doesn't grant any new
- * permissions; callers must already hold permissions obtained with
- * {@link Intent#ACTION_OPEN_DOCUMENT} or related APIs.
- *
- * @param mediaUri The {@link MediaStore} Uri to convert.
- * @return An equivalent {@link DocumentsProvider} Uri. Returns {@code null}
- * if no equivalent was found.
- * @see #getMediaUri(Context, Uri)
- */
- public static @Nullable Uri getDocumentUri(@NonNull Context context, @NonNull Uri mediaUri) {
- final ContentResolver resolver = context.getContentResolver();
- final List<UriPermission> uriPermissions = resolver.getPersistedUriPermissions();
-
- try (ContentProviderClient client = resolver.acquireContentProviderClient(AUTHORITY)) {
- final Bundle in = new Bundle();
- in.putParcelable(EXTRA_URI, mediaUri);
- in.putParcelableArrayList(EXTRA_URI_PERMISSIONS, new ArrayList<>(uriPermissions));
- final Bundle out = client.call(GET_DOCUMENT_URI_CALL, null, in);
- return out.getParcelable(EXTRA_URI);
- } catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
- }
- }
-
- /**
- * Return a {@link MediaStore} Uri that is an equivalent to the given
- * {@link DocumentsProvider} Uri.
- * <p>
- * This allows apps with Storage Access Framework permissions to convert
- * between {@link MediaStore} and {@link DocumentsProvider} Uris that refer
- * to the same underlying item. Note that this method doesn't grant any new
- * permissions; callers must already hold permissions obtained with
- * {@link Intent#ACTION_OPEN_DOCUMENT} or related APIs.
- *
- * @param documentUri The {@link DocumentsProvider} Uri to convert.
- * @return An equivalent {@link MediaStore} Uri. Returns {@code null} if no
- * equivalent was found.
- * @see #getDocumentUri(Context, Uri)
- */
- public static @Nullable Uri getMediaUri(@NonNull Context context, @NonNull Uri documentUri) {
- final ContentResolver resolver = context.getContentResolver();
- final List<UriPermission> uriPermissions = resolver.getPersistedUriPermissions();
-
- try (ContentProviderClient client = resolver.acquireContentProviderClient(AUTHORITY)) {
- final Bundle in = new Bundle();
- in.putParcelable(EXTRA_URI, documentUri);
- in.putParcelableArrayList(EXTRA_URI_PERMISSIONS, new ArrayList<>(uriPermissions));
- final Bundle out = client.call(GET_MEDIA_URI_CALL, null, in);
- return out.getParcelable(EXTRA_URI);
- } catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
- }
- }
-
- /** @hide */
- @TestApi
- public static void waitForIdle(@NonNull ContentResolver resolver) {
- resolver.call(AUTHORITY, WAIT_FOR_IDLE_CALL, null, null);
- }
-
- /**
- * Perform a blocking scan of the given {@link File}, returning the
- * {@link Uri} of the scanned file.
- *
- * @hide
- */
- @SystemApi
- @TestApi
- @SuppressLint("StreamFiles")
- public static @NonNull Uri scanFile(@NonNull ContentResolver resolver, @NonNull File file) {
- final Bundle out = resolver.call(AUTHORITY, SCAN_FILE_CALL, file.getAbsolutePath(), null);
- return out.getParcelable(Intent.EXTRA_STREAM);
- }
-
- /**
- * Perform a blocking scan of the given storage volume.
- *
- * @hide
- */
- @SystemApi
- @TestApi
- public static void scanVolume(@NonNull ContentResolver resolver, @NonNull String volumeName) {
- resolver.call(AUTHORITY, SCAN_VOLUME_CALL, volumeName, null);
- }
-}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index f4e2329797b2..3aa534e79965 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -494,25 +494,94 @@ public final class Settings {
* Activity Action: Show setting page to process an Easy Connect (Wi-Fi DPP) QR code and start
* configuration. This intent should be used when you want to use this device to take on the
* configurator role for an IoT/other device. When provided with a valid DPP URI string Settings
- * will open a wifi selection screen for the user to indicate which network they would like
- * to configure the device specified in the DPP URI string for and carry them through the rest
- * of the flow for provisioning the device.
+ * will open a wifi selection screen for the user to indicate which network they would like to
+ * configure the device specified in the DPP URI string for and carry them through the rest of
+ * the flow for provisioning the device.
* <p>
- * In some cases, a matching Activity may not exist, so ensure you safeguard
- * against this by checking WifiManager.isEasyConnectSupported();
+ * In some cases, a matching Activity may not exist, so ensure you safeguard against this by
+ * checking WifiManager.isEasyConnectSupported();
* <p>
* Input: The Intent's data URI specifies bootstrapping information for authenticating and
* provisioning the peer, with the "DPP" scheme.
* <p>
* Output: After {@code startActivityForResult}, the callback {@code onActivityResult} will have
- * resultCode {@link android.app.Activity#RESULT_OK} if Wi-Fi Easy Connect configuration
- * success and the user clicks 'Done' button.
+ * resultCode {@link android.app.Activity#RESULT_OK} if Wi-Fi Easy Connect configuration succeeded
+ * and the user tapped 'Done' button, or {@link android.app.Activity#RESULT_CANCELED} if operation
+ * failed and user tapped 'Cancel'. In case the operation has failed, a status code from {@link
+ * android.net.wifi.EasyConnectStatusCallback.EasyConnectFailureStatusCode} will be returned as
+ * Extra {@link #EXTRA_EASY_CONNECT_ERROR_CODE}. Easy Connect R2 Enrollees report additional
+ * details about the error they encountered, which will be provided in the {@link
+ * #EXTRA_EASY_CONNECT_ATTEMPTED_SSID}, {@link #EXTRA_EASY_CONNECT_CHANNEL_LIST}, and {@link
+ * #EXTRA_EASY_CONNECT_BAND_LIST}.
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_PROCESS_WIFI_EASY_CONNECT_URI =
"android.settings.PROCESS_WIFI_EASY_CONNECT_URI";
/**
+ * Activity Extra: The Easy Connect operation error code
+ * <p>
+ * An extra returned on the result intent received when using the {@link
+ * #ACTION_PROCESS_WIFI_EASY_CONNECT_URI} intent to launch the Easy Connect Operation. This
+ * extra contains the error code of the operation - one of
+ * {@link android.net.wifi.EasyConnectStatusCallback.EasyConnectFailureStatusCode}.
+ * If there is no error, i.e. if the operation returns {@link android.app.Activity#RESULT_OK},
+ * then this extra is not attached to the result intent.
+ */
+ public static final String EXTRA_EASY_CONNECT_ERROR_CODE =
+ "android.provider.extra.EASY_CONNECT_ERROR_CODE";
+
+ /**
+ * Activity Extra: The SSID that the Enrollee tried to connect to.
+ * <p>
+ * An extra returned on the result intent received when using the {@link
+ * #ACTION_PROCESS_WIFI_EASY_CONNECT_URI} intent to launch the Easy Connect Operation. This
+ * extra contains the SSID of the Access Point that the remote Enrollee tried to connect to.
+ * This value is populated only by remote R2 devices, and only for the following error codes:
+ * {@link android.net.wifi.EasyConnectStatusCallback.EasyConnectFailureStatusCode#EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK}
+ * {@link android.net.wifi.EasyConnectStatusCallback.EasyConnectFailureStatusCode#EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION}.
+ * Therefore, always check if this extra is available using {@link Intent#hasExtra(String)}. If
+ * there is no error, i.e. if the operation returns {@link android.app.Activity#RESULT_OK}, then
+ * this extra is not attached to the result intent.
+ */
+ public static final String EXTRA_EASY_CONNECT_ATTEMPTED_SSID =
+ "android.provider.extra.EASY_CONNECT_ATTEMPTED_SSID";
+
+ /**
+ * Activity Extra: The Channel List that the Enrollee used to scan a network.
+ * <p>
+ * An extra returned on the result intent received when using the {@link
+ * #ACTION_PROCESS_WIFI_EASY_CONNECT_URI} intent to launch the Easy Connect Operation. This
+ * extra contains the list channels the Enrollee used to scan for a network. This value is
+ * populated only by remote R2 devices, and only for the following error code: {@link
+ * android.net.wifi.EasyConnectStatusCallback.EasyConnectFailureStatusCode#EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK}.
+ * Therefore, always check if this extra is available using {@link Intent#hasExtra(String)}. If
+ * there is no error, i.e. if the operation returns {@link android.app.Activity#RESULT_OK}, then
+ * this extra is not attached to the result intent. The list is JSON formatted, as an array
+ * (Wi-Fi global operating classes) of arrays (Wi-Fi channels).
+ */
+ public static final String EXTRA_EASY_CONNECT_CHANNEL_LIST =
+ "android.provider.extra.EASY_CONNECT_CHANNEL_LIST";
+
+ /**
+ * Activity Extra: The Band List that the Enrollee supports.
+ * <p>
+ * An extra returned on the result intent received when using the {@link
+ * #ACTION_PROCESS_WIFI_EASY_CONNECT_URI} intent to launch the Easy Connect Operation. This
+ * extra contains the bands the Enrollee supports, expressed as the Global Operating Class,
+ * see Table E-4 in IEEE Std 802.11-2016 -Global operating classes. This value is populated only
+ * by remote R2 devices, and only for the following error codes: {@link
+ * android.net.wifi.EasyConnectStatusCallback.EasyConnectFailureStatusCode#EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK}
+ * {@link android.net.wifi.EasyConnectStatusCallback.EasyConnectFailureStatusCode#EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION}
+ * {@link android.net.wifi.EasyConnectStatusCallback.EasyConnectFailureStatusCode#EASY_CONNECT_EVENT_FAILURE_ENROLLEE_REJECTED_CONFIGURATION}.
+ * Therefore, always check if this extra is available using {@link Intent#hasExtra(String)}. If
+ * there is no error, i.e. if the operation returns {@link android.app.Activity#RESULT_OK}, then
+ * this extra is not attached to the result intent.
+ */
+ public static final String EXTRA_EASY_CONNECT_BAND_LIST =
+ "android.provider.extra.EASY_CONNECT_BAND_LIST";
+
+ /**
* Activity Action: Show settings to allow configuration of data and view data usage.
* <p>
* In some cases, a matching Activity may not exist, so ensure you
@@ -568,16 +637,47 @@ public final class Settings {
/**
* Activity Action: Show settings to enroll fingerprints, and setup PIN/Pattern/Pass if
* necessary.
+ * @deprecated See {@link #ACTION_BIOMETRIC_ENROLL}.
* <p>
* Input: Nothing.
* <p>
* Output: Nothing.
*/
+ @Deprecated
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_FINGERPRINT_ENROLL =
"android.settings.FINGERPRINT_ENROLL";
/**
+ * Activity Action: Show settings to enroll biometrics, and setup PIN/Pattern/Pass if
+ * necessary. By default, this prompts the user to enroll biometrics with strength
+ * Weak or above, as defined by the CDD. Only biometrics that meet or exceed Strong, as defined
+ * in the CDD are allowed to participate in Keystore operations.
+ * <p>
+ * Input: extras {@link #EXTRA_BIOMETRIC_MINIMUM_STRENGTH_REQUIRED} as an integer, with
+ * constants defined in {@link android.hardware.biometrics.BiometricManager.Authenticators},
+ * e.g. {@link android.hardware.biometrics.BiometricManager.Authenticators#BIOMETRIC_STRONG}.
+ * If not specified, the default behavior is
+ * {@link android.hardware.biometrics.BiometricManager.Authenticators#BIOMETRIC_WEAK}.
+ * <p>
+ * Output: Nothing.
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_BIOMETRIC_ENROLL =
+ "android.settings.BIOMETRIC_ENROLL";
+
+ /**
+ * Activity Extra: The minimum strength to request enrollment for.
+ * <p>
+ * This can be passed as an extra field to the {@link #ACTION_BIOMETRIC_ENROLL} intent to
+ * indicate that only enrollment for sensors that meet this strength should be shown. The
+ * value should be one of the biometric strength constants defined in
+ * {@link android.hardware.biometrics.BiometricManager.Authenticators}.
+ */
+ public static final String EXTRA_BIOMETRIC_MINIMUM_STRENGTH_REQUIRED =
+ "android.provider.extra.BIOMETRIC_MINIMUM_STRENGTH_REQUIRED";
+
+ /**
* Activity Action: Show settings to allow configuration of cast endpoints.
* <p>
* In some cases, a matching Activity may not exist, so ensure you
@@ -3869,6 +3969,12 @@ public final class Settings {
public static final String VOLUME_ACCESSIBILITY = "volume_a11y";
/**
+ * @hide
+ * Volume index for virtual assistant.
+ */
+ public static final String VOLUME_ASSISTANT = "volume_assistant";
+
+ /**
* Master volume (float in the range 0.0f to 1.0f).
*
* @hide
@@ -3946,7 +4052,7 @@ public final class Settings {
"" /*STREAM_SYSTEM_ENFORCED, no setting for this stream*/,
"" /*STREAM_DTMF, no setting for this stream*/,
"" /*STREAM_TTS, no setting for this stream*/,
- VOLUME_ACCESSIBILITY
+ VOLUME_ACCESSIBILITY, VOLUME_ASSISTANT
};
/**
@@ -4493,6 +4599,7 @@ public final class Settings {
PUBLIC_SETTINGS.add(VOLUME_ALARM);
PUBLIC_SETTINGS.add(VOLUME_NOTIFICATION);
PUBLIC_SETTINGS.add(VOLUME_BLUETOOTH_SCO);
+ PUBLIC_SETTINGS.add(VOLUME_ASSISTANT);
PUBLIC_SETTINGS.add(RINGTONE);
PUBLIC_SETTINGS.add(NOTIFICATION_SOUND);
PUBLIC_SETTINGS.add(ALARM_ALERT);
@@ -8436,6 +8543,29 @@ public final class Settings {
public static final String WINDOW_MAGNIFICATION = "window_magnification";
/**
+ * Controls magnification mode when magnification is enabled via a system-wide
+ * triple tap gesture or the accessibility shortcut.
+ *
+ * @see#ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN
+ * @see#ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW
+ * @hide
+ */
+ public static final String ACCESSIBILITY_MAGNIFICATION_MODE =
+ "accessibility_magnification_mode";
+
+ /**
+ * Magnification mode value that magnifies whole display.
+ * @hide
+ */
+ public static final int ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN = 0x1;
+
+ /**
+ * Magnification mode value that magnifies magnify particular region in a window
+ * @hide
+ */
+ public static final int ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW = 0x2;
+
+ /**
* Keys we no longer back up under the current schema, but want to continue to
* process when restoring historical backup datasets.
*
@@ -9525,35 +9655,37 @@ public final class Settings {
*/
public static final String SMS_SHORT_CODE_RULE = "sms_short_code_rule";
- /**
- * Used to select TCP's default initial receiver window size in segments - defaults to a build config value
- * @hide
- */
- public static final String TCP_DEFAULT_INIT_RWND = "tcp_default_init_rwnd";
+ /**
+ * Used to select TCP's default initial receiver window size in segments - defaults to a
+ * build config value.
+ * @hide
+ */
+ public static final String TCP_DEFAULT_INIT_RWND = "tcp_default_init_rwnd";
- /**
- * Used to disable Tethering on a device - defaults to true
- * @hide
- */
- public static final String TETHER_SUPPORTED = "tether_supported";
+ /**
+ * Used to disable Tethering on a device - defaults to true.
+ * @hide
+ */
+ @SystemApi
+ public static final String TETHER_SUPPORTED = "tether_supported";
- /**
- * Used to require DUN APN on the device or not - defaults to a build config value
- * which defaults to false
- * @hide
- */
- public static final String TETHER_DUN_REQUIRED = "tether_dun_required";
+ /**
+ * Used to require DUN APN on the device or not - defaults to a build config value
+ * which defaults to false.
+ * @hide
+ */
+ public static final String TETHER_DUN_REQUIRED = "tether_dun_required";
- /**
- * Used to hold a gservices-provisioned apn value for DUN. If set, or the
- * corresponding build config values are set it will override the APN DB
- * values.
- * Consists of a comma seperated list of strings:
- * "name,apn,proxy,port,username,password,server,mmsc,mmsproxy,mmsport,mcc,mnc,auth,type"
- * note that empty fields can be omitted: "name,apn,,,,,,,,,310,260,,DUN"
- * @hide
- */
- public static final String TETHER_DUN_APN = "tether_dun_apn";
+ /**
+ * Used to hold a gservices-provisioned apn value for DUN. If set, or the
+ * corresponding build config values are set it will override the APN DB
+ * values.
+ * Consists of a comma separated list of strings:
+ * "name,apn,proxy,port,username,password,server,mmsc,mmsproxy,mmsport,mcc,mnc,auth,type"
+ * note that empty fields can be omitted: "name,apn,,,,,,,,,310,260,,DUN"
+ * @hide
+ */
+ public static final String TETHER_DUN_APN = "tether_dun_apn";
/**
* Used to disable trying to talk to any available tethering offload HAL.
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index c287ae381261..fed3d7ba0f13 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -1389,7 +1389,6 @@ public final class Telephony {
for (int i = 0; i < pduCount; i++) {
byte[] pdu = (byte[]) messages[i];
msgs[i] = SmsMessage.createFromPdu(pdu, format);
- if (msgs[i] != null) msgs[i].setSubId(subId);
}
return msgs;
}
diff --git a/core/java/android/se/omapi/SEService.java b/core/java/android/se/omapi/SEService.java
index 00060ab8ef4a..d646e23d230a 100644
--- a/core/java/android/se/omapi/SEService.java
+++ b/core/java/android/se/omapi/SEService.java
@@ -22,11 +22,14 @@
package android.se.omapi;
+import android.app.ActivityThread;
import android.annotation.NonNull;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
@@ -140,6 +143,10 @@ public final class SEService {
throw new NullPointerException("Arguments must not be null");
}
+ if (!hasOMAPIReaders()) {
+ throw new UnsupportedOperationException("Device does not support any OMAPI reader");
+ }
+
mContext = context;
mSEListener.mListener = listener;
mSEListener.mExecutor = executor;
@@ -270,4 +277,23 @@ public final class SEService {
throw new IllegalStateException(e.getMessage());
}
}
+
+ /**
+ * Helper to check if this device support any OMAPI readers
+ */
+ private static boolean hasOMAPIReaders() {
+ IPackageManager pm = ActivityThread.getPackageManager();
+ if (pm == null) {
+ Log.e(TAG, "Cannot get package manager, assuming OMAPI readers supported");
+ return true;
+ }
+ try {
+ return pm.hasSystemFeature(PackageManager.FEATURE_SE_OMAPI_UICC, 0)
+ || pm.hasSystemFeature(PackageManager.FEATURE_SE_OMAPI_ESE, 0)
+ || pm.hasSystemFeature(PackageManager.FEATURE_SE_OMAPI_SD, 0);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Package manager query failed, assuming OMAPI readers supported", e);
+ return true;
+ }
+ }
}
diff --git a/core/java/android/security/FileIntegrityManager.java b/core/java/android/security/FileIntegrityManager.java
new file mode 100644
index 000000000000..cdd6584e9b35
--- /dev/null
+++ b/core/java/android/security/FileIntegrityManager.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security;
+
+import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemService;
+import android.content.Context;
+import android.os.RemoteException;
+
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+
+/**
+ * This class provides access to file integrity related operations.
+ */
+@SystemService(Context.FILE_INTEGRITY_SERVICE)
+public final class FileIntegrityManager {
+ @NonNull private final IFileIntegrityService mService;
+
+ /** @hide */
+ public FileIntegrityManager(@NonNull IFileIntegrityService service) {
+ mService = service;
+ }
+
+ /**
+ * Returns true if APK Verity is supported on the device. When supported, an APK can be
+ * installed with a fs-verity signature (if verified with trusted App Source Certificate) for
+ * continuous on-access verification.
+ */
+ public boolean isApkVeritySupported() {
+ try {
+ // Go through the service just to avoid exposing the vendor controlled system property
+ // to all apps.
+ return mService.isApkVeritySupported();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns whether the given certificate can be used to prove app's install source. Always
+ * return false if the feature is not supported.
+ *
+ * <p>A store can use this API to decide if a signature file needs to be downloaded. Also, if a
+ * store has shipped different certificates before (e.g. with stronger and weaker key), it can
+ * also use this API to download the best signature on the running device.
+ *
+ * @return whether the certificate is trusted in the system
+ */
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.INSTALL_PACKAGES,
+ android.Manifest.permission.REQUEST_INSTALL_PACKAGES
+ })
+ public boolean isAppSourceCertificateTrusted(@NonNull X509Certificate certificate)
+ throws CertificateEncodingException {
+ try {
+ return mService.isAppSourceCertificateTrusted(certificate.getEncoded());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/MainLooper.java b/core/java/android/security/IFileIntegrityService.aidl
index 750d7d72035c..ebb8bcb85350 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/MainLooper.java
+++ b/core/java/android/security/IFileIntegrityService.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,17 +14,13 @@
* limitations under the License.
*/
-package com.android.systemui.dagger.qualifiers;
+package android.security;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-
-import javax.inject.Qualifier;
-
-@Qualifier
-@Documented
-@Retention(RUNTIME)
-public @interface MainLooper {
+/**
+ * Binder interface to communicate with FileIntegrityService.
+ * @hide
+ */
+interface IFileIntegrityService {
+ boolean isApkVeritySupported();
+ boolean isAppSourceCertificateTrusted(in byte[] certificateBytes);
}
diff --git a/core/java/android/security/keystore/recovery/KeyChainProtectionParams.java b/core/java/android/security/keystore/recovery/KeyChainProtectionParams.java
index 8801217f9ebe..2b70c714bb74 100644
--- a/core/java/android/security/keystore/recovery/KeyChainProtectionParams.java
+++ b/core/java/android/security/keystore/recovery/KeyChainProtectionParams.java
@@ -22,11 +22,10 @@ import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
-import com.android.internal.util.Preconditions;
-
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
+import java.util.Objects;
/**
* A {@link KeyChainSnapshot} is protected with a key derived from the user's lock screen. This
@@ -220,8 +219,8 @@ public final class KeyChainProtectionParams implements Parcelable {
if (mInstance.mUserSecretType == null) {
mInstance.mUserSecretType = TYPE_LOCKSCREEN;
}
- Preconditions.checkNotNull(mInstance.mLockScreenUiFormat);
- Preconditions.checkNotNull(mInstance.mKeyDerivationParams);
+ Objects.requireNonNull(mInstance.mLockScreenUiFormat);
+ Objects.requireNonNull(mInstance.mKeyDerivationParams);
if (mInstance.mSecret == null) {
mInstance.mSecret = new byte[]{};
}
diff --git a/core/java/android/security/keystore/recovery/KeyChainSnapshot.java b/core/java/android/security/keystore/recovery/KeyChainSnapshot.java
index 2f584717ec6f..fdc00f4a99e8 100644
--- a/core/java/android/security/keystore/recovery/KeyChainSnapshot.java
+++ b/core/java/android/security/keystore/recovery/KeyChainSnapshot.java
@@ -27,6 +27,7 @@ import com.android.internal.util.Preconditions;
import java.security.cert.CertPath;
import java.security.cert.CertificateException;
import java.util.List;
+import java.util.Objects;
/**
* A snapshot of a version of the keystore. Two events can trigger the generation of a new snapshot:
@@ -272,9 +273,9 @@ public final class KeyChainSnapshot implements Parcelable {
"keyChainProtectionParams");
Preconditions.checkCollectionElementsNotNull(mInstance.mEntryRecoveryData,
"entryRecoveryData");
- Preconditions.checkNotNull(mInstance.mEncryptedRecoveryKeyBlob);
- Preconditions.checkNotNull(mInstance.mServerParams);
- Preconditions.checkNotNull(mInstance.mCertPath);
+ Objects.requireNonNull(mInstance.mEncryptedRecoveryKeyBlob);
+ Objects.requireNonNull(mInstance.mServerParams);
+ Objects.requireNonNull(mInstance.mCertPath);
return mInstance;
}
}
diff --git a/core/java/android/security/keystore/recovery/KeyDerivationParams.java b/core/java/android/security/keystore/recovery/KeyDerivationParams.java
index d036d144aaa1..6c541dae0db6 100644
--- a/core/java/android/security/keystore/recovery/KeyDerivationParams.java
+++ b/core/java/android/security/keystore/recovery/KeyDerivationParams.java
@@ -22,10 +22,9 @@ import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
-import com.android.internal.util.Preconditions;
-
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
/**
* Collection of parameters which define a key derivation function.
@@ -109,7 +108,7 @@ public final class KeyDerivationParams implements Parcelable {
private KeyDerivationParams(@KeyDerivationAlgorithm int algorithm, @NonNull byte[] salt,
int memoryDifficulty) {
mAlgorithm = algorithm;
- mSalt = Preconditions.checkNotNull(salt);
+ mSalt = Objects.requireNonNull(salt);
mMemoryDifficulty = memoryDifficulty;
}
diff --git a/core/java/android/security/keystore/recovery/RecoveryCertPath.java b/core/java/android/security/keystore/recovery/RecoveryCertPath.java
index 51bd2ae0d066..ff10b291f4dc 100644
--- a/core/java/android/security/keystore/recovery/RecoveryCertPath.java
+++ b/core/java/android/security/keystore/recovery/RecoveryCertPath.java
@@ -20,13 +20,12 @@ import android.annotation.NonNull;
import android.os.Parcel;
import android.os.Parcelable;
-import com.android.internal.util.Preconditions;
-
import java.io.ByteArrayInputStream;
import java.security.cert.CertPath;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
+import java.util.Objects;
/**
* The certificate path of the recovery service.
@@ -67,7 +66,7 @@ public final class RecoveryCertPath implements Parcelable {
}
private RecoveryCertPath(@NonNull byte[] encodedCertPath) {
- mEncodedCertPath = Preconditions.checkNotNull(encodedCertPath);
+ mEncodedCertPath = Objects.requireNonNull(encodedCertPath);
}
private RecoveryCertPath(Parcel in) {
@@ -98,13 +97,13 @@ public final class RecoveryCertPath implements Parcelable {
@NonNull
private static byte[] encodeCertPath(@NonNull CertPath certPath)
throws CertificateEncodingException {
- Preconditions.checkNotNull(certPath);
+ Objects.requireNonNull(certPath);
return certPath.getEncoded(CERT_PATH_ENCODING);
}
@NonNull
private static CertPath decodeCertPath(@NonNull byte[] bytes) throws CertificateException {
- Preconditions.checkNotNull(bytes);
+ Objects.requireNonNull(bytes);
CertificateFactory certFactory;
try {
certFactory = CertificateFactory.getInstance("X.509");
diff --git a/core/java/android/security/keystore/recovery/WrappedApplicationKey.java b/core/java/android/security/keystore/recovery/WrappedApplicationKey.java
index 665c937591a3..0cb69a4da50f 100644
--- a/core/java/android/security/keystore/recovery/WrappedApplicationKey.java
+++ b/core/java/android/security/keystore/recovery/WrappedApplicationKey.java
@@ -22,7 +22,7 @@ import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
-import com.android.internal.util.Preconditions;
+import java.util.Objects;
/**
* Helper class with data necessary recover a single application key, given a recovery key.
@@ -106,8 +106,8 @@ public final class WrappedApplicationKey implements Parcelable {
* @throws NullPointerException if some required fields were not set.
*/
public @NonNull WrappedApplicationKey build() {
- Preconditions.checkNotNull(mInstance.mAlias);
- Preconditions.checkNotNull(mInstance.mEncryptedKeyMaterial);
+ Objects.requireNonNull(mInstance.mAlias);
+ Objects.requireNonNull(mInstance.mEncryptedKeyMaterial);
return mInstance;
}
}
@@ -120,8 +120,8 @@ public final class WrappedApplicationKey implements Parcelable {
*/
@Deprecated
public WrappedApplicationKey(@NonNull String alias, @NonNull byte[] encryptedKeyMaterial) {
- mAlias = Preconditions.checkNotNull(alias);
- mEncryptedKeyMaterial = Preconditions.checkNotNull(encryptedKeyMaterial);
+ mAlias = Objects.requireNonNull(alias);
+ mEncryptedKeyMaterial = Objects.requireNonNull(encryptedKeyMaterial);
}
/**
diff --git a/core/java/android/service/controls/ControlState.aidl b/core/java/android/service/autofill/Dataset.aidl
index 520d85b47d3e..6fe7dd6119e7 100644
--- a/core/java/android/service/controls/ControlState.aidl
+++ b/core/java/android/service/autofill/Dataset.aidl
@@ -1,4 +1,4 @@
-/*
+/**
* Copyright (c) 2019, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.service.controls;
+package android.service.autofill;
-parcelable ControlState; \ No newline at end of file
+parcelable Dataset;
diff --git a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
index 66c3e1966134..484eddc8c2f6 100644
--- a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
+++ b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
@@ -236,9 +236,9 @@ public abstract class AugmentedAutofillService extends Service {
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
-
- onFillRequest(new FillRequest(proxy), cancellationSignal, new FillController(proxy),
- new FillCallback(proxy));
+ // TODO(b/146453195): pass the inline suggestion request over.
+ onFillRequest(new FillRequest(proxy, /* inlineSuggestionsRequest= */null),
+ cancellationSignal, new FillController(proxy), new FillCallback(proxy));
}
private void handleOnDestroyAllFillWindowsRequest() {
@@ -500,7 +500,7 @@ public abstract class AugmentedAutofillService extends Service {
}
}
try {
- mCallback.onSuccess();
+ mCallback.onSuccess(/* mInlineSuggestionsData= */null);
} catch (RemoteException e) {
Log.e(TAG, "Error reporting success: " + e);
}
diff --git a/core/java/android/service/autofill/augmented/FillRequest.java b/core/java/android/service/autofill/augmented/FillRequest.java
index 0b44470670de..ca49e7daf054 100644
--- a/core/java/android/service/autofill/augmented/FillRequest.java
+++ b/core/java/android/service/autofill/augmented/FillRequest.java
@@ -23,6 +23,9 @@ import android.content.ComponentName;
import android.service.autofill.augmented.AugmentedAutofillService.AutofillProxy;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillValue;
+import android.view.inputmethod.InlineSuggestionsRequest;
+
+import com.android.internal.util.DataClass;
/**
* Represents a request to augment-fill an activity.
@@ -31,14 +34,20 @@ import android.view.autofill.AutofillValue;
@SystemApi
// TODO(b/123100811): pass a requestId and/or sessionId?
@TestApi
+@DataClass(
+ genToString = true,
+ genBuilder = false,
+ genHiddenConstructor = true)
+@DataClass.Suppress({"getProxy"})
public final class FillRequest {
- final AutofillProxy mProxy;
+ private final @NonNull AutofillProxy mProxy;
- /** @hide */
- FillRequest(@NonNull AutofillProxy proxy) {
- mProxy = proxy;
- }
+ //TODO(b/146901891): add detailed docs once we have stable APIs.
+ /**
+ * An optional request for inline suggestions.
+ */
+ private final @Nullable InlineSuggestionsRequest mInlineSuggestionsRequest;
/**
* Gets the task of the activity associated with this request.
@@ -81,10 +90,76 @@ public final class FillRequest {
return mProxy.getSmartSuggestionParams();
}
- @NonNull
- @Override
- public String toString() {
+ String proxyToString() {
return "FillRequest[act=" + getActivityComponent().flattenToShortString()
+ ", id=" + mProxy.getFocusedId() + "]";
}
+
+
+
+
+ // Code below generated by codegen v1.0.14.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/service/autofill/augmented/FillRequest.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ /**
+ * Creates a new FillRequest.
+ *
+ * @param inlineSuggestionsRequest
+ * An optional request for inline suggestions.
+ * @hide
+ */
+ @DataClass.Generated.Member
+ public FillRequest(
+ @NonNull AutofillProxy proxy,
+ @Nullable InlineSuggestionsRequest inlineSuggestionsRequest) {
+ this.mProxy = proxy;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mProxy);
+ this.mInlineSuggestionsRequest = inlineSuggestionsRequest;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ /**
+ * An optional request for inline suggestions.
+ */
+ @DataClass.Generated.Member
+ public @Nullable InlineSuggestionsRequest getInlineSuggestionsRequest() {
+ return mInlineSuggestionsRequest;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public String toString() {
+ // You can override field toString logic by defining methods like:
+ // String fieldNameToString() { ... }
+
+ return "FillRequest { " +
+ "proxy = " + proxyToString() + ", " +
+ "inlineSuggestionsRequest = " + mInlineSuggestionsRequest +
+ " }";
+ }
+
+ @DataClass.Generated(
+ time = 1577399314707L,
+ codegenVersion = "1.0.14",
+ sourceFile = "frameworks/base/core/java/android/service/autofill/augmented/FillRequest.java",
+ inputSignatures = "private final @android.annotation.NonNull android.service.autofill.augmented.AugmentedAutofillService.AutofillProxy mProxy\nprivate final @android.annotation.Nullable android.view.inputmethod.InlineSuggestionsRequest mInlineSuggestionsRequest\npublic int getTaskId()\npublic @android.annotation.NonNull android.content.ComponentName getActivityComponent()\npublic @android.annotation.NonNull android.view.autofill.AutofillId getFocusedId()\npublic @android.annotation.NonNull android.view.autofill.AutofillValue getFocusedValue()\npublic @android.annotation.Nullable android.service.autofill.augmented.PresentationParams getPresentationParams()\n java.lang.String proxyToString()\nclass FillRequest extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genToString=true, genBuilder=false, genHiddenConstructor=true)")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
}
diff --git a/core/java/android/service/autofill/augmented/FillResponse.java b/core/java/android/service/autofill/augmented/FillResponse.java
index 48a3c1b18334..e8e6ff05da03 100644
--- a/core/java/android/service/autofill/augmented/FillResponse.java
+++ b/core/java/android/service/autofill/augmented/FillResponse.java
@@ -19,6 +19,12 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
+import android.service.autofill.Dataset;
+
+import com.android.internal.util.DataClass;
+
+import java.util.ArrayList;
+import java.util.List;
/**
* Response to a {@link FillRequest}.
@@ -27,65 +33,165 @@ import android.annotation.TestApi;
*/
@SystemApi
@TestApi
+@DataClass(
+ genBuilder = true,
+ genHiddenGetters = true)
public final class FillResponse {
- private final FillWindow mFillWindow;
+ /**
+ * The {@link FillWindow} used to display the Autofill UI.
+ */
+ private @Nullable FillWindow mFillWindow;
- private FillResponse(@NonNull Builder builder) {
- mFillWindow = builder.mFillWindow;
+ /**
+ * The {@link Dataset}s representing the inline suggestions data. Defaults to null if no
+ * inline suggestions are available from the service.
+ */
+ @DataClass.PluralOf("inlineSuggestion")
+ private @Nullable List<Dataset> mInlineSuggestions;
+
+ private static FillWindow defaultFillWindow() {
+ return null;
+ }
+
+ private static List<Dataset> defaultInlineSuggestions() {
+ return null;
}
+
/** @hide */
- @Nullable
- FillWindow getFillWindow() {
+ abstract static class BaseBuilder {
+ abstract FillResponse.Builder addInlineSuggestion(@NonNull Dataset value);
+ }
+
+
+
+ // Code below generated by codegen v1.0.14.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/service/autofill/augmented/FillResponse.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ @DataClass.Generated.Member
+ /* package-private */ FillResponse(
+ @Nullable FillWindow fillWindow,
+ @Nullable List<Dataset> inlineSuggestions) {
+ this.mFillWindow = fillWindow;
+ this.mInlineSuggestions = inlineSuggestions;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ /**
+ * The {@link FillWindow} used to display the Autofill UI.
+ *
+ * @hide
+ */
+ @DataClass.Generated.Member
+ public @Nullable FillWindow getFillWindow() {
return mFillWindow;
}
/**
- * Builder for {@link FillResponse} objects.
+ * The {@link Dataset}s representing the inline suggestions data. Defaults to null if no
+ * inline suggestions are available from the service.
*
* @hide
*/
- @SystemApi
- @TestApi
- public static final class Builder {
+ @DataClass.Generated.Member
+ public @Nullable List<Dataset> getInlineSuggestions() {
+ return mInlineSuggestions;
+ }
+
+ /**
+ * A builder for {@link FillResponse}
+ */
+ @SuppressWarnings("WeakerAccess")
+ @DataClass.Generated.Member
+ public static final class Builder extends BaseBuilder {
- private FillWindow mFillWindow;
+ private @Nullable FillWindow mFillWindow;
+ private @Nullable List<Dataset> mInlineSuggestions;
+
+ private long mBuilderFieldsSet = 0L;
+
+ public Builder() {
+ }
/**
- * Sets the {@link FillWindow} used to display the Autofill UI.
- *
- * <p>Must be called when the service is handling the request so the Android System can
- * properly synchronize the UI.
- *
- * @return this builder
+ * The {@link FillWindow} used to display the Autofill UI.
*/
- @NonNull
- public Builder setFillWindow(@NonNull FillWindow fillWindow) {
- // TODO(b/123100712): check not null / unit test / throw exception if FillWindow not
- // updated yet
- mFillWindow = fillWindow;
+ @DataClass.Generated.Member
+ public @NonNull Builder setFillWindow(@Nullable FillWindow value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x1;
+ mFillWindow = value;
return this;
}
/**
- * Builds a new {@link FillResponse} instance.
- *
- * @throws IllegalStateException if any of the following conditions occur:
- * <ol>
- * <li>{@link #build()} was already called.
- * <li>No call was made to {@link #setFillWindow(FillWindow)} or
- * {@ling #setIgnoredIds(List<AutofillId>)}.
- * </ol>
- *
- * @return A built response.
+ * The {@link Dataset}s representing the inline suggestions data. Defaults to null if no
+ * inline suggestions are available from the service.
*/
- @NonNull
- public FillResponse build() {
- // TODO(b/123100712): check conditions / add unit test
- return new FillResponse(this);
+ @DataClass.Generated.Member
+ public @NonNull Builder setInlineSuggestions(@Nullable List<Dataset> value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x2;
+ mInlineSuggestions = value;
+ return this;
+ }
+
+ /** @see #setInlineSuggestions */
+ @DataClass.Generated.Member
+ @Override
+ @NonNull FillResponse.Builder addInlineSuggestion(@NonNull Dataset value) {
+ if (mInlineSuggestions == null) setInlineSuggestions(new ArrayList<>());
+ mInlineSuggestions.add(value);
+ return this;
+ }
+
+ /** Builds the instance. This builder should not be touched after calling this! */
+ public @NonNull FillResponse build() {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x4; // Mark builder used
+
+ if ((mBuilderFieldsSet & 0x1) == 0) {
+ mFillWindow = defaultFillWindow();
+ }
+ if ((mBuilderFieldsSet & 0x2) == 0) {
+ mInlineSuggestions = defaultInlineSuggestions();
+ }
+ FillResponse o = new FillResponse(
+ mFillWindow,
+ mInlineSuggestions);
+ return o;
+ }
+
+ private void checkNotUsed() {
+ if ((mBuilderFieldsSet & 0x4) != 0) {
+ throw new IllegalStateException(
+ "This Builder should not be reused. Use a new Builder instance instead");
+ }
}
}
- // TODO(b/123100811): implement to String
+ @DataClass.Generated(
+ time = 1577476012370L,
+ codegenVersion = "1.0.14",
+ sourceFile = "frameworks/base/core/java/android/service/autofill/augmented/FillResponse.java",
+ inputSignatures = "private @android.annotation.Nullable android.service.autofill.augmented.FillWindow mFillWindow\nprivate @com.android.internal.util.DataClass.PluralOf(\"inlineSuggestion\") @android.annotation.Nullable java.util.List<android.service.autofill.Dataset> mInlineSuggestions\nprivate static android.service.autofill.augmented.FillWindow defaultFillWindow()\nprivate static java.util.List<android.service.autofill.Dataset> defaultInlineSuggestions()\nclass FillResponse extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genBuilder=true, genHiddenGetters=true)\nabstract android.service.autofill.augmented.FillResponse.Builder addInlineSuggestion(android.service.autofill.Dataset)\nclass BaseBuilder extends java.lang.Object implements []")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
}
diff --git a/core/java/android/service/autofill/augmented/IFillCallback.aidl b/core/java/android/service/autofill/augmented/IFillCallback.aidl
index 88baa878f118..3ccb3114a10f 100644
--- a/core/java/android/service/autofill/augmented/IFillCallback.aidl
+++ b/core/java/android/service/autofill/augmented/IFillCallback.aidl
@@ -18,6 +18,8 @@ package android.service.autofill.augmented;
import android.os.ICancellationSignal;
+import android.service.autofill.Dataset;
+
/**
* Interface to receive the result of an autofill request.
*
@@ -25,7 +27,7 @@ import android.os.ICancellationSignal;
*/
interface IFillCallback {
void onCancellable(in ICancellationSignal cancellation);
- void onSuccess();
+ void onSuccess(in @nullable Dataset[] mInlineSuggestionsData);
boolean isCompleted();
void cancel();
}
diff --git a/core/java/android/service/controls/Control.java b/core/java/android/service/controls/Control.java
index 2c17e89d02cc..43a308cf82cb 100644
--- a/core/java/android/service/controls/Control.java
+++ b/core/java/android/service/controls/Control.java
@@ -16,88 +16,161 @@
package android.service.controls;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.PendingIntent;
import android.content.Intent;
-import android.content.res.ColorStateList;
-import android.graphics.drawable.Icon;
import android.os.Parcel;
import android.os.Parcelable;
+import android.service.controls.actions.ControlAction;
+import android.service.controls.templates.ControlTemplate;
+import android.util.Log;
import com.android.internal.util.Preconditions;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* Represents a physical object that can be represented by a {@link ControlTemplate} and whose
* properties may be modified through a {@link ControlAction}.
*
- * The information is provided by a {@link ControlProviderService} and represents static
+ * The information is provided by a {@link ControlsProviderService} and represents static
* information (not current status) about the device.
* <p>
* Each control needs a unique (per provider) identifier that is persistent across reboots of the
* system.
* <p>
- * Each {@link Control} will have a name and an icon. The name is usually set up by the user in the
- * {@link ControlProvider} while the icon is usually decided by the {@link ControlProvider} based
- * on the type of device.
+ * Each {@link Control} will have a name, a subtitle and will optionally belong to a structure
+ * and zone. Some of these values are defined by the user and/or the {@link ControlsProviderService}
+ * and will be used to display the control as well as group them for management.
* <p>
- * The {@link ControlTemplate.TemplateType} provided will be used as a hint when displaying this in
- * non-interactive situations (for example when there's no state to display). This template is not
- * the one that will be shown with the current state and provide interactions. That template is set
- * using {@link ControlState}.
+ * Each object will have an associated {@link DeviceTypes.DeviceType}. This will determine the icons and colors
+ * used to display it.
* <p>
- * An {@link Intent} linking to the provider Activity that expands this {@link Control} should be
- * provided.
+ * An {@link Intent} linking to the provider Activity that expands on this {@link Control} and
+ * allows for further actions should be provided.
* @hide
*/
public class Control implements Parcelable {
+ private static final String TAG = "Control";
+
+ private static final int NUM_STATUS = 5;
+ /**
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ STATUS_UNKNOWN,
+ STATUS_OK,
+ STATUS_NOT_FOUND,
+ STATUS_ERROR,
+ STATUS_DISABLED,
+ })
+ public @interface Status {};
+
+ public static final int STATUS_UNKNOWN = 0;
+
+ /**
+ * The device corresponding to the {@link Control} is responding correctly.
+ */
+ public static final int STATUS_OK = 1;
+
+ /**
+ * The device corresponding to the {@link Control} cannot be found or was removed.
+ */
+ public static final int STATUS_NOT_FOUND = 2;
+
+ /**
+ * The device corresponding to the {@link Control} is in an error state.
+ */
+ public static final int STATUS_ERROR = 3;
+
+ /**
+ * The {@link Control} is currently disabled.
+ */
+ public static final int STATUS_DISABLED = 4;
private final @NonNull String mControlId;
- private final @NonNull Icon mIcon;
+ private final @DeviceTypes.DeviceType int mDeviceType;
private final @NonNull CharSequence mTitle;
- private final @Nullable ColorStateList mTintColor;
+ private final @NonNull CharSequence mSubtitle;
+ private final @Nullable CharSequence mStructure;
+ private final @Nullable CharSequence mZone;
private final @NonNull PendingIntent mAppIntent;
- private final @ControlTemplate.TemplateType int mPrimaryType;
+ private final @Status int mStatus;
+ private final @NonNull ControlTemplate mControlTemplate;
+ private final @NonNull CharSequence mStatusText;
/**
* @param controlId the unique persistent identifier for this object.
- * @param icon an icon to display identifying the control.
+ * @param deviceType the type of device for this control. This will determine icons and colors.
* @param title the user facing name of this control (e.g. "Bedroom thermostat").
- * @param tintColor the color to tint parts of the element UI. If {@code null} is passed, the
- * system accent color will be used.
+ * @param subtitle a user facing subtitle with extra information about this control
+ * @param structure a user facing name for the structure containing the device associated with
+ * this control.
+ * @param zone
* @param appIntent a {@link PendingIntent} linking to a page to interact with the
* corresponding device.
- * @param primaryType the primary template for this type.
*/
public Control(@NonNull String controlId,
- @NonNull Icon icon,
+ @DeviceTypes.DeviceType int deviceType,
@NonNull CharSequence title,
- @Nullable ColorStateList tintColor,
+ @NonNull CharSequence subtitle,
+ @Nullable CharSequence structure,
+ @Nullable CharSequence zone,
@NonNull PendingIntent appIntent,
- int primaryType) {
+ @Status int status,
+ @NonNull ControlTemplate controlTemplate,
+ @NonNull CharSequence statusText) {
Preconditions.checkNotNull(controlId);
- Preconditions.checkNotNull(icon);
Preconditions.checkNotNull(title);
+ Preconditions.checkNotNull(subtitle);
Preconditions.checkNotNull(appIntent);
+ Preconditions.checkNotNull(controlTemplate);
+ Preconditions.checkNotNull(statusText);
mControlId = controlId;
- mIcon = icon;
+ if (!DeviceTypes.validDeviceType(deviceType)) {
+ Log.e(TAG, "Invalid device type:" + deviceType);
+ mDeviceType = DeviceTypes.TYPE_UNKNOWN;
+ } else {
+ mDeviceType = deviceType;
+ }
mTitle = title;
- mTintColor = tintColor;
+ mSubtitle = subtitle;
+ mStructure = structure;
+ mZone = zone;
mAppIntent = appIntent;
- mPrimaryType = primaryType;
+ if (status < 0 || status >= NUM_STATUS) {
+ mStatus = STATUS_UNKNOWN;
+ Log.e(TAG, "Status unknown:" + status);
+ } else {
+ mStatus = status;
+ }
+ mControlTemplate = controlTemplate;
+ mStatusText = statusText;
}
public Control(Parcel in) {
mControlId = in.readString();
- mIcon = Icon.CREATOR.createFromParcel(in);
+ mDeviceType = in.readInt();
mTitle = in.readCharSequence();
- if (in.readByte() == 1) {
- mTintColor = ColorStateList.CREATOR.createFromParcel(in);
+ mSubtitle = in.readCharSequence();
+ if (in.readByte() == (byte) 1) {
+ mStructure = in.readCharSequence();
+ } else {
+ mStructure = null;
+ }
+ if (in.readByte() == (byte) 1) {
+ mZone = in.readCharSequence();
} else {
- mTintColor = null;
+ mZone = null;
}
mAppIntent = PendingIntent.CREATOR.createFromParcel(in);
- mPrimaryType = in.readInt();
+ mStatus = in.readInt();
+ mControlTemplate = ControlTemplate.CREATOR.createFromParcel(in);
+ mStatusText = in.readCharSequence();
}
@NonNull
@@ -105,9 +178,9 @@ public class Control implements Parcelable {
return mControlId;
}
- @NonNull
- public Icon getIcon() {
- return mIcon;
+ @DeviceTypes.DeviceType
+ public int getDeviceType() {
+ return mDeviceType;
}
@NonNull
@@ -115,9 +188,19 @@ public class Control implements Parcelable {
return mTitle;
}
+ @NonNull
+ public CharSequence getSubtitle() {
+ return mSubtitle;
+ }
+
+ @Nullable
+ public CharSequence getStructure() {
+ return mStructure;
+ }
+
@Nullable
- public ColorStateList getTint() {
- return mTintColor;
+ public CharSequence getZone() {
+ return mZone;
}
@NonNull
@@ -125,9 +208,19 @@ public class Control implements Parcelable {
return mAppIntent;
}
- @ControlTemplate.TemplateType
- public int getPrimaryType() {
- return mPrimaryType;
+ @Status
+ public int getStatus() {
+ return mStatus;
+ }
+
+ @NonNull
+ public ControlTemplate getControlTemplate() {
+ return mControlTemplate;
+ }
+
+ @NonNull
+ public CharSequence getStatusText() {
+ return mStatusText;
}
@Override
@@ -138,16 +231,25 @@ public class Control implements Parcelable {
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mControlId);
- mIcon.writeToParcel(dest, flags);
+ dest.writeInt(mDeviceType);
dest.writeCharSequence(mTitle);
- if (mTintColor != null) {
+ dest.writeCharSequence(mSubtitle);
+ if (mStructure != null) {
dest.writeByte((byte) 1);
- mTintColor.writeToParcel(dest, flags);
+ dest.writeCharSequence(mStructure);
+ } else {
+ dest.writeByte((byte) 0);
+ }
+ if (mZone != null) {
+ dest.writeByte((byte) 1);
+ dest.writeCharSequence(mZone);
} else {
dest.writeByte((byte) 0);
}
mAppIntent.writeToParcel(dest, flags);
- dest.writeInt(mPrimaryType);
+ dest.writeInt(mStatus);
+ mControlTemplate.writeToParcel(dest, flags);
+ dest.writeCharSequence(mStatusText);
}
public static final Creator<Control> CREATOR = new Creator<Control>() {
@@ -165,69 +267,80 @@ public class Control implements Parcelable {
/**
* Builder class for {@link Control}.
*
- * This class facilitates the creation of {@link Control}. It provides the following
- * defaults for non-optional parameters:
+ * This class facilitates the creation of {@link Control} with no state.
+ * It provides the following defaults for non-optional parameters:
* <ul>
+ * <li> Device type: {@link DeviceTypes#TYPE_UNKNOWN}
* <li> Title: {@code ""}
- * <li> Primary template: {@link ControlTemplate#TYPE_NONE}
+ * <li> Subtitle: {@code ""}
+ * </ul>
+ * This fixes the values relating to state of the {@link Control} as required by
+ * {@link ControlsProviderService#onLoad}:
+ * <ul>
+ * <li> Status: {@link Status#STATUS_UNKNOWN}
+ * <li> Control template: {@link ControlTemplate#NO_TEMPLATE}
+ * <li> Status text: {@code ""}
* </ul>
*/
- public static class Builder {
- private String mControlId;
- private Icon mIcon;
- private CharSequence mTitle = "";
- private ColorStateList mTintColor;
- private @Nullable PendingIntent mAppIntent;
- private @ControlTemplate.TemplateType int mPrimaryType = ControlTemplate.TYPE_NONE;
+ public static class StatelessBuilder {
+ private static final String TAG = "StatelessBuilder";
+ protected @NonNull String mControlId;
+ protected @DeviceTypes.DeviceType int mDeviceType = DeviceTypes.TYPE_UNKNOWN;
+ protected @NonNull CharSequence mTitle = "";
+ protected @NonNull CharSequence mSubtitle = "";
+ protected @Nullable CharSequence mStructure;
+ protected @Nullable CharSequence mZone;
+ protected @NonNull PendingIntent mAppIntent;
+ protected @Status int mStatus = STATUS_UNKNOWN;
+ protected @NonNull ControlTemplate mControlTemplate = ControlTemplate.NO_TEMPLATE;
+ protected @NonNull CharSequence mStatusText = "";
/**
* @param controlId the identifier for the {@link Control}.
- * @param icon the icon for the {@link Control}.
* @param appIntent the pending intent linking to the device Activity.
*/
- public Builder(@NonNull String controlId,
- @NonNull Icon icon,
+ public StatelessBuilder(@NonNull String controlId,
@NonNull PendingIntent appIntent) {
Preconditions.checkNotNull(controlId);
- Preconditions.checkNotNull(icon);
Preconditions.checkNotNull(appIntent);
mControlId = controlId;
- mIcon = icon;
mAppIntent = appIntent;
}
/**
- * Creates a {@link Builder} using an existing {@link Control} as a base.
+ * Creates a {@link StatelessBuilder} using an existing {@link Control} as a base.
* @param control base for the builder.
*/
- public Builder(@NonNull Control control) {
+ public StatelessBuilder(@NonNull Control control) {
Preconditions.checkNotNull(control);
mControlId = control.mControlId;
- mIcon = control.mIcon;
+ mDeviceType = control.mDeviceType;
mTitle = control.mTitle;
- mTintColor = control.mTintColor;
+ mSubtitle = control.mSubtitle;
+ mStructure = control.mStructure;
+ mZone = control.mZone;
mAppIntent = control.mAppIntent;
- mPrimaryType = control.mPrimaryType;
}
/**
* @param controlId the identifier for the {@link Control}.
* @return {@code this}
*/
- public Builder setControlId(@NonNull String controlId) {
+ @NonNull
+ public StatelessBuilder setControlId(@NonNull String controlId) {
Preconditions.checkNotNull(controlId);
mControlId = controlId;
return this;
}
- /**
- * @param icon the icon for the {@link Control}
- * @return {@code this}
- */
@NonNull
- public Builder setIcon(@NonNull Icon icon) {
- Preconditions.checkNotNull(icon);
- mIcon = icon;
+ public StatelessBuilder setDeviceType(@DeviceTypes.DeviceType int deviceType) {
+ if (!DeviceTypes.validDeviceType(deviceType)) {
+ Log.e(TAG, "Invalid device type:" + deviceType);
+ mDeviceType = DeviceTypes.TYPE_UNKNOWN;
+ } else {
+ mDeviceType = deviceType;
+ }
return this;
}
@@ -236,20 +349,28 @@ public class Control implements Parcelable {
* @return {@code this}
*/
@NonNull
- public Builder setTitle(@NonNull CharSequence title) {
+ public StatelessBuilder setTitle(@NonNull CharSequence title) {
Preconditions.checkNotNull(title);
mTitle = title;
return this;
}
- /**
- * @param tint colors for tinting parts of the {@link Control} UI. Passing {@code null} will
- * default to using the current color accent.
- * @return {@code this}
- */
@NonNull
- public Builder setTint(@Nullable ColorStateList tint) {
- mTintColor = tint;
+ public StatelessBuilder setSubtitle(@NonNull CharSequence subtitle) {
+ Preconditions.checkNotNull(subtitle);
+ mSubtitle = subtitle;
+ return this;
+ }
+
+ @NonNull
+ public StatelessBuilder setStructure(@Nullable CharSequence structure) {
+ mStructure = structure;
+ return this;
+ }
+
+ @NonNull
+ public StatelessBuilder setZone(@Nullable CharSequence zone) {
+ mZone = zone;
return this;
}
@@ -258,29 +379,127 @@ public class Control implements Parcelable {
* @return {@code this}
*/
@NonNull
- public Builder setAppIntent(@NonNull PendingIntent appIntent) {
+ public StatelessBuilder setAppIntent(@NonNull PendingIntent appIntent) {
Preconditions.checkNotNull(appIntent);
mAppIntent = appIntent;
return this;
}
/**
- * @param type type to use as default in the {@link Control}
+ * Build a {@link Control}
+ * @return a valid {@link Control}
+ */
+ @NonNull
+ public Control build() {
+ return new Control(mControlId,
+ mDeviceType,
+ mTitle,
+ mSubtitle,
+ mStructure,
+ mZone,
+ mAppIntent,
+ mStatus,
+ mControlTemplate,
+ mStatusText);
+ }
+ }
+
+ public static class StatefulBuilder extends StatelessBuilder {
+ private static final String TAG = "StatefulBuilder";
+
+ /**
+ * @param controlId the identifier for the {@link Control}.
+ * @param appIntent the pending intent linking to the device Activity.
+ */
+ public StatefulBuilder(@NonNull String controlId,
+ @NonNull PendingIntent appIntent) {
+ super(controlId, appIntent);
+ }
+
+ public StatefulBuilder(@NonNull Control control) {
+ super(control);
+ mStatus = control.mStatus;
+ mControlTemplate = control.mControlTemplate;
+ mStatusText = control.mStatusText;
+ }
+
+ /**
+ * @param controlId the identifier for the {@link Control}.
* @return {@code this}
*/
@NonNull
- public Builder setPrimaryType(@ControlTemplate.TemplateType int type) {
- mPrimaryType = type;
+ public StatefulBuilder setControlId(@NonNull String controlId) {
+ super.setControlId(controlId);
+ return this;
+ }
+
+ @NonNull
+ public StatefulBuilder setDeviceType(@DeviceTypes.DeviceType int deviceType) {
+ super.setDeviceType(deviceType);
return this;
}
/**
- * Build a {@link Control}
- * @return a valid {@link Control}
+ * @param title the user facing name of the {@link Control}
+ * @return {@code this}
*/
@NonNull
- public Control build() {
- return new Control(mControlId, mIcon, mTitle, mTintColor, mAppIntent, mPrimaryType);
+ public StatefulBuilder setTitle(@NonNull CharSequence title) {
+ super.setTitle(title);
+ return this;
+ }
+
+ @NonNull
+ public StatefulBuilder setSubtitle(@NonNull CharSequence subtitle) {
+ super.setSubtitle(subtitle);
+ return this;
+ }
+
+ @NonNull
+ public StatefulBuilder setStructure(@Nullable CharSequence structure) {
+ super.setStructure(structure);
+ return this;
+ }
+
+ @NonNull
+ public StatefulBuilder setZone(@Nullable CharSequence zone) {
+ super.setZone(zone);
+ return this;
+ }
+
+ /**
+ * @param appIntent an {@link Intent} linking to an Activity for the {@link Control}
+ * @return {@code this}
+ */
+ @NonNull
+ public StatefulBuilder setAppIntent(@NonNull PendingIntent appIntent) {
+ super.setAppIntent(appIntent);
+ return this;
+ }
+
+ @NonNull
+ public StatefulBuilder setStatus(@Status int status) {
+ if (status < 0 || status >= NUM_STATUS) {
+ mStatus = STATUS_UNKNOWN;
+ Log.e(TAG, "Status unknown:" + status);
+ } else {
+ mStatus = status;
+ }
+ return this;
+ }
+
+ @NonNull
+ public StatefulBuilder setControlTemplate(@NonNull ControlTemplate controlTemplate) {
+ Preconditions.checkNotNull(controlTemplate);
+ mControlTemplate = controlTemplate;
+ return this;
+ }
+
+ @NonNull
+ public StatefulBuilder setStatusText(@NonNull CharSequence statusText) {
+ Preconditions.checkNotNull(statusText);
+ mStatusText = statusText;
+ return this;
}
}
}
diff --git a/core/java/android/service/controls/ControlState.java b/core/java/android/service/controls/ControlState.java
deleted file mode 100644
index f2410a8ea7c1..000000000000
--- a/core/java/android/service/controls/ControlState.java
+++ /dev/null
@@ -1,389 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.service.controls;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.app.PendingIntent;
-import android.content.res.ColorStateList;
-import android.graphics.drawable.Icon;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import com.android.internal.util.Preconditions;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Current state for a {@link Control}.
- *
- * Collects information to render the current state of a {@link Control} as well as possible action
- * that can be performed on it.
- * <p>
- * Additionally, this object is used to modify elements from the {@link Control} such as icons,
- * colors, names and intents. This information will last until it is again modified by a
- * {@link ControlState}.
- * @hide
- */
-public final class ControlState implements Parcelable {
-
- /**
- * @hide
- */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef({
- STATUS_OK,
- STATUS_NOT_FOUND,
- STATUS_ERROR,
- STATUS_DISABLED,
- })
- public @interface Status {};
-
- /**
- * The device corresponding to the {@link Control} is responding correctly.
- */
- public static final int STATUS_OK = 0;
-
- /**
- * The device corresponding to the {@link Control} cannot be found or was removed.
- */
- public static final int STATUS_NOT_FOUND = 1;
-
- /**
- * The device corresponding to the {@link Control} is in an error state.
- */
- public static final int STATUS_ERROR = 2;
-
- /**
- * The {@link Control} is currently disabled.
- */
- public static final int STATUS_DISABLED = 3;
-
- private final @NonNull String mControlId;
- private final @Status int mStatus;
- private final @NonNull ControlTemplate mControlTemplate;
- private final @NonNull CharSequence mStatusText;
- private final @Nullable CharSequence mTitle;
- private final @Nullable PendingIntent mAppIntent;
- private final @Nullable Icon mIcon;
- private final @Nullable ColorStateList mTint;
-
- /**
- * @param controlId the identifier of the {@link Control} this object refers to.
- * @param status the current status of the {@link Control}.
- * @param controlTemplate the template to be used to render the {@link Control}. This can be
- * of a different
- * {@link android.service.controls.ControlTemplate.TemplateType} than the
- * one defined in {@link Control#getPrimaryType}
- * @param statusText the user facing text describing the current status.
- * @param title the title to replace the one set in the {@link Control} or set in the
- * last {@link ControlState}. Pass {@code null} to use the last value set for this
- * {@link Control}
- * @param appIntent the {@link PendingIntent} to replace the one set in the {@link Control} or
- * set in the last {@link ControlState}. Pass {@code null} to use the last
- * value set for this {@link Control}.
- * @param icon the icon to replace the one set in the {@link Control} or set in the last
- * {@link ControlState}. Pass {@code null} to use the last value set for this
- * {@link Control}.
- * @param tint the colors to replace those set in the {@link Control} or set in the last
- * {@link ControlState}. Pass {@code null} to use the last value set for this
- * {@link Control}.
- */
- public ControlState(@NonNull String controlId,
- int status,
- @NonNull ControlTemplate controlTemplate,
- @NonNull CharSequence statusText,
- @Nullable CharSequence title,
- @Nullable PendingIntent appIntent,
- @Nullable Icon icon,
- @Nullable ColorStateList tint) {
- Preconditions.checkNotNull(controlId);
- Preconditions.checkNotNull(controlTemplate);
- Preconditions.checkNotNull(statusText);
- mControlId = controlId;
- mStatus = status;
- mControlTemplate = controlTemplate;
- mStatusText = statusText;
- mTitle = title;
- mAppIntent = appIntent;
- mIcon = icon;
- mTint = tint;
- }
-
- ControlState(Parcel in) {
- mControlId = in.readString();
- mStatus = in.readInt();
- mControlTemplate = ControlTemplate.CREATOR.createFromParcel(in);
- mStatusText = in.readCharSequence();
- if (in.readByte() == 1) {
- mTitle = in.readCharSequence();
- } else {
- mTitle = null;
- }
- if (in.readByte() == 1) {
- mAppIntent = PendingIntent.CREATOR.createFromParcel(in);
- } else {
- mAppIntent = null;
- }
- if (in.readByte() == 1) {
- mIcon = Icon.CREATOR.createFromParcel(in);
- } else {
- mIcon = null;
- }
- if (in.readByte() == 1) {
- mTint = ColorStateList.CREATOR.createFromParcel(in);
- } else {
- mTint = null;
- }
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @NonNull
- public String getControlId() {
- return mControlId;
- }
-
- @Nullable
- public CharSequence getTitle() {
- return mTitle;
- }
-
- @Nullable
- public PendingIntent getAppIntent() {
- return mAppIntent;
- }
-
- @Status
- public int getStatus() {
- return mStatus;
- }
-
- @NonNull
- public ControlTemplate getControlTemplate() {
- return mControlTemplate;
- }
-
- @Nullable
- public Icon getIcon() {
- return mIcon;
- }
-
- @NonNull
- public CharSequence getStatusText() {
- return mStatusText;
- }
-
- @Nullable
- public ColorStateList getTint() {
- return mTint;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(mControlId);
- dest.writeInt(mStatus);
- mControlTemplate.writeToParcel(dest, flags);
- dest.writeCharSequence(mStatusText);
- if (mTitle != null) {
- dest.writeByte((byte) 1);
- dest.writeCharSequence(mTitle);
- } else {
- dest.writeByte((byte) 0);
- }
- if (mAppIntent != null) {
- dest.writeByte((byte) 1);
- mAppIntent.writeToParcel(dest, flags);
- }
- if (mIcon != null) {
- dest.writeByte((byte) 1);
- mIcon.writeToParcel(dest, flags);
- } else {
- dest.writeByte((byte) 0);
- }
- if (mTint != null) {
- dest.writeByte((byte) 1);
- mTint.writeToParcel(dest, flags);
- } else {
- dest.writeByte((byte) 0);
- }
- }
-
- public static final Creator<ControlState> CREATOR = new Creator<ControlState>() {
- @Override
- public ControlState createFromParcel(Parcel source) {
- return new ControlState(source);
- }
-
- @Override
- public ControlState[] newArray(int size) {
- return new ControlState[size];
- }
- };
-
- /**
- * Builder class for {@link ControlState}.
- *
- * This class facilitates the creation of {@link ControlState}. It provides the following
- * defaults for non-optional parameters:
- * <ul>
- * <li> Status: {@link ControlState#STATUS_OK}
- * <li> Control template: {@link ControlTemplate#NO_TEMPLATE}
- * <li> Status text: {@code ""}
- * </ul>
- */
- public static class Builder {
- private @NonNull String mControlId;
- private @Status int mStatus = STATUS_OK;
- private @NonNull ControlTemplate mControlTemplate = ControlTemplate.NO_TEMPLATE;
- private @NonNull CharSequence mStatusText = "";
- private @Nullable CharSequence mTitle;
- private @Nullable PendingIntent mAppIntent;
- private @Nullable Icon mIcon;
- private @Nullable ColorStateList mTint;
-
- /**
- * @param controlId the identifier of the {@link Control} that the resulting
- * {@link ControlState} refers to.
- */
- public Builder(@NonNull String controlId) {
- Preconditions.checkNotNull(controlId);
- mControlId = controlId;
- }
-
- /**
- * Creates a {@link Builder} using an existing {@link ControlState} as a base.
- * @param controlState base for the builder.
- */
- public Builder(@NonNull ControlState controlState) {
- Preconditions.checkNotNull(controlState);
- mControlId = controlState.mControlId;
- mStatus = controlState.mStatus;
- mControlTemplate = controlState.mControlTemplate;
- mStatusText = controlState.mStatusText;
- mTitle = controlState.mTitle;
- mAppIntent = controlState.mAppIntent;
- mIcon = controlState.mIcon;
- mTint = controlState.mTint;
- }
-
-
- /**
- * @param controlId the identifier of the {@link Control} for the resulting object.
- * @return {@code this}
- */
- @NonNull
- public Builder setControlId(@NonNull String controlId) {
- mControlId = controlId;
- return this;
- }
-
- /**
- * @param status the current status of the {@link Control}
- * @return {@code this}
- */
- @NonNull
- public Builder setStatus(@Status int status) {
- mStatus = status;
- return this;
- }
-
- /**
- * @param controlTemplate the template to use when rendering the {@code Control}.
- * @return {@code this}
- */
- @NonNull
- public Builder setControlTemplate(@NonNull ControlTemplate controlTemplate) {
- Preconditions.checkNotNull(controlTemplate);
- mControlTemplate = controlTemplate;
- return this;
- }
-
- /**
- * @param statusText the user-visible description of the status.
- * @return {@code this}
- */
- @NonNull
- public Builder setStatusText(@NonNull CharSequence statusText) {
- Preconditions.checkNotNull(statusText);
- mStatusText = statusText;
- return this;
- }
-
- /**
- * @param title the title to replace the one defined in the corresponding {@link Control} or
- * set by the last {@link ControlState}. Pass {@code null} to keep the last
- * value.
- * @return {@code this}
- */
- @NonNull
- public Builder setTitle(@Nullable CharSequence title) {
- mTitle = title;
- return this;
- }
-
- /**
- * @param appIntent the Pending Intent to replace the one defined in the corresponding
- * {@link Control} or set by the last {@link ControlState}. Pass
- * {@code null} to keep the last value.
- * @return {@code this}
- */
- @NonNull
- public Builder setAppIntent(@Nullable PendingIntent appIntent) {
- mAppIntent = appIntent;
- return this;
- }
-
- /**
- * @param icon the title to replace the one defined in the corresponding {@link Control} or
- * set by the last {@link ControlState}. Pass {@code null} to keep the last
- * value.
- * @return {@code this}
- */
- @NonNull
- public Builder setIcon(@Nullable Icon icon) {
- mIcon = icon;
- return this;
- }
-
- /**
- * @param tint the title to replace the one defined in the corresponding {@link Control} or
- * set by the last {@link ControlState}. Pass {@code null} to keep the last
- * value.
- * @return {@code this}
- */
- @NonNull
- public Builder setTint(@Nullable ColorStateList tint) {
- mTint = tint;
- return this;
- }
-
- /**
- * @return a new {@link ControlState}
- */
- public ControlState build() {
- return new ControlState(mControlId, mStatus, mControlTemplate, mStatusText,
- mTitle, mAppIntent, mIcon, mTint);
- }
- }
-}
-
diff --git a/core/java/android/service/controls/ControlsProviderService.java b/core/java/android/service/controls/ControlsProviderService.java
new file mode 100644
index 000000000000..258ef23c64cf
--- /dev/null
+++ b/core/java/android/service/controls/ControlsProviderService.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.service.controls;
+
+import android.annotation.NonNull;
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
+import android.app.Service;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.service.controls.actions.ControlAction;
+import android.service.controls.templates.ControlTemplate;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Service implementation allowing applications to contribute controls to the
+ * System UI.
+ * @hide
+ */
+public abstract class ControlsProviderService extends Service {
+
+ @SdkConstant(SdkConstantType.SERVICE_ACTION)
+ public static final String CONTROLS_ACTION = "android.service.controls.ControlsProviderService";
+ public static final String CALLBACK_BUNDLE = "CALLBACK_BUNDLE";
+ public static final String CALLBACK_BINDER = "CALLBACK_BINDER";
+ public static final String CALLBACK_TOKEN = "CALLBACK_TOKEN";
+
+ public final String TAG = getClass().getSimpleName();
+
+ private IControlsProviderCallback mCallback;
+ private IBinder mToken;
+ private RequestHandler mHandler;
+
+ /**
+ * Signal to retrieve all Controls. When complete, call
+ * {@link IControlsProviderCallback#onLoad} to inform the caller.
+ */
+ public abstract void load();
+
+ /**
+ * Informs the service that the caller is listening for updates to the given controlIds.
+ * {@link IControlsProviderCallback#onRefreshState} should be called any time
+ * there are Control updates to render.
+ */
+ public abstract void subscribe(@NonNull List<String> controlIds);
+
+ /**
+ * Informs the service that the caller is done listening for updates,
+ * and any calls to {@link IControlsProviderCallback#onRefreshState} will be ignored.
+ */
+ public abstract void unsubscribe();
+
+ /**
+ * The user has interacted with a Control. The action is dictated by the type of
+ * {@link ControlAction} that was sent.
+ */
+ public abstract void onAction(@NonNull String controlId, @NonNull ControlAction action);
+
+ /**
+ * Sends a list of the controls available from this service.
+ *
+ * The items in the list must not have state information (as created by
+ * {@link Control.StatelessBuilder}).
+ * @param controls
+ */
+ public void onLoad(@NonNull List<Control> controls) {
+ Preconditions.checkNotNull(controls);
+ List<Control> list = new ArrayList<>();
+ for (Control control: controls) {
+ if (control == null) {
+ Log.e(TAG, "onLoad: null control.");
+ }
+ if (isStateless(control)) {
+ list.add(control);
+ } else {
+ Log.w(TAG, "onLoad: control is not stateless.");
+ list.add(new Control.StatelessBuilder(control).build());
+ }
+ }
+ try {
+ mCallback.onLoad(mToken, list);
+ } catch (RemoteException ex) {
+ ex.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
+ * Sends a list of the controls requested by {@link ControlsProviderService#subscribe} with
+ * their state.
+ * @param statefulControls
+ */
+ public void onRefreshState(@NonNull List<Control> statefulControls) {
+ Preconditions.checkNotNull(statefulControls);
+ try {
+ mCallback.onRefreshState(mToken, statefulControls);
+ } catch (RemoteException ex) {
+ ex.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
+ * Sends the response of a command in the specified {@link Control}.
+ * @param controlId
+ * @param response
+ */
+ public void onControlActionResponse(
+ @NonNull String controlId, @ControlAction.ResponseResult int response) {
+ Preconditions.checkNotNull(controlId);
+ if (!ControlAction.isValidResponse(response)) {
+ Log.e(TAG, "Not valid response result: " + response);
+ response = ControlAction.RESPONSE_UNKNOWN;
+ }
+ try {
+ mCallback.onControlActionResponse(mToken, controlId, response);
+ } catch (RemoteException ex) {
+ ex.rethrowAsRuntimeException();
+ }
+ }
+
+ private boolean isStateless(Control control) {
+ return (control.getStatus() == Control.STATUS_UNKNOWN
+ && control.getControlTemplate().getTemplateType() == ControlTemplate.TYPE_NONE
+ && TextUtils.isEmpty(control.getStatusText()));
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ mHandler = new RequestHandler(Looper.getMainLooper());
+
+ Bundle bundle = intent.getBundleExtra(CALLBACK_BUNDLE);
+ IBinder callbackBinder = bundle.getBinder(CALLBACK_BINDER);
+ mToken = bundle.getBinder(CALLBACK_TOKEN);
+ mCallback = IControlsProviderCallback.Stub.asInterface(callbackBinder);
+
+ return new IControlsProvider.Stub() {
+ public void load() {
+ mHandler.sendEmptyMessage(RequestHandler.MSG_LOAD);
+ }
+
+ public void subscribe(List<String> ids) {
+ mHandler.obtainMessage(RequestHandler.MSG_SUBSCRIBE, ids).sendToTarget();
+ }
+
+ public void unsubscribe() {
+ mHandler.sendEmptyMessage(RequestHandler.MSG_UNSUBSCRIBE);
+ }
+
+ public void onAction(String id, ControlAction action) {
+ ActionMessage msg = new ActionMessage(id, action);
+ mHandler.obtainMessage(RequestHandler.MSG_ON_ACTION, msg).sendToTarget();
+ }
+ };
+ }
+
+ @Override
+ public boolean onUnbind(Intent intent) {
+ mCallback = null;
+ mHandler = null;
+ return true;
+ }
+
+ private class RequestHandler extends Handler {
+ private static final int MSG_LOAD = 1;
+ private static final int MSG_SUBSCRIBE = 2;
+ private static final int MSG_UNSUBSCRIBE = 3;
+ private static final int MSG_ON_ACTION = 4;
+
+ RequestHandler(Looper looper) {
+ super(looper);
+ }
+
+ public void handleMessage(Message msg) {
+ switch(msg.what) {
+ case MSG_LOAD:
+ ControlsProviderService.this.load();
+ break;
+ case MSG_SUBSCRIBE:
+ List<String> ids = (List<String>) msg.obj;
+ ControlsProviderService.this.subscribe(ids);
+ break;
+ case MSG_UNSUBSCRIBE:
+ ControlsProviderService.this.unsubscribe();
+ break;
+ case MSG_ON_ACTION:
+ ActionMessage aMsg = (ActionMessage) msg.obj;
+ ControlsProviderService.this.onAction(aMsg.mId, aMsg.mAction);
+ break;
+ }
+ }
+ }
+
+ private class ActionMessage {
+ final String mId;
+ final ControlAction mAction;
+
+ ActionMessage(String id, ControlAction action) {
+ this.mId = id;
+ this.mAction = action;
+ }
+ }
+}
diff --git a/core/java/android/service/controls/DeviceTypes.java b/core/java/android/service/controls/DeviceTypes.java
new file mode 100644
index 000000000000..b2d1c08d65ba
--- /dev/null
+++ b/core/java/android/service/controls/DeviceTypes.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.controls;
+
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * @hide
+ */
+public class DeviceTypes {
+
+ // Update this when adding new concrete types. Does not count TYPE_UNKNOWN
+ private static final int NUM_CONCRETE_TYPES = 51;
+
+ public static final @DeviceType int TYPE_UNKNOWN = 0;
+ public static final @DeviceType int TYPE_AC_HEATER = 1;
+ public static final @DeviceType int TYPE_AC_UNIT = 2;
+ public static final @DeviceType int TYPE_AIR_FRESHENER = 3;
+ public static final @DeviceType int TYPE_AIR_PURIFIER = 4;
+ public static final @DeviceType int TYPE_COFFEE_MAKER = 5;
+ public static final @DeviceType int TYPE_DEHUMIDIFIER = 6;
+ public static final @DeviceType int TYPE_DISPLAY = 7;
+ public static final @DeviceType int TYPE_FAN = 8;
+ public static final @DeviceType int TYPE_HOOD = 10;
+ public static final @DeviceType int TYPE_HUMIDIFIER = 11;
+ public static final @DeviceType int TYPE_KETTLE = 12;
+ public static final @DeviceType int TYPE_LIGHT = 13;
+ public static final @DeviceType int TYPE_MICROWAVE = 14;
+ public static final @DeviceType int TYPE_OUTLET = 15;
+ public static final @DeviceType int TYPE_RADIATOR = 16;
+ public static final @DeviceType int TYPE_REMOTE_CONTROL = 17;
+ public static final @DeviceType int TYPE_SET_TOP = 18;
+ public static final @DeviceType int TYPE_STANDMIXER = 19;
+ public static final @DeviceType int TYPE_STYLER = 20;
+ public static final @DeviceType int TYPE_SWITCH = 21;
+ public static final @DeviceType int TYPE_TV = 22;
+ public static final @DeviceType int TYPE_WATER_HEATER = 23;
+
+ public static final @DeviceType int TYPE_DISHWASHER = 24;
+ public static final @DeviceType int TYPE_DRYER = 25;
+ public static final @DeviceType int TYPE_MOP = 26;
+ public static final @DeviceType int TYPE_MOWER = 27;
+ public static final @DeviceType int TYPE_MULTICOOKER = 28;
+ public static final @DeviceType int TYPE_SHOWER = 29;
+ public static final @DeviceType int TYPE_SPRINKLER = 30;
+ public static final @DeviceType int TYPE_WASHER = 31;
+ public static final @DeviceType int TYPE_VACUUM = 32;
+
+ public static final @DeviceType int TYPE_AWNING = 33;
+ public static final @DeviceType int TYPE_BLINDS = 34;
+ public static final @DeviceType int TYPE_CLOSET = 35;
+ public static final @DeviceType int TYPE_CURTAIN = 36;
+ public static final @DeviceType int TYPE_DOOR = 37;
+ public static final @DeviceType int TYPE_DRAWER = 38;
+ public static final @DeviceType int TYPE_GARAGE = 39;
+ public static final @DeviceType int TYPE_GATE = 40;
+ public static final @DeviceType int TYPE_PERGOLA = 41;
+ public static final @DeviceType int TYPE_SHUTTER = 42;
+ public static final @DeviceType int TYPE_WINDOW = 43;
+ public static final @DeviceType int TYPE_VALVE = 44;
+
+ public static final @DeviceType int TYPE_LOCK = 45;
+
+ public static final @DeviceType int TYPE_SECURITY_SYSTEM = 46;
+
+ public static final @DeviceType int TYPE_HEATER = 47;
+ public static final @DeviceType int TYPE_REFRIGERATOR = 48;
+ public static final @DeviceType int TYPE_THERMOSTAT = 49;
+
+ public static final @DeviceType int TYPE_CAMERA = 50;
+ public static final @DeviceType int TYPE_DOORBELL = 51;
+
+ // Update this when adding new generic types.
+ private static final int NUM_GENERIC_TYPES = 7;
+ public static final @DeviceType int TYPE_GENERIC_ON_OFF = -1;
+ public static final @DeviceType int TYPE_GENERIC_START_STOP = -2;
+ public static final @DeviceType int TYPE_GENERIC_OPEN_CLOSE = -3;
+ public static final @DeviceType int TYPE_GENERIC_LOCK_UNLOCK = -4;
+ public static final @DeviceType int TYPE_GENERIC_ARM_DISARM = -5;
+ public static final @DeviceType int TYPE_GENERIC_TEMP_SETTING = -6;
+ public static final @DeviceType int TYPE_GENERIC_VIEWSTREAM = -7;
+
+ public static boolean validDeviceType(int deviceType) {
+ return deviceType >= -NUM_GENERIC_TYPES && deviceType <= NUM_CONCRETE_TYPES;
+ }
+
+ /**
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ TYPE_GENERIC_ON_OFF,
+ TYPE_GENERIC_START_STOP,
+ TYPE_GENERIC_OPEN_CLOSE,
+ TYPE_GENERIC_LOCK_UNLOCK,
+ TYPE_GENERIC_ARM_DISARM,
+ TYPE_GENERIC_TEMP_SETTING,
+ TYPE_GENERIC_VIEWSTREAM,
+
+ TYPE_UNKNOWN,
+
+ TYPE_AC_HEATER,
+ TYPE_AC_UNIT,
+ TYPE_AIR_FRESHENER,
+ TYPE_AIR_PURIFIER,
+ TYPE_COFFEE_MAKER,
+ TYPE_DEHUMIDIFIER,
+ TYPE_DISPLAY,
+ TYPE_FAN,
+ TYPE_HOOD,
+ TYPE_HUMIDIFIER,
+ TYPE_KETTLE,
+ TYPE_LIGHT,
+ TYPE_MICROWAVE,
+ TYPE_OUTLET,
+ TYPE_RADIATOR,
+ TYPE_REMOTE_CONTROL,
+ TYPE_SET_TOP,
+ TYPE_STANDMIXER,
+ TYPE_STYLER,
+ TYPE_SWITCH,
+ TYPE_TV,
+ TYPE_WATER_HEATER,
+ TYPE_DISHWASHER,
+ TYPE_DRYER,
+ TYPE_MOP,
+ TYPE_MOWER,
+ TYPE_MULTICOOKER,
+ TYPE_SHOWER,
+ TYPE_SPRINKLER,
+ TYPE_WASHER,
+ TYPE_VACUUM,
+ TYPE_AWNING,
+ TYPE_BLINDS,
+ TYPE_CLOSET,
+ TYPE_CURTAIN,
+ TYPE_DOOR,
+ TYPE_DRAWER,
+ TYPE_GARAGE,
+ TYPE_GATE,
+ TYPE_PERGOLA,
+ TYPE_SHUTTER,
+ TYPE_WINDOW,
+ TYPE_VALVE,
+ TYPE_LOCK,
+ TYPE_SECURITY_SYSTEM,
+ TYPE_HEATER,
+ TYPE_REFRIGERATOR,
+ TYPE_THERMOSTAT,
+ TYPE_CAMERA,
+ TYPE_DOORBELL
+ })
+ public @interface DeviceType {}
+
+ private DeviceTypes() {}
+}
diff --git a/core/java/android/service/controls/IControlsProvider.aidl b/core/java/android/service/controls/IControlsProvider.aidl
index f778653eb3d3..6c105bb20c80 100644
--- a/core/java/android/service/controls/IControlsProvider.aidl
+++ b/core/java/android/service/controls/IControlsProvider.aidl
@@ -16,7 +16,7 @@
package android.service.controls;
-import android.service.controls.ControlAction;
+import android.service.controls.actions.ControlAction;
/** @hide */
oneway interface IControlsProvider {
diff --git a/core/java/android/service/controls/IControlsProviderCallback.aidl b/core/java/android/service/controls/IControlsProviderCallback.aidl
index 3dbb68c1c7f0..91f6a7980ce6 100644
--- a/core/java/android/service/controls/IControlsProviderCallback.aidl
+++ b/core/java/android/service/controls/IControlsProviderCallback.aidl
@@ -17,13 +17,12 @@
package android.service.controls;
import android.service.controls.Control;
-import android.service.controls.ControlState;
/** @hide */
oneway interface IControlsProviderCallback {
- void onLoad(in List<Control> controls);
+ void onLoad(in IBinder token, in List<Control> controls);
- void onRefreshState(in List<ControlState> controlStates);
+ void onRefreshState(in IBinder token, in List<Control> statefulControls);
- void onControlActionResponse(in String controlId, int response);
+ void onControlActionResponse(in IBinder token, in String controlId, int response);
} \ No newline at end of file
diff --git a/core/java/android/service/controls/BooleanAction.aidl b/core/java/android/service/controls/actions/BooleanAction.aidl
index 730ad36749f7..d1e7e02730cc 100644
--- a/core/java/android/service/controls/BooleanAction.aidl
+++ b/core/java/android/service/controls/actions/BooleanAction.aidl
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.service.controls;
+package android.service.controls.actions;
parcelable BooleanAction; \ No newline at end of file
diff --git a/core/java/android/service/controls/BooleanAction.java b/core/java/android/service/controls/actions/BooleanAction.java
index 877f82e96174..fb2c5ad99659 100644
--- a/core/java/android/service/controls/BooleanAction.java
+++ b/core/java/android/service/controls/actions/BooleanAction.java
@@ -14,12 +14,13 @@
* limitations under the License.
*/
-package android.service.controls;
+package android.service.controls.actions;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Bundle;
import android.os.Parcel;
+import android.service.controls.templates.ToggleTemplate;
/**
* Action sent by a {@link ToggleTemplate}
@@ -27,6 +28,7 @@ import android.os.Parcel;
*/
public final class BooleanAction extends ControlAction {
+ private static final @ActionType int TYPE = TYPE_BOOLEAN;
private static final String KEY_NEW_STATE = "key_new_state";
private final boolean mNewState;
@@ -41,15 +43,15 @@ public final class BooleanAction extends ControlAction {
/**
* @param templateId the identifier of the {@link ToggleTemplate} that originated this action.
- * @param newValue new value for the state displayed by the {@link ToggleTemplate}.
+ * @param newState new value for the state displayed by the {@link ToggleTemplate}.
* @param challengeValue a value sent by the user along with the action to authenticate. {@code}
* null is sent when no authentication is needed or has not been
* requested.
*/
- public BooleanAction(@NonNull String templateId, boolean newValue,
+ public BooleanAction(@NonNull String templateId, boolean newState,
@Nullable String challengeValue) {
super(templateId, challengeValue);
- mNewState = newValue;
+ mNewState = newState;
}
BooleanAction(Bundle b) {
@@ -72,7 +74,7 @@ public final class BooleanAction extends ControlAction {
*/
@Override
public int getActionType() {
- return ControlAction.TYPE_BOOLEAN;
+ return TYPE;
}
@Override
@@ -85,6 +87,8 @@ public final class BooleanAction extends ControlAction {
public static final @NonNull Creator<BooleanAction> CREATOR = new Creator<BooleanAction>() {
@Override
public BooleanAction createFromParcel(Parcel source) {
+ int type = source.readInt();
+ verifyType(type, TYPE);
return new BooleanAction(source.readBundle());
}
diff --git a/core/java/android/service/controls/actions/CommandAction.aidl b/core/java/android/service/controls/actions/CommandAction.aidl
new file mode 100644
index 000000000000..7c1ee41fb8c3
--- /dev/null
+++ b/core/java/android/service/controls/actions/CommandAction.aidl
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.service.controls.actions;
+
+parcelable CommandAction; \ No newline at end of file
diff --git a/core/java/android/service/controls/actions/CommandAction.java b/core/java/android/service/controls/actions/CommandAction.java
new file mode 100644
index 000000000000..c69c53976349
--- /dev/null
+++ b/core/java/android/service/controls/actions/CommandAction.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.controls.actions;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Bundle;
+import android.os.Parcel;
+
+/**
+ * @hide
+ */
+public final class CommandAction extends ControlAction {
+
+ private static final @ActionType int TYPE = TYPE_COMMAND;
+
+ public CommandAction(@NonNull String templateId, @Nullable String challengeValue) {
+ super(templateId, challengeValue);
+ }
+
+ public CommandAction(@NonNull String templateId) {
+ this(templateId, null);
+ }
+
+ public CommandAction(Bundle b) {
+ super(b);
+ }
+
+ @Override
+ public int getActionType() {
+ return TYPE;
+ }
+
+ public static final Creator<CommandAction> CREATOR = new Creator<CommandAction>() {
+ @Override
+ public CommandAction createFromParcel(Parcel source) {
+ int type = source.readInt();
+ verifyType(type, TYPE);
+ return new CommandAction(source.readBundle());
+ }
+
+ @Override
+ public CommandAction[] newArray(int size) {
+ return new CommandAction[size];
+ }
+ };
+}
diff --git a/core/java/android/service/controls/ControlAction.aidl b/core/java/android/service/controls/actions/ControlAction.aidl
index e1a5276b70d6..b012521c7255 100644
--- a/core/java/android/service/controls/ControlAction.aidl
+++ b/core/java/android/service/controls/actions/ControlAction.aidl
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.service.controls;
+package android.service.controls.actions;
parcelable ControlAction; \ No newline at end of file
diff --git a/core/java/android/service/controls/ControlAction.java b/core/java/android/service/controls/actions/ControlAction.java
index 0a7c97c1bbc9..83d1cf824f1f 100644
--- a/core/java/android/service/controls/ControlAction.java
+++ b/core/java/android/service/controls/actions/ControlAction.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.service.controls;
+package android.service.controls.actions;
import android.annotation.CallSuper;
import android.annotation.IntDef;
@@ -23,6 +23,8 @@ import android.annotation.Nullable;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
+import android.service.controls.IControlsProviderCallback;
+import android.service.controls.templates.ControlTemplate;
import com.android.internal.util.Preconditions;
@@ -41,13 +43,6 @@ public abstract class ControlAction implements Parcelable {
private static final String KEY_TEMPLATE_ID = "key_template_id";
private static final String KEY_CHALLENGE_VALUE = "key_challenge_value";
- public static final ControlAction UNKNOWN_ACTION = new ControlAction() {
-
- @Override
- public int getActionType() {
- return TYPE_UNKNOWN;
- }
- };
/**
* @hide
@@ -56,9 +51,19 @@ public abstract class ControlAction implements Parcelable {
@IntDef({
TYPE_UNKNOWN,
TYPE_BOOLEAN,
- TYPE_FLOAT
+ TYPE_FLOAT,
+ TYPE_MULTI_FLOAT,
+ TYPE_MODE,
+ TYPE_COMMAND
})
public @interface ActionType {};
+ public static final ControlAction UNKNOWN_ACTION = new ControlAction() {
+
+ @Override
+ public int getActionType() {
+ return TYPE_UNKNOWN;
+ }
+ };
public static final @ActionType int TYPE_UNKNOWN = 0;
/**
@@ -71,11 +76,23 @@ public abstract class ControlAction implements Parcelable {
*/
public static final @ActionType int TYPE_FLOAT = 2;
+ public static final @ActionType int TYPE_MULTI_FLOAT = 3;
+
+ public static final @ActionType int TYPE_MODE = 4;
+
+ public static final @ActionType int TYPE_COMMAND = 5;
+
+
+ public static final boolean isValidResponse(@ResponseResult int response) {
+ return (response >= 0 && response < NUM_RESPONSE_TYPES);
+ }
+ private static final int NUM_RESPONSE_TYPES = 6;
/**
* @hide
*/
@Retention(RetentionPolicy.SOURCE)
@IntDef({
+ RESPONSE_UNKNOWN,
RESPONSE_OK,
RESPONSE_FAIL,
RESPONSE_CHALLENGE_ACK,
@@ -84,31 +101,33 @@ public abstract class ControlAction implements Parcelable {
})
public @interface ResponseResult {};
+ public static final @ResponseResult int RESPONSE_UNKNOWN = 0;
+
/**
* Response code for {@link IControlsProviderCallback#onControlActionResponse} indicating that
* the action has been performed. The action may still fail later and the state may not change.
*/
- public static final @ResponseResult int RESPONSE_OK = 0;
+ public static final @ResponseResult int RESPONSE_OK = 1;
/**
* Response code for {@link IControlsProviderCallback#onControlActionResponse} indicating that
* the action has failed.
*/
- public static final @ResponseResult int RESPONSE_FAIL = 1;
+ public static final @ResponseResult int RESPONSE_FAIL = 2;
/**
* Response code for {@link IControlsProviderCallback#onControlActionResponse} indicating that
* in order for the action to be performed, acknowledgment from the user is required.
*/
- public static final @ResponseResult int RESPONSE_CHALLENGE_ACK = 2;
+ public static final @ResponseResult int RESPONSE_CHALLENGE_ACK = 3;
/**
* Response code for {@link IControlsProviderCallback#onControlActionResponse} indicating that
* in order for the action to be performed, a PIN is required.
*/
- public static final @ResponseResult int RESPONSE_CHALLENGE_PIN = 3;
+ public static final @ResponseResult int RESPONSE_CHALLENGE_PIN = 4;
/**
* Response code for {@link IControlsProviderCallback#onControlActionResponse} indicating that
* in order for the action to be performed, an alphanumeric passphrase is required.
*/
- public static final @ResponseResult int RESPONSE_CHALLENGE_PASSPHRASE = 4;
+ public static final @ResponseResult int RESPONSE_CHALLENGE_PASSPHRASE = 5;
/**
* The {@link ActionType} associated with this class.
@@ -199,13 +218,25 @@ public abstract class ControlAction implements Parcelable {
private static ControlAction createActionFromType(@ActionType int type, Parcel source) {
switch(type) {
case TYPE_BOOLEAN:
- return BooleanAction.CREATOR.createFromParcel(source);
+ return new BooleanAction(source.readBundle());
case TYPE_FLOAT:
- return FloatAction.CREATOR.createFromParcel(source);
+ return new FloatAction(source.readBundle());
+ case TYPE_MULTI_FLOAT:
+ return new MultiFloatAction(source.readBundle());
+ case TYPE_MODE:
+ return new ModeAction(source.readBundle());
+ case TYPE_COMMAND:
+ return new CommandAction(source.readBundle());
default:
source.readBundle();
return UNKNOWN_ACTION;
}
}
+ protected static void verifyType(@ActionType int type, @ActionType int thisType) {
+ if (type != thisType) {
+ throw new IllegalStateException("The type " + type + "does not match " + thisType);
+ }
+ }
+
}
diff --git a/core/java/android/service/controls/FloatAction.aidl b/core/java/android/service/controls/actions/FloatAction.aidl
index dbc0f726880c..2c1e76d68803 100644
--- a/core/java/android/service/controls/FloatAction.aidl
+++ b/core/java/android/service/controls/actions/FloatAction.aidl
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.service.controls;
+package android.service.controls.actions;
parcelable FloatAction; \ No newline at end of file
diff --git a/core/java/android/service/controls/FloatAction.java b/core/java/android/service/controls/actions/FloatAction.java
index 229435f647a2..1c3fb4d39744 100644
--- a/core/java/android/service/controls/FloatAction.java
+++ b/core/java/android/service/controls/actions/FloatAction.java
@@ -14,19 +14,22 @@
* limitations under the License.
*/
-package android.service.controls;
+package android.service.controls.actions;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Bundle;
import android.os.Parcel;
+import android.service.controls.templates.RangeTemplate;
+import android.service.controls.templates.ToggleRangeTemplate;
/**
- * Action sent by a {@link RangeTemplate}.
+ * Action sent by a {@link RangeTemplate}, {@link ToggleRangeTemplate}.
* @hide
*/
public final class FloatAction extends ControlAction {
+ private static final @ActionType int TYPE = TYPE_FLOAT;
private static final String KEY_NEW_VALUE = "key_new_value";
private final float mNewValue;
@@ -70,7 +73,7 @@ public final class FloatAction extends ControlAction {
*/
@Override
public int getActionType() {
- return TYPE_FLOAT;
+ return TYPE;
}
@Override
@@ -83,6 +86,8 @@ public final class FloatAction extends ControlAction {
public static final @NonNull Creator<FloatAction> CREATOR = new Creator<FloatAction>() {
@Override
public FloatAction createFromParcel(Parcel source) {
+ int type = source.readInt();
+ verifyType(type, TYPE);
return new FloatAction(source.readBundle());
}
diff --git a/core/java/android/service/controls/actions/ModeAction.aidl b/core/java/android/service/controls/actions/ModeAction.aidl
new file mode 100644
index 000000000000..3ef89e0bfce9
--- /dev/null
+++ b/core/java/android/service/controls/actions/ModeAction.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.controls.actions;
+
+parcelable ModeAction; \ No newline at end of file
diff --git a/core/java/android/service/controls/actions/ModeAction.java b/core/java/android/service/controls/actions/ModeAction.java
new file mode 100644
index 000000000000..0bd1d24e873f
--- /dev/null
+++ b/core/java/android/service/controls/actions/ModeAction.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.controls.actions;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Bundle;
+import android.os.Parcel;
+
+/**
+ * @hide
+ */
+public final class ModeAction extends ControlAction {
+
+ private static final @ActionType int TYPE = TYPE_MODE;
+ private static final String KEY_MODE = "key_mode";
+
+ private final int mNewMode;
+
+ @Override
+ public int getActionType() {
+ return TYPE;
+ }
+
+ public ModeAction(@NonNull String templateId, int newMode, @Nullable String challengeValue) {
+ super(templateId, challengeValue);
+ mNewMode = newMode;
+ }
+
+ public ModeAction(@NonNull String templateId, int newMode) {
+ this(templateId, newMode, null);
+ }
+
+ ModeAction(Bundle b) {
+ super(b);
+ mNewMode = b.getInt(KEY_MODE);
+ }
+
+ @Override
+ protected Bundle getDataBundle() {
+ Bundle b = super.getDataBundle();
+ b.putInt(KEY_MODE, mNewMode);
+ return b;
+ }
+
+ public int getNewMode() {
+ return mNewMode;
+ }
+
+ public static final Creator<ModeAction> CREATOR = new Creator<ModeAction>() {
+ @Override
+ public ModeAction createFromParcel(Parcel source) {
+ int type = source.readInt();
+ verifyType(type, TYPE);
+ return new ModeAction(source.readBundle());
+ }
+
+ @Override
+ public ModeAction[] newArray(int size) {
+ return new ModeAction[size];
+ }
+ };
+}
diff --git a/core/java/android/service/controls/actions/MultiFloatAction.aidl b/core/java/android/service/controls/actions/MultiFloatAction.aidl
new file mode 100644
index 000000000000..bcba75810b0c
--- /dev/null
+++ b/core/java/android/service/controls/actions/MultiFloatAction.aidl
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.service.controls.actions;
+
+parcelable MultiFloatAction; \ No newline at end of file
diff --git a/core/java/android/service/controls/actions/MultiFloatAction.java b/core/java/android/service/controls/actions/MultiFloatAction.java
new file mode 100644
index 000000000000..aef8a785a665
--- /dev/null
+++ b/core/java/android/service/controls/actions/MultiFloatAction.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.controls.actions;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.util.Log;
+
+import com.android.internal.util.Preconditions;
+
+/**
+ * @hide
+ */
+public final class MultiFloatAction extends ControlAction {
+
+ private static final String TAG = "MultiFloatAction";
+ private static final @ActionType int TYPE = TYPE_MULTI_FLOAT;
+ private static final String KEY_VALUES = "key_values";
+
+ private final @NonNull float[] mNewValues;
+
+ @Override
+ public int getActionType() {
+ return TYPE;
+ }
+
+ public MultiFloatAction(@NonNull String templateId,
+ @NonNull float[] newValues,
+ @Nullable String challengeValue) {
+ super(templateId, challengeValue);
+ Preconditions.checkNotNull(newValues);
+ if (newValues.length == 0) {
+ throw new IllegalArgumentException("newValues array length 0");
+ }
+ if (newValues.length == 1) {
+ Log.w(TAG, "newValues array length 1");
+ }
+ mNewValues = newValues.clone();
+ }
+
+ public MultiFloatAction(@NonNull String templateId, @NonNull float[] newValues) {
+ this(templateId, newValues, null);
+ }
+
+ MultiFloatAction(Bundle b) {
+ super(b);
+ mNewValues = b.getFloatArray(KEY_VALUES);
+ }
+
+ @NonNull
+ public float[] getNewValues() {
+ return mNewValues.clone();
+ }
+
+ @Override
+ protected Bundle getDataBundle() {
+ Bundle b = super.getDataBundle();
+ b.putFloatArray(KEY_VALUES, mNewValues);
+ return b;
+ }
+
+ public static final Creator<MultiFloatAction> CREATOR = new Creator<MultiFloatAction>() {
+ @Override
+ public MultiFloatAction createFromParcel(Parcel source) {
+ int type = source.readInt();
+ verifyType(type, TYPE);
+ return new MultiFloatAction(source.readBundle());
+ }
+
+ @Override
+ public MultiFloatAction[] newArray(int size) {
+ return new MultiFloatAction[size];
+ }
+ };
+}
diff --git a/core/java/android/service/controls/ControlButton.aidl b/core/java/android/service/controls/templates/ControlButton.aidl
index 6a7262d9542e..f1b3c988e19b 100644
--- a/core/java/android/service/controls/ControlButton.aidl
+++ b/core/java/android/service/controls/templates/ControlButton.aidl
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.service.controls;
+package android.service.controls.templates;
parcelable ControlButton; \ No newline at end of file
diff --git a/core/java/android/service/controls/ControlButton.java b/core/java/android/service/controls/templates/ControlButton.java
index 969c0a75f4ed..e03ac6f8bf51 100644
--- a/core/java/android/service/controls/ControlButton.java
+++ b/core/java/android/service/controls/templates/ControlButton.java
@@ -14,10 +14,9 @@
* limitations under the License.
*/
-package android.service.controls;
+package android.service.controls.templates;
import android.annotation.NonNull;
-import android.graphics.drawable.Icon;
import android.os.Parcel;
import android.os.Parcelable;
@@ -27,24 +26,20 @@ import com.android.internal.util.Preconditions;
* Button element for {@link ControlTemplate}.
* @hide
*/
-public class ControlButton implements Parcelable {
+public final class ControlButton implements Parcelable {
private final boolean mChecked;
- private final @NonNull Icon mIcon;
- private final @NonNull CharSequence mContentDescription;
+ private final @NonNull CharSequence mActionDescription;
/**
* @param checked true if the button should be rendered as active.
- * @param icon icon to display in the button.
- * @param contentDescription content description for the button.
+ * @param actionDescription action description for the button.
*/
- public ControlButton(boolean checked, @NonNull Icon icon,
- @NonNull CharSequence contentDescription) {
- Preconditions.checkNotNull(icon);
- Preconditions.checkNotNull(contentDescription);
+ public ControlButton(boolean checked,
+ @NonNull CharSequence actionDescription) {
+ Preconditions.checkNotNull(actionDescription);
mChecked = checked;
- mIcon = icon;
- mContentDescription = contentDescription;
+ mActionDescription = actionDescription;
}
/**
@@ -55,19 +50,11 @@ public class ControlButton implements Parcelable {
}
/**
- * The icon for this button.
- */
- @NonNull
- public Icon getIcon() {
- return mIcon;
- }
-
- /**
* The content description for this button.
*/
@NonNull
- public CharSequence getContentDescription() {
- return mContentDescription;
+ public CharSequence getActionDescription() {
+ return mActionDescription;
}
@@ -79,14 +66,12 @@ public class ControlButton implements Parcelable {
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeByte(mChecked ? (byte) 1 : (byte) 0);
- mIcon.writeToParcel(dest, flags);
- dest.writeCharSequence(mContentDescription);
+ dest.writeCharSequence(mActionDescription);
}
ControlButton(Parcel in) {
mChecked = in.readByte() != 0;
- mIcon = Icon.CREATOR.createFromParcel(in);
- mContentDescription = in.readCharSequence();
+ mActionDescription = in.readCharSequence();
}
public static final Creator<ControlButton> CREATOR = new Creator<ControlButton>() {
diff --git a/core/java/android/service/controls/ControlTemplate.aidl b/core/java/android/service/controls/templates/ControlTemplate.aidl
index ecb948c8a306..b6ab28026a8d 100644
--- a/core/java/android/service/controls/ControlTemplate.aidl
+++ b/core/java/android/service/controls/templates/ControlTemplate.aidl
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.service.controls;
+package android.service.controls.templates;
parcelable ControlTemplate; \ No newline at end of file
diff --git a/core/java/android/service/controls/ControlTemplate.java b/core/java/android/service/controls/templates/ControlTemplate.java
index 8bcabd6972a5..bf194f8efcda 100644
--- a/core/java/android/service/controls/ControlTemplate.java
+++ b/core/java/android/service/controls/templates/ControlTemplate.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.service.controls;
+package android.service.controls.templates;
import android.annotation.CallSuper;
import android.annotation.IntDef;
@@ -22,6 +22,8 @@ import android.annotation.NonNull;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
+import android.service.controls.Control;
+import android.service.controls.actions.ControlAction;
import com.android.internal.util.Preconditions;
@@ -31,12 +33,11 @@ import java.lang.annotation.RetentionPolicy;
/**
* An abstract input template for a {@link Control}.
*
- * Specifies what layout is presented to the user when a {@link ControlState} is assigned to a
- * particular {@link Control}.
+ * Specifies what layout is presented to the user for a given {@link Control}.
* <p>
* Some instances of {@link Control} can originate actions (via user interaction) to modify its
- * associated state. The actions available to a given {@link Control} in a particular
- * {@link ControlState} are determined by its {@link ControlTemplate}.
+ * associated state. The actions available to a given {@link Control} are determined by its
+ * {@link ControlTemplate}.
* @see ControlAction
* @hide
*/
@@ -64,7 +65,10 @@ public abstract class ControlTemplate implements Parcelable {
TYPE_RANGE,
TYPE_THUMBNAIL,
TYPE_DISCRETE_TOGGLE,
- TYPE_COORD_RANGE
+ TYPE_COORD_RANGE,
+ TYPE_TOGGLE_RANGE,
+ TYPE_TEMPERATURE,
+ TYPE_STATELESS
})
public @interface TemplateType {}
@@ -98,6 +102,12 @@ public abstract class ControlTemplate implements Parcelable {
*/
public static final int TYPE_COORD_RANGE = 5;
+ public static final int TYPE_TOGGLE_RANGE = 6;
+
+ public static final int TYPE_TEMPERATURE = 7;
+
+ public static final int TYPE_STATELESS = 8;
+
private @NonNull final String mTemplateId;
/**
@@ -167,17 +177,31 @@ public abstract class ControlTemplate implements Parcelable {
private static ControlTemplate createTemplateFromType(@TemplateType int type, Parcel source) {
switch(type) {
case TYPE_TOGGLE:
- return ToggleTemplate.CREATOR.createFromParcel(source);
+ return new ToggleTemplate(source.readBundle());
case TYPE_RANGE:
- return RangeTemplate.CREATOR.createFromParcel(source);
+ return new RangeTemplate(source.readBundle());
case TYPE_THUMBNAIL:
- return ThumbnailTemplate.CREATOR.createFromParcel(source);
+ return new ThumbnailTemplate(source.readBundle());
case TYPE_DISCRETE_TOGGLE:
- return DiscreteToggleTemplate.CREATOR.createFromParcel(source);
+ return new DiscreteToggleTemplate(source.readBundle());
+ case TYPE_COORD_RANGE:
+ return new CoordinatedRangeTemplate(source.readBundle());
+ case TYPE_TOGGLE_RANGE:
+ return new ToggleRangeTemplate(source.readBundle());
+ case TYPE_TEMPERATURE:
+ return new TemperatureControlTemplate(source.readBundle());
+ case TYPE_STATELESS:
+ return new StatelessTemplate(source.readBundle());
case TYPE_NONE:
default:
source.readBundle();
return NO_TEMPLATE;
}
}
+
+ protected static void verifyType(@TemplateType int type, @TemplateType int thisType) {
+ if (type != thisType) {
+ throw new IllegalStateException("The type " + type + "does not match " + thisType);
+ }
+ }
}
diff --git a/core/java/android/service/controls/templates/CoordinatedRangeTemplate.aidl b/core/java/android/service/controls/templates/CoordinatedRangeTemplate.aidl
new file mode 100644
index 000000000000..972142c5aa03
--- /dev/null
+++ b/core/java/android/service/controls/templates/CoordinatedRangeTemplate.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.controls.templates;
+
+parcelable CoordinatedRangeTemplate; \ No newline at end of file
diff --git a/core/java/android/service/controls/templates/CoordinatedRangeTemplate.java b/core/java/android/service/controls/templates/CoordinatedRangeTemplate.java
new file mode 100644
index 000000000000..3d820c49eeab
--- /dev/null
+++ b/core/java/android/service/controls/templates/CoordinatedRangeTemplate.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.controls.templates;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.util.Log;
+
+/**
+ * @hide
+ */
+public final class CoordinatedRangeTemplate extends ControlTemplate {
+
+ private static final String TAG = "CoordinatedRangeTemplate";
+
+ private static final @TemplateType int TYPE = TYPE_COORD_RANGE;
+ private static final String KEY_RANGE_LOW = "key_range_low";
+ private static final String KEY_RANGE_HIGH = "key_range_high";
+ private static final String KEY_MIN_GAP = "key_min_gap";
+
+ private final @NonNull RangeTemplate mRangeLow;
+ private final @NonNull RangeTemplate mRangeHigh;
+ private final float mMinGap;
+
+ public CoordinatedRangeTemplate(
+ @NonNull String templateId,
+ float minGap,
+ @NonNull RangeTemplate rangeLow,
+ @NonNull RangeTemplate rangeHigh) {
+ super(templateId);
+ mRangeLow = rangeLow;
+ mRangeHigh = rangeHigh;
+ if (minGap < 0) {
+ Log.e(TAG, "minGap must be non-negative. Setting to 0");
+ mMinGap = 0;
+ } else {
+ mMinGap = minGap;
+ }
+ validateRanges();
+ }
+
+ public CoordinatedRangeTemplate(
+ @NonNull String templateId,
+ float minGap,
+ float minValueLow,
+ float maxValueLow,
+ float currentValueLow,
+ float minValueHigh,
+ float maxValueHigh,
+ float currentValueHigh,
+ float stepValue,
+ @Nullable CharSequence formatString) {
+ this(templateId,
+ minGap,
+ new RangeTemplate("",
+ minValueLow, maxValueLow, currentValueLow, stepValue, formatString),
+ new RangeTemplate("",
+ minValueHigh, maxValueHigh, currentValueHigh, stepValue, formatString));
+ }
+
+ CoordinatedRangeTemplate(Bundle b) {
+ super(b);
+ mRangeLow = b.getParcelable(KEY_RANGE_LOW);
+ mRangeHigh = b.getParcelable(KEY_RANGE_HIGH);
+ mMinGap = b.getFloat(KEY_MIN_GAP);
+ validateRanges();
+ }
+
+ @NonNull
+ public RangeTemplate getRangeLow() {
+ return mRangeLow;
+ }
+
+ @NonNull
+ public RangeTemplate getRangeHigh() {
+ return mRangeHigh;
+ }
+
+ public float getMinValueLow() {
+ return mRangeLow.getMinValue();
+ }
+
+ public float getMaxValueLow() {
+ return mRangeLow.getMaxValue();
+ }
+
+ public float getCurrentValueLow() {
+ return mRangeLow.getCurrentValue();
+ }
+
+ public float getMinValueHigh() {
+ return mRangeHigh.getMinValue();
+ }
+
+ public float getMaxValueHigh() {
+ return mRangeHigh.getMaxValue();
+ }
+
+ public float getCurrentValueHigh() {
+ return mRangeHigh.getCurrentValue();
+ }
+
+ public float getStepValue() {
+ return mRangeLow.getStepValue();
+ }
+
+ public float getMinGap() {
+ return mMinGap;
+ }
+
+ @NonNull
+ public CharSequence getFormatString() {
+ return mRangeLow.getFormatString();
+ }
+
+ @Override
+ public int getTemplateType() {
+ return TYPE;
+ }
+
+ @Override
+ protected Bundle getDataBundle() {
+ Bundle b = super.getDataBundle();
+ b.putParcelable(KEY_RANGE_LOW, mRangeLow);
+ b.putParcelable(KEY_RANGE_HIGH, mRangeHigh);
+ return b;
+ }
+
+ private void validateRanges() {
+ if (Float.compare(mRangeLow.getStepValue(), mRangeHigh.getStepValue()) != 0) {
+ throw new IllegalArgumentException(
+ String.format("lowStepValue=%f != highStepValue=%f",
+ mRangeLow.getStepValue(), mRangeHigh.getStepValue()));
+ }
+ if (!mRangeLow.getFormatString().equals(mRangeHigh.getFormatString())) {
+ throw new IllegalArgumentException(
+ String.format("lowFormatString=%s != highFormatString=%s",
+ mRangeLow.getFormatString(), mRangeHigh.getFormatString()));
+ }
+ if (mMinGap > mRangeHigh.getCurrentValue() - mRangeLow.getCurrentValue()) {
+ throw new IllegalArgumentException(
+ String.format("Minimum gap (%f) > Current gap (%f)", mMinGap,
+ mRangeHigh.getCurrentValue() - mRangeLow.getCurrentValue()));
+ }
+ }
+
+ public static final Creator<CoordinatedRangeTemplate> CREATOR =
+ new Creator<CoordinatedRangeTemplate>() {
+ @Override
+ public CoordinatedRangeTemplate createFromParcel(Parcel source) {
+ int type = source.readInt();
+ verifyType(type, TYPE);
+ return new CoordinatedRangeTemplate(source.readBundle());
+ }
+
+ @Override
+ public CoordinatedRangeTemplate[] newArray(int size) {
+ return new CoordinatedRangeTemplate[size];
+ }
+ };
+}
diff --git a/core/java/android/service/controls/templates/DiscreteToggleTemplate.aidl b/core/java/android/service/controls/templates/DiscreteToggleTemplate.aidl
new file mode 100644
index 000000000000..d22e37501605
--- /dev/null
+++ b/core/java/android/service/controls/templates/DiscreteToggleTemplate.aidl
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.service.controls.templates;
+
+parcelable DiscreteToggleTemplate; \ No newline at end of file
diff --git a/core/java/android/service/controls/DiscreteToggleTemplate.java b/core/java/android/service/controls/templates/DiscreteToggleTemplate.java
index 571825299c77..a8c193c5b1dc 100644
--- a/core/java/android/service/controls/DiscreteToggleTemplate.java
+++ b/core/java/android/service/controls/templates/DiscreteToggleTemplate.java
@@ -14,11 +14,13 @@
* limitations under the License.
*/
-package android.service.controls;
+package android.service.controls.templates;
import android.annotation.NonNull;
import android.os.Bundle;
import android.os.Parcel;
+import android.service.controls.Control;
+import android.service.controls.actions.BooleanAction;
import com.android.internal.util.Preconditions;
@@ -35,11 +37,12 @@ import com.android.internal.util.Preconditions;
*/
public class DiscreteToggleTemplate extends ControlTemplate {
+ private static final @TemplateType int TYPE = TYPE_DISCRETE_TOGGLE;
private static final String KEY_NEGATIVE_BUTTON = "key_negative_button";
private static final String KEY_POSITIVE_BUTTON = "key_positive_button";
- private final @NonNull ControlButton mNegativeButton;
private final @NonNull ControlButton mPositiveButton;
+ private final @NonNull ControlButton mNegativeButton;
/**
* @param templateId the identifier for this template object
@@ -83,7 +86,7 @@ public class DiscreteToggleTemplate extends ControlTemplate {
*/
@Override
public int getTemplateType() {
- return TYPE_DISCRETE_TOGGLE;
+ return TYPE;
}
@@ -95,8 +98,8 @@ public class DiscreteToggleTemplate extends ControlTemplate {
@Override
protected Bundle getDataBundle() {
Bundle b = super.getDataBundle();
- b.putObject(KEY_NEGATIVE_BUTTON, mNegativeButton);
- b.putObject(KEY_POSITIVE_BUTTON, mPositiveButton);
+ b.putParcelable(KEY_NEGATIVE_BUTTON, mNegativeButton);
+ b.putParcelable(KEY_POSITIVE_BUTTON, mPositiveButton);
return b;
}
@@ -104,6 +107,8 @@ public class DiscreteToggleTemplate extends ControlTemplate {
new Creator<DiscreteToggleTemplate>() {
@Override
public DiscreteToggleTemplate createFromParcel(Parcel source) {
+ int type = source.readInt();
+ verifyType(type, TYPE);
return new DiscreteToggleTemplate(source.readBundle());
}
diff --git a/core/java/android/service/controls/RangeTemplate.aidl b/core/java/android/service/controls/templates/RangeTemplate.aidl
index a3d1ca074276..992881552903 100644
--- a/core/java/android/service/controls/RangeTemplate.aidl
+++ b/core/java/android/service/controls/templates/RangeTemplate.aidl
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.service.controls;
+package android.service.controls.templates;
parcelable RangeTemplate; \ No newline at end of file
diff --git a/core/java/android/service/controls/RangeTemplate.java b/core/java/android/service/controls/templates/RangeTemplate.java
index f0bce30081b8..bb79d83b1825 100644
--- a/core/java/android/service/controls/RangeTemplate.java
+++ b/core/java/android/service/controls/templates/RangeTemplate.java
@@ -14,14 +14,14 @@
* limitations under the License.
*/
-package android.service.controls;
+package android.service.controls.templates;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Bundle;
import android.os.Parcel;
-
-import java.security.InvalidParameterException;
+import android.service.controls.Control;
+import android.service.controls.actions.FloatAction;
/**
* A template for a {@link Control} with inputs in a "continuous" range of values.
@@ -31,6 +31,7 @@ import java.security.InvalidParameterException;
*/
public final class RangeTemplate extends ControlTemplate {
+ private static final @TemplateType int TYPE = TYPE_RANGE;
private static final String KEY_MIN_VALUE = "key_min_value";
private static final String KEY_MAX_VALUE = "key_max_value";
private static final String KEY_CURRENT_VALUE = "key_current_value";
@@ -59,11 +60,11 @@ public final class RangeTemplate extends ControlTemplate {
* @param templateId the identifier for this template object
* @param minValue minimum value for the input
* @param maxValue maximum value for the input
- * @param currentValue the current value of the {@link ControlState} containing this object.
+ * @param currentValue the current value of the {@link Control} containing this object.
* @param stepValue minimum value of increments/decrements when interacting with this control.
* @param formatString a formatting string as per {@link String#format} used to display the
* {@code currentValue}. If {@code null} is passed, the "%.1f" is used.
- * @throws InvalidParameterException if the parameters passed do not make a valid range.
+ * @throws IllegalArgumentException if the parameters passed do not make a valid range.
*/
public RangeTemplate(@NonNull String templateId,
float minValue,
@@ -87,7 +88,7 @@ public final class RangeTemplate extends ControlTemplate {
/**
* Construct a new {@link RangeTemplate} from a {@link Parcel}.
*
- * @throws InvalidParameterException if the parameters passed do not make a valid range
+ * @throws IllegalArgumentException if the parameters passed do not make a valid range
* @see RangeTemplate#RangeTemplate(String, float, float, float, float, CharSequence)
* @hide
*/
@@ -144,7 +145,7 @@ public final class RangeTemplate extends ControlTemplate {
*/
@Override
public int getTemplateType() {
- return TYPE_RANGE;
+ return TYPE;
}
@Override
@@ -161,29 +162,31 @@ public final class RangeTemplate extends ControlTemplate {
/**
* Validate constructor parameters
*
- * @throws InvalidParameterException if the parameters passed do not make a valid range
+ * @throws IllegalArgumentException if the parameters passed do not make a valid range
*/
private void validate() {
if (Float.compare(mMinValue, mMaxValue) > 0) {
- throw new InvalidParameterException(
+ throw new IllegalArgumentException(
String.format("minValue=%f > maxValue=%f", mMinValue, mMaxValue));
}
if (Float.compare(mMinValue, mCurrentValue) > 0) {
- throw new InvalidParameterException(
+ throw new IllegalArgumentException(
String.format("minValue=%f > currentValue=%f", mMinValue, mCurrentValue));
}
if (Float.compare(mCurrentValue, mMaxValue) > 0) {
- throw new InvalidParameterException(
+ throw new IllegalArgumentException(
String.format("currentValue=%f > maxValue=%f", mCurrentValue, mMaxValue));
}
if (mStepValue <= 0) {
- throw new InvalidParameterException(String.format("stepValue=%f <= 0", mStepValue));
+ throw new IllegalArgumentException(String.format("stepValue=%f <= 0", mStepValue));
}
}
public static final Creator<RangeTemplate> CREATOR = new Creator<RangeTemplate>() {
@Override
public RangeTemplate createFromParcel(Parcel source) {
+ int type = source.readInt();
+ verifyType(type, TYPE);
return new RangeTemplate(source.readBundle());
}
diff --git a/core/java/android/service/controls/templates/StatelessTemplate.aidl b/core/java/android/service/controls/templates/StatelessTemplate.aidl
new file mode 100644
index 000000000000..02e18d9ac83d
--- /dev/null
+++ b/core/java/android/service/controls/templates/StatelessTemplate.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.controls.templates;
+
+parcelable StatelessTemplate; \ No newline at end of file
diff --git a/core/java/android/service/controls/templates/StatelessTemplate.java b/core/java/android/service/controls/templates/StatelessTemplate.java
new file mode 100644
index 000000000000..12ab9bc567ac
--- /dev/null
+++ b/core/java/android/service/controls/templates/StatelessTemplate.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.controls.templates;
+
+import android.annotation.NonNull;
+import android.os.Bundle;
+import android.os.Parcel;
+
+/**
+ * @hide
+ */
+public final class StatelessTemplate extends ControlTemplate {
+
+ @Override
+ public int getTemplateType() {
+ return TYPE_STATELESS;
+ }
+
+ public StatelessTemplate(@NonNull Bundle b) {
+ super(b);
+ }
+
+ public StatelessTemplate(@NonNull String templateId) {
+ super(templateId);
+ }
+
+ public static final Creator<StatelessTemplate> CREATOR = new Creator<StatelessTemplate>() {
+ @Override
+ public StatelessTemplate createFromParcel(Parcel source) {
+ return new StatelessTemplate(source.readBundle());
+ }
+
+ @Override
+ public StatelessTemplate[] newArray(int size) {
+ return new StatelessTemplate[size];
+ }
+ };
+}
diff --git a/core/java/android/service/controls/templates/TemperatureControlTemplate.java b/core/java/android/service/controls/templates/TemperatureControlTemplate.java
new file mode 100644
index 000000000000..987621e011c2
--- /dev/null
+++ b/core/java/android/service/controls/templates/TemperatureControlTemplate.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.controls.templates;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.util.Log;
+
+import com.android.internal.util.Preconditions;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * @hide
+ */
+public final class TemperatureControlTemplate extends ControlTemplate {
+
+ private static final String TAG = "ThermostatTemplate";
+
+ private static final @TemplateType int TYPE = TYPE_TEMPERATURE;
+ private static final String KEY_TEMPLATE = "key_template";
+ private static final String KEY_CURRENT_MODE = "key_current_mode";
+ private static final String KEY_CURRENT_ACTIVE_MODE = "key_current_active_mode";
+ private static final String KEY_MODES = "key_modes";
+
+ /**
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ MODE_UNKNOWN,
+ MODE_OFF,
+ MODE_HEAT,
+ MODE_COOL,
+ MODE_HEAT_COOL,
+ MODE_ECO
+ })
+ public @interface Mode {}
+
+ private static final int NUM_MODES = 6;
+ public static final @Mode int MODE_UNKNOWN = 0;
+
+ public static final @Mode int MODE_OFF = 1;
+
+ public static final @Mode int MODE_HEAT = 2;
+
+ public static final @Mode int MODE_COOL = 3;
+
+ public static final @Mode int MODE_HEAT_COOL = 4;
+
+ public static final @Mode int MODE_ECO = 5;
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = true, value = {
+ FLAG_MODE_OFF,
+ FLAG_MODE_HEAT,
+ FLAG_MODE_COOL,
+ FLAG_MODE_HEAT_COOL,
+ FLAG_MODE_ECO
+ })
+ public @interface ModeFlag {}
+
+ public static final int FLAG_MODE_OFF = 1 << MODE_OFF;
+ public static final int FLAG_MODE_HEAT = 1 << MODE_HEAT;
+ public static final int FLAG_MODE_COOL = 1 << MODE_COOL;
+ public static final int FLAG_MODE_HEAT_COOL = 1 << MODE_HEAT_COOL;
+ public static final int FLAG_MODE_ECO = 1 << MODE_ECO;
+ private static final int ALL_FLAGS =
+ FLAG_MODE_OFF |
+ FLAG_MODE_HEAT |
+ FLAG_MODE_COOL |
+ FLAG_MODE_HEAT_COOL |
+ FLAG_MODE_ECO;
+
+ private static final int[] modeToFlag = new int[]{
+ 0,
+ FLAG_MODE_OFF,
+ FLAG_MODE_HEAT,
+ FLAG_MODE_COOL,
+ FLAG_MODE_HEAT_COOL,
+ FLAG_MODE_ECO
+ };
+
+ private final @NonNull ControlTemplate mTemplate;
+ private final @Mode int mCurrentMode;
+ private final @Mode int mCurrentActiveMode;
+ private final @ModeFlag int mModes;
+
+ public TemperatureControlTemplate(@NonNull String templateId,
+ @NonNull ControlTemplate controlTemplate,
+ @Mode int currentMode,
+ @Mode int currentActiveMode,
+ @ModeFlag int modesFlag) {
+ super(templateId);
+ Preconditions.checkNotNull(controlTemplate);
+ mTemplate = controlTemplate;
+
+ if (currentMode < 0 || currentMode >= NUM_MODES) {
+ Log.e(TAG, "Invalid current mode:" + currentMode);
+ mCurrentMode = MODE_UNKNOWN;
+ } else {
+ mCurrentMode = currentMode;
+ }
+
+ if (currentActiveMode < 0 || currentActiveMode >= NUM_MODES) {
+ Log.e(TAG, "Invalid current active mode:" + currentActiveMode);
+ mCurrentActiveMode = MODE_UNKNOWN;
+ } else {
+ mCurrentActiveMode = currentActiveMode;
+ }
+
+ mModes = modesFlag & ALL_FLAGS;
+ if (mCurrentMode != MODE_UNKNOWN && (modeToFlag[mCurrentMode] & mModes) == 0) {
+ throw new IllegalArgumentException("Mode " + mCurrentMode + " not supported in flag.");
+ }
+ if (mCurrentActiveMode != MODE_UNKNOWN && (modeToFlag[mCurrentActiveMode] & mModes) == 0) {
+ throw new IllegalArgumentException(
+ "Mode " + currentActiveMode + " not supported in flag.");
+ }
+ }
+
+ TemperatureControlTemplate(@NonNull Bundle b) {
+ super(b);
+ mTemplate = b.getParcelable(KEY_TEMPLATE);
+ mCurrentMode = b.getInt(KEY_CURRENT_MODE);
+ mCurrentActiveMode = b.getInt(KEY_CURRENT_ACTIVE_MODE);
+ mModes = b.getInt(KEY_MODES);
+ }
+
+ @Override
+ protected Bundle getDataBundle() {
+ Bundle b = super.getDataBundle();
+ b.putParcelable(KEY_TEMPLATE, mTemplate);
+ b.putInt(KEY_CURRENT_MODE, mCurrentMode);
+ b.putInt(KEY_CURRENT_ACTIVE_MODE, mCurrentActiveMode);
+ b.putInt(KEY_MODES, mModes);
+ return b;
+ }
+
+ @NonNull
+ public ControlTemplate getTemplate() {
+ return mTemplate;
+ }
+
+ public int getCurrentMode() {
+ return mCurrentMode;
+ }
+
+ public int getCurrentActiveMode() {
+ return mCurrentActiveMode;
+ }
+
+ public int getModes() {
+ return mModes;
+ }
+
+ @Override
+ public int getTemplateType() {
+ return TYPE;
+ }
+
+ public static final Creator<TemperatureControlTemplate> CREATOR = new Creator<TemperatureControlTemplate>() {
+ @Override
+ public TemperatureControlTemplate createFromParcel(Parcel source) {
+ int type = source.readInt();
+ verifyType(type, TYPE);
+ return new TemperatureControlTemplate(source.readBundle());
+ }
+
+ @Override
+ public TemperatureControlTemplate[] newArray(int size) {
+ return new TemperatureControlTemplate[size];
+ }
+ };
+}
diff --git a/core/java/android/service/controls/templates/ThermostatTemplate.aidl b/core/java/android/service/controls/templates/ThermostatTemplate.aidl
new file mode 100644
index 000000000000..1fefda42d284
--- /dev/null
+++ b/core/java/android/service/controls/templates/ThermostatTemplate.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.controls.templates;
+
+parcelable ThermostatTemplate; \ No newline at end of file
diff --git a/core/java/android/service/controls/ThumbnailTemplate.aidl b/core/java/android/service/controls/templates/ThumbnailTemplate.aidl
index fe8c7fed7c89..81c879b227bb 100644
--- a/core/java/android/service/controls/ThumbnailTemplate.aidl
+++ b/core/java/android/service/controls/templates/ThumbnailTemplate.aidl
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.service.controls;
+package android.service.controls.templates;
parcelable ThumbnailTemplate; \ No newline at end of file
diff --git a/core/java/android/service/controls/ThumbnailTemplate.java b/core/java/android/service/controls/templates/ThumbnailTemplate.java
index 6e729c011196..111d60dc80c9 100644
--- a/core/java/android/service/controls/ThumbnailTemplate.java
+++ b/core/java/android/service/controls/templates/ThumbnailTemplate.java
@@ -14,21 +14,24 @@
* limitations under the License.
*/
-package android.service.controls;
+package android.service.controls.templates;
import android.annotation.NonNull;
import android.graphics.drawable.Icon;
import android.os.Bundle;
import android.os.Parcel;
+import android.service.controls.Control;
import com.android.internal.util.Preconditions;
/**
* A template for a {@link Control} that displays an image.
+ *
* @hide
*/
public final class ThumbnailTemplate extends ControlTemplate {
+ private static final @TemplateType int TYPE = TYPE_THUMBNAIL;
private static final String KEY_ICON = "key_icon";
private static final String KEY_CONTENT_DESCRIPTION = "key_content_description";
@@ -76,7 +79,7 @@ public final class ThumbnailTemplate extends ControlTemplate {
*/
@Override
public int getTemplateType() {
- return TYPE_THUMBNAIL;
+ return TYPE;
}
@Override
@@ -90,6 +93,8 @@ public final class ThumbnailTemplate extends ControlTemplate {
public static final Creator<ThumbnailTemplate> CREATOR = new Creator<ThumbnailTemplate>() {
@Override
public ThumbnailTemplate createFromParcel(Parcel source) {
+ int type = source.readInt();
+ verifyType(type, TYPE);
return new ThumbnailTemplate(source.readBundle());
}
diff --git a/core/java/android/service/controls/templates/ToggleRangeTemplate.aidl b/core/java/android/service/controls/templates/ToggleRangeTemplate.aidl
new file mode 100644
index 000000000000..261128488365
--- /dev/null
+++ b/core/java/android/service/controls/templates/ToggleRangeTemplate.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.controls.templates;
+
+parcelable ToggleRangeTemplate; \ No newline at end of file
diff --git a/core/java/android/service/controls/templates/ToggleRangeTemplate.java b/core/java/android/service/controls/templates/ToggleRangeTemplate.java
new file mode 100644
index 000000000000..aa6f6fbad97b
--- /dev/null
+++ b/core/java/android/service/controls/templates/ToggleRangeTemplate.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.controls.templates;
+
+import android.annotation.NonNull;
+import android.os.Bundle;
+import android.os.Parcel;
+
+import com.android.internal.util.Preconditions;
+
+/**
+ * @hide
+ */
+public final class ToggleRangeTemplate extends ControlTemplate {
+
+ private static final @TemplateType int TYPE = TYPE_TOGGLE_RANGE;
+ private static final String KEY_BUTTON = "key_button";
+ private static final String KEY_RANGE = "key_range";
+
+ private @NonNull final ControlButton mControlButton;
+ private @NonNull final RangeTemplate mRangeTemplate;
+
+
+ ToggleRangeTemplate(@NonNull Bundle b) {
+ super(b);
+ mControlButton = b.getParcelable(KEY_BUTTON);
+ mRangeTemplate = b.getParcelable(KEY_RANGE);
+ }
+
+ public ToggleRangeTemplate(@NonNull String templateId,
+ @NonNull ControlButton button,
+ @NonNull RangeTemplate range) {
+ super(templateId);
+ Preconditions.checkNotNull(button);
+ Preconditions.checkNotNull(range);
+ mControlButton = button;
+ mRangeTemplate = range;
+ }
+
+ public ToggleRangeTemplate(@NonNull String templateId,
+ boolean checked,
+ @NonNull CharSequence actionDescription,
+ @NonNull RangeTemplate range) {
+ this(templateId,
+ new ControlButton(checked, actionDescription),
+ range);
+ }
+
+ @Override
+ protected Bundle getDataBundle() {
+ Bundle b = super.getDataBundle();
+ b.putParcelable(KEY_BUTTON, mControlButton);
+ b.putParcelable(KEY_RANGE, mRangeTemplate);
+ return b;
+ }
+
+ @NonNull
+ public RangeTemplate getRange() {
+ return mRangeTemplate;
+ }
+
+ public boolean isChecked() {
+ return mControlButton.isChecked();
+ }
+
+ @NonNull
+ public CharSequence getActionDescription() {
+ return mControlButton.getActionDescription();
+ }
+
+ @Override
+ public int getTemplateType() {
+ return TYPE;
+ }
+
+ public static final Creator<ToggleRangeTemplate> CREATOR = new Creator<ToggleRangeTemplate>() {
+
+ @Override
+ public ToggleRangeTemplate createFromParcel(Parcel source) {
+ int type = source.readInt();
+ verifyType(type, TYPE);
+ return new ToggleRangeTemplate(source.readBundle());
+ }
+
+ @Override
+ public ToggleRangeTemplate[] newArray(int size) {
+ return new ToggleRangeTemplate[size];
+ }
+ };
+}
diff --git a/core/java/android/service/controls/ToggleTemplate.aidl b/core/java/android/service/controls/templates/ToggleTemplate.aidl
index 1c823d9aee6d..98a9e49b7664 100644
--- a/core/java/android/service/controls/ToggleTemplate.aidl
+++ b/core/java/android/service/controls/templates/ToggleTemplate.aidl
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.service.controls;
+package android.service.controls.templates;
parcelable ToggleTemplate; \ No newline at end of file
diff --git a/core/java/android/service/controls/ToggleTemplate.java b/core/java/android/service/controls/templates/ToggleTemplate.java
index 4c4fd5e33cde..0e5fd336e2a7 100644
--- a/core/java/android/service/controls/ToggleTemplate.java
+++ b/core/java/android/service/controls/templates/ToggleTemplate.java
@@ -14,11 +14,13 @@
* limitations under the License.
*/
-package android.service.controls;
+package android.service.controls.templates;
import android.annotation.NonNull;
import android.os.Bundle;
import android.os.Parcel;
+import android.service.controls.Control;
+import android.service.controls.actions.BooleanAction;
import com.android.internal.util.Preconditions;
@@ -33,6 +35,7 @@ import com.android.internal.util.Preconditions;
*/
public final class ToggleTemplate extends ControlTemplate {
+ private static final @TemplateType int TYPE = TYPE_TOGGLE;
private static final String KEY_BUTTON = "key_button";
private final @NonNull ControlButton mButton;
@@ -51,12 +54,12 @@ public final class ToggleTemplate extends ControlTemplate {
mButton = b.getParcelable(KEY_BUTTON);
}
- /**
- * The button provided to this object in {@link ToggleTemplate#ToggleTemplate}
- */
- @NonNull
- public ControlButton getButton() {
- return mButton;
+ public boolean isChecked() {
+ return mButton.isChecked();
+ }
+
+ public CharSequence getContentDescription() {
+ return mButton.getActionDescription();
}
/**
@@ -64,19 +67,21 @@ public final class ToggleTemplate extends ControlTemplate {
*/
@Override
public int getTemplateType() {
- return TYPE_TOGGLE;
+ return TYPE;
}
@Override
protected Bundle getDataBundle() {
Bundle b = super.getDataBundle();
- b.putObject(KEY_BUTTON, mButton);
+ b.putParcelable(KEY_BUTTON, mButton);
return b;
}
public static final Creator<ToggleTemplate> CREATOR = new Creator<ToggleTemplate>() {
@Override
public ToggleTemplate createFromParcel(Parcel source) {
+ int type = source.readInt();
+ verifyType(type, TYPE);
return new ToggleTemplate(source.readBundle());
}
diff --git a/core/java/android/service/dataloader/DataLoaderService.java b/core/java/android/service/dataloader/DataLoaderService.java
new file mode 100644
index 000000000000..75f252e23f79
--- /dev/null
+++ b/core/java/android/service/dataloader/DataLoaderService.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.dataloader;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.app.Service;
+import android.content.Intent;
+import android.content.pm.DataLoaderParams;
+import android.content.pm.DataLoaderParamsParcel;
+import android.content.pm.FileSystemControlParcel;
+import android.content.pm.IDataLoader;
+import android.content.pm.IDataLoaderStatusListener;
+import android.content.pm.InstallationFile;
+import android.content.pm.NamedParcelFileDescriptor;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
+import android.util.ExceptionUtils;
+import android.util.Slog;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * The base class for implementing data loader service to control data loaders. Expecting
+ * Incremental Service to bind to a children class of this.
+ *
+ * WARNING: This is a system API to aid internal development.
+ * Use at your own risk. It will change or be removed without warning.
+ *
+ * TODO(b/136132412): update with latest API design
+ *
+ * @hide
+ */
+@SystemApi
+public abstract class DataLoaderService extends Service {
+ private static final String TAG = "DataLoaderService";
+ private final DataLoaderBinderService mBinder = new DataLoaderBinderService();
+
+ /**
+ * Managed DataLoader interface. Each instance corresponds to a single installation session.
+ * @hide
+ */
+ public interface DataLoader {
+ /**
+ * A virtual constructor.
+ *
+ * @param dataLoaderParams parameters set in the installation session
+ * @param connector FS API wrapper
+ * @return True if initialization of a Data Loader was successful. False will be reported to
+ * PackageManager and fail the installation
+ */
+ boolean onCreate(@NonNull DataLoaderParams dataLoaderParams,
+ @NonNull FileSystemConnector connector);
+
+ /**
+ * Prepare installation image. After this method succeeds installer will validate the files
+ * and continue installation.
+ *
+ * @param addedFiles list of files created in this installation session.
+ * @param removedFiles list of files removed in this installation session.
+ * @return false if unable to create and populate all addedFiles.
+ */
+ boolean onPrepareImage(Collection<InstallationFile> addedFiles,
+ Collection<String> removedFiles);
+ }
+
+ /**
+ * DataLoader factory method.
+ *
+ * @return An instance of a DataLoader.
+ * @hide
+ */
+ public @Nullable DataLoader onCreateDataLoader() {
+ return null;
+ }
+
+ /**
+ * @hide
+ */
+ public final @NonNull IBinder onBind(@NonNull Intent intent) {
+ return (IBinder) mBinder;
+ }
+
+ private class DataLoaderBinderService extends IDataLoader.Stub {
+ private int mId;
+
+ @Override
+ public void create(int id, @NonNull Bundle options,
+ @NonNull IDataLoaderStatusListener listener)
+ throws IllegalArgumentException, RuntimeException {
+ mId = id;
+ final DataLoaderParamsParcel params = options.getParcelable("params");
+ if (params == null) {
+ throw new IllegalArgumentException("Must specify data loader params");
+ }
+ final FileSystemControlParcel control = options.getParcelable("control");
+ if (control == null) {
+ throw new IllegalArgumentException("Must specify control parcel");
+ }
+ try {
+ if (!nativeCreateDataLoader(id, control, params, listener)) {
+ Slog.e(TAG, "Failed to create native loader for " + mId);
+ }
+ } catch (Exception ex) {
+ Slog.e(TAG, "Failed to create native loader for " + mId, ex);
+ destroy();
+ throw new RuntimeException(ex);
+ } finally {
+ // Closing FDs.
+ if (control.incremental != null) {
+ if (control.incremental.cmd != null) {
+ try {
+ control.incremental.cmd.close();
+ } catch (IOException e) {
+ Slog.e(TAG, "Failed to close IncFs CMD file descriptor " + e);
+ }
+ }
+ if (control.incremental.log != null) {
+ try {
+ control.incremental.log.close();
+ } catch (IOException e) {
+ Slog.e(TAG, "Failed to close IncFs LOG file descriptor " + e);
+ }
+ }
+ }
+ if (params.dynamicArgs != null) {
+ NamedParcelFileDescriptor[] fds = params.dynamicArgs;
+ for (NamedParcelFileDescriptor nfd : fds) {
+ try {
+ nfd.fd.close();
+ } catch (IOException e) {
+ Slog.e(TAG, "Failed to close DynamicArgs parcel file descriptor " + e);
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public void start() {
+ if (!nativeStartDataLoader(mId)) {
+ Slog.e(TAG, "Failed to start loader: " + mId);
+ }
+ }
+
+ @Override
+ public void stop() {
+ if (!nativeStopDataLoader(mId)) {
+ Slog.w(TAG, "Failed to stop loader: " + mId);
+ }
+ }
+
+ @Override
+ public void destroy() {
+ if (!nativeDestroyDataLoader(mId)) {
+ Slog.w(TAG, "Failed to destroy loader: " + mId);
+ }
+ }
+
+ @Override
+ public void prepareImage(List<InstallationFile> addedFiles, List<String> removedFiles) {
+ if (!nativePrepareImage(mId, addedFiles, removedFiles)) {
+ Slog.w(TAG, "Failed to destroy loader: " + mId);
+ }
+ }
+ }
+
+ /**
+ * Used by the DataLoaderService implementations.
+ *
+ * @hide
+ */
+ public static final class FileSystemConnector {
+ /**
+ * Create a wrapper for a native instance.
+ *
+ * @hide
+ */
+ FileSystemConnector(long nativeInstance) {
+ mNativeInstance = nativeInstance;
+ }
+
+ /**
+ * Write data to an installation file from an arbitrary FD.
+ *
+ * @param name name of file previously added to the installation session.
+ * @param offsetBytes offset into the file to begin writing at, or 0 to start at the
+ * beginning of the file.
+ * @param lengthBytes total size of the file being written, used to preallocate the
+ * underlying disk space, or -1 if unknown. The system may clear various
+ * caches as needed to allocate this space.
+ * @param incomingFd FD to read bytes from.
+ * @throws IOException if trouble opening the file for writing, such as lack of disk space
+ * or unavailable media.
+ */
+ public void writeData(String name, long offsetBytes, long lengthBytes,
+ ParcelFileDescriptor incomingFd) throws IOException {
+ try {
+ nativeWriteData(mNativeInstance, name, offsetBytes, lengthBytes, incomingFd);
+ } catch (RuntimeException e) {
+ ExceptionUtils.maybeUnwrapIOException(e);
+ throw e;
+ }
+ }
+
+ private final long mNativeInstance;
+ }
+
+ /* Native methods */
+ private native boolean nativeCreateDataLoader(int storageId,
+ @NonNull FileSystemControlParcel control,
+ @NonNull DataLoaderParamsParcel params,
+ IDataLoaderStatusListener listener);
+
+ private native boolean nativeStartDataLoader(int storageId);
+
+ private native boolean nativeStopDataLoader(int storageId);
+
+ private native boolean nativeDestroyDataLoader(int storageId);
+
+ private native boolean nativePrepareImage(int storageId,
+ Collection<InstallationFile> addedFiles, Collection<String> removedFiles);
+
+ private static native void nativeWriteData(long nativeInstance, String name, long offsetBytes,
+ long lengthBytes, ParcelFileDescriptor incomingFd);
+
+}
diff --git a/core/java/android/service/incremental/IncrementalDataLoaderService.java b/core/java/android/service/incremental/IncrementalDataLoaderService.java
deleted file mode 100644
index c4a06c8f53db..000000000000
--- a/core/java/android/service/incremental/IncrementalDataLoaderService.java
+++ /dev/null
@@ -1,563 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.service.incremental;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.app.Service;
-import android.content.Intent;
-import android.content.pm.IDataLoader;
-import android.content.pm.IDataLoaderStatusListener;
-import android.content.pm.InstallationFile;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.incremental.IncrementalDataLoaderParams;
-import android.os.incremental.IncrementalDataLoaderParamsParcel;
-import android.os.incremental.IncrementalFileSystemControlParcel;
-import android.os.incremental.NamedParcelFileDescriptor;
-import android.util.Slog;
-
-import java.io.IOException;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.Collection;
-import java.util.List;
-
-
-/**
- * The base class for implementing data loader service to control data loaders. Expecting
- * Incremental Service to bind to a children class of this.
- *
- * @hide
- *
- * Hide for now, should be @SystemApi
- * TODO(b/136132412): update with latest API design
- */
-public abstract class IncrementalDataLoaderService extends Service {
- private static final String TAG = "IncrementalDataLoaderService";
- private final DataLoaderBinderService mBinder = new DataLoaderBinderService();
-
- public static final int DATA_LOADER_READY =
- IDataLoaderStatusListener.DATA_LOADER_READY;
- public static final int DATA_LOADER_NOT_READY =
- IDataLoaderStatusListener.DATA_LOADER_NOT_READY;
- public static final int DATA_LOADER_RUNNING =
- IDataLoaderStatusListener.DATA_LOADER_RUNNING;
- public static final int DATA_LOADER_STOPPED =
- IDataLoaderStatusListener.DATA_LOADER_STOPPED;
- public static final int DATA_LOADER_SLOW_CONNECTION =
- IDataLoaderStatusListener.DATA_LOADER_SLOW_CONNECTION;
- public static final int DATA_LOADER_NO_CONNECTION =
- IDataLoaderStatusListener.DATA_LOADER_NO_CONNECTION;
- public static final int DATA_LOADER_CONNECTION_OK =
- IDataLoaderStatusListener.DATA_LOADER_CONNECTION_OK;
-
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(prefix = {"DATA_LOADER_"}, value = {
- DATA_LOADER_READY,
- DATA_LOADER_NOT_READY,
- DATA_LOADER_RUNNING,
- DATA_LOADER_STOPPED,
- DATA_LOADER_SLOW_CONNECTION,
- DATA_LOADER_NO_CONNECTION,
- DATA_LOADER_CONNECTION_OK
- })
- public @interface DataLoaderStatus {
- }
-
- /**
- * Incremental FileSystem block size.
- **/
- public static final int BLOCK_SIZE = 4096;
-
- /**
- * Data compression types
- */
- public static final int COMPRESSION_NONE = 0;
- public static final int COMPRESSION_LZ4 = 1;
-
- /**
- * @hide
- */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef({COMPRESSION_NONE, COMPRESSION_LZ4})
- public @interface CompressionType {
- }
-
- /**
- * Managed DataLoader interface. Each instance corresponds to a single Incremental File System
- * instance.
- */
- public abstract static class DataLoader {
- /**
- * A virtual constructor used to do simple initialization. Not ready to serve any data yet.
- * All heavy-lifting has to be done in onStart.
- *
- * @param params Data loader configuration parameters.
- * @param connector IncFS API wrapper.
- * @param listener Used for reporting internal state to IncrementalService.
- * @return True if initialization of a Data Loader was successful. False will be reported to
- * IncrementalService and can cause an unmount of an IFS instance.
- */
- public abstract boolean onCreate(@NonNull IncrementalDataLoaderParams params,
- @NonNull FileSystemConnector connector,
- @NonNull StatusListener listener);
-
- /**
- * Start the data loader. After this method returns data loader is considered to be ready to
- * receive callbacks from IFS, supply data via connector and send status updates via
- * callbacks.
- *
- * @return True if Data Loader was able to start. False will be reported to
- * IncrementalService and can cause an unmount of an IFS instance.
- */
- public abstract boolean onStart();
-
- /**
- * Stop the data loader. Use to stop any additional threads and free up resources. Data
- * loader is not longer responsible for supplying data. Start/Stop pair can be called
- * multiple times e.g. if IFS detects corruption and data needs to be re-loaded.
- */
- public abstract void onStop();
-
- /**
- * Virtual destructor. Use to cleanup all internal state. After this method returns, the
- * data loader can no longer use connector or callbacks. For any additional operations with
- * this instance of IFS a new DataLoader will be created using createDataLoader method.
- */
- public abstract void onDestroy();
-
- /**
- * IFS reports a pending read each time the page needs to be loaded, e.g. missing.
- *
- * @param pendingReads array of blocks to load.
- *
- * TODO(b/136132412): avoid using collections
- */
- public abstract void onPendingReads(
- @NonNull Collection<FileSystemConnector.PendingReadInfo> pendingReads);
-
- /**
- * IFS tracks all reads and reports them using onPageReads.
- *
- * @param reads array of blocks.
- *
- * TODO(b/136132412): avoid using collections
- */
- public abstract void onPageReads(@NonNull Collection<FileSystemConnector.ReadInfo> reads);
-
- /**
- * IFS informs data loader that a new file has been created.
- * <p>
- * This can be used to prepare the data loader before it starts loading data. For example,
- * the data loader can keep a list of newly created files, so that it knows what files to
- * download from the server.
- *
- * @param inode The inode value of the new file.
- * @param metadata The metadata of the new file.
- */
- public abstract void onFileCreated(long inode, byte[] metadata);
- }
-
- /**
- * DataLoader factory method.
- *
- * @return An instance of a DataLoader.
- */
- public abstract @Nullable DataLoader onCreateDataLoader();
-
- /**
- * @hide
- */
- public final @NonNull IBinder onBind(@NonNull Intent intent) {
- return (IBinder) mBinder;
- }
-
- private class DataLoaderBinderService extends IDataLoader.Stub {
- private int mId;
-
- @Override
- public void create(int id, @NonNull Bundle options,
- @NonNull IDataLoaderStatusListener listener)
- throws IllegalArgumentException, RuntimeException {
- mId = id;
- final IncrementalDataLoaderParamsParcel params = options.getParcelable("params");
- if (params == null) {
- throw new IllegalArgumentException("Must specify Incremental data loader params");
- }
- final IncrementalFileSystemControlParcel control =
- options.getParcelable("control");
- if (control == null) {
- throw new IllegalArgumentException("Must specify Incremental control parcel");
- }
- mStatusListener = listener;
- try {
- if (!nativeCreateDataLoader(id, control, params, listener)) {
- Slog.e(TAG, "Failed to create native loader for " + mId);
- }
- } catch (Exception ex) {
- destroy();
- throw new RuntimeException(ex);
- } finally {
- // Closing FDs.
- if (control.cmd != null) {
- try {
- control.cmd.close();
- } catch (IOException e) {
- Slog.e(TAG, "Failed to close IncFs CMD file descriptor " + e);
- }
- }
- if (control.log != null) {
- try {
- control.log.close();
- } catch (IOException e) {
- Slog.e(TAG, "Failed to close IncFs LOG file descriptor " + e);
- }
- }
- NamedParcelFileDescriptor[] fds = params.dynamicArgs;
- for (NamedParcelFileDescriptor nfd : fds) {
- try {
- nfd.fd.close();
- } catch (IOException e) {
- Slog.e(TAG,
- "Failed to close DynamicArgs parcel file descriptor " + e);
- }
- }
- }
- }
-
- @Override
- public void start(List<InstallationFile> fileInfos) {
- if (!nativeStartDataLoader(mId)) {
- Slog.e(TAG, "Failed to start loader: loader not found for " + mId);
- }
- }
-
- @Override
- public void stop() {
- if (!nativeStopDataLoader(mId)) {
- Slog.w(TAG, "Failed to stop loader: loader not found for " + mId);
- }
- }
-
- @Override
- public void destroy() {
- if (!nativeDestroyDataLoader(mId)) {
- Slog.w(TAG, "Failed to destroy loader: loader not found for " + mId);
- }
- }
-
- @Override
- // TODO(b/136132412): remove this
- public void onFileCreated(long inode, byte[] metadata) {
- if (!nativeOnFileCreated(mId, inode, metadata)) {
- Slog.w(TAG, "Failed to handle onFileCreated for storage:" + mId
- + " inode:" + inode);
- }
- }
- }
-
- /**
- * IncFs API wrapper for writing pages and getting page missing info. Non-hidden methods are
- * expected to be called by the IncrementalDataLoaderService implemented by developers.
- *
- * @hide
- *
- * TODO(b/136132412) Should be @SystemApi
- */
- public static final class FileSystemConnector {
- /**
- * Defines a block address. A block is the unit of data chunk that IncFs operates with.
- *
- * @hide
- */
- public static class BlockAddress {
- /**
- * Linux inode uniquely identifies file within a single IFS instance.
- */
- private final long mFileIno;
- /**
- * Index of a 4K block within a file.
- */
- private final int mBlockIndex;
-
- public BlockAddress(long fileIno, int blockIndex) {
- this.mFileIno = fileIno;
- this.mBlockIndex = blockIndex;
- }
-
- public long getFileIno() {
- return mFileIno;
- }
-
- public int getBlockIndex() {
- return mBlockIndex;
- }
- }
-
- /**
- * A block is the unit of data chunk that IncFs operates with.
- *
- * @hide
- */
- public static class Block extends BlockAddress {
- /**
- * Data content of the block.
- */
- private final @NonNull byte[] mDataBytes;
-
- public Block(long fileIno, int blockIndex, @NonNull byte[] dataBytes) {
- super(fileIno, blockIndex);
- this.mDataBytes = dataBytes;
- }
- }
-
- /**
- * Defines a page/block inside a file.
- */
- public static class DataBlock extends Block {
- /**
- * Compression type of the data block.
- */
- private final @CompressionType int mCompressionType;
-
- public DataBlock(long fileIno, int blockIndex, @NonNull byte[] dataBytes,
- @CompressionType int compressionType) {
- super(fileIno, blockIndex, dataBytes);
- this.mCompressionType = compressionType;
- }
- }
-
- /**
- * Defines a hash block for a certain file. A hash block index is the index in an array of
- * hashes which is the 1-d representation of the hash tree. One DataBlock might be
- * associated with multiple HashBlocks.
- */
- public static class HashBlock extends Block {
- public HashBlock(long fileIno, int blockIndex, @NonNull byte[] dataBytes) {
- super(fileIno, blockIndex, dataBytes);
- }
- }
-
- /**
- * Information about a page that is pending to be read.
- */
- public static class PendingReadInfo extends BlockAddress {
- PendingReadInfo(long fileIno, int blockIndex) {
- super(fileIno, blockIndex);
- }
- }
-
- /**
- * Information about a page that is read.
- */
- public static class ReadInfo extends BlockAddress {
- /**
- * A monotonically increasing read timestamp.
- */
- private final long mTimePoint;
- /**
- * Number of blocks read starting from blockIndex.
- */
- private final int mBlockCount;
-
- ReadInfo(long timePoint, long fileIno, int firstBlockIndex, int blockCount) {
- super(fileIno, firstBlockIndex);
- this.mTimePoint = timePoint;
- this.mBlockCount = blockCount;
- }
-
- public long getTimePoint() {
- return mTimePoint;
- }
-
- public int getBlockCount() {
- return mBlockCount;
- }
- }
-
- /**
- * Defines the dynamic information about an IncFs file.
- */
- public static class FileInfo {
- /**
- * BitSet to show if any block is available at each block index.
- */
- private final @NonNull
- byte[] mBlockBitmap;
-
- /**
- * @hide
- */
- public FileInfo(@NonNull byte[] blockBitmap) {
- this.mBlockBitmap = blockBitmap;
- }
- }
-
- /**
- * Creates a wrapper for a native instance.
- */
- FileSystemConnector(long nativeInstance) {
- mNativeInstance = nativeInstance;
- }
-
- /**
- * Checks whether a range in a file if loaded.
- *
- * @param node inode of the file.
- * @param start The starting offset of the range.
- * @param end The ending offset of the range.
- * @return True if the file is fully loaded.
- */
- public boolean isFileRangeLoaded(long node, long start, long end) {
- return nativeIsFileRangeLoadedNode(mNativeInstance, node, start, end);
- }
-
- /**
- * Gets the metadata of a file.
- *
- * @param node inode of the file.
- * @return The metadata object.
- */
- @NonNull
- public byte[] getFileMetadata(long node) throws IOException {
- final byte[] metadata = nativeGetFileMetadataNode(mNativeInstance, node);
- if (metadata == null || metadata.length == 0) {
- throw new IOException(
- "IncrementalFileSystem failed to obtain metadata for node: " + node);
- }
- return metadata;
- }
-
- /**
- * Gets the dynamic information of a file, such as page bitmaps. Can be used to get missing
- * page indices by the FileSystemConnector.
- *
- * @param node inode of the file.
- * @return Dynamic file info.
- */
- @NonNull
- public FileInfo getDynamicFileInfo(long node) throws IOException {
- final byte[] blockBitmap = nativeGetFileInfoNode(mNativeInstance, node);
- if (blockBitmap == null || blockBitmap.length == 0) {
- throw new IOException(
- "IncrementalFileSystem failed to obtain dynamic file info for node: "
- + node);
- }
- return new FileInfo(blockBitmap);
- }
-
- /**
- * Writes a page's data and/or hashes.
- *
- * @param dataBlocks the DataBlock objects that contain data block index and data bytes.
- * @param hashBlocks the HashBlock objects that contain hash indices and hash bytes.
- *
- * TODO(b/136132412): change API to avoid dynamic allocation of data block objects
- */
- public void writeMissingData(@NonNull DataBlock[] dataBlocks,
- @Nullable HashBlock[] hashBlocks) throws IOException {
- if (!nativeWriteMissingData(mNativeInstance, dataBlocks, hashBlocks)) {
- throw new IOException("IncrementalFileSystem failed to write missing data.");
- }
- }
-
- /**
- * Writes the signer block of a file. Expecting the connector to call this when it got
- * signing data from data loader.
- *
- * @param node the file to be written to.
- * @param signerData the raw signer data byte array.
- */
- public void writeSignerData(long node, @NonNull byte[] signerData)
- throws IOException {
- if (!nativeWriteSignerDataNode(mNativeInstance, node, signerData)) {
- throw new IOException(
- "IncrementalFileSystem failed to write signer data of node " + node);
- }
- }
-
- private final long mNativeInstance;
- }
-
- /**
- * Wrapper for native reporting DataLoader statuses.
- *
- * @hide
- *
- * TODO(b/136132412) Should be @SystemApi
- */
- public static final class StatusListener {
- /**
- * Creates a wrapper for a native instance.
- *
- * @hide
- */
- StatusListener(long nativeInstance) {
- mNativeInstance = nativeInstance;
- }
-
- /**
- * Report the status of DataLoader. Used for system-wide notifications e.g., disabling
- * applications which rely on this data loader to function properly.
- *
- * @param status status to report.
- * @return True if status was reported successfully.
- */
- public boolean onStatusChanged(@DataLoaderStatus int status) {
- return nativeReportStatus(mNativeInstance, status);
- }
-
- private final long mNativeInstance;
- }
-
- private IDataLoaderStatusListener mStatusListener = null;
-
- /* Native methods */
- private native boolean nativeCreateDataLoader(int storageId,
- @NonNull IncrementalFileSystemControlParcel control,
- @NonNull IncrementalDataLoaderParamsParcel params,
- IDataLoaderStatusListener listener);
-
- private native boolean nativeStartDataLoader(int storageId);
-
- private native boolean nativeStopDataLoader(int storageId);
-
- private native boolean nativeDestroyDataLoader(int storageId);
-
- private static native boolean nativeOnFileCreated(int storageId,
- long inode, byte[] metadata);
-
- private static native boolean nativeIsFileRangeLoadedNode(
- long nativeInstance, long node, long start, long end);
-
- private static native boolean nativeWriteMissingData(
- long nativeInstance, FileSystemConnector.DataBlock[] dataBlocks,
- FileSystemConnector.HashBlock[] hashBlocks);
-
- private static native boolean nativeWriteSignerDataNode(
- long nativeInstance, long node, byte[] signerData);
-
- private static native byte[] nativeGetFileMetadataNode(
- long nativeInstance, long node);
-
- private static native byte[] nativeGetFileInfoNode(
- long nativeInstance, long node);
-
- private static native boolean nativeReportStatus(long nativeInstance, int status);
-}
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 44446ad04edd..172495f917a9 100644
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -1771,7 +1771,7 @@ public class TextToSpeech {
*
* @param text The text that should be synthesized. No longer than
* {@link #getMaxSpeechInputLength()} characters.
- * @param params Parameters for the request. Can be null.
+ * @param params Parameters for the request.
* Engine specific parameters may be passed in but the parameter keys
* must be prefixed by the name of the engine they are intended for. For example
* the keys "com.svox.pico_foo" and "com.svox.pico:bar" will be passed to the engine
@@ -1798,7 +1798,7 @@ public class TextToSpeech {
*
* @param text The text that should be synthesized. No longer than
* {@link #getMaxSpeechInputLength()} characters.
- * @param params Parameters for the request. Can be null.
+ * @param params Parameters for the request. Cannot be null.
* Engine specific parameters may be passed in but the parameter keys
* must be prefixed by the name of the engine they are intended for. For example
* the keys "com.svox.pico_foo" and "com.svox.pico:bar" will be passed to the
@@ -1842,7 +1842,7 @@ public class TextToSpeech {
*
* @param text The text that should be synthesized. No longer than
* {@link #getMaxSpeechInputLength()} characters.
- * @param params Parameters for the request. Can be null.
+ * @param params Parameters for the request. Cannot be null.
* Supported parameter names:
* {@link Engine#KEY_PARAM_UTTERANCE_ID}.
* Engine specific parameters may be passed in but the parameter keys
diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java
index 51a9c864ee29..7841f991c4bc 100644
--- a/core/java/android/telephony/PhoneStateListener.java
+++ b/core/java/android/telephony/PhoneStateListener.java
@@ -24,7 +24,6 @@ import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.os.Binder;
import android.os.Build;
-import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.Looper;
@@ -319,10 +318,8 @@ public class PhoneStateListener {
* Listen for call disconnect causes which contains {@link DisconnectCause} and
* {@link PreciseDisconnectCause}.
*
- * @hide
*/
@RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
- @SystemApi
public static final int LISTEN_CALL_DISCONNECT_CAUSES = 0x02000000;
/**
@@ -342,10 +339,8 @@ public class PhoneStateListener {
* {@link android.telephony.ims.ImsReasonInfo}
*
* @see #onImsCallDisconnectCauseChanged(ImsReasonInfo)
- * @hide
*/
@RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
- @SystemApi
public static final int LISTEN_IMS_CALL_DISCONNECT_CAUSES = 0x08000000;
/**
@@ -661,10 +656,8 @@ public class PhoneStateListener {
* @param disconnectCause {@link DisconnectCause}.
* @param preciseDisconnectCause {@link PreciseDisconnectCause}.
*
- * @hide
*/
@RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
- @SystemApi
public void onCallDisconnectCauseChanged(int disconnectCause, int preciseDisconnectCause) {
// default implementation empty
}
@@ -680,10 +673,8 @@ public class PhoneStateListener {
*
* @param imsReasonInfo {@link ImsReasonInfo} contains details on why IMS call failed.
*
- * @hide
*/
@RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
- @SystemApi
public void onImsCallDisconnectCauseChanged(@NonNull ImsReasonInfo imsReasonInfo) {
// default implementation empty
}
@@ -911,8 +902,7 @@ public class PhoneStateListener {
* subId. Otherwise, this callback applies to
* {@link SubscriptionManager#getDefaultSubscriptionId()}.
*
- * Requires
- * the READ_PRIVILEGED_PHONE_STATE permission.
+ * @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE}
* @param state the modem radio power state
* @hide
*/
@@ -993,8 +983,11 @@ public class PhoneStateListener {
() -> mExecutor.execute(() -> psl.onCallForwardingIndicatorChanged(cfi)));
}
- public void onCellLocationChanged(Bundle bundle) {
- CellLocation location = CellLocation.newFromBundle(bundle);
+ public void onCellLocationChanged(CellIdentity cellIdentity) {
+ // There is no system/public API to create an CellIdentity in system server,
+ // so the server pass a null to indicate an empty initial location.
+ CellLocation location =
+ cellIdentity == null ? CellLocation.getEmpty() : cellIdentity.asCellLocation();
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
if (psl == null) return;
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index f574160e5303..1b2fedad842e 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -22,7 +22,6 @@ import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.content.Context;
import android.os.Binder;
-import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.telephony.Annotation.CallState;
@@ -633,10 +632,14 @@ public class TelephonyRegistryManager {
}
/**
- * TODO change from bundle to CellLocation?
+ * Notify {@link android.telephony.CellLocation} changed.
+ *
+ * <p>To be compatible with {@link TelephonyRegistry}, use {@link CellIdentity} which is
+ * parcelable, and convert to CellLocation in client code.
+ *
* @hide
*/
- public void notifyCellLocation(int subId, Bundle cellLocation) {
+ public void notifyCellLocation(int subId, CellIdentity cellLocation) {
try {
sRegistry.notifyCellLocationForSubscriber(subId, cellLocation);
} catch (RemoteException ex) {
diff --git a/core/java/android/util/CloseGuard.java b/core/java/android/util/CloseGuard.java
index c39a6c9aac93..6ac769623bff 100644
--- a/core/java/android/util/CloseGuard.java
+++ b/core/java/android/util/CloseGuard.java
@@ -38,6 +38,11 @@ import android.annotation.NonNull;
* public void cleanup() {
* guard.close();
* ...;
+ * if (Build.VERSION.SDK_INT >= 28) {
+ * Reference.reachabilityFence(this);
+ * }
+ * // For full correctness in the absence of a close() call, other methods may also need
+ * // reachabilityFence() calls.
* }
*
* protected void finalize() throws Throwable {
@@ -75,7 +80,9 @@ import android.annotation.NonNull;
* public void cleanup() {
* guard.close();
* ...;
- * Reference.reachabilityFence(this);
+ * if (Build.VERSION.SDK_INT >= 28) {
+ * Reference.reachabilityFence(this);
+ * }
* // For full correctness in the absence of a close() call, other methods may also need
* // reachabilityFence() calls.
* }
diff --git a/core/java/android/util/proto/ProtoOutputStream.java b/core/java/android/util/proto/ProtoOutputStream.java
index 6efcfbfd05f8..7b24ba997307 100644
--- a/core/java/android/util/proto/ProtoOutputStream.java
+++ b/core/java/android/util/proto/ProtoOutputStream.java
@@ -16,7 +16,8 @@
package android.util.proto;
-import android.annotation.TestApi;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.util.Log;
import java.io.FileDescriptor;
@@ -28,19 +29,23 @@ import java.io.UnsupportedEncodingException;
/**
* Class to write to a protobuf stream.
*
- * Each write method takes an ID code from the protoc generated classes
- * and the value to write. To make a nested object, call #start
- * and then #end when you are done.
+ * <p>
+ * This API is not as convenient or type safe as the standard protobuf
+ * classes. If possible, the best recommended library is to use protobuf lite.
+ * However, in environements (such as the Android platform itself), a
+ * more memory efficient version is necessary.
*
- * The ID codes have type information embedded into them, so if you call
- * the incorrect function you will get an IllegalArgumentException.
+ * <p>Each write method takes an ID code from the protoc generated classes
+ * and the value to write. To make a nested object, call {@link #start(long)}
+ * and then {@link #end(long)} when you are done.
*
- * To retrieve the encoded protobuf stream, call getBytes().
+ * <p>The ID codes have type information embedded into them, so if you call
+ * the incorrect function you will get an {@link IllegalArgumentException}.
+ *
+ * <p>To retrieve the encoded protobuf stream, call {@link #getBytes()}.
*
- * TODO: Add a constructor that takes an OutputStream and write to that
* stream as the top-level objects are finished.
*
- * @hide
*/
/* IMPLEMENTATION NOTES
@@ -99,7 +104,6 @@ import java.io.UnsupportedEncodingException;
* correctly matched pairs of #start and #end calls, and issue
* errors if they are not matched.
*/
-@TestApi
public final class ProtoOutputStream extends ProtoStream {
/**
* @hide
@@ -124,7 +128,9 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* An ID given to objects and returned in the token from startObject
* and stored in the buffer until endObject is called, where the two
- * are checked. Starts at -1 and becomes more negative, so the values
+ * are checked.
+ *
+ * <p>Starts at -1 and becomes more negative, so the values
* aren't likely to alias with the size it will be overwritten with,
* which tend to be small, and we will be more likely to catch when
* the caller of endObject uses a stale token that they didn't intend
@@ -133,8 +139,9 @@ public final class ProtoOutputStream extends ProtoStream {
private int mNextObjectId = -1;
/**
- * The object token we are expecting in endObject. If another call to
- * startObject happens, this is written to that location, which gives
+ * The object token we are expecting in endObject.
+ *
+ * <p>If another call to startObject happens, this is written to that location, which gives
* us a stack, stored in the space for the as-yet unused size fields.
*/
private long mExpectedObjectToken;
@@ -151,39 +158,45 @@ public final class ProtoOutputStream extends ProtoStream {
private boolean mCompacted;
/**
- * Construct a ProtoOutputStream with the default chunk size.
+ * Construct a {@link ProtoOutputStream} with the default chunk size.
+ *
+ * <p>This is for an in-memory proto. The caller should use {@link #getBytes()} for the result.
*/
public ProtoOutputStream() {
this(0);
}
/**
- * Construct a ProtoOutputStream with the given chunk size.
+ * Construct a {@link ProtoOutputStream with the given chunk size.
+ *
+ * <p>This is for an in-memory proto. The caller should use {@link #getBytes()} for the result.
*/
public ProtoOutputStream(int chunkSize) {
mBuffer = new EncodedBuffer(chunkSize);
}
/**
- * Construct a ProtoOutputStream that sits on top of an OutputStream.
- * @more
- * The {@link #flush() flush()} method must be called when done writing
- * to flush any remanining data, althought data *may* be written at intermediate
+ * Construct a {@link ProtoOutputStream} that sits on top of an {@link OutputStream}.
+ *
+ * <p>The {@link #flush()} method must be called when done writing
+ * to flush any remaining data, although data *may* be written at intermediate
* points within the writing as well.
*/
- public ProtoOutputStream(OutputStream stream) {
+ public ProtoOutputStream(@NonNull OutputStream stream) {
this();
mStream = stream;
}
/**
- * Construct a ProtoOutputStream that sits on top of a FileDescriptor.
- * @more
- * The {@link #flush() flush()} method must be called when done writing
- * to flush any remanining data, althought data *may* be written at intermediate
+ * Construct a {@link ProtoOutputStream} that sits on top of a {@link FileDescriptor}.
+ *
+ * <p>The {@link #flush()} method must be called when done writing
+ * to flush any remaining data, although data *may* be written at intermediate
* points within the writing as well.
+ *
+ * @hide
*/
- public ProtoOutputStream(FileDescriptor fd) {
+ public ProtoOutputStream(@NonNull FileDescriptor fd) {
this(new FileOutputStream(fd));
}
@@ -202,7 +215,7 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a value for the given fieldId.
*
- * Will automatically convert for the following field types, and
+ * <p>Will automatically convert for the following field types, and
* throw an exception for others: double, float, int32, int64, uint32, uint64,
* sint32, sint64, fixed32, fixed64, sfixed32, sfixed64, bool, enum.
*
@@ -337,7 +350,7 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a value for the given fieldId.
*
- * Will automatically convert for the following field types, and
+ * <p>Will automatically convert for the following field types, and
* throw an exception for others: double, float, int32, int64, uint32, uint64,
* sint32, sint64, fixed32, fixed64, sfixed32, sfixed64, bool, enum.
*
@@ -472,7 +485,7 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a value for the given fieldId.
*
- * Will automatically convert for the following field types, and
+ * <p>Will automatically convert for the following field types, and
* throw an exception for others: double, float, int32, int64, uint32, uint64,
* sint32, sint64, fixed32, fixed64, sfixed32, sfixed64, bool, enum.
*
@@ -607,7 +620,7 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a value for the given fieldId.
*
- * Will automatically convert for the following field types, and
+ * <p>Will automatically convert for the following field types, and
* throw an exception for others: double, float, int32, int64, uint32, uint64,
* sint32, sint64, fixed32, fixed64, sfixed32, sfixed64, bool, enum.
*
@@ -742,7 +755,7 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a boolean value for the given fieldId.
*
- * If the field is not a bool field, an exception will be thrown.
+ * <p>If the field is not a bool field, an {@link IllegalStateException} will be thrown.
*
* @param fieldId The field identifier constant from the generated class.
* @param val The value.
@@ -771,12 +784,12 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a string value for the given fieldId.
*
- * If the field is not a string field, an exception will be thrown.
+ * <p>If the field is not a string field, an exception will be thrown.
*
* @param fieldId The field identifier constant from the generated class.
* @param val The value.
*/
- public void write(long fieldId, String val) {
+ public void write(long fieldId, @Nullable String val) {
assertNotCompacted();
final int id = (int)fieldId;
@@ -800,12 +813,12 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a byte[] value for the given fieldId.
*
- * If the field is not a bytes or object field, an exception will be thrown.
+ * <p>If the field is not a bytes or object field, an exception will be thrown.
*
* @param fieldId The field identifier constant from the generated class.
* @param val The value.
*/
- public void write(long fieldId, byte[] val) {
+ public void write(long fieldId, @Nullable byte[] val) {
assertNotCompacted();
final int id = (int)fieldId;
@@ -836,6 +849,9 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Start a sub object.
+ *
+ * @param fieldId The field identifier constant from the generated class.
+ * @return The token to call {@link #end(long)} with.
*/
public long start(long fieldId) {
assertNotCompacted();
@@ -855,6 +871,8 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* End the object started by start() that returned token.
+ *
+ * @param token The token returned from {@link #start(long)}
*/
public void end(long token) {
endObjectImpl(token, getRepeatedFromToken(token));
@@ -870,7 +888,8 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a single proto "double" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, double)} instead.
+ * @hide
*/
@Deprecated
public void writeDouble(long fieldId, double val) {
@@ -890,7 +909,8 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a single repeated proto "double" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, double)} instead.
+ * @hide
*/
@Deprecated
public void writeRepeatedDouble(long fieldId, double val) {
@@ -908,10 +928,11 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a list of packed proto "double" type field values.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, double)} instead.
+ * @hide
*/
@Deprecated
- public void writePackedDouble(long fieldId, double[] val) {
+ public void writePackedDouble(long fieldId, @Nullable double[] val) {
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_DOUBLE);
@@ -934,7 +955,8 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a single proto "float" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, float)} instead.
+ * @hide
*/
@Deprecated
public void writeFloat(long fieldId, float val) {
@@ -954,7 +976,8 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a single repeated proto "float" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, float)} instead.
+ * @hide
*/
@Deprecated
public void writeRepeatedFloat(long fieldId, float val) {
@@ -972,10 +995,11 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a list of packed proto "float" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, float)} instead.
+ * @hide
*/
@Deprecated
- public void writePackedFloat(long fieldId, float[] val) {
+ public void writePackedFloat(long fieldId, @Nullable float[] val) {
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_FLOAT);
@@ -999,7 +1023,7 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Writes a java int as an usigned varint.
*
- * The unadorned int32 type in protobuf is unfortunate because it
+ * <p>The unadorned int32 type in protobuf is unfortunate because it
* is stored in memory as a signed value, but encodes as unsigned
* varints, which are formally always longs. So here, we encode
* negative values as 64 bits, which will get the sign-extension,
@@ -1017,11 +1041,12 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a single proto "int32" type field value.
*
- * Note that these are stored in memory as signed values and written as unsigned
+ * <p>Note that these are stored in memory as signed values and written as unsigned
* varints, which if negative, are 10 bytes long. If you know the data is likely
* to be negative, use "sint32".
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, int)} instead.
+ * @hide
*/
@Deprecated
public void writeInt32(long fieldId, int val) {
@@ -1041,11 +1066,12 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a single repeated proto "int32" type field value.
*
- * Note that these are stored in memory as signed values and written as unsigned
+ * <p>Note that these are stored in memory as signed values and written as unsigned
* varints, which if negative, are 10 bytes long. If you know the data is likely
* to be negative, use "sint32".
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, int)} instead.
+ * @hide
*/
@Deprecated
public void writeRepeatedInt32(long fieldId, int val) {
@@ -1063,14 +1089,15 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a list of packed proto "int32" type field value.
*
- * Note that these are stored in memory as signed values and written as unsigned
+ * <p>Note that these are stored in memory as signed values and written as unsigned
* varints, which if negative, are 10 bytes long. If you know the data is likely
* to be negative, use "sint32".
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, int)} instead.
+ * @hide
*/
@Deprecated
- public void writePackedInt32(long fieldId, int[] val) {
+ public void writePackedInt32(long fieldId, @Nullable int[] val) {
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_INT32);
@@ -1099,7 +1126,8 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a single proto "int64" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, long)} instead.
+ * @hide
*/
@Deprecated
public void writeInt64(long fieldId, long val) {
@@ -1119,7 +1147,8 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a single repeated proto "int64" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, long)} instead.
+ * @hide
*/
@Deprecated
public void writeRepeatedInt64(long fieldId, long val) {
@@ -1137,10 +1166,11 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a list of packed proto "int64" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, long)} instead.
+ * @hide
*/
@Deprecated
- public void writePackedInt64(long fieldId, long[] val) {
+ public void writePackedInt64(long fieldId, @Nullable long[] val) {
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_INT64);
@@ -1168,7 +1198,8 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a single proto "uint32" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, int)} instead.
+ * @hide
*/
@Deprecated
public void writeUInt32(long fieldId, int val) {
@@ -1188,7 +1219,8 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a single repeated proto "uint32" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, int)} instead.
+ * @hide
*/
@Deprecated
public void writeRepeatedUInt32(long fieldId, int val) {
@@ -1206,10 +1238,11 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a list of packed proto "uint32" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, int)} instead.
+ * @hide
*/
@Deprecated
- public void writePackedUInt32(long fieldId, int[] val) {
+ public void writePackedUInt32(long fieldId, @Nullable int[] val) {
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_UINT32);
@@ -1237,7 +1270,8 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a single proto "uint64" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, long)} instead.
+ * @hide
*/
@Deprecated
public void writeUInt64(long fieldId, long val) {
@@ -1257,7 +1291,8 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a single proto "uint64" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, long)} instead.
+ * @hide
*/
@Deprecated
public void writeRepeatedUInt64(long fieldId, long val) {
@@ -1275,10 +1310,11 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a single proto "uint64" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, long)} instead.
+ * @hide
*/
@Deprecated
- public void writePackedUInt64(long fieldId, long[] val) {
+ public void writePackedUInt64(long fieldId, @Nullable long[] val) {
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_UINT64);
@@ -1306,7 +1342,8 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a single proto "sint32" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, int)} instead.
+ * @hide
*/
@Deprecated
public void writeSInt32(long fieldId, int val) {
@@ -1326,7 +1363,8 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a single repeated proto "sint32" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, int)} instead.
+ * @hide
*/
@Deprecated
public void writeRepeatedSInt32(long fieldId, int val) {
@@ -1344,10 +1382,11 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a list of packed proto "sint32" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, int)} instead.
+ * @hide
*/
@Deprecated
- public void writePackedSInt32(long fieldId, int[] val) {
+ public void writePackedSInt32(long fieldId, @Nullable int[] val) {
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_SINT32);
@@ -1375,7 +1414,8 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a single proto "sint64" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, long)} instead.
+ * @hide
*/
@Deprecated
public void writeSInt64(long fieldId, long val) {
@@ -1395,7 +1435,8 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a single repeated proto "sint64" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, long)} instead.
+ * @hide
*/
@Deprecated
public void writeRepeatedSInt64(long fieldId, long val) {
@@ -1413,10 +1454,11 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a list of packed proto "sint64" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, long)} instead.
+ * @hide
*/
@Deprecated
- public void writePackedSInt64(long fieldId, long[] val) {
+ public void writePackedSInt64(long fieldId, @Nullable long[] val) {
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_SINT64);
@@ -1443,7 +1485,8 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a single proto "fixed32" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, int)} instead.
+ * @hide
*/
@Deprecated
public void writeFixed32(long fieldId, int val) {
@@ -1463,7 +1506,8 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a single repeated proto "fixed32" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, int)} instead.
+ * @hide
*/
@Deprecated
public void writeRepeatedFixed32(long fieldId, int val) {
@@ -1481,10 +1525,11 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a list of packed proto "fixed32" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, int)} instead.
+ * @hide
*/
@Deprecated
- public void writePackedFixed32(long fieldId, int[] val) {
+ public void writePackedFixed32(long fieldId, @Nullable int[] val) {
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_FIXED32);
@@ -1507,7 +1552,8 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a single proto "fixed64" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, long)} instead.
+ * @hide
*/
@Deprecated
public void writeFixed64(long fieldId, long val) {
@@ -1527,7 +1573,8 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a single repeated proto "fixed64" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, long)} instead.
+ * @hide
*/
@Deprecated
public void writeRepeatedFixed64(long fieldId, long val) {
@@ -1545,10 +1592,11 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a list of packed proto "fixed64" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, long)} instead.
+ * @hide
*/
@Deprecated
- public void writePackedFixed64(long fieldId, long[] val) {
+ public void writePackedFixed64(long fieldId, @Nullable long[] val) {
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_FIXED64);
@@ -1570,7 +1618,8 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a single proto "sfixed32" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, int)} instead.
+ * @hide
*/
@Deprecated
public void writeSFixed32(long fieldId, int val) {
@@ -1590,7 +1639,8 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a single repeated proto "sfixed32" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, int)} instead.
+ * @hide
*/
@Deprecated
public void writeRepeatedSFixed32(long fieldId, int val) {
@@ -1608,10 +1658,11 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a list of packed proto "sfixed32" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, int)} instead.
+ * @hide
*/
@Deprecated
- public void writePackedSFixed32(long fieldId, int[] val) {
+ public void writePackedSFixed32(long fieldId, @Nullable int[] val) {
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_SFIXED32);
@@ -1634,7 +1685,8 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a single proto "sfixed64" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, long)} instead.
+ * @hide
*/
@Deprecated
public void writeSFixed64(long fieldId, long val) {
@@ -1654,7 +1706,8 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a single repeated proto "sfixed64" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, long)} instead.
+ * @hide
*/
@Deprecated
public void writeRepeatedSFixed64(long fieldId, long val) {
@@ -1672,10 +1725,11 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a list of packed proto "sfixed64" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, long)} instead.
+ * @hide
*/
@Deprecated
- public void writePackedSFixed64(long fieldId, long[] val) {
+ public void writePackedSFixed64(long fieldId, @Nullable long[] val) {
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_SFIXED64);
@@ -1698,7 +1752,8 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a single proto "bool" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, boolean)} instead.
+ * @hide
*/
@Deprecated
public void writeBool(long fieldId, boolean val) {
@@ -1719,7 +1774,8 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a single repeated proto "bool" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, boolean)} instead.
+ * @hide
*/
@Deprecated
public void writeRepeatedBool(long fieldId, boolean val) {
@@ -1737,10 +1793,11 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a list of packed proto "bool" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, boolean)} instead.
+ * @hide
*/
@Deprecated
- public void writePackedBool(long fieldId, boolean[] val) {
+ public void writePackedBool(long fieldId, @Nullable boolean[] val) {
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_BOOL);
@@ -1767,10 +1824,11 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a single proto "string" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, String)} instead.
+ * @hide
*/
@Deprecated
- public void writeString(long fieldId, String val) {
+ public void writeString(long fieldId, @Nullable String val) {
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_STRING);
@@ -1786,10 +1844,11 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a single repeated proto "string" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, String)} instead.
+ * @hide
*/
@Deprecated
- public void writeRepeatedString(long fieldId, String val) {
+ public void writeRepeatedString(long fieldId, @Nullable String val) {
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_STRING);
@@ -1828,10 +1887,11 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a single proto "bytes" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, byte[])} instead.
+ * @hide
*/
@Deprecated
- public void writeBytes(long fieldId, byte[] val) {
+ public void writeBytes(long fieldId, @Nullable byte[] val) {
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_BYTES);
@@ -1848,10 +1908,11 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a single repeated proto "bytes" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, byte[])} instead.
+ * @hide
*/
@Deprecated
- public void writeRepeatedBytes(long fieldId, byte[] val) {
+ public void writeRepeatedBytes(long fieldId, @Nullable byte[] val) {
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_BYTES);
@@ -1874,7 +1935,8 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a single proto enum type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, int)} instead.
+ * @hide
*/
@Deprecated
public void writeEnum(long fieldId, int val) {
@@ -1894,7 +1956,8 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a single repeated proto enum type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, int)} instead.
+ * @hide
*/
@Deprecated
public void writeRepeatedEnum(long fieldId, int val) {
@@ -1912,10 +1975,11 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write a list of packed proto enum type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, int)} instead.
+ * @hide
*/
@Deprecated
- public void writePackedEnum(long fieldId, int[] val) {
+ public void writePackedEnum(long fieldId, @Nullable int[] val) {
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_ENUM);
@@ -1940,7 +2004,8 @@ public final class ProtoOutputStream extends ProtoStream {
* Returns a token which should be passed to endObject. Calls to endObject must be
* nested properly.
*
- * @deprecated Use #start() instead.
+ * @deprecated Use {@link #start(long)} instead.
+ * @hide
*/
@Deprecated
public long startObject(long fieldId) {
@@ -1953,7 +2018,8 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* End a child object. Pass in the token from the correspoinding startObject call.
*
- * @deprecated Use #end() instead.
+ * @deprecated Use {@link #end(long)} instead.
+ * @hide
*/
@Deprecated
public void endObject(long token) {
@@ -1968,7 +2034,8 @@ public final class ProtoOutputStream extends ProtoStream {
* Returns a token which should be passed to endObject. Calls to endObject must be
* nested properly.
*
- * @deprecated Use #start() instead.
+ * @deprecated Use {@link #start(long)} instead.
+ * @hide
*/
@Deprecated
public long startRepeatedObject(long fieldId) {
@@ -1981,7 +2048,8 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* End a child object. Pass in the token from the correspoinding startRepeatedObject call.
*
- * @deprecated Use #end() instead.
+ * @deprecated Use {@link #end(long)} instead.
+ * @hide
*/
@Deprecated
public void endRepeatedObject(long token) {
@@ -2064,12 +2132,13 @@ public final class ProtoOutputStream extends ProtoStream {
}
/**
- * Write an object that has already been flattend.
+ * Write an object that has already been flattened.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, byte[])} instead.
+ * @hide
*/
@Deprecated
- public void writeObject(long fieldId, byte[] value) {
+ public void writeObject(long fieldId, @Nullable byte[] value) {
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_MESSAGE);
@@ -2084,12 +2153,13 @@ public final class ProtoOutputStream extends ProtoStream {
}
/**
- * Write an object that has already been flattend.
+ * Write an object that has already been flattened.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, byte[])} instead.
+ * @hide
*/
@Deprecated
- public void writeRepeatedObject(long fieldId, byte[] value) {
+ public void writeRepeatedObject(long fieldId, @Nullable byte[] value) {
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_MESSAGE);
@@ -2115,11 +2185,11 @@ public final class ProtoOutputStream extends ProtoStream {
}
/**
- * Validates that the fieldId providied is of the type and count from expectedType.
+ * Validates that the fieldId provided is of the type and count from expectedType.
*
- * The type must match exactly to pass this check.
+ * <p>The type must match exactly to pass this check.
*
- * The count must match according to this truth table to pass the check:
+ * <p>The count must match according to this truth table to pass the check:
*
* expectedFlags
* UNKNOWN SINGLE REPEATED PACKED
@@ -2129,7 +2199,7 @@ public final class ProtoOutputStream extends ProtoStream {
* REPEATED x false true false
* PACKED x false true true
*
- * @throws IllegalArgumentException if it is not.
+ * @throws {@link IllegalArgumentException} if it is not.
*
* @return The raw ID of that field.
*/
@@ -2201,7 +2271,7 @@ public final class ProtoOutputStream extends ProtoStream {
}
/**
- * Write a field tage to the stream.
+ * Write a field tag to the stream.
*/
public void writeTag(int id, int wireType) {
mBuffer.writeRawVarint32((id << FIELD_ID_SHIFT) | wireType);
@@ -2239,10 +2309,10 @@ public final class ProtoOutputStream extends ProtoStream {
* Finish the encoding of the data, and return a byte[] with
* the protobuf formatted data.
*
- * After this call, do not call any of the write* functions. The
+ * <p>After this call, do not call any of the write* functions. The
* behavior is undefined.
*/
- public byte[] getBytes() {
+ public @NonNull byte[] getBytes() {
compactIfNecessary();
return mBuffer.getBytes(mBuffer.getReadableSize());
@@ -2289,7 +2359,7 @@ public final class ProtoOutputStream extends ProtoStream {
}
/**
- * First compaction pass. Iterate through the data, and fill in the
+ * First compaction pass. Iterate through the data, and fill in the
* nested object sizes so the next pass can compact them.
*/
private int editEncodedSize(int rawSize) {
@@ -2416,10 +2486,10 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Write remaining data to the output stream. If there is no output stream,
* this function does nothing. Any currently open objects (i.e. ones that
- * have not had endObject called for them will not be written). Whether this
+ * have not had {@link #end(long)} called for them will not be written). Whether this
* writes objects that are closed if there are remaining open objects is
* undefined (current implementation does not write it, future ones will).
- * For now, can either call getBytes() or flush(), but not both.
+ * For now, can either call {@link #getBytes()} or {@link #flush()}, but not both.
*/
public void flush() {
if (mStream == null) {
@@ -2457,7 +2527,7 @@ public final class ProtoOutputStream extends ProtoStream {
/**
* Dump debugging data about the buffers with the given log tag.
*/
- public void dump(String tag) {
+ public void dump(@NonNull String tag) {
Log.d(tag, mBuffer.getDebugString());
mBuffer.dumpBuffers(tag);
}
diff --git a/core/java/android/util/proto/ProtoStream.java b/core/java/android/util/proto/ProtoStream.java
index 9e2e95a5923d..4969d8a7fbe7 100644
--- a/core/java/android/util/proto/ProtoStream.java
+++ b/core/java/android/util/proto/ProtoStream.java
@@ -16,28 +16,104 @@
package android.util.proto;
-import android.annotation.TestApi;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
/**
- * Abstract base class for both protobuf streams.
+ * Base utility class for protobuf streams.
*
- * Contains a set of useful constants and methods used by both
- * ProtoOutputStream and ProtoInputStream
+ * Contains a set of constants and methods used in generated code for
+ * {@link ProtoOutputStream}.
*
* @hide
*/
-@TestApi
-public abstract class ProtoStream {
+public class ProtoStream {
+ /**
+ * Number of bits to shift the field number to form a tag.
+ *
+ * <pre>
+ * // Reading a field number from a tag.
+ * int fieldNumber = tag &gt;&gt;&gt; FIELD_ID_SHIFT;
+ *
+ * // Building a tag from a field number and a wire type.
+ * int tag = (fieldNumber &lt;&lt; FIELD_ID_SHIFT) | wireType;
+ * </pre>
+ *
+ * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
+ * Encoding</a>
+ */
public static final int FIELD_ID_SHIFT = 3;
+
+ /**
+ * Mask to select the wire type from a tag.
+ *
+ * <pre>
+ * // Reading a wire type from a tag.
+ * int wireType = tag &amp; WIRE_TYPE_MASK;
+ *
+ * // Building a tag from a field number and a wire type.
+ * int tag = (fieldNumber &lt;&lt; FIELD_ID_SHIFT) | wireType;
+ * </pre>
+ *
+ * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
+ * Encoding</a>
+ */
public static final int WIRE_TYPE_MASK = (1 << FIELD_ID_SHIFT) - 1;
+
+ /**
+ * Mask to select the field id from a tag.
+ * @hide (not used by anything, and not actually useful, because you also want
+ * to shift when you mask the field id).
+ */
public static final int FIELD_ID_MASK = ~WIRE_TYPE_MASK;
+ /**
+ * Varint wire type code.
+ *
+ * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
+ * Encoding</a>
+ */
public static final int WIRE_TYPE_VARINT = 0;
+
+ /**
+ * Fixed64 wire type code.
+ *
+ * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
+ * Encoding</a>
+ */
public static final int WIRE_TYPE_FIXED64 = 1;
+
+ /**
+ * Length delimited wire type code.
+ *
+ * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
+ * Encoding</a>
+ */
public static final int WIRE_TYPE_LENGTH_DELIMITED = 2;
+
+ /**
+ * Start group wire type code.
+ *
+ * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
+ * Encoding</a>
+ */
public static final int WIRE_TYPE_START_GROUP = 3;
+
+ /**
+ * End group wire type code.
+ *
+ * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
+ * Encoding</a>
+ */
public static final int WIRE_TYPE_END_GROUP = 4;
+
+ /**
+ * Fixed32 wire type code.
+ *
+ * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
+ * Encoding</a>
+ */
public static final int WIRE_TYPE_FIXED32 = 5;
/**
@@ -51,32 +127,147 @@ public abstract class ProtoStream {
*/
public static final long FIELD_TYPE_MASK = 0x0ffL << FIELD_TYPE_SHIFT;
+ /**
+ * Not a real wire type.
+ * @hide
+ */
public static final long FIELD_TYPE_UNKNOWN = 0;
+
+ /*
+ * The FIELD_TYPE_ constants are copied from
+ * external/protobuf/src/google/protobuf/descriptor.h directly, so no
+ * extra mapping needs to be maintained in this case.
+ */
+
/**
- * The types are copied from external/protobuf/src/google/protobuf/descriptor.h directly,
- * so no extra mapping needs to be maintained in this case.
+ * Field type code for double fields. Used to build constants in generated
+ * code for use with the {@link ProtoOutputStream#write(long, double)
+ * ProtoOutputStream.write(long, double)} method.
*/
public static final long FIELD_TYPE_DOUBLE = 1L << FIELD_TYPE_SHIFT;
+
+ /**
+ * Field type code for float fields. Used to build constants in generated
+ * code for use with the {@link ProtoOutputStream#write(long, float)
+ * ProtoOutputStream.write(long, float)} method.
+ */
public static final long FIELD_TYPE_FLOAT = 2L << FIELD_TYPE_SHIFT;
+
+ /**
+ * Field type code for int64 fields. Used to build constants in generated
+ * code for use with the {@link ProtoOutputStream#write(long, long)
+ * ProtoOutputStream.write(long, long)} method.
+ */
public static final long FIELD_TYPE_INT64 = 3L << FIELD_TYPE_SHIFT;
+
+ /**
+ * Field type code for uint64 fields. Used to build constants in generated
+ * code for use with the {@link ProtoOutputStream#write(long, long)
+ * ProtoOutputStream.write(long, long)} method.
+ */
public static final long FIELD_TYPE_UINT64 = 4L << FIELD_TYPE_SHIFT;
+
+ /**
+ * Field type code for int32 fields. Used to build constants in generated
+ * code for use with the {@link ProtoOutputStream#write(long, int)
+ * ProtoOutputStream.write(long, int)} method.
+ */
public static final long FIELD_TYPE_INT32 = 5L << FIELD_TYPE_SHIFT;
+
+ /**
+ * Field type code for fixed64 fields. Used to build constants in generated
+ * code for use with the {@link ProtoOutputStream#write(long, long)
+ * ProtoOutputStream.write(long, long)} method.
+ */
public static final long FIELD_TYPE_FIXED64 = 6L << FIELD_TYPE_SHIFT;
+
+ /**
+ * Field type code for fixed32 fields. Used to build constants in generated
+ * code for use with the {@link ProtoOutputStream#write(long, int)
+ * ProtoOutputStream.write(long, int)} method.
+ */
+
+ /**
+ * Field type code for fixed32 fields. Used to build constants in generated
+ * code for use with the {@link ProtoOutputStream#write(long, int)
+ * ProtoOutputStream.write(long, int)} method.
+ */
public static final long FIELD_TYPE_FIXED32 = 7L << FIELD_TYPE_SHIFT;
+
+ /**
+ * Field type code for bool fields. Used to build constants in generated
+ * code for use with the {@link ProtoOutputStream#write(long, boolean)
+ * ProtoOutputStream.write(long, boolean)} method.
+ */
public static final long FIELD_TYPE_BOOL = 8L << FIELD_TYPE_SHIFT;
+
+ /**
+ * Field type code for string fields. Used to build constants in generated
+ * code for use with the {@link ProtoOutputStream#write(long, String)
+ * ProtoOutputStream.write(long, String)} method.
+ */
public static final long FIELD_TYPE_STRING = 9L << FIELD_TYPE_SHIFT;
+
// public static final long FIELD_TYPE_GROUP = 10L << FIELD_TYPE_SHIFT; // Deprecated.
+
+ /**
+ * Field type code for message fields. Used to build constants in generated
+ * code for use with the {@link ProtoOutputStream#start(long)
+ * ProtoOutputStream.start(long)} method.
+ */
public static final long FIELD_TYPE_MESSAGE = 11L << FIELD_TYPE_SHIFT;
+
+ /**
+ * Field type code for bytes fields. Used to build constants in generated
+ * code for use with the {@link ProtoOutputStream#write(long, byte[])
+ * ProtoOutputStream.write(long, byte[])} method.
+ */
public static final long FIELD_TYPE_BYTES = 12L << FIELD_TYPE_SHIFT;
+
+ /**
+ * Field type code for uint32 fields. Used to build constants in generated
+ * code for use with the {@link ProtoOutputStream#write(long, int)
+ * ProtoOutputStream.write(long, int)} method.
+ */
public static final long FIELD_TYPE_UINT32 = 13L << FIELD_TYPE_SHIFT;
+
+ /**
+ * Field type code for enum fields. Used to build constants in generated
+ * code for use with the {@link ProtoOutputStream#write(long, int)
+ * ProtoOutputStream.write(long, int)} method.
+ */
public static final long FIELD_TYPE_ENUM = 14L << FIELD_TYPE_SHIFT;
+
+ /**
+ * Field type code for sfixed32 fields. Used to build constants in generated
+ * code for use with the {@link ProtoOutputStream#write(long, int)
+ * ProtoOutputStream.write(long, int)} method.
+ */
public static final long FIELD_TYPE_SFIXED32 = 15L << FIELD_TYPE_SHIFT;
+
+ /**
+ * Field type code for sfixed64 fields. Used to build constants in generated
+ * code for use with the {@link ProtoOutputStream#write(long, long)
+ * ProtoOutputStream.write(long, long)} method.
+ */
public static final long FIELD_TYPE_SFIXED64 = 16L << FIELD_TYPE_SHIFT;
+
+ /**
+ * Field type code for sint32 fields. Used to build constants in generated
+ * code for use with the {@link ProtoOutputStream#write(long, int)
+ * ProtoOutputStream.write(long, int)} method.
+ */
public static final long FIELD_TYPE_SINT32 = 17L << FIELD_TYPE_SHIFT;
+
+ /**
+ * Field type code for sint64 fields. Used to build constants in generated
+ * code for use with the {@link ProtoOutputStream#write(long, long)
+ * ProtoOutputStream.write(long, long)} method.
+ */
public static final long FIELD_TYPE_SINT64 = 18L << FIELD_TYPE_SHIFT;
- protected static final String[] FIELD_TYPE_NAMES = new String[]{
+ private static final @NonNull String[] FIELD_TYPE_NAMES = new String[]{
"Double",
"Float",
"Int64",
@@ -100,19 +291,94 @@ public abstract class ProtoStream {
//
// FieldId flags for whether the field is single, repeated or packed.
//
+ /**
+ * Bit offset for building a field id to be used with a
+ * <code>{@link ProtoOutputStream}.write(...)</code>.
+ *
+ * @see #FIELD_COUNT_MASK
+ * @see #FIELD_COUNT_UNKNOWN
+ * @see #FIELD_COUNT_SINGLE
+ * @see #FIELD_COUNT_REPEATED
+ * @see #FIELD_COUNT_PACKED
+ */
public static final int FIELD_COUNT_SHIFT = 40;
+
+ /**
+ * Bit mask for selecting the field count when reading a field id that
+ * is used with a <code>{@link ProtoOutputStream}.write(...)</code> method.
+ *
+ * @see #FIELD_COUNT_SHIFT
+ * @see #FIELD_COUNT_MASK
+ * @see #FIELD_COUNT_UNKNOWN
+ * @see #FIELD_COUNT_SINGLE
+ * @see #FIELD_COUNT_REPEATED
+ * @see #FIELD_COUNT_PACKED
+ * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
+ * Encoding</a>
+ */
public static final long FIELD_COUNT_MASK = 0x0fL << FIELD_COUNT_SHIFT;
+ /**
+ * Unknown field count, encoded into a field id used with a
+ * <code>{@link ProtoOutputStream}.write(...)</code> method.
+ *
+ * @see #FIELD_COUNT_SHIFT
+ * @see #FIELD_COUNT_MASK
+ * @see #FIELD_COUNT_SINGLE
+ * @see #FIELD_COUNT_REPEATED
+ * @see #FIELD_COUNT_PACKED
+ * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
+ * Encoding</a>
+ */
public static final long FIELD_COUNT_UNKNOWN = 0;
+
+ /**
+ * Single field count, encoded into a field id used with a
+ * <code>{@link ProtoOutputStream}.write(...)</code> method.
+ *
+ * @see #FIELD_COUNT_SHIFT
+ * @see #FIELD_COUNT_MASK
+ * @see #FIELD_COUNT_UNKNOWN
+ * @see #FIELD_COUNT_REPEATED
+ * @see #FIELD_COUNT_PACKED
+ * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
+ * Encoding</a>
+ */
public static final long FIELD_COUNT_SINGLE = 1L << FIELD_COUNT_SHIFT;
+
+ /**
+ * Repeated field count, encoded into a field id used with a
+ * <code>{@link ProtoOutputStream}.write(...)</code> method.
+ *
+ * @see #FIELD_COUNT_SHIFT
+ * @see #FIELD_COUNT_MASK
+ * @see #FIELD_COUNT_UNKNOWN
+ * @see #FIELD_COUNT_SINGLE
+ * @see #FIELD_COUNT_PACKED
+ * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
+ * Encoding</a>
+ */
public static final long FIELD_COUNT_REPEATED = 2L << FIELD_COUNT_SHIFT;
+
+ /**
+ * Repeated packed field count, encoded into a field id used with a
+ * <code>{@link ProtoOutputStream}.write(...)</code> method.
+ *
+ * @see #FIELD_COUNT_SHIFT
+ * @see #FIELD_COUNT_MASK
+ * @see #FIELD_COUNT_UNKNOWN
+ * @see #FIELD_COUNT_SINGLE
+ * @see #FIELD_COUNT_REPEATED
+ * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
+ * Encoding</a>
+ */
public static final long FIELD_COUNT_PACKED = 5L << FIELD_COUNT_SHIFT;
/**
* Get the developer-usable name of a field type.
*/
- public static String getFieldTypeString(long fieldType) {
+ public static @Nullable String getFieldTypeString(long fieldType) {
int index = ((int) ((fieldType & FIELD_TYPE_MASK) >>> FIELD_TYPE_SHIFT)) - 1;
if (index >= 0 && index < FIELD_TYPE_NAMES.length) {
return FIELD_TYPE_NAMES[index];
@@ -124,7 +390,7 @@ public abstract class ProtoStream {
/**
* Get the developer-usable name of a field count.
*/
- public static String getFieldCountString(long fieldCount) {
+ public static @Nullable String getFieldCountString(long fieldCount) {
if (fieldCount == FIELD_COUNT_SINGLE) {
return "";
} else if (fieldCount == FIELD_COUNT_REPEATED) {
@@ -139,7 +405,7 @@ public abstract class ProtoStream {
/**
* Get the developer-usable name of a wire type.
*/
- public static String getWireTypeString(int wireType) {
+ public static @Nullable String getWireTypeString(int wireType) {
switch (wireType) {
case WIRE_TYPE_VARINT:
return "Varint";
@@ -161,7 +427,7 @@ public abstract class ProtoStream {
/**
* Get a debug string for a fieldId.
*/
- public static String getFieldIdString(long fieldId) {
+ public static @NonNull String getFieldIdString(long fieldId) {
final long fieldCount = fieldId & FIELD_COUNT_MASK;
String countString = getFieldCountString(fieldCount);
if (countString == null) {
@@ -218,29 +484,39 @@ public abstract class ProtoStream {
/**
* Get the encoded tag size from the token.
+ *
+ * @hide
*/
public static int getTagSizeFromToken(long token) {
return (int) (0x7 & (token >> 61));
}
/**
- * Get whether this is a call to startObject (false) or startRepeatedObject (true).
+ * Get whether the token has the repeated bit set to true or false
+ *
+ * @hide
*/
public static boolean getRepeatedFromToken(long token) {
return (0x1 & (token >> 60)) != 0;
}
/**
- * Get the nesting depth of startObject calls from the token.
+ * Get the nesting depth from the token.
+ *
+ * @hide
*/
public static int getDepthFromToken(long token) {
return (int) (0x01ff & (token >> 51));
}
/**
- * Get the object ID from the token. The object ID is a serial number for the
+ * Get the object ID from the token.
+ *
+ * <p>The object ID is a serial number for the
* startObject calls that have happened on this object. The values are truncated
* to 9 bits, but that is sufficient for error checking.
+ *
+ * @hide
*/
public static int getObjectIdFromToken(long token) {
return (int) (0x07ffff & (token >> 32));
@@ -248,6 +524,8 @@ public abstract class ProtoStream {
/**
* Get the location of the offset recorded in the token.
+ *
+ * @hide
*/
public static int getOffsetFromToken(long token) {
return (int) token;
@@ -255,8 +533,11 @@ public abstract class ProtoStream {
/**
* Convert the object ID to the ordinal value -- the n-th call to startObject.
- * The object IDs start at -1 and count backwards, so that the value is unlikely
+ *
+ * <p>The object IDs start at -1 and count backwards, so that the value is unlikely
* to alias with an actual size field that had been written.
+ *
+ * @hide
*/
public static int convertObjectIdToOrdinal(int objectId) {
return (-1 & 0x07ffff) - objectId;
@@ -265,7 +546,7 @@ public abstract class ProtoStream {
/**
* Return a debugging string of a token.
*/
- public static String token2String(long token) {
+ public static @NonNull String token2String(long token) {
if (token == 0L) {
return "Token(0)";
} else {
@@ -277,4 +558,9 @@ public abstract class ProtoStream {
+ ')';
}
}
+
+ /**
+ * @hide
+ */
+ protected ProtoStream() {}
}
diff --git a/core/java/android/util/proto/ProtoUtils.java b/core/java/android/util/proto/ProtoUtils.java
index 03bf590902c0..a71561b7614b 100644
--- a/core/java/android/util/proto/ProtoUtils.java
+++ b/core/java/android/util/proto/ProtoUtils.java
@@ -24,12 +24,12 @@ import java.io.IOException;
/**
* This class contains a list of helper functions to write common proto in
* //frameworks/base/core/proto/android/base directory
+ * @hide
*/
public class ProtoUtils {
/**
* Dump AggStats to ProtoOutputStream
- * @hide
*/
public static void toAggStatsProto(ProtoOutputStream proto, long fieldId,
long min, long average, long max) {
@@ -42,7 +42,6 @@ public class ProtoUtils {
/**
* Dump Duration to ProtoOutputStream
- * @hide
*/
public static void toDuration(ProtoOutputStream proto, long fieldId, long startMs, long endMs) {
final long token = proto.start(fieldId);
@@ -53,7 +52,6 @@ public class ProtoUtils {
/**
* Helper function to write bit-wise flags to proto as repeated enums
- * @hide
*/
public static void writeBitWiseFlagsToProtoEnum(ProtoOutputStream proto, long fieldId,
int flags, int[] origEnums, int[] protoEnums) {
diff --git a/core/java/android/util/proto/TEST_MAPPING b/core/java/android/util/proto/TEST_MAPPING
index cf9f0772ac2d..5b9874153de3 100644
--- a/core/java/android/util/proto/TEST_MAPPING
+++ b/core/java/android/util/proto/TEST_MAPPING
@@ -2,6 +2,9 @@
"presubmit": [
{
"name": "ProtoInputStreamTests"
+ },
+ {
+ "name": "CtsProtoTestCases"
}
]
-} \ No newline at end of file
+}
diff --git a/core/java/android/util/proto/package.html b/core/java/android/util/proto/package.html
index a636bd457d3d..ef1125b5f248 100644
--- a/core/java/android/util/proto/package.html
+++ b/core/java/android/util/proto/package.html
@@ -1,5 +1,5 @@
+<html>
<body>
Provides utility classes to export protocol buffers from the system.
-
-{@hide}
</body>
+</html> \ No newline at end of file
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index 71ac578e2c68..987edf7761d2 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -20,7 +20,7 @@ import static android.view.DisplayEventReceiver.VSYNC_SOURCE_APP;
import static android.view.DisplayEventReceiver.VSYNC_SOURCE_SURFACE_FLINGER;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.FrameInfo;
import android.graphics.Insets;
import android.hardware.display.DisplayManagerGlobal;
diff --git a/core/java/android/view/ContextThemeWrapper.java b/core/java/android/view/ContextThemeWrapper.java
index 696e048ffed8..876331b5c57f 100644
--- a/core/java/android/view/ContextThemeWrapper.java
+++ b/core/java/android/view/ContextThemeWrapper.java
@@ -18,7 +18,7 @@ package android.view;
import android.annotation.Nullable;
import android.annotation.StyleRes;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.res.AssetManager;
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index ba2509302094..4368115917e5 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -21,9 +21,10 @@ import static android.Manifest.permission.CONFIGURE_DISPLAY_COLOR_MODE;
import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.KeyguardManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -43,7 +44,9 @@ import android.util.Log;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
/**
* Provides information about the size and density of a logical display.
@@ -382,6 +385,23 @@ public final class Display {
/** @hide */
public static final int COLOR_MODE_DISPLAY_P3 = 9;
+ /** @hide **/
+ @IntDef(prefix = {"COLOR_MODE_"}, value = {
+ COLOR_MODE_INVALID,
+ COLOR_MODE_DEFAULT,
+ COLOR_MODE_BT601_625,
+ COLOR_MODE_BT601_625_UNADJUSTED,
+ COLOR_MODE_BT601_525,
+ COLOR_MODE_BT601_525_UNADJUSTED,
+ COLOR_MODE_BT709,
+ COLOR_MODE_DCI_P3,
+ COLOR_MODE_SRGB,
+ COLOR_MODE_ADOBE_RGB,
+ COLOR_MODE_DISPLAY_P3
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ColorMode {}
+
/**
* Indicates that when display is removed, all its activities will be moved to the primary
* display and the topmost activity should become focused.
@@ -857,6 +877,31 @@ public final class Display {
}
/**
+ * <p> Returns true if the connected display can be switched into a mode with minimal
+ * post processing. </p>
+ *
+ * <p> If the Display sink is connected via HDMI, this method will return true if the
+ * display supports either Auto Low Latency Mode or Game Content Type.
+ *
+ * <p> If the Display sink has an internal connection or uses some other protocol than
+ * HDMI, this method will return true if the sink can be switched into an
+ * implementation-defined low latency image processing mode. </p>
+ *
+ * <p> The ability to switch to a mode with minimal post processing may be disabled
+ * by a user setting in the system settings menu. In that case, this method returns
+ * false. </p>
+ *
+ * @see android.view.Window#setPreferMinimalPostProcessing
+ */
+ @SuppressLint("VisiblySynchronized")
+ public boolean isMinimalPostProcessingSupported() {
+ synchronized (this) {
+ updateDisplayInfoLocked();
+ return mDisplayInfo.minimalPostProcessingSupported;
+ }
+ }
+
+ /**
* Request the display applies a color mode.
* @hide
*/
@@ -960,6 +1005,37 @@ public final class Display {
}
/**
+ * Gets the supported wide color gamuts of this device.
+ *
+ * @return Supported WCG color spaces.
+ * @hide
+ */
+ public @ColorMode ColorSpace[] getSupportedWideColorGamut() {
+ synchronized (this) {
+ final ColorSpace[] defaultColorSpaces = new ColorSpace[0];
+ updateDisplayInfoLocked();
+ if (!isWideColorGamut()) {
+ return defaultColorSpaces;
+ }
+
+ final int[] colorModes = getSupportedColorModes();
+ final List<ColorSpace> colorSpaces = new ArrayList<>();
+ for (int colorMode : colorModes) {
+ // Refer to DisplayInfo#isWideColorGamut.
+ switch (colorMode) {
+ case COLOR_MODE_DCI_P3:
+ colorSpaces.add(ColorSpace.get(ColorSpace.Named.DCI_P3));
+ break;
+ case COLOR_MODE_DISPLAY_P3:
+ colorSpaces.add(ColorSpace.get(ColorSpace.Named.DISPLAY_P3));
+ break;
+ }
+ }
+ return colorSpaces.toArray(defaultColorSpaces);
+ }
+ }
+
+ /**
* Gets the app VSYNC offset, in nanoseconds. This is a positive value indicating
* the phase offset of the VSYNC events provided by Choreographer relative to the
* display refresh. For example, if Choreographer reports that the refresh occurred
diff --git a/core/java/android/view/DisplayAdjustments.java b/core/java/android/view/DisplayAdjustments.java
index da4d92fa0c94..834dd7b6e7d8 100644
--- a/core/java/android/view/DisplayAdjustments.java
+++ b/core/java/android/view/DisplayAdjustments.java
@@ -16,7 +16,7 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
diff --git a/core/java/android/view/DisplayEventReceiver.java b/core/java/android/view/DisplayEventReceiver.java
index 91acc4638c26..eaf297cc05d8 100644
--- a/core/java/android/view/DisplayEventReceiver.java
+++ b/core/java/android/view/DisplayEventReceiver.java
@@ -16,7 +16,7 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Looper;
import android.os.MessageQueue;
import android.util.Log;
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index 04e82c72da89..7d455c93729c 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -24,7 +24,7 @@ import static android.view.DisplayInfoProto.LOGICAL_WIDTH;
import static android.view.DisplayInfoProto.NAME;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
@@ -184,6 +184,14 @@ public final class DisplayInfo implements Parcelable {
public Display.HdrCapabilities hdrCapabilities;
/**
+ * Indicates whether the display can be switched into a mode with minimal post
+ * processing.
+ *
+ * @see android.view.Display#isMinimalPostProcessingSupported
+ */
+ public boolean minimalPostProcessingSupported;
+
+ /**
* The logical display density which is the basis for density-independent
* pixels.
*/
@@ -305,6 +313,7 @@ public final class DisplayInfo implements Parcelable {
&& colorMode == other.colorMode
&& Arrays.equals(supportedColorModes, other.supportedColorModes)
&& Objects.equals(hdrCapabilities, other.hdrCapabilities)
+ && minimalPostProcessingSupported == other.minimalPostProcessingSupported
&& logicalDensityDpi == other.logicalDensityDpi
&& physicalXDpi == other.physicalXDpi
&& physicalYDpi == other.physicalYDpi
@@ -346,6 +355,7 @@ public final class DisplayInfo implements Parcelable {
supportedColorModes = Arrays.copyOf(
other.supportedColorModes, other.supportedColorModes.length);
hdrCapabilities = other.hdrCapabilities;
+ minimalPostProcessingSupported = other.minimalPostProcessingSupported;
logicalDensityDpi = other.logicalDensityDpi;
physicalXDpi = other.physicalXDpi;
physicalYDpi = other.physicalYDpi;
@@ -388,6 +398,7 @@ public final class DisplayInfo implements Parcelable {
supportedColorModes[i] = source.readInt();
}
hdrCapabilities = source.readParcelable(null);
+ minimalPostProcessingSupported = source.readBoolean();
logicalDensityDpi = source.readInt();
physicalXDpi = source.readFloat();
physicalYDpi = source.readFloat();
@@ -430,6 +441,7 @@ public final class DisplayInfo implements Parcelable {
dest.writeInt(supportedColorModes[i]);
}
dest.writeParcelable(hdrCapabilities, flags);
+ dest.writeBoolean(minimalPostProcessingSupported);
dest.writeInt(logicalDensityDpi);
dest.writeFloat(physicalXDpi);
dest.writeFloat(physicalYDpi);
diff --git a/core/java/android/view/DisplayListCanvas.java b/core/java/android/view/DisplayListCanvas.java
index 8e6e99a6d949..6035cbebb032 100644
--- a/core/java/android/view/DisplayListCanvas.java
+++ b/core/java/android/view/DisplayListCanvas.java
@@ -16,7 +16,7 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.BaseRecordingCanvas;
import android.graphics.CanvasProperty;
import android.graphics.Paint;
diff --git a/core/java/android/view/DragEvent.java b/core/java/android/view/DragEvent.java
index 2a43bcc00daf..35af0f252d2d 100644
--- a/core/java/android/view/DragEvent.java
+++ b/core/java/android/view/DragEvent.java
@@ -16,7 +16,7 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ClipData;
import android.content.ClipDescription;
import android.os.Parcel;
diff --git a/core/java/android/view/FrameMetrics.java b/core/java/android/view/FrameMetrics.java
index ea66656bfc45..054dff726ca1 100644
--- a/core/java/android/view/FrameMetrics.java
+++ b/core/java/android/view/FrameMetrics.java
@@ -17,7 +17,7 @@
package android.view;
import android.annotation.IntDef;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
diff --git a/core/java/android/view/FrameMetricsObserver.java b/core/java/android/view/FrameMetricsObserver.java
index 0f38e847f4bd..41bc9a742752 100644
--- a/core/java/android/view/FrameMetricsObserver.java
+++ b/core/java/android/view/FrameMetricsObserver.java
@@ -17,11 +17,8 @@
package android.view;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
-import android.os.Looper;
-import android.os.MessageQueue;
-
-import com.android.internal.util.VirtualRefBasePtr;
+import android.graphics.HardwareRendererObserver;
+import android.os.Handler;
import java.lang.ref.WeakReference;
@@ -31,47 +28,39 @@ import java.lang.ref.WeakReference;
*
* @hide
*/
-public class FrameMetricsObserver {
- @UnsupportedAppUsage
- private MessageQueue mMessageQueue;
-
- private WeakReference<Window> mWindow;
-
- @UnsupportedAppUsage
- private FrameMetrics mFrameMetrics;
-
- /* pacage */ Window.OnFrameMetricsAvailableListener mListener;
- /** @hide */
- public VirtualRefBasePtr mNative;
+public class FrameMetricsObserver
+ implements HardwareRendererObserver.OnFrameMetricsAvailableListener {
+ private final WeakReference<Window> mWindow;
+ private final FrameMetrics mFrameMetrics;
+ private final HardwareRendererObserver mObserver;
+ /*package*/ final Window.OnFrameMetricsAvailableListener mListener;
/**
* Creates a FrameMetricsObserver
*
- * @param looper the looper to use when invoking callbacks
+ * @param handler the Handler to use when invoking callbacks
*/
- FrameMetricsObserver(@NonNull Window window, @NonNull Looper looper,
+ FrameMetricsObserver(@NonNull Window window, @NonNull Handler handler,
@NonNull Window.OnFrameMetricsAvailableListener listener) {
- if (looper == null) {
- throw new NullPointerException("looper cannot be null");
- }
-
- mMessageQueue = looper.getQueue();
- if (mMessageQueue == null) {
- throw new IllegalStateException("invalid looper, null message queue\n");
- }
-
- mFrameMetrics = new FrameMetrics();
mWindow = new WeakReference<>(window);
mListener = listener;
+ mFrameMetrics = new FrameMetrics();
+ mObserver = new HardwareRendererObserver(this, mFrameMetrics.mTimingData, handler);
}
- // Called by native on the provided Handler
- @SuppressWarnings("unused")
- @UnsupportedAppUsage
- private void notifyDataAvailable(int dropCount) {
- final Window window = mWindow.get();
- if (window != null) {
- mListener.onFrameMetricsAvailable(window, mFrameMetrics, dropCount);
+ /**
+ * Implementation of OnFrameMetricsAvailableListener
+ * @param dropCountSinceLastInvocation the number of reports dropped since the last time
+ * @Override
+ */
+ public void onFrameMetricsAvailable(int dropCountSinceLastInvocation) {
+ if (mWindow.get() != null) {
+ mListener.onFrameMetricsAvailable(mWindow.get(), mFrameMetrics,
+ dropCountSinceLastInvocation);
}
}
+
+ /*package*/ HardwareRendererObserver getRendererObserver() {
+ return mObserver;
+ }
}
diff --git a/core/java/android/view/GestureDetector.java b/core/java/android/view/GestureDetector.java
index d59ee92dba7e..4d71136d0af1 100644
--- a/core/java/android/view/GestureDetector.java
+++ b/core/java/android/view/GestureDetector.java
@@ -23,7 +23,7 @@ import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SC
import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SINGLE_TAP;
import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Build;
import android.os.Handler;
diff --git a/core/java/android/view/GhostView.java b/core/java/android/view/GhostView.java
index 3286bd623694..a72832760f96 100644
--- a/core/java/android/view/GhostView.java
+++ b/core/java/android/view/GhostView.java
@@ -15,7 +15,7 @@
*/
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.RecordingCanvas;
diff --git a/core/java/android/view/IPinnedStackController.aidl b/core/java/android/view/IPinnedStackController.aidl
index f1d152ba29af..00edb3a29e87 100644
--- a/core/java/android/view/IPinnedStackController.aidl
+++ b/core/java/android/view/IPinnedStackController.aidl
@@ -45,4 +45,17 @@ interface IPinnedStackController {
* {@param animationDuration} suggests the animation duration transitioning to PiP window.
*/
void startAnimation(in Rect destinationBounds, in Rect sourceRectHint, int animationDuration);
+
+ /**
+ * Notifies the controller to reset on bounds animation, if there is any.
+ * This could happen when screen rotation is happening and we need to notify the WM to reset
+ * any running bounds animation on the pinned stack.
+ * {@param bounds} here is the final destination bounds.
+ */
+ void resetBoundsAnimation(in Rect bounds);
+
+ /**
+ * Reports the current default and movement bounds to controller.
+ */
+ void reportBounds(in Rect defaultBounds, in Rect movementBounds);
}
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 0489e14993e3..8f25d89fe08c 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -293,7 +293,7 @@ interface IWindowSession {
* will neither be dispatched to this window nor change the focus to this window. Passing an
* invalid region will remove the area from the exclude region of this window.
*/
- void updateTapExcludeRegion(IWindow window, int regionId, in Region region);
+ void updateTapExcludeRegion(IWindow window, in Region region);
/**
* Called when the client has changed the local insets state, and now the server should reflect
diff --git a/core/java/android/view/InputChannel.java b/core/java/android/view/InputChannel.java
index 5d0d5bd79857..5a64b131faea 100644
--- a/core/java/android/view/InputChannel.java
+++ b/core/java/android/view/InputChannel.java
@@ -16,7 +16,7 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index e723f91887c1..360deddf544d 100644
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -18,7 +18,7 @@ package android.view;
import android.annotation.RequiresPermission;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.hardware.input.InputDeviceIdentifier;
import android.hardware.input.InputManager;
diff --git a/core/java/android/view/InputEvent.java b/core/java/android/view/InputEvent.java
index 4b88a6a54efe..5f9c4801ee66 100644
--- a/core/java/android/view/InputEvent.java
+++ b/core/java/android/view/InputEvent.java
@@ -16,7 +16,7 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/view/InputEventConsistencyVerifier.java b/core/java/android/view/InputEventConsistencyVerifier.java
index e4b1a8d855ec..c0a3cec4547a 100644
--- a/core/java/android/view/InputEventConsistencyVerifier.java
+++ b/core/java/android/view/InputEventConsistencyVerifier.java
@@ -16,7 +16,7 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.util.Log;
diff --git a/core/java/android/view/InputEventReceiver.java b/core/java/android/view/InputEventReceiver.java
index 3080b42e81ce..c67ff6ea0111 100644
--- a/core/java/android/view/InputEventReceiver.java
+++ b/core/java/android/view/InputEventReceiver.java
@@ -16,7 +16,7 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.IBinder;
import android.os.Looper;
import android.os.MessageQueue;
@@ -25,6 +25,7 @@ import android.util.SparseIntArray;
import dalvik.system.CloseGuard;
+import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
/**
@@ -86,6 +87,7 @@ public abstract class InputEventReceiver {
/**
* Disposes the receiver.
+ * Must be called on the same Looper thread to which the receiver is attached.
*/
public void dispose() {
dispose(false);
@@ -109,6 +111,7 @@ public abstract class InputEventReceiver {
mInputChannel = null;
}
mMessageQueue = null;
+ Reference.reachabilityFence(this);
}
/**
diff --git a/core/java/android/view/InputEventSender.java b/core/java/android/view/InputEventSender.java
index c5f4c23b7b15..86a309e3ed79 100644
--- a/core/java/android/view/InputEventSender.java
+++ b/core/java/android/view/InputEventSender.java
@@ -16,7 +16,7 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Looper;
import android.os.MessageQueue;
import android.util.Log;
diff --git a/core/java/android/view/InputFilter.java b/core/java/android/view/InputFilter.java
index 3aaf31ef406f..36d558630da9 100644
--- a/core/java/android/view/InputFilter.java
+++ b/core/java/android/view/InputFilter.java
@@ -16,7 +16,7 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
diff --git a/core/java/android/view/InputQueue.java b/core/java/android/view/InputQueue.java
index 69ebc46cb456..74ce6ac02db3 100644
--- a/core/java/android/view/InputQueue.java
+++ b/core/java/android/view/InputQueue.java
@@ -16,7 +16,7 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Looper;
import android.os.MessageQueue;
import android.util.LongSparseArray;
diff --git a/core/java/android/view/InputWindowHandle.java b/core/java/android/view/InputWindowHandle.java
index 08e4eeb45400..5f74b2a510ca 100644
--- a/core/java/android/view/InputWindowHandle.java
+++ b/core/java/android/view/InputWindowHandle.java
@@ -82,9 +82,6 @@ public final class InputWindowHandle {
// Input event dispatching is paused.
public boolean paused;
- // Window layer.
- public int layer;
-
// Id of process and user that owns the window.
public int ownerPid;
public int ownerUid;
@@ -126,7 +123,6 @@ public final class InputWindowHandle {
@Override
public String toString() {
return new StringBuilder(name != null ? name : "")
- .append(", layer=").append(layer)
.append(", frame=[").append(frameLeft).append(",").append(frameTop).append(",")
.append(frameRight).append(",").append(frameBottom).append("]")
.append(", touchableRegion=").append(touchableRegion)
diff --git a/core/java/android/view/InsetsAnimationControlCallbacks.java b/core/java/android/view/InsetsAnimationControlCallbacks.java
new file mode 100644
index 000000000000..6fdadc60afea
--- /dev/null
+++ b/core/java/android/view/InsetsAnimationControlCallbacks.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+/**
+ * Provide an interface to let InsetsAnimationControlImpl call back into its owner.
+ * @hide
+ */
+public interface InsetsAnimationControlCallbacks {
+ /**
+ * Dispatch the animation started event to all listeners.
+ * @param animation
+ */
+ void dispatchAnimationStarted(WindowInsetsAnimationCallback.InsetsAnimation animation,
+ WindowInsetsAnimationCallback.AnimationBounds bounds);
+
+ /**
+ * Schedule the apply by posting the animation callback.
+ */
+ void scheduleApplyChangeInsets();
+
+ /**
+ * Finish the final steps after the animation.
+ * @param controller The controller used to control the animation.
+ * @param shown {@code true} if the insets are shown.
+ */
+ void notifyFinished(InsetsAnimationControlImpl controller, boolean shown);
+
+ /**
+ * Get the description of the insets state.
+ * @return {@link InsetsState} for adjusting corresponding {@link InsetsSource}.
+ */
+ InsetsState getState();
+
+ /**
+ * Apply the new params to the surface.
+ * @param params The {@link android.view.SyncRtSurfaceTransactionApplier.SurfaceParams} to
+ * apply.
+ */
+ void applySurfaceParams(SyncRtSurfaceTransactionApplier.SurfaceParams... params);
+}
diff --git a/core/java/android/view/InsetsAnimationControlImpl.java b/core/java/android/view/InsetsAnimationControlImpl.java
index cdfd397a732a..771695c2b873 100644
--- a/core/java/android/view/InsetsAnimationControlImpl.java
+++ b/core/java/android/view/InsetsAnimationControlImpl.java
@@ -40,7 +40,6 @@ import android.view.WindowManager.LayoutParams;
import com.android.internal.annotations.VisibleForTesting;
import java.util.ArrayList;
-import java.util.function.Supplier;
/**
* Implements {@link WindowInsetsAnimationController}
@@ -52,9 +51,9 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
private final Rect mTmpFrame = new Rect();
private final WindowInsetsAnimationControlListener mListener;
- private final SparseArray<InsetsSourceConsumer> mConsumers;
+ private final SparseArray<InsetsSourceControl> mControls;
private final SparseIntArray mTypeSideMap = new SparseIntArray();
- private final SparseSetArray<InsetsSourceConsumer> mSideSourceMap = new SparseSetArray<>();
+ private final SparseSetArray<InsetsSourceControl> mSideSourceMap = new SparseSetArray<>();
/** @see WindowInsetsAnimationController#getHiddenStateInsets */
private final Insets mHiddenInsets;
@@ -64,8 +63,7 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
private final Matrix mTmpMatrix = new Matrix();
private final InsetsState mInitialInsetsState;
private final @InsetsType int mTypes;
- private final Supplier<SyncRtSurfaceTransactionApplier> mTransactionApplierSupplier;
- private final InsetsController mController;
+ private final InsetsAnimationControlCallbacks mController;
private final WindowInsetsAnimationCallback.InsetsAnimation mAnimation;
private final Rect mFrame;
private final boolean mFade;
@@ -79,25 +77,23 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
private float mPendingAlpha;
@VisibleForTesting
- public InsetsAnimationControlImpl(SparseArray<InsetsSourceConsumer> consumers, Rect frame,
+ public InsetsAnimationControlImpl(SparseArray<InsetsSourceControl> controls, Rect frame,
InsetsState state, WindowInsetsAnimationControlListener listener,
@InsetsType int types,
- Supplier<SyncRtSurfaceTransactionApplier> transactionApplierSupplier,
- InsetsController controller, long durationMs, boolean fade) {
- mConsumers = consumers;
+ InsetsAnimationControlCallbacks controller, long durationMs, boolean fade) {
+ mControls = controls;
mListener = listener;
mTypes = types;
mFade = fade;
- mTransactionApplierSupplier = transactionApplierSupplier;
mController = controller;
mInitialInsetsState = new InsetsState(state, true /* copySources */);
mCurrentInsets = getInsetsFromState(mInitialInsetsState, frame, null /* typeSideMap */);
- mHiddenInsets = calculateInsets(mInitialInsetsState, frame, consumers, false /* shown */,
+ mHiddenInsets = calculateInsets(mInitialInsetsState, frame, controls, false /* shown */,
null /* typeSideMap */);
- mShownInsets = calculateInsets(mInitialInsetsState, frame, consumers, true /* shown */,
+ mShownInsets = calculateInsets(mInitialInsetsState, frame, controls, true /* shown */,
mTypeSideMap);
mFrame = new Rect(frame);
- buildTypeSourcesMap(mTypeSideMap, mSideSourceMap, mConsumers);
+ buildTypeSourcesMap(mTypeSideMap, mSideSourceMap, mControls);
// TODO: Check for controllability first and wait for IME if needed.
listener.onReady(this, types);
@@ -172,8 +168,7 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
updateLeashesForSide(ISIDE_FLOATING, 0 /* offset */, 0 /* inset */, 0 /* maxInset */,
params, state, alphaOffset);
- SyncRtSurfaceTransactionApplier applier = mTransactionApplierSupplier.get();
- applier.scheduleApply(params.toArray(new SurfaceParams[params.size()]));
+ mController.applySurfaceParams(params.toArray(new SurfaceParams[params.size()]));
mCurrentInsets = mPendingInsets;
mAnimation.setFraction(mPendingFraction);
mCurrentAlpha = 1 - alphaOffset;
@@ -189,9 +184,9 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
return;
}
InsetsState state = new InsetsState(mController.getState());
- for (int i = mConsumers.size() - 1; i >= 0; i--) {
- InsetsSourceConsumer consumer = mConsumers.valueAt(i);
- state.getSource(consumer.getType()).setVisible(shown);
+ for (int i = mControls.size() - 1; i >= 0; i--) {
+ InsetsSourceControl control = mControls.valueAt(i);
+ state.getSource(control.getType()).setVisible(shown);
}
Insets insets = getInsetsFromState(state, mFrame, null /* typeSideMap */);
setInsetsAndAlpha(insets, 1f /* alpha */, shown ? 1f : 0f /* fraction */);
@@ -222,10 +217,12 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
}
private Insets calculateInsets(InsetsState state, Rect frame,
- SparseArray<InsetsSourceConsumer> consumers, boolean shown,
+ SparseArray<InsetsSourceControl> controls, boolean shown,
@Nullable @InternalInsetsSide SparseIntArray typeSideMap) {
- for (int i = consumers.size() - 1; i >= 0; i--) {
- state.getSource(consumers.valueAt(i).getType()).setVisible(shown);
+ for (int i = controls.size() - 1; i >= 0; i--) {
+ // control may be null if it got revoked.
+ if (controls.valueAt(i) == null) continue;
+ state.getSource(controls.valueAt(i).getType()).setVisible(shown);
}
return getInsetsFromState(state, frame, typeSideMap);
}
@@ -233,7 +230,7 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
private Insets getInsetsFromState(InsetsState state, Rect frame,
@Nullable @InternalInsetsSide SparseIntArray typeSideMap) {
return state.calculateInsets(frame, false /* isScreenRound */,
- false /* alwaysConsumerNavBar */, null /* displayCutout */,
+ false /* alwaysConsumeSystemBars */, null /* displayCutout */,
null /* legacyContentInsets */, null /* legacyStableInsets */,
LayoutParams.SOFT_INPUT_ADJUST_RESIZE /* legacySoftInputMode*/, typeSideMap)
.getInsets(mTypes);
@@ -252,20 +249,19 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
private void updateLeashesForSide(@InternalInsetsSide int side, int offset, int inset,
int maxInset, ArrayList<SurfaceParams> surfaceParams, InsetsState state, Float alpha) {
- ArraySet<InsetsSourceConsumer> items = mSideSourceMap.get(side);
+ ArraySet<InsetsSourceControl> items = mSideSourceMap.get(side);
if (items == null) {
return;
}
// TODO: Implement behavior when inset spans over multiple types
for (int i = items.size() - 1; i >= 0; i--) {
- final InsetsSourceConsumer consumer = items.valueAt(i);
- final InsetsSource source = mInitialInsetsState.getSource(consumer.getType());
- final InsetsSourceControl control = consumer.getControl();
+ final InsetsSourceControl control = items.valueAt(i);
+ final InsetsSource source = mInitialInsetsState.getSource(control.getType());
if (control == null) {
- // Control may not be available for consumer yet or revoked.
+ // TODO: remove this check when we ensure the elements will not be null.
continue;
}
- final SurfaceControl leash = consumer.getControl().getLeash();
+ final SurfaceControl leash = control.getLeash();
mTmpMatrix.setTranslate(control.getSurfacePosition().x, control.getSurfacePosition().y);
mTmpFrame.set(source.getFrame());
@@ -279,7 +275,8 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
alpha = mFade ? ((float) maxInset / inset * 0.3f + 0.7f) : alpha;
surfaceParams.add(new SurfaceParams(leash, alpha, mTmpMatrix,
null /* windowCrop */, 0 /* layer */, 0f /* cornerRadius*/,
- side == ISIDE_FLOATING ? consumer.isVisible() : inset != 0 /* visible */));
+ side == ISIDE_FLOATING ? state.getSource(source.getType()).isVisible()
+ : inset != 0 /* visible */));
}
}
}
@@ -307,18 +304,18 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
}
private static void buildTypeSourcesMap(SparseIntArray typeSideMap,
- SparseSetArray<InsetsSourceConsumer> sideSourcesMap,
- SparseArray<InsetsSourceConsumer> consumers) {
+ SparseSetArray<InsetsSourceControl> sideSourcesMap,
+ SparseArray<InsetsSourceControl> controls) {
for (int i = typeSideMap.size() - 1; i >= 0; i--) {
final int type = typeSideMap.keyAt(i);
final int side = typeSideMap.valueAt(i);
- final InsetsSourceConsumer consumer = consumers.get(type);
- if (consumer == null) {
+ final InsetsSourceControl control = controls.get(type);
+ if (control == null) {
// If the types that we are controlling are less than the types that the system has,
- // there can be some null consumers.
+ // there can be some null controllers.
continue;
}
- sideSourcesMap.add(side, consumer);
+ sideSourcesMap.add(side, control);
}
}
}
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index 5563d629f25e..4d4ace27cac9 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -53,7 +53,7 @@ import java.util.ArrayList;
* Implements {@link WindowInsetsController} on the client.
* @hide
*/
-public class InsetsController implements WindowInsetsController {
+public class InsetsController implements WindowInsetsController, InsetsAnimationControlCallbacks {
private static final int ANIMATION_DURATION_SHOW_MS = 275;
private static final int ANIMATION_DURATION_HIDE_MS = 340;
@@ -186,6 +186,8 @@ public class InsetsController implements WindowInsetsController {
private int mLastLegacySoftInputMode;
+ private SyncRtSurfaceTransactionApplier mApplier;
+
public InsetsController(ViewRootImpl viewRoot) {
mViewRoot = viewRoot;
mAnimCallback = () -> {
@@ -375,9 +377,10 @@ public class InsetsController implements WindowInsetsController {
final ArraySet<Integer> internalTypes = mState.toInternalType(types);
final SparseArray<InsetsSourceConsumer> consumers = new SparseArray<>();
+ final SparseArray<InsetsSourceControl> controls = new SparseArray<>();
- Pair<Integer, Boolean> typesReadyPair = collectConsumers(
- fromIme, internalTypes, consumers, listener);
+ Pair<Integer, Boolean> typesReadyPair = collectSourceControls(
+ fromIme, internalTypes, controls, listener);
int typesReady = typesReadyPair.first;
boolean isReady = typesReadyPair.second;
if (!isReady) {
@@ -388,24 +391,23 @@ public class InsetsController implements WindowInsetsController {
}
// pending types from previous request.
- typesReady = collectPendingConsumers(typesReady, consumers);
+ typesReady = collectPendingTypes(typesReady);
if (typesReady == 0) {
listener.onCancelled();
return;
}
- final InsetsAnimationControlImpl controller = new InsetsAnimationControlImpl(consumers,
- frame, mState, listener, typesReady,
- () -> new SyncRtSurfaceTransactionApplier(mViewRoot.mView), this, durationMs, fade);
+ final InsetsAnimationControlImpl controller = new InsetsAnimationControlImpl(controls,
+ frame, mState, listener, typesReady, this, durationMs, fade);
mAnimationControls.add(controller);
}
/**
* @return Pair of (types ready to animate, is ready to animate).
*/
- private Pair<Integer, Boolean> collectConsumers(boolean fromIme,
- ArraySet<Integer> internalTypes, SparseArray<InsetsSourceConsumer> consumers,
+ private Pair<Integer, Boolean> collectSourceControls(boolean fromIme,
+ ArraySet<Integer> internalTypes, SparseArray<InsetsSourceControl> controls,
WindowInsetsAnimationControlListener listener) {
int typesReady = 0;
boolean isReady = true;
@@ -439,22 +441,14 @@ public class InsetsController implements WindowInsetsController {
}
typesReady |= InsetsState.toPublicType(consumer.getType());
}
- consumers.put(consumer.getType(), consumer);
+ controls.put(consumer.getType(), consumer.getControl());
}
return new Pair<>(typesReady, isReady);
}
- private int collectPendingConsumers(@InsetsType int typesReady,
- SparseArray<InsetsSourceConsumer> consumers) {
- if (mPendingTypesToShow != 0) {
- typesReady |= mPendingTypesToShow;
- final ArraySet<Integer> internalTypes = mState.toInternalType(mPendingTypesToShow);
- for (int i = internalTypes.size() - 1; i >= 0; i--) {
- InsetsSourceConsumer consumer = getSourceConsumer(internalTypes.valueAt(i));
- consumers.put(consumer.getType(), consumer);
- }
- mPendingTypesToShow = 0;
- }
+ private int collectPendingTypes(@InsetsType int typesReady) {
+ typesReady |= mPendingTypesToShow;
+ mPendingTypesToShow = 0;
return typesReady;
}
@@ -468,6 +462,7 @@ public class InsetsController implements WindowInsetsController {
}
@VisibleForTesting
+ @Override
public void notifyFinished(InsetsAnimationControlImpl controller, boolean shown) {
mAnimationControls.remove(controller);
if (shown) {
@@ -477,6 +472,17 @@ public class InsetsController implements WindowInsetsController {
}
}
+ @Override
+ public void applySurfaceParams(final SyncRtSurfaceTransactionApplier.SurfaceParams... params) {
+ if (mApplier == null) {
+ if (mViewRoot.mView == null) {
+ throw new IllegalStateException("View of the ViewRootImpl is not initiated.");
+ }
+ mApplier = new SyncRtSurfaceTransactionApplier(mViewRoot.mView);
+ }
+ mApplier.scheduleApply(params);
+ }
+
void notifyControlRevoked(InsetsSourceConsumer consumer) {
for (int i = mAnimationControls.size() - 1; i >= 0; i--) {
InsetsAnimationControlImpl control = mAnimationControls.get(i);
@@ -620,6 +626,7 @@ public class InsetsController implements WindowInsetsController {
}
@VisibleForTesting
+ @Override
public void dispatchAnimationStarted(InsetsAnimation animation, AnimationBounds bounds) {
mViewRoot.mView.dispatchWindowInsetsAnimationStarted(animation, bounds);
}
@@ -630,6 +637,7 @@ public class InsetsController implements WindowInsetsController {
}
@VisibleForTesting
+ @Override
public void scheduleApplyChangeInsets() {
if (!mAnimCallbackScheduled) {
mViewRoot.mChoreographer.postCallback(Choreographer.CALLBACK_INSETS_ANIMATION,
diff --git a/core/java/android/view/InsetsSourceControl.java b/core/java/android/view/InsetsSourceControl.java
index bcf5c7875894..7be3e6a42475 100644
--- a/core/java/android/view/InsetsSourceControl.java
+++ b/core/java/android/view/InsetsSourceControl.java
@@ -39,6 +39,17 @@ public class InsetsSourceControl implements Parcelable {
mSurfacePosition = surfacePosition;
}
+ public InsetsSourceControl(InsetsSourceControl other) {
+ mType = other.mType;
+ if (other.mLeash != null) {
+ mLeash = new SurfaceControl();
+ mLeash.copyFrom(other.mLeash);
+ } else {
+ mLeash = null;
+ }
+ mSurfacePosition = new Point(other.mSurfacePosition);
+ }
+
public int getType() {
return mType;
}
diff --git a/core/java/android/view/KeyCharacterMap.java b/core/java/android/view/KeyCharacterMap.java
index bd033480ea87..90e0f3f89a0f 100644
--- a/core/java/android/view/KeyCharacterMap.java
+++ b/core/java/android/view/KeyCharacterMap.java
@@ -16,7 +16,7 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.hardware.input.InputManager;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 60db6a57d187..c638717b13c0 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -20,7 +20,7 @@ import static android.view.Display.INVALID_DISPLAY;
import android.annotation.NonNull;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index 75862e01d41c..1afe11ea1acf 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -21,7 +21,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.res.Resources;
@@ -31,10 +31,7 @@ import android.graphics.Canvas;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
-import android.os.SystemProperties;
import android.os.Trace;
-import android.provider.DeviceConfig;
-import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 1c94e02462d0..c3c7b950838b 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -22,7 +22,7 @@ import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.annotation.IntDef;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Matrix;
import android.os.Build;
import android.os.Parcel;
diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java
index d54e9d58356b..8ec5df85dc7b 100644
--- a/core/java/android/view/NotificationHeaderView.java
+++ b/core/java/android/view/NotificationHeaderView.java
@@ -17,9 +17,9 @@
package android.view;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.app.AppOpsManager;
import android.app.Notification;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
diff --git a/core/java/android/view/PointerIcon.java b/core/java/android/view/PointerIcon.java
index dfe34c80bb8f..18d0d7b98a42 100644
--- a/core/java/android/view/PointerIcon.java
+++ b/core/java/android/view/PointerIcon.java
@@ -17,8 +17,8 @@
package android.view;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.XmlRes;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
diff --git a/core/java/android/view/RemoteAnimationAdapter.java b/core/java/android/view/RemoteAnimationAdapter.java
index c686440171a2..166d3baa2fdf 100644
--- a/core/java/android/view/RemoteAnimationAdapter.java
+++ b/core/java/android/view/RemoteAnimationAdapter.java
@@ -16,8 +16,8 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityOptions;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/view/RemoteAnimationDefinition.java b/core/java/android/view/RemoteAnimationDefinition.java
index da599efb6eee..5a8ac544e27e 100644
--- a/core/java/android/view/RemoteAnimationDefinition.java
+++ b/core/java/android/view/RemoteAnimationDefinition.java
@@ -19,12 +19,15 @@ package android.view;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.app.WindowConfiguration;
import android.app.WindowConfiguration.ActivityType;
+import android.compat.annotation.UnsupportedAppUsage;
+import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.RemoteException;
import android.util.ArraySet;
+import android.util.Slog;
import android.util.SparseArray;
import android.view.WindowManager.TransitionType;
@@ -124,6 +127,20 @@ public class RemoteAnimationDefinition implements Parcelable {
}
}
+ /**
+ * Links the death of the runner to the provided death recipient.
+ */
+ public void linkToDeath(IBinder.DeathRecipient deathRecipient) {
+ try {
+ for (int i = 0; i < mTransitionAnimationMap.size(); i++) {
+ mTransitionAnimationMap.valueAt(i).adapter.getRunner().asBinder()
+ .linkToDeath(deathRecipient, 0 /* flags */);
+ }
+ } catch (RemoteException e) {
+ Slog.e("RemoteAnimationDefinition", "Failed to link to death recipient");
+ }
+ }
+
@Override
public int describeContents() {
return 0;
diff --git a/core/java/android/view/RemoteAnimationTarget.java b/core/java/android/view/RemoteAnimationTarget.java
index b87348257e0e..b04372a1ce19 100644
--- a/core/java/android/view/RemoteAnimationTarget.java
+++ b/core/java/android/view/RemoteAnimationTarget.java
@@ -30,8 +30,8 @@ import static android.view.RemoteAnimationTargetProto.TASK_ID;
import static android.view.RemoteAnimationTargetProto.WINDOW_CONFIGURATION;
import android.annotation.IntDef;
-import android.annotation.UnsupportedAppUsage;
import android.app.WindowConfiguration;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Parcel;
diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java
index 93f52a04d626..06cb51927ba8 100644
--- a/core/java/android/view/RenderNodeAnimator.java
+++ b/core/java/android/view/RenderNodeAnimator.java
@@ -19,7 +19,7 @@ package android.view;
import android.animation.Animator;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.CanvasProperty;
import android.graphics.Paint;
import android.graphics.RecordingCanvas;
diff --git a/core/java/android/view/ScaleGestureDetector.java b/core/java/android/view/ScaleGestureDetector.java
index 1d721516a979..346f76cace7d 100644
--- a/core/java/android/view/ScaleGestureDetector.java
+++ b/core/java/android/view/ScaleGestureDetector.java
@@ -16,7 +16,7 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Build;
import android.os.Handler;
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index dac62821fe90..7707ad163b85 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -18,7 +18,7 @@ package android.view;
import android.annotation.IntDef;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.CompatibilityInfo.Translator;
import android.graphics.Canvas;
import android.graphics.ColorSpace;
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 87628da42599..f6d6522f80d6 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -32,7 +32,7 @@ import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Size;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Bitmap;
import android.graphics.ColorSpace;
import android.graphics.GraphicBuffer;
@@ -158,11 +158,10 @@ public final class SurfaceControl implements Parcelable {
IBinder displayToken, long numFrames, long timestamp);
private static native int nativeGetActiveConfig(IBinder displayToken);
private static native boolean nativeSetActiveConfig(IBinder displayToken, int id);
- private static native boolean nativeSetAllowedDisplayConfigs(IBinder displayToken,
- int[] allowedConfigs);
- private static native int[] nativeGetAllowedDisplayConfigs(IBinder displayToken);
private static native boolean nativeSetDesiredDisplayConfigSpecs(IBinder displayToken,
SurfaceControl.DesiredDisplayConfigSpecs desiredDisplayConfigSpecs);
+ private static native SurfaceControl.DesiredDisplayConfigSpecs
+ nativeGetDesiredDisplayConfigSpecs(IBinder displayToken);
private static native int[] nativeGetDisplayColorModes(IBinder displayToken);
private static native SurfaceControl.DisplayPrimaries nativeGetDisplayNativePrimaries(
IBinder displayToken);
@@ -170,6 +169,8 @@ public final class SurfaceControl implements Parcelable {
private static native int nativeGetActiveColorMode(IBinder displayToken);
private static native boolean nativeSetActiveColorMode(IBinder displayToken,
int colorMode);
+ private static native void nativeSetAutoLowLatencyMode(IBinder displayToken, boolean on);
+ private static native void nativeSetGameContentType(IBinder displayToken, boolean on);
private static native void nativeSetDisplayPowerMode(
IBinder displayToken, int mode);
private static native void nativeDeferTransactionUntil(long transactionObj, long nativeObject,
@@ -187,6 +188,9 @@ public final class SurfaceControl implements Parcelable {
private static native Display.HdrCapabilities nativeGetHdrCapabilities(IBinder displayToken);
+ private static native boolean nativeGetAutoLowLatencyModeSupport(IBinder displayToken);
+ private static native boolean nativeGetGameContentTypeSupport(IBinder displayToken);
+
private static native void nativeSetInputWindowInfo(long transactionObj, long nativeObject,
InputWindowHandle handle);
@@ -442,10 +446,16 @@ public final class SurfaceControl implements Parcelable {
public static final int METADATA_TASK_ID = 3;
/**
+ * The style of mouse cursor and hotspot.
+ * @hide
+ */
+ public static final int METADATA_MOUSE_CURSOR = 4;
+
+ /**
* Accessibility ID to allow association between surfaces and accessibility tree.
* @hide
*/
- public static final int METADATA_ACCESSIBILITY_ID = 4;
+ public static final int METADATA_ACCESSIBILITY_ID = 5;
/**
* A wrapper around GraphicBuffer that contains extra information about how to
@@ -1474,58 +1484,60 @@ public final class SurfaceControl implements Parcelable {
}
/**
+ * Contains information about desired display configuration.
+ *
* @hide
*/
- public static boolean setAllowedDisplayConfigs(IBinder displayToken, int[] allowedConfigs) {
- if (displayToken == null) {
- throw new IllegalArgumentException("displayToken must not be null");
- }
- if (allowedConfigs == null) {
- throw new IllegalArgumentException("allowedConfigs must not be null");
+ public static final class DesiredDisplayConfigSpecs {
+ public int defaultConfig;
+ public float minRefreshRate;
+ public float maxRefreshRate;
+
+ public DesiredDisplayConfigSpecs() {}
+
+ public DesiredDisplayConfigSpecs(DesiredDisplayConfigSpecs other) {
+ copyFrom(other);
}
- return nativeSetAllowedDisplayConfigs(displayToken, allowedConfigs);
- }
+ public DesiredDisplayConfigSpecs(
+ int defaultConfig, float minRefreshRate, float maxRefreshRate) {
+ this.defaultConfig = defaultConfig;
+ this.minRefreshRate = minRefreshRate;
+ this.maxRefreshRate = maxRefreshRate;
+ }
- /**
- * @hide
- */
- public static int[] getAllowedDisplayConfigs(IBinder displayToken) {
- if (displayToken == null) {
- throw new IllegalArgumentException("displayToken must not be null");
+ @Override
+ public boolean equals(Object o) {
+ return o instanceof DesiredDisplayConfigSpecs && equals((DesiredDisplayConfigSpecs) o);
}
- return nativeGetAllowedDisplayConfigs(displayToken);
- }
- /**
- * Contains information about desired display configuration.
- *
- * @hide
- */
- public static final class DesiredDisplayConfigSpecs {
/**
- * @hide
+ * Tests for equality.
*/
- public int mDefaultModeId;
+ public boolean equals(DesiredDisplayConfigSpecs other) {
+ return other != null && defaultConfig == other.defaultConfig
+ && minRefreshRate == other.minRefreshRate
+ && maxRefreshRate == other.maxRefreshRate;
+ }
- /**
- * @hide
- */
- public float mMinRefreshRate;
+ @Override
+ public int hashCode() {
+ return 0; // don't care
+ }
/**
- * @hide
+ * Copies the supplied object's values to this object.
*/
- public float mMaxRefreshRate;
+ public void copyFrom(DesiredDisplayConfigSpecs other) {
+ defaultConfig = other.defaultConfig;
+ minRefreshRate = other.minRefreshRate;
+ maxRefreshRate = other.maxRefreshRate;
+ }
- /**
- * @hide
- */
- public DesiredDisplayConfigSpecs(
- int defaultModeId, float minRefreshRate, float maxRefreshRate) {
- mDefaultModeId = defaultModeId;
- mMinRefreshRate = minRefreshRate;
- mMaxRefreshRate = maxRefreshRate;
+ @Override
+ public String toString() {
+ return String.format("defaultConfig=%d min=%.0f max=%.0f", defaultConfig,
+ minRefreshRate, maxRefreshRate);
}
}
@@ -1544,6 +1556,18 @@ public final class SurfaceControl implements Parcelable {
/**
* @hide
*/
+ public static SurfaceControl.DesiredDisplayConfigSpecs getDesiredDisplayConfigSpecs(
+ IBinder displayToken) {
+ if (displayToken == null) {
+ throw new IllegalArgumentException("displayToken must not be null");
+ }
+
+ return nativeGetDesiredDisplayConfigSpecs(displayToken);
+ }
+
+ /**
+ * @hide
+ */
public static int[] getDisplayColorModes(IBinder displayToken) {
if (displayToken == null) {
throw new IllegalArgumentException("displayToken must not be null");
@@ -1670,6 +1694,28 @@ public final class SurfaceControl implements Parcelable {
/**
* @hide
*/
+ public static void setAutoLowLatencyMode(IBinder displayToken, boolean on) {
+ if (displayToken == null) {
+ throw new IllegalArgumentException("displayToken must not be null");
+ }
+
+ nativeSetAutoLowLatencyMode(displayToken, on);
+ }
+
+ /**
+ * @hide
+ */
+ public static void setGameContentType(IBinder displayToken, boolean on) {
+ if (displayToken == null) {
+ throw new IllegalArgumentException("displayToken must not be null");
+ }
+
+ nativeSetGameContentType(displayToken, on);
+ }
+
+ /**
+ * @hide
+ */
@UnsupportedAppUsage
public static void setDisplayProjection(IBinder displayToken,
int orientation, Rect layerStackRect, Rect displayRect) {
@@ -1721,6 +1767,28 @@ public final class SurfaceControl implements Parcelable {
/**
* @hide
*/
+ public static boolean getAutoLowLatencyModeSupport(IBinder displayToken) {
+ if (displayToken == null) {
+ throw new IllegalArgumentException("displayToken must not be null");
+ }
+
+ return nativeGetAutoLowLatencyModeSupport(displayToken);
+ }
+
+ /**
+ * @hide
+ */
+ public static boolean getGameContentTypeSupport(IBinder displayToken) {
+ if (displayToken == null) {
+ throw new IllegalArgumentException("displayToken must not be null");
+ }
+
+ return nativeGetGameContentTypeSupport(displayToken);
+ }
+
+ /**
+ * @hide
+ */
@UnsupportedAppUsage
public static IBinder createDisplay(String name, boolean secure) {
if (name == null) {
@@ -2092,6 +2160,13 @@ public final class SurfaceControl implements Parcelable {
Runnable mFreeNativeResources;
/**
+ * @hide
+ */
+ protected void checkPreconditions(SurfaceControl sc) {
+ sc.checkNotReleased();
+ }
+
+ /**
* Open a new transaction object. The transaction may be filed with commands to
* manipulate {@link SurfaceControl} instances, and then applied atomically with
* {@link #apply}. Eventually the user should invoke {@link #close}, when the object
@@ -2155,7 +2230,7 @@ public final class SurfaceControl implements Parcelable {
*/
@NonNull
public Transaction setVisibility(@NonNull SurfaceControl sc, boolean visible) {
- sc.checkNotReleased();
+ checkPreconditions(sc);
if (visible) {
return show(sc);
} else {
@@ -2172,7 +2247,7 @@ public final class SurfaceControl implements Parcelable {
*/
@UnsupportedAppUsage
public Transaction show(SurfaceControl sc) {
- sc.checkNotReleased();
+ checkPreconditions(sc);
nativeSetFlags(mNativeObject, sc.mNativeObject, 0, SURFACE_HIDDEN);
return this;
}
@@ -2186,7 +2261,7 @@ public final class SurfaceControl implements Parcelable {
*/
@UnsupportedAppUsage
public Transaction hide(SurfaceControl sc) {
- sc.checkNotReleased();
+ checkPreconditions(sc);
nativeSetFlags(mNativeObject, sc.mNativeObject, SURFACE_HIDDEN, SURFACE_HIDDEN);
return this;
}
@@ -2196,7 +2271,7 @@ public final class SurfaceControl implements Parcelable {
*/
@UnsupportedAppUsage
public Transaction setPosition(SurfaceControl sc, float x, float y) {
- sc.checkNotReleased();
+ checkPreconditions(sc);
nativeSetPosition(mNativeObject, sc.mNativeObject, x, y);
return this;
}
@@ -2213,7 +2288,7 @@ public final class SurfaceControl implements Parcelable {
@NonNull
public Transaction setBufferSize(@NonNull SurfaceControl sc,
@IntRange(from = 0) int w, @IntRange(from = 0) int h) {
- sc.checkNotReleased();
+ checkPreconditions(sc);
mResizedSurfaces.put(sc, new Point(w, h));
nativeSetSize(mNativeObject, sc.mNativeObject, w, h);
return this;
@@ -2231,7 +2306,7 @@ public final class SurfaceControl implements Parcelable {
@NonNull
public Transaction setLayer(@NonNull SurfaceControl sc,
@IntRange(from = Integer.MIN_VALUE, to = Integer.MAX_VALUE) int z) {
- sc.checkNotReleased();
+ checkPreconditions(sc);
nativeSetLayer(mNativeObject, sc.mNativeObject, z);
return this;
}
@@ -2240,7 +2315,7 @@ public final class SurfaceControl implements Parcelable {
* @hide
*/
public Transaction setRelativeLayer(SurfaceControl sc, SurfaceControl relativeTo, int z) {
- sc.checkNotReleased();
+ checkPreconditions(sc);
nativeSetRelativeLayer(mNativeObject, sc.mNativeObject, relativeTo.mNativeObject, z);
return this;
}
@@ -2249,7 +2324,7 @@ public final class SurfaceControl implements Parcelable {
* @hide
*/
public Transaction setTransparentRegionHint(SurfaceControl sc, Region transparentRegion) {
- sc.checkNotReleased();
+ checkPreconditions(sc);
nativeSetTransparentRegionHint(mNativeObject,
sc.mNativeObject, transparentRegion);
return this;
@@ -2265,7 +2340,7 @@ public final class SurfaceControl implements Parcelable {
@NonNull
public Transaction setAlpha(@NonNull SurfaceControl sc,
@FloatRange(from = 0.0, to = 1.0) float alpha) {
- sc.checkNotReleased();
+ checkPreconditions(sc);
nativeSetAlpha(mNativeObject, sc.mNativeObject, alpha);
return this;
}
@@ -2274,7 +2349,7 @@ public final class SurfaceControl implements Parcelable {
* @hide
*/
public Transaction setInputWindowInfo(SurfaceControl sc, InputWindowHandle handle) {
- sc.checkNotReleased();
+ checkPreconditions(sc);
nativeSetInputWindowInfo(mNativeObject, sc.mNativeObject, handle);
return this;
}
@@ -2304,7 +2379,7 @@ public final class SurfaceControl implements Parcelable {
@NonNull
public Transaction setGeometry(@NonNull SurfaceControl sc, @Nullable Rect sourceCrop,
@Nullable Rect destFrame, @Surface.Rotation int orientation) {
- sc.checkNotReleased();
+ checkPreconditions(sc);
nativeSetGeometry(mNativeObject, sc.mNativeObject, sourceCrop, destFrame, orientation);
return this;
}
@@ -2315,7 +2390,7 @@ public final class SurfaceControl implements Parcelable {
@UnsupportedAppUsage
public Transaction setMatrix(SurfaceControl sc,
float dsdx, float dtdx, float dtdy, float dsdy) {
- sc.checkNotReleased();
+ checkPreconditions(sc);
nativeSetMatrix(mNativeObject, sc.mNativeObject,
dsdx, dtdx, dtdy, dsdy);
return this;
@@ -2349,7 +2424,7 @@ public final class SurfaceControl implements Parcelable {
*/
public Transaction setColorTransform(SurfaceControl sc, @Size(9) float[] matrix,
@Size(3) float[] translation) {
- sc.checkNotReleased();
+ checkPreconditions(sc);
nativeSetColorTransform(mNativeObject, sc.mNativeObject, matrix, translation);
return this;
}
@@ -2361,7 +2436,7 @@ public final class SurfaceControl implements Parcelable {
* @hide
*/
public Transaction setColorSpaceAgnostic(SurfaceControl sc, boolean agnostic) {
- sc.checkNotReleased();
+ checkPreconditions(sc);
nativeSetColorSpaceAgnostic(mNativeObject, sc.mNativeObject, agnostic);
return this;
}
@@ -2378,7 +2453,7 @@ public final class SurfaceControl implements Parcelable {
*/
@UnsupportedAppUsage
public Transaction setWindowCrop(SurfaceControl sc, Rect crop) {
- sc.checkNotReleased();
+ checkPreconditions(sc);
if (crop != null) {
nativeSetWindowCrop(mNativeObject, sc.mNativeObject,
crop.left, crop.top, crop.right, crop.bottom);
@@ -2399,7 +2474,7 @@ public final class SurfaceControl implements Parcelable {
* @hide
*/
public Transaction setWindowCrop(SurfaceControl sc, int width, int height) {
- sc.checkNotReleased();
+ checkPreconditions(sc);
nativeSetWindowCrop(mNativeObject, sc.mNativeObject, 0, 0, width, height);
return this;
}
@@ -2413,7 +2488,7 @@ public final class SurfaceControl implements Parcelable {
*/
@UnsupportedAppUsage
public Transaction setCornerRadius(SurfaceControl sc, float cornerRadius) {
- sc.checkNotReleased();
+ checkPreconditions(sc);
nativeSetCornerRadius(mNativeObject, sc.mNativeObject, cornerRadius);
return this;
@@ -2424,7 +2499,7 @@ public final class SurfaceControl implements Parcelable {
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.O)
public Transaction setLayerStack(SurfaceControl sc, int layerStack) {
- sc.checkNotReleased();
+ checkPreconditions(sc);
nativeSetLayerStack(mNativeObject, sc.mNativeObject, layerStack);
return this;
}
@@ -2438,7 +2513,7 @@ public final class SurfaceControl implements Parcelable {
if (frameNumber < 0) {
return this;
}
- sc.checkNotReleased();
+ checkPreconditions(sc);
nativeDeferTransactionUntil(mNativeObject, sc.mNativeObject, barrier.mNativeObject,
frameNumber);
return this;
@@ -2453,7 +2528,7 @@ public final class SurfaceControl implements Parcelable {
if (frameNumber < 0) {
return this;
}
- sc.checkNotReleased();
+ checkPreconditions(sc);
nativeDeferTransactionUntilSurface(mNativeObject, sc.mNativeObject,
barrierSurface.mNativeObject, frameNumber);
return this;
@@ -2463,7 +2538,7 @@ public final class SurfaceControl implements Parcelable {
* @hide
*/
public Transaction reparentChildren(SurfaceControl sc, SurfaceControl newParent) {
- sc.checkNotReleased();
+ checkPreconditions(sc);
nativeReparentChildren(mNativeObject, sc.mNativeObject, newParent.mNativeObject);
return this;
}
@@ -2480,7 +2555,7 @@ public final class SurfaceControl implements Parcelable {
@NonNull
public Transaction reparent(@NonNull SurfaceControl sc,
@Nullable SurfaceControl newParent) {
- sc.checkNotReleased();
+ checkPreconditions(sc);
long otherObject = 0;
if (newParent != null) {
newParent.checkNotReleased();
@@ -2494,7 +2569,7 @@ public final class SurfaceControl implements Parcelable {
* @hide
*/
public Transaction detachChildren(SurfaceControl sc) {
- sc.checkNotReleased();
+ checkPreconditions(sc);
nativeSeverChildren(mNativeObject, sc.mNativeObject);
return this;
}
@@ -2503,7 +2578,7 @@ public final class SurfaceControl implements Parcelable {
* @hide
*/
public Transaction setOverrideScalingMode(SurfaceControl sc, int overrideScalingMode) {
- sc.checkNotReleased();
+ checkPreconditions(sc);
nativeSetOverrideScalingMode(mNativeObject, sc.mNativeObject,
overrideScalingMode);
return this;
@@ -2516,7 +2591,7 @@ public final class SurfaceControl implements Parcelable {
*/
@UnsupportedAppUsage
public Transaction setColor(SurfaceControl sc, @Size(3) float[] color) {
- sc.checkNotReleased();
+ checkPreconditions(sc);
nativeSetColor(mNativeObject, sc.mNativeObject, color);
return this;
}
@@ -2527,7 +2602,7 @@ public final class SurfaceControl implements Parcelable {
* @hide
*/
public Transaction setSecure(SurfaceControl sc, boolean isSecure) {
- sc.checkNotReleased();
+ checkPreconditions(sc);
if (isSecure) {
nativeSetFlags(mNativeObject, sc.mNativeObject, SECURE, SECURE);
} else {
@@ -2542,7 +2617,7 @@ public final class SurfaceControl implements Parcelable {
* @hide
*/
public Transaction setOpaque(SurfaceControl sc, boolean isOpaque) {
- sc.checkNotReleased();
+ checkPreconditions(sc);
if (isOpaque) {
nativeSetFlags(mNativeObject, sc.mNativeObject, SURFACE_OPAQUE, SURFACE_OPAQUE);
} else {
@@ -2657,7 +2732,7 @@ public final class SurfaceControl implements Parcelable {
* @hide
*/
public Transaction setMetadata(SurfaceControl sc, int key, Parcel data) {
- sc.checkNotReleased();
+ checkPreconditions(sc);
nativeSetMetadata(mNativeObject, sc.mNativeObject, key, data);
return this;
}
@@ -2680,7 +2755,7 @@ public final class SurfaceControl implements Parcelable {
* @hide
*/
public Transaction setShadowRadius(SurfaceControl sc, float shadowRadius) {
- sc.checkNotReleased();
+ checkPreconditions(sc);
nativeSetShadowRadius(mNativeObject, sc.mNativeObject, shadowRadius);
return this;
}
@@ -2763,4 +2838,27 @@ public final class SurfaceControl implements Parcelable {
}
};
}
+
+ /**
+ * A debugging utility subclass of SurfaceControl.Transaction. At construction
+ * you can pass in a monitor object, and all the other methods will throw an exception
+ * if the monitor is not held when they are called.
+ * @hide
+ */
+ public static class LockDebuggingTransaction extends SurfaceControl.Transaction {
+ Object mMonitor;
+
+ public LockDebuggingTransaction(Object o) {
+ mMonitor = o;
+ }
+
+ @Override
+ protected void checkPreconditions(SurfaceControl sc) {
+ super.checkPreconditions(sc);
+ if (!Thread.holdsLock(mMonitor)) {
+ throw new RuntimeException(
+ "Unlocked access to synchronized SurfaceControl.Transaction");
+ }
+ }
+ }
}
diff --git a/core/java/android/view/WindowlessViewRoot.java b/core/java/android/view/SurfaceControlViewHost.java
index 68f2bde9c265..4f8aecd08f6d 100644
--- a/core/java/android/view/WindowlessViewRoot.java
+++ b/core/java/android/view/SurfaceControlViewHost.java
@@ -29,25 +29,55 @@ import android.os.IBinder;
* @hide
*/
@TestApi
-public class WindowlessViewRoot {
+public class SurfaceControlViewHost {
private ViewRootImpl mViewRoot;
private WindowlessWindowManager mWm;
+ private SurfaceControl mSurfaceControl;
+
+ /**
+ * @hide
+ */
+ @TestApi
+ public class SurfacePackage {
+ final SurfaceControl mSurfaceControl;
+ // TODO: Accessibility ID goes here
+
+ SurfacePackage(SurfaceControl sc) {
+ mSurfaceControl = sc;
+ }
+
+ public @NonNull SurfaceControl getSurfaceControl() {
+ return mSurfaceControl;
+ }
+ }
+
/** @hide */
- public WindowlessViewRoot(@NonNull Context c, @NonNull Display d,
+ public SurfaceControlViewHost(@NonNull Context c, @NonNull Display d,
@NonNull WindowlessWindowManager wwm) {
mWm = wwm;
mViewRoot = new ViewRootImpl(c, d, mWm);
}
- public WindowlessViewRoot(@NonNull Context c, @NonNull Display d,
- @NonNull SurfaceControl rootSurface,
+ public SurfaceControlViewHost(@NonNull Context c, @NonNull Display d,
@Nullable IBinder hostInputToken) {
- mWm = new WindowlessWindowManager(c.getResources().getConfiguration(), rootSurface,
+ mSurfaceControl = new SurfaceControl.Builder()
+ .setContainerLayer()
+ .setName("SurfaceControlViewHost")
+ .build();
+ mWm = new WindowlessWindowManager(c.getResources().getConfiguration(), mSurfaceControl,
hostInputToken);
mViewRoot = new ViewRootImpl(c, d, mWm);
}
+ public @Nullable SurfacePackage getSurfacePackage() {
+ if (mSurfaceControl != null) {
+ return new SurfacePackage(mSurfaceControl);
+ } else {
+ return null;
+ }
+ }
+
public void addView(View view, WindowManager.LayoutParams attrs) {
mViewRoot.setView(view, attrs, null);
}
diff --git a/core/java/android/view/SurfaceSession.java b/core/java/android/view/SurfaceSession.java
index 361ac932758e..0f851c1881f5 100644
--- a/core/java/android/view/SurfaceSession.java
+++ b/core/java/android/view/SurfaceSession.java
@@ -16,7 +16,7 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* An instance of this class represents a connection to the surface
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 0b5af2d01349..52ea2b2142ad 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -22,7 +22,7 @@ import static android.view.WindowManagerPolicyConstants.APPLICATION_PANEL_SUBLAY
import android.annotation.Nullable;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.CompatibilityInfo.Translator;
import android.graphics.BlendMode;
@@ -379,9 +379,11 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
* This gets called on a RenderThread worker thread, so members accessed here must
* be protected by a lock.
*/
+ final boolean useBLAST = ViewRootImpl.USE_BLAST_BUFFERQUEUE;
viewRoot.registerRtFrameCallback(frame -> {
try {
- final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+ final SurfaceControl.Transaction t = useBLAST ?
+ viewRoot.getBLASTSyncTransaction() : new SurfaceControl.Transaction();
synchronized (mSurfaceControlLock) {
if (!parent.isValid()) {
if (DEBUG) {
@@ -404,7 +406,9 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
+ " updateSurfaceAlpha RT: set alpha=" + alpha);
}
t.setAlpha(mSurfaceControl, alpha);
- t.deferTransactionUntilSurface(mSurfaceControl, parent, frame);
+ if (!useBLAST) {
+ t.deferTransactionUntilSurface(mSurfaceControl, parent, frame);
+ }
}
// It's possible that mSurfaceControl is released in the UI thread before
// the transaction completes. If that happens, an exception is thrown, which
@@ -1101,33 +1105,39 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
Surface viewRootSurface, long nextViewRootFrameNumber) {
}
- private void applySurfaceTransforms(SurfaceControl surface, Rect position, long frameNumber) {
- if (frameNumber > 0) {
+ private void applySurfaceTransforms(SurfaceControl surface, SurfaceControl.Transaction t,
+ Rect position, long frameNumber) {
+ if (frameNumber > 0 && ViewRootImpl.USE_BLAST_BUFFERQUEUE == false) {
final ViewRootImpl viewRoot = getViewRootImpl();
- mRtTransaction.deferTransactionUntilSurface(surface, viewRoot.mSurface,
+ t.deferTransactionUntilSurface(surface, viewRoot.mSurface,
frameNumber);
}
- mRtTransaction.setPosition(surface, position.left, position.top);
- mRtTransaction.setMatrix(surface,
+ t.setPosition(surface, position.left, position.top);
+ t.setMatrix(surface,
position.width() / (float) mSurfaceWidth,
0.0f, 0.0f,
position.height() / (float) mSurfaceHeight);
if (mViewVisibility) {
- mRtTransaction.show(surface);
+ t.show(surface);
}
}
private void setParentSpaceRectangle(Rect position, long frameNumber) {
+ final boolean useBLAST = ViewRootImpl.USE_BLAST_BUFFERQUEUE;
final ViewRootImpl viewRoot = getViewRootImpl();
+ final SurfaceControl.Transaction t = useBLAST ? viewRoot.getBLASTSyncTransaction() :
+ mRtTransaction;
- applySurfaceTransforms(mSurfaceControl, position, frameNumber);
+ applySurfaceTransforms(mSurfaceControl, t, position, frameNumber);
- applyChildSurfaceTransaction_renderWorker(mRtTransaction, viewRoot.mSurface,
+ applyChildSurfaceTransaction_renderWorker(t, viewRoot.mSurface,
frameNumber);
- mRtTransaction.apply();
+ if (!useBLAST) {
+ t.apply();
+ }
}
private Rect mRTLastReportedPosition = new Rect();
@@ -1176,6 +1186,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
@Override
public void positionLost(long frameNumber) {
+ boolean useBLAST = ViewRootImpl.USE_BLAST_BUFFERQUEUE;
if (DEBUG) {
Log.d(TAG, String.format("%d windowPositionLost, frameNr = %d",
System.identityHashCode(this), frameNumber));
@@ -1187,13 +1198,18 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
}
final ViewRootImpl viewRoot = getViewRootImpl();
- if (frameNumber > 0 && viewRoot != null) {
+
+ final SurfaceControl.Transaction t = useBLAST ?
+ (viewRoot != null ? viewRoot.getBLASTSyncTransaction() : mRtTransaction) :
+ mRtTransaction;
+
+ if (frameNumber > 0 && viewRoot != null && !useBLAST) {
if (viewRoot.mSurface.isValid()) {
mRtTransaction.deferTransactionUntilSurface(mSurfaceControl, viewRoot.mSurface,
frameNumber);
}
}
- mRtTransaction.hide(mSurfaceControl);
+ t.hide(mSurfaceControl);
synchronized (mSurfaceControlLock) {
if (mRtReleaseSurfaces) {
@@ -1206,7 +1222,11 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
mRtHandlingPositionUpdates = false;
}
- mRtTransaction.apply();
+ // If we aren't using BLAST, we apply the transaction locally, otherise we let the ViewRoot apply it for us.
+ // If the ViewRoot is null, we behave as if we aren't using BLAST so we need to apply the transaction.
+ if (!useBLAST || viewRoot == null) {
+ mRtTransaction.apply();
+ }
}
};
@@ -1496,4 +1516,19 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
t.setRelativeLayer(mBackgroundControl, viewRoot, Integer.MIN_VALUE);
t.setRelativeLayer(mSurfaceControl, viewRoot, mSubLayer);
}
+
+ /**
+ * @hide
+ * Note: Base class method is @UnsupportedAppUsage
+ */
+ @Override
+ public void invalidate(boolean invalidateCache) {
+ super.invalidate(invalidateCache);
+ if (ViewRootImpl.USE_BLAST_BUFFERQUEUE == false) {
+ return;
+ }
+ final ViewRootImpl viewRoot = getViewRootImpl();
+ if (viewRoot == null) return;
+ viewRoot.setUseBLASTSyncTransaction();
+ }
}
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index 5876b03476ce..277b872a8cd0 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -18,7 +18,7 @@ package android.view;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
diff --git a/core/java/android/view/TouchDelegate.java b/core/java/android/view/TouchDelegate.java
index 2ea95e90a8bf..de0f9e5c5cf6 100644
--- a/core/java/android/view/TouchDelegate.java
+++ b/core/java/android/view/TouchDelegate.java
@@ -17,7 +17,7 @@
package android.view;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Rect;
import android.graphics.Region;
import android.util.ArrayMap;
diff --git a/core/java/android/view/VelocityTracker.java b/core/java/android/view/VelocityTracker.java
index 7154f2bdee42..a56633e3c5fa 100644
--- a/core/java/android/view/VelocityTracker.java
+++ b/core/java/android/view/VelocityTracker.java
@@ -16,7 +16,7 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.Pools.SynchronizedPool;
/**
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 44f211ac8ede..0db80e2749c3 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -43,7 +43,7 @@ import android.annotation.Size;
import android.annotation.StyleRes;
import android.annotation.TestApi;
import android.annotation.UiThread;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.AutofillOptions;
import android.content.ClipData;
import android.content.Context;
@@ -6162,10 +6162,27 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
mRenderNode = RenderNode.create(getClass().getName(), new ViewAnimationHostBridge(this));
}
- final boolean debugDraw() {
+ /**
+ * Returns {@code true} when the View is attached and the system developer setting to show
+ * the layout bounds is enabled or {@code false} otherwise.
+ */
+ public final boolean isShowingLayoutBounds() {
return DEBUG_DRAW || mAttachInfo != null && mAttachInfo.mDebugLayout;
}
+ /**
+ * Used to test isShowingLayoutBounds(). This sets the local value used
+ * by that function. This method does nothing if the layout isn't attached.
+ *
+ * @hide
+ */
+ @TestApi
+ public final void setShowingLayoutBounds(boolean debugLayout) {
+ if (mAttachInfo != null) {
+ mAttachInfo.mDebugLayout = debugLayout;
+ }
+ }
+
private static SparseArray<String> getAttributeMap() {
if (mAttributeMap == null) {
mAttributeMap = new SparseArray<>();
@@ -7147,10 +7164,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
mFrameMetricsObservers = new ArrayList<>();
}
- FrameMetricsObserver fmo = new FrameMetricsObserver(window,
- handler.getLooper(), listener);
+ FrameMetricsObserver fmo = new FrameMetricsObserver(window, handler, listener);
mFrameMetricsObservers.add(fmo);
- mAttachInfo.mThreadedRenderer.addFrameMetricsObserver(fmo);
+ mAttachInfo.mThreadedRenderer.addObserver(fmo.getRendererObserver());
} else {
Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
}
@@ -7159,8 +7175,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
mFrameMetricsObservers = new ArrayList<>();
}
- FrameMetricsObserver fmo = new FrameMetricsObserver(window,
- handler.getLooper(), listener);
+ FrameMetricsObserver fmo = new FrameMetricsObserver(window, handler, listener);
mFrameMetricsObservers.add(fmo);
}
}
@@ -7182,7 +7197,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (mFrameMetricsObservers != null) {
mFrameMetricsObservers.remove(fmo);
if (renderer != null) {
- renderer.removeFrameMetricsObserver(fmo);
+ renderer.removeObserver(fmo.getRendererObserver());
}
}
}
@@ -7192,7 +7207,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
ThreadedRenderer renderer = getThreadedRenderer();
if (renderer != null) {
for (FrameMetricsObserver fmo : mFrameMetricsObservers) {
- renderer.addFrameMetricsObserver(fmo);
+ renderer.addObserver(fmo.getRendererObserver());
}
} else {
Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
@@ -20883,7 +20898,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (mOverlay != null && !mOverlay.isEmpty()) {
mOverlay.getOverlayView().draw(canvas);
}
- if (debugDraw()) {
+ if (isShowingLayoutBounds()) {
debugDrawFocus(canvas);
}
} else {
@@ -22028,7 +22043,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
// Step 7, draw the default focus highlight
drawDefaultFocusHighlight(canvas);
- if (debugDraw()) {
+ if (isShowingLayoutBounds()) {
debugDrawFocus(canvas);
}
@@ -22203,7 +22218,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
// Step 6, draw decorations (foreground, scrollbars)
onDrawForeground(canvas);
- if (debugDraw()) {
+ if (isShowingLayoutBounds()) {
debugDrawFocus(canvas);
}
}
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index 9e914d4e7d41..774a2dea6311 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -18,8 +18,8 @@ package android.view;
import android.annotation.FloatRange;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.AppGlobals;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index a62ba63b64e4..2f44fe039cf5 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -19,7 +19,7 @@ package android.view;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 4334bb510176..5fb71773db8f 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -24,7 +24,7 @@ import android.annotation.IdRes;
import android.annotation.NonNull;
import android.annotation.TestApi;
import android.annotation.UiThread;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ClipData;
import android.content.Context;
import android.content.Intent;
@@ -681,7 +681,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
private void initViewGroup() {
// ViewGroup doesn't draw by default
- if (!debugDraw()) {
+ if (!isShowingLayoutBounds()) {
setFlags(WILL_NOT_DRAW, DRAW_MASK);
}
mGroupFlags |= FLAG_CLIP_CHILDREN;
@@ -4156,7 +4156,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
if (usingRenderNodeProperties) canvas.insertInorderBarrier();
- if (debugDraw()) {
+ if (isShowingLayoutBounds()) {
onDebugDraw(canvas);
}
diff --git a/core/java/android/view/ViewHierarchyEncoder.java b/core/java/android/view/ViewHierarchyEncoder.java
index d5716bfaaf00..b0e0524a0d85 100644
--- a/core/java/android/view/ViewHierarchyEncoder.java
+++ b/core/java/android/view/ViewHierarchyEncoder.java
@@ -2,7 +2,7 @@ package android.view;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
diff --git a/core/java/android/view/ViewOverlay.java b/core/java/android/view/ViewOverlay.java
index e23c687af49b..7830c57e53ec 100644
--- a/core/java/android/view/ViewOverlay.java
+++ b/core/java/android/view/ViewOverlay.java
@@ -17,7 +17,7 @@ package android.view;
import android.animation.LayoutTransition;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index df6f3b80d11c..522ff9a3bcb5 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -49,10 +49,10 @@ import android.animation.LayoutTransition;
import android.annotation.AnyThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
import android.app.ActivityThread;
import android.app.ResourcesManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ClipData;
import android.content.ClipDescription;
import android.content.Context;
@@ -191,7 +191,10 @@ public final class ViewRootImpl implements ViewParent,
*/
private static final boolean MT_RENDERER_AVAILABLE = true;
- private static final boolean USE_BLAST_BUFFERQUEUE = false;
+ /**
+ * @hide
+ */
+ public static final boolean USE_BLAST_BUFFERQUEUE = false;
/**
* If set to 2, the view system will switch from using rectangles retrieved from window to
@@ -211,26 +214,26 @@ public final class ViewRootImpl implements ViewParent,
* @see #USE_NEW_INSETS_PROPERTY
* @hide
*/
- public static final int NEW_INSETS_MODE_NONE = 0;
+ public static int sNewInsetsMode =
+ SystemProperties.getInt(USE_NEW_INSETS_PROPERTY, 0);
/**
* @see #USE_NEW_INSETS_PROPERTY
* @hide
*/
- public static final int NEW_INSETS_MODE_IME = 1;
+ public static final int NEW_INSETS_MODE_NONE = 0;
/**
* @see #USE_NEW_INSETS_PROPERTY
* @hide
*/
- public static final int NEW_INSETS_MODE_FULL = 2;
+ public static final int NEW_INSETS_MODE_IME = 1;
/**
* @see #USE_NEW_INSETS_PROPERTY
* @hide
*/
- public static int sNewInsetsMode =
- SystemProperties.getInt(USE_NEW_INSETS_PROPERTY, NEW_INSETS_MODE_IME);
+ public static final int NEW_INSETS_MODE_FULL = 2;
/**
* Set this system property to true to force the view hierarchy to render
@@ -632,6 +635,12 @@ public final class ViewRootImpl implements ViewParent,
int localChanges;
}
+ private boolean mNextDrawUseBLASTSyncTransaction;
+ // Be very careful with the threading here. This is used from the render thread while
+ // the UI thread is paused and then applied and cleared from the UI thread right after
+ // draw returns.
+ private SurfaceControl.Transaction mRtBLASTSyncTransaction = new SurfaceControl.Transaction();
+
private String mTag = TAG;
public ViewRootImpl(Context context, Display display) {
this(context, display, WindowManagerGlobal.getWindowSession());
@@ -3604,6 +3613,7 @@ public final class ViewRootImpl implements ViewParent,
final Handler handler = mAttachInfo.mHandler;
mAttachInfo.mThreadedRenderer.setFrameCompleteCallback((long frameNr) ->
handler.postAtFrontOfQueue(() -> {
+ finishBLASTSync();
// TODO: Use the frame number
pendingDrawFinished();
if (commitCallbacks != null) {
@@ -3616,6 +3626,7 @@ public final class ViewRootImpl implements ViewParent,
final Handler handler = mAttachInfo.mHandler;
mAttachInfo.mThreadedRenderer.setFrameCompleteCallback((long frameNr) ->
handler.postAtFrontOfQueue(() -> {
+ finishBLASTSync();
for (int i = 0; i < commitCallbacks.size(); i++) {
commitCallbacks.get(i).run();
}
@@ -3624,10 +3635,14 @@ public final class ViewRootImpl implements ViewParent,
}
try {
+ if (mNextDrawUseBLASTSyncTransaction) {
+ mBlastBufferQueue.setNextTransaction(mRtBLASTSyncTransaction);
+ }
boolean canUseAsync = draw(fullRedrawNeeded);
if (usingAsyncReport && !canUseAsync) {
mAttachInfo.mThreadedRenderer.setFrameCompleteCallback(null);
usingAsyncReport = false;
+ finishBLASTSync();
}
} finally {
mIsDrawing = false;
@@ -7619,11 +7634,22 @@ public final class ViewRootImpl implements ViewParent,
}
private void dispatchInsetsChanged(InsetsState insetsState) {
+ if (Binder.getCallingPid() == android.os.Process.myPid()) {
+ insetsState = new InsetsState(insetsState, true /* copySource */);
+ }
mHandler.obtainMessage(MSG_INSETS_CHANGED, insetsState).sendToTarget();
}
private void dispatchInsetsControlChanged(InsetsState insetsState,
InsetsSourceControl[] activeControls) {
+ if (Binder.getCallingPid() == android.os.Process.myPid()) {
+ insetsState = new InsetsState(insetsState, true /* copySource */);
+ if (activeControls != null) {
+ for (int i = activeControls.length - 1; i >= 0; i--) {
+ activeControls[i] = new InsetsSourceControl(activeControls[i]);
+ }
+ }
+ }
SomeArgs args = SomeArgs.obtain();
args.arg1 = insetsState;
args.arg2 = activeControls;
@@ -9421,4 +9447,19 @@ public final class ViewRootImpl implements ViewParent,
return false;
}
}
+
+ void setUseBLASTSyncTransaction() {
+ mNextDrawUseBLASTSyncTransaction = true;
+ }
+
+ private void finishBLASTSync() {
+ if (mNextDrawUseBLASTSyncTransaction) {
+ mNextDrawUseBLASTSyncTransaction = false;
+ mRtBLASTSyncTransaction.apply();
+ }
+ }
+
+ SurfaceControl.Transaction getBLASTSyncTransaction() {
+ return mRtBLASTSyncTransaction;
+ }
}
diff --git a/core/java/android/view/ViewTreeObserver.java b/core/java/android/view/ViewTreeObserver.java
index c72baca0b93b..d7b0afc89eaa 100644
--- a/core/java/android/view/ViewTreeObserver.java
+++ b/core/java/android/view/ViewTreeObserver.java
@@ -18,7 +18,7 @@ package android.view;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.graphics.Rect;
import android.graphics.Region;
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index ff31115a37f0..a1894f30d6f6 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -26,8 +26,8 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StyleRes;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.WindowConfiguration;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
@@ -1199,6 +1199,44 @@ public abstract class Window {
}
/**
+ * If {@code isPreferred} is true, this method requests that the connected display does minimal
+ * post processing when this window is visible on the screen. Otherwise, it requests that the
+ * display switches back to standard image processing.
+ *
+ * <p> By default, the display does not do minimal post processing and if this is desired, this
+ * method should not be used. It should be used with {@code isPreferred=true} when low
+ * latency has a higher priority than image enhancement processing (e.g. for games or video
+ * conferencing). The display will automatically go back into standard image processing mode
+ * when no window requesting minimal posst processing is visible on screen anymore.
+ * {@code setPreferMinimalPostProcessing(false)} can be used if
+ * {@code setPreferMinimalPostProcessing(true)} was previously called for this window and
+ * minimal post processing is no longer required.
+ *
+ * <p>If the Display sink is connected via HDMI, the device will begin to send infoframes with
+ * Auto Low Latency Mode enabled and Game Content Type. This will switch the connected display
+ * to a minimal image processing mode (if available), which reduces latency, improving the user
+ * experience for gaming or video conferencing applications. For more information, see HDMI 2.1
+ * specification.
+ *
+ * <p>If the Display sink has an internal connection or uses some other protocol than HDMI,
+ * effects may be similar but implementation-defined.
+ *
+ * <p>The ability to switch to a mode with minimal post proessing may be disabled by a user
+ * setting in the system settings menu. In that case, this method does nothing.
+ *
+ * @see android.content.pm.ActivityInfo#preferMinimalPostProcessing
+ * @see android.view.Display#isMinimalPostProcessingSupported
+ * @see android.view.WindowManager.LayoutParams#preferMinimalPostProcessing
+ *
+ * @param isPreferred Indicates whether minimal post processing is preferred for this window
+ * ({@code isPreferred=true}) or not ({@code isPreferred=false}).
+ */
+ public void setPreferMinimalPostProcessing(boolean isPreferred) {
+ mWindowAttributes.preferMinimalPostProcessing = isPreferred;
+ dispatchWindowAttributesChanged(mWindowAttributes);
+ }
+
+ /**
* Returns the requested color mode of the window, one of
* {@link ActivityInfo#COLOR_MODE_DEFAULT}, {@link ActivityInfo#COLOR_MODE_WIDE_COLOR_GAMUT}
* or {@link ActivityInfo#COLOR_MODE_HDR}. If {@link ActivityInfo#COLOR_MODE_WIDE_COLOR_GAMUT}
diff --git a/core/java/android/view/WindowAnimationFrameStats.java b/core/java/android/view/WindowAnimationFrameStats.java
index 399dfba64461..dfc4f0cd4dc6 100644
--- a/core/java/android/view/WindowAnimationFrameStats.java
+++ b/core/java/android/view/WindowAnimationFrameStats.java
@@ -16,7 +16,7 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/view/WindowContentFrameStats.java b/core/java/android/view/WindowContentFrameStats.java
index 9fa5a005055d..217197c96793 100644
--- a/core/java/android/view/WindowContentFrameStats.java
+++ b/core/java/android/view/WindowContentFrameStats.java
@@ -16,7 +16,7 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java
index 2404c84457bb..a9cc50f9e65e 100644
--- a/core/java/android/view/WindowInsets.java
+++ b/core/java/android/view/WindowInsets.java
@@ -34,7 +34,7 @@ import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.graphics.Insets;
import android.graphics.Rect;
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 3b6c55b1339d..f7d9706a9fce 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -66,9 +66,9 @@ import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.KeyguardManager;
import android.app.Presentation;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.graphics.PixelFormat;
@@ -2607,6 +2607,33 @@ public interface WindowManager extends ViewManager {
public long hideTimeoutMilliseconds = -1;
/**
+ * Indicates whether this window wants the connected display to do minimal post processing
+ * on the produced image or video frames. This will only be requested if the window is
+ * visible on the screen.
+ *
+ * <p>This setting should be used when low latency has a higher priority than image
+ * enhancement processing (e.g. for games or video conferencing).
+ *
+ * <p>If the Display sink is connected via HDMI, the device will begin to send infoframes
+ * with Auto Low Latency Mode enabled and Game Content Type. This will switch the connected
+ * display to a minimal image processing mode (if available), which reduces latency,
+ * improving the user experience for gaming or video conferencing applications. For more
+ * information, see HDMI 2.1 specification.
+ *
+ * <p>If the Display sink has an internal connection or uses some other protocol than HDMI,
+ * effects may be similar but implementation-defined.
+ *
+ * <p>The ability to switch to a mode with minimal post proessing may be disabled by a user
+ * setting in the system settings menu. In that case, this field is ignored and the display
+ * will remain in its current mode.
+ *
+ * @see android.content.pm.ActivityInfo#preferMinimalPostProcessing
+ * @see android.view.Display#isMinimalPostProcessingSupported
+ * @see android.view.Window#setPreferMinimalPostProcessing
+ */
+ public boolean preferMinimalPostProcessing = false;
+
+ /**
* The color mode requested by this window. The target display may
* not be able to honor the request. When the color mode is not set
* to {@link ActivityInfo#COLOR_MODE_DEFAULT}, it might override the
@@ -2909,6 +2936,7 @@ public interface WindowManager extends ViewManager {
out.writeInt(mFitWindowInsetsTypes);
out.writeInt(mFitWindowInsetsSides);
out.writeBoolean(mFitIgnoreVisibility);
+ out.writeBoolean(preferMinimalPostProcessing);
}
public static final @android.annotation.NonNull Parcelable.Creator<LayoutParams> CREATOR
@@ -2969,6 +2997,7 @@ public interface WindowManager extends ViewManager {
mFitWindowInsetsTypes = in.readInt();
mFitWindowInsetsSides = in.readInt();
mFitIgnoreVisibility = in.readBoolean();
+ preferMinimalPostProcessing = in.readBoolean();
}
@SuppressWarnings({"PointlessBitwiseExpression"})
@@ -3014,6 +3043,8 @@ public interface WindowManager extends ViewManager {
public static final int COLOR_MODE_CHANGED = 1 << 26;
/** {@hide} */
public static final int INSET_FLAGS_CHANGED = 1 << 27;
+ /** {@hide} */
+ public static final int MINIMAL_POST_PROCESSING_PREFERENCE_CHANGED = 1 << 28;
// internal buffer to backup/restore parameters under compatibility mode.
private int[] mCompatibilityParamsBackup = null;
@@ -3194,6 +3225,11 @@ public interface WindowManager extends ViewManager {
changes |= COLOR_MODE_CHANGED;
}
+ if (preferMinimalPostProcessing != o.preferMinimalPostProcessing) {
+ preferMinimalPostProcessing = o.preferMinimalPostProcessing;
+ changes |= MINIMAL_POST_PROCESSING_PREFERENCE_CHANGED;
+ }
+
// This can't change, it's only set at window creation time.
hideTimeoutMilliseconds = o.hideTimeoutMilliseconds;
@@ -3348,6 +3384,10 @@ public interface WindowManager extends ViewManager {
if (mColorMode != COLOR_MODE_DEFAULT) {
sb.append(" colorMode=").append(ActivityInfo.colorModeToString(mColorMode));
}
+ if (preferMinimalPostProcessing) {
+ sb.append(" preferMinimalPostProcessing=");
+ sb.append(preferMinimalPostProcessing);
+ }
sb.append(System.lineSeparator());
sb.append(prefix).append(" fl=").append(
ViewDebug.flagsToString(LayoutParams.class, "flags", flags));
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index 55b2a2a4033a..95780023563d 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -18,8 +18,8 @@ package android.view;
import android.animation.ValueAnimator;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentCallbacks2;
import android.content.Context;
import android.content.pm.ApplicationInfo;
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index c3494432ebcb..cdeeaa438acb 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -17,7 +17,7 @@
package android.view;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.graphics.Region;
import android.os.Bundle;
diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java
index 2ba09750b001..1312a9b1c158 100644
--- a/core/java/android/view/WindowlessWindowManager.java
+++ b/core/java/android/view/WindowlessWindowManager.java
@@ -336,7 +336,7 @@ public class WindowlessWindowManager implements IWindowSession {
}
@Override
- public void updateTapExcludeRegion(android.view.IWindow window, int regionId,
+ public void updateTapExcludeRegion(android.view.IWindow window,
android.graphics.Region region) {
}
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index 34654edd00e8..3b8368380dda 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -18,7 +18,7 @@ package android.view.accessibility;
import android.annotation.IntDef;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
index 386651731d45..914ff1871d69 100644
--- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java
+++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
@@ -17,7 +17,7 @@
package android.view.accessibility;
import android.accessibilityservice.IAccessibilityServiceConnection;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index 843f8e33c66a..ff31bccfa648 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -30,8 +30,8 @@ import android.annotation.SdkConstant;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.UserIdInt;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index f2f84cdc631c..92aa7d523da0 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -26,7 +26,7 @@ import android.accessibilityservice.AccessibilityServiceInfo;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Rect;
import android.graphics.Region;
import android.os.Build;
diff --git a/core/java/android/view/accessibility/AccessibilityRecord.java b/core/java/android/view/accessibility/AccessibilityRecord.java
index 4f6c9ef55220..c3a4d3206462 100644
--- a/core/java/android/view/accessibility/AccessibilityRecord.java
+++ b/core/java/android/view/accessibility/AccessibilityRecord.java
@@ -20,7 +20,7 @@ import static com.android.internal.util.CollectionUtils.isEmpty;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcelable;
import android.view.View;
diff --git a/core/java/android/view/accessibility/CaptioningManager.java b/core/java/android/view/accessibility/CaptioningManager.java
index c42e9fec91bf..3d68692a3b5c 100644
--- a/core/java/android/view/accessibility/CaptioningManager.java
+++ b/core/java/android/view/accessibility/CaptioningManager.java
@@ -19,7 +19,7 @@ package android.view.accessibility;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
diff --git a/core/java/android/view/animation/Animation.java b/core/java/android/view/animation/Animation.java
index b03732a2a7f0..b1d618eff40a 100644
--- a/core/java/android/view/animation/Animation.java
+++ b/core/java/android/view/animation/Animation.java
@@ -19,7 +19,7 @@ package android.view.animation;
import android.annotation.AnimRes;
import android.annotation.ColorInt;
import android.annotation.InterpolatorRes;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.RectF;
diff --git a/core/java/android/view/animation/AnimationUtils.java b/core/java/android/view/animation/AnimationUtils.java
index f5b074674454..7ce0f4571f76 100644
--- a/core/java/android/view/animation/AnimationUtils.java
+++ b/core/java/android/view/animation/AnimationUtils.java
@@ -19,7 +19,7 @@ package android.view.animation;
import android.annotation.AnimRes;
import android.annotation.InterpolatorRes;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
diff --git a/core/java/android/view/animation/Transformation.java b/core/java/android/view/animation/Transformation.java
index 58da04d8d38f..cfc6e39da876 100644
--- a/core/java/android/view/animation/Transformation.java
+++ b/core/java/android/view/animation/Transformation.java
@@ -17,7 +17,7 @@
package android.view.animation;
import android.annotation.FloatRange;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Matrix;
import android.graphics.Rect;
diff --git a/core/java/android/view/animation/TranslateAnimation.java b/core/java/android/view/animation/TranslateAnimation.java
index 6c040d4c61aa..ec55a0273999 100644
--- a/core/java/android/view/animation/TranslateAnimation.java
+++ b/core/java/android/view/animation/TranslateAnimation.java
@@ -16,7 +16,7 @@
package android.view.animation;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
diff --git a/core/java/android/view/animation/TranslateYAnimation.java b/core/java/android/view/animation/TranslateYAnimation.java
index a6e0ccb18805..1a1dfbfd6f05 100644
--- a/core/java/android/view/animation/TranslateYAnimation.java
+++ b/core/java/android/view/animation/TranslateYAnimation.java
@@ -16,7 +16,7 @@
package android.view.animation;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Matrix;
/**
diff --git a/core/java/android/view/autofill/AutofillValue.java b/core/java/android/view/autofill/AutofillValue.java
index 64c877759338..cfd624acf3bc 100644
--- a/core/java/android/view/autofill/AutofillValue.java
+++ b/core/java/android/view/autofill/AutofillValue.java
@@ -68,7 +68,7 @@ public final class AutofillValue implements Parcelable {
}
/**
- * Checks is this is a text value.
+ * Checks if this is a text value.
*
* <p>See {@link View#AUTOFILL_TYPE_TEXT} for more info.</p>
*/
@@ -89,7 +89,7 @@ public final class AutofillValue implements Parcelable {
}
/**
- * Checks is this is a toggle value.
+ * Checks if this is a toggle value.
*
* <p>See {@link View#AUTOFILL_TYPE_TOGGLE} for more info.</p>
*/
@@ -110,7 +110,7 @@ public final class AutofillValue implements Parcelable {
}
/**
- * Checks is this is a list value.
+ * Checks if this is a list value.
*
* <p>See {@link View#AUTOFILL_TYPE_LIST} for more info.</p>
*/
@@ -131,7 +131,7 @@ public final class AutofillValue implements Parcelable {
}
/**
- * Checks is this is a date value.
+ * Checks if this is a date value.
*
* <p>See {@link View#AUTOFILL_TYPE_DATE} for more info.</p>
*/
diff --git a/core/java/android/view/inline/InlinePresentationSpec.java b/core/java/android/view/inline/InlinePresentationSpec.java
index 1eddef554397..a85b5f1d027c 100644
--- a/core/java/android/view/inline/InlinePresentationSpec.java
+++ b/core/java/android/view/inline/InlinePresentationSpec.java
@@ -31,6 +31,7 @@ import com.android.internal.util.DataClass;
*/
@DataClass(genEqualsHashCode = true, genToString = true, genBuilder = true)
public final class InlinePresentationSpec implements Parcelable {
+
/** The minimal size of the suggestion. */
@NonNull
private final Size mMinSize;
@@ -38,7 +39,26 @@ public final class InlinePresentationSpec implements Parcelable {
@NonNull
private final Size mMaxSize;
- // TODO(b/137800469): add more attributes, such as text appearance info.
+ /**
+ * The fully qualified resource name of the UI style resource identifier, defaults to {@code
+ * null}.
+ *
+ * <p> The value can be obtained by calling {@code Resources#getResourceName(int)}.
+ */
+ @Nullable
+ private final String mStyle;
+
+ private static String defaultStyle() {
+ return null;
+ }
+
+ /**
+ * @hide
+ */
+ public @Nullable String getStyle() {
+ return mStyle;
+ }
+
/** @hide */
@DataClass.Suppress({"setMaxSize", "setMinSize"})
@@ -63,13 +83,15 @@ public final class InlinePresentationSpec implements Parcelable {
@DataClass.Generated.Member
/* package-private */ InlinePresentationSpec(
@NonNull Size minSize,
- @NonNull Size maxSize) {
+ @NonNull Size maxSize,
+ @Nullable String style) {
this.mMinSize = minSize;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, mMinSize);
this.mMaxSize = maxSize;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, mMaxSize);
+ this.mStyle = style;
// onConstructed(); // You can define this method to get a callback
}
@@ -98,7 +120,8 @@ public final class InlinePresentationSpec implements Parcelable {
return "InlinePresentationSpec { " +
"minSize = " + mMinSize + ", " +
- "maxSize = " + mMaxSize +
+ "maxSize = " + mMaxSize + ", " +
+ "style = " + mStyle +
" }";
}
@@ -116,7 +139,8 @@ public final class InlinePresentationSpec implements Parcelable {
//noinspection PointlessBooleanExpression
return true
&& java.util.Objects.equals(mMinSize, that.mMinSize)
- && java.util.Objects.equals(mMaxSize, that.mMaxSize);
+ && java.util.Objects.equals(mMaxSize, that.mMaxSize)
+ && java.util.Objects.equals(mStyle, that.mStyle);
}
@Override
@@ -128,6 +152,7 @@ public final class InlinePresentationSpec implements Parcelable {
int _hash = 1;
_hash = 31 * _hash + java.util.Objects.hashCode(mMinSize);
_hash = 31 * _hash + java.util.Objects.hashCode(mMaxSize);
+ _hash = 31 * _hash + java.util.Objects.hashCode(mStyle);
return _hash;
}
@@ -137,8 +162,12 @@ public final class InlinePresentationSpec implements Parcelable {
// You can override field parcelling by defining methods like:
// void parcelFieldName(Parcel dest, int flags) { ... }
+ byte flg = 0;
+ if (mStyle != null) flg |= 0x4;
+ dest.writeByte(flg);
dest.writeSize(mMinSize);
dest.writeSize(mMaxSize);
+ if (mStyle != null) dest.writeString(mStyle);
}
@Override
@@ -152,8 +181,10 @@ public final class InlinePresentationSpec implements Parcelable {
// You can override field unparcelling by defining methods like:
// static FieldType unparcelFieldName(Parcel in) { ... }
+ byte flg = in.readByte();
Size minSize = (Size) in.readSize();
Size maxSize = (Size) in.readSize();
+ String style = (flg & 0x4) == 0 ? null : in.readString();
this.mMinSize = minSize;
com.android.internal.util.AnnotationValidations.validate(
@@ -161,6 +192,7 @@ public final class InlinePresentationSpec implements Parcelable {
this.mMaxSize = maxSize;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, mMaxSize);
+ this.mStyle = style;
// onConstructed(); // You can define this method to get a callback
}
@@ -188,6 +220,7 @@ public final class InlinePresentationSpec implements Parcelable {
private @NonNull Size mMinSize;
private @NonNull Size mMaxSize;
+ private @Nullable String mStyle;
private long mBuilderFieldsSet = 0L;
@@ -210,19 +243,37 @@ public final class InlinePresentationSpec implements Parcelable {
NonNull.class, null, mMaxSize);
}
+ /**
+ * The fully qualified resource name of the UI style resource identifier, defaults to {@code
+ * null}.
+ *
+ * <p> The value can be obtained by calling {@code Resources#getResourceName(int)}.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setStyle(@Nullable String value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x4;
+ mStyle = value;
+ return this;
+ }
+
/** Builds the instance. This builder should not be touched after calling this! */
public @NonNull InlinePresentationSpec build() {
checkNotUsed();
- mBuilderFieldsSet |= 0x4; // Mark builder used
+ mBuilderFieldsSet |= 0x8; // Mark builder used
+ if ((mBuilderFieldsSet & 0x4) == 0) {
+ mStyle = defaultStyle();
+ }
InlinePresentationSpec o = new InlinePresentationSpec(
mMinSize,
- mMaxSize);
+ mMaxSize,
+ mStyle);
return o;
}
private void checkNotUsed() {
- if ((mBuilderFieldsSet & 0x4) != 0) {
+ if ((mBuilderFieldsSet & 0x8) != 0) {
throw new IllegalStateException(
"This Builder should not be reused. Use a new Builder instance instead");
}
@@ -230,10 +281,10 @@ public final class InlinePresentationSpec implements Parcelable {
}
@DataClass.Generated(
- time = 1574406062532L,
+ time = 1577145109444L,
codegenVersion = "1.0.14",
sourceFile = "frameworks/base/core/java/android/view/inline/InlinePresentationSpec.java",
- inputSignatures = "private final @android.annotation.NonNull android.util.Size mMinSize\nprivate final @android.annotation.NonNull android.util.Size mMaxSize\nclass InlinePresentationSpec extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genBuilder=true)\nclass BaseBuilder extends java.lang.Object implements []")
+ inputSignatures = "private final @android.annotation.NonNull android.util.Size mMinSize\nprivate final @android.annotation.NonNull android.util.Size mMaxSize\nprivate final @android.annotation.Nullable java.lang.String mStyle\nprivate static java.lang.String defaultStyle()\npublic @android.annotation.Nullable java.lang.String getStyle()\nclass InlinePresentationSpec extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genBuilder=true)\nclass BaseBuilder extends java.lang.Object implements []")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/view/inputmethod/InlineSuggestionsRequest.java b/core/java/android/view/inputmethod/InlineSuggestionsRequest.java
index dd609ee70810..386c9cb9d14f 100644
--- a/core/java/android/view/inputmethod/InlineSuggestionsRequest.java
+++ b/core/java/android/view/inputmethod/InlineSuggestionsRequest.java
@@ -36,7 +36,17 @@ public final class InlineSuggestionsRequest implements Parcelable {
/** Constant used to indicate not putting a cap on the number of suggestions to return. */
public static final int SUGGESTION_COUNT_UNLIMITED = Integer.MAX_VALUE;
+ /**
+ * Max number of suggestions expected from the response. Defaults to {@code
+ * SUGGESTION_COUNT_UNLIMITED} if not set.
+ */
private final int mMaxSuggestionCount;
+
+ /**
+ * The {@link InlinePresentationSpec} for each suggestion in the response. If the max suggestion
+ * count is larger than the number of specs in the list, then the last spec is used for the
+ * remainder of the suggestions.
+ */
private final @NonNull List<InlinePresentationSpec> mPresentationSpecs;
private void onConstructed() {
@@ -79,11 +89,20 @@ public final class InlineSuggestionsRequest implements Parcelable {
onConstructed();
}
+ /**
+ * Max number of suggestions expected from the response. Defaults to {@code
+ * SUGGESTION_COUNT_UNLIMITED} if not set.
+ */
@DataClass.Generated.Member
public int getMaxSuggestionCount() {
return mMaxSuggestionCount;
}
+ /**
+ * The {@link InlinePresentationSpec} for each suggestion in the response. If the max suggestion
+ * count is larger than the number of specs in the list, then the last spec is used for the
+ * remainder of the suggestions.
+ */
@DataClass.Generated.Member
public @NonNull List<InlinePresentationSpec> getPresentationSpecs() {
return mPresentationSpecs;
@@ -189,6 +208,14 @@ public final class InlineSuggestionsRequest implements Parcelable {
private long mBuilderFieldsSet = 0L;
+ /**
+ * Creates a new Builder.
+ *
+ * @param presentationSpecs
+ * The {@link InlinePresentationSpec} for each suggestion in the response. If the max suggestion
+ * count is larger than the number of specs in the list, then the last spec is used for the
+ * remainder of the suggestions.
+ */
public Builder(
@NonNull List<InlinePresentationSpec> presentationSpecs) {
mPresentationSpecs = presentationSpecs;
@@ -196,6 +223,10 @@ public final class InlineSuggestionsRequest implements Parcelable {
NonNull.class, null, mPresentationSpecs);
}
+ /**
+ * Max number of suggestions expected from the response. Defaults to {@code
+ * SUGGESTION_COUNT_UNLIMITED} if not set.
+ */
@DataClass.Generated.Member
public @NonNull Builder setMaxSuggestionCount(int value) {
checkNotUsed();
@@ -204,6 +235,11 @@ public final class InlineSuggestionsRequest implements Parcelable {
return this;
}
+ /**
+ * The {@link InlinePresentationSpec} for each suggestion in the response. If the max suggestion
+ * count is larger than the number of specs in the list, then the last spec is used for the
+ * remainder of the suggestions.
+ */
@DataClass.Generated.Member
@Override
@NonNull Builder setPresentationSpecs(@NonNull List<InlinePresentationSpec> value) {
@@ -247,7 +283,7 @@ public final class InlineSuggestionsRequest implements Parcelable {
}
@DataClass.Generated(
- time = 1574406255024L,
+ time = 1576637222199L,
codegenVersion = "1.0.14",
sourceFile = "frameworks/base/core/java/android/view/inputmethod/InlineSuggestionsRequest.java",
inputSignatures = "public static final int SUGGESTION_COUNT_UNLIMITED\nprivate final int mMaxSuggestionCount\nprivate final @android.annotation.NonNull java.util.List<android.view.inline.InlinePresentationSpec> mPresentationSpecs\nprivate void onConstructed()\nprivate static int defaultMaxSuggestionCount()\nclass InlineSuggestionsRequest extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genBuilder=true)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setPresentationSpecs(java.util.List<android.view.inline.InlinePresentationSpec>)\nclass BaseBuilder extends java.lang.Object implements []")
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
index fe07feef3bfa..34005ac02735 100644
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
+++ b/core/java/android/view/inputmethod/InputMethodInfo.java
@@ -17,7 +17,7 @@
package android.view.inputmethod;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ApplicationInfo;
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 2650a67652a5..67ce8d2e49b5 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -26,9 +26,9 @@ import android.annotation.RequiresFeature;
import android.annotation.RequiresPermission;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.UserIdInt;
import android.app.ActivityThread;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
@@ -2863,7 +2863,7 @@ public final class InputMethodManager {
}
/**
- * This is kept due to {@link android.annotation.UnsupportedAppUsage}.
+ * This is kept due to {@link android.compat.annotation.UnsupportedAppUsage}.
*
* <p>TODO(Bug 113914148): Check if we can remove this. We have accidentally exposed
* WindowManagerInternal#getInputMethodWindowVisibleHeight to app developers and some of them
diff --git a/core/java/android/view/inputmethod/InputMethodSubtypeArray.java b/core/java/android/view/inputmethod/InputMethodSubtypeArray.java
index 8dd0dcd45a1c..50e95c80cfed 100644
--- a/core/java/android/view/inputmethod/InputMethodSubtypeArray.java
+++ b/core/java/android/view/inputmethod/InputMethodSubtypeArray.java
@@ -16,7 +16,7 @@
package android.view.inputmethod;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.util.Slog;
diff --git a/core/java/android/view/textclassifier/ConversationAction.java b/core/java/android/view/textclassifier/ConversationAction.java
index 6070b5341cf9..e633404fd7d8 100644
--- a/core/java/android/view/textclassifier/ConversationAction.java
+++ b/core/java/android/view/textclassifier/ConversationAction.java
@@ -26,9 +26,8 @@ import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
-import com.android.internal.util.Preconditions;
-
import java.lang.annotation.Retention;
+import java.util.Objects;
/** Represents the action suggested by a {@link TextClassifier} on a given conversation. */
public final class ConversationAction implements Parcelable {
@@ -133,11 +132,11 @@ public final class ConversationAction implements Parcelable {
@Nullable CharSequence textReply,
float score,
@NonNull Bundle extras) {
- mType = Preconditions.checkNotNull(type);
+ mType = Objects.requireNonNull(type);
mAction = action;
mTextReply = textReply;
mScore = score;
- mExtras = Preconditions.checkNotNull(extras);
+ mExtras = Objects.requireNonNull(extras);
}
private ConversationAction(Parcel in) {
@@ -221,7 +220,7 @@ public final class ConversationAction implements Parcelable {
private Bundle mExtras;
public Builder(@NonNull @ActionType String actionType) {
- mType = Preconditions.checkNotNull(actionType);
+ mType = Objects.requireNonNull(actionType);
}
/**
diff --git a/core/java/android/view/textclassifier/ConversationActions.java b/core/java/android/view/textclassifier/ConversationActions.java
index f7f503ab60ec..80027b1ed75d 100644
--- a/core/java/android/view/textclassifier/ConversationActions.java
+++ b/core/java/android/view/textclassifier/ConversationActions.java
@@ -38,6 +38,7 @@ import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Objects;
/**
* Represents a list of actions suggested by a {@link TextClassifier} on a given conversation.
@@ -66,7 +67,7 @@ public final class ConversationActions implements Parcelable {
public ConversationActions(
@NonNull List<ConversationAction> conversationActions, @Nullable String id) {
mConversationActions =
- Collections.unmodifiableList(Preconditions.checkNotNull(conversationActions));
+ Collections.unmodifiableList(Objects.requireNonNull(conversationActions));
mId = id;
}
@@ -149,7 +150,7 @@ public final class ConversationActions implements Parcelable {
mAuthor = author;
mReferenceTime = referenceTime;
mText = text;
- mExtras = Preconditions.checkNotNull(bundle);
+ mExtras = Objects.requireNonNull(bundle);
}
private Message(Parcel in) {
@@ -243,7 +244,7 @@ public final class ConversationActions implements Parcelable {
* {@link #PERSON_USER_OTHERS} to represent a remote user.
*/
public Builder(@NonNull Person author) {
- mAuthor = Preconditions.checkNotNull(author);
+ mAuthor = Objects.requireNonNull(author);
}
/** Sets the text of this message. */
@@ -329,8 +330,8 @@ public final class ConversationActions implements Parcelable {
int maxSuggestions,
@Nullable @Hint List<String> hints,
@NonNull Bundle extras) {
- mConversation = Preconditions.checkNotNull(conversation);
- mTypeConfig = Preconditions.checkNotNull(typeConfig);
+ mConversation = Objects.requireNonNull(conversation);
+ mTypeConfig = Objects.requireNonNull(typeConfig);
mMaxSuggestions = maxSuggestions;
mHints = hints;
mExtras = extras;
@@ -483,7 +484,7 @@ public final class ConversationActions implements Parcelable {
* actions for.
*/
public Builder(@NonNull List<Message> conversation) {
- mConversation = Preconditions.checkNotNull(conversation);
+ mConversation = Objects.requireNonNull(conversation);
}
/**
diff --git a/core/java/android/view/textclassifier/EntityConfidence.java b/core/java/android/view/textclassifier/EntityConfidence.java
index 3c51c38952f0..4c12dda0109a 100644
--- a/core/java/android/view/textclassifier/EntityConfidence.java
+++ b/core/java/android/view/textclassifier/EntityConfidence.java
@@ -22,12 +22,11 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.util.ArrayMap;
-import com.android.internal.util.Preconditions;
-
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
/**
* Helper object for setting and getting entity scores for classified text.
@@ -42,7 +41,7 @@ final class EntityConfidence implements Parcelable {
EntityConfidence() {}
EntityConfidence(@NonNull EntityConfidence source) {
- Preconditions.checkNotNull(source);
+ Objects.requireNonNull(source);
mEntityConfidence.putAll(source.mEntityConfidence);
mSortedEntities.addAll(source.mSortedEntities);
}
@@ -56,7 +55,7 @@ final class EntityConfidence implements Parcelable {
* 1 (high confidence).
*/
EntityConfidence(@NonNull Map<String, Float> source) {
- Preconditions.checkNotNull(source);
+ Objects.requireNonNull(source);
// Prune non-existent entities and clamp to 1.
mEntityConfidence.ensureCapacity(source.size());
diff --git a/core/java/android/view/textclassifier/GenerateLinksLogger.java b/core/java/android/view/textclassifier/GenerateLinksLogger.java
index 3996b277aa1c..17ec73ad395f 100644
--- a/core/java/android/view/textclassifier/GenerateLinksLogger.java
+++ b/core/java/android/view/textclassifier/GenerateLinksLogger.java
@@ -23,7 +23,6 @@ import android.util.ArrayMap;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.internal.util.Preconditions;
import java.util.Locale;
import java.util.Map;
@@ -66,9 +65,9 @@ public final class GenerateLinksLogger {
/** Logs statistics about a call to generateLinks. */
public void logGenerateLinks(CharSequence text, TextLinks links, String callingPackageName,
long latencyMs) {
- Preconditions.checkNotNull(text);
- Preconditions.checkNotNull(links);
- Preconditions.checkNotNull(callingPackageName);
+ Objects.requireNonNull(text);
+ Objects.requireNonNull(links);
+ Objects.requireNonNull(callingPackageName);
if (!shouldLog()) {
return;
}
diff --git a/core/java/android/view/textclassifier/ModelFileManager.java b/core/java/android/view/textclassifier/ModelFileManager.java
index e04285db75be..0a4ff5d559ab 100644
--- a/core/java/android/view/textclassifier/ModelFileManager.java
+++ b/core/java/android/view/textclassifier/ModelFileManager.java
@@ -23,7 +23,6 @@ import android.os.ParcelFileDescriptor;
import android.text.TextUtils;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.Preconditions;
import java.io.File;
import java.io.FileNotFoundException;
@@ -51,7 +50,7 @@ public final class ModelFileManager {
private List<ModelFile> mModelFiles;
public ModelFileManager(Supplier<List<ModelFile>> modelFileSupplier) {
- mModelFileSupplier = Preconditions.checkNotNull(modelFileSupplier);
+ mModelFileSupplier = Objects.requireNonNull(modelFileSupplier);
}
/**
@@ -106,12 +105,12 @@ public final class ModelFileManager {
File updatedModelFile,
Function<Integer, Integer> versionSupplier,
Function<Integer, String> supportedLocalesSupplier) {
- mUpdatedModelFile = Preconditions.checkNotNull(updatedModelFile);
- mFactoryModelDir = Preconditions.checkNotNull(factoryModelDir);
+ mUpdatedModelFile = Objects.requireNonNull(updatedModelFile);
+ mFactoryModelDir = Objects.requireNonNull(factoryModelDir);
mModelFilenamePattern = Pattern.compile(
- Preconditions.checkNotNull(factoryModelFileNameRegex));
- mVersionSupplier = Preconditions.checkNotNull(versionSupplier);
- mSupportedLocalesSupplier = Preconditions.checkNotNull(supportedLocalesSupplier);
+ Objects.requireNonNull(factoryModelFileNameRegex));
+ mVersionSupplier = Objects.requireNonNull(versionSupplier);
+ mSupportedLocalesSupplier = Objects.requireNonNull(supportedLocalesSupplier);
}
@Override
@@ -208,10 +207,10 @@ public final class ModelFileManager {
public ModelFile(File file, int version, List<Locale> supportedLocales,
String supportedLocalesStr,
boolean languageIndependent) {
- mFile = Preconditions.checkNotNull(file);
+ mFile = Objects.requireNonNull(file);
mVersion = version;
- mSupportedLocales = Preconditions.checkNotNull(supportedLocales);
- mSupportedLocalesStr = Preconditions.checkNotNull(supportedLocalesStr);
+ mSupportedLocales = Objects.requireNonNull(supportedLocales);
+ mSupportedLocalesStr = Objects.requireNonNull(supportedLocalesStr);
mLanguageIndependent = languageIndependent;
}
@@ -232,7 +231,7 @@ public final class ModelFileManager {
/** Returns whether the language supports any language in the given ranges. */
public boolean isAnyLanguageSupported(List<Locale.LanguageRange> languageRanges) {
- Preconditions.checkNotNull(languageRanges);
+ Objects.requireNonNull(languageRanges);
return mLanguageIndependent || Locale.lookup(languageRanges, mSupportedLocales) != null;
}
diff --git a/core/java/android/view/textclassifier/SelectionEvent.java b/core/java/android/view/textclassifier/SelectionEvent.java
index 7d1077e50258..09cb7a07faa8 100644
--- a/core/java/android/view/textclassifier/SelectionEvent.java
+++ b/core/java/android/view/textclassifier/SelectionEvent.java
@@ -149,7 +149,7 @@ public final class SelectionEvent implements Parcelable {
mAbsoluteStart = start;
mAbsoluteEnd = end;
mEventType = eventType;
- mEntityType = Preconditions.checkNotNull(entityType);
+ mEntityType = Objects.requireNonNull(entityType);
mResultId = resultId;
mInvocationMethod = invocationMethod;
}
@@ -257,7 +257,7 @@ public final class SelectionEvent implements Parcelable {
public static SelectionEvent createSelectionModifiedEvent(
int start, int end, @NonNull TextClassification classification) {
Preconditions.checkArgument(end >= start, "end cannot be less than start");
- Preconditions.checkNotNull(classification);
+ Objects.requireNonNull(classification);
final String entityType = classification.getEntityCount() > 0
? classification.getEntity(0)
: TextClassifier.TYPE_UNKNOWN;
@@ -281,7 +281,7 @@ public final class SelectionEvent implements Parcelable {
public static SelectionEvent createSelectionModifiedEvent(
int start, int end, @NonNull TextSelection selection) {
Preconditions.checkArgument(end >= start, "end cannot be less than start");
- Preconditions.checkNotNull(selection);
+ Objects.requireNonNull(selection);
final String entityType = selection.getEntityCount() > 0
? selection.getEntity(0)
: TextClassifier.TYPE_UNKNOWN;
@@ -329,7 +329,7 @@ public final class SelectionEvent implements Parcelable {
int start, int end, @SelectionEvent.ActionType int actionType,
@NonNull TextClassification classification) {
Preconditions.checkArgument(end >= start, "end cannot be less than start");
- Preconditions.checkNotNull(classification);
+ Objects.requireNonNull(classification);
checkActionType(actionType);
final String entityType = classification.getEntityCount() > 0
? classification.getEntity(0)
@@ -398,7 +398,7 @@ public final class SelectionEvent implements Parcelable {
}
void setEntityType(@EntityType String entityType) {
- mEntityType = Preconditions.checkNotNull(entityType);
+ mEntityType = Objects.requireNonNull(entityType);
}
/**
diff --git a/core/java/android/view/textclassifier/SelectionSessionLogger.java b/core/java/android/view/textclassifier/SelectionSessionLogger.java
index 20cc94433872..9c9b2d0f1ce2 100644
--- a/core/java/android/view/textclassifier/SelectionSessionLogger.java
+++ b/core/java/android/view/textclassifier/SelectionSessionLogger.java
@@ -24,7 +24,6 @@ import android.metrics.LogMaker;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.internal.util.Preconditions;
import java.text.BreakIterator;
import java.util.List;
@@ -65,12 +64,12 @@ public final class SelectionSessionLogger {
@VisibleForTesting
public SelectionSessionLogger(@NonNull MetricsLogger metricsLogger) {
- mMetricsLogger = Preconditions.checkNotNull(metricsLogger);
+ mMetricsLogger = Objects.requireNonNull(metricsLogger);
}
/** Emits a selection event to the logs. */
public void writeEvent(@NonNull SelectionEvent event) {
- Preconditions.checkNotNull(event);
+ Objects.requireNonNull(event);
final LogMaker log = new LogMaker(MetricsEvent.TEXT_SELECTION_SESSION)
.setType(getLogType(event))
.setSubtype(getLogSubType(event))
@@ -240,7 +239,7 @@ public final class SelectionSessionLogger {
* Returns a token iterator for tokenizing text for logging purposes.
*/
public static BreakIterator getTokenIterator(@NonNull Locale locale) {
- return BreakIterator.getWordInstance(Preconditions.checkNotNull(locale));
+ return BreakIterator.getWordInstance(Objects.requireNonNull(locale));
}
/**
@@ -249,9 +248,9 @@ public final class SelectionSessionLogger {
public static String createId(
String text, int start, int end, Context context, int modelVersion,
List<Locale> locales) {
- Preconditions.checkNotNull(text);
- Preconditions.checkNotNull(context);
- Preconditions.checkNotNull(locales);
+ Objects.requireNonNull(text);
+ Objects.requireNonNull(context);
+ Objects.requireNonNull(locales);
final StringJoiner localesJoiner = new StringJoiner(",");
for (Locale locale : locales) {
localesJoiner.add(locale.toLanguageTag());
diff --git a/core/java/android/view/textclassifier/SystemTextClassifier.java b/core/java/android/view/textclassifier/SystemTextClassifier.java
index 66f75043a9c8..138d25dd7c83 100644
--- a/core/java/android/view/textclassifier/SystemTextClassifier.java
+++ b/core/java/android/view/textclassifier/SystemTextClassifier.java
@@ -33,8 +33,8 @@ import android.service.textclassifier.TextClassifierService;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting.Visibility;
import com.android.internal.util.IndentingPrintWriter;
-import com.android.internal.util.Preconditions;
+import java.util.Objects;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -61,10 +61,10 @@ public final class SystemTextClassifier implements TextClassifier {
throws ServiceManager.ServiceNotFoundException {
mManagerService = ITextClassifierService.Stub.asInterface(
ServiceManager.getServiceOrThrow(Context.TEXT_CLASSIFICATION_SERVICE));
- mSettings = Preconditions.checkNotNull(settings);
+ mSettings = Objects.requireNonNull(settings);
mFallback = context.getSystemService(TextClassificationManager.class)
.getTextClassifier(TextClassifier.LOCAL);
- mPackageName = Preconditions.checkNotNull(context.getOpPackageName());
+ mPackageName = Objects.requireNonNull(context.getOpPackageName());
mUserId = context.getUserId();
}
@@ -74,7 +74,7 @@ public final class SystemTextClassifier implements TextClassifier {
@Override
@WorkerThread
public TextSelection suggestSelection(TextSelection.Request request) {
- Preconditions.checkNotNull(request);
+ Objects.requireNonNull(request);
Utils.checkMainThread();
try {
request.setCallingPackageName(mPackageName);
@@ -98,7 +98,7 @@ public final class SystemTextClassifier implements TextClassifier {
@Override
@WorkerThread
public TextClassification classifyText(TextClassification.Request request) {
- Preconditions.checkNotNull(request);
+ Objects.requireNonNull(request);
Utils.checkMainThread();
try {
request.setCallingPackageName(mPackageName);
@@ -122,7 +122,7 @@ public final class SystemTextClassifier implements TextClassifier {
@Override
@WorkerThread
public TextLinks generateLinks(@NonNull TextLinks.Request request) {
- Preconditions.checkNotNull(request);
+ Objects.requireNonNull(request);
Utils.checkMainThread();
if (!mSettings.isSmartLinkifyEnabled() && request.isLegacyFallback()) {
@@ -147,7 +147,7 @@ public final class SystemTextClassifier implements TextClassifier {
@Override
public void onSelectionEvent(SelectionEvent event) {
- Preconditions.checkNotNull(event);
+ Objects.requireNonNull(event);
Utils.checkMainThread();
try {
@@ -160,7 +160,7 @@ public final class SystemTextClassifier implements TextClassifier {
@Override
public void onTextClassifierEvent(@NonNull TextClassifierEvent event) {
- Preconditions.checkNotNull(event);
+ Objects.requireNonNull(event);
Utils.checkMainThread();
try {
@@ -178,7 +178,7 @@ public final class SystemTextClassifier implements TextClassifier {
@Override
public TextLanguage detectLanguage(TextLanguage.Request request) {
- Preconditions.checkNotNull(request);
+ Objects.requireNonNull(request);
Utils.checkMainThread();
try {
@@ -199,7 +199,7 @@ public final class SystemTextClassifier implements TextClassifier {
@Override
public ConversationActions suggestConversationActions(ConversationActions.Request request) {
- Preconditions.checkNotNull(request);
+ Objects.requireNonNull(request);
Utils.checkMainThread();
try {
@@ -260,7 +260,7 @@ public final class SystemTextClassifier implements TextClassifier {
void initializeRemoteSession(
@NonNull TextClassificationContext classificationContext,
@NonNull TextClassificationSessionId sessionId) {
- mSessionId = Preconditions.checkNotNull(sessionId);
+ mSessionId = Objects.requireNonNull(sessionId);
try {
classificationContext.setUserId(mUserId);
mManagerService.onCreateTextClassificationSession(classificationContext, mSessionId);
diff --git a/core/java/android/view/textclassifier/TextClassification.java b/core/java/android/view/textclassifier/TextClassification.java
index 93f7103c3d8d..3628d2d40c1e 100644
--- a/core/java/android/view/textclassifier/TextClassification.java
+++ b/core/java/android/view/textclassifier/TextClassification.java
@@ -150,7 +150,7 @@ public final class TextClassification implements Parcelable {
mLegacyIntent = legacyIntent;
mLegacyOnClickListener = legacyOnClickListener;
mActions = Collections.unmodifiableList(actions);
- mEntityConfidence = Preconditions.checkNotNull(entityConfidence);
+ mEntityConfidence = Objects.requireNonNull(entityConfidence);
mId = id;
mExtras = extras;
}
@@ -287,7 +287,7 @@ public final class TextClassification implements Parcelable {
* @hide
*/
public static OnClickListener createIntentOnClickListener(@NonNull final PendingIntent intent) {
- Preconditions.checkNotNull(intent);
+ Objects.requireNonNull(intent);
return v -> {
try {
intent.send();
diff --git a/core/java/android/view/textclassifier/TextClassificationContext.java b/core/java/android/view/textclassifier/TextClassificationContext.java
index e4baaac9a300..930765b29197 100644
--- a/core/java/android/view/textclassifier/TextClassificationContext.java
+++ b/core/java/android/view/textclassifier/TextClassificationContext.java
@@ -24,9 +24,8 @@ import android.os.Parcelable;
import android.os.UserHandle;
import android.view.textclassifier.TextClassifier.WidgetType;
-import com.android.internal.util.Preconditions;
-
import java.util.Locale;
+import java.util.Objects;
/**
* A representation of the context in which text classification would be performed.
@@ -44,8 +43,8 @@ public final class TextClassificationContext implements Parcelable {
String packageName,
String widgetType,
String widgetVersion) {
- mPackageName = Preconditions.checkNotNull(packageName);
- mWidgetType = Preconditions.checkNotNull(widgetType);
+ mPackageName = Objects.requireNonNull(packageName);
+ mWidgetType = Objects.requireNonNull(widgetType);
mWidgetVersion = widgetVersion;
}
@@ -121,8 +120,8 @@ public final class TextClassificationContext implements Parcelable {
* @return this builder
*/
public Builder(@NonNull String packageName, @NonNull @WidgetType String widgetType) {
- mPackageName = Preconditions.checkNotNull(packageName);
- mWidgetType = Preconditions.checkNotNull(widgetType);
+ mPackageName = Objects.requireNonNull(packageName);
+ mWidgetType = Objects.requireNonNull(widgetType);
}
/**
diff --git a/core/java/android/view/textclassifier/TextClassificationManager.java b/core/java/android/view/textclassifier/TextClassificationManager.java
index 7c25bf0f277d..bb96d5543b0b 100644
--- a/core/java/android/view/textclassifier/TextClassificationManager.java
+++ b/core/java/android/view/textclassifier/TextClassificationManager.java
@@ -19,8 +19,8 @@ package android.view.textclassifier;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.ServiceManager;
import android.provider.DeviceConfig;
@@ -31,9 +31,9 @@ import android.view.textclassifier.TextClassifier.TextClassifierType;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;
-import com.android.internal.util.Preconditions;
import java.lang.ref.WeakReference;
+import java.util.Objects;
import java.util.Set;
/**
@@ -71,7 +71,7 @@ public final class TextClassificationManager {
/** @hide */
public TextClassificationManager(Context context) {
- mContext = Preconditions.checkNotNull(context);
+ mContext = Objects.requireNonNull(context);
mSessionFactory = mDefaultSessionFactory;
mSettingsObserver = new SettingsObserver(this);
}
@@ -157,10 +157,10 @@ public final class TextClassificationManager {
@NonNull
public TextClassifier createTextClassificationSession(
@NonNull TextClassificationContext classificationContext) {
- Preconditions.checkNotNull(classificationContext);
+ Objects.requireNonNull(classificationContext);
final TextClassifier textClassifier =
mSessionFactory.createTextClassificationSession(classificationContext);
- Preconditions.checkNotNull(textClassifier, "Session Factory should never return null");
+ Objects.requireNonNull(textClassifier, "Session Factory should never return null");
return textClassifier;
}
@@ -170,8 +170,8 @@ public final class TextClassificationManager {
*/
public TextClassifier createTextClassificationSession(
TextClassificationContext classificationContext, TextClassifier textClassifier) {
- Preconditions.checkNotNull(classificationContext);
- Preconditions.checkNotNull(textClassifier);
+ Objects.requireNonNull(classificationContext);
+ Objects.requireNonNull(textClassifier);
return new TextClassificationSession(classificationContext, textClassifier);
}
@@ -280,7 +280,7 @@ public final class TextClassificationManager {
/** @hide */
public static TextClassificationConstants getSettings(Context context) {
- Preconditions.checkNotNull(context);
+ Objects.requireNonNull(context);
final TextClassificationManager tcm =
context.getSystemService(TextClassificationManager.class);
if (tcm != null) {
diff --git a/core/java/android/view/textclassifier/TextClassificationSession.java b/core/java/android/view/textclassifier/TextClassificationSession.java
index 6a706f5183ce..abfbc6c4f4ae 100644
--- a/core/java/android/view/textclassifier/TextClassificationSession.java
+++ b/core/java/android/view/textclassifier/TextClassificationSession.java
@@ -20,6 +20,7 @@ import android.annotation.WorkerThread;
import android.view.textclassifier.SelectionEvent.InvocationMethod;
import com.android.internal.util.Preconditions;
+import java.util.Objects;
/**
* Session-aware TextClassifier.
@@ -37,8 +38,8 @@ final class TextClassificationSession implements TextClassifier {
private boolean mDestroyed;
TextClassificationSession(TextClassificationContext context, TextClassifier delegate) {
- mClassificationContext = Preconditions.checkNotNull(context);
- mDelegate = Preconditions.checkNotNull(delegate);
+ mClassificationContext = Objects.requireNonNull(context);
+ mDelegate = Objects.requireNonNull(delegate);
mSessionId = new TextClassificationSessionId();
mEventHelper = new SelectionEventHelper(mSessionId, mClassificationContext);
initializeRemoteSession();
@@ -149,8 +150,8 @@ final class TextClassificationSession implements TextClassifier {
SelectionEventHelper(
TextClassificationSessionId sessionId, TextClassificationContext context) {
- mSessionId = Preconditions.checkNotNull(sessionId);
- mContext = Preconditions.checkNotNull(context);
+ mSessionId = Objects.requireNonNull(sessionId);
+ mContext = Objects.requireNonNull(context);
}
/**
diff --git a/core/java/android/view/textclassifier/TextClassificationSessionId.java b/core/java/android/view/textclassifier/TextClassificationSessionId.java
index 8b68e17aa681..f90e6b2e407c 100644
--- a/core/java/android/view/textclassifier/TextClassificationSessionId.java
+++ b/core/java/android/view/textclassifier/TextClassificationSessionId.java
@@ -20,9 +20,8 @@ import android.annotation.NonNull;
import android.os.Parcel;
import android.os.Parcelable;
-import com.android.internal.util.Preconditions;
-
import java.util.Locale;
+import java.util.Objects;
import java.util.UUID;
/**
@@ -118,7 +117,7 @@ public final class TextClassificationSessionId implements Parcelable {
@Override
public TextClassificationSessionId createFromParcel(Parcel parcel) {
return new TextClassificationSessionId(
- Preconditions.checkNotNull(parcel.readString()));
+ Objects.requireNonNull(parcel.readString()));
}
@Override
diff --git a/core/java/android/view/textclassifier/TextClassifier.java b/core/java/android/view/textclassifier/TextClassifier.java
index ac8a429a0fd6..9b3369390b6a 100644
--- a/core/java/android/view/textclassifier/TextClassifier.java
+++ b/core/java/android/view/textclassifier/TextClassifier.java
@@ -46,6 +46,7 @@ import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
/**
@@ -193,7 +194,7 @@ public interface TextClassifier {
@WorkerThread
@NonNull
default TextSelection suggestSelection(@NonNull TextSelection.Request request) {
- Preconditions.checkNotNull(request);
+ Objects.requireNonNull(request);
Utils.checkMainThread();
return new TextSelection.Builder(request.getStartIndex(), request.getEndIndex()).build();
}
@@ -252,7 +253,7 @@ public interface TextClassifier {
@WorkerThread
@NonNull
default TextClassification classifyText(@NonNull TextClassification.Request request) {
- Preconditions.checkNotNull(request);
+ Objects.requireNonNull(request);
Utils.checkMainThread();
return TextClassification.EMPTY;
}
@@ -313,7 +314,7 @@ public interface TextClassifier {
@WorkerThread
@NonNull
default TextLinks generateLinks(@NonNull TextLinks.Request request) {
- Preconditions.checkNotNull(request);
+ Objects.requireNonNull(request);
Utils.checkMainThread();
return new TextLinks.Builder(request.getText().toString()).build();
}
@@ -346,7 +347,7 @@ public interface TextClassifier {
@WorkerThread
@NonNull
default TextLanguage detectLanguage(@NonNull TextLanguage.Request request) {
- Preconditions.checkNotNull(request);
+ Objects.requireNonNull(request);
Utils.checkMainThread();
return TextLanguage.EMPTY;
}
@@ -358,7 +359,7 @@ public interface TextClassifier {
@NonNull
default ConversationActions suggestConversationActions(
@NonNull ConversationActions.Request request) {
- Preconditions.checkNotNull(request);
+ Objects.requireNonNull(request);
Utils.checkMainThread();
return new ConversationActions(Collections.emptyList(), null);
}
@@ -427,9 +428,9 @@ public interface TextClassifier {
List<String> excludedEntityTypes,
List<String> hints,
boolean includeTypesFromTextClassifier) {
- mIncludedTypes = Preconditions.checkNotNull(includedEntityTypes);
- mExcludedTypes = Preconditions.checkNotNull(excludedEntityTypes);
- mHints = Preconditions.checkNotNull(hints);
+ mIncludedTypes = Objects.requireNonNull(includedEntityTypes);
+ mExcludedTypes = Objects.requireNonNull(excludedEntityTypes);
+ mHints = Objects.requireNonNull(hints);
mIncludeTypesFromTextClassifier = includeTypesFromTextClassifier;
}
diff --git a/core/java/android/view/textclassifier/TextClassifierEvent.java b/core/java/android/view/textclassifier/TextClassifierEvent.java
index eb6aec07aad9..db8801150f0d 100644
--- a/core/java/android/view/textclassifier/TextClassifierEvent.java
+++ b/core/java/android/view/textclassifier/TextClassifierEvent.java
@@ -25,11 +25,11 @@ import android.os.Parcel;
import android.os.Parcelable;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.Preconditions;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
+import java.util.Objects;
/**
* This class represents events that are sent by components to the {@link TextClassifier} to report
@@ -549,7 +549,7 @@ public abstract class TextClassifierEvent implements Parcelable {
*/
@NonNull
public T setEntityTypes(@NonNull String... entityTypes) {
- Preconditions.checkNotNull(entityTypes);
+ Objects.requireNonNull(entityTypes);
mEntityTypes = new String[entityTypes.length];
System.arraycopy(entityTypes, 0, mEntityTypes, 0, entityTypes.length);
return self();
@@ -587,7 +587,7 @@ public abstract class TextClassifierEvent implements Parcelable {
*/
@NonNull
public T setScores(@NonNull float... scores) {
- Preconditions.checkNotNull(scores);
+ Objects.requireNonNull(scores);
mScores = new float[scores.length];
System.arraycopy(scores, 0, mScores, 0, scores.length);
return self();
@@ -652,7 +652,7 @@ public abstract class TextClassifierEvent implements Parcelable {
*/
@NonNull
public T setExtras(@NonNull Bundle extras) {
- mExtras = Preconditions.checkNotNull(extras);
+ mExtras = Objects.requireNonNull(extras);
return self();
}
diff --git a/core/java/android/view/textclassifier/TextClassifierEventTronLogger.java b/core/java/android/view/textclassifier/TextClassifierEventTronLogger.java
index 3e088b8565f2..8162699a74c6 100644
--- a/core/java/android/view/textclassifier/TextClassifierEventTronLogger.java
+++ b/core/java/android/view/textclassifier/TextClassifierEventTronLogger.java
@@ -29,7 +29,7 @@ import android.metrics.LogMaker;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.internal.util.Preconditions;
+import java.util.Objects;
/**
@@ -50,12 +50,12 @@ public final class TextClassifierEventTronLogger {
@VisibleForTesting
public TextClassifierEventTronLogger(MetricsLogger metricsLogger) {
- mMetricsLogger = Preconditions.checkNotNull(metricsLogger);
+ mMetricsLogger = Objects.requireNonNull(metricsLogger);
}
/** Emits a text classifier event to the logs. */
public void writeEvent(TextClassifierEvent event) {
- Preconditions.checkNotNull(event);
+ Objects.requireNonNull(event);
int category = getCategory(event);
if (category == -1) {
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index 024c379e0165..61bd7c72b80b 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -130,9 +130,9 @@ public final class TextClassifierImpl implements TextClassifier {
public TextClassifierImpl(
Context context, TextClassificationConstants settings, TextClassifier fallback) {
- mContext = Preconditions.checkNotNull(context);
- mFallback = Preconditions.checkNotNull(fallback);
- mSettings = Preconditions.checkNotNull(settings);
+ mContext = Objects.requireNonNull(context);
+ mFallback = Objects.requireNonNull(fallback);
+ mSettings = Objects.requireNonNull(settings);
mGenerateLinksLogger = new GenerateLinksLogger(mSettings.getGenerateLinksLogSampleRate());
mAnnotatorModelFileManager = new ModelFileManager(
new ModelFileManager.ModelFileSupplierImpl(
@@ -180,7 +180,7 @@ public final class TextClassifierImpl implements TextClassifier {
@Override
@WorkerThread
public TextSelection suggestSelection(TextSelection.Request request) {
- Preconditions.checkNotNull(request);
+ Objects.requireNonNull(request);
Utils.checkMainThread();
try {
final int rangeLength = request.getEndIndex() - request.getStartIndex();
@@ -245,7 +245,7 @@ public final class TextClassifierImpl implements TextClassifier {
@Override
@WorkerThread
public TextClassification classifyText(TextClassification.Request request) {
- Preconditions.checkNotNull(request);
+ Objects.requireNonNull(request);
Utils.checkMainThread();
try {
final int rangeLength = request.getEndIndex() - request.getStartIndex();
@@ -285,7 +285,7 @@ public final class TextClassifierImpl implements TextClassifier {
@Override
@WorkerThread
public TextLinks generateLinks(@NonNull TextLinks.Request request) {
- Preconditions.checkNotNull(request);
+ Objects.requireNonNull(request);
Utils.checkTextLength(request.getText(), getMaxGenerateLinksTextLength());
Utils.checkMainThread();
@@ -399,7 +399,7 @@ public final class TextClassifierImpl implements TextClassifier {
/** @inheritDoc */
@Override
public TextLanguage detectLanguage(@NonNull TextLanguage.Request request) {
- Preconditions.checkNotNull(request);
+ Objects.requireNonNull(request);
Utils.checkMainThread();
try {
final TextLanguage.Builder builder = new TextLanguage.Builder();
@@ -420,7 +420,7 @@ public final class TextClassifierImpl implements TextClassifier {
@Override
public ConversationActions suggestConversationActions(ConversationActions.Request request) {
- Preconditions.checkNotNull(request);
+ Objects.requireNonNull(request);
Utils.checkMainThread();
try {
ActionsSuggestionsModel actionsImpl = getActionsImpl();
diff --git a/core/java/android/view/textclassifier/TextLinks.java b/core/java/android/view/textclassifier/TextLinks.java
index bbb7f07e0fdc..1aa2aeccc0db 100644
--- a/core/java/android/view/textclassifier/TextLinks.java
+++ b/core/java/android/view/textclassifier/TextLinks.java
@@ -42,12 +42,14 @@ import com.android.internal.util.Preconditions;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.Objects;
import java.util.function.Function;
/**
@@ -109,7 +111,6 @@ public final class TextLinks implements Parcelable {
/**
* Returns the text that was used to generate these links.
- * @hide
*/
@NonNull
public String getText() {
@@ -155,7 +156,7 @@ public final class TextLinks implements Parcelable {
@NonNull Spannable text,
@ApplyStrategy int applyStrategy,
@Nullable Function<TextLink, TextLinkSpan> spanFactory) {
- Preconditions.checkNotNull(text);
+ Objects.requireNonNull(text);
return new TextLinksParams.Builder()
.setApplyStrategy(applyStrategy)
.setSpanFactory(spanFactory)
@@ -223,10 +224,10 @@ public final class TextLinks implements Parcelable {
*/
private TextLink(int start, int end, @NonNull EntityConfidence entityConfidence,
@NonNull Bundle extras, @Nullable URLSpan urlSpan) {
- Preconditions.checkNotNull(entityConfidence);
+ Objects.requireNonNull(entityConfidence);
Preconditions.checkArgument(!entityConfidence.getEntities().isEmpty());
Preconditions.checkArgument(start <= end);
- Preconditions.checkNotNull(extras);
+ Objects.requireNonNull(extras);
mStart = start;
mEnd = end;
mEntityScores = entityConfidence;
@@ -341,6 +342,7 @@ public final class TextLinks implements Parcelable {
private final boolean mLegacyFallback;
@Nullable private String mCallingPackageName;
private final Bundle mExtras;
+ @Nullable private final ZonedDateTime mReferenceTime;
@UserIdInt
private int mUserId = UserHandle.USER_NULL;
@@ -349,11 +351,13 @@ public final class TextLinks implements Parcelable {
LocaleList defaultLocales,
EntityConfig entityConfig,
boolean legacyFallback,
+ ZonedDateTime referenceTime,
Bundle extras) {
mText = text;
mDefaultLocales = defaultLocales;
mEntityConfig = entityConfig;
mLegacyFallback = legacyFallback;
+ mReferenceTime = referenceTime;
mExtras = extras;
}
@@ -394,6 +398,15 @@ public final class TextLinks implements Parcelable {
}
/**
+ * @return reference time based on which relative dates (e.g. "tomorrow") should be
+ * interpreted.
+ */
+ @Nullable
+ public ZonedDateTime getReferenceTime() {
+ return mReferenceTime;
+ }
+
+ /**
* Sets the name of the package that is sending this request.
* <p>
* Package-private for SystemTextClassifier's use.
@@ -453,9 +466,10 @@ public final class TextLinks implements Parcelable {
@Nullable private EntityConfig mEntityConfig;
private boolean mLegacyFallback = true; // Use legacy fall back by default.
@Nullable private Bundle mExtras;
+ @Nullable private ZonedDateTime mReferenceTime;
public Builder(@NonNull CharSequence text) {
- mText = Preconditions.checkNotNull(text);
+ mText = Objects.requireNonNull(text);
}
/**
@@ -510,13 +524,26 @@ public final class TextLinks implements Parcelable {
}
/**
+ * @param referenceTime reference time based on which relative dates (e.g. "tomorrow"
+ * should be interpreted. This should usually be the time when the text was
+ * originally composed.
+ *
+ * @return this builder
+ */
+ @NonNull
+ public Builder setReferenceTime(@Nullable ZonedDateTime referenceTime) {
+ mReferenceTime = referenceTime;
+ return this;
+ }
+
+ /**
* Builds and returns the request object.
*/
@NonNull
public Request build() {
return new Request(
mText, mDefaultLocales, mEntityConfig,
- mLegacyFallback,
+ mLegacyFallback, mReferenceTime,
mExtras == null ? Bundle.EMPTY : mExtras);
}
}
@@ -534,6 +561,7 @@ public final class TextLinks implements Parcelable {
dest.writeString(mCallingPackageName);
dest.writeInt(mUserId);
dest.writeBundle(mExtras);
+ dest.writeString(mReferenceTime == null ? null : mReferenceTime.toString());
}
private static Request readFromParcel(Parcel in) {
@@ -543,9 +571,12 @@ public final class TextLinks implements Parcelable {
final String callingPackageName = in.readString();
final int userId = in.readInt();
final Bundle extras = in.readBundle();
+ final String referenceTimeString = in.readString();
+ final ZonedDateTime referenceTime = referenceTimeString == null
+ ? null : ZonedDateTime.parse(referenceTimeString);
final Request request = new Request(text, defaultLocales, entityConfig,
- /* legacyFallback= */ true, extras);
+ /* legacyFallback= */ true, referenceTime, extras);
request.setCallingPackageName(callingPackageName);
request.setUserId(userId);
return request;
@@ -654,7 +685,7 @@ public final class TextLinks implements Parcelable {
* @param fullText The full text to annotate with links
*/
public Builder(@NonNull String fullText) {
- mFullText = Preconditions.checkNotNull(fullText);
+ mFullText = Objects.requireNonNull(fullText);
mLinks = new ArrayList<>();
}
diff --git a/core/java/android/view/textclassifier/TextLinksParams.java b/core/java/android/view/textclassifier/TextLinksParams.java
index 8af423300406..b7d63bfabd6d 100644
--- a/core/java/android/view/textclassifier/TextLinksParams.java
+++ b/core/java/android/view/textclassifier/TextLinksParams.java
@@ -25,10 +25,9 @@ import android.text.util.Linkify.LinkifyMask;
import android.view.textclassifier.TextLinks.TextLink;
import android.view.textclassifier.TextLinks.TextLinkSpan;
-import com.android.internal.util.Preconditions;
-
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
import java.util.function.Function;
/**
@@ -103,8 +102,8 @@ public final class TextLinksParams {
*/
@TextLinks.Status
public int apply(@NonNull Spannable text, @NonNull TextLinks textLinks) {
- Preconditions.checkNotNull(text);
- Preconditions.checkNotNull(textLinks);
+ Objects.requireNonNull(text);
+ Objects.requireNonNull(textLinks);
final String textString = text.toString();
diff --git a/core/java/android/view/textclassifier/TextSelection.java b/core/java/android/view/textclassifier/TextSelection.java
index 0c8974956a7a..4a36cbfc35e5 100644
--- a/core/java/android/view/textclassifier/TextSelection.java
+++ b/core/java/android/view/textclassifier/TextSelection.java
@@ -36,6 +36,7 @@ import com.android.internal.util.Preconditions;
import java.util.Locale;
import java.util.Map;
+import java.util.Objects;
/**
* Information about where text selection should be.
@@ -165,7 +166,7 @@ public final class TextSelection implements Parcelable {
public Builder setEntityType(
@NonNull @EntityType String type,
@FloatRange(from = 0.0, to = 1.0) float confidenceScore) {
- Preconditions.checkNotNull(type);
+ Objects.requireNonNull(type);
mEntityConfidence.put(type, confidenceScore);
return this;
}
diff --git a/core/java/android/view/textclassifier/intent/LabeledIntent.java b/core/java/android/view/textclassifier/intent/LabeledIntent.java
index 30fc20ea86a1..cbd9d1a522f6 100644
--- a/core/java/android/view/textclassifier/intent/LabeledIntent.java
+++ b/core/java/android/view/textclassifier/intent/LabeledIntent.java
@@ -32,7 +32,8 @@ import android.view.textclassifier.TextClassification;
import android.view.textclassifier.TextClassifier;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.Preconditions;
+
+import java.util.Objects;
/**
* Helper class to store the information from which RemoteActions are built.
@@ -86,9 +87,9 @@ public final class LabeledIntent {
}
this.titleWithoutEntity = titleWithoutEntity;
this.titleWithEntity = titleWithEntity;
- this.description = Preconditions.checkNotNull(description);
+ this.description = Objects.requireNonNull(description);
this.descriptionWithAppName = descriptionWithAppName;
- this.intent = Preconditions.checkNotNull(intent);
+ this.intent = Objects.requireNonNull(intent);
this.requestCode = requestCode;
}
@@ -198,8 +199,8 @@ public final class LabeledIntent {
public final RemoteAction remoteAction;
public Result(Intent resolvedIntent, RemoteAction remoteAction) {
- this.resolvedIntent = Preconditions.checkNotNull(resolvedIntent);
- this.remoteAction = Preconditions.checkNotNull(remoteAction);
+ this.resolvedIntent = Objects.requireNonNull(resolvedIntent);
+ this.remoteAction = Objects.requireNonNull(remoteAction);
}
}
diff --git a/core/java/android/view/textclassifier/intent/TemplateClassificationIntentFactory.java b/core/java/android/view/textclassifier/intent/TemplateClassificationIntentFactory.java
index 111fc6ab5f9f..aef4bd6c7351 100644
--- a/core/java/android/view/textclassifier/intent/TemplateClassificationIntentFactory.java
+++ b/core/java/android/view/textclassifier/intent/TemplateClassificationIntentFactory.java
@@ -30,6 +30,7 @@ import com.google.android.textclassifier.RemoteActionTemplate;
import java.time.Instant;
import java.util.Collections;
import java.util.List;
+import java.util.Objects;
/**
* Creates intents based on {@link RemoteActionTemplate} objects for a ClassificationResult.
@@ -44,8 +45,8 @@ public final class TemplateClassificationIntentFactory implements Classification
public TemplateClassificationIntentFactory(TemplateIntentFactory templateIntentFactory,
ClassificationIntentFactory fallback) {
- mTemplateIntentFactory = Preconditions.checkNotNull(templateIntentFactory);
- mFallback = Preconditions.checkNotNull(fallback);
+ mTemplateIntentFactory = Objects.requireNonNull(templateIntentFactory);
+ mFallback = Objects.requireNonNull(fallback);
}
/**
diff --git a/core/java/android/view/textclassifier/logging/SmartSelectionEventTracker.java b/core/java/android/view/textclassifier/logging/SmartSelectionEventTracker.java
index 157c43597a44..7dbcbf971bed 100644
--- a/core/java/android/view/textclassifier/logging/SmartSelectionEventTracker.java
+++ b/core/java/android/view/textclassifier/logging/SmartSelectionEventTracker.java
@@ -19,7 +19,7 @@ package android.view.textclassifier.logging;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.metrics.LogMaker;
import android.util.Log;
@@ -105,14 +105,14 @@ public final class SmartSelectionEventTracker {
public SmartSelectionEventTracker(@NonNull Context context, @WidgetType int widgetType) {
mWidgetType = widgetType;
mWidgetVersion = null;
- mContext = Preconditions.checkNotNull(context);
+ mContext = Objects.requireNonNull(context);
}
public SmartSelectionEventTracker(
@NonNull Context context, @WidgetType int widgetType, @Nullable String widgetVersion) {
mWidgetType = widgetType;
mWidgetVersion = widgetVersion;
- mContext = Preconditions.checkNotNull(context);
+ mContext = Objects.requireNonNull(context);
}
/**
@@ -122,7 +122,7 @@ public final class SmartSelectionEventTracker {
*/
@UnsupportedAppUsage(trackingBug = 136637107)
public void logEvent(@NonNull SelectionEvent event) {
- Preconditions.checkNotNull(event);
+ Objects.requireNonNull(event);
if (event.mEventType != SelectionEvent.EventType.SELECTION_STARTED && mSessionId == null
&& DEBUG_LOG_ENABLED) {
@@ -435,8 +435,8 @@ public final class SmartSelectionEventTracker {
mStart = start;
mEnd = end;
mEventType = eventType;
- mEntityType = Preconditions.checkNotNull(entityType);
- mVersionTag = Preconditions.checkNotNull(versionTag);
+ mEntityType = Objects.requireNonNull(entityType);
+ mVersionTag = Objects.requireNonNull(versionTag);
}
/**
diff --git a/core/java/android/view/textservice/SpellCheckerSession.java b/core/java/android/view/textservice/SpellCheckerSession.java
index f553ca512881..afddaa2ff58a 100644
--- a/core/java/android/view/textservice/SpellCheckerSession.java
+++ b/core/java/android/view/textservice/SpellCheckerSession.java
@@ -16,7 +16,7 @@
package android.view.textservice;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Binder;
import android.os.Handler;
import android.os.HandlerThread;
diff --git a/core/java/android/view/textservice/TextServicesManager.java b/core/java/android/view/textservice/TextServicesManager.java
index 9ff64d9b268a..acb35d63df9d 100644
--- a/core/java/android/view/textservice/TextServicesManager.java
+++ b/core/java/android/view/textservice/TextServicesManager.java
@@ -18,8 +18,8 @@ package android.view.textservice;
import android.annotation.NonNull;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.UserIdInt;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Bundle;
import android.os.RemoteException;
diff --git a/core/java/android/webkit/CacheManager.java b/core/java/android/webkit/CacheManager.java
index 7e067197ced8..fafe81393888 100644
--- a/core/java/android/webkit/CacheManager.java
+++ b/core/java/android/webkit/CacheManager.java
@@ -17,7 +17,7 @@
package android.webkit;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import java.io.File;
import java.io.IOException;
diff --git a/core/java/android/webkit/ConsoleMessage.java b/core/java/android/webkit/ConsoleMessage.java
index e54849772f9a..5474557c9998 100644
--- a/core/java/android/webkit/ConsoleMessage.java
+++ b/core/java/android/webkit/ConsoleMessage.java
@@ -16,7 +16,7 @@
package android.webkit;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
/**
diff --git a/core/java/android/webkit/JsResult.java b/core/java/android/webkit/JsResult.java
index 5bf6aab3225d..448db58e2658 100644
--- a/core/java/android/webkit/JsResult.java
+++ b/core/java/android/webkit/JsResult.java
@@ -17,7 +17,7 @@
package android.webkit;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* An instance of this class is passed as a parameter in various {@link WebChromeClient} action
diff --git a/core/java/android/webkit/PluginData.java b/core/java/android/webkit/PluginData.java
index 8aeeb1c53241..c9a196017a75 100644
--- a/core/java/android/webkit/PluginData.java
+++ b/core/java/android/webkit/PluginData.java
@@ -16,7 +16,8 @@
package android.webkit;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
+
import java.io.InputStream;
import java.util.Map;
diff --git a/core/java/android/webkit/URLUtil.java b/core/java/android/webkit/URLUtil.java
index 5d704cb09dcb..844b156b84d3 100644
--- a/core/java/android/webkit/URLUtil.java
+++ b/core/java/android/webkit/URLUtil.java
@@ -17,7 +17,7 @@
package android.webkit;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.ParseException;
import android.net.Uri;
import android.net.WebAddress;
diff --git a/core/java/android/webkit/UrlInterceptHandler.java b/core/java/android/webkit/UrlInterceptHandler.java
index f23aae6be8c2..a48e10799be7 100644
--- a/core/java/android/webkit/UrlInterceptHandler.java
+++ b/core/java/android/webkit/UrlInterceptHandler.java
@@ -17,9 +17,8 @@
package android.webkit;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.webkit.CacheManager.CacheResult;
-import android.webkit.PluginData;
import java.util.Map;
diff --git a/core/java/android/webkit/UrlInterceptRegistry.java b/core/java/android/webkit/UrlInterceptRegistry.java
index eeb28d73be85..c9dee00942c3 100644
--- a/core/java/android/webkit/UrlInterceptRegistry.java
+++ b/core/java/android/webkit/UrlInterceptRegistry.java
@@ -17,10 +17,8 @@
package android.webkit;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.webkit.CacheManager.CacheResult;
-import android.webkit.PluginData;
-import android.webkit.UrlInterceptHandler;
import java.util.Iterator;
import java.util.LinkedList;
diff --git a/core/java/android/webkit/WebResourceResponse.java b/core/java/android/webkit/WebResourceResponse.java
index 7c8f33e181d6..219523b15ab0 100644
--- a/core/java/android/webkit/WebResourceResponse.java
+++ b/core/java/android/webkit/WebResourceResponse.java
@@ -18,7 +18,7 @@ package android.webkit;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import java.io.InputStream;
import java.io.StringBufferInputStream;
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 2895621f962a..2d27a789ebcb 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -19,7 +19,7 @@ package android.webkit;
import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import java.lang.annotation.ElementType;
diff --git a/core/java/android/webkit/WebSyncManager.java b/core/java/android/webkit/WebSyncManager.java
index e44d6ebf37d1..7046c5108783 100644
--- a/core/java/android/webkit/WebSyncManager.java
+++ b/core/java/android/webkit/WebSyncManager.java
@@ -16,7 +16,7 @@
package android.webkit;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
/**
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 4b479270d9eb..f9a713ac7fcc 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -21,8 +21,8 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.Widget;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
diff --git a/core/java/android/webkit/WebViewDelegate.java b/core/java/android/webkit/WebViewDelegate.java
index f5657dff538f..df86926a95dc 100644
--- a/core/java/android/webkit/WebViewDelegate.java
+++ b/core/java/android/webkit/WebViewDelegate.java
@@ -19,10 +19,10 @@ package android.webkit;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
import android.app.Application;
import android.app.ResourcesManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.res.Resources;
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index 678a25223ef5..941af6ef1d7a 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -17,10 +17,10 @@
package android.webkit;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
import android.app.AppGlobals;
import android.app.Application;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
diff --git a/core/java/android/webkit/WebViewProviderInfo.java b/core/java/android/webkit/WebViewProviderInfo.java
index 7e00cded2c5a..6629fdc4cdee 100644
--- a/core/java/android/webkit/WebViewProviderInfo.java
+++ b/core/java/android/webkit/WebViewProviderInfo.java
@@ -17,7 +17,7 @@
package android.webkit;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.Signature;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/webkit/WebViewProviderResponse.java b/core/java/android/webkit/WebViewProviderResponse.java
index 5622abe0e99f..b58cc4bb1577 100644
--- a/core/java/android/webkit/WebViewProviderResponse.java
+++ b/core/java/android/webkit/WebViewProviderResponse.java
@@ -16,7 +16,7 @@
package android.webkit;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.PackageInfo;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/webkit/WebViewUpdateService.java b/core/java/android/webkit/WebViewUpdateService.java
index 12d3221fb7b5..9152b438618f 100644
--- a/core/java/android/webkit/WebViewUpdateService.java
+++ b/core/java/android/webkit/WebViewUpdateService.java
@@ -17,7 +17,7 @@
package android.webkit;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.RemoteException;
/**
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 6d60366dc72d..4752eadfe385 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -20,7 +20,7 @@ import android.annotation.ColorInt;
import android.annotation.DrawableRes;
import android.annotation.NonNull;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java
index bbcba2e12a2c..11a6acf5b934 100644
--- a/core/java/android/widget/AbsSeekBar.java
+++ b/core/java/android/widget/AbsSeekBar.java
@@ -18,7 +18,7 @@ package android.widget;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
diff --git a/core/java/android/widget/ActionMenuPresenter.java b/core/java/android/widget/ActionMenuPresenter.java
index cfb93ec2321f..aa3590aaff0a 100644
--- a/core/java/android/widget/ActionMenuPresenter.java
+++ b/core/java/android/widget/ActionMenuPresenter.java
@@ -22,7 +22,7 @@ import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
diff --git a/core/java/android/widget/ActionMenuView.java b/core/java/android/widget/ActionMenuView.java
index 7e58622db3b8..3a743562110f 100644
--- a/core/java/android/widget/ActionMenuView.java
+++ b/core/java/android/widget/ActionMenuView.java
@@ -18,7 +18,7 @@ package android.widget;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StyleRes;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.drawable.Drawable;
diff --git a/core/java/android/widget/ActivityChooserModel.java b/core/java/android/widget/ActivityChooserModel.java
index f5bf7598aa5a..d87bdf482e43 100644
--- a/core/java/android/widget/ActivityChooserModel.java
+++ b/core/java/android/widget/ActivityChooserModel.java
@@ -16,8 +16,8 @@
package android.widget;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/widget/ActivityChooserView.java b/core/java/android/widget/ActivityChooserView.java
index 89ea0747b532..aa18d576c8f4 100644
--- a/core/java/android/widget/ActivityChooserView.java
+++ b/core/java/android/widget/ActivityChooserView.java
@@ -17,7 +17,7 @@
package android.widget;
import android.annotation.StringRes;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index c55f7d654548..52658404548c 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -18,7 +18,7 @@ package android.widget;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.database.DataSetObserver;
import android.os.Build;
diff --git a/core/java/android/widget/AnalogClock.java b/core/java/android/widget/AnalogClock.java
index 67a70b48b534..d165bd0f0fa7 100644
--- a/core/java/android/widget/AnalogClock.java
+++ b/core/java/android/widget/AnalogClock.java
@@ -16,7 +16,7 @@
package android.widget;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/widget/ArrayAdapter.java b/core/java/android/widget/ArrayAdapter.java
index f7225d036e15..de9f76d6eea1 100644
--- a/core/java/android/widget/ArrayAdapter.java
+++ b/core/java/android/widget/ArrayAdapter.java
@@ -21,7 +21,7 @@ import android.annotation.IdRes;
import android.annotation.LayoutRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Resources;
import android.util.Log;
diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java
index 8785251b0a64..8d9ae58be290 100644
--- a/core/java/android/widget/AutoCompleteTextView.java
+++ b/core/java/android/widget/AutoCompleteTextView.java
@@ -18,7 +18,7 @@ package android.widget;
import android.annotation.DrawableRes;
import android.annotation.IntDef;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Resources.Theme;
import android.content.res.TypedArray;
diff --git a/core/java/android/widget/BaseAdapter.java b/core/java/android/widget/BaseAdapter.java
index 7b9365b08a41..27cf9a64a8d5 100644
--- a/core/java/android/widget/BaseAdapter.java
+++ b/core/java/android/widget/BaseAdapter.java
@@ -17,7 +17,7 @@
package android.widget;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.database.DataSetObservable;
import android.database.DataSetObserver;
import android.view.View;
diff --git a/core/java/android/widget/CalendarView.java b/core/java/android/widget/CalendarView.java
index b552aa6c85c4..4b2f738ef7ab 100644
--- a/core/java/android/widget/CalendarView.java
+++ b/core/java/android/widget/CalendarView.java
@@ -23,8 +23,8 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StyleRes;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.Widget;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.TypedArray;
diff --git a/core/java/android/widget/CheckedTextView.java b/core/java/android/widget/CheckedTextView.java
index 8b70f41f050c..422d2d37321c 100644
--- a/core/java/android/widget/CheckedTextView.java
+++ b/core/java/android/widget/CheckedTextView.java
@@ -19,7 +19,7 @@ package android.widget;
import android.annotation.DrawableRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index eb0d9bf088af..3b6a00948463 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -148,8 +148,11 @@ import java.util.Map;
public class Editor {
private static final String TAG = "Editor";
private static final boolean DEBUG_UNDO = false;
- // Specifies whether to use or not the magnifier when pressing the insertion or selection
- // handles.
+
+ // Specifies whether to allow starting a cursor drag by dragging anywhere over the text.
+ @VisibleForTesting
+ public static boolean FLAG_ENABLE_CURSOR_DRAG = false;
+ // Specifies whether to use the magnifier when pressing the insertion or selection handles.
private static final boolean FLAG_USE_MAGNIFIER = true;
private static final int DELAY_BEFORE_HANDLE_FADES_OUT = 4000;
@@ -204,7 +207,7 @@ public class Editor {
private final MetricsLogger mMetricsLogger = new MetricsLogger();
// Cursor Controllers.
- private InsertionPointCursorController mInsertionPointCursorController;
+ InsertionPointCursorController mInsertionPointCursorController;
SelectionModifierCursorController mSelectionModifierCursorController;
// Action mode used when text is selected or when actions on an insertion cursor are triggered.
private ActionMode mTextActionMode;
@@ -1471,6 +1474,9 @@ public class Editor {
mTouchState.update(event, viewConfiguration);
updateFloatingToolbarVisibility(event);
+ if (hasInsertionController()) {
+ getInsertionController().onTouchEvent(event);
+ }
if (hasSelectionController()) {
getSelectionController().onTouchEvent(event);
}
@@ -5179,15 +5185,11 @@ public class Editor {
case MotionEvent.ACTION_UP:
if (!offsetHasBeenChanged()) {
- final float deltaX = mLastDownRawX - ev.getRawX();
- final float deltaY = mLastDownRawY - ev.getRawY();
- final float distanceSquared = deltaX * deltaX + deltaY * deltaY;
-
- final ViewConfiguration viewConfiguration = ViewConfiguration.get(
- mTextView.getContext());
- final int touchSlop = viewConfiguration.getScaledTouchSlop();
-
- if (distanceSquared < touchSlop * touchSlop) {
+ ViewConfiguration config = ViewConfiguration.get(mTextView.getContext());
+ boolean isWithinTouchSlop = EditorTouchState.isDistanceWithin(
+ mLastDownRawX, mLastDownRawY, ev.getRawX(), ev.getRawY(),
+ config.getScaledTouchSlop());
+ if (isWithinTouchSlop) {
// Tapping on the handle toggles the insertion action mode.
if (mTextActionMode != null) {
stopTextActionMode();
@@ -5237,6 +5239,10 @@ public class Editor {
} else {
offset = -1;
}
+ if (TextView.DEBUG_CURSOR) {
+ logCursor("InsertionHandleView: updatePosition", "x=%f, y=%f, offset=%d, line=%d",
+ x, y, offset, mPreviousLineTouched);
+ }
positionAtCursorOffset(offset, false, fromTouchScreen);
if (mTextActionMode != null) {
invalidateActionMode();
@@ -5716,8 +5722,82 @@ public class Editor {
}
}
- private class InsertionPointCursorController implements CursorController {
+ class InsertionPointCursorController implements CursorController {
private InsertionHandleView mHandle;
+ private boolean mIsDraggingCursor;
+
+ public void onTouchEvent(MotionEvent event) {
+ switch (event.getActionMasked()) {
+ case MotionEvent.ACTION_DOWN:
+ mIsDraggingCursor = false;
+ break;
+ case MotionEvent.ACTION_MOVE:
+ if (mIsDraggingCursor) {
+ performCursorDrag(event);
+ } else if (FLAG_ENABLE_CURSOR_DRAG
+ && mTextView.getLayout() != null
+ && mTextView.isFocused()
+ && mTouchState.isMovedEnoughForDrag()) {
+ startCursorDrag(event);
+ }
+ break;
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_CANCEL:
+ if (mIsDraggingCursor) {
+ endCursorDrag(event);
+ }
+ break;
+ }
+ }
+
+ private void positionCursorDuringDrag(MotionEvent event) {
+ int line = mTextView.getLineAtCoordinate(event.getY());
+ int offset = mTextView.getOffsetAtCoordinate(line, event.getX());
+ int oldSelectionStart = mTextView.getSelectionStart();
+ int oldSelectionEnd = mTextView.getSelectionEnd();
+ if (offset == oldSelectionStart && offset == oldSelectionEnd) {
+ return;
+ }
+ Selection.setSelection((Spannable) mTextView.getText(), offset);
+ updateCursorPosition();
+ if (mHapticTextHandleEnabled) {
+ mTextView.performHapticFeedback(HapticFeedbackConstants.TEXT_HANDLE_MOVE);
+ }
+ }
+
+ private void startCursorDrag(MotionEvent event) {
+ if (TextView.DEBUG_CURSOR) {
+ logCursor("InsertionPointCursorController", "start cursor drag");
+ }
+ mIsDraggingCursor = true;
+ // We don't want the parent scroll/long-press handlers to take over while dragging.
+ mTextView.getParent().requestDisallowInterceptTouchEvent(true);
+ mTextView.cancelLongPress();
+ // Update the cursor position.
+ positionCursorDuringDrag(event);
+ // Show the cursor handle and magnifier.
+ show();
+ getHandle().removeHiderCallback();
+ getHandle().updateMagnifier(event);
+ // TODO(b/146555651): Figure out if suspendBlink() should be called here.
+ }
+
+ private void performCursorDrag(MotionEvent event) {
+ positionCursorDuringDrag(event);
+ getHandle().updateMagnifier(event);
+ }
+
+ private void endCursorDrag(MotionEvent event) {
+ if (TextView.DEBUG_CURSOR) {
+ logCursor("InsertionPointCursorController", "end cursor drag");
+ }
+ mIsDraggingCursor = false;
+ // Hide the magnifier and set the handle to be hidden after a delay.
+ getHandle().dismissMagnifier();
+ getHandle().hideAfterDelay();
+ // We're no longer dragging, so let the parent receive events.
+ mTextView.getParent().requestDisallowInterceptTouchEvent(false);
+ }
public void show() {
getHandle().show();
@@ -5725,15 +5805,19 @@ public class Editor {
final long durationSinceCutOrCopy =
SystemClock.uptimeMillis() - TextView.sLastCutCopyOrTextChangedTime;
- // Cancel the single tap delayed runnable.
- if (mInsertionActionModeRunnable != null
- && (mTouchState.isMultiTap() || isCursorInsideEasyCorrectionSpan())) {
- mTextView.removeCallbacks(mInsertionActionModeRunnable);
+ if (mInsertionActionModeRunnable != null) {
+ if (mIsDraggingCursor
+ || mTouchState.isMultiTap()
+ || isCursorInsideEasyCorrectionSpan()) {
+ // Cancel the runnable for showing the floating toolbar.
+ mTextView.removeCallbacks(mInsertionActionModeRunnable);
+ }
}
- // Prepare and schedule the single tap runnable to run exactly after the double tap
- // timeout has passed.
- if (!mTouchState.isMultiTap()
+ // If the user recently performed a Cut or Copy action, we want to show the floating
+ // toolbar even for a single tap.
+ if (!mIsDraggingCursor
+ && !mTouchState.isMultiTap()
&& !isCursorInsideEasyCorrectionSpan()
&& (durationSinceCutOrCopy < RECENT_CUT_COPY_DURATION_MS)) {
if (mTextActionMode == null) {
@@ -5751,7 +5835,9 @@ public class Editor {
}
}
- getHandle().hideAfterDelay();
+ if (!mIsDraggingCursor) {
+ getHandle().hideAfterDelay();
+ }
if (mSelectionModifierCursorController != null) {
mSelectionModifierCursorController.hide();
@@ -5797,7 +5883,7 @@ public class Editor {
@Override
public boolean isCursorBeingModified() {
- return mHandle != null && mHandle.isDragging();
+ return mIsDraggingCursor || (mHandle != null && mHandle.isDragging());
}
@Override
@@ -5959,7 +6045,6 @@ public class Editor {
case MotionEvent.ACTION_MOVE:
final ViewConfiguration viewConfig = ViewConfiguration.get(
mTextView.getContext());
- final int touchSlop = viewConfig.getScaledTouchSlop();
if (mGestureStayedInTapRegion || mHaventMovedEnoughToStartDrag) {
final float deltaX = eventX - mTouchState.getLastDownX();
@@ -5973,6 +6058,7 @@ public class Editor {
}
if (mHaventMovedEnoughToStartDrag) {
// We don't start dragging until the user has moved enough.
+ int touchSlop = viewConfig.getScaledTouchSlop();
mHaventMovedEnoughToStartDrag =
distanceSquared <= touchSlop * touchSlop;
}
diff --git a/core/java/android/widget/EditorTouchState.java b/core/java/android/widget/EditorTouchState.java
index f880939bee35..3798d0095f2d 100644
--- a/core/java/android/widget/EditorTouchState.java
+++ b/core/java/android/widget/EditorTouchState.java
@@ -55,6 +55,8 @@ public class EditorTouchState {
private int mMultiTapStatus = MultiTapStatus.NONE;
private boolean mMultiTapInSameArea;
+ private boolean mMovedEnoughForDrag;
+
public float getLastDownX() {
return mLastDownX;
}
@@ -88,10 +90,14 @@ public class EditorTouchState {
return isMultiTap() && mMultiTapInSameArea;
}
+ public boolean isMovedEnoughForDrag() {
+ return mMovedEnoughForDrag;
+ }
+
/**
* Updates the state based on the new event.
*/
- public void update(MotionEvent event, ViewConfiguration viewConfiguration) {
+ public void update(MotionEvent event, ViewConfiguration config) {
final int action = event.getActionMasked();
if (action == MotionEvent.ACTION_DOWN) {
final boolean isMouse = event.isFromSource(InputDevice.SOURCE_MOUSE);
@@ -105,11 +111,8 @@ public class EditorTouchState {
} else {
mMultiTapStatus = MultiTapStatus.TRIPLE_CLICK;
}
- final float deltaX = event.getX() - mLastDownX;
- final float deltaY = event.getY() - mLastDownY;
- final int distanceSquared = (int) ((deltaX * deltaX) + (deltaY * deltaY));
- int doubleTapSlop = viewConfiguration.getScaledDoubleTapSlop();
- mMultiTapInSameArea = distanceSquared < doubleTapSlop * doubleTapSlop;
+ mMultiTapInSameArea = isDistanceWithin(mLastDownX, mLastDownY,
+ event.getX(), event.getY(), config.getScaledDoubleTapSlop());
if (TextView.DEBUG_CURSOR) {
String status = isDoubleTap() ? "double" : "triple";
String inSameArea = mMultiTapInSameArea ? "in same area" : "not in same area";
@@ -125,6 +128,7 @@ public class EditorTouchState {
}
mLastDownX = event.getX();
mLastDownY = event.getY();
+ mMovedEnoughForDrag = false;
} else if (action == MotionEvent.ACTION_UP) {
if (TextView.DEBUG_CURSOR) {
logCursor("EditorTouchState", "ACTION_UP");
@@ -132,6 +136,23 @@ public class EditorTouchState {
mLastUpX = event.getX();
mLastUpY = event.getY();
mLastUpMillis = event.getEventTime();
+ mMovedEnoughForDrag = false;
+ } else if (action == MotionEvent.ACTION_MOVE) {
+ mMovedEnoughForDrag = !isDistanceWithin(mLastDownX, mLastDownY,
+ event.getX(), event.getY(), config.getScaledTouchSlop());
}
}
+
+ /**
+ * Returns true if the distance between the given coordinates is <= to the specified max.
+ * This is useful to be able to determine e.g. when the user's touch has moved enough in
+ * order to be considered a drag (no longer within touch slop).
+ */
+ public static boolean isDistanceWithin(float x1, float y1, float x2, float y2,
+ int maxDistance) {
+ float deltaX = x2 - x1;
+ float deltaY = y2 - y1;
+ float distanceSquared = (deltaX * deltaX) + (deltaY * deltaY);
+ return distanceSquared <= maxDistance * maxDistance;
+ }
}
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index ac2336c4a10f..fbd29ba2f592 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -309,6 +309,9 @@ public class Switch extends CompoundButton {
// Refresh display with current params
refreshDrawableState();
+ // Default state is derived from on/off-text, so state has to be updated when on/off-text
+ // are updated.
+ setDefaultStateDescritption();
setChecked(isChecked());
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index ee169f25b778..43d98955f299 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -10870,6 +10870,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (mEditor != null) {
mEditor.onTouchEvent(event);
+ if (mEditor.mInsertionPointCursorController != null
+ && mEditor.mInsertionPointCursorController.isCursorBeingModified()) {
+ return true;
+ }
if (mEditor.mSelectionModifierCursorController != null
&& mEditor.mSelectionModifierCursorController.isDragAcceleratorActive()) {
return true;
diff --git a/core/java/android/widget/ToggleButton.java b/core/java/android/widget/ToggleButton.java
index d47405b3b11e..59e0c16cde37 100644
--- a/core/java/android/widget/ToggleButton.java
+++ b/core/java/android/widget/ToggleButton.java
@@ -58,6 +58,9 @@ public class ToggleButton extends CompoundButton {
mTextOff = a.getText(com.android.internal.R.styleable.ToggleButton_textOff);
mDisabledAlpha = a.getFloat(com.android.internal.R.styleable.ToggleButton_disabledAlpha, 0.5f);
syncTextState();
+ // Default state is derived from on/off-text, so state has to be updated when on/off-text
+ // are updated.
+ setDefaultStateDescritption();
a.recycle();
}
diff --git a/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java b/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java
index c64b7051276a..08022e983892 100644
--- a/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java
+++ b/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
package com.android.internal.app;
+
import android.annotation.IntDef;
import android.annotation.Nullable;
import android.content.Context;
@@ -23,10 +24,10 @@ import android.view.ViewGroup;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.widget.PagerAdapter;
-
-import com.android.internal.util.Preconditions;
import com.android.internal.widget.ViewPager;
+import java.util.Objects;
+
/**
* Skeletal {@link PagerAdapter} implementation of a work or personal profile page for
* intent resolution (including share sheet).
@@ -42,7 +43,7 @@ public abstract class AbstractMultiProfilePagerAdapter extends PagerAdapter {
private int mCurrentPage;
AbstractMultiProfilePagerAdapter(Context context, int currentPage) {
- mContext = Preconditions.checkNotNull(context);
+ mContext = Objects.requireNonNull(context);
mCurrentPage = currentPage;
}
diff --git a/core/java/com/android/internal/app/AccessibilityButtonChooserActivity.java b/core/java/com/android/internal/app/AccessibilityButtonChooserActivity.java
index 7af45fc53ddf..33aa665e95ea 100644
--- a/core/java/com/android/internal/app/AccessibilityButtonChooserActivity.java
+++ b/core/java/com/android/internal/app/AccessibilityButtonChooserActivity.java
@@ -15,28 +15,26 @@
*/
package com.android.internal.app;
-import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
-
import android.accessibilityservice.AccessibilityServiceInfo;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Activity;
+import android.app.AlertDialog;
import android.content.Context;
+import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.provider.Settings;
-import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.view.Window;
import android.view.accessibility.AccessibilityManager;
import android.widget.BaseAdapter;
-import android.widget.GridView;
import android.widget.ImageView;
import android.widget.TextView;
import com.android.internal.R;
-import com.android.internal.widget.ResolverDrawerLayout;
import java.util.ArrayList;
import java.util.Collections;
@@ -54,66 +52,43 @@ public class AccessibilityButtonChooserActivity extends Activity {
private List<AccessibilityButtonTarget> mTargets = null;
+ private AlertDialog mAlertDialog;
+
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.accessibility_button_chooser);
-
- final ResolverDrawerLayout rdl = findViewById(R.id.contentPanel);
- if (rdl != null) {
- rdl.setOnDismissedListener(this::finish);
- }
- String component = Settings.Secure.getString(getContentResolver(),
- Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT);
-
- if (isGestureNavigateEnabled()) {
- TextView promptPrologue = findViewById(R.id.accessibility_button_prompt_prologue);
- promptPrologue.setText(isTouchExploreOn()
- ? R.string.accessibility_gesture_3finger_prompt_text
- : R.string.accessibility_gesture_prompt_text);
- }
-
- if (TextUtils.isEmpty(component)) {
- TextView prompt = findViewById(R.id.accessibility_button_prompt);
- if (isGestureNavigateEnabled()) {
- prompt.setText(isTouchExploreOn()
- ? R.string.accessibility_gesture_3finger_instructional_text
- : R.string.accessibility_gesture_instructional_text);
- }
- prompt.setVisibility(View.VISIBLE);
+ final TypedArray theme = getTheme().obtainStyledAttributes(android.R.styleable.Theme);
+ if (!theme.getBoolean(android.R.styleable.Theme_windowNoTitle, /* defValue= */false)) {
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
}
+ // TODO(b/146815874): Will replace it with white list services
mMagnificationTarget = new AccessibilityButtonTarget(this, MAGNIFICATION_COMPONENT_ID,
R.string.accessibility_magnification_chooser_text,
R.drawable.ic_accessibility_magnification);
+ // TODO(b/146815544): Will use shortcut type or button type to get the corresponding
+ // services
mTargets = getServiceAccessibilityButtonTargets(this);
if (Settings.Secure.getInt(getContentResolver(),
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED, 0) == 1) {
mTargets.add(mMagnificationTarget);
}
- if (mTargets.size() < 2) {
- // Why are we here?
- finish();
- }
-
- GridView gridview = findViewById(R.id.accessibility_button_chooser_grid);
- gridview.setAdapter(new TargetAdapter());
- gridview.setOnItemClickListener((parent, view, position, id) -> {
- onTargetSelected(mTargets.get(position));
- });
- }
-
- private boolean isGestureNavigateEnabled() {
- return NAV_BAR_MODE_GESTURAL == getResources().getInteger(
- com.android.internal.R.integer.config_navBarInteractionMode);
+ // TODO(b/146815548): Will add title to separate which one type
+ mAlertDialog = new AlertDialog.Builder(this)
+ .setAdapter(new TargetAdapter(),
+ (dialog, position) -> onTargetSelected(mTargets.get(position)))
+ .setOnDismissListener(dialog -> finish())
+ .create();
+ mAlertDialog.show();
}
- private boolean isTouchExploreOn() {
- return ((AccessibilityManager) getSystemService(Context.ACCESSIBILITY_SERVICE))
- .isTouchExplorationEnabled();
+ @Override
+ protected void onDestroy() {
+ mAlertDialog.dismiss();
+ super.onDestroy();
}
private static List<AccessibilityButtonTarget> getServiceAccessibilityButtonTargets(
@@ -167,6 +142,8 @@ public class AccessibilityButtonChooserActivity extends Activity {
TextView labelView = root.findViewById(R.id.accessibility_button_target_label);
iconView.setImageDrawable(target.getDrawable());
labelView.setText(target.getLabel());
+
+ // TODO(b/146815874): Need to get every service status to update UI
return root;
}
}
@@ -175,7 +152,7 @@ public class AccessibilityButtonChooserActivity extends Activity {
public String mId;
public CharSequence mLabel;
public Drawable mDrawable;
-
+ // TODO(b/146815874): Will add fragment type and related functions
public AccessibilityButtonTarget(@NonNull Context context,
@NonNull AccessibilityServiceInfo serviceInfo) {
this.mId = serviceInfo.getComponentName().flattenToString();
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index f361784e81d7..06e96d517e19 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -98,10 +98,10 @@ import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
-import android.view.WindowInsets;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.widget.ImageView;
+import android.widget.Space;
import android.widget.TextView;
import android.widget.Toast;
@@ -120,7 +120,6 @@ import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.internal.content.PackageMonitor;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.internal.util.ImageUtils;
import com.android.internal.widget.GridLayoutManager;
import com.android.internal.widget.RecyclerView;
import com.android.internal.widget.ResolverDrawerLayout;
@@ -345,7 +344,9 @@ public class ChooserActivity extends ResolverActivity implements
mHandler.sendEmptyMessageDelayed(IMAGE_LOAD_TIMEOUT, mImageLoadTimeoutMillis);
AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> {
- final Bitmap bmp = loadThumbnail(uri, new Size(200, 200));
+ int size = getResources().getDimensionPixelSize(
+ R.dimen.chooser_preview_image_max_dimen);
+ final Bitmap bmp = loadThumbnail(uri, new Size(size, size));
final Message msg = Message.obtain();
msg.what = IMAGE_LOAD_INTO_VIEW;
msg.obj = new LoadUriTask(imageResourceId, uri, extraImages, bmp);
@@ -859,14 +860,21 @@ public class ChooserActivity extends ResolverActivity implements
return new PackageMonitor() {
@Override
public void onSomePackagesChanged() {
- // TODO(arangelov): Dispatch this to all adapters when we have the helper methods
- // in a follow-up CL
- mChooserMultiProfilePagerAdapter.getActiveListAdapter().handlePackagesChanged();
- updateProfileViewButton();
+ handlePackagesChanged();
}
};
}
+ /**
+ * Update UI to reflect changes in data.
+ */
+ public void handlePackagesChanged() {
+ // TODO(arangelov): Dispatch this to all adapters when we have the helper methods
+ // in a follow-up CL
+ mChooserMultiProfilePagerAdapter.getActiveListAdapter().handlePackagesChanged();
+ updateProfileViewButton();
+ }
+
private void onCopyButtonClicked(View v) {
Intent targetIntent = getTargetIntent();
if (targetIntent == null) {
@@ -1370,9 +1378,8 @@ public class ChooserActivity extends ResolverActivity implements
for (TargetInfo innerInfo : mti.getTargets()) {
labels.add(innerInfo.getResolveInfo().loadLabel(getPackageManager()));
}
- f = new ResolverTargetActionsDialogFragment(
- mti.getResolveInfo().loadLabel(getPackageManager()), name, mti.getTargets(),
- labels);
+ f = new ResolverTargetActionsDialogFragment(mti.getDisplayLabel(), name,
+ mti.getTargets(), labels);
} else {
f = new ResolverTargetActionsDialogFragment(
ti.getResolveInfo().loadLabel(getPackageManager()), name, pinned);
@@ -1432,20 +1439,22 @@ public class ChooserActivity extends ResolverActivity implements
final long selectionCost = System.currentTimeMillis() - mChooserShownTime;
- // Stacked apps get a disambiguation first
if (targetInfo instanceof MultiDisplayResolveInfo) {
MultiDisplayResolveInfo mti = (MultiDisplayResolveInfo) targetInfo;
- CharSequence[] labels = new CharSequence[mti.getTargets().size()];
- int i = 0;
- for (TargetInfo ti : mti.getTargets()) {
- labels[i++] = ti.getResolveInfo().loadLabel(getPackageManager());
- }
- ChooserStackedAppDialogFragment f = new ChooserStackedAppDialogFragment(
- targetInfo.getDisplayLabel(),
- ((MultiDisplayResolveInfo) targetInfo).getTargets(), labels);
+ if (!mti.hasSelected()) {
+ // Stacked apps get a disambiguation first
+ CharSequence[] labels = new CharSequence[mti.getTargets().size()];
+ int i = 0;
+ for (TargetInfo ti : mti.getTargets()) {
+ labels[i++] = ti.getResolveInfo().loadLabel(getPackageManager());
+ }
+ ChooserStackedAppDialogFragment f = new ChooserStackedAppDialogFragment(
+ targetInfo.getDisplayLabel(),
+ ((MultiDisplayResolveInfo) targetInfo), labels, which);
- f.show(getFragmentManager(), TARGET_DETAILS_FRAGMENT_TAG);
- return;
+ f.show(getFragmentManager(), TARGET_DETAILS_FRAGMENT_TAG);
+ return;
+ }
}
super.startSelected(which, always, filtered);
@@ -1537,6 +1546,21 @@ public class ChooserActivity extends ResolverActivity implements
return -1;
}
+ @Override
+ protected boolean shouldAddFooterView() {
+ // To accommodate for window insets
+ return true;
+ }
+
+ @Override
+ protected void applyFooterView(int height) {
+ int count = mChooserMultiProfilePagerAdapter.getItemCount();
+
+ for (int i = 0; i < count; i++) {
+ mChooserMultiProfilePagerAdapter.getAdapterForIndex(i).setFooterHeight(height);
+ }
+ }
+
void queryTargetServices(ChooserListAdapter adapter) {
mQueriedTargetServicesTimeMs = System.currentTimeMillis();
@@ -2121,7 +2145,7 @@ public class ChooserActivity extends ResolverActivity implements
}
try {
- return ImageUtils.loadThumbnail(getContentResolver(), uri, size);
+ return getContentResolver().loadThumbnail(uri, size, null);
} catch (IOException | NullPointerException | SecurityException ex) {
logContentPreviewWarning(uri);
}
@@ -2404,12 +2428,17 @@ public class ChooserActivity extends ResolverActivity implements
}
/**
- * Intentionally override the {@link ResolverActivity} implementation as we only need that
- * implementation for the intent resolver case.
+ * Add a footer to the list, to support scrolling behavior below the navbar.
*/
- @Override
- protected WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
- return insets.consumeSystemWindowInsets();
+ final class FooterViewHolder extends RecyclerView.ViewHolder {
+ FooterViewHolder(View itemView) {
+ super(itemView);
+ }
+
+ public void setHeight(int height) {
+ itemView.setLayoutParams(
+ new RecyclerView.LayoutParams(LayoutParams.MATCH_PARENT, height));
+ }
}
/**
@@ -2442,11 +2471,14 @@ public class ChooserActivity extends ResolverActivity implements
private boolean mLayoutRequested = false;
+ private FooterViewHolder mFooterViewHolder;
+
private static final int VIEW_TYPE_DIRECT_SHARE = 0;
private static final int VIEW_TYPE_NORMAL = 1;
private static final int VIEW_TYPE_PROFILE = 2;
private static final int VIEW_TYPE_AZ_LABEL = 3;
private static final int VIEW_TYPE_CALLER_AND_RANK = 4;
+ private static final int VIEW_TYPE_FOOTER = 5;
private static final int MAX_TARGETS_PER_ROW_PORTRAIT = 4;
private static final int MAX_TARGETS_PER_ROW_LANDSCAPE = 8;
@@ -2458,6 +2490,9 @@ public class ChooserActivity extends ResolverActivity implements
mChooserListAdapter = wrappedAdapter;
mLayoutInflater = LayoutInflater.from(ChooserActivity.this);
+ mFooterViewHolder = new FooterViewHolder(
+ new Space(ChooserActivity.this.getApplicationContext()));
+
mShowAzLabelIfPoss = getNumSheetExpansions() < NUM_EXPANSIONS_TO_HIDE_AZ_LABEL;
wrappedAdapter.registerDataSetObserver(new DataSetObserver() {
@@ -2475,6 +2510,10 @@ public class ChooserActivity extends ResolverActivity implements
});
}
+ public void setFooterHeight(int height) {
+ mFooterViewHolder.setHeight(height);
+ }
+
/**
* Calculate the chooser target width to maximize space per item
*
@@ -2525,6 +2564,10 @@ public class ChooserActivity extends ResolverActivity implements
return mChooserListAdapter.getOtherProfile() == null ? 0 : 1;
}
+ public int getFooterRowCount() {
+ return 1;
+ }
+
public int getCallerAndRankedTargetRowCount() {
return (int) Math.ceil(
((float) mChooserListAdapter.getCallerTargetCount()
@@ -2554,6 +2597,7 @@ public class ChooserActivity extends ResolverActivity implements
+ getCallerAndRankedTargetRowCount()
+ getAzLabelRowCount()
+ mChooserListAdapter.getAlphaTargetCount()
+ + getFooterRowCount()
);
}
@@ -2569,6 +2613,8 @@ public class ChooserActivity extends ResolverActivity implements
case VIEW_TYPE_DIRECT_SHARE:
case VIEW_TYPE_CALLER_AND_RANK:
return createItemGroupViewHolder(viewType, parent);
+ case VIEW_TYPE_FOOTER:
+ return mFooterViewHolder;
default:
// Since we catch all possible viewTypes above, no chance this is being called.
return null;
@@ -2606,6 +2652,8 @@ public class ChooserActivity extends ResolverActivity implements
countSum += (count = getAzLabelRowCount());
if (count > 0 && position < countSum) return VIEW_TYPE_AZ_LABEL;
+ if (position == getItemCount() - 1) return VIEW_TYPE_FOOTER;
+
return VIEW_TYPE_NORMAL;
}
diff --git a/core/java/com/android/internal/app/ChooserStackedAppDialogFragment.java b/core/java/com/android/internal/app/ChooserStackedAppDialogFragment.java
index ff6582d10535..f4c69a51ece1 100644
--- a/core/java/com/android/internal/app/ChooserStackedAppDialogFragment.java
+++ b/core/java/com/android/internal/app/ChooserStackedAppDialogFragment.java
@@ -24,10 +24,7 @@ import android.content.DialogInterface;
import android.content.res.Configuration;
import android.os.Bundle;
-import com.android.internal.app.chooser.DisplayResolveInfo;
-
-import java.util.ArrayList;
-import java.util.List;
+import com.android.internal.app.chooser.MultiDisplayResolveInfo;
/**
* Shows individual actions for a "stacked" app target - such as an app with multiple posting
@@ -38,24 +35,20 @@ public class ChooserStackedAppDialogFragment extends DialogFragment
private static final String TITLE_KEY = "title";
private static final String PINNED_KEY = "pinned";
- private List<DisplayResolveInfo> mTargetInfos = new ArrayList<>();
+ private MultiDisplayResolveInfo mTargetInfos;
private CharSequence[] mLabels;
+ private int mParentWhich;
public ChooserStackedAppDialogFragment() {
}
- public ChooserStackedAppDialogFragment(CharSequence title) {
- Bundle args = new Bundle();
- args.putCharSequence(TITLE_KEY, title);
- setArguments(args);
- }
-
public ChooserStackedAppDialogFragment(CharSequence title,
- List<DisplayResolveInfo> targets, CharSequence[] labels) {
+ MultiDisplayResolveInfo targets, CharSequence[] labels, int parentWhich) {
Bundle args = new Bundle();
args.putCharSequence(TITLE_KEY, title);
mTargetInfos = targets;
mLabels = labels;
+ mParentWhich = parentWhich;
setArguments(args);
}
@@ -72,7 +65,8 @@ public class ChooserStackedAppDialogFragment extends DialogFragment
@Override
public void onClick(DialogInterface dialog, int which) {
final Bundle args = getArguments();
- mTargetInfos.get(which).start(getActivity(), null);
+ mTargetInfos.setSelected(which);
+ ((ChooserActivity) getActivity()).startSelected(mParentWhich, false, true);
dismiss();
}
diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl
index 99bf93e98cd1..46025aa2d6f0 100644
--- a/core/java/com/android/internal/app/IAppOpsService.aidl
+++ b/core/java/com/android/internal/app/IAppOpsService.aidl
@@ -32,14 +32,13 @@ interface IAppOpsService {
// and not be reordered
int checkOperation(int code, int uid, String packageName);
int noteOperation(int code, int uid, String packageName, @nullable String featureId);
- int startOperation(IBinder token, int code, int uid, String packageName,
+ int startOperation(IBinder clientId, int code, int uid, String packageName,
@nullable String featureId, boolean startIfModeDefault);
@UnsupportedAppUsage
- void finishOperation(IBinder token, int code, int uid, String packageName,
+ void finishOperation(IBinder clientId, int code, int uid, String packageName,
@nullable String featureId);
void startWatchingMode(int op, String packageName, IAppOpsCallback callback);
void stopWatchingMode(IAppOpsCallback callback);
- IBinder getToken(IBinder clientToken);
int permissionToOpCode(String permission);
int checkAudioOperation(int code, int usage, int uid, String packageName);
void noteAsyncOp(@nullable String callingPackageName, int uid, @nullable String packageName,
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 8dc3a072b47e..a4cd4f12cfe1 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -472,34 +472,52 @@ public class ResolverActivity extends Activity implements
finish();
}
+ /**
+ * Numerous layouts are supported, each with optional ViewGroups.
+ * Make sure the inset gets added to the correct View, using
+ * a footer for Lists so it can properly scroll under the navbar.
+ */
+ protected boolean shouldAddFooterView() {
+ if (useLayoutWithDefault()) return true;
+
+ View buttonBar = findViewById(R.id.button_bar);
+ if (buttonBar == null || buttonBar.getVisibility() == View.GONE) return true;
+
+ return false;
+ }
+
+ protected void applyFooterView(int height) {
+ if (mFooterSpacer == null) {
+ mFooterSpacer = new Space(getApplicationContext());
+ } else {
+ ((ResolverMultiProfilePagerAdapter) mMultiProfilePagerAdapter)
+ .getCurrentAdapterView().removeFooterView(mFooterSpacer);
+ }
+ mFooterSpacer.setLayoutParams(new AbsListView.LayoutParams(LayoutParams.MATCH_PARENT,
+ mSystemWindowInsets.bottom));
+ ((ResolverMultiProfilePagerAdapter) mMultiProfilePagerAdapter)
+ .getCurrentAdapterView().addFooterView(mFooterSpacer);
+ }
+
protected WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
mSystemWindowInsets = insets.getSystemWindowInsets();
mResolverDrawerLayout.setPadding(mSystemWindowInsets.left, mSystemWindowInsets.top,
mSystemWindowInsets.right, 0);
+ resetButtonBar();
+
// Need extra padding so the list can fully scroll up
- if (useLayoutWithDefault()) {
- if (mFooterSpacer == null) {
- mFooterSpacer = new Space(getApplicationContext());
- } else {
- ((ResolverMultiProfilePagerAdapter) mMultiProfilePagerAdapter)
- .getCurrentAdapterView().removeFooterView(mFooterSpacer);
- }
- mFooterSpacer.setLayoutParams(new AbsListView.LayoutParams(LayoutParams.MATCH_PARENT,
- mSystemWindowInsets.bottom));
- ((ResolverMultiProfilePagerAdapter) mMultiProfilePagerAdapter)
- .getCurrentAdapterView().addFooterView(mFooterSpacer);
- } else {
- View emptyView = findViewById(R.id.empty);
- if (emptyView != null) {
- emptyView.setPadding(0, 0, 0, mSystemWindowInsets.bottom
- + getResources().getDimensionPixelSize(
- R.dimen.chooser_edge_margin_normal) * 2);
- }
+ if (shouldAddFooterView()) {
+ applyFooterView(mSystemWindowInsets.bottom);
}
- resetButtonBar();
+ View emptyView = findViewById(R.id.empty);
+ if (emptyView != null) {
+ emptyView.setPadding(0, 0, 0, mSystemWindowInsets.bottom
+ + getResources().getDimensionPixelSize(
+ R.dimen.chooser_edge_margin_normal) * 2);
+ }
return insets.consumeSystemWindowInsets();
}
diff --git a/core/java/com/android/internal/app/ResolverTargetActionsDialogFragment.java b/core/java/com/android/internal/app/ResolverTargetActionsDialogFragment.java
index bdbe2109cf05..21efc78bddf8 100644
--- a/core/java/com/android/internal/app/ResolverTargetActionsDialogFragment.java
+++ b/core/java/com/android/internal/app/ResolverTargetActionsDialogFragment.java
@@ -116,7 +116,7 @@ public class ResolverTargetActionsDialogFragment extends DialogFragment
pinComponent(mTargetInfos.get(which).getResolvedComponentName());
}
// Force the chooser to requery and resort things
- getActivity().recreate();
+ ((ChooserActivity) getActivity()).handlePackagesChanged();
} else {
// Last item in dialog is App Info
Intent in = new Intent().setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
diff --git a/core/java/com/android/internal/app/SuspendedAppActivity.java b/core/java/com/android/internal/app/SuspendedAppActivity.java
index 33b2113b0674..c610ac4503c9 100644
--- a/core/java/com/android/internal/app/SuspendedAppActivity.java
+++ b/core/java/com/android/internal/app/SuspendedAppActivity.java
@@ -45,12 +45,14 @@ public class SuspendedAppActivity extends AlertActivity
public static final String EXTRA_SUSPENDING_PACKAGE =
PACKAGE_NAME + ".extra.SUSPENDING_PACKAGE";
public static final String EXTRA_DIALOG_INFO = PACKAGE_NAME + ".extra.DIALOG_INFO";
+ public static final String EXTRA_ACTIVITY_OPTIONS = PACKAGE_NAME + ".extra.ACTIVITY_OPTIONS";
private Intent mMoreDetailsIntent;
private int mUserId;
private PackageManager mPm;
private Resources mSuspendingAppResources;
private SuspendDialogInfo mSuppliedDialogInfo;
+ private Bundle mOptions;
private CharSequence getAppLabel(String packageName) {
try {
@@ -143,6 +145,7 @@ public class SuspendedAppActivity extends AlertActivity
getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
final Intent intent = getIntent();
+ mOptions = intent.getBundleExtra(EXTRA_ACTIVITY_OPTIONS);
mUserId = intent.getIntExtra(Intent.EXTRA_USER_ID, -1);
if (mUserId < 0) {
Slog.wtf(TAG, "Invalid user: " + mUserId);
@@ -178,20 +181,22 @@ public class SuspendedAppActivity extends AlertActivity
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case AlertDialog.BUTTON_NEUTRAL:
- startActivityAsUser(mMoreDetailsIntent, UserHandle.of(mUserId));
- Slog.i(TAG, "Started more details activity");
+ startActivityAsUser(mMoreDetailsIntent, mOptions, UserHandle.of(mUserId));
+ Slog.i(TAG, "Started activity: " + mMoreDetailsIntent.getAction()
+ + " in user " + mUserId);
break;
}
finish();
}
public static Intent createSuspendedAppInterceptIntent(String suspendedPackage,
- String suspendingPackage, SuspendDialogInfo dialogInfo, int userId) {
+ String suspendingPackage, SuspendDialogInfo dialogInfo, Bundle options, int userId) {
return new Intent()
.setClassName("android", SuspendedAppActivity.class.getName())
.putExtra(EXTRA_SUSPENDED_PACKAGE, suspendedPackage)
.putExtra(EXTRA_DIALOG_INFO, dialogInfo)
.putExtra(EXTRA_SUSPENDING_PACKAGE, suspendingPackage)
+ .putExtra(EXTRA_ACTIVITY_OPTIONS, options)
.putExtra(Intent.EXTRA_USER_ID, userId)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
diff --git a/core/java/com/android/internal/app/chooser/MultiDisplayResolveInfo.java b/core/java/com/android/internal/app/chooser/MultiDisplayResolveInfo.java
index 4c52411d6376..e58258352106 100644
--- a/core/java/com/android/internal/app/chooser/MultiDisplayResolveInfo.java
+++ b/core/java/com/android/internal/app/chooser/MultiDisplayResolveInfo.java
@@ -16,6 +16,12 @@
package com.android.internal.app.chooser;
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.UserHandle;
+
+import com.android.internal.app.ResolverActivity;
+
import java.util.ArrayList;
import java.util.List;
@@ -25,9 +31,10 @@ import java.util.List;
public class MultiDisplayResolveInfo extends DisplayResolveInfo {
List<DisplayResolveInfo> mTargetInfos = new ArrayList<>();
- String mPackageName;
// We'll use this DRI for basic presentation info - eg icon, name.
final DisplayResolveInfo mBaseInfo;
+ // Index of selected target
+ private int mSelected = -1;
/**
* @param firstInfo A representative DRI to use for the main icon, title, etc for this Info.
@@ -38,6 +45,12 @@ public class MultiDisplayResolveInfo extends DisplayResolveInfo {
mTargetInfos.add(firstInfo);
}
+ @Override
+ public CharSequence getExtendedInfo() {
+ // Never show subtitle for stacked apps
+ return null;
+ }
+
/**
* Add another DisplayResolveInfo to the list included for this target.
*/
@@ -52,4 +65,30 @@ public class MultiDisplayResolveInfo extends DisplayResolveInfo {
return mTargetInfos;
}
+ public void setSelected(int selected) {
+ mSelected = selected;
+ }
+
+ /**
+ * Whether or not the user has selected a specific target for this MultiInfo.
+ */
+ public boolean hasSelected() {
+ return mSelected >= 0;
+ }
+
+ @Override
+ public boolean start(Activity activity, Bundle options) {
+ return mTargetInfos.get(mSelected).start(activity, options);
+ }
+
+ @Override
+ public boolean startAsCaller(ResolverActivity activity, Bundle options, int userId) {
+ return mTargetInfos.get(mSelected).startAsCaller(activity, options, userId);
+ }
+
+ @Override
+ public boolean startAsUser(Activity activity, Bundle options, UserHandle user) {
+ return mTargetInfos.get(mSelected).startAsUser(activity, options, user);
+ }
+
}
diff --git a/core/java/com/android/internal/content/FileSystemProvider.java b/core/java/com/android/internal/content/FileSystemProvider.java
index dec9ae701fb2..221cd6d8a5c3 100644
--- a/core/java/com/android/internal/content/FileSystemProvider.java
+++ b/core/java/com/android/internal/content/FileSystemProvider.java
@@ -66,6 +66,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.regex.Pattern;
/**
* A helper class for {@link android.provider.DocumentsProvider} to perform file operations on local
@@ -388,7 +389,9 @@ public abstract class FileSystemProvider extends DocumentsProvider {
resolveProjection(projection), parentDocumentId, parent);
if (parent.isDirectory()) {
for (File file : FileUtils.listFilesOrEmpty(parent)) {
- includeFile(result, null, file);
+ if (!shouldHide(file)) {
+ includeFile(result, null, file);
+ }
}
} else {
Log.w(TAG, "parentDocumentId '" + parentDocumentId + "' is not Directory");
@@ -422,6 +425,8 @@ public abstract class FileSystemProvider extends DocumentsProvider {
pending.add(folder);
while (!pending.isEmpty() && result.getCount() < 24) {
final File file = pending.removeFirst();
+ if (shouldHide(file)) continue;
+
if (file.isDirectory()) {
for (File child : file.listFiles()) {
pending.add(child);
@@ -540,6 +545,7 @@ public abstract class FileSystemProvider extends DocumentsProvider {
} else {
file = getFileForDocId(docId);
}
+
final String mimeType = getDocumentType(docId, file);
row.add(Document.COLUMN_DOCUMENT_ID, docId);
row.add(Document.COLUMN_MIME_TYPE, mimeType);
@@ -598,6 +604,17 @@ public abstract class FileSystemProvider extends DocumentsProvider {
return row;
}
+ private static final Pattern PATTERN_HIDDEN_PATH = Pattern.compile(
+ "(?i)^/storage/[^/]+/(?:[0-9]+/)?Android/(?:data|obb|sandbox)$");
+
+ /**
+ * In a scoped storage world, access to "Android/data" style directories are
+ * hidden for privacy reasons.
+ */
+ protected boolean shouldHide(@NonNull File file) {
+ return (PATTERN_HIDDEN_PATH.matcher(file.getAbsolutePath()).matches());
+ }
+
protected boolean shouldBlockFromTree(@NonNull String docId) {
return false;
}
diff --git a/core/java/com/android/internal/content/PackageMonitor.java b/core/java/com/android/internal/content/PackageMonitor.java
index 6e9c4c36d40b..6b76a0f4127d 100644
--- a/core/java/com/android/internal/content/PackageMonitor.java
+++ b/core/java/com/android/internal/content/PackageMonitor.java
@@ -28,9 +28,9 @@ import android.os.UserHandle;
import android.util.Slog;
import com.android.internal.os.BackgroundThread;
-import com.android.internal.util.Preconditions;
import java.util.HashSet;
+import java.util.Objects;
/**
* Helper class for monitoring the state of packages: adding, removing,
@@ -93,7 +93,7 @@ public abstract class PackageMonitor extends android.content.BroadcastReceiver {
throw new IllegalStateException("Already registered");
}
mRegisteredContext = context;
- mRegisteredHandler = Preconditions.checkNotNull(handler);
+ mRegisteredHandler = Objects.requireNonNull(handler);
if (user != null) {
context.registerReceiverAsUser(this, user, sPackageFilt, null, mRegisteredHandler);
context.registerReceiverAsUser(this, user, sNonDataFilt, null, mRegisteredHandler);
diff --git a/core/java/com/android/internal/infra/AndroidFuture.aidl b/core/java/com/android/internal/infra/AndroidFuture.aidl
index b19aab8ab0d5..5f623b183168 100644
--- a/core/java/com/android/internal/infra/AndroidFuture.aidl
+++ b/core/java/com/android/internal/infra/AndroidFuture.aidl
@@ -17,4 +17,4 @@
package com.android.internal.infra;
/** @hide */
-parcelable AndroidFuture;
+parcelable AndroidFuture<T>;
diff --git a/core/java/com/android/internal/infra/PerUser.java b/core/java/com/android/internal/infra/PerUser.java
new file mode 100644
index 000000000000..560ca8cff8df
--- /dev/null
+++ b/core/java/com/android/internal/infra/PerUser.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.infra;
+
+import android.annotation.NonNull;
+import android.util.SparseArray;
+
+import com.android.internal.util.Preconditions;
+
+/**
+ * A {@link SparseArray} customized for a common use-case of storing state per-user.
+ *
+ * Unlike a normal {@link SparseArray} this will always create a value on {@link #get} if one is
+ * not present instead of returning null.
+ *
+ * @param <T> user state type
+ */
+public abstract class PerUser<T> extends SparseArray<T> {
+
+ /**
+ * Initialize state for the given user
+ */
+ protected abstract @NonNull T create(int userId);
+
+ /**
+ * Same as {@link #get(int)}, renamed for readability.
+ *
+ * This will never return null, deferring to {@link #create} instead
+ * when called for the first time.
+ */
+ public @NonNull T forUser(int userId) {
+ return get(userId);
+ }
+
+ @Override
+ public @NonNull T get(int userId) {
+ T userState = super.get(userId);
+ if (userState != null) {
+ return userState;
+ } else {
+ userState = Preconditions.checkNotNull(create(userId));
+ put(userId, userState);
+ return userState;
+ }
+ }
+}
diff --git a/core/java/com/android/internal/infra/ServiceConnector.java b/core/java/com/android/internal/infra/ServiceConnector.java
index 98d679eb776b..857377afd3e8 100644
--- a/core/java/com/android/internal/infra/ServiceConnector.java
+++ b/core/java/com/android/internal/infra/ServiceConnector.java
@@ -32,7 +32,6 @@ import android.text.TextUtils;
import android.util.DebugUtils;
import android.util.Log;
-import com.android.internal.util.Preconditions;
import com.android.internal.util.function.pooled.PooledLambda;
import java.io.PrintWriter;
@@ -40,6 +39,7 @@ import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.Objects;
import java.util.Queue;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
@@ -352,7 +352,7 @@ public interface ServiceConnector<I extends IInterface> {
@Override
public <R> CompletionAwareJob<I, R> postForResult(@NonNull Job<I, R> job) {
CompletionAwareJob<I, R> task = new CompletionAwareJob<>();
- task.mDelegate = Preconditions.checkNotNull(job);
+ task.mDelegate = Objects.requireNonNull(job);
enqueue(task);
return task;
}
@@ -360,7 +360,7 @@ public interface ServiceConnector<I extends IInterface> {
@Override
public <R> AndroidFuture<R> postAsync(@NonNull Job<I, CompletableFuture<R>> job) {
CompletionAwareJob<I, R> task = new CompletionAwareJob<>();
- task.mDelegate = Preconditions.checkNotNull((Job) job);
+ task.mDelegate = Objects.requireNonNull((Job) job);
task.mAsync = true;
enqueue(task);
return task;
diff --git a/core/java/com/android/internal/infra/WhitelistHelper.java b/core/java/com/android/internal/infra/WhitelistHelper.java
index 9d653bad4d00..b1d85f78984c 100644
--- a/core/java/com/android/internal/infra/WhitelistHelper.java
+++ b/core/java/com/android/internal/infra/WhitelistHelper.java
@@ -23,10 +23,9 @@ import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
-import com.android.internal.util.Preconditions;
-
import java.io.PrintWriter;
import java.util.List;
+import java.util.Objects;
/**
* Helper class for keeping track of whitelisted packages/activities.
@@ -107,7 +106,7 @@ public final class WhitelistHelper {
* Returns {@code true} if the entire package is whitelisted.
*/
public boolean isWhitelisted(@NonNull String packageName) {
- Preconditions.checkNotNull(packageName);
+ Objects.requireNonNull(packageName);
if (mWhitelistedPackages == null) return false;
@@ -119,7 +118,7 @@ public final class WhitelistHelper {
* Returns {@code true} if the specified activity is whitelisted.
*/
public boolean isWhitelisted(@NonNull ComponentName componentName) {
- Preconditions.checkNotNull(componentName);
+ Objects.requireNonNull(componentName);
final String packageName = componentName.getPackageName();
final ArraySet<ComponentName> whitelistedComponents = getWhitelistedComponents(packageName);
@@ -136,7 +135,7 @@ public final class WhitelistHelper {
*/
@Nullable
public ArraySet<ComponentName> getWhitelistedComponents(@NonNull String packageName) {
- Preconditions.checkNotNull(packageName);
+ Objects.requireNonNull(packageName);
return mWhitelistedPackages == null ? null : mWhitelistedPackages.get(packageName);
}
diff --git a/core/java/com/android/internal/os/FuseAppLoop.java b/core/java/com/android/internal/os/FuseAppLoop.java
index d08930b007ff..a22615ba19ef 100644
--- a/core/java/com/android/internal/os/FuseAppLoop.java
+++ b/core/java/com/android/internal/os/FuseAppLoop.java
@@ -32,6 +32,7 @@ import com.android.internal.util.Preconditions;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
+import java.util.Objects;
import java.util.concurrent.ThreadFactory;
public class FuseAppLoop implements Handler.Callback {
@@ -92,8 +93,8 @@ public class FuseAppLoop implements Handler.Callback {
public int registerCallback(@NonNull ProxyFileDescriptorCallback callback,
@NonNull Handler handler) throws FuseUnavailableMountException {
synchronized (mLock) {
- Preconditions.checkNotNull(callback);
- Preconditions.checkNotNull(handler);
+ Objects.requireNonNull(callback);
+ Objects.requireNonNull(handler);
Preconditions.checkState(
mCallbackMap.size() < Integer.MAX_VALUE - MIN_INODE, "Too many opened files.");
Preconditions.checkArgument(
@@ -333,8 +334,8 @@ public class FuseAppLoop implements Handler.Callback {
boolean opened;
CallbackEntry(ProxyFileDescriptorCallback callback, Handler handler) {
- this.callback = Preconditions.checkNotNull(callback);
- this.handler = Preconditions.checkNotNull(handler);
+ this.callback = Objects.requireNonNull(callback);
+ this.handler = Objects.requireNonNull(handler);
}
long getThreadId() {
@@ -368,7 +369,7 @@ public class FuseAppLoop implements Handler.Callback {
void stopUsing(long threadId) {
final BytesMapEntry entry = mEntries.get(threadId);
- Preconditions.checkNotNull(entry);
+ Objects.requireNonNull(entry);
entry.counter--;
if (entry.counter <= 0) {
mEntries.remove(threadId);
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 2b988c155412..2248b8853f8c 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -151,6 +151,9 @@ public final class Zygote {
/** Make the new process have top application priority. */
public static final String START_AS_TOP_APP_ARG = "--is-top-app";
+ /** List of packages with the same uid, and its app data info: volume uuid and inode. */
+ public static final String PKG_DATA_INFO_MAP = "--pkg-data-info-map";
+
/**
* An extraArg passed when a zygote process is forking a child-zygote, specifying a name
* in the abstract socket namespace. This socket name is what the new child zygote
@@ -254,6 +257,8 @@ public final class Zygote {
* @param instructionSet null-ok the instruction set to use.
* @param appDataDir null-ok the data directory of the app.
* @param isTopApp true if the process is for top (high priority) application.
+ * @param pkgDataInfoList A list that stores related packages and its app data
+ * info: volume uuid and inode.
*
* @return 0 if this is the child, pid of the child
* if this is the parent, or -1 on error.
@@ -261,12 +266,13 @@ public final class Zygote {
static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags,
int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir,
- int targetSdkVersion, boolean isTopApp) {
+ int targetSdkVersion, boolean isTopApp, String[] pkgDataInfoList) {
ZygoteHooks.preFork();
int pid = nativeForkAndSpecialize(
uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
- fdsToIgnore, startChildZygote, instructionSet, appDataDir, isTopApp);
+ fdsToIgnore, startChildZygote, instructionSet, appDataDir, isTopApp,
+ pkgDataInfoList);
// Enable tracing as soon as possible for the child process.
if (pid == 0) {
Zygote.disableExecuteOnly(targetSdkVersion);
@@ -286,7 +292,7 @@ public final class Zygote {
private static native int nativeForkAndSpecialize(int uid, int gid, int[] gids,
int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName,
int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet,
- String appDataDir, boolean isTopApp);
+ String appDataDir, boolean isTopApp, String[] pkgDataInfoList);
/**
* Specialize an unspecialized app process. The current VM must have been started
@@ -309,12 +315,18 @@ public final class Zygote {
* @param instructionSet null-ok The instruction set to use.
* @param appDataDir null-ok The data directory of the app.
* @param isTopApp True if the process is for top (high priority) application.
+ * @param pkgDataInfoList A list that stores related packages and its app data
+ * volume uuid and CE dir inode. For example, pkgDataInfoList = [app_a_pkg_name,
+ * app_a_data_volume_uuid, app_a_ce_inode, app_b_pkg_name, app_b_data_volume_uuid,
+ * app_b_ce_inode, ...];
*/
private static void specializeAppProcess(int uid, int gid, int[] gids, int runtimeFlags,
int[][] rlimits, int mountExternal, String seInfo, String niceName,
- boolean startChildZygote, String instructionSet, String appDataDir, boolean isTopApp) {
+ boolean startChildZygote, String instructionSet, String appDataDir, boolean isTopApp,
+ String[] pkgDataInfoList) {
nativeSpecializeAppProcess(uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo,
- niceName, startChildZygote, instructionSet, appDataDir, isTopApp);
+ niceName, startChildZygote, instructionSet, appDataDir, isTopApp,
+ pkgDataInfoList);
// Enable tracing as soon as possible for the child process.
Trace.setTracingEnabled(true, runtimeFlags);
@@ -336,7 +348,8 @@ public final class Zygote {
private static native void nativeSpecializeAppProcess(int uid, int gid, int[] gids,
int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName,
- boolean startChildZygote, String instructionSet, String appDataDir, boolean isTopApp);
+ boolean startChildZygote, String instructionSet, String appDataDir, boolean isTopApp,
+ String[] pkgDataInfoList);
/**
* Called to do any initialization before starting an application.
@@ -665,7 +678,8 @@ public final class Zygote {
specializeAppProcess(args.mUid, args.mGid, args.mGids,
args.mRuntimeFlags, rlimits, args.mMountExternal,
args.mSeInfo, args.mNiceName, args.mStartChildZygote,
- args.mInstructionSet, args.mAppDataDir, args.mIsTopApp);
+ args.mInstructionSet, args.mAppDataDir, args.mIsTopApp,
+ args.mPkgDataInfoList);
disableExecuteOnly(args.mTargetSdkVersion);
diff --git a/core/java/com/android/internal/os/ZygoteArguments.java b/core/java/com/android/internal/os/ZygoteArguments.java
index 54b2a2063451..d3499541a3a3 100644
--- a/core/java/com/android/internal/os/ZygoteArguments.java
+++ b/core/java/com/android/internal/os/ZygoteArguments.java
@@ -221,6 +221,12 @@ class ZygoteArguments {
long[] mDisabledCompatChanges = null;
/**
+ * A list that stores all related packages and its data info: volume uuid and inode.
+ * Null if it does need to do app data isolation.
+ */
+ String[] mPkgDataInfoList;
+
+ /**
* Constructs instance and parses args
*
* @param args zygote command-line args
@@ -437,6 +443,8 @@ class ZygoteArguments {
for (int i = 0; i < length; i++) {
mDisabledCompatChanges[i] = Long.parseLong(params[i]);
}
+ } else if (arg.startsWith(Zygote.PKG_DATA_INFO_MAP)) {
+ mPkgDataInfoList = getAssignmentList(arg);
} else {
break;
}
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index 3111b6ff0f72..9c6a288372c6 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -258,7 +258,7 @@ class ZygoteConnection {
parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, parsedArgs.mSeInfo,
parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,
parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mTargetSdkVersion,
- parsedArgs.mIsTopApp);
+ parsedArgs.mIsTopApp, parsedArgs.mPkgDataInfoList);
try {
if (pid == 0) {
diff --git a/core/java/com/android/internal/os/ZygoteServer.java b/core/java/com/android/internal/os/ZygoteServer.java
index 4a21d37a38fb..8d281b7ce9a0 100644
--- a/core/java/com/android/internal/os/ZygoteServer.java
+++ b/core/java/com/android/internal/os/ZygoteServer.java
@@ -184,9 +184,8 @@ class ZygoteServer {
Zygote.USAP_POOL_SECONDARY_SOCKET_NAME);
}
- fetchUsapPoolPolicyProps();
-
mUsapPoolSupported = true;
+ fetchUsapPoolPolicyProps();
}
void setForkChild() {
diff --git a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
index cb67309ce74f..6c7e3dc84425 100644
--- a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
+++ b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
@@ -16,8 +16,8 @@
package com.android.internal.telephony;
-import android.os.Bundle;
import android.telephony.CallAttributes;
+import android.telephony.CellIdentity;
import android.telephony.CellInfo;
import android.telephony.DataConnectionRealTimeInfo;
import android.telephony.PhoneCapability;
@@ -37,8 +37,8 @@ oneway interface IPhoneStateListener {
void onMessageWaitingIndicatorChanged(boolean mwi);
void onCallForwardingIndicatorChanged(boolean cfi);
- // we use bundle here instead of CellLocation so it can get the right subclass
- void onCellLocationChanged(in Bundle location);
+ // Uses CellIdentity which is Parcelable here; will convert to CellLocation in client.
+ void onCellLocationChanged(in CellIdentity location);
void onCallStateChanged(int state, String incomingNumber);
void onDataConnectionStateChanged(int state, int networkType);
void onDataActivity(int direction);
@@ -63,4 +63,3 @@ oneway interface IPhoneStateListener {
void onCallDisconnectCauseChanged(in int disconnectCause, in int preciseDisconnectCause);
void onImsCallDisconnectCauseChanged(in ImsReasonInfo imsReasonInfo);
}
-
diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index f954679ebf4d..4e405037f6ef 100644
--- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -19,8 +19,8 @@ package com.android.internal.telephony;
import android.content.Intent;
import android.net.LinkProperties;
import android.net.NetworkCapabilities;
-import android.os.Bundle;
import android.telephony.CallQuality;
+import android.telephony.CellIdentity;
import android.telephony.CellInfo;
import android.telephony.ims.ImsReasonInfo;
import android.telephony.PhoneCapability;
@@ -66,9 +66,9 @@ interface ITelephonyRegistry {
int phoneId, int subId, String apnType, in PreciseDataConnectionState preciseState);
@UnsupportedAppUsage
void notifyDataConnectionFailed(String apnType);
- @UnsupportedAppUsage(maxTargetSdk = 28)
- void notifyCellLocation(in Bundle cellLocation);
- void notifyCellLocationForSubscriber(in int subId, in Bundle cellLocation);
+ // Uses CellIdentity which is Parcelable here; will convert to CellLocation in client.
+ void notifyCellLocation(in CellIdentity cellLocation);
+ void notifyCellLocationForSubscriber(in int subId, in CellIdentity cellLocation);
@UnsupportedAppUsage
void notifyCellInfo(in List<CellInfo> cellInfo);
void notifyPreciseCallState(int phoneId, int subId, int ringingCallState,
diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java
index bc8019796d22..c7ec2cd6ca88 100644
--- a/core/java/com/android/internal/util/ArrayUtils.java
+++ b/core/java/com/android/internal/util/ArrayUtils.java
@@ -136,6 +136,13 @@ public class ArrayUtils {
}
/**
+ * Returns the same array or an empty one if it's null.
+ */
+ public static @NonNull <T> T[] emptyIfNull(@Nullable T[] items, Class<T> kind) {
+ return items != null ? items : emptyArray(kind);
+ }
+
+ /**
* Checks if given array is null or has zero elements.
*/
public static boolean isEmpty(@Nullable Collection<?> array) {
@@ -751,6 +758,42 @@ public class ArrayUtils {
return result;
}
+ /**
+ * Returns an array containing elements from the given one that match the given predicate.
+ */
+ public static @Nullable <T> T[] filter(@Nullable T[] items,
+ @NonNull IntFunction<T[]> arrayConstructor,
+ @NonNull java.util.function.Predicate<T> predicate) {
+ if (isEmpty(items)) {
+ return items;
+ }
+
+ int matchesCount = 0;
+ int size = size(items);
+ for (int i = 0; i < size; i++) {
+ if (predicate.test(items[i])) {
+ matchesCount++;
+ }
+ }
+ if (matchesCount == 0) {
+ return items;
+ }
+ if (matchesCount == items.length) {
+ return items;
+ }
+ if (matchesCount == 0) {
+ return null;
+ }
+ T[] result = arrayConstructor.apply(matchesCount);
+ int outIdx = 0;
+ for (int i = 0; i < size; i++) {
+ if (predicate.test(items[i])) {
+ result[outIdx++] = items[i];
+ }
+ }
+ return result;
+ }
+
public static boolean startsWith(byte[] cur, byte[] val) {
if (cur == null || val == null) return false;
if (cur.length < val.length) return false;
diff --git a/core/java/com/android/internal/util/FileRotator.java b/core/java/com/android/internal/util/FileRotator.java
index f8885a20970d..3ca33203f554 100644
--- a/core/java/com/android/internal/util/FileRotator.java
+++ b/core/java/com/android/internal/util/FileRotator.java
@@ -27,6 +27,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.util.Objects;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
@@ -96,8 +97,8 @@ public class FileRotator {
* may be deleted.
*/
public FileRotator(File basePath, String prefix, long rotateAgeMillis, long deleteAgeMillis) {
- mBasePath = Preconditions.checkNotNull(basePath);
- mPrefix = Preconditions.checkNotNull(prefix);
+ mBasePath = Objects.requireNonNull(basePath);
+ mPrefix = Objects.requireNonNull(prefix);
mRotateAgeMillis = rotateAgeMillis;
mDeleteAgeMillis = deleteAgeMillis;
@@ -406,7 +407,7 @@ public class FileRotator {
public long endMillis;
public FileInfo(String prefix) {
- this.prefix = Preconditions.checkNotNull(prefix);
+ this.prefix = Objects.requireNonNull(prefix);
}
/**
diff --git a/core/java/com/android/internal/util/FunctionalUtils.java b/core/java/com/android/internal/util/FunctionalUtils.java
index b955f672fe93..3c9791791a68 100644
--- a/core/java/com/android/internal/util/FunctionalUtils.java
+++ b/core/java/com/android/internal/util/FunctionalUtils.java
@@ -19,6 +19,7 @@ package com.android.internal.util;
import android.os.RemoteException;
import android.util.ExceptionUtils;
+import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
@@ -54,6 +55,13 @@ public class FunctionalUtils {
/**
* @see #uncheckExceptions(ThrowingConsumer)
*/
+ public static <A, B> BiConsumer<A, B> uncheckExceptions(ThrowingBiConsumer<A, B> action) {
+ return action;
+ }
+
+ /**
+ * @see #uncheckExceptions(ThrowingConsumer)
+ */
public static <T> Supplier<T> uncheckExceptions(ThrowingSupplier<T> action) {
return action;
}
@@ -185,4 +193,29 @@ public class FunctionalUtils {
}
}
}
+
+ /**
+ * A {@link BiConsumer} that allows throwing checked exceptions from its single abstract method.
+ *
+ * Can be used together with {@link #uncheckExceptions} to effectively turn a lambda expression
+ * that throws a checked exception into a regular {@link Function}
+ *
+ * @param <A> see {@link BiConsumer}
+ * @param <B> see {@link BiConsumer}
+ */
+ @FunctionalInterface
+ @SuppressWarnings("FunctionalInterfaceMethodChanged")
+ public interface ThrowingBiConsumer<A, B> extends BiConsumer<A, B> {
+ /** @see ThrowingFunction */
+ void acceptOrThrow(A a, B b) throws Exception;
+
+ @Override
+ default void accept(A a, B b) {
+ try {
+ acceptOrThrow(a, b);
+ } catch (Exception ex) {
+ throw ExceptionUtils.propagate(ex);
+ }
+ }
+ }
}
diff --git a/core/java/com/android/internal/util/MemInfoReader.java b/core/java/com/android/internal/util/MemInfoReader.java
index c1d129b66e7a..580c2fa66de2 100644
--- a/core/java/com/android/internal/util/MemInfoReader.java
+++ b/core/java/com/android/internal/util/MemInfoReader.java
@@ -91,7 +91,15 @@ public final class MemInfoReader {
* that are mapped in to processes.
*/
public long getCachedSizeKb() {
- return mInfos[Debug.MEMINFO_BUFFERS] + mInfos[Debug.MEMINFO_SLAB_RECLAIMABLE]
+ long kReclaimable = mInfos[Debug.MEMINFO_KRECLAIMABLE];
+
+ // Note: MEMINFO_KRECLAIMABLE includes MEMINFO_SLAB_RECLAIMABLE and ION pools.
+ // Fall back to using MEMINFO_SLAB_RECLAIMABLE in case of older kernels that do
+ // not include KReclaimable meminfo field.
+ if (kReclaimable == 0) {
+ kReclaimable = mInfos[Debug.MEMINFO_SLAB_RECLAIMABLE];
+ }
+ return mInfos[Debug.MEMINFO_BUFFERS] + kReclaimable
+ mInfos[Debug.MEMINFO_CACHED] - mInfos[Debug.MEMINFO_MAPPED];
}
@@ -99,9 +107,12 @@ public final class MemInfoReader {
* Amount of RAM that is in use by the kernel for actual allocations.
*/
public long getKernelUsedSizeKb() {
- return mInfos[Debug.MEMINFO_SHMEM] + mInfos[Debug.MEMINFO_SLAB_UNRECLAIMABLE]
- + mInfos[Debug.MEMINFO_VM_ALLOC_USED] + mInfos[Debug.MEMINFO_PAGE_TABLES]
- + mInfos[Debug.MEMINFO_KERNEL_STACK];
+ long size = mInfos[Debug.MEMINFO_SHMEM] + mInfos[Debug.MEMINFO_SLAB_UNRECLAIMABLE]
+ + mInfos[Debug.MEMINFO_VM_ALLOC_USED] + mInfos[Debug.MEMINFO_PAGE_TABLES];
+ if (!Debug.isVmapStack()) {
+ size += mInfos[Debug.MEMINFO_KERNEL_STACK];
+ }
+ return size;
}
public long getSwapTotalSizeKb() {
diff --git a/core/java/com/android/internal/util/ObjectUtils.java b/core/java/com/android/internal/util/ObjectUtils.java
index a47768870dfe..5568d91011dc 100644
--- a/core/java/com/android/internal/util/ObjectUtils.java
+++ b/core/java/com/android/internal/util/ObjectUtils.java
@@ -19,6 +19,7 @@ package com.android.internal.util;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import java.util.Objects;
/** @hide */
public class ObjectUtils {
@@ -32,7 +33,7 @@ public class ObjectUtils {
*/
@NonNull
public static <T> T firstNotNull(@Nullable T a, @NonNull T b) {
- return a != null ? a : Preconditions.checkNotNull(b);
+ return a != null ? a : Objects.requireNonNull(b);
}
/**
diff --git a/core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java b/core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java
index c7502ef04f1b..8446bbd09df7 100755
--- a/core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java
+++ b/core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java
@@ -25,7 +25,6 @@ import android.util.Pools;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.BitUtils;
-import com.android.internal.util.Preconditions;
import com.android.internal.util.function.DecConsumer;
import com.android.internal.util.function.DecFunction;
import com.android.internal.util.function.DecPredicate;
@@ -545,7 +544,7 @@ final class PooledLambdaImpl<R> extends OmniFunction<Object,
+ ", k = " + k
+ ")");
}
- r.mFunc = Preconditions.checkNotNull(func);
+ r.mFunc = Objects.requireNonNull(func);
r.setFlags(MASK_FUNC_TYPE, LambdaType.encode(fNumArgs, fReturnType));
r.setFlags(MASK_EXPOSED_AS, LambdaType.encode(numPlaceholders, fReturnType));
if (ArrayUtils.size(r.mArgs) < fNumArgs) r.mArgs = new Object[fNumArgs];
diff --git a/core/java/com/android/internal/view/FloatingActionMode.java b/core/java/com/android/internal/view/FloatingActionMode.java
index 54dede6753e4..f9e98e7eb473 100644
--- a/core/java/com/android/internal/view/FloatingActionMode.java
+++ b/core/java/com/android/internal/view/FloatingActionMode.java
@@ -33,11 +33,11 @@ import android.view.WindowManager;
import android.widget.PopupWindow;
import com.android.internal.R;
-import com.android.internal.util.Preconditions;
import com.android.internal.view.menu.MenuBuilder;
import com.android.internal.widget.FloatingToolbar;
import java.util.Arrays;
+import java.util.Objects;
public final class FloatingActionMode extends ActionMode {
@@ -84,8 +84,8 @@ public final class FloatingActionMode extends ActionMode {
public FloatingActionMode(
Context context, ActionMode.Callback2 callback,
View originatingView, FloatingToolbar floatingToolbar) {
- mContext = Preconditions.checkNotNull(context);
- mCallback = Preconditions.checkNotNull(callback);
+ mContext = Objects.requireNonNull(context);
+ mCallback = Objects.requireNonNull(callback);
mMenu = new MenuBuilder(context).setDefaultShowAsAction(
MenuItem.SHOW_AS_ACTION_IF_ROOM);
setType(ActionMode.TYPE_FLOATING);
@@ -107,14 +107,14 @@ public final class FloatingActionMode extends ActionMode {
mViewRectOnScreen = new Rect();
mPreviousViewRectOnScreen = new Rect();
mScreenRect = new Rect();
- mOriginatingView = Preconditions.checkNotNull(originatingView);
+ mOriginatingView = Objects.requireNonNull(originatingView);
mOriginatingView.getLocationOnScreen(mViewPositionOnScreen);
// Allow the content rect to overshoot a little bit beyond the
// bottom view bound if necessary.
mBottomAllowance = context.getResources()
.getDimensionPixelSize(R.dimen.content_rect_bottom_clip_allowance);
mDisplaySize = new Point();
- setFloatingToolbar(Preconditions.checkNotNull(floatingToolbar));
+ setFloatingToolbar(Objects.requireNonNull(floatingToolbar));
}
private void setFloatingToolbar(FloatingToolbar floatingToolbar) {
@@ -328,7 +328,7 @@ public final class FloatingActionMode extends ActionMode {
private long mLastShowTime;
public FloatingToolbarVisibilityHelper(FloatingToolbar toolbar) {
- mToolbar = Preconditions.checkNotNull(toolbar);
+ mToolbar = Objects.requireNonNull(toolbar);
}
public void activate() {
diff --git a/core/java/com/android/internal/view/menu/StandardMenuPopup.java b/core/java/com/android/internal/view/menu/StandardMenuPopup.java
index d618f6758faa..1979e4fe7a90 100644
--- a/core/java/com/android/internal/view/menu/StandardMenuPopup.java
+++ b/core/java/com/android/internal/view/menu/StandardMenuPopup.java
@@ -35,7 +35,7 @@ import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.PopupWindow.OnDismissListener;
-import com.android.internal.util.Preconditions;
+import java.util.Objects;
/**
* A standard menu popup in which when a submenu is opened, it replaces its parent menu in the
@@ -113,7 +113,7 @@ final class StandardMenuPopup extends MenuPopup implements OnDismissListener, On
public StandardMenuPopup(Context context, MenuBuilder menu, View anchorView, int popupStyleAttr,
int popupStyleRes, boolean overflowOnly) {
- mContext = Preconditions.checkNotNull(context);
+ mContext = Objects.requireNonNull(context);
mMenu = menu;
mOverflowOnly = overflowOnly;
final LayoutInflater inflater = LayoutInflater.from(context);
diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java
index bb7423a67754..d7611dcd0aa0 100644
--- a/core/java/com/android/internal/widget/FloatingToolbar.java
+++ b/core/java/com/android/internal/widget/FloatingToolbar.java
@@ -155,7 +155,7 @@ public final class FloatingToolbar {
// TODO(b/65172902): Pass context in constructor when DecorView (and other callers)
// supports multi-display.
mContext = applyDefaultTheme(window.getContext());
- mWindow = Preconditions.checkNotNull(window);
+ mWindow = Objects.requireNonNull(window);
mPopup = new FloatingToolbarPopup(mContext, window.getDecorView());
}
@@ -165,7 +165,7 @@ public final class FloatingToolbar {
* toolbar.
*/
public FloatingToolbar setMenu(Menu menu) {
- mMenu = Preconditions.checkNotNull(menu);
+ mMenu = Objects.requireNonNull(menu);
return this;
}
@@ -189,7 +189,7 @@ public final class FloatingToolbar {
* toolbar.
*/
public FloatingToolbar setContentRect(Rect rect) {
- mContentRect.set(Preconditions.checkNotNull(rect));
+ mContentRect.set(Objects.requireNonNull(rect));
return this;
}
@@ -457,8 +457,8 @@ public final class FloatingToolbar {
* from.
*/
public FloatingToolbarPopup(Context context, View parent) {
- mParent = Preconditions.checkNotNull(parent);
- mContext = Preconditions.checkNotNull(context);
+ mParent = Objects.requireNonNull(parent);
+ mContext = Objects.requireNonNull(context);
mContentContainer = createContentContainer(context);
mPopupWindow = createPopupWindow(mContentContainer);
mMarginHorizontal = parent.getResources()
@@ -578,7 +578,7 @@ public final class FloatingToolbar {
* The specified coordinates may be adjusted to make sure the popup is entirely on-screen.
*/
public void show(Rect contentRectOnScreen) {
- Preconditions.checkNotNull(contentRectOnScreen);
+ Objects.requireNonNull(contentRectOnScreen);
if (isShowing()) {
return;
@@ -650,7 +650,7 @@ public final class FloatingToolbar {
* This is a no-op if this popup is not showing.
*/
public void updateCoordinates(Rect contentRectOnScreen) {
- Preconditions.checkNotNull(contentRectOnScreen);
+ Objects.requireNonNull(contentRectOnScreen);
if (!isShowing() || !mPopupWindow.isShowing()) {
return;
@@ -1134,11 +1134,11 @@ public final class FloatingToolbar {
* Sets the touchable region of this popup to be the area occupied by its content.
*/
private void setContentAreaAsTouchableSurface() {
- Preconditions.checkNotNull(mMainPanelSize);
+ Objects.requireNonNull(mMainPanelSize);
final int width;
final int height;
if (mIsOverflowOpen) {
- Preconditions.checkNotNull(mOverflowPanelSize);
+ Objects.requireNonNull(mOverflowPanelSize);
width = mOverflowPanelSize.getWidth();
height = mOverflowPanelSize.getHeight();
} else {
@@ -1183,7 +1183,7 @@ public final class FloatingToolbar {
*/
public List<MenuItem> layoutMainPanelItems(
List<MenuItem> menuItems, final int toolbarWidth) {
- Preconditions.checkNotNull(menuItems);
+ Objects.requireNonNull(menuItems);
int availableWidth = toolbarWidth;
@@ -1555,7 +1555,7 @@ public final class FloatingToolbar {
private final FloatingToolbarPopup mPopup;
OverflowPanel(FloatingToolbarPopup popup) {
- super(Preconditions.checkNotNull(popup).mContext);
+ super(Objects.requireNonNull(popup).mContext);
this.mPopup = popup;
setScrollBarDefaultDelayBeforeFade(ViewConfiguration.getScrollDefaultDelay() * 3);
setScrollIndicators(View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_BOTTOM);
@@ -1616,7 +1616,7 @@ public final class FloatingToolbar {
private final Context mContext;
public OverflowPanelViewHelper(Context context, int iconTextSpacing) {
- mContext = Preconditions.checkNotNull(context);
+ mContext = Objects.requireNonNull(context);
mIconTextSpacing = iconTextSpacing;
mSidePadding = context.getResources()
.getDimensionPixelSize(R.dimen.floating_toolbar_overflow_side_padding);
@@ -1624,7 +1624,7 @@ public final class FloatingToolbar {
}
public View getView(MenuItem menuItem, int minimumWidth, View convertView) {
- Preconditions.checkNotNull(menuItem);
+ Objects.requireNonNull(menuItem);
if (convertView != null) {
updateMenuItemButton(
convertView, menuItem, mIconTextSpacing, shouldShowIcon(menuItem));
diff --git a/core/java/com/android/internal/widget/LockscreenCredential.java b/core/java/com/android/internal/widget/LockscreenCredential.java
index f456349a8937..9b87dd2c5f8b 100644
--- a/core/java/com/android/internal/widget/LockscreenCredential.java
+++ b/core/java/com/android/internal/widget/LockscreenCredential.java
@@ -33,6 +33,7 @@ import com.android.internal.util.Preconditions;
import java.util.Arrays;
import java.util.List;
+import java.util.Objects;
/**
* A class representing a lockscreen credential. It can be either an empty password, a pattern
@@ -67,7 +68,7 @@ public class LockscreenCredential implements Parcelable, AutoCloseable {
* minimize the number of extra copies introduced.
*/
private LockscreenCredential(int type, byte[] credential) {
- Preconditions.checkNotNull(credential);
+ Objects.requireNonNull(credential);
if (type == CREDENTIAL_TYPE_NONE) {
Preconditions.checkArgument(credential.length == 0);
} else {
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index a2f6a62157ed..98ce8b04c11a 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -110,7 +110,6 @@ cc_library_shared {
"android_view_InputEventReceiver.cpp",
"android_view_InputEventSender.cpp",
"android_view_InputQueue.cpp",
- "android_view_FrameMetricsObserver.cpp",
"android_view_KeyCharacterMap.cpp",
"android_view_KeyEvent.cpp",
"android_view_MotionEvent.cpp",
@@ -142,6 +141,7 @@ cc_library_shared {
"android_os_UEventObserver.cpp",
"android_os_VintfObject.cpp",
"android_os_VintfRuntimeInfo.cpp",
+ "android_os_incremental_IncrementalManager.cpp",
"android_net_LocalSocketImpl.cpp",
"android_net_NetUtils.cpp",
"android_service_DataLoaderService.cpp",
@@ -208,6 +208,7 @@ cc_library_shared {
static_libs: [
"libasync_safe",
+ "libdmabufinfo",
"libgif",
"libseccomp_policy",
"libgrallocusage",
@@ -351,6 +352,7 @@ cc_library_static {
"android_graphics_ColorSpace.cpp",
"android_graphics_drawable_AnimatedVectorDrawable.cpp",
"android_graphics_drawable_VectorDrawable.cpp",
+ "android_graphics_HardwareRendererObserver.cpp",
"android_graphics_Picture.cpp",
"android_nio_utils.cpp",
"android_view_DisplayListCanvas.cpp",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 3cde887ba465..c41b19ef0692 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -152,6 +152,7 @@ extern int register_android_os_HidlMemory(JNIEnv* env);
extern int register_android_os_MemoryFile(JNIEnv* env);
extern int register_android_os_SharedMemory(JNIEnv* env);
extern int register_android_service_DataLoaderService(JNIEnv* env);
+extern int register_android_os_incremental_IncrementalManager(JNIEnv* env);
extern int register_android_net_LocalSocketImpl(JNIEnv* env);
extern int register_android_net_NetworkUtils(JNIEnv* env);
extern int register_android_text_AndroidCharacter(JNIEnv *env);
@@ -1496,6 +1497,7 @@ static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_net_NetworkUtils),
REG_JNI(register_android_os_MemoryFile),
REG_JNI(register_android_os_SharedMemory),
+ REG_JNI(register_android_os_incremental_IncrementalManager),
REG_JNI(register_com_android_internal_os_ClassLoaderFactory),
REG_JNI(register_com_android_internal_os_Zygote),
REG_JNI(register_com_android_internal_os_ZygoteInit),
diff --git a/core/jni/android/graphics/apex/jni_runtime.cpp b/core/jni/android/graphics/apex/jni_runtime.cpp
index 7f9bac0df44a..1f661534ad81 100644
--- a/core/jni/android/graphics/apex/jni_runtime.cpp
+++ b/core/jni/android/graphics/apex/jni_runtime.cpp
@@ -52,6 +52,7 @@ extern int register_android_graphics_ColorFilter(JNIEnv* env);
extern int register_android_graphics_ColorSpace(JNIEnv* env);
extern int register_android_graphics_DrawFilter(JNIEnv* env);
extern int register_android_graphics_FontFamily(JNIEnv* env);
+extern int register_android_graphics_HardwareRendererObserver(JNIEnv* env);
extern int register_android_graphics_Matrix(JNIEnv* env);
extern int register_android_graphics_Paint(JNIEnv* env);
extern int register_android_graphics_Path(JNIEnv* env);
@@ -71,7 +72,6 @@ extern int register_android_graphics_text_LineBreaker(JNIEnv *env);
extern int register_android_util_PathParser(JNIEnv* env);
extern int register_android_view_DisplayListCanvas(JNIEnv* env);
-extern int register_android_view_FrameMetricsObserver(JNIEnv* env);
extern int register_android_view_RenderNode(JNIEnv* env);
extern int register_android_view_TextureLayer(JNIEnv* env);
extern int register_android_view_ThreadedRenderer(JNIEnv* env);
@@ -105,6 +105,7 @@ static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_graphics_ColorFilter),
REG_JNI(register_android_graphics_DrawFilter),
REG_JNI(register_android_graphics_FontFamily),
+ REG_JNI(register_android_graphics_HardwareRendererObserver),
REG_JNI(register_android_graphics_ImageDecoder),
REG_JNI(register_android_graphics_drawable_AnimatedImageDrawable),
REG_JNI(register_android_graphics_Interpolator),
@@ -135,7 +136,6 @@ static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_util_PathParser),
REG_JNI(register_android_view_RenderNode),
REG_JNI(register_android_view_DisplayListCanvas),
- REG_JNI(register_android_view_FrameMetricsObserver),
REG_JNI(register_android_view_TextureLayer),
REG_JNI(register_android_view_ThreadedRenderer),
};
diff --git a/core/jni/android_graphics_HardwareRendererObserver.cpp b/core/jni/android_graphics_HardwareRendererObserver.cpp
new file mode 100644
index 000000000000..89b77b0b069a
--- /dev/null
+++ b/core/jni/android_graphics_HardwareRendererObserver.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "android_graphics_HardwareRendererObserver.h"
+
+#include "core_jni_helpers.h"
+#include "nativehelper/jni_macros.h"
+
+#include <array>
+
+namespace android {
+
+struct {
+ jmethodID callback;
+} gHardwareRendererObserverClassInfo;
+
+static JNIEnv* getenv(JavaVM* vm) {
+ JNIEnv* env;
+ if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+ LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", vm);
+ }
+ return env;
+}
+
+HardwareRendererObserver::HardwareRendererObserver(JavaVM *vm, jobject observer) : mVm(vm) {
+ mObserverWeak = getenv(mVm)->NewWeakGlobalRef(observer);
+ LOG_ALWAYS_FATAL_IF(mObserverWeak == nullptr,
+ "unable to create frame stats observer reference");
+}
+
+HardwareRendererObserver::~HardwareRendererObserver() {
+ JNIEnv* env = getenv(mVm);
+ env->DeleteWeakGlobalRef(mObserverWeak);
+}
+
+bool HardwareRendererObserver::getNextBuffer(JNIEnv* env, jlongArray metrics, int* dropCount) {
+ jsize bufferSize = env->GetArrayLength(reinterpret_cast<jarray>(metrics));
+ LOG_ALWAYS_FATAL_IF(bufferSize != HardwareRendererObserver::kBufferSize,
+ "Mismatched Java/Native FrameMetrics data format.");
+
+ FrameMetricsNotification& elem = mRingBuffer[mNextInQueue];
+ if (elem.hasData.load()) {
+ env->SetLongArrayRegion(metrics, 0, kBufferSize, elem.buffer);
+ *dropCount = elem.dropCount;
+ mNextInQueue = (mNextInQueue + 1) % kRingSize;
+ elem.hasData = false;
+ return true;
+ }
+
+ return false;
+}
+
+void HardwareRendererObserver::notify(const int64_t* stats) {
+ FrameMetricsNotification& elem = mRingBuffer[mNextFree];
+
+ if (!elem.hasData.load()) {
+ memcpy(elem.buffer, stats, kBufferSize * sizeof(stats[0]));
+
+ elem.dropCount = mDroppedReports;
+ mDroppedReports = 0;
+ mNextFree = (mNextFree + 1) % kRingSize;
+ elem.hasData = true;
+
+ JNIEnv* env = getenv(mVm);
+ jobject target = env->NewLocalRef(mObserverWeak);
+ if (target != nullptr) {
+ env->CallVoidMethod(target, gHardwareRendererObserverClassInfo.callback);
+ env->DeleteLocalRef(target);
+ }
+ } else {
+ mDroppedReports++;
+ }
+}
+
+static jlong android_graphics_HardwareRendererObserver_createObserver(JNIEnv* env,
+ jobject observerObj) {
+ JavaVM* vm = nullptr;
+ if (env->GetJavaVM(&vm) != JNI_OK) {
+ LOG_ALWAYS_FATAL("Unable to get Java VM");
+ return 0;
+ }
+
+ HardwareRendererObserver* observer = new HardwareRendererObserver(vm, observerObj);
+ return reinterpret_cast<jlong>(observer);
+}
+
+static jint android_graphics_HardwareRendererObserver_getNextBuffer(JNIEnv* env, jobject,
+ jlong observerPtr,
+ jlongArray metrics) {
+ HardwareRendererObserver* observer = reinterpret_cast<HardwareRendererObserver*>(observerPtr);
+ int dropCount = 0;
+ if (observer->getNextBuffer(env, metrics, &dropCount)) {
+ return dropCount;
+ } else {
+ return -1;
+ }
+}
+
+static const std::array gMethods = {
+ MAKE_JNI_NATIVE_METHOD("nCreateObserver", "()J",
+ android_graphics_HardwareRendererObserver_createObserver),
+ MAKE_JNI_NATIVE_METHOD("nGetNextBuffer", "(J[J)I",
+ android_graphics_HardwareRendererObserver_getNextBuffer),
+};
+
+int register_android_graphics_HardwareRendererObserver(JNIEnv* env) {
+
+ jclass observerClass = FindClassOrDie(env, "android/graphics/HardwareRendererObserver");
+ gHardwareRendererObserverClassInfo.callback = GetMethodIDOrDie(env, observerClass,
+ "notifyDataAvailable", "()V");
+
+ return RegisterMethodsOrDie(env, "android/graphics/HardwareRendererObserver",
+ gMethods.data(), gMethods.size());
+
+}
+
+} // namespace android \ No newline at end of file
diff --git a/core/jni/android_graphics_HardwareRendererObserver.h b/core/jni/android_graphics_HardwareRendererObserver.h
new file mode 100644
index 000000000000..62111fd7d7a1
--- /dev/null
+++ b/core/jni/android_graphics_HardwareRendererObserver.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "jni.h"
+
+#include <FrameInfo.h>
+#include <FrameMetricsObserver.h>
+
+namespace android {
+
+/*
+ * Implements JNI layer for hwui frame metrics reporting.
+ */
+class HardwareRendererObserver : public uirenderer::FrameMetricsObserver {
+public:
+ HardwareRendererObserver(JavaVM *vm, jobject observer);
+ ~HardwareRendererObserver();
+
+ /**
+ * Retrieves frame metrics for the oldest frame that the renderer has retained. The renderer
+ * will retain a buffer until it has been retrieved, via this method, or its internal storage
+ * is exhausted at which point it informs the caller of how many frames it has failed to store
+ * since the last time this method was invoked.
+ * @param env java env required to populate the provided buffer array
+ * @param metrics output parameter that represents the buffer of metrics that is to be filled
+ * @param dropCount output parameter that is updated to reflect the number of buffers that were
+ discarded since the last successful invocation of this method.
+ * @return true if there was data to populate the array and false otherwise. If false then
+ * neither the metrics buffer or dropCount will be modified.
+ */
+ bool getNextBuffer(JNIEnv* env, jlongArray metrics, int* dropCount);
+
+ void notify(const int64_t* stats) override;
+
+private:
+ static constexpr int kBufferSize = static_cast<int>(uirenderer::FrameInfoIndex::NumIndexes);
+ static constexpr int kRingSize = 3;
+
+ class FrameMetricsNotification {
+ public:
+ FrameMetricsNotification() {}
+
+ std::atomic_bool hasData = false;
+ int64_t buffer[kBufferSize];
+ int dropCount = 0;
+ private:
+ // non-copyable
+ FrameMetricsNotification(const FrameMetricsNotification&) = delete;
+ FrameMetricsNotification& operator=(const FrameMetricsNotification& ) = delete;
+ };
+
+ JavaVM* const mVm;
+ jweak mObserverWeak;
+
+ int mNextFree = 0;
+ int mNextInQueue = 0;
+ FrameMetricsNotification mRingBuffer[kRingSize];
+
+ int mDroppedReports = 0;
+};
+
+} // namespace android
diff --git a/core/jni/android_hardware_input_InputWindowHandle.cpp b/core/jni/android_hardware_input_InputWindowHandle.cpp
index 2265268f4d20..79f62cb19db0 100644
--- a/core/jni/android_hardware_input_InputWindowHandle.cpp
+++ b/core/jni/android_hardware_input_InputWindowHandle.cpp
@@ -59,7 +59,6 @@ static struct {
jfieldID hasFocus;
jfieldID hasWallpaper;
jfieldID paused;
- jfieldID layer;
jfieldID ownerPid;
jfieldID ownerUid;
jfieldID inputFeatures;
@@ -152,8 +151,6 @@ bool NativeInputWindowHandle::updateInfo() {
gInputWindowHandleClassInfo.hasWallpaper);
mInfo.paused = env->GetBooleanField(obj,
gInputWindowHandleClassInfo.paused);
- mInfo.layer = env->GetIntField(obj,
- gInputWindowHandleClassInfo.layer);
mInfo.ownerPid = env->GetIntField(obj,
gInputWindowHandleClassInfo.ownerPid);
mInfo.ownerUid = env->GetIntField(obj,
@@ -332,9 +329,6 @@ int register_android_view_InputWindowHandle(JNIEnv* env) {
GET_FIELD_ID(gInputWindowHandleClassInfo.paused, clazz,
"paused", "Z");
- GET_FIELD_ID(gInputWindowHandleClassInfo.layer, clazz,
- "layer", "I");
-
GET_FIELD_ID(gInputWindowHandleClassInfo.ownerPid, clazz,
"ownerPid", "I");
diff --git a/core/jni/android_media_AudioFormat.h b/core/jni/android_media_AudioFormat.h
index 99b5f8592e5d..a3c455bfc111 100644
--- a/core/jni/android_media_AudioFormat.h
+++ b/core/jni/android_media_AudioFormat.h
@@ -38,6 +38,7 @@
#define ENCODING_AC4 17
#define ENCODING_E_AC3_JOC 18
#define ENCODING_DOLBY_MAT 19
+#define ENCODING_OPUS 20
#define ENCODING_INVALID 0
#define ENCODING_DEFAULT 1
@@ -88,6 +89,8 @@ static inline audio_format_t audioFormatToNative(int audioFormat)
return AUDIO_FORMAT_DEFAULT;
case ENCODING_DOLBY_MAT:
return AUDIO_FORMAT_MAT;
+ case ENCODING_OPUS:
+ return AUDIO_FORMAT_OPUS;
default:
return AUDIO_FORMAT_INVALID;
}
@@ -142,6 +145,8 @@ static inline int audioFormatFromNative(audio_format_t nativeFormat)
case AUDIO_FORMAT_MAT_2_0:
case AUDIO_FORMAT_MAT_2_1:
return ENCODING_DOLBY_MAT;
+ case AUDIO_FORMAT_OPUS:
+ return ENCODING_OPUS;
case AUDIO_FORMAT_DEFAULT:
return ENCODING_DEFAULT;
default:
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index d62d2d967d85..4314eb6efb18 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -43,12 +43,14 @@
#include <nativehelper/JNIHelp.h>
#include <nativehelper/ScopedUtfChars.h>
#include "jni.h"
+#include <dmabufinfo/dmabufinfo.h>
#include <meminfo/procmeminfo.h>
#include <meminfo/sysmeminfo.h>
#include <memtrack/memtrack.h>
#include <memunreachable/memunreachable.h>
#include <android-base/strings.h>
#include "android_os_Debug.h"
+#include <vintf/VintfObject.h>
namespace android
{
@@ -560,6 +562,7 @@ enum {
MEMINFO_VMALLOC_USED,
MEMINFO_PAGE_TABLES,
MEMINFO_KERNEL_STACK,
+ MEMINFO_KERNEL_RECLAIMABLE,
MEMINFO_COUNT
};
@@ -780,6 +783,76 @@ static jlong android_os_Debug_getFreeZramKb(JNIEnv* env, jobject clazz) {
return zramFreeKb;
}
+static jlong android_os_Debug_getIonHeapsSizeKb(JNIEnv* env, jobject clazz) {
+ jlong heapsSizeKb = 0;
+ uint64_t size;
+
+ if (meminfo::ReadIonHeapsSizeKb(&size)) {
+ heapsSizeKb = size;
+ }
+
+ return heapsSizeKb;
+}
+
+static jlong android_os_Debug_getIonPoolsSizeKb(JNIEnv* env, jobject clazz) {
+ jlong poolsSizeKb = 0;
+ uint64_t size;
+
+ if (meminfo::ReadIonPoolsSizeKb(&size)) {
+ poolsSizeKb = size;
+ }
+
+ return poolsSizeKb;
+}
+
+static jlong android_os_Debug_getIonMappedSizeKb(JNIEnv* env, jobject clazz) {
+ jlong ionPss = 0;
+ std::vector<dmabufinfo::DmaBuffer> dmabufs;
+
+ std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir("/proc"), closedir);
+ if (!dir) {
+ LOG(ERROR) << "Failed to open /proc directory";
+ return false;
+ }
+
+ struct dirent* dent;
+ while ((dent = readdir(dir.get()))) {
+ if (dent->d_type != DT_DIR) continue;
+
+ int pid = atoi(dent->d_name);
+ if (pid == 0) {
+ continue;
+ }
+
+ if (!AppendDmaBufInfo(pid, &dmabufs, false)) {
+ LOG(ERROR) << "Failed to read maps for pid " << pid;
+ }
+ }
+
+ for (const dmabufinfo::DmaBuffer& buf : dmabufs) {
+ ionPss += buf.size() / 1024;
+ }
+
+ return ionPss;
+}
+
+static jboolean android_os_Debug_isVmapStack(JNIEnv *env, jobject clazz)
+{
+ static enum {
+ CONFIG_UNKNOWN,
+ CONFIG_SET,
+ CONFIG_UNSET,
+ } cfg_state = CONFIG_UNKNOWN;
+
+ if (cfg_state == CONFIG_UNKNOWN) {
+ const std::map<std::string, std::string> configs =
+ vintf::VintfObject::GetInstance()->getRuntimeInfo()->kernelConfigs();
+ std::map<std::string, std::string>::const_iterator it = configs.find("CONFIG_VMAP_STACK");
+ cfg_state = (it != configs.end() && it->second == "y") ? CONFIG_SET : CONFIG_UNSET;
+ }
+ return cfg_state == CONFIG_SET;
+}
+
/*
* JNI registration.
*/
@@ -823,6 +896,14 @@ static const JNINativeMethod gMethods[] = {
(void*)android_os_Debug_getUnreachableMemory },
{ "getZramFreeKb", "()J",
(void*)android_os_Debug_getFreeZramKb },
+ { "getIonHeapsSizeKb", "()J",
+ (void*)android_os_Debug_getIonHeapsSizeKb },
+ { "getIonPoolsSizeKb", "()J",
+ (void*)android_os_Debug_getIonPoolsSizeKb },
+ { "getIonMappedSizeKb", "()J",
+ (void*)android_os_Debug_getIonMappedSizeKb },
+ { "isVmapStack", "()Z",
+ (void*)android_os_Debug_isVmapStack },
};
int register_android_os_Debug(JNIEnv *env)
diff --git a/core/jni/android_os_VintfObject.cpp b/core/jni/android_os_VintfObject.cpp
index ee11b6162db0..25ffbabd6199 100644
--- a/core/jni/android_os_VintfObject.cpp
+++ b/core/jni/android_os_VintfObject.cpp
@@ -96,28 +96,9 @@ static jobjectArray android_os_VintfObject_report(JNIEnv* env, jclass)
return toJavaStringArray(env, cStrings);
}
-static jint android_os_VintfObject_verify(JNIEnv* env, jclass, jobjectArray packageInfo) {
- std::vector<std::string> cPackageInfo;
- if (packageInfo) {
- size_t count = env->GetArrayLength(packageInfo);
- cPackageInfo.resize(count);
- for (size_t i = 0; i < count; ++i) {
- jstring element = (jstring)env->GetObjectArrayElement(packageInfo, i);
- const char *cString = env->GetStringUTFChars(element, NULL /* isCopy */);
- cPackageInfo[i] = cString;
- env->ReleaseStringUTFChars(element, cString);
- }
- }
- std::string error;
- int32_t status = VintfObject::CheckCompatibility(cPackageInfo, &error);
- if (status)
- LOG(WARNING) << "VintfObject.verify() returns " << status << ": " << error;
- return status;
-}
-
static jint android_os_VintfObject_verifyWithoutAvb(JNIEnv* env, jclass) {
std::string error;
- int32_t status = VintfObject::CheckCompatibility({}, &error,
+ int32_t status = VintfObject::GetInstance()->checkCompatibility(&error,
::android::vintf::CheckFlags::DISABLE_AVB_CHECK);
if (status)
LOG(WARNING) << "VintfObject.verifyWithoutAvb() returns " << status << ": " << error;
@@ -170,7 +151,6 @@ static jobject android_os_VintfObject_getTargetFrameworkCompatibilityMatrixVersi
static const JNINativeMethod gVintfObjectMethods[] = {
{"report", "()[Ljava/lang/String;", (void*)android_os_VintfObject_report},
- {"verify", "([Ljava/lang/String;)I", (void*)android_os_VintfObject_verify},
{"verifyWithoutAvb", "()I", (void*)android_os_VintfObject_verifyWithoutAvb},
{"getHalNamesAndVersions", "()[Ljava/lang/String;", (void*)android_os_VintfObject_getHalNamesAndVersions},
{"getSepolicyVersion", "()Ljava/lang/String;", (void*)android_os_VintfObject_getSepolicyVersion},
diff --git a/core/jni/android_os_incremental_IncrementalManager.cpp b/core/jni/android_os_incremental_IncrementalManager.cpp
new file mode 100644
index 000000000000..698062a2651e
--- /dev/null
+++ b/core/jni/android_os_incremental_IncrementalManager.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "incremental_manager-jni"
+
+#include "core_jni_helpers.h"
+#include "incfs_ndk.h"
+#include "jni.h"
+#include "nativehelper/JNIHelp.h"
+
+#include <iterator>
+#include <memory>
+
+namespace android {
+
+static jboolean nativeIsIncrementalPath(JNIEnv* env,
+ jobject clazz,
+ jstring javaPath) {
+ ScopedUtfChars path(env, javaPath);
+ return (jboolean)IncFs_IsIncFsPath(path.c_str());
+}
+
+static const JNINativeMethod method_table[] = {
+ {"nativeIsIncrementalPath", "(Ljava/lang/String;)Z",
+ (void*)nativeIsIncrementalPath},
+};
+
+int register_android_os_incremental_IncrementalManager(JNIEnv* env) {
+ return jniRegisterNativeMethods(env, "android/os/incremental/IncrementalManager",
+ method_table, std::size(method_table));
+}
+
+} // namespace android
diff --git a/core/jni/android_service_DataLoaderService.cpp b/core/jni/android_service_DataLoaderService.cpp
index 4c0f55f2bf23..a62d127a968f 100644
--- a/core/jni/android_service_DataLoaderService.cpp
+++ b/core/jni/android_service_DataLoaderService.cpp
@@ -16,83 +16,18 @@
#define LOG_TAG "dataloader-jni"
-#include <vector>
-
#include "core_jni_helpers.h"
#include "dataloader_ndk.h"
-#include "jni.h"
namespace android {
namespace {
-struct JniIds {
- jfieldID dataBlockFileIno;
- jfieldID dataBlockBlockIndex;
- jfieldID dataBlockDataBytes;
- jfieldID dataBlockCompressionType;
-
- JniIds(JNIEnv* env) {
- const auto dataBlock =
- FindClassOrDie(env,
- "android/service/incremental/"
- "IncrementalDataLoaderService$FileSystemConnector$DataBlock");
- dataBlockFileIno = GetFieldIDOrDie(env, dataBlock, "mFileIno", "J");
- dataBlockBlockIndex =
- GetFieldIDOrDie(env, dataBlock, "mBlockIndex", "I");
- dataBlockDataBytes = GetFieldIDOrDie(env, dataBlock, "mDataBytes", "[B");
- dataBlockCompressionType =
- GetFieldIDOrDie(env, dataBlock, "mCompressionType", "I");
- }
-};
-
-const JniIds& jniIds(JNIEnv* env) {
- static const JniIds ids(env);
- return ids;
-}
-
-class ScopedJniArrayCritical {
-public:
- ScopedJniArrayCritical(JNIEnv* env, jarray array) : mEnv(env), mArr(array) {
- mPtr = array ? env->GetPrimitiveArrayCritical(array, nullptr) : nullptr;
- }
- ~ScopedJniArrayCritical() {
- if (mPtr) {
- mEnv->ReleasePrimitiveArrayCritical(mArr, mPtr, 0);
- mPtr = nullptr;
- }
- }
-
- ScopedJniArrayCritical(const ScopedJniArrayCritical&) = delete;
- void operator=(const ScopedJniArrayCritical&) = delete;
-
- ScopedJniArrayCritical(ScopedJniArrayCritical&& other)
- : mEnv(other.mEnv),
- mArr(std::exchange(mArr, nullptr)),
- mPtr(std::exchange(mPtr, nullptr)) {}
- ScopedJniArrayCritical& operator=(ScopedJniArrayCritical&& other) {
- mEnv = other.mEnv;
- mArr = std::exchange(other.mArr, nullptr);
- mPtr = std::exchange(other.mPtr, nullptr);
- return *this;
- }
-
- void* ptr() const { return mPtr; }
- jsize size() const { return mArr ? mEnv->GetArrayLength(mArr) : 0; }
-
-private:
- JNIEnv* mEnv;
- jarray mArr;
- void* mPtr;
-};
-
static jboolean nativeCreateDataLoader(JNIEnv* env,
jobject thiz,
jint storageId,
jobject control,
jobject params,
jobject callback) {
- ALOGE("nativeCreateDataLoader: %p/%d, %d, %p, %p, %p", thiz,
- env->GetObjectRefType(thiz), storageId, params, control, callback);
return DataLoaderService_OnCreate(env, thiz,
storageId, control, params, callback);
}
@@ -100,169 +35,55 @@ static jboolean nativeCreateDataLoader(JNIEnv* env,
static jboolean nativeStartDataLoader(JNIEnv* env,
jobject thiz,
jint storageId) {
- ALOGE("nativeStartDataLoader: %p/%d, %d", thiz, env->GetObjectRefType(thiz),
- storageId);
return DataLoaderService_OnStart(storageId);
}
static jboolean nativeStopDataLoader(JNIEnv* env,
jobject thiz,
jint storageId) {
- ALOGE("nativeStopDataLoader: %p/%d, %d", thiz, env->GetObjectRefType(thiz),
- storageId);
return DataLoaderService_OnStop(storageId);
}
static jboolean nativeDestroyDataLoader(JNIEnv* env,
jobject thiz,
jint storageId) {
- ALOGE("nativeDestroyDataLoader: %p/%d, %d", thiz,
- env->GetObjectRefType(thiz), storageId);
return DataLoaderService_OnDestroy(storageId);
}
-static jboolean nativeOnFileCreated(JNIEnv* env,
- jobject thiz,
- jint storageId,
- jlong inode,
- jbyteArray metadata) {
- ALOGE("nativeOnFileCreated: %p/%d, %d", thiz,
- env->GetObjectRefType(thiz), storageId);
- return DataLoaderService_OnFileCreated(storageId, inode, metadata);
+static jboolean nativePrepareImage(JNIEnv* env, jobject thiz, jint storageId, jobject addedFiles, jobject removedFiles) {
+ return DataLoaderService_OnPrepareImage(storageId, addedFiles, removedFiles);
}
-static jboolean nativeIsFileRangeLoadedNode(JNIEnv* env,
- jobject clazz,
- jlong self,
- jlong node,
- jlong start,
- jlong end) {
- // TODO(b/136132412): implement this
- return JNI_FALSE;
-}
-
-static jboolean nativeWriteMissingData(JNIEnv* env,
- jobject clazz,
- jlong self,
- jobjectArray data_block,
- jobjectArray hash_blocks) {
- const auto& jni = jniIds(env);
- auto length = env->GetArrayLength(data_block);
- std::vector<incfs_new_data_block> instructions(length);
-
- // May not call back into Java after even a single jniArrayCritical, so
- // let's collect the Java pointers to byte buffers first and lock them in
- // memory later.
-
- std::vector<jbyteArray> blockBuffers(length);
- for (int i = 0; i != length; ++i) {
- auto& inst = instructions[i];
- auto jniBlock = env->GetObjectArrayElement(data_block, i);
- inst.file_ino = env->GetLongField(jniBlock, jni.dataBlockFileIno);
- inst.block_index = env->GetIntField(jniBlock, jni.dataBlockBlockIndex);
- blockBuffers[i] = (jbyteArray)env->GetObjectField(
- jniBlock, jni.dataBlockDataBytes);
- inst.compression = (incfs_compression_alg)env->GetIntField(
- jniBlock, jni.dataBlockCompressionType);
- }
-
- std::vector<ScopedJniArrayCritical> jniScopedArrays;
- jniScopedArrays.reserve(length);
- for (int i = 0; i != length; ++i) {
- auto buffer = blockBuffers[i];
- jniScopedArrays.emplace_back(env, buffer);
- auto& inst = instructions[i];
- inst.data = (uint64_t)jniScopedArrays.back().ptr();
- inst.data_len = jniScopedArrays.back().size();
- }
-
- auto connector = (DataLoaderFilesystemConnectorPtr)self;
- if (auto err = DataLoader_FilesystemConnector_writeBlocks(
- connector, instructions.data(), length);
- err < 0) {
- jniScopedArrays.clear();
- return JNI_FALSE;
- }
-
- return JNI_TRUE;
-}
-
-static jboolean nativeWriteSignerDataNode(JNIEnv* env,
- jobject clazz,
- jlong self,
- jstring relative_path,
- jbyteArray signer_data) {
- // TODO(b/136132412): implement this
- return JNI_TRUE;
-}
-
-static jbyteArray nativeGetFileMetadataNode(JNIEnv* env,
- jobject clazz,
- jlong self,
- jlong inode) {
+static void nativeWriteData(JNIEnv* env,
+ jobject clazz,
+ jlong self,
+ jstring name,
+ jlong offsetBytes,
+ jlong lengthBytes,
+ jobject incomingFd) {
auto connector = (DataLoaderFilesystemConnectorPtr)self;
- std::vector<char> metadata(INCFS_MAX_FILE_ATTR_SIZE);
- size_t size = metadata.size();
- if (DataLoader_FilesystemConnector_getRawMetadata(connector, inode,
- metadata.data(), &size) < 0) {
- size = 0;
- }
- metadata.resize(size);
-
- auto buffer = env->NewByteArray(metadata.size());
- env->SetByteArrayRegion(buffer, 0, metadata.size(),
- (jbyte*)metadata.data());
- return buffer;
-}
-
-static jbyteArray nativeGetFileInfoNode(JNIEnv* env,
- jobject clazz,
- jlong self,
- jlong inode) {
- // TODO(b/136132412): implement this
- return nullptr;
-}
-
-static jboolean nativeReportStatus(JNIEnv* env,
- jobject clazz,
- jlong self,
- jint status) {
- auto listener = (DataLoaderStatusListenerPtr)self;
- return DataLoader_StatusListener_reportStatus(listener,
- (DataLoaderStatus)status);
+ return DataLoader_FilesystemConnector_writeData(connector, name, offsetBytes, lengthBytes, incomingFd);
}
static const JNINativeMethod dlc_method_table[] = {
{"nativeCreateDataLoader",
- "(ILandroid/os/incremental/IncrementalFileSystemControlParcel;"
- "Landroid/os/incremental/IncrementalDataLoaderParamsParcel;"
+ "(ILandroid/content/pm/FileSystemControlParcel;"
+ "Landroid/content/pm/DataLoaderParamsParcel;"
"Landroid/content/pm/IDataLoaderStatusListener;)Z",
(void*)nativeCreateDataLoader},
{"nativeStartDataLoader", "(I)Z", (void*)nativeStartDataLoader},
{"nativeStopDataLoader", "(I)Z", (void*)nativeStopDataLoader},
{"nativeDestroyDataLoader", "(I)Z", (void*)nativeDestroyDataLoader},
- {"nativeIsFileRangeLoadedNode", "(JJJJ)Z",
- (void*)nativeIsFileRangeLoadedNode},
- {"nativeWriteMissingData",
- "(J[Landroid/service/incremental/"
- "IncrementalDataLoaderService$FileSystemConnector$DataBlock;[Landroid/service/incremental/"
- "IncrementalDataLoaderService$FileSystemConnector$HashBlock;)Z",
- (void*)nativeWriteMissingData},
- {"nativeWriteSignerDataNode", "(JJ[B)Z",
- (void*)nativeWriteSignerDataNode},
- {"nativeGetFileMetadataNode", "(JJ)[B",
- (void*)nativeGetFileMetadataNode},
- {"nativeGetFileInfoNode", "(JJ)[B", (void*)nativeGetFileInfoNode},
- {"nativeReportStatus", "(JI)Z", (void*)nativeReportStatus},
- {"nativeOnFileCreated", "(IJ[B)Z", (void*)nativeOnFileCreated},
+ {"nativePrepareImage", "(ILjava/util/Collection;Ljava/util/Collection;)Z", (void*)nativePrepareImage},
+ {"nativeWriteData", "(JLjava/lang/String;JJLandroid/os/ParcelFileDescriptor;)V", (void*)nativeWriteData},
};
} // namespace
int register_android_service_DataLoaderService(JNIEnv* env) {
return jniRegisterNativeMethods(env,
- "android/service/incremental/IncrementalDataLoaderService",
+ "android/service/dataloader/DataLoaderService",
dlc_method_table, NELEM(dlc_method_table));
}
diff --git a/core/jni/android_view_FrameMetricsObserver.cpp b/core/jni/android_view_FrameMetricsObserver.cpp
deleted file mode 100644
index febcb55bd0cd..000000000000
--- a/core/jni/android_view_FrameMetricsObserver.cpp
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "android_view_FrameMetricsObserver.h"
-
-namespace android {
-
-struct {
- jfieldID frameMetrics;
- jfieldID timingDataBuffer;
- jfieldID messageQueue;
- jmethodID callback;
-} gFrameMetricsObserverClassInfo;
-
-static JNIEnv* getenv(JavaVM* vm) {
- JNIEnv* env;
- if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
- LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", vm);
- }
- return env;
-}
-
-static jlongArray get_metrics_buffer(JNIEnv* env, jobject observer) {
- jobject frameMetrics = env->GetObjectField(
- observer, gFrameMetricsObserverClassInfo.frameMetrics);
- LOG_ALWAYS_FATAL_IF(frameMetrics == nullptr, "unable to retrieve data sink object");
- jobject buffer = env->GetObjectField(
- frameMetrics, gFrameMetricsObserverClassInfo.timingDataBuffer);
- LOG_ALWAYS_FATAL_IF(buffer == nullptr, "unable to retrieve data sink buffer");
- return reinterpret_cast<jlongArray>(buffer);
-}
-
-class NotifyHandler : public MessageHandler {
-public:
- NotifyHandler(JavaVM* vm, FrameMetricsObserverProxy* observer) : mVm(vm), mObserver(observer) {}
-
- virtual void handleMessage(const Message& message);
-
-private:
- JavaVM* const mVm;
- FrameMetricsObserverProxy* const mObserver;
-};
-
-void NotifyHandler::handleMessage(const Message& message) {
- JNIEnv* env = getenv(mVm);
-
- jobject target = env->NewLocalRef(mObserver->getObserverReference());
-
- if (target != nullptr) {
- jlongArray javaBuffer = get_metrics_buffer(env, target);
- int dropCount = 0;
- while (mObserver->getNextBuffer(env, javaBuffer, &dropCount)) {
- env->CallVoidMethod(target, gFrameMetricsObserverClassInfo.callback, dropCount);
- }
- env->DeleteLocalRef(target);
- }
-
- mObserver->decStrong(nullptr);
-}
-
-FrameMetricsObserverProxy::FrameMetricsObserverProxy(JavaVM *vm, jobject observer) : mVm(vm) {
- JNIEnv* env = getenv(mVm);
-
- mObserverWeak = env->NewWeakGlobalRef(observer);
- LOG_ALWAYS_FATAL_IF(mObserverWeak == nullptr,
- "unable to create frame stats observer reference");
-
- jlongArray buffer = get_metrics_buffer(env, observer);
- jsize bufferSize = env->GetArrayLength(reinterpret_cast<jarray>(buffer));
- LOG_ALWAYS_FATAL_IF(bufferSize != kBufferSize,
- "Mismatched Java/Native FrameMetrics data format.");
-
- jobject messageQueueLocal = env->GetObjectField(
- observer, gFrameMetricsObserverClassInfo.messageQueue);
- mMessageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueLocal);
- LOG_ALWAYS_FATAL_IF(mMessageQueue == nullptr, "message queue not available");
-
- mMessageHandler = new NotifyHandler(mVm, this);
- LOG_ALWAYS_FATAL_IF(mMessageHandler == nullptr,
- "OOM: unable to allocate NotifyHandler");
-}
-
-FrameMetricsObserverProxy::~FrameMetricsObserverProxy() {
- JNIEnv* env = getenv(mVm);
- env->DeleteWeakGlobalRef(mObserverWeak);
-}
-
-bool FrameMetricsObserverProxy::getNextBuffer(JNIEnv* env, jlongArray sink, int* dropCount) {
- FrameMetricsNotification& elem = mRingBuffer[mNextInQueue];
-
- if (elem.hasData.load()) {
- env->SetLongArrayRegion(sink, 0, kBufferSize, elem.buffer);
- *dropCount = elem.dropCount;
- mNextInQueue = (mNextInQueue + 1) % kRingSize;
- elem.hasData = false;
- return true;
- }
-
- return false;
-}
-
-void FrameMetricsObserverProxy::notify(const int64_t* stats) {
- FrameMetricsNotification& elem = mRingBuffer[mNextFree];
-
- if (!elem.hasData.load()) {
- memcpy(elem.buffer, stats, kBufferSize * sizeof(stats[0]));
-
- elem.dropCount = mDroppedReports;
- mDroppedReports = 0;
-
- incStrong(nullptr);
- mNextFree = (mNextFree + 1) % kRingSize;
- elem.hasData = true;
-
- mMessageQueue->getLooper()->sendMessage(mMessageHandler, mMessage);
- } else {
- mDroppedReports++;
- }
-}
-
-int register_android_view_FrameMetricsObserver(JNIEnv* env) {
- jclass observerClass = FindClassOrDie(env, "android/view/FrameMetricsObserver");
- gFrameMetricsObserverClassInfo.frameMetrics = GetFieldIDOrDie(
- env, observerClass, "mFrameMetrics", "Landroid/view/FrameMetrics;");
- gFrameMetricsObserverClassInfo.messageQueue = GetFieldIDOrDie(
- env, observerClass, "mMessageQueue", "Landroid/os/MessageQueue;");
- gFrameMetricsObserverClassInfo.callback = GetMethodIDOrDie(
- env, observerClass, "notifyDataAvailable", "(I)V");
-
- jclass metricsClass = FindClassOrDie(env, "android/view/FrameMetrics");
- gFrameMetricsObserverClassInfo.timingDataBuffer = GetFieldIDOrDie(
- env, metricsClass, "mTimingData", "[J");
- return JNI_OK;
-}
-
-} // namespace android \ No newline at end of file
diff --git a/core/jni/android_view_FrameMetricsObserver.h b/core/jni/android_view_FrameMetricsObserver.h
deleted file mode 100644
index 647f51c4492d..000000000000
--- a/core/jni/android_view_FrameMetricsObserver.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "jni.h"
-#include "core_jni_helpers.h"
-
-#include "android_os_MessageQueue.h"
-
-#include <FrameInfo.h>
-#include <FrameMetricsObserver.h>
-
-namespace android {
-
-/*
- * Implements JNI layer for hwui frame metrics reporting.
- */
-class FrameMetricsObserverProxy : public uirenderer::FrameMetricsObserver {
-public:
- FrameMetricsObserverProxy(JavaVM *vm, jobject observer);
-
- ~FrameMetricsObserverProxy();
-
- jweak getObserverReference() {
- return mObserverWeak;
- }
-
- bool getNextBuffer(JNIEnv* env, jlongArray sink, int* dropCount);
-
- virtual void notify(const int64_t* stats);
-
-private:
- static const int kBufferSize = static_cast<int>(uirenderer::FrameInfoIndex::NumIndexes);
- static constexpr int kRingSize = 3;
-
- class FrameMetricsNotification {
- public:
- FrameMetricsNotification() : hasData(false) {}
-
- std::atomic_bool hasData;
- int64_t buffer[kBufferSize];
- int dropCount = 0;
- };
-
- JavaVM* const mVm;
- jweak mObserverWeak;
-
- sp<MessageQueue> mMessageQueue;
- sp<MessageHandler> mMessageHandler;
- Message mMessage;
-
- int mNextFree = 0;
- int mNextInQueue = 0;
- FrameMetricsNotification mRingBuffer[kRingSize];
-
- int mDroppedReports = 0;
-};
-
-} // namespace android
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index c6e678ab50b0..4a7276c4f94e 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -141,7 +141,7 @@ static struct {
static struct {
jclass clazz;
jmethodID ctor;
- jfieldID defaultModeId;
+ jfieldID defaultConfig;
jfieldID minRefreshRate;
jfieldID maxRefreshRate;
} gDesiredDisplayConfigSpecsClassInfo;
@@ -776,65 +776,40 @@ static jobjectArray nativeGetDisplayConfigs(JNIEnv* env, jclass clazz,
return configArray;
}
-static jboolean nativeSetAllowedDisplayConfigs(JNIEnv* env, jclass clazz,
- jobject tokenObj, jintArray configArray) {
- sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
- if (token == nullptr) return JNI_FALSE;
-
- std::vector<int32_t> allowedConfigs;
- jsize configArraySize = env->GetArrayLength(configArray);
- allowedConfigs.reserve(configArraySize);
-
- jint* configArrayElements = env->GetIntArrayElements(configArray, 0);
- for (int i = 0; i < configArraySize; i++) {
- allowedConfigs.push_back(configArrayElements[i]);
- }
- env->ReleaseIntArrayElements(configArray, configArrayElements, 0);
-
- size_t result = SurfaceComposerClient::setAllowedDisplayConfigs(token, allowedConfigs);
- return result == NO_ERROR ? JNI_TRUE : JNI_FALSE;
-}
-
-static jintArray nativeGetAllowedDisplayConfigs(JNIEnv* env, jclass clazz, jobject tokenObj) {
- sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
- if (token == nullptr) return JNI_FALSE;
-
- std::vector<int32_t> allowedConfigs;
- size_t result = SurfaceComposerClient::getAllowedDisplayConfigs(token, &allowedConfigs);
- if (result != NO_ERROR) {
- return nullptr;
- }
-
- jintArray allowedConfigsArray = env->NewIntArray(allowedConfigs.size());
- if (allowedConfigsArray == nullptr) {
- jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
- return nullptr;
- }
- jint* allowedConfigsArrayValues = env->GetIntArrayElements(allowedConfigsArray, 0);
- for (size_t i = 0; i < allowedConfigs.size(); i++) {
- allowedConfigsArrayValues[i] = static_cast<jint>(allowedConfigs[i]);
- }
- env->ReleaseIntArrayElements(allowedConfigsArray, allowedConfigsArrayValues, 0);
- return allowedConfigsArray;
-}
-
static jboolean nativeSetDesiredDisplayConfigSpecs(JNIEnv* env, jclass clazz, jobject tokenObj,
jobject desiredDisplayConfigSpecs) {
sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
if (token == nullptr) return JNI_FALSE;
- jint defaultModeId = env->GetIntField(desiredDisplayConfigSpecs,
- gDesiredDisplayConfigSpecsClassInfo.defaultModeId);
+ jint defaultConfig = env->GetIntField(desiredDisplayConfigSpecs,
+ gDesiredDisplayConfigSpecsClassInfo.defaultConfig);
jfloat minRefreshRate = env->GetFloatField(desiredDisplayConfigSpecs,
gDesiredDisplayConfigSpecsClassInfo.minRefreshRate);
jfloat maxRefreshRate = env->GetFloatField(desiredDisplayConfigSpecs,
gDesiredDisplayConfigSpecsClassInfo.maxRefreshRate);
size_t result = SurfaceComposerClient::setDesiredDisplayConfigSpecs(
- token, defaultModeId, minRefreshRate, maxRefreshRate);
+ token, defaultConfig, minRefreshRate, maxRefreshRate);
return result == NO_ERROR ? JNI_TRUE : JNI_FALSE;
}
+static jobject nativeGetDesiredDisplayConfigSpecs(JNIEnv* env, jclass clazz, jobject tokenObj) {
+ sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+ if (token == nullptr) return nullptr;
+
+ int32_t defaultConfig;
+ float minRefreshRate;
+ float maxRefreshRate;
+ if (SurfaceComposerClient::getDesiredDisplayConfigSpecs(token, &defaultConfig, &minRefreshRate,
+ &maxRefreshRate) != NO_ERROR) {
+ return nullptr;
+ }
+
+ return env->NewObject(gDesiredDisplayConfigSpecsClassInfo.clazz,
+ gDesiredDisplayConfigSpecsClassInfo.ctor, defaultConfig, minRefreshRate,
+ maxRefreshRate);
+}
+
static jint nativeGetActiveConfig(JNIEnv* env, jclass clazz, jobject tokenObj) {
sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
if (token == NULL) return -1;
@@ -1199,6 +1174,34 @@ static jobject nativeGetHdrCapabilities(JNIEnv* env, jclass clazz, jobject token
capabilities.getDesiredMaxAverageLuminance(), capabilities.getDesiredMinLuminance());
}
+static jboolean nativeGetAutoLowLatencyModeSupport(JNIEnv* env, jclass clazz, jobject tokenObject) {
+ sp<IBinder> token(ibinderForJavaObject(env, tokenObject));
+ if (token == NULL) return NULL;
+
+ return SurfaceComposerClient::getAutoLowLatencyModeSupport(token);
+}
+
+static jboolean nativeGetGameContentTypeSupport(JNIEnv* env, jclass clazz, jobject tokenObject) {
+ sp<IBinder> token(ibinderForJavaObject(env, tokenObject));
+ if (token == NULL) return NULL;
+
+ return SurfaceComposerClient::getGameContentTypeSupport(token);
+}
+
+static void nativeSetAutoLowLatencyMode(JNIEnv* env, jclass clazz, jobject tokenObject, jboolean on) {
+ sp<IBinder> token(ibinderForJavaObject(env, tokenObject));
+ if (token == NULL) return;
+
+ SurfaceComposerClient::setAutoLowLatencyMode(token, on);
+}
+
+static void nativeSetGameContentType(JNIEnv* env, jclass clazz, jobject tokenObject, jboolean on) {
+ sp<IBinder> token(ibinderForJavaObject(env, tokenObject));
+ if (token == NULL) return;
+
+ SurfaceComposerClient::setGameContentType(token, on);
+}
+
static jlong nativeReadFromParcel(JNIEnv* env, jclass clazz, jobject parcelObj) {
Parcel* parcel = parcelForJavaObject(env, parcelObj);
if (parcel == NULL) {
@@ -1387,13 +1390,12 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
(void*)nativeGetActiveConfig },
{"nativeSetActiveConfig", "(Landroid/os/IBinder;I)Z",
(void*)nativeSetActiveConfig },
- {"nativeSetAllowedDisplayConfigs", "(Landroid/os/IBinder;[I)Z",
- (void*)nativeSetAllowedDisplayConfigs },
- {"nativeGetAllowedDisplayConfigs", "(Landroid/os/IBinder;)[I",
- (void*)nativeGetAllowedDisplayConfigs },
{"nativeSetDesiredDisplayConfigSpecs",
"(Landroid/os/IBinder;Landroid/view/SurfaceControl$DesiredDisplayConfigSpecs;)Z",
(void*)nativeSetDesiredDisplayConfigSpecs },
+ {"nativeGetDesiredDisplayConfigSpecs",
+ "(Landroid/os/IBinder;)Landroid/view/SurfaceControl$DesiredDisplayConfigSpecs;",
+ (void*)nativeGetDesiredDisplayConfigSpecs },
{"nativeGetDisplayColorModes", "(Landroid/os/IBinder;)[I",
(void*)nativeGetDisplayColorModes},
{"nativeGetDisplayNativePrimaries", "(Landroid/os/IBinder;)Landroid/view/SurfaceControl$DisplayPrimaries;",
@@ -1402,6 +1404,14 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
(void*)nativeGetActiveColorMode},
{"nativeSetActiveColorMode", "(Landroid/os/IBinder;I)Z",
(void*)nativeSetActiveColorMode},
+ {"nativeGetAutoLowLatencyModeSupport", "(Landroid/os/IBinder;)Z",
+ (void*)nativeGetAutoLowLatencyModeSupport },
+ {"nativeSetAutoLowLatencyMode", "(Landroid/os/IBinder;Z)V",
+ (void*)nativeSetAutoLowLatencyMode },
+ {"nativeGetGameContentTypeSupport", "(Landroid/os/IBinder;)Z",
+ (void*)nativeGetGameContentTypeSupport },
+ {"nativeSetGameContentType", "(Landroid/os/IBinder;Z)V",
+ (void*)nativeSetGameContentType },
{"nativeGetCompositionDataspaces", "()[I",
(void*)nativeGetCompositionDataspaces},
{"nativeGetHdrCapabilities", "(Landroid/os/IBinder;)Landroid/view/Display$HdrCapabilities;",
@@ -1569,12 +1579,12 @@ int register_android_view_SurfaceControl(JNIEnv* env)
MakeGlobalRefOrDie(env, desiredDisplayConfigSpecsClazz);
gDesiredDisplayConfigSpecsClassInfo.ctor =
GetMethodIDOrDie(env, gDesiredDisplayConfigSpecsClassInfo.clazz, "<init>", "(IFF)V");
- gDesiredDisplayConfigSpecsClassInfo.defaultModeId =
- GetFieldIDOrDie(env, desiredDisplayConfigSpecsClazz, "mDefaultModeId", "I");
+ gDesiredDisplayConfigSpecsClassInfo.defaultConfig =
+ GetFieldIDOrDie(env, desiredDisplayConfigSpecsClazz, "defaultConfig", "I");
gDesiredDisplayConfigSpecsClassInfo.minRefreshRate =
- GetFieldIDOrDie(env, desiredDisplayConfigSpecsClazz, "mMinRefreshRate", "F");
+ GetFieldIDOrDie(env, desiredDisplayConfigSpecsClazz, "minRefreshRate", "F");
gDesiredDisplayConfigSpecsClassInfo.maxRefreshRate =
- GetFieldIDOrDie(env, desiredDisplayConfigSpecsClazz, "mMaxRefreshRate", "F");
+ GetFieldIDOrDie(env, desiredDisplayConfigSpecsClazz, "maxRefreshRate", "F");
return err;
}
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 170e467a72cd..69ca17c08257 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -30,7 +30,7 @@
#include <gui/BufferQueue.h>
#include <gui/Surface.h>
-#include "android_view_FrameMetricsObserver.h"
+#include "android_graphics_HardwareRendererObserver.h"
#include <private/EGL/cache.h>
@@ -580,28 +580,21 @@ static void android_view_ThreadedRenderer_preload(JNIEnv*, jclass) {
}
// ----------------------------------------------------------------------------
-// FrameMetricsObserver
+// HardwareRendererObserver
// ----------------------------------------------------------------------------
-static jlong android_view_ThreadedRenderer_addFrameMetricsObserver(JNIEnv* env,
- jclass clazz, jlong proxyPtr, jobject fso) {
- JavaVM* vm = nullptr;
- if (env->GetJavaVM(&vm) != JNI_OK) {
- LOG_ALWAYS_FATAL("Unable to get Java VM");
- return 0;
- }
-
+static void android_view_ThreadedRenderer_addObserver(JNIEnv* env, jclass clazz,
+ jlong proxyPtr, jlong observerPtr) {
+ HardwareRendererObserver* observer = reinterpret_cast<HardwareRendererObserver*>(observerPtr);
renderthread::RenderProxy* renderProxy =
reinterpret_cast<renderthread::RenderProxy*>(proxyPtr);
- FrameMetricsObserver* observer = new FrameMetricsObserverProxy(vm, fso);
renderProxy->addFrameMetricsObserver(observer);
- return reinterpret_cast<jlong>(observer);
}
-static void android_view_ThreadedRenderer_removeFrameMetricsObserver(JNIEnv* env, jclass clazz,
+static void android_view_ThreadedRenderer_removeObserver(JNIEnv* env, jclass clazz,
jlong proxyPtr, jlong observerPtr) {
- FrameMetricsObserver* observer = reinterpret_cast<FrameMetricsObserver*>(observerPtr);
+ HardwareRendererObserver* observer = reinterpret_cast<HardwareRendererObserver*>(observerPtr);
renderthread::RenderProxy* renderProxy =
reinterpret_cast<renderthread::RenderProxy*>(proxyPtr);
@@ -675,12 +668,8 @@ static const JNINativeMethod gMethods[] = {
(void*)android_view_ThreadedRenderer_setFrameCallback},
{ "nSetFrameCompleteCallback", "(JLandroid/graphics/HardwareRenderer$FrameCompleteCallback;)V",
(void*)android_view_ThreadedRenderer_setFrameCompleteCallback },
- { "nAddFrameMetricsObserver",
- "(JLandroid/view/FrameMetricsObserver;)J",
- (void*)android_view_ThreadedRenderer_addFrameMetricsObserver },
- { "nRemoveFrameMetricsObserver",
- "(JJ)V",
- (void*)android_view_ThreadedRenderer_removeFrameMetricsObserver },
+ { "nAddObserver", "(JJ)V", (void*)android_view_ThreadedRenderer_addObserver },
+ { "nRemoveObserver", "(JJ)V", (void*)android_view_ThreadedRenderer_removeObserver },
{ "nCopySurfaceInto", "(Landroid/view/Surface;IIIIJ)I",
(void*)android_view_ThreadedRenderer_copySurfaceInto },
{ "nCreateHardwareBitmap", "(JII)Landroid/graphics/Bitmap;",
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index c4ac89acd0db..df5b02c22a2d 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -31,6 +31,8 @@
// sys/mount.h has to come before linux/fs.h due to redefinition of MS_RDONLY, MS_BIND, etc
#include <sys/mount.h>
#include <linux/fs.h>
+#include <sys/types.h>
+#include <dirent.h>
#include <array>
#include <atomic>
@@ -40,6 +42,7 @@
#include <sstream>
#include <string>
#include <string_view>
+#include <unordered_set>
#include <android/fdsan.h>
#include <arpa/inet.h>
@@ -51,6 +54,7 @@
#include <mntent.h>
#include <paths.h>
#include <signal.h>
+#include <stdio.h>
#include <stdlib.h>
#include <sys/capability.h>
#include <sys/cdefs.h>
@@ -159,6 +163,17 @@ static std::atomic_uint32_t gUsapPoolCount = 0;
*/
static int gUsapPoolEventFD = -1;
+static constexpr int DEFAULT_DATA_DIR_PERMISSION = 0751;
+
+/**
+ * Property to control if app data isolation is enabled.
+ */
+static const std::string ANDROID_APP_DATA_ISOLATION_ENABLED_PROPERTY =
+ "persist.zygote.app_data_isolation";
+
+static constexpr const uint64_t UPPER_HALF_WORD_MASK = 0xFFFF'FFFF'0000'0000;
+static constexpr const uint64_t LOWER_HALF_WORD_MASK = 0x0000'0000'FFFF'FFFF;
+
/**
* The maximum value that the gUSAPPoolSizeMax variable may take. This value
* is a mirror of ZygoteServer.USAP_POOL_SIZE_MAX_LIMIT
@@ -663,7 +678,7 @@ static int UnmountTree(const char* path) {
return 0;
}
-static void CreateDir(const std::string& dir, mode_t mode, uid_t uid, gid_t gid,
+static void PrepareDir(const std::string& dir, mode_t mode, uid_t uid, gid_t gid,
fail_fn_t fail_fn) {
if (fs_prepare_dir(dir.c_str(), mode, uid, gid) != 0) {
fail_fn(CREATE_ERROR("fs_prepare_dir failed on %s: %s",
@@ -671,6 +686,16 @@ static void CreateDir(const std::string& dir, mode_t mode, uid_t uid, gid_t gid,
}
}
+static void PrepareDirIfNotPresent(const std::string& dir, mode_t mode, uid_t uid, gid_t gid,
+ fail_fn_t fail_fn) {
+ struct stat sb;
+ if (TEMP_FAILURE_RETRY(stat(dir.c_str(), &sb)) != -1) {
+ // Directory exists already
+ return;
+ }
+ PrepareDir(dir, mode, uid, gid, fail_fn);
+}
+
static void BindMount(const std::string& source_dir, const std::string& target_dir,
fail_fn_t fail_fn) {
if (TEMP_FAILURE_RETRY(mount(source_dir.c_str(), target_dir.c_str(), nullptr,
@@ -680,6 +705,15 @@ static void BindMount(const std::string& source_dir, const std::string& target_d
}
}
+static void MountAppDataTmpFs(const std::string& target_dir,
+ fail_fn_t fail_fn) {
+ if (TEMP_FAILURE_RETRY(mount("tmpfs", target_dir.c_str(), "tmpfs",
+ MS_NOSUID | MS_NODEV | MS_NOEXEC, "uid=0,gid=0,mode=0751")) == -1) {
+ fail_fn(CREATE_ERROR("Failed to mount tmpfs to %s: %s",
+ target_dir.c_str(), strerror(errno)));
+ }
+}
+
// Create a private mount namespace and bind mount appropriate emulated
// storage for the given user.
static void MountEmulatedStorage(uid_t uid, jint mount_mode,
@@ -712,11 +746,19 @@ static void MountEmulatedStorage(uid_t uid, jint mount_mode,
const std::string pass_through_source = StringPrintf("/mnt/pass_through/%d", user_id);
bool isFuse = GetBoolProperty(kPropFuse, false);
- CreateDir(user_source, 0751, AID_ROOT, AID_ROOT, fail_fn);
+ PrepareDir(user_source, DEFAULT_DATA_DIR_PERMISSION, AID_ROOT, AID_ROOT, fail_fn);
if (isFuse) {
- BindMount(mount_mode == MOUNT_EXTERNAL_PASS_THROUGH ? pass_through_source : user_source,
- "/storage", fail_fn);
+ if (mount_mode == MOUNT_EXTERNAL_PASS_THROUGH || mount_mode ==
+ MOUNT_EXTERNAL_INSTALLER || mount_mode == MOUNT_EXTERNAL_FULL) {
+ // For now, MediaProvider, installers and "full" get the pass_through mount
+ // view, which is currently identical to the sdcardfs write view.
+ //
+ // TODO(b/146189163): scope down MOUNT_EXTERNAL_INSTALLER
+ BindMount(pass_through_source, "/storage", fail_fn);
+ } else {
+ BindMount(user_source, "/storage", fail_fn);
+ }
} else {
const std::string& storage_source = ExternalStorageViews[mount_mode];
BindMount(storage_source, "/storage", fail_fn);
@@ -1008,6 +1050,231 @@ static pid_t ForkCommon(JNIEnv* env, bool is_system_server,
return pid;
}
+// Create an app data directory over tmpfs overlayed CE / DE storage, and bind mount it
+// from the actual app data directory in data mirror.
+static void createAndMountAppData(std::string_view package_name,
+ std::string_view mirror_pkg_dir_name, std::string_view mirror_data_path,
+ std::string_view actual_data_path, fail_fn_t fail_fn) {
+
+ char mirrorAppDataPath[PATH_MAX];
+ char actualAppDataPath[PATH_MAX];
+ snprintf(mirrorAppDataPath, PATH_MAX, "%s/%s", mirror_data_path.data(),
+ mirror_pkg_dir_name.data());
+ snprintf(actualAppDataPath, PATH_MAX, "%s/%s", actual_data_path.data(), package_name.data());
+
+ PrepareDir(actualAppDataPath, 0700, AID_ROOT, AID_ROOT, fail_fn);
+
+ // Bind mount from original app data directory in mirror.
+ BindMount(mirrorAppDataPath, actualAppDataPath, fail_fn);
+}
+
+// Get the directory name stored in /data/data. If device is unlocked it should be the same as
+// package name, otherwise it will be an encrypted name but with same inode number.
+static std::string getAppDataDirName(std::string_view parent_path, std::string_view package_name,
+ long long ce_data_inode, fail_fn_t fail_fn) {
+ // Check if directory exists
+ char tmpPath[PATH_MAX];
+ snprintf(tmpPath, PATH_MAX, "%s/%s", parent_path.data(), package_name.data());
+ struct stat s;
+ int err = stat(tmpPath, &s);
+ if (err == 0) {
+ // Directory exists, so return the directory name
+ return package_name.data();
+ } else {
+ if (errno != ENOENT) {
+ fail_fn(CREATE_ERROR("Unexpected error in getAppDataDirName: %s", strerror(errno)));
+ return nullptr;
+ }
+ // Directory doesn't exist, try to search the name from inode
+ DIR* dir = opendir(parent_path.data());
+ if (dir == nullptr) {
+ fail_fn(CREATE_ERROR("Failed to opendir %s", parent_path.data()));
+ }
+ struct dirent* ent;
+ while ((ent = readdir(dir))) {
+ if (ent->d_ino == ce_data_inode) {
+ closedir(dir);
+ return ent->d_name;
+ }
+ }
+ closedir(dir);
+
+ // Fallback due to b/145989852, ce_data_inode stored in package manager may be corrupted
+ // if ino_t is 32 bits.
+ ino_t fixed_ce_data_inode = 0;
+ if ((ce_data_inode & UPPER_HALF_WORD_MASK) == UPPER_HALF_WORD_MASK) {
+ fixed_ce_data_inode = ce_data_inode & LOWER_HALF_WORD_MASK;
+ } else if ((ce_data_inode & LOWER_HALF_WORD_MASK) == LOWER_HALF_WORD_MASK) {
+ fixed_ce_data_inode = ((ce_data_inode >> 32) & LOWER_HALF_WORD_MASK);
+ }
+ if (fixed_ce_data_inode != 0) {
+ dir = opendir(parent_path.data());
+ if (dir == nullptr) {
+ fail_fn(CREATE_ERROR("Failed to opendir %s", parent_path.data()));
+ }
+ while ((ent = readdir(dir))) {
+ if (ent->d_ino == fixed_ce_data_inode) {
+ long long d_ino = ent->d_ino;
+ ALOGW("Fallback success inode %lld -> %lld", ce_data_inode, d_ino);
+ closedir(dir);
+ return ent->d_name;
+ }
+ }
+ closedir(dir);
+ }
+ // Fallback done
+
+ fail_fn(CREATE_ERROR("Unable to find %s:%lld in %s", package_name.data(),
+ ce_data_inode, parent_path.data()));
+ return nullptr;
+ }
+}
+
+// Isolate app's data directory, by mounting a tmpfs on CE DE storage,
+// and create and bind mount app data in related_packages.
+static void isolateAppDataPerPackage(int userId, std::string_view package_name,
+ std::string_view volume_uuid, long long ce_data_inode, std::string_view actualCePath,
+ std::string_view actualDePath, fail_fn_t fail_fn) {
+
+ char mirrorCePath[PATH_MAX];
+ char mirrorDePath[PATH_MAX];
+ char mirrorCeParent[PATH_MAX];
+ snprintf(mirrorCeParent, PATH_MAX, "/data_mirror/data_ce/%s", volume_uuid.data());
+ snprintf(mirrorCePath, PATH_MAX, "%s/%d", mirrorCeParent, userId);
+ snprintf(mirrorDePath, PATH_MAX, "/data_mirror/data_de/%s/%d", volume_uuid.data(), userId);
+
+ createAndMountAppData(package_name, package_name, mirrorDePath, actualDePath, fail_fn);
+
+ std::string ce_data_path = getAppDataDirName(mirrorCePath, package_name, ce_data_inode, fail_fn);
+ createAndMountAppData(package_name, ce_data_path, mirrorCePath, actualCePath, fail_fn);
+}
+
+/**
+ * Make other apps data directory not visible in CE, DE storage.
+ *
+ * Apps without app data isolation can detect if another app is installed on system,
+ * by "touching" other apps data directory like /data/data/com.whatsapp, if it returns
+ * "Permission denied" it means apps installed, otherwise it returns "File not found".
+ * Traditional file permissions or SELinux can only block accessing those directories but
+ * can't fix fingerprinting like this.
+ * We fix it by "overlaying" data directory, and only relevant app data packages exists
+ * in data directories.
+ *
+ * Steps:
+ * 1). Collect a list of all related apps (apps with same uid and whitelisted apps) data info
+ * (package name, data stored volume uuid, and inode number of its CE data directory)
+ * 2). Mount tmpfs on /data/data, /data/user(_de) and /mnt/expand, so apps no longer
+ * able to access apps data directly.
+ * 3). For each related app, create its app data directory and bind mount the actual content
+ * from apps data mirror directory. This works on both CE and DE storage, as DE storage
+ * is always available even storage is FBE locked, while we use inode number to find
+ * the encrypted DE directory in mirror so we can still bind mount it successfully.
+ *
+ * Example:
+ * 0). Assuming com.android.foo CE data is stored in /data/data and no shared uid
+ * 1). Mount a tmpfs on /data/data, /data/user, /data/user_de, /mnt/expand
+ * List = ["com.android.foo", "null" (volume uuid "null"=default),
+ * 123456 (inode number)]
+ * 2). On DE storage, we create a directory /data/user_de/0/com.com.android.foo, and bind
+ * mount (in the app's mount namespace) it from /data_mirror/data_de/0/com.android.foo.
+ * 3). We do similar for CE storage. But in direct boot mode, as /data_mirror/data_ce/0/ is
+ * encrypted, we can't find a directory with name com.android.foo on it, so we will
+ * use the inode number to find the right directory instead, which that directory content will
+ * be decrypted after storage is decrypted.
+ *
+ */
+static void isolateAppData(JNIEnv* env, jobjectArray pkg_data_info_list,
+ uid_t uid, const char* process_name, jstring managed_nice_name,
+ fail_fn_t fail_fn) {
+
+ const userid_t userId = multiuser_get_user_id(uid);
+
+ auto extract_fn = std::bind(ExtractJString, env, process_name, managed_nice_name, _1);
+
+ int size = (pkg_data_info_list != nullptr) ? env->GetArrayLength(pkg_data_info_list) : 0;
+ // Size should be a multiple of 3, as it contains list of <package_name, volume_uuid, inode>
+ if ((size % 3) != 0) {
+ fail_fn(CREATE_ERROR("Wrong pkg_inode_list size %d", size));
+ }
+
+ // Mount tmpfs on all possible data directories, so app no longer see the original apps data.
+ char internalCePath[PATH_MAX];
+ char internalLegacyCePath[PATH_MAX];
+ char internalDePath[PATH_MAX];
+ char externalPrivateMountPath[PATH_MAX];
+
+ snprintf(internalCePath, PATH_MAX, "/data/user");
+ snprintf(internalLegacyCePath, PATH_MAX, "/data/data");
+ snprintf(internalDePath, PATH_MAX, "/data/user_de");
+ snprintf(externalPrivateMountPath, PATH_MAX, "/mnt/expand");
+
+ MountAppDataTmpFs(internalLegacyCePath, fail_fn);
+ MountAppDataTmpFs(internalCePath, fail_fn);
+ MountAppDataTmpFs(internalDePath, fail_fn);
+ MountAppDataTmpFs(externalPrivateMountPath, fail_fn);
+
+ for (int i = 0; i < size; i += 3) {
+ jstring package_str = (jstring) (env->GetObjectArrayElement(pkg_data_info_list, i));
+ std::string packageName = extract_fn(package_str).value();
+
+ jstring vol_str = (jstring) (env->GetObjectArrayElement(pkg_data_info_list, i + 1));
+ std::string volUuid = extract_fn(vol_str).value();
+
+ jstring inode_str = (jstring) (env->GetObjectArrayElement(pkg_data_info_list, i + 2));
+ std::string inode = extract_fn(inode_str).value();
+ std::string::size_type sz;
+ long long ceDataInode = std::stoll(inode, &sz);
+
+ std::string actualCePath, actualDePath;
+ if (volUuid.compare("null") != 0) {
+ // Volume that is stored in /mnt/expand
+ char volPath[PATH_MAX];
+ char volCePath[PATH_MAX];
+ char volDePath[PATH_MAX];
+ char volCeUserPath[PATH_MAX];
+ char volDeUserPath[PATH_MAX];
+
+ snprintf(volPath, PATH_MAX, "/mnt/expand/%s", volUuid.c_str());
+ snprintf(volCePath, PATH_MAX, "%s/user", volPath);
+ snprintf(volDePath, PATH_MAX, "%s/user_de", volPath);
+ snprintf(volCeUserPath, PATH_MAX, "%s/%d", volCePath, userId);
+ snprintf(volDeUserPath, PATH_MAX, "%s/%d", volDePath, userId);
+
+ PrepareDirIfNotPresent(volPath, DEFAULT_DATA_DIR_PERMISSION, AID_ROOT, AID_ROOT, fail_fn);
+ PrepareDirIfNotPresent(volCePath, DEFAULT_DATA_DIR_PERMISSION, AID_ROOT, AID_ROOT, fail_fn);
+ PrepareDirIfNotPresent(volDePath, DEFAULT_DATA_DIR_PERMISSION, AID_ROOT, AID_ROOT, fail_fn);
+ PrepareDirIfNotPresent(volCeUserPath, DEFAULT_DATA_DIR_PERMISSION, AID_ROOT, AID_ROOT,
+ fail_fn);
+ PrepareDirIfNotPresent(volDeUserPath, DEFAULT_DATA_DIR_PERMISSION, AID_ROOT, AID_ROOT,
+ fail_fn);
+
+ actualCePath = volCeUserPath;
+ actualDePath = volDeUserPath;
+ } else {
+ // Internal volume that stored in /data
+ char internalCeUserPath[PATH_MAX];
+ char internalDeUserPath[PATH_MAX];
+ snprintf(internalCeUserPath, PATH_MAX, "/data/user/%d", userId);
+ snprintf(internalDeUserPath, PATH_MAX, "/data/user_de/%d", userId);
+ // If it's user 0, create a symlink /data/user/0 -> /data/data,
+ // otherwise create /data/user/$USER
+ if (userId == 0) {
+ symlink(internalLegacyCePath, internalCeUserPath);
+ actualCePath = internalLegacyCePath;
+ } else {
+ PrepareDirIfNotPresent(internalCeUserPath, DEFAULT_DATA_DIR_PERMISSION,
+ AID_ROOT, AID_ROOT, fail_fn);
+ actualCePath = internalCeUserPath;
+ }
+ PrepareDirIfNotPresent(internalDeUserPath, DEFAULT_DATA_DIR_PERMISSION,
+ AID_ROOT, AID_ROOT, fail_fn);
+ actualDePath = internalDeUserPath;
+ }
+ isolateAppDataPerPackage(userId, packageName, volUuid, ceDataInode,
+ actualCePath, actualDePath, fail_fn);
+ }
+}
+
// Utility routine to specialize a zygote child process.
static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids,
jint runtime_flags, jobjectArray rlimits,
@@ -1015,7 +1282,8 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids,
jint mount_external, jstring managed_se_info,
jstring managed_nice_name, bool is_system_server,
bool is_child_zygote, jstring managed_instruction_set,
- jstring managed_app_data_dir, bool is_top_app) {
+ jstring managed_app_data_dir, bool is_top_app,
+ jobjectArray pkg_data_info_list) {
const char* process_name = is_system_server ? "system_server" : "zygote";
auto fail_fn = std::bind(ZygoteFailure, env, process_name, managed_nice_name, _1);
auto extract_fn = std::bind(ExtractJString, env, process_name, managed_nice_name, _1);
@@ -1051,6 +1319,16 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids,
MountEmulatedStorage(uid, mount_external, use_native_bridge, fail_fn);
+ // System services, isolated process, webview/app zygote, old target sdk app, should
+ // give a null in same_uid_pkgs and private_volumes so they don't need app data isolation.
+ // Isolated process / webview / app zygote should be gated by SELinux and file permission
+ // so they can't even traverse CE / DE directories.
+ if (pkg_data_info_list != nullptr
+ && GetBoolProperty(ANDROID_APP_DATA_ISOLATION_ENABLED_PROPERTY, false)) {
+ isolateAppData(env, pkg_data_info_list, uid, process_name, managed_nice_name,
+ fail_fn);
+ }
+
// If this zygote isn't root, it won't be able to create a process group,
// since the directory is owned by root.
if (!is_system_server && getuid() == 0) {
@@ -1417,7 +1695,8 @@ static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(
jint runtime_flags, jobjectArray rlimits,
jint mount_external, jstring se_info, jstring nice_name,
jintArray managed_fds_to_close, jintArray managed_fds_to_ignore, jboolean is_child_zygote,
- jstring instruction_set, jstring app_data_dir, jboolean is_top_app) {
+ jstring instruction_set, jstring app_data_dir, jboolean is_top_app,
+ jobjectArray pkg_data_info_list) {
jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote);
if (UNLIKELY(managed_fds_to_close == nullptr)) {
@@ -1449,7 +1728,7 @@ static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(
capabilities, capabilities,
mount_external, se_info, nice_name, false,
is_child_zygote == JNI_TRUE, instruction_set, app_data_dir,
- is_top_app == JNI_TRUE);
+ is_top_app == JNI_TRUE, pkg_data_info_list);
}
return pid;
}
@@ -1473,10 +1752,13 @@ static jint com_android_internal_os_Zygote_nativeForkSystemServer(
fds_to_ignore,
true);
if (pid == 0) {
+ // System server prcoess does not need data isolation so no need to
+ // know pkg_data_info_list.
SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,
permitted_capabilities, effective_capabilities,
MOUNT_EXTERNAL_DEFAULT, nullptr, nullptr, true,
- false, nullptr, nullptr, /* is_top_app= */ false);
+ false, nullptr, nullptr, /* is_top_app= */ false,
+ /* pkg_data_info_list */ nullptr);
} else if (pid > 0) {
// The zygote process checks whether the child process has died or not.
ALOGI("System server process %d has been created", pid);
@@ -1599,14 +1881,15 @@ static void com_android_internal_os_Zygote_nativeSpecializeAppProcess(
JNIEnv* env, jclass, jint uid, jint gid, jintArray gids,
jint runtime_flags, jobjectArray rlimits,
jint mount_external, jstring se_info, jstring nice_name,
- jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir, jboolean is_top_app) {
+ jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir, jboolean is_top_app,
+ jobjectArray pkg_data_info_list) {
jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote);
SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,
capabilities, capabilities,
mount_external, se_info, nice_name, false,
is_child_zygote == JNI_TRUE, instruction_set, app_data_dir,
- is_top_app == JNI_TRUE);
+ is_top_app == JNI_TRUE, pkg_data_info_list);
}
/**
@@ -1767,7 +2050,7 @@ static void com_android_internal_os_Zygote_nativeBoostUsapPriority(JNIEnv* env,
static const JNINativeMethod gMethods[] = {
{ "nativeForkAndSpecialize",
- "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;Z)I",
+ "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;Z[Ljava/lang/String;)I",
(void *) com_android_internal_os_Zygote_nativeForkAndSpecialize },
{ "nativeForkSystemServer", "(II[II[[IJJ)I",
(void *) com_android_internal_os_Zygote_nativeForkSystemServer },
@@ -1780,7 +2063,7 @@ static const JNINativeMethod gMethods[] = {
{ "nativeForkUsap", "(II[IZ)I",
(void *) com_android_internal_os_Zygote_nativeForkUsap },
{ "nativeSpecializeAppProcess",
- "(II[II[[IILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;Z)V",
+ "(II[II[[IILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;Z[Ljava/lang/String;)V",
(void *) com_android_internal_os_Zygote_nativeSpecializeAppProcess },
{ "nativeInitNativeState", "(Z)V",
(void *) com_android_internal_os_Zygote_nativeInitNativeState },
diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp
index 8c1ecae67401..5624f457a9b2 100644
--- a/core/jni/fd_utils.cpp
+++ b/core/jni/fd_utils.cpp
@@ -37,11 +37,11 @@ static const char* kPathWhitelist[] = {
"/apex/com.android.conscrypt/javalib/conscrypt.jar",
"/apex/com.android.ipsec/javalib/ike.jar",
"/apex/com.android.media/javalib/updatable-media.jar",
+ "/apex/com.android.mediaprovider/javalib/framework-mediaprovider.jar",
"/apex/com.android.os.statsd/javalib/framework-statsd.jar",
"/apex/com.android.sdkext/javalib/framework-sdkext.jar",
- "/apex/com.android.telephony/javalib/telephony-common.jar",
- "/apex/com.android.telephony/javalib/ims-common.jar",
"/apex/com.android.wifi/javalib/framework-wifi.jar",
+ "/apex/com.android.tethering/javalib/framework-tethering.jar",
"/dev/null",
"/dev/socket/zygote",
"/dev/socket/zygote_secondary",
diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto
index e3e07de3556e..d5a3b5e91151 100644
--- a/core/proto/android/app/settings_enums.proto
+++ b/core/proto/android/app/settings_enums.proto
@@ -251,6 +251,9 @@ enum Action {
// ACTION: Create a Settings shortcut item.
ACTION_SETTINGS_CREATE_SHORTCUT = 829;
+ // ACTION: A tile in Settings information architecture is clicked
+ ACTION_SETTINGS_TILE_CLICK = 830;
+
// ACTION: Settings advanced button is expanded
ACTION_SETTINGS_ADVANCED_BUTTON_EXPAND = 834;
@@ -713,7 +716,7 @@ enum PageId {
// OS: 6.0
ACCESSIBILITY = 2;
- // OPEN: Settings > Accessibility > Captions
+ // OPEN: Settings > Accessibility > Captions preference
// CATEGORY: SETTINGS
// OS: 6.0
ACCESSIBILITY_CAPTION_PROPERTIES = 3;
@@ -2477,4 +2480,66 @@ enum PageId {
// CATEGORY: SETTINGS
// OS: R
PANEL_ADD_WIFI_NETWORKS = 1809;
+
+ // OPEN: Settings > Accessibility > Enable accessibility service > Show tutorial dialog
+ // CATEGORY: SETTINGS
+ // OS: R
+ DIALOG_TOGGLE_SCREEN_ACCESSIBILITY_BUTTON = 1810;
+
+ // OPEN: Settings > Accessibility > Enable accessibility service > Show tutorial dialog in
+ // gesture mode
+ // CATEGORY: SETTINGS
+ // OS: R
+ DIALOG_TOGGLE_SCREEN_GESTURE_NAVIGATION = 1811;
+
+ // OPEN: Settings > Accessibility > Edit shortcut dialog
+ // CATEGORY: SETTINGS
+ // OS: R
+ DIALOG_ACCESSIBILITY_SERVICE_EDIT_SHORTCUT = 1812;
+
+ // OPEN: Settings > Accessibility > Magnification > Edit shortcut dialog
+ // CATEGORY: SETTINGS
+ // OS: R
+ DIALOG_MAGNIFICATION_EDIT_SHORTCUT = 1813;
+
+ // OPEN: Settings > Accessibility > Color correction > Edit shortcut dialog
+ // CATEGORY: SETTINGS
+ // OS: R
+ DIALOG_DALTONIZER_EDIT_SHORTCUT = 1814;
+
+ // OPEN: Settings > Accessibility > Magnification > Settings
+ // CATEGORY: SETTINGS
+ // OS: R
+ ACCESSIBILITY_MAGNIFICATION_SETTINGS = 1815;
+
+ // OPEN: Settings > Accessibility > Magnification > Settings > Magnification area dialog
+ // CATEGORY: SETTINGS
+ // OS: R
+ DIALOG_MAGNIFICATION_CAPABILITY = 1816;
+
+ // OPEN: Settings > Accessibility > Color inversion
+ // CATEGORY: SETTINGS
+ // OS: R
+ ACCESSIBILITY_COLOR_INVERSION_SETTINGS = 1817;
+
+ // OPEN: Settings > Accessibility > Color inversion > Edit shortcut dialog
+ // CATEGORY: SETTINGS
+ // OS: R
+ DIALOG_COLOR_INVERSION_EDIT_SHORTCUT = 1818;
+
+ // OPEN: Settings > Accessibility > Captions preference > Captions appearance
+ // CATEGORY: SETTINGS
+ // OS: R
+ ACCESSIBILITY_CAPTION_APPEARANCE = 1819;
+
+ // OPEN: Settings > Accessibility > Captions preference > More options
+ // CATEGORY: SETTINGS
+ // OS: R
+ ACCESSIBILITY_CAPTION_MORE_OPTIONS = 1820;
+
+ // OPEN: Settings > Battery > Battery share
+ // CATEGORY: SETTINGS
+ // OS: R
+ FUELGAUGE_BATTERY_SHARE = 1821;
+
}
diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto
index 6a1ec6c849c8..7835016439e0 100644
--- a/core/proto/android/providers/settings/secure.proto
+++ b/core/proto/android/providers/settings/secure.proto
@@ -75,6 +75,8 @@ message SecureSettingsProto {
// Settings for accessibility timeout
optional SettingProto non_interactive_ui_timeout_ms = 32 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto interactive_ui_timeout_ms = 33 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Settings for magnification mode
+ optional SettingProto accessibility_magnification_mode = 34 [ (android.privacy).dest = DEST_AUTOMATIC ];
}
optional Accessibility accessibility = 2;
diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto
index 9f31b590cf77..c79f314ffaf2 100644
--- a/core/proto/android/server/activitymanagerservice.proto
+++ b/core/proto/android/server/activitymanagerservice.proto
@@ -60,7 +60,7 @@ message ActivityManagerServiceDumpActivitiesProto {
message ActivityStackSupervisorProto {
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
- optional .com.android.server.wm.ConfigurationContainerProto configuration_container = 1;
+ optional .com.android.server.wm.ConfigurationContainerProto configuration_container = 1 [deprecated=true];
repeated ActivityDisplayProto displays = 2;
optional KeyguardControllerProto keyguard_controller = 3;
// TODO(b/111541062): Focused stack and resumed activity are now per-display. Topmost instances
@@ -71,6 +71,7 @@ message ActivityStackSupervisorProto {
// know what activity types to check for when invoking splitscreen multi-window.
optional bool is_home_recents_component = 6;
repeated .com.android.server.wm.IdentifierProto pending_activities = 7;
+ optional .com.android.server.wm.RootWindowContainerProto root_window_container = 8;
}
/* represents ActivityStackSupervisor.ActivityDisplay */
diff --git a/core/proto/android/stats/docsui/docsui_enums.proto b/core/proto/android/stats/docsui/docsui_enums.proto
index f648912d36eb..5963f6a7f938 100644
--- a/core/proto/android/stats/docsui/docsui_enums.proto
+++ b/core/proto/android/stats/docsui/docsui_enums.proto
@@ -56,6 +56,7 @@ enum Root {
ROOT_VIDEOS = 9;
ROOT_MTP = 10;
ROOT_THIRD_PARTY_APP = 11;
+ ROOT_DOCUMENTS = 12;
}
enum ContextScope {
diff --git a/core/proto/android/util/quotatracker.proto b/core/proto/android/util/quotatracker.proto
index 0dea853b0986..5d022ed6327b 100644
--- a/core/proto/android/util/quotatracker.proto
+++ b/core/proto/android/util/quotatracker.proto
@@ -34,17 +34,25 @@ message QuotaTrackerProto {
// Current elapsed realtime.
optional int64 elapsed_realtime = 3;
- message AlarmListener {
+ message InQuotaAlarmListener {
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
- // Whether the listener is waiting for an alarm or not.
- optional bool is_waiting = 1;
- // The time at which the alarm should go off, in the elapsed realtime timebase. Only
- // valid if is_waiting is true.
- optional int64 trigger_time_elapsed = 2;
+ // The time at which the alarm is set to go off, in the elapsed realtime timebase.
+ optional int64 trigger_time_elapsed = 1;
+
+ message Alarm {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
+ optional UptcProto uptc = 1;
+
+ // The time at which the UPTC will be in quota, in the elapsed realtime timebase.
+ optional int64 in_quota_time_elapsed = 2;
+ }
+ repeated Alarm alarms = 2;
}
+ optional InQuotaAlarmListener in_quota_alarm_listener = 4;
- // Next tag: 4
+ // Next tag: 5
}
// A com.android.util.quota.Category object.
@@ -118,8 +126,6 @@ message CountQuotaTrackerProto {
repeated Event events = 3;
repeated ExecutionStats execution_stats = 4;
-
- optional QuotaTrackerProto.AlarmListener in_quota_alarm_listener = 5;
}
repeated UptcStats uptc_stats = 3;
@@ -195,8 +201,6 @@ message DurationQuotaTrackerProto {
repeated TimingSession saved_sessions = 4;
repeated ExecutionStats execution_stats = 5;
-
- optional QuotaTrackerProto.AlarmListener in_quota_alarm_listener = 6;
}
repeated UptcStats uptc_stats = 3;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index cb5b4a595ac3..7719165aa402 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -307,6 +307,7 @@
<protected-broadcast android:name="android.net.nsd.STATE_CHANGED" />
<protected-broadcast android:name="android.nfc.action.ADAPTER_STATE_CHANGED" />
+ <protected-broadcast android:name="android.nfc.action.PREFERRED_PAYMENT_CHANGED" />
<protected-broadcast android:name="android.nfc.action.TRANSACTION_DETECTED" />
<protected-broadcast android:name="com.android.nfc.action.LLCP_UP" />
<protected-broadcast android:name="com.android.nfc.action.LLCP_DOWN" />
@@ -346,6 +347,10 @@
<protected-broadcast android:name="com.android.server.am.DELETE_DUMPHEAP" />
<protected-broadcast android:name="com.android.server.net.action.SNOOZE_WARNING" />
<protected-broadcast android:name="com.android.server.net.action.SNOOZE_RAPID" />
+ <protected-broadcast android:name="com.android.server.wifi.ACTION_SHOW_SET_RANDOMIZATION_DETAILS" />
+ <protected-broadcast android:name="com.android.server.wifi.action.NetworkSuggestion.USER_ALLOWED_APP" />
+ <protected-broadcast android:name="com.android.server.wifi.action.NetworkSuggestion.USER_DISALLOWED_APP" />
+ <protected-broadcast android:name="com.android.server.wifi.action.NetworkSuggestion.USER_DISMISSED" />
<protected-broadcast android:name="com.android.server.wifi.ConnectToNetworkNotification.USER_DISMISSED_NOTIFICATION" />
<protected-broadcast android:name="com.android.server.wifi.ConnectToNetworkNotification.CONNECT_TO_NETWORK" />
<protected-broadcast android:name="com.android.server.wifi.ConnectToNetworkNotification.PICK_WIFI_NETWORK" />
@@ -637,7 +642,7 @@
<!-- NETWORK_SET_TIME moved from com.android.phone to system server. It should ultimately be
removed. -->
- <protected-broadcast android:name="android.intent.action.NETWORK_SET_TIME" />
+ <protected-broadcast android:name="android.telephony.action.NETWORK_SET_TIME" />
<!-- For tether entitlement recheck-->
<protected-broadcast
@@ -721,6 +726,11 @@
<!-- ====================================================================== -->
<eat-comment />
+ <!-- @SystemApi Allows accessing the messages on ICC
+ @hide Used internally. -->
+ <permission android:name="android.permission.ACCESS_MESSAGES_ON_ICC"
+ android:protectionLevel="signature|telephony" />
+
<!-- Used for runtime permissions related to user's SMS messages. -->
<permission-group android:name="android.permission-group.SMS"
android:icon="@drawable/perm_group_sms"
@@ -1629,6 +1639,14 @@
<permission android:name="android.permission.NETWORK_SETTINGS"
android:protectionLevel="signature|telephony" />
+ <!-- Allows holder to request bluetooth/wifi scan bypassing global "use location" setting and
+ location permissions.
+ <p>Not for use by third-party or privileged applications.
+ @hide
+ -->
+ <permission android:name="android.permission.RADIO_SCAN_WITHOUT_LOCATION"
+ android:protectionLevel="signature|companion" />
+
<!-- Allows SetupWizard to call methods in Networking services
<p>Not for use by any other third-party or privileged applications.
@SystemApi
@@ -1749,6 +1767,14 @@
<p>Protection level: normal
-->
<permission android:name="android.permission.NFC_TRANSACTION_EVENT"
+ android:protectionLevel="normal" />
+
+ <!-- Allows applications to receive NFC preferred payment service information.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.NFC_PREFERRED_PAYMENT_INFO"
+ android:description="@string/permdesc_preferredPaymentInfo"
+ android:label="@string/permlab_preferredPaymentInfo"
android:protectionLevel="normal" />
<!-- @deprecated This permission used to allow too broad access to sensitive methods and all its
@@ -1850,6 +1876,13 @@
android:description="@string/permdesc_vibrate"
android:protectionLevel="normal|instant" />
+ <!-- Allows access to the vibrator always-on settings.
+ <p>Protection level: signature
+ @hide
+ -->
+ <permission android:name="android.permission.VIBRATE_ALWAYS_ON"
+ android:protectionLevel="signature" />
+
<!-- Allows using PowerManager WakeLocks to keep processor from sleeping or screen
from dimming.
<p>Protection level: normal
@@ -2201,6 +2234,17 @@
<permission android:name="android.permission.MANAGE_DOCUMENTS"
android:protectionLevel="signature|documenter" />
+ <!-- Allows an application to manage access to crates, usually as part
+ of a crates picker.
+ <p>This permission should <em>only</em> be requested by the platform
+ management app. This permission cannot be granted to
+ third-party apps.
+ @hide
+ @TestApi
+ -->
+ <permission android:name="android.permission.MANAGE_CRATES"
+ android:protectionLevel="signature" />
+
<!-- @hide Allows an application to cache content.
<p>Not for use by third-party applications.
-->
@@ -2926,6 +2970,14 @@
<permission android:name="android.permission.BIND_QUICK_SETTINGS_TILE"
android:protectionLevel="signature" />
+ <!-- Allows SystemUI to request third party controls.
+ <p>Should only be requested by the System and required by
+ ControlsService declarations.
+ @hide
+ -->
+ <permission android:name="android.permission.BIND_CONTROLS"
+ android:protectionLevel="signature" />
+
<!-- @SystemApi Allows an application to force a BACK operation on whatever is the
top activity.
<p>Not for use by third-party applications.
@@ -4070,7 +4122,7 @@
<permission android:name="android.permission.INTENT_FILTER_VERIFICATION_AGENT"
android:protectionLevel="signature|privileged" />
- <!-- Must be required by intent filter verifier receiver, to ensure that only the
+ <!-- Must be required by intent filter verifier rintent-filtereceiver, to ensure that only the
system can interact with it.
@hide
-->
@@ -4689,6 +4741,12 @@
<permission android:name="android.permission.PEEK_DROPBOX_DATA"
android:protectionLevel="signature" />
+ <!-- @SystemApi Allows an application to access TV tuner HAL
+ <p>Not for use by third-party applications.
+ @hide -->
+ <permission android:name="android.permission.ACCESS_TV_TUNER"
+ android:protectionLevel="signature|privileged" />
+
<application android:process="system"
android:persistent="true"
android:hasCode="false"
@@ -4719,7 +4777,7 @@
</activity>
<activity android:name="com.android.internal.app.AccessibilityButtonChooserActivity"
android:exported="false"
- android:theme="@style/Theme.DeviceDefault.Resolver"
+ android:theme="@style/Theme.DeviceDefault.Dialog.Alert.DayNight"
android:finishOnCloseSystemDialogs="true"
android:excludeFromRecents="true"
android:documentLaunchMode="never"
@@ -5094,6 +5152,12 @@
android:permission="android.permission.BIND_JOB_SERVICE" >
</service>
-</application>
+ <service android:name="com.android.server.pm.PackageManagerShellCommandDataLoader">
+ <intent-filter>
+ <action android:name="android.intent.action.LOAD_DATA" />
+ </intent-filter>
+ </service>
+
+ </application>
</manifest>
diff --git a/core/res/res/layout/accessibility_button_chooser.xml b/core/res/res/layout/accessibility_button_chooser.xml
deleted file mode 100644
index 383780a3ccde..000000000000
--- a/core/res/res/layout/accessibility_button_chooser.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-* Copyright 2017, The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT 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.internal.widget.ResolverDrawerLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:maxWidth="@dimen/resolver_max_width"
- android:maxCollapsedHeight="256dp"
- android:maxCollapsedHeightSmall="56dp"
- android:id="@id/contentPanel">
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alwaysShow="true"
- android:orientation="vertical"
- android:background="?attr/colorBackground"
- android:paddingTop="8dp"
- android:paddingBottom="8dp"
- android:paddingStart="?attr/dialogPreferredPadding"
- android:paddingEnd="?attr/dialogPreferredPadding">
-
- <TextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:minHeight="56dp"
- android:id="@+id/accessibility_button_prompt_prologue"
- android:textAppearance="?attr/textAppearanceMedium"
- android:text="@string/accessibility_button_prompt_text"
- android:gravity="start|center_vertical"
- android:layout_alignParentStart="true"
- android:paddingTop="8dp"
- android:paddingBottom="8dp"/>
-
- <GridView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:id="@+id/accessibility_button_chooser_grid"
- android:columnWidth="90dp"
- android:numColumns="auto_fit"
- android:verticalSpacing="10dp"
- android:horizontalSpacing="10dp"
- android:stretchMode="columnWidth"
- android:gravity="center"/>
-
- <TextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:id="@+id/accessibility_button_prompt"
- android:textAppearance="?attr/textAppearanceMedium"
- android:text="@string/accessibility_button_instructional_text"
- android:gravity="start|center_vertical"
- android:paddingTop="8dp"
- android:paddingBottom="8dp"
- android:visibility="gone"/>
- </LinearLayout>
-</com.android.internal.widget.ResolverDrawerLayout>
diff --git a/core/res/res/layout/accessibility_button_chooser_item.xml b/core/res/res/layout/accessibility_button_chooser_item.xml
index 76a93083bd3e..fddca5aa0531 100644
--- a/core/res/res/layout/accessibility_button_chooser_item.xml
+++ b/core/res/res/layout/accessibility_button_chooser_item.xml
@@ -16,37 +16,28 @@
** limitations under the License.
*/
-->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:minWidth="80dp"
- android:gravity="center"
- android:paddingTop="8dp"
- android:paddingBottom="8dp"
- android:background="?attr/selectableItemBackgroundBorderless">
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:paddingBottom="12dp"
+ android:paddingEnd="16dp"
+ android:paddingStart="16dp"
+ android:paddingTop="12dp">
- <ImageView android:id="@+id/accessibility_button_target_icon"
- android:layout_width="48dp"
- android:layout_height="48dp"
- android:layout_marginLeft="3dp"
- android:layout_marginRight="3dp"
- android:layout_marginBottom="3dp"
- android:scaleType="fitCenter"/>
+ <ImageView
+ android:id="@+id/accessibility_button_target_icon"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:scaleType="fitCenter"/>
- <TextView android:id="@+id/accessibility_button_target_label"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
- android:layout_marginLeft="4dp"
- android:layout_marginRight="4dp"
- android:textAppearance="?attr/textAppearanceSmall"
- android:textColor="?attr/textColorPrimary"
- android:textSize="12sp"
- android:fontFamily="sans-serif-condensed"
- android:gravity="top|center_horizontal"
- android:minLines="2"
- android:maxLines="2"
- android:ellipsize="marquee"/>
+ <TextView
+ android:id="@+id/accessibility_button_target_label"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="8dp"
+ android:layout_weight="1"
+ android:textColor="?attr/textColorPrimary"/>
</LinearLayout>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 4acdeeb29b46..3dd5651c6e96 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Die werkprofiel se administrasieprogram ontbreek of is korrup. Gevolglik is jou werkprofiel en verwante data uitgevee. Kontak jou administrateur vir bystand."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Jou werkprofiel is nie meer op hierdie toestel beskikbaar nie"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Te veel wagwoordpogings"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Administrateur het toestel vir persoonlike gebruik afgestaan"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Toestel word bestuur"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Jou organisasie bestuur hierdie toestel en kan netwerkverkeer monitor. Tik vir besonderhede."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Jou toestel sal uitgevee word"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Laat die program toe om vaste uitsendings wat agterbly nadat die uitsending eindig, te stuur. Oormatige gebruik kan jou Android TV-toestel stadig of onstabiel maak omdat dit veroorsaak dat jou toestel te veel geheue gebruik."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Laat die program toe om taai uitsendings te stuur, wat agterbly nadat die uitsending klaar is. Oormatige gebruik kan die foon stadig of onstabiel maak deurdat dit te veel geheue gebruik."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"lees jou kontakte"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Laat die program toe om inligting oor jou kontakte wat op jou tablet gestoor is, te lees, insluitend die gereeldheid van oproepe wat jy gemaak het, e-posse wat jy gestuur het, of ander maniere waarop jy met spesifieke individue gekommunikeer het. Hierdie toestemming laat programme toe om jou kontakdata te stoor, en kwaadwillige programme kan moontlik kontakdata sonder jou kennis deel."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Laat die program toe om data te lees oor jou kontakte wat op jou Android TV-toestel geberg is, insluitend hoe gereeld jy spesifieke individue gebel, ge-e-pos of op ander maniere met hulle gekommunikeer het. Hierdie toestemming laat programme toe om jou kontakdata te stoor, én kwaadwillige programme kan kontakdata deel sonder dat jy dit weet."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Laat die program toe om inligting oor jou kontakte wat op jou foon gestoor is, te lees, insluitend die gereeldheid van oproepe wat jy gemaak het, e-posse wat jy gestuur het, of ander maniere waarop jy met spesifieke individue gekommunikeer het. Hierdie toestemming laat programme toe om jou kontakdata te stoor, en kwaadwillige programme kan moontlik kontakdata sonder jou kennis deel."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Laat die program toe om data te lees oor jou kontakte wat op jou tablet geberg is. Programme sal ook toegang hê tot die rekeninge op jou tablet wat kontakte geskep het. Dit kan rekeninge insluit wat geskep is deur programme wat jy geïnstalleer het. Hierdie toestemming laat programme toe om jou kontakdata te stoor, en kwaadwillige programme kan kontakdata deel sonder dat jy dit weet."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Laat die program toe om data te lees oor jou kontakte wat op jou Android TV-toestel geberg is. Programme sal ook toegang hê tot die rekeninge op jou Android TV-toestel wat kontakte geskep het. Dit kan rekeninge insluit wat geskep is deur programme wat jy geïnstalleer het. Hierdie toestemming laat programme toe om jou kontakdata te stoor, en kwaadwillige programme kan kontakdata deel sonder dat jy dit weet."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Laat die program toe om data te lees oor jou kontakte wat op jou foon geberg is. Programme sal ook toegang hê tot die rekeninge op jou foon wat kontakte geskep het. Dit kan rekeninge insluit wat geskep is deur programme wat jy geïnstalleer het. Hierdie toestemming laat programme toe om jou kontakdata te stoor, en kwaadwillige programme kan kontakdata deel sonder dat jy dit weet."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"verander jou kontakte"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Laat die program toe om data oor jou kontakte wat op jou tablet gestoor is te verander, insluitend die gereeldheid van oproepe wat jy gemaak het, e-posse wat jy gestuur het, of ander maniere waarop jy met spesifieke individue gekommunikeer het. Hierdie toestemming laat programme toe om kontakdata uit te vee."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Laat die program toe om die data oor jou kontakte wat op jou Android TV-toestel gestoor is, te verander – dit sluit in hoe gereeld jy spesifieke kontakte gebel, ge-e-pos of op ander maniere met hulle gekommunikeer het. Hierdie toestemming laat programme toe om kontakdata uit te vee."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Laat die program toe om data oor jou kontakte wat op jou foon gestoor is te verander, insluitend die gereeldheid waarop jy oproepe gemaak het, gee-pos het, of op ander maniere met spesifieke kontakte gekommunikeer het. Hierdie toestemming laat programme toe om kontakdata te skrap."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Laat die program toe om die data te wysig oor jou kontakte wat op jou tablet geberg is. Hierdie toestemming laat programme toe om kontakdata uit te vee."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Laat die program toe om die data te wysig oor jou kontakte wat op jou Android TV-toestel geberg is. Hierdie toestemming laat programme toe om kontakdata uit te vee."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Laat die program toe om die data te wysig oor jou kontakte wat op jou foon geberg is. Hierdie toestemming laat programme toe om kontakdata uit te vee."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"lees oproeprekord"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Hierdie program kan jou oproepgeskiedenis lees."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"skryf oproeprekord"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"Kry toegang tot ekstra liggingverskaffer-bevele"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Gee die program toegang tot ekstra liggingverskaffer-bevele. Dit kan die program dalk toelaat om in te meng met die werking van die GPS of ander liggingbronne."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"kry net op die voorgrond toegang tot presiese ligging"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Hierdie program kan jou presiese ligging kry net wanneer dit op die voorgrond is. Hierdie liggingdienste moet aangeskakel wees en op jou foon beskikbaar wees sodat die program hulle kan gebruik. Dit kan veroorsaak dat meer batterykrag gebruik word."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"kry benaderde ligging (netwerkgegrond) net op die voorgrond"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Hierdie program kan jou ligging kry op grond van netwerkhulpbronne soos selfoontorings en Wi-Fi-netwerke, maar net wanneer die program op die voorgrond is. Die program kan hierdie liggingdienste net gebruik as hulle aangeskakel is en op jou tablet beskikbaar is."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Hierdie program kan jou ligging kry op grond van netwerkhulpbronne soos selfoontorings en Wi-Fi-netwerke, maar net wanneer die program op die voorgrond is. Die program kan hierdie liggingdienste net gebruik as hulle aangeskakel is en op jou Android TV-toestel beskikbaar is."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Hierdie program kan jou ligging kry op grond van netwerkhulpbronne soos selfoontorings en Wi-Fi-netwerke, maar net wanneer die program op die voorgrond is. Die program kan hierdie liggingdienste net gebruik as hulle aangeskakel is en op jou foon beskikbaar is."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Hierdie program kan jou presiese ligging kry net wanneer dit op die voorgrond is. Liggingdienste moet aangeskakel wees en op jou toestel beskikbaar wees sodat die program hulle kan gebruik. Dit kan veroorsaak dat meer batterykrag gebruik word."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"kry benaderde ligging net op die voorgrond"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Hierdie program kan jou benaderde ligging net kry wanneer dit op die voorgrond is. Liggingdienste moet aangeskakel wees en op jou toestel beskikbaar wees sodat die program hulle kan gebruik."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"kry ligging op die agtergrond"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"As dit bo en behalwe toegang tot die benaderde of presiese ligging verleen word, kan die program die ligging kry terwyl dit op die agtergrond werk."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Hierdie program het toegang tot ligging terwyl dit op die agtergrond werk, asook voorgrondtoegang tot ligging."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"verander jou klankinstellings"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Laat die program toe om globale klankinstellings soos volume en watter luidspreker vir uitvoer gebruik word, te verander."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"neem klank op"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Laat die program toe om die opstelling van Bluetooth op die tablet te sien, en om verbindings met saamgebinde toestelle te maak en te aanvaar."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Laat die program toe om die opstelling van Bluetooth op jou Android TV-toestel te bekyk, en om verbindings met saamgebinde toestelle te maak en te aanvaar."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Laat die program toe om die opstelling van die Bluetooth op die foon te sien, en om verbindings met saamgebinde toestelle te maak en te aanvaar."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Voorkeur-NFC-betalingdiensinligting"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Laat die program toe om voorkeur-NFC-betalingdiensinligting soos geregistreerde hulpmiddels en roetebestemming te kry."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"beheer kortveldkommunikasie"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Laat die program toe om met kortveldkommunikasie- (NFC) merkers, kaarte en lesers te kommunikeer."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"deaktiveer jou skermslot"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"Toeganklikheidskortpad het <xliff:g id="SERVICE_NAME">%1$s</xliff:g> aangeskakel"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"Toeganklikheidskortpad het <xliff:g id="SERVICE_NAME">%1$s</xliff:g> afgeskakel"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Druk en hou albei volumesleutels drie sekondes lank om <xliff:g id="SERVICE_NAME">%1$s</xliff:g> te gebruik"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Kies \'n diens om te gebruik wanneer jy op die toeganklikheidknoppie tik:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Kies \'n diens om te gebruik saam met die toeganklikheidgebaar (swiep met twee vingers op van die onderkant van die skerm af):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Kies \'n diens om te gebruik saam met die toeganklikheidgebaar (swiep met drie vingers op van die onderkant van die skerm af):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Raak en hou die toeganklikheidknoppie om tussen dienste te wissel."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Swiep op met twee vingers en hou om tussen dienste te wissel."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Swiep op met drie vingers en hou om tussen dienste te wissel."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Vergroting"</string>
<string name="user_switched" msgid="7249833311585228097">"Huidige gebruiker <xliff:g id="NAME">%1$s</xliff:g> ."</string>
<string name="user_switching_message" msgid="1912993630661332336">"Skakel tans oor na <xliff:g id="NAME">%1$s</xliff:g> …"</string>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Gekoppel aan <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Tik om lêers te bekyk"</string>
<string name="pin_target" msgid="8036028973110156895">"Speld vas"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Speld <xliff:g id="LABEL">%1$s</xliff:g> vas"</string>
<string name="unpin_target" msgid="3963318576590204447">"Ontspeld"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Ontspeld <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Programinligting"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Begin tans demonstrasie …"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Dateer hierdie items op in "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> en <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Stoor"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Nee, dankie"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Nie nou nie"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Nooit"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Dateer op"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Gaan voort"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"wagwoord"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Wissel verdeelde skerm"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Sluitskerm"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Skermkiekie"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"<xliff:g id="APP_NAME">%1$s</xliff:g>-program in opspringervenster."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> se onderskrifbalk."</string>
</resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index c6e55c39ff95..9b9dbb0c7d4c 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"የሥራ መገለጫ አስተዳዳሪ መተግበሪያው ወይም ይጎድላል ወይም ተበላሽቷል። በዚህ ምክንያት የሥራ መገለጫዎ እና ተዛማጅ ውሂብ ተሰርዘዋል። እርዳታን ለማግኘት አስተዳዳሪዎን ያነጋግሩ።"</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"የሥራ መገለጫዎ ከዚህ በኋላ በዚህ መሣሪያ ላይ አይገኝም"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"በጣም ብዙ የይለፍ ቃል ሙከራዎች"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"አስተዳዳሪ መሣሪያዎን ለግል ጥቅም ትተውታል"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"መሣሪያው የሚተዳደር ነው"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"የእርስዎ ድርጅት ይህን መሣሪያ ያስተዳድራል፣ እና የአውታረ መረብ ትራፊክን ሊከታተል ይችላል። ዝርዝሮችን ለማግኘት መታ ያድርጉ።"</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"የእርስዎ መሣሪያ ይደመሰሳል"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"መተግበሪያው ስርጭቱ ከተጠናቀቀ በኋላ የሚቀሩ አጣባቂ ስርጭቶችን እንዲልክ ያስችለዋል። ከልክ በላይ መጠቀም የእርስዎን Android TV መሣሪያ ብዙ ማህደረ ትውስታን እንዲጠቀም በማድረግ ቀርፋፋ ወይም ያልተረጋጋ ሊያደርገው ይችላል።"</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"መተግበሪያው ስርጭቱ ከተጠናቀቀ በኋላ የሚቀሩ አጣባቂ ስርጭቶችን እንዲልክ ይፈቅድለታል። ከልክ በላይ መጠቀም ስልኩ ብዙ ማህደረ ትውስታን እንዲጠቀም በማድረግ ቀርፋፋ ወይም ያልተረጋጋ ሊያደርገው ይችላል።"</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"እውቂያዎችዎን ያንብቡ"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"መተግበሪያው በጡባዊ ተኮህ ስለተከማቹ ዕውቂያዎች ያሉትን ውሂቦች በሙሉ፤ ጥሪ ያደረግክበትን፣ ኢሜይል የላክበትን ወይም ከተወሰኑ ግለሰቦች ጋር በሌላ መንገድ የተገናኘህበትን ድግምግሞሽ ጨምሮ፣ እንዲያነብ ይፈቅድለታል። ይህ ፈቃድ መተግበሪያዎች የእውቂያ ውሂብህን እንዲያስቀምጡ የሚፈቅድላቸው ሲሆን ተንኮል አዘል መተግበሪያዎች የእውቂያህን ውሂብ ሳታውቀው ሊያጋሩት ይችላሉ።"</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"መተግበሪያው ከተወሰኑ ግለሰቦች ጋር የተደዋወሉበት፣ ኢሜይል የተላላኩበት ወይም የተገናኙበት ተደጋጋሚነትም ጨምሮ በእርስዎ Android TV ላይ ስለተከማቹ እውቂያዎች እንዲያነብ ያስችለዋል። ይህ ፍቃድ መተግበሪያዎች የእውቂያ ውሂብዎን እንዲያስቀምጥ ያስችላቸዋል፣ እና ተንኮል-አዘል መተግበሪያዎች የእውቂያ ውሂብ ያለእውቀትዎ ሊያጋሩ ይችላሉ።"</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"መተግበሪያው በስልክዎ ስለተከማቹ ዕውቂያዎች ያሉትን ውሂቦች በሙሉ፤ ጥሪ ያደረጉበትን፣ ኢሜይል የላኩበትን ወይም ከተወሰኑ ግለሰቦች ጋር በሌላ መንገድ የተገናኙበትን ድግምግሞሽ ጨምሮ፣ እንዲያነብ ይፈቅድለታል። ይህ ፈቃድ መተግበሪያዎች የእውቂያ ውሂብዎን እንዲያስቀምጡ የሚፈቅድላቸው ሲሆን ተንኮል አዘል መተግበሪያዎች የእውቂያዎን ውሂብ ሳያውቁት ሊያጋሩት ይችላሉ።"</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"መተግበሪያው በእርስዎ ጡባዊ ላይ ስለተከማቹ ዕውቂያዎችዎ ያለ ውሂብ እንዲያነብብ ያስችለዋል። መተግበሪያዎች እንዲሁም በእርስዎ ጡባዊ ላይ እውቂያዎችን የፈጠሩ የመለያዎች መዳረሻ ይኖራቸዋል። ይህ እርስዎ በጫኗቸው መተግበሪያዎች የተፈጠሩ መለያዎችን ሊያካትት ይችላል። ይህ ፈቃድ መተግበሪያዎች የእውቂያ ውሂብዎን እንዲያስቀምጡ የሚፈቅድላቸው ሲሆን ተንኮል-አዘል መተግበሪያዎች የእውቂያዎን ውሂብ ሳያውቁት ሊያጋሩት ይችላሉ።"</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"መተግበሪያው በእርስዎ የAndroid TV መሣሪያ ላይ ስለተከማቹ እውቂያዎችዎ ያለ ውሂብን እንዲቀይር ያስችለዋል። መተግበሪያዎች እንዲሁም በእርስዎ የAndroid TV መሣሪያ ላይ እውቂያዎችን የፈጠሩ የመለያዎች መዳረሻ ይኖራቸዋል። ይህ እርስዎ በጫኗቸው መተግበሪያዎች የተፈጠሩ መለያዎችን ሊያካትት ይችላል። ይህ ፈቃድ መተግበሪያዎች የእውቂያ ውሂብዎን እንዲያስቀምጡ የሚፈቅድላቸው ሲሆን ተንኮል-አዘል መተግበሪያዎች የእውቂያዎን ውሂብ ሳያውቁት ሊያጋሩት ይችላሉ።"</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"መተግበሪያው በእርስዎ ስልክ ላይ ስለተከማቹ ዕውቂያዎችዎ ያለ ውሂብ እንዲያነብብ ያስችለዋል። መተግበሪያዎች እንዲሁም በእርስዎ ስልክ ላይ እውቂያዎችን የፈጠሩ የመለያዎች መዳረሻ ይኖራቸዋል። ይህ እርስዎ በጫኗቸው መተግበሪያዎች የተፈጠሩ መለያዎችን ሊያካትት ይችላል። ይህ ፈቃድ መተግበሪያዎች የእውቂያ ውሂብዎን እንዲያስቀምጡ የሚፈቅድላቸው ሲሆን ተንኮል-አዘል መተግበሪያዎች የእውቂያዎን ውሂብ ሳያውቁት ሊያጋሩት ይችላሉ።"</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"ዕውቂያዎችዎን ያስተካክሉ"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"መተግበሪያው በጡባዊ ቱኮህ ስለተከማቹ የዕውቂያዎችህ ውሂብ በሙሉ፤ ጥሪ ያደረግክበትን፣ ኢሜይል የላክበትን ወይም ከተወሰኑ እውቂያዎች ጋር በሌላ መንገድ የተገናኘህበትን ድግምግሞሽ ጨምሮ፣ እንዲያስተካክል ይፈቅድለታል። ይህ ፈቃድ መተግበሪያዎች የእውቂያ ውሂብ እንዲሰርዙ ይፈቅድላቸዋል።"</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"መተግበሪያው ከተወሰኑ እውቂያዎች ጋር የሚደዋወሉበት፣ ኢሜይል የሚላላኩበት ወይም የሚገናኙበት ተደጋጋሚነትም ጨምሮ በእርስዎ Android TV ላይ ስለተከማቹ ዕውቂያዎችዎ ያለ ውሂብ እንዲቀይር ያስችለዋል። ይህ ፈቃድ መተግበሪያዎች የእውቂያ ውሂብ እንዲሰርዙ ያስችላቸዋል።"</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"መተግበሪያው በስልክዎ ስለተከማቹ የዕውቂያዎችዎ ውሂብ በሙሉ፤ ጥሪ ያደረጉበትን፣ ኢሜይል የላኩበትን ወይም ከተወሰኑ እውቂያዎች ጋር በሌላ መንገድ የተገናኙበትን ድግምግሞሽ ጨምሮ፣ እንዲያስተካክል ይፈቅድለታል። ይህ ፈቃድ መተግበሪያዎች የእውቂያ ውሂብ እንዲሰርዙ ይፈቅድላቸዋል።"</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"መተግበሪያው በእርስዎ ጡባዊ ላይ ስለተከማቹ እውቂያዎችዎ ያለ ውሂብን እንዲቀይር ያስችለዋል። ይህ ፈቃድ መተግበሪያዎች የእውቂያ ውሂብን እንዲሰርዙ ያስችላቸዋል።"</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"መተግበሪያው በእርስዎ የAndroid TV መሣሪያ ላይ ስለተከማቹ የዕውቂያዎች እንዲቀይር ይፈቅድለታል። ይህ ፈቃድ መተግበሪያዎች የእውቂያ ውሂብን እንዲሰርዙ ያስችላቸዋል።"</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"መተግበሪያው በእርስዎ ስልክ ላይ ስለተከማቹ እውቂያዎችዎ ያለ ውሂብን እንዲቀይር ያስችለዋል። ይህ ፈቃድ መተግበሪያዎች የእውቂያ ውሂብን እንዲሰርዙ ያስችላቸዋል።"</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"የጥሪ ምዝግብ ማስታወሻን ያንብቡ"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"ይህ መተግበሪያ የእርስዎን የጥሪ ታሪክ ማንበብ ይችላል።"</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"የጥሪ ምዝግብ ማስታወሻን ፃፍ"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"ተጨማሪ ሥፍራ አቅራቢ ትዕዛዞችን ድረስ።"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"መተግበሪያው ተጨማሪ የአካባቢ አቅራቢ ትእዛዞችን እንዲደርስ ይፈቅድለታል። ይሄ መተግበሪያው በጂፒኤስ ወይም ሌላ የአካባቢ ምንጮች ስራ ላይ ጣልቃ እንዲገባ ሊፈቅድለት ይችላል።"</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"መዳረሻ ከፊት ለፊት ብቻ ትክክለኛ ነው"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"ይህ መተግበሪያ ከፊት ላይ ሆኖ ሲበራ ብቻ ትክክለኛውን መገኛ አካባቢ ማግኘት ይችላል። እነዚህ የመገኛ አካባቢ አገልግሎቶች መተግበሪያው መጠቀም እንዲችል ሊበሩ እና በእርስዎ ስልክ ላይ ሊገኙ የሚችሉ መሆን አለባቸው።"</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"ግምታዊ አካባቢ (በአውታረ መረብ ላይ የተመሠረተ) ከፊት ላይ ሲሆን ብቻ መድረስ"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"ይህ መተግበሪያ እንደ የሕዋስ ማማዎች እና የWi-Fi አውታረ መረቦች ባሉ የአውታረ መረብ ምንጮች ላይ በመመስረት የእርስዎን አካባቢ ማግኘት ይችላል፣ ነገር ግን መተግበሪያው ከፊት ሲሆን ብቻ። እነዚህ የአካባቢ አገልግሎቶች መተግበሪያው መጠቀም እንዲችል ሊበሩ እና በእርስዎ ጡባዊ ላይ ሊገኙ የሚችሉ መሆን አለባቸው።"</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"ይህ መተግበሪያ እንደ የሕዋስ ማማዎች እና የWi-Fi አውታረ መረቦች ባሉ የአውታረ መረብ ምንጮች ላይ በመመስረት የእርስዎን አካባቢ ማግኘት ይችላል፣ ነገር ግን መተግበሪያው ከፊት ሲሆን ብቻ። እነዚህ የአካባቢ አገልግሎቶች መተግበሪያው መጠቀም እንዲችል ሊበሩ እና በእርስዎ Android TV መሣሪያ ላይ ሊገኙ የሚችሉ መሆን አለባቸው።"</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"ይህ መተግበሪያ እንደ የሕዋስ ማማዎች እና የWi-Fi አውታረ መረቦች ባሉ የአውታረ መረብ ምንጮች ላይ በመመስረት የእርስዎን አካባቢ ማግኘት ይችላል፣ ነገር ግን መተግበሪያው ከፊት ሲሆን ብቻ። እነዚህ የአካባቢ አገልግሎቶች መተግበሪያው መጠቀም እንዲችል ሊበሩ እና በእርስዎ ስልክ ላይ ሊገኙ የሚችሉ መሆን አለባቸው።"</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"ይህ መተግበሪያ ከፊት ላይ ሆኖ ሲበራ ብቻ ትክክለኛውን አካባቢዎ ማግኘት ይችላል። መተግበሪያው የአካባቢ አገልግሎቶች መጠቀም እንዲችል ሊበሩ እና በእርስዎ መሣሪያ ላይ ሊገኙ የሚችሉ መሆን አለባቸው።"</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"ከፊት ለፊት ብቻ ግምታዊ አካባቢን ድረስ"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"ይህ መተግበሪያ ግምታዊ አካባቢዎን ማግኘት የሚችለው ከፊት ሲሆን ብቻ ነው። መተግበሪያው የአካባቢ አገልግሎቶች መጠቀም እንዲችል ሊበሩ እና በእርስዎ መሣሪያ ላይ ሊገኙ የሚችሉ መሆን አለባቸው።"</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"አካባቢን በበስተጀርባ ድረስ"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"ይህ ከግምታዊ ወይም ትክክለኛ አካባቢ በተጨማሪ ከተሰጠ መተግበሪያው በበስተጀርባ እያሄደ ሳለ አካባቢውን መድረስ ይችላል።"</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"ይህ መተግበሪያ ከፊት የአካባቢ መዳረሻ በተጨማሪም ከበስተጀርባ እያሄደ ሳለ አካባቢን መድረስ ይችላል።"</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"የድምፅ ቅንብሮችን ለውጥ"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"መተግበሪያው አንደ የድምጽ መጠን እና ለውጽአት የትኛውን የድምጽ ማጉያ ጥቅም ላይ እንደዋለ የመሳሰሉ ሁለንተናዊ የድምጽ ቅንብሮችን እንዲያስተካክል ይፈቅድለታል።"</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"ኦዲዮ ይቅዱ"</string>
@@ -494,6 +491,8 @@
<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_preferredPaymentInfo" msgid="5274423844767445054">"ተመራጭ NFC የክፍያ አገልግሎት መረጃ"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"እንደ የተመዘገቡ እርዳታዎች እና የጉዞ መሥመር መዳረሻ የመሳሰለ ተመራጭ nfc የክፍያ አገልግሎት መረጃን ለማግኘት ለመተግበሪያው ያፈቅድለታል።"</string>
<string name="permlab_nfc" msgid="1904455246837674977">"ቅርብ የግኑኙነትመስክ (NFC) ተቆጣጠር"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"ከቅርብ ግኑኙነት መስክ (NFC) መለያዎች፣ ካርዶች እና አንባቢ ጋር ለማገናኘት ለመተግበሪያው ይፈቅዳሉ።"</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"የማያ ገጽዎን መቆለፊያ ያሰናክሉ"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"የተደራሽነት አቋራጭ <xliff:g id="SERVICE_NAME">%1$s</xliff:g>ን አብርቶታል"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"የተደራሽነት አቋራጭ <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>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"የተደራሽነት አዝራርን መታ በሚያደርጉበት ጊዜ ጥቅም ላይ የሚውለውን አገልግሎት ይምረጡ፦"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"ከተደራሽነት ጣት ምልክት ጋር የሚጠቀሙበት አአገልግሎት ይምረጡ (በሁለት ጣቶች ከማያ ገጹ ግርጌ ወደ ላይ ይጥረጉ)፦"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"ከተደራሽነት ጣት ምልክት ጋር አብረው የሚጠቀሙበት አገልግሎት ይምረጡ (በሶስት ጣቶች ከማያ ገጹ ግርጌ ወደ ላይ ይጥረጉ)፦"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"በአገልግሎቶች መካከል ለመቀያየር የተደራሽነት አዝራሩን ነክተው ይያዙ።"</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"በአገልግሎቶች መካከል ለመቀያየር በሁለት ጣቶች ወደ ላይ ጠርገው ይያዙ።"</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"በአገልግሎቶች መካከል ለመቀያየር በሶስት ጣቶች ወደ ላይ ጠርገው ይያዙ።"</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>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"ከ<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> ጋር ተገናኝቷል"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"ፋይሎችን ለመመልከት መታ ያድርጉ"</string>
<string name="pin_target" msgid="8036028973110156895">"ፒን"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"<xliff:g id="LABEL">%1$s</xliff:g>ን ይሰኩ"</string>
<string name="unpin_target" msgid="3963318576590204447">"ንቀል"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"<xliff:g id="LABEL">%1$s</xliff:g> ንቀል"</string>
<string name="app_info" msgid="6113278084877079851">"የመተግበሪያ መረጃ"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"ማሳያን በማስጀመር ላይ…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"እነዚህ ንጥሎች በ"<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" ውስጥ ይዘመኑ፦ <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>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"አስቀምጥ"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"አይ፣ አመሰግናለሁ"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"አሁን አይደለም"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"በጭራሽ"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"አዘምን"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"ቀጥል"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"የይለፍ ቃል"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"የተከፈለ ማያን ቀያይር"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"የማያ ገጽ ቁልፍ"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"ቅጽበታዊ ገጽ እይታ"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"የ<xliff:g id="APP_NAME">%1$s</xliff:g> መተግበሪያ በብቅ-ባይ መስኮት ውስጥ።"</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"የ<xliff:g id="APP_NAME">%1$s</xliff:g> የሥዕል ገላጭ ጽሑፍ አሞሌ።"</string>
</resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 609b77e4f1db..eb1f5534fdef 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -196,8 +196,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"تطبيق المشرف للملف الشخصي للعمل مفقود أو تالف لذا تم حذف الملف الشخصي للعمل والبيانات ذات الصلة. اتصل بالمشرف للحصول على المساعدة."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"لم يعد ملفك الشخصي للعمل متاحًا على هذا الجهاز"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"تم إجراء محاولات كثيرة جدًا لإدخال كلمة المرور"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"تنازل المشرف عن الجهاز للاستخدام الشخصي"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"تتم إدارة الجهاز"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"تدير مؤسستك هذا الجهاز ويمكنها مراقبة حركة بيانات الشبكة. يمكنك النقر للحصول على تفاصيل."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"سيتم محو بيانات جهازك."</string>
@@ -263,7 +262,7 @@
<string name="global_action_settings" msgid="4671878836947494217">"الإعدادات"</string>
<string name="global_action_assist" msgid="2517047220311505805">"مساعدة"</string>
<string name="global_action_voice_assist" msgid="6655788068555086695">"المساعد الصوتي"</string>
- <string name="global_action_lockdown" msgid="2475471405907902963">"التأمين"</string>
+ <string name="global_action_lockdown" msgid="2475471405907902963">"إلغاء التأمين"</string>
<string name="status_bar_notification_info_overflow" msgid="3330152558746563475">"999+"</string>
<string name="notification_hidden_text" msgid="2835519769868187223">"إشعار جديد"</string>
<string name="notification_channel_virtual_keyboard" msgid="6465975799223304567">"لوحة المفاتيح الافتراضية"</string>
@@ -393,13 +392,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"‏للسماح للتطبيق بإرسال مواد بث ثابتة، والتي تظل متوفرة بعد انتهاء البث. وقد يؤدي الاستخدام المفرط لهذا التطبيق إلى حدوث بطء أو عدم استقرار في جهاز Android TV من خلال جعل الجهاز يستخدم قدرًا كبيرًا جدًا من الذاكرة."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"للسماح للتطبيق بإرسال مجموعات بث مستمرة، والتي تظل بعد انتهاء البث. قد يؤدي الاستخدام بكثرة إلى حدوث بطء أو عدم استقرار في الهاتف من خلال التسبب في استخدام الهاتف لمساحة كبيرة للغاية من الذاكرة."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"قراءة جهات الاتصال"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"للسماح للتطبيق بقراءة بيانات حول جهات الاتصال المخزنة على الجهاز اللوحي، بما في ذلك مدى تكرار اتصالك بأفراد بعينهم أو مراسلتهم عبر البريد الإلكتروني أو التواصل معهم بطرق أخرى خلافًا لذلك. ويتيح هذا الإذن للتطبيقات حفظ بيانات جهات الاتصال، وقد تشارك التطبيقات الضارة بيانات جهات الاتصال بدون معرفتك."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"‏للسماح للتطبيق بقراءة البيانات حول جهات الاتصال المخزّنة على جهاز Android TV، بما في ذلك مدى تكرار اتصالك بأفراد بعينهم أو مراسلتهم عبر البريد الإلكتروني أو التواصل معهم بطرق أخرى. ويتيح هذا الإذن للتطبيقات إمكانية حفظ بيانات جهة الاتصال، وقد تشارك التطبيقات الضارة بيانات جهة الاتصال بدون علمك."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"للسماح للتطبيق بقراءة بيانات حول جهات الاتصال المخزنة على الهاتف، بما في ذلك مدى تكرار اتصالك بأفراد بعينهم أو مراسلتهم عبر البريد الإلكتروني أو التواصل معهم بطرق أخرى خلافًا لذلك. ويتيح هذا الإذن للتطبيقات حفظ بيانات جهات الاتصال، وقد تشارك التطبيقات الضارة بيانات جهات الاتصال بدون معرفتك."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"يسمح هذا الإذن للتطبيق بقراءة بيانات حول جهات الاتصال المخزّنة على جهازك اللوحي. ويمكن للتطبيقات أيضًا الوصول إلى الحسابات التي تم إنشاء جهات الاتصال من خلالها على جهازك اللوحي. ويمكن أن يشمل ذلك الحسابات التي أنشأتها التطبيقات التي ثبتّها. ويتيح هذا الإذن للتطبيقات حفظ بيانات جهة الاتصال، وقد تشارك التطبيقات الضارة بيانات جهة الاتصال بدون علمك."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"‏يسمح هذا الإذن للتطبيق بقراءة بيانات حول جهات الاتصال المخزّنة على جهاز Android TV. ويمكن للتطبيقات أيضًا الوصول إلى الحسابات التي تم إنشاء جهات الاتصال من خلالها على جهاز Android TV. ويمكن أن يشمل ذلك الحسابات التي أنشأتها التطبيقات التي ثبتّها. ويتيح هذا الإذن للتطبيقات حفظ بيانات جهة الاتصال، وقد تشارك التطبيقات الضارة بيانات جهة الاتصال بدون علمك."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"يسمح هذا الإذن للتطبيق بقراءة بيانات حول جهات الاتصال المخزّنة على هاتفك. ويمكن للتطبيقات أيضًا الوصول إلى الحسابات التي تم إنشاء جهات الاتصال من خلالها على هاتفك. ويمكن أن يشمل ذلك الحسابات التي أنشأتها التطبيقات التي ثبتّها. ويتيح هذا الإذن للتطبيقات حفظ بيانات جهة الاتصال، وقد تشارك التطبيقات الضارة بيانات جهة الاتصال بدون علمك."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"تعديل جهات الاتصال"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"للسماح للتطبيق بتعديل البيانات حول جهات الاتصال المخزنة على جهازك اللوحي، بما في ذلك مدى تكرار اتصالك بجهات اتصال بعينها أو مراسلتها عبر البريد الإلكتروني أو التواصل معها بأية طريقة أخرى خلافًا لذلك. وقد يتيح هذا الإذن للتطبيقات حذف بيانات جهات الاتصال."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"‏للسماح للتطبيق بتعديل البيانات حول جهات الاتصال المخزّنة على جهاز Android TV، بما في ذلك مدى تكرار اتصالك بجهات اتصال بعينها أو مراسلتها عبر البريد الإلكتروني أو التواصل معها بطرق أخرى. ويتيح هذا الإذن للتطبيقات إمكانية حذف بيانات جهات الاتصال."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"للسماح للتطبيق بتعديل البيانات حول جهات الاتصال المخزنة على هاتفك، بما في ذلك مدى تكرار اتصالك بجهات اتصال بعينها أو مراسلتها عبر البريد الإلكتروني أو التواصل معها بأية طريقة أخرى خلافًا لذلك. وقد يتيح هذا الإذن للتطبيقات حذف بيانات جهات الاتصال."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"يسمح هذا الإذن للتطبيق بتعديل البيانات حول جهات الاتصال المخزّنة على جهازك اللوحي. ويسمح هذا الإذن للتطبيقات بحذف بيانات جهات الاتصال."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"‏يسمح هذا الإذن للتطبيق بتعديل البيانات حول جهات الاتصال المخزّنة على جهاز Android TV. ويسمح هذا الإذن للتطبيقات بحذف بيانات جهات الاتصال."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"يسمح هذا الإذن للتطبيق بتعديل البيانات حول جهات الاتصال المخزّنة على هاتفك. ويسمح هذا الإذن للتطبيقات بحذف بيانات جهات الاتصال."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"قراءة سجل المكالمات"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"يمكن لهذا التطبيق قراءة سجل المكالمات."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"كتابة سجل المكالمات"</string>
@@ -419,13 +418,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"الدخول إلى المزيد من أوامر موفر الموقع"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"‏للسماح للتطبيق بالدخول إلى أوامر إضافية لموفر الموقع. قد يتيح هذا للتطبيق التداخل مع تشغيل تقنية نظام تحديد المواقع العالمي (GPS) أو مصادر الموقع الأخرى."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"الوصول إلى الموقع الجغرافي الدقيق في الواجهة الأمامية فقط"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"لا يمكن لهذا التطبيق معرفة موقعك الجغرافي بالضبط إلا عندما يعمل في الخلفية. ويجب تفعيل خدمات الموقع الجغرافي هذه وأن تكون متاحة على الهاتف حتى يتمكن التطبيق من استخدامها. وقد يؤدي هذا إلى زيادة استهلاك طاقة البطارية."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"الوصول إلى الموقع الجغرافي التقريبي (بالاعتماد على الشبكة) في الخلفية فقط"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"‏يمكن لهذا التطبيق معرفة موقعك مستعينًا بمصادر الشبكات مثل الأبراج الخلوية وشبكات Wi-Fi ولكن يجب أن يعمل في الخلفية. ويجب تفعيل خدمات المواقع هذه وتوفّرها على جهازك اللوحي كي يتمكن التطبيق من استخدامها."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"‏يمكن لهذا التطبيق معرفة موقعك الجغرافي مستعينًا بمصادر الشبكات مثل الأبراج الخلوية وشبكات Wi-Fi، ولكن بشرط أن يعمل التطبيق في الواجهة الأمامية. ويجب تفعيل \"خدمات الموقع الجغرافي\" هذه وتوفّرها على جهاز Android TV لكي يتمكّن التطبيق من استخدامها."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"‏يمكن لهذا التطبيق معرفة موقعك مستعينًا بمصادر الشبكات مثل الأبراج الخلوية وشبكات Wi-Fi ولكن يجب أن يعمل في الخلفية. ويجب تفعيل خدمات المواقع هذه وتوفّرها على هاتفك كي يتمكن التطبيق من استخدامها."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"لا يمكن لهذا التطبيق معرفة موقعك الجغرافي بالضبط عندما يعمل في الخلفية. ويجب تفعيل خدمات الموقع الجغرافي وأن تكون متاحة على جهازك حتى يتمكن التطبيق من استخدامها. وقد يؤدي هذا إلى زيادة استهلاك طاقة البطارية."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"الوصول إلى الموقع الجغرافي التقريبي في الواجهة الأمامية فقط"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"لا يمكن لهذا التطبيق معرفة موقعك الجغرافي التقريبي إذا كان يعمل في الخلفية. ويجب تفعيل خدمات الموقع الجغرافي وأن تكون متاحة على جهازك حتى يتمكن التطبيق من استخدامها."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"الوصول إلى الموقع الجغرافي في الخلفية"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"إذا تمّ منح إذن التطبيق هذا بالإضافة إلى الموقع الجغرافي التقريبي أو الدقيق، يمكن للتطبيق الوصول إلى الموقع الجغرافي أثناء تشغيله في الخلفية."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"يمكن لهذا التطبيق الوصول إلى الموقع الجغرافي أثناء عمله في الخلفية، بالإضافة إلى إمكانية وصوله للموقع الجغرافي أثناء عمله في الواجهة الأمامية."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"تغيير إعداداتك الصوتية"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"للسماح للتطبيق بتعديل إعدادات الصوت العامة مثل مستوى الصوت وأي السماعات يتم استخدامها للاستماع."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"تسجيل الصوت"</string>
@@ -506,6 +503,8 @@
<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_preferredPaymentInfo" msgid="5274423844767445054">"‏معلومات الخدمات المدفوعة باستخدام الاتصال قصير المدى NFC المفضّل"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"‏يسمح هذا الإذن للتطبيق بالحصول على معلومات الخدمات المدفوعة باستخدام الاتصال قصير المدى NFC المفضّل، مثلاً المساعدات المسجّلة ووجهة المسار."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"التحكم في اتصال الحقل القريب"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"‏للسماح للتطبيق بالاتصال بعلامات الاتصال قريب المدى (NFC)، والبطاقات وبرامج القراءة."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"إيقاف قفل الشاشة"</string>
@@ -1706,12 +1705,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"شغَّل اختصار إمكانية الوصول خدمة <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"أوقف اختصار إمكانية الوصول خدمة <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"اضغط مع الاستمرار على مفتاحي مستوى الصوت لمدة 3 ثوانٍ لاستخدام <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"يمكنك اختيار إحدى الخدمات لاستخدامها عند النقر على زر \"سهولة الاستخدام\":"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"يمكنك اختيار إحدى الخدمات لاستخدامها مع إيماءة \"سهولة الاستخدام\" (مرّر سريعًا إلى الأعلى من أسفل الشاشة باستخدام إصبعين):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"يمكنك اختيار إحدى الخدمات التالية لاستخدامها مع إيماءة \"سهولة الاستخدام\" (مرّر سريعًا إلى الأعلى من أسفل الشاشة باستخدام ثلاثة أصابع):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"للتبديل بين الخدمات، يمكنك النقر والاستمرار على زر \"سهولة الاستخدام\"."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"للتبديل بين الخدمات، يمكنك التمرير سريعًا من أسفل الشاشة إلى أعلاها باستخدام إصبعين مع تثبيتهما."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"للتبديل بين الخدمات، يمكنك التمرير سريعًا من أسفل الشاشة إلى أعلاها باستخدام ثلاثة أصابع مع تثبيت الأصابع."</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>
@@ -1990,7 +1983,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"تم الاتصال بـ <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"انقر لعرض الملفات"</string>
<string name="pin_target" msgid="8036028973110156895">"تثبيت"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"تثبيت <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"إزالة تثبيت"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"إزالة تثبيت <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"معلومات عن التطبيق"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"جارٍ بدء العرض التوضيحي…"</string>
@@ -2037,6 +2032,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"هل تريد تحديث هذه العناصر في "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <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>؟"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"حفظ"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"لا، شكرًا"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"ليس الآن"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"أبدًا"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"تعديل"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"متابعة"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"كلمة مرور"</string>
@@ -2136,5 +2133,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"تبديل \"تقسيم الشاشة\""</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"شاشة القفل"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"لقطة شاشة"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"تطبيق <xliff:g id="APP_NAME">%1$s</xliff:g> في نافذة منبثقة"</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"شريط الشرح لتطبيق <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index 091b563ff2e9..149ac6b1bd96 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"কৰ্মস্থানৰ প্ৰ\'ফাইলৰ প্ৰশাসক এপ্ নাই বা ব্যৱহাৰযোগ্য হৈ থকা নাই। যাৰ ফলত আপোনাৰ কৰ্মস্থানৰ প্ৰ\'ফাইল আৰু ইয়াৰ লগত জড়িত অন্য ডেটাসমূহ মচা হৈছে। সহায়ৰ বাবে আপোনাৰ প্ৰশাসকৰ সৈতে সম্পর্ক কৰক।"</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"আপোনাৰ কৰ্মস্থানৰ প্ৰ\'ফাইল এই ডিভাইচটোত আৰু উপলব্ধ নহয়"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"বহুতবাৰ ভুলকৈ পাছৱৰ্ড দিয়া হৈছে"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"প্ৰশাসকে ডিভাইচটো ব্যক্তিগত ব্যৱহাৰৰ বাবে বাজেয়প্ত কৰিছে"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"পৰিচালিত ডিভাইচ"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"আপোনাৰ প্ৰতিষ্ঠানটোৱে এই ডিভাইচটো পৰিচালনা কৰে আৰু ই নেটৱৰ্কৰ ট্ৰেফিক পৰ্যবেক্ষণ কৰিব পাৰে। সবিশেষ জানিবলৈ টিপক।"</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"আপোনাৰ ডিভাইচৰ ডেটা মচা হ\'ব"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"এপ্‌টোক ব্ৰ’ডকাষ্ট শেষ হোৱাৰ পাছত বাকী থকা ষ্টিকী ব্ৰ’ডকাষ্টবোৰ পঠিয়াবলৈ অনুমতি দিয়ে। ইয়াক অত্যধিক ব্যৱহাৰ কৰিলে আপোনাৰ Android TV ডিভাইচটোক অতি বেছি পৰিমাণৰ মেম’ৰী খৰচ কৰাই লেহেমীয়া অথবা অস্থিৰ কৰিব পাৰে।"</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"সম্প্ৰচাৰৰ শেষত বাকী ৰোৱা ষ্টিকী ব্ৰ\'ডকাষ্টবোৰ প্ৰেৰণ কৰিবলৈ এপক অনুমতি দিয়ে। ইয়াক অত্য়ধিক ব্যৱহাৰ কৰাৰ ফলত মেম\'ৰি অধিক খৰচ হোৱাৰ বাবে ফ\'নটো লেহেমীয়া বা অস্থিৰ হৈ পৰে।"</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"নিজৰ সম্পর্ক সূচী পঢ়ক"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"আপুনি কোনো ব্যক্তি বিশেষৰ সৈতে টেবলেট, ইমেইল বা অন্য মাধ্যমেৰে কিমান সঘনাই যোগাযোগ কৰিছে সেই তথ্য়সহ ফ\'নৰ সম্পর্কসূচীত সঞ্চয় কৰা ডেটা পঢ়িবলৈ এপক অনুমতি দিয়ে৷ এই কার্যই এপক আপোনাৰ সম্পর্কৰ ডেটা ছেভ কৰিবলৈ অনুমতি দিয়ে আৰু ক্ষতিকাৰক এপবোৰে সম্পর্কসূচীৰ ডেটা আপোনাৰ অজ্ঞাতেই শ্বেয়াৰ কৰিব পাৰে৷"</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"এপ্‌টোক আপোনাৰ Android TV ডিভাইচটোত ষ্ট’ৰ কৰি ৰখা সম্পৰ্কবোৰৰ ডেটা পঢ়িবলৈ দিয়াৰ লগতে আপুনি কোনো বিশেষ ব্যক্তিৰ সৈতে কিমান সঘনাই কল, ইমেইল বা অন্য মাধ্যমেৰে যোগাযোগ কৰিছে তাকো জানিবলৈ অনুমতি দিয়ে। এই অনুমতিটোৱে এপ্‌টোক আপোনাৰ সম্পর্ক ডেটা ছেভ কৰিবলৈ দিয়ে আৰু ক্ষতিকাৰক এপ্‌সমূহে আপুনি নজনাকৈ আপোনাৰ সম্পর্কসূচীৰ ডেটা শ্বেয়াৰ কৰিব পাৰে।"</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"আপুনি কোনো বিশেষ ব্যক্তিৰ সৈতে কিমান সঘনাই ফ\'ন, ইমেইল বা অন্য মাধ্যমেৰে যোগাযোগ কৰে সেই সম্পর্কে ফ\'নৰ সম্পর্ক সূচীত সঞ্চয় কৰা ডেটা পঢ়িবলৈ এপক অনুমতি দিয়ে। এই অনুমতিএ এপক আপোনাৰ সম্পর্কৰ ডেটা ছেভ কৰিবলৈ দিয়ে আৰু ক্ষতিকাৰক এপবোৰে সম্পর্কৰ ডেটা আপোনাৰ অজ্ঞাতেই শ্বেয়াৰ কৰিব পাৰে।"</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"এপ্‌টোক আপোনাৰ টেবলেটত ষ্ট’ৰ কৰি ৰখা সম্পৰ্কবোৰৰ ডেটা পঢ়িবলৈ দিয়ে। এপ্‌সমূহৰ আপোনাৰ টেবলেটত থকা একাউণ্টসমূহলৈও এক্সেছ থাকিব যি সম্পৰ্কসমূহ সৃষ্টি কৰিছে। ইয়াত আপুনি ইনষ্টল কৰা এপ্‌সমূহে সৃষ্টি কৰা একাউণ্টসমূহ অন্তৰ্ভুক্ত হ’ব পাৰে। এই অনুমতিটোৱে এপ্‌সমূহক আপোনাৰ সম্পর্ক ডেটা ছেভ কৰিবলৈ দিয়ে আৰু ক্ষতিকাৰক এপ্‌সমূহে আপুনি নজনাকৈ সম্পর্ক ডেটা শ্বেয়াৰ কৰিব পাৰে।"</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"এপ্‌টোক আপোনাৰ Android TV ডিভাইচত ষ্ট’ৰ কৰি ৰখা সম্পৰ্কবোৰৰ ডেটা পঢ়িবলৈ দিয়ে। এপ্‌সমূহৰ আপোনাৰ Android TV ডিভাইচটোত থকা একাউণ্টসমূহলৈও এক্সেছ থাকিব যিবোৰে সম্পৰ্কসমূহ সৃষ্টি কৰিছে। ইয়াত আপুনি ইনষ্টল কৰা এপ্‌সমূহে সৃষ্টি কৰা একাউণ্টসমূহ অন্তৰ্ভুক্ত হ’ব পাৰে। এই অনুমতিটোৱে এপ্‌সমূহক আপোনাৰ সম্পর্ক ডেটা ছেভ কৰিবলৈ দিয়ে আৰু ক্ষতিকাৰক এপ্‌সমূহে আপুনি নজনাকৈ সম্পর্ক ডেটা শ্বেয়াৰ কৰিব পাৰে।"</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"এপ্‌টোক আপোনাৰ ফ’নত ষ্ট’ৰ কৰি ৰখা সম্পৰ্কবোৰৰ ডেটা পঢ়িবলৈ দিয়ে। এপ্‌সমূহৰ আপোনাৰ ফ’নত থকা একাউণ্টসমূহলৈও এক্সেছ থাকিব যিবোৰে সম্পৰ্কসমূহ সৃষ্টি কৰিছে। ইয়াত আপুনি ইনষ্টল কৰা এপ্‌সমূহে সৃষ্টি কৰা একাউণ্টসমূহ অন্তৰ্ভুক্ত হ’ব পাৰে। এই অনুমতিটোৱে এপ্‌সমূহক আপোনাৰ সম্পর্ক ডেটা ছেভ কৰিবলৈ দিয়ে আৰু ক্ষতিকাৰক এপ্‌সমূহে আপুনি নজনাকৈ সম্পর্ক ডেটা শ্বেয়াৰ কৰিব পাৰে।"</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"আপোনাৰ সম্পর্ক সূচী সংশোধন কৰক"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"আপুনি ব্য়ক্তি বিশেষক কিমান সঘনাই কল কৰিছে, ইমেইল কৰিছে বা অন্য উপায়েৰে যোগাযোগ কৰিছে তাক অন্তৰ্ভুক্ত কৰি এপটোক আপোনাৰ টেবলেটত সঞ্চয় কৰি ৰখা সম্পৰ্ক সূচীৰ ডেটা সংশোধন কৰিবলৈ অনুমতি দিয়ে৷ এই অনুমতি দিলে এপসমূহে সম্পৰ্কসূচীৰ ডেটা মচিব পাৰে।"</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"এপ্‌টোক আপোনাৰ Android TV ডিভাইচটোত ষ্ট’ৰ কৰি ৰখা সম্পৰ্কবোৰৰ ডেটা সংশোধন কৰিবলৈ দিয়াৰ লগতে আপুনি কোনো বিশেষ ব্যক্তিৰ সৈতে কিমান সঘনাই কল, ইমেইল বা অন্য মাধ্যমেৰে যোগাযোগ কৰিছে তাকো জানিবলৈ অনুমতি দিয়ে। এই অনুমতিটোৱে এপ্‌সমূহক সম্পৰ্কসূচীৰ ডেটা মচিবলৈ অনুমতি দিয়ে।"</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"আপুনি কোনো বিশেষ ব্যক্তিৰ সৈতে কিমান সঘনাই ফ\'ন, ইমেইল বা অন্য মাধ্যমেৰে যোগাযোগ কৰে সেই সম্পর্কে ফ\'নৰ সম্পর্ক সূচীত সঞ্চয় কৰা ডেটা পঢ়িবলৈ এপক অনুমতি দিয়ে। এই কার্যই এপক সম্পর্কৰ ডেটা মচিবলৈ অনুমতি দিয়ে।"</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"এপ্‌টোক আপোনাৰ টেবলেটত ষ্ট’ৰ কৰি ৰখা সম্পৰ্কবোৰৰ ডেটা সংশোধন কৰিবলৈ দিয়ে। এই অনুমতিয়ে এপ্‌সমূহক সম্পর্ক ডেটা মচিবলৈ দিয়ে।"</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"এপ্‌টোক আপোনাৰ Android TV ডিভাইচত ষ্ট’ৰ কৰি ৰখা সম্পৰ্কবোৰৰ ডেটা সংশোধন কৰিবলৈ দিয়ে। এই অনুমতিয়ে এপ্‌সমূহক সম্পর্ক ডেটা মচিবলৈ দিয়ে।"</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"এপ্‌টোক আপোনাৰ ফ\'নত ষ্ট’ৰ কৰি ৰখা সম্পৰ্কবোৰৰ ডেটা সংশোধন কৰিবলৈ দিয়ে। এই অনুমতিয়ে এপ্‌সমূহক সম্পর্ক ডেটা মচিবলৈ দিয়ে।"</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"কল লগ পঢ়ক"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"এই এপে আপোনাৰ কলৰ ইতিহাস পঢ়িব পাৰে।"</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"কল লগ লিখক"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"অতিৰিক্ত অৱস্থান দেখুওৱা নির্দেশত প্ৰৱেশ কৰক"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"অৱস্থানৰ অতিৰিক্ত নির্দেশনাসমূহত প্ৰৱেশ কৰিবলৈ এপক অনুমতি দিয়ে। ইয়ে এপটোক জিপিএছ বা অন্য অৱস্থান উৎসসমূহৰ কাৰ্যকলাপত হস্তক্ষেপ কৰাৰ সুযোগ দিব পাৰে।"</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"কেৱল অগ্ৰভূমিত অৱস্থানৰ সঠিক তথ্য় পাওক"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"এই এপটোৱে যেতিয়া ই নেপথ্যত চলি থাকে তেতিয়া আপোনাৰ সঠিক অৱস্থান নিৰ্ণয় কৰিব পাৰে। এপটোৱে ব্যৱহাৰ কৰিব পৰাকৈ এই অৱস্থান সেৱাসমূহ অন হৈ থাকিবই লাগিব আৰু আপোনাৰ ফ\'নত উপলব্ধ হ\'ব লাগিব। ইয়াৰ ফলত বেটাৰিৰ খৰচ বাঢ়িব পাৰে।"</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"কেৱল অগ্ৰভূমিত থকা অৱস্থাতহে আনুমানিক অৱস্থানৰ (নেটৱৰ্কৰ ওপৰত ভিত্তি কৰি) এক্সেছ"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"এই এপটোৱে অগ্ৰভূমিত থকা অৱস্থাতহে চেল টাৱাৰ আৰু ৱাই-ফাই নেটৱৰ্ক আদিৰ দৰে নেটৱৰ্ক উৎসৰ ওপৰত ভিত্তি কৰি আপোনাৰ অৱস্থান জানিব পাৰে। এপটোৱে এই অৱস্থান সেৱাসমূহ ব্যৱহাৰ কৰিবলৈ হ\'লে সেইবোৰ অন হৈ থকাৰ লগতে আপোনাৰ টেবলেটত থাকিবই লাগিব।"</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"এই এপ্‌টোৱে অগ্ৰভূমিত থকা অৱস্থাতহে চেল টাৱাৰবোৰ আৰু ৱাই-ফাই নেটৱৰ্কবোৰৰ দৰে নেটৱৰ্ক উৎসবোৰৰ ওপৰত ভিত্তি কৰি আপোনাৰ অৱস্থান পাব পাৰে, কিন্তু কেৱল তেতিয়াহে যেতিয়া এপ্‌টো অগ্ৰভূমিত থাকে। এপ্‌টোৱে এই অৱস্থান সেৱাসমূহ ব্যৱহাৰ কৰিবলৈ সেইবোৰ আপোনাৰ Android TV ডিভাইচটোত অন কৰি ৰখাৰ লগতে উপলব্ধ হ’ব লাগিব।"</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"এই এপটোৱে অগ্ৰভূমিত থকা অৱস্থাতহে চেল টাৱাৰ আৰু ৱাই-ফাই নেটৱৰ্ক আদিৰ দৰে নেটৱৰ্ক উৎসৰ ওপৰত ভিত্তি কৰি আপোনাৰ অৱস্থান জানিব পাৰে। এপটোৱে এই অৱস্থান সেৱাসমূহ ব্যৱহাৰ কৰিবলৈ হ\'লে সেইবোৰ অন হৈ থকাৰ লগতে আপোনাৰ ফ\'নত থাকিবই লাগিব।"</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"এই এপ্‌টো কেৱল অগ্ৰভূমিত থাকিলেহে এইটোৱে আপোনাৰ সঠিক অৱস্থান লাভ কৰিব পাৰে। এপ্‌টোৱে অৱস্থান সেৱাসমূহ ব্যৱহাৰ কৰিবলৈ হ’লে সেইবোৰ অন হৈ থকাৰ লগতে সেয়া আপোনাৰ ডিভাইচত উপলব্ধ থাকিবই লাগিব। ইয়াৰ ফলত বেটাৰিৰ খৰচ বাঢ়িব পাৰে।"</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"কেৱল অগ্ৰভূমিত আনুমানিক অৱস্থান এক্সেছ কৰক"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"এই এপ্‌টো অগ্ৰভূমিত থাকিলেহে এইটোৱে আপোনাৰ আনুমানিক অৱস্থান লাভ কৰিব পাৰে। এপ্‌টোৱে অৱস্থান সেৱাসমূহ ব্যৱহাৰ কৰিবলৈ হ’লে সেইবোৰ অন হৈ থকাৰ লগতে সেয়া আপোনাৰ ডিভাইচত উপলব্ধ থাকিবই লাগিব।"</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"নেপথ্যত চলি থকা সময়ত অৱস্থানৰ এক্সেছ"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"ইয়াৰ উপৰিও যদি ইয়াক আনুমানিক বা সঠিক অৱস্থানৰ এক্সেছ দিয়া হয়, তেন্তে উক্ত এপে নেপথ্যত চলি থকাৰ সময়ত অৱস্থানৰ এক্সেছ লাভ কৰিব পাৰে।"</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"এই এপ্‌টোৱে অগ্ৰভূমিত অৱস্থান এক্সেছ কৰাৰ ওপৰিও নেপথ্যত চলি থাকিলেও অৱস্থান এক্সেছ কৰিব পাৰে।"</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"আপোনাৰ অডিঅ\' ছেটিংসমূহ সলনি কৰক"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"এপটোক ভলিউমৰ দৰে গ্ল\'বেল অডিঅ\' ছেটিংসমূহ যাৰ স্পীকাৰক আউটপুটৰ বাবে ব্যৱহাৰ হয় তাক সলনি কৰিবলৈ অনুমতি দিয়ে৷"</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"অডিঅ\' ৰেকর্ড কৰক"</string>
@@ -494,6 +491,8 @@
<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_preferredPaymentInfo" msgid="5274423844767445054">"অগ্ৰাধিকাৰ দিয়া NFC পৰিশোধ সেৱাৰ তথ্য"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"এপ্‌টোক অগ্ৰাধিকাৰ দিয়া nfc পৰিশোধ সেৱাৰ পঞ্জীকৃত সহায়কসমূহ আৰু পৰিশোধ কৰিব লগা লক্ষ্যস্থান দৰে তথ্য পাবলৈ অনুমতি দিয়ে।"</string>
<string name="permlab_nfc" msgid="1904455246837674977">"নিয়েৰ ফিল্ড কমিউনিকেশ্বন নিয়ন্ত্ৰণ কৰক"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"এপটোক নিয়েৰ ফিল্ড কমিউনিকেশ্বন (NFC) টেগ, কাৰ্ড আৰু ৰিডাৰসমূহৰ সৈতে যোগাযোগ কৰিবলৈ অনুমতি দিয়ে।"</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"আপোনাৰ স্ক্ৰীণ ল\'ক অক্ষম কৰক"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"দিব্যাংগসকলৰ সুবিধাৰ শ্বৰ্টকাটটোৱে <xliff:g id="SERVICE_NAME">%1$s</xliff:g>ক অন কৰিছে"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"দিব্যাংগসকলৰ সুবিধাৰ শ্বৰ্টকাটটোৱে <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>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"আপুনি সাধ্য সুবিধাৰ বুটামটো টিপিলে ব্যৱহাৰ কৰিবলৈ এটা সেৱা বাছনি কৰক:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"সাধ্য সুবিধা ভংগিমাৰ সৈতে ব্যৱহাৰ কৰিবলৈ এটা সেৱা বাছনি কৰক (দুটা আঙুলিৰে স্ক্রীণখনৰ একেবাৰে তলিৰ পৰা ওপৰলৈ ছোৱাইপ কৰক):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"সাধ্য সুবিধা ভংগিমাৰ সৈতে ব্যৱহাৰ কৰিবলৈ এটা সেৱা বাছনি কৰক (তিনিটা আঙুলিৰে স্ক্রীণখনৰ একেবাৰে তলিৰ পৰা ওপৰলৈ ছোৱাইপ কৰক):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"সেৱাসমূহ সালসলনিকৈ ব্যৱহাৰ কৰিবলৈ সাধ্য সুবিধাৰ বুটামটো স্পৰ্শ কৰি ধৰি ৰাখক।"</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"সেৱাসমূহ সালসলনিকৈ ব্যৱহাৰ কৰিবলৈ দুটা আঙুলিৰে ওপৰলৈ ছোৱাইপ কৰি ধৰি ৰাখক।"</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"সেৱাসমূহ সালসলনিকৈ ব্যৱহাৰ কৰিবলৈ তিনিটা আঙুলিৰে ওপৰলৈ ছোৱাইপ কৰি ধৰি ৰাখক।"</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>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g>ৰ সৈতে সংযুক্ত হৈ আছে"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"ফাইলসমূহ চাবৰ বাবে টিপক"</string>
<string name="pin_target" msgid="8036028973110156895">"পিন"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"<xliff:g id="LABEL">%1$s</xliff:g>ক পিন কৰক"</string>
<string name="unpin_target" msgid="3963318576590204447">"আনপিন"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"<xliff:g id="LABEL">%1$s</xliff:g>ক আনপিন কৰক"</string>
<string name="app_info" msgid="6113278084877079851">"এপ্ সম্পৰ্কীয় তথ্য"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"ডেম\' আৰম্ভ কৰি থকা হৈছে…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"এই তথ্যবোৰ "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <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>ত আপডে’ট কৰিবনে ?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"ছেভ কৰক"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"নালাগে, ধন্যবাদ"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"এতিয়া নহয়"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"কেতিয়াও নহয়"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"আপডে’ট কৰক"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"অব্যাহত ৰাখক"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"পাছৱৰ্ড"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"বিভাজিত স্ক্ৰীন ট’গল কৰক"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"লক স্ক্ৰীন"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"স্ক্ৰীণশ্বট"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"পপ আপ ৱিণ্ড’ত <xliff:g id="APP_NAME">%1$s</xliff:g> এপ্‌।"</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ কেপশ্বন বাৰ।"</string>
</resources>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index 359dfb757014..829b8a099c81 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"İş profili admin tətbiqi ya yoxdur, ya da korlanıb. Nəticədə iş profili və onunla bağlı data silinib. Kömək üçün admin ilə əlaqə saxlayın."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"İş profili artıq bu cihazda əlçatan deyil"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Həddindən çox parol cəhdi"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Admin şəxsi istifadə üçün cihazdan imtina etdi"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Cihaz idarə olunur"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Təşkilat bu cihazı idarə edir və şəbəkənin ötürülməsinə nəzarət edə bilər. Detallar üçün klikləyin."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Cihazınız təmizlənəcəkdir"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Tətbiqə yayım bitdikdən sonra qalan əlaqələndirici yayımları göndərmək icazəsi verir. Həddindən çox istifadə Android TV cihazının daha çox yaddaşdan istifadə etməsinə səbəb olaraq onun surətini zəiflədə və stabilliyini poza bilər."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Tətbiqə yayım bitdikdən sonra da qalan çətin yayımlar göndərməyə imkan verir. Hədsiz istifadə çox yaddaş istifadəsinə səbəb olmaqla telefonu yavaş və qeyri-stabil edə bilər."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"kontakrlatınızı oxumaq"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Tətbiqə planşetinizdə yerləşən kontaktları oxumaq icazəsi verir, tez-tez zəng elədiyiniz, emailləşdiyiniz və ya əlaqə saxladığınız xüsusi individuallar daxil olmaqla. Bu icazə tətbiqlərə kontakt məlumatlarınızı saxlamağa və zərərli tətbiqlərə kontakt məlumatlarını sizin bilginiz olmada paylaşma imkanı yaradır."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Tətbiqə xüsusi şəxslərə hansı müddətdən bir zəng etmək, e-poçt göndərmək və ya onlarla başqa şəkildə əlaqə saxlamaq daxil olmaqla, Android TV cihazında saxlanan kontaktlar haqqında datanı oxumaq icazəsi verir. Bu icazə proqramlara əlaqə məlumatlarınızı saxlamaq imkanı verir və zərərli proqramlar sizin xəbəriniz olmadan əlaqə məlumatlarınızı paylaşa bilər."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Tətbiqə tez-tez zəng elədiyiniz, e-məktub göndərdiyiniz və ya əlaqə saxladığınız xüsusi individuallar daxil olmaqla telefonunuzda yerləşən kontaktları oxumaq icazəsi verir. Bu icazə tətbiqlərə kontakt məlumatlarınızı saxlamağa və zərərli tətbiqlərə kontakt məlumatlarını sizin xəbəriniz olmada paylaşma imkanı yaradır."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Tətbiqə planşetinizdə saxlanılan kontaktlar haqqında datanı oxumaq icazəsi verir. Tətbiqlərin, həmçinin planşetinizdə kontaktlar yaradan hesablara da giriş imkanı olacaq. Buraya quraşdırdığınız tətbiqlər tərəfindən yaradılan hesablar daxil ola bilər. Bu icazə tətbiqlərə kontakt məlumatlarınızı yadda saxlamaq imkanı verir və zərərli tətbiqlər kontakt məlumatlarını xəbəriniz olmadan paylaşa bilər."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Tətbiqə Android TV cihazınızda saxlanan kontaktlar haqqında datanı oxumaq icazəsi verir. Tətbiqlərin, həmçinin Android TV cihazınızda kontaktlar yaradan hesablara da giriş imkanı olacaq. Buraya quraşdırdığınız tətbiqlər tərəfindən yaradılan hesablar daxil ola bilər. Bu icazə tətbiqlərə kontakt məlumatlarınızı yadda saxlamaq imkanı verir və zərərli tətbiqlər kontakt məlumatlarını xəbəriniz olmadan paylaşa bilər."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Tətbiqə telefonunuzda saxlanılan kontaktlar haqqında datanı oxumaq icazəsi verir. Tətbiqlərin, həmçinin telefonunuzda kontaktlar yaradan hesablara da giriş imkanı olacaq. Buraya quraşdırdığınız tətbiqlər tərəfindən yaradılan hesablar daxil ola bilər. Bu icazə tətbiqlərə kontakt məlumatlarınızı yadda saxlamaq imkanı verir və zərərli tətbiqlər kontakt məlumatlarını xəbəriniz olmadan paylaşa bilər."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"kontaktlarınızı dəyişdirir"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Tətbiqə planşetinizdəki zəng etmək tezliyiniz, elektron poçtlarınız, ünsiyyətləriniz haqqında məlumatları dəyişməyə imkan verir. Bu icazə kontakt məlumatlarının silinməsinə də imkan verir."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Tətbiqə xüsusi şəxslərə hansı müddətdən bir zəng etmək, e-poçt göndərmək və ya onlarla başqa şəkildə əlaqə saxlamaq daxil olmaqla, Android TV cihazında saxlanan kontaktlar haqqında datanı dəyişdirmək icazəsi verir. Bu icazə tətbiqlərə kontakt datasını silmək imkanı verir."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Tətbiqə Sizin zəng etmək tezliyiniz, elektron poçtlarınız, ünsiyyətləriniz haqqında məlumatları dəyişməyə imkan verir. Buna kontaktların silinməsi imkanı də daxildir."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Tətbiqə planşetinizdə saxlanan kontaktlar haqqında datanı dəyişdirmək icazəsi verir. Bu icazə tətbiqlərə kontakt datasını silmək imkanı verir."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Tətbiqə Android TV cihazında saxlanan kontaktlar haqqında datanı dəyişdirmək icazəsi verir. Bu icazə tətbiqlərə kontakt datasını silmək imkanı verir."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Tətbiqə telefonunuzda saxlanan kontaktlar haqqında datanı dəyişdirmək icazəsi verir. Bu icazə tətbiqlərə kontakt datasını silmək imkanı verir."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"zəng qeydiyyatını oxu"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Bu tətbiq zəng tarixçənizi oxuya bilər."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"zəng loqu yazır"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"əlavə məkan provayderi əmrlərinə çıxış"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Tətbiqə ekstra məkan provayder əmrlərinə girişə imkan verir. Bu, tətbiqə GPS və ya digər lokal mənbələrlə əməliyyata müdaxiləyə imkan verə bilər."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"yalnız ön planda dəqiq məkana daxil olun"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Bu tətbiq yalnız ön fonda olduqda dəqiq məkanınızı əldə edə bilər. Tətbiqin bunlardan istifadə etməsi üçün bu məkan xidmətləri aktiv edilməlidir və telefonda əlçatan olmalıdır. Bu, batareya sərfiyyatını artıra bilər."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"yalnız ön planda təxmini məkana (şəbəkəyə əsaslanan) giriş"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Bu tətbiq baza stansiyaları və Wi-Fi şəbəkələri kimi şəbəkə mənbələrinə əsaslanaraq məkanınızı əldə edə bilər. Bu, yalnız tətbiq ön planda olduqda mümkündür. Tətbiqin istifadə edə bilməsi üçün bu məkan xidmətləri aktiv edilməli və planşetdə əlçatan olmalıdır."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Bu tətbiq baza stansiyaları və Wi-Fi kimi şəbəkə mənbələrinə əsaslanaraq məkanınızı əldə edə bilər. Bu, yalnız tətbiq ön planda olduqda mümkündür. Tətbiqin istifadə etməsi üçün bu məkan xidmətləri aktiv edilməli və Android TV cihazında əlçatan olmalıdır."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Bu tətbiq baza stansiyaları və Wi-Fi kimi şəbəkə mənbələrinə əsaslanaraq məkanınızı əldə edə bilər. Bu, yalnız tətbiq ön planda olduqda mümkündür. Tətbiqin istifadə edə bilməsi üçün bu məkan xidmətləri aktiv edilməli və telefonda əlçatan olmalıdır."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Bu tətbiq yalnız ön fonda olduqda dəqiq məkanınızı əldə edə bilər. Tətbiqin bunlardan istifadə etməsi üçün məkan xidmətləri aktiv edilməli və cihazda əlçatan olmalıdır. Bu, batareya sərfiyyatını artıra bilər."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"yalnız ön planda təqribi məkana giriş"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Bu tətbiq yalnız ön fonda olduqda təqribi məkanınızı əldə edə bilər. Tətbiqin istifadə edə bilməsi üçün məkan xidmətləri cihazda aktiv edilməli və əlçatan olmalıdır."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"arxa fonda məkan girişi"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Bu, təqribi və ya dəqiq məkan girişinə əlavə olaraq verilərsə, tətbiq arxa fonda işləyərkən məkana daxil ola bilər."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Bu tətbiq ön planda məkana girişlə yanaşı, arxa fonda işləyərkən məkana giriş edə bilər."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"audio ayarlarınızı dəyişir"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Tətbiqə səs və hansı spikerin çıxış üçün istifadə olunduğu kimi qlobal səs ayarlarını dəyişdirməyə imkan verir."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"səs yaz"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Tətbiqə yerli Bluetooth planşetinin konfiqurasiyasını görməyə və cütlənmiş cihazlarla bağlantılar etməyə və qəbul etməyə imkan verir."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Tətbiqə Android TV cihazında Bluetooth konfiqurasiyasına baxmaq, həmçinin qoşulmuş cihazlar ilə bağlantılar yaratmaq və qəbul etmək icazəsi verir."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Tətbiqə Bluetooth və ya telefon konfiqurasiyalarını görməyə və qoşulmuş cihazlarla əlaqə qurmağa və qəbul etməyə icazə verir."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Tərcih edilən NFC ödəniş xidməti məlumatı"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Tətbiqə qeydiyyatdan keçmiş yardım və marşrut təyinatı kimi tərcih edilən nfc ödəniş xidməti məlumatını əldə etmək icazəsi verir."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"Near Field Communication\'ı kontrol et"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Tətbiqə Yaxın Məsafə Kommunikasiyası (NFC) teqləri, kartları və oxuyucuları ilə əlaqə qurmağa icazə verir."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"Ekran kilidini deaktiv edir"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"Əlçatımlıq Qısayolu <xliff:g id="SERVICE_NAME">%1$s</xliff:g> xidmətini aktiv etdi"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"Əlçatımlıq Qısayolu <xliff:g id="SERVICE_NAME">%1$s</xliff:g> xidmətini deaktiv etdi"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> istifadə etmək üçün hər iki səs düyməsini üç saniyə basıb saxlayın"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Əlçatımlılıq düyməsinə toxunduqda istifadə etmək üçün xidmət seçin:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Əlçatımlılıq jestləri (iki barmağınızla ekranın aşağısından yuxarı doğru sürüşdürün) ilə istifadə etmək üçün xidmət seçin:"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Əlçatımlılıq jestləri (üç barmağınızla ekranın aşağısından yuxarı doğru sürüşdürün) ilə istifadə etmək üçün xidmət seçin:"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Xidmətlər arasında keçid etmək üçün əlçatımlılıq düyməsinə basın &amp; saxlayın."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Xidmətlər arasında keçid etmək üçün ekranı iki barmağınızla yuxarı sürüşdürüb saxlayın."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Xidmətlər arasında keçid etmək üçün ekranı üç barmağınızla yuxarı sürüşdürüb saxlayın."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Böyütmə"</string>
<string name="user_switched" msgid="7249833311585228097">"Cari istifadəçi <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="1912993630661332336">"<xliff:g id="NAME">%1$s</xliff:g> adına keçirilir…"</string>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> məhsuluna bağlandı"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Faylları görmək üçün basın"</string>
<string name="pin_target" msgid="8036028973110156895">"Pin kod"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"İşarələyin: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Çıxarın"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"İşarələməyin: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Tətbiq məlumatı"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Demo başlayır…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Bu elementlər "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" ünvanında yenilənsin: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> və <xliff:g id="TYPE_2">%3$s</xliff:g> ?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Yadda saxlayın"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Xeyr, çox sağ olun"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"İndi yox"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Heç vaxt"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Yeniləyin"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Davam edin"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"parol"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Bölünmüş Ekrana keçid"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Kilid Ekranı"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Ekran şəkli"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"Açilən pəncərədə <xliff:g id="APP_NAME">%1$s</xliff:g> tətbiqi."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> başlıq paneli."</string>
</resources>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index a27d3590dbd1..790987258e36 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -190,8 +190,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Aplikacija za administratore na profilu za Work nedostaje ili je oštećena. Zbog toga su profil za Work i povezani podaci izbrisani. Obratite se administratoru za pomoć."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Profil za Work više nije dostupan na ovom uređaju"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Previše pokušaja unosa lozinke"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Administrator je ustupio uređaj za ličnu upotrebu"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Uređajem se upravlja"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Organizacija upravlja ovim uređajem i može da nadgleda mrežni saobraćaj. Dodirnite za detalje."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Uređaj će biti obrisan"</string>
@@ -384,13 +383,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Dozvoljava aplikaciji da šalje lepljiva emitovanja koja ostaju po završetku emitovanja. Prekomerna upotreba može da uspori ili destabilizuje Android TV uređaj tako što će ga primorati da troši previše memorije."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Dozvoljava aplikaciji da šalje prijemčiva emitovanja, koja ostaju po završetku emitovanja. Prekomerna upotreba može da uspori ili destabilizuje telefon tako što će ga primorati da troši previše memorije."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"čitanje kontakata"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Dozvoljava aplikaciji da čita podatke o kontaktima uskladištene na tabletu, uključujući podatke o tome koliko često zovete određene osobe, šaljete im poruke e-pošte ili na drugi način komunicirate sa njima. Ova dozvola omogućava aplikacijama da čuvaju podatke o kontaktima, a zlonamerne aplikacije mogu da dele podatke o kontaktima bez vašeg znanja."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Dozvoljava aplikaciji da čita podatke o kontaktima koje čuvate na Android TV uređaju, uključujući učestalost poziva, slanja imejlova ili drugih načina komunikacije sa određenim pojedincima. Ova dozvola omogućava aplikacijama da čuvaju podatke o kontaktima i zlonamerne aplikacije mogu da dele podatke o kontaktima bez vašeg znanja."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Dozvoljava aplikaciji da čita podatke o kontaktima uskladištene na telefonu, uključujući podatke o tome koliko često zovete određene osobe, šaljete im poruke e-pošte ili na drugi način komunicirate sa njima. Ova dozvola omogućava aplikacijama da čuvaju podatke o kontaktima, a zlonamerne aplikacije mogu da dele podatke o kontaktima bez vašeg znanja."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Dozvoljava aplikaciji da čita podatke o kontaktima koje čuvate na tabletu. Aplikacije će imati pristup i nalozima na vašem tabletu na kojima su napravljeni kontakti. Tu mogu da spadaju nalozi koje su otvorile aplikacije koje ste instalirali. Ova dozvola omogućava aplikacijama da čuvaju podatke o kontaktima i zlonamerne aplikacije mogu da dele podatke o kontaktima bez vašeg znanja."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Dozvoljava aplikaciji da čita podatke o kontaktima koje čuvate na Android TV uređaju. Aplikacije će imati pristup i nalozima na vašem Android TV uređaju na kojima su napravljeni kontakti. Tu mogu da spadaju nalozi koje su otvorile aplikacije koje ste instalirali. Ova dozvola omogućava aplikacijama da čuvaju podatke o kontaktima i zlonamerne aplikacije mogu da dele podatke o kontaktima bez vašeg znanja."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Dozvoljava aplikaciji da čita podatke o kontaktima koje čuvate na telefonu. Aplikacije će imati pristup i nalozima na vašem telefonu na kojima su napravljeni kontakti. Tu mogu da spadaju nalozi koje su otvorile aplikacije koje ste instalirali. Ova dozvola omogućava aplikacijama da čuvaju podatke o kontaktima i zlonamerne aplikacije mogu da dele podatke o kontaktima bez vašeg znanja."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"izmena kontakata"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Dozvoljava aplikaciji da menja podatke o kontaktima uskladištene na tabletu, uključujući podatke o tome koliko često zovete određene kontakte, šaljete im poruke e-pošte ili na drugi način komunicirate sa njima. Ova dozvola omogućava aplikacijama da brišu podatke o kontaktima."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Dozvoljava aplikaciji da menja podatke o kontaktima koje čuvate na Android TV uređaju, uključujući učestalost poziva, slanja imejlova ili drugih načina komunikacije sa određenim kontaktima. Ova dozvola omogućava aplikacijama da brišu podatke o kontaktima."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Dozvoljava aplikaciji da menja podatke o kontaktima uskladištene na telefonu, uključujući podatke o tome koliko često zovete određene kontakte, šaljete im poruke e-pošte ili na drugi način komunicirate sa njima. Ova dozvola omogućava aplikacijama da brišu podatke o kontaktima."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Dozvoljava aplikaciji da menja podatke o kontaktima koje čuvate na tabletu. Ova dozvola omogućava aplikacijama da brišu podatke o kontaktima."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Dozvoljava aplikaciji da menja podatke o kontaktima koje čuvate na Android TV uređaju. Ova dozvola omogućava aplikacijama da brišu podatke o kontaktima."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Dozvoljava aplikaciji da menja podatke o kontaktima koje čuvate na telefonu. Ova dozvola omogućava aplikacijama da brišu podatke o kontaktima."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"čitanje evidencije poziva"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Ova aplikacija može da čita istoriju poziva."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"pisanje evidencije poziva"</string>
@@ -410,13 +409,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"pristup dodatnim komandama dobavljača lokacije"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Omogućava aplikaciji da pristupa dodatnim komandama davaoca usluga lokacije. To može da omogući aplikaciji da utiče na rad GPS-a ili drugih izvora lokacije."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"pristup preciznoj lokaciji samo u prvom planu"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Ova aplikacija može da odredi vašu tačnu lokaciju samo kada radi u prvom planu. Ove usluge lokacije moraju da budu uključene i dostupne na telefonu da bi aplikacija mogla da ih koristi. To može da poveća potrošnju baterije."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"pristup približnoj lokaciji (utvrđenoj preko mreže) samo u prvom planu"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Ova aplikacija može da pristupi vašoj lokaciji pomoću izvora mreže, kao što su mobilni predajnici i Wi-Fi mreže, ali samo kada aplikacija radi u prvom planu. Ove usluge lokacije moraju da budu uključene i dostupne na tabletu da bi aplikacija mogla da ih koristi"</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Ova aplikacija može da pristupi vašoj lokaciji pomoću izvora mreže, kao što su mobilni predajnici i Wi-Fi mreže, ali samo kada aplikacija radi u prvom planu. Ove usluge lokacije moraju da budu uključene i dostupne na Android TV uređaju da bi aplikacija mogla da ih koristi."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Ova aplikacija može da pristupi vašoj lokaciji pomoću izvora mreže, kao što su mobilni predajnici i Wi-Fi mreže, ali samo kada aplikacija radi u prvom planu. Ove usluge lokacije moraju da budu uključene i dostupne na telefonu da bi aplikacija mogla da ih koristi."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Ova aplikacija može da odredi vašu tačnu lokaciju samo kada radi u prvom planu. Usluge lokacije moraju da budu uključene i dostupne na uređaju da bi aplikacija mogla da ih koristi. To može da poveća potrošnju baterije."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"pristup približnoj lokaciji samo u prvom planu"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Ova aplikacija može da odredi vašu približnu lokaciju samo kada radi u prvom planu. Usluge lokacije moraju da budu uključene i dostupne na uređaju da bi aplikacija mogla da ih koristi."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"pristup lokaciji u pozadini"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Ako se pored približnog ili preciznog pristupa lokacija odobri i ovaj, aplikacija može da pristupa lokaciji dok je pokrenuta u pozadini."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Ova aplikacija može da pristupa lokaciji dok radi u pozadini, kao i kada radi u prvom planu."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"promena audio podešavanja"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Dozvoljava aplikaciji da menja globalna audio podešavanja kao što su jačina zvuka i izbor zvučnika koji se koristi kao izlaz."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"snimanje audio zapisa"</string>
@@ -497,6 +494,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Dozvoljava aplikaciji da pregleda konfiguraciju Bluetooth-a na tabletu, kao i da uspostavlja i prihvata veze sa uparenim uređajima."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Dozvoljava aplikaciji da pregleda konfiguraciju Bluetooth-a na Android TV uređaju i da uspostavlja i prihvata veze sa uparenim uređajima."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Dozvoljava aplikaciji da pregleda konfiguraciju Bluetooth-a na telefonu, kao i da uspostavlja i prihvata veze sa uparenim uređajima."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Informacije o željenoj NFC usluzi za plaćanje"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Dozvoljava aplikaciji da preuzima informacije o željenoj NFC usluzi za plaćanje, poput registrovanih identifikatora aplikacija i odredišta preusmeravanja."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"kontrola komunikacije u užem polju (Near Field Communication)"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Dozvoljava aplikaciji da komunicira sa oznakama, karticama i čitačima komunikacije kratkog dometa (NFC)."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"onemogućavanje zaključavanja ekrana"</string>
@@ -1640,12 +1639,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"Prečica za pristupačnost je uključila uslugu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"Prečica za pristupačnost je isključila uslugu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Pritisnite i zadržite oba tastera za jačinu zvuka tri sekunde da biste koristili <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Odaberite uslugu koja će se koristiti kada dodirnete dugme za pristupačnost:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Odaberite funkciju koja će se koristiti pomoću pokreta za pristupačnost (pomoću dva prsta prevucite nagore od dna ekrana):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Odaberite uslugu koja će se koristiti pomoću pokreta za pristupačnost (pomoću tri prsta prevucite nagore od dna ekrana):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Da biste prelazili sa jedne usluge na drugu, dodirnite i zadržite dugme za pristupačnost."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Da biste prelazili sa jedne usluge na drugu, prevucite nagore pomoću dva prsta i zadržite."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Da biste prelazili sa jedne usluge na drugu, prevucite nagore pomoću tri prsta i zadržite."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Uvećanje"</string>
<string name="user_switched" msgid="7249833311585228097">"Aktuelni korisnik <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="1912993630661332336">"Prebacivanje na <xliff:g id="NAME">%1$s</xliff:g>…"</string>
@@ -1894,7 +1887,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Povezano je sa proizvodom <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Dodirnite za pregled datoteka"</string>
<string name="pin_target" msgid="8036028973110156895">"Zakači"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Zakači aplikaciju <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Otkači"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Otkači aplikaciju <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Informacije o aplikaciji"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Pokrećemo demonstraciju..."</string>
@@ -1938,6 +1933,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Želite li da ažurirate ove stavke u usluzi "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> i <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Sačuvaj"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Ne, hvala"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Ne sada"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Nikada"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Ažuriraj"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Nastavi"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"lozinka"</string>
@@ -2034,5 +2031,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Uključite/isključite podeljeni ekran"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Zaključani ekran"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Snimak ekrana"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> u iskačućem prozoru."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Traka sa naslovima aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index fb0fa33259f5..306934bdf6b1 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -192,8 +192,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Праграма адміністратара для працоўнага профілю адсутнічае або пашкоджана. У выніку гэтага ваш працоўны профіль і звязаныя з ім даныя былі выдалены. Звярніцеся па дапамогу да адміністратара."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Ваш працоўны профіль больш не даступны на гэтай прыладзе"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Занадта шмат спроб уводу пароля"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Адміністратар пераналадзіў прыладу для асабістага выкарыстання"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Прылада знаходзіцца пад кіраваннем"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Ваша арганізацыя кіруе гэтай прыладай і можа сачыць за сеткавым трафікам. Дакраніцеся для атрымання дадатковай інфармацыі."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Даныя вашай прылады будуць сцерты"</string>
@@ -387,13 +386,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Дазваляе праграме адпраўляць замацаваныя трансляцыі, якія застаюцца пасля заканчэння асноўнай трансляцыі. Злоўжыванне гэтым можа зрабіць працу прылады Android TV павольнай або няўстойлівай, прымушаючы яе выкарыстоўваць занадта шмат памяці."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Дазваляе прыкладанню адпраўляць далейшыя звязаныя перадачы, якія застаюцца пасля заканчэння асноўнай перадачы. Злоўжыванне можа зрабіць працу тэлефона павольнай або няўстойлівай, прымушаючы яго выкарыстоўваць занадта шмат памяці."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"чытанне кантактаў"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Дазваляе прыкладанням счытваць дадзеныя аб кантактах, якія захоўваюцца на планшэце, у тым ліку звесткi пра тое, як часта вы выклiкалi канкрэтных абанентаў, пiсалi iм па электроннай пошце або кантактавалi іншымi спосабамі. Дзякуючы гэтаму дазволу прыкладаннi могуць захоўваць дадзеныя гiсторыi выклiкаў, а шкоднасныя прыкладаннi могуць адпраўляць кантактныя дадзеныя без вашага ведама."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Дазваляе праграме счытваць даныя пра кантакты, якія захоўваюцца на прыладзе Android TV, у тым ліку звесткі пра тое, як часта вы выклікалі пэўных абанентаў, пісалі ім электронныя лісты ці звязваліся з імі іншымі спосабамі. Гэты дазвол дае праграмам магчымасць захоўваць даныя пра кантакты, а шкодныя праграмы могуць абагульваць гэтыя даныя без вашага ведама."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Дазваляе прыкладанням счытваць дадзеныя аб кантактах, якія захоўваюцца на тэлефоне, у тым ліку звесткi пра частату, з якой вы выклiкалi iх, пiсалi iм па электроннай пошце ці кантактавалi іншым спосабам. Дзякуючы гэтаму дазволу прыкладаннi могуць захоўваць дадзеныя гiсторыi выклiкаў, а шкоднасныя прыкладаннi могуць адпраўляць кантактныя дадзеныя без вашага ведама."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Дазваляе праграме счытваць даныя пра кантакты, якія захоўваюцца на вашым планшэце. Праграмы таксама атрымаюць доступ на планшэце да ўліковых запісаў, у якіх створаны кантакты. Сярод іх могуць быць уліковыя запісы, створаныя праграмамі, якія вы ўсталявалі. Гэты дазвол дае праграмам магчымасць захоўваць даныя пра кантакты, а шкодныя праграмы могуць абагульваць гэтыя даныя без вашага ведама."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Дазваляе праграме счытваць даныя пра кантакты, якія захоўваюцца на вашай прыладзе Android TV. Праграмы таксама атрымаюць доступ да ўліковых запісаў на прыладзе Android TV, у якіх створаны кантакты. Сярод іх могуць быць уліковыя запісы, створаныя праграмамі, якія вы ўсталявалі. Гэты дазвол дае праграмам магчымасць захоўваць даныя пра кантакты, а шкодныя праграмы могуць абагульваць гэтыя даныя без вашага ведама."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Дазваляе праграме счытваць даныя пра кантакты, якія захоўваюцца на вашым тэлефоне. Праграмы таксама атрымаюць доступ на тэлефоне да ўліковых запісаў, у якіх створаны кантакты. Сярод іх могуць быць уліковыя запісы, створаныя праграмамі, якія вы ўсталявалі. Гэты дазвол дае праграмам магчымасць захоўваць даныя пра кантакты, а шкодныя праграмы могуць абагульваць гэтыя даныя без вашага ведама."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"змена кантактаў"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Дазваляе прыкладанням змяняць дадзеныя аб кантактах, якія захоўваюцца на планшэце, у тым ліку частата, з якой вы выклiкалi асоб, пiсалi па электроннай пошце ці іншым спосабам кантактавалi з iмі. З гэтым дазволам прыкладаннi змогуць выдаляць кантактныя дадзеныя."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Дазваляе праграме змяняць даныя пра кантакты, якія захоўваюцца на прыладзе Android TV, у тым ліку звесткі пра тое, як часта вы выклікалі пэўных абанентаў, пісалі ім электронныя лісты ці звязваліся з імі іншымi спосабамі. Гэты дазвол дае праграмам магчымасць выдаляць даныя пра кантакты."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Дазваляе прыкладанням змяняць дадзеныя аб кантактах, якія захоўваюцца на тэлефоне, у тым ліку частата, з якой вы выклiкалi асоб, пiсалi па электроннай пошце ці іншым спосабам кантактавалi з iмі. З гэтым дазволам прыкладаннi змогуць выдаляць кантактныя дадзеныя."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Дазваляе праграме змяняць даныя пра кантакты, якія захоўваюцца на вашым планшэце. Гэты дазвол дае праграмам магчымасць выдаляць даныя пра кантакты."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Дазваляе праграме змяняць даныя пра кантакты, якія захоўваюцца на вашай прыладзе Android TV. Гэты дазвол дае праграмам магчымасць выдаляць даныя пра кантакты."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Дазваляе праграме змяняць даныя пра кантакты, якія захоўваюцца на вашым тэлефоне. Гэты дазвол дае праграмам магчымасць выдаляць даныя пра кантакты."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"чытанне гiсторыi выклікаў"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Гэта праграма можа чытаць вашу гісторыю выклікаў."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"запіс гiсторыi выклікаў"</string>
@@ -413,13 +412,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"доступ да дадатковых камандаў пастаўшчыка месцазнаходжання"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Дазваляе праграме атрымліваць доступ да дадатковых каманд службаў вызначэння месцазнаходжання. Гэта можа дазволіць праграме ўмешвацца ў функцыянаванне GPS або іншых крыніц даных аб месцазнаходжаннi."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"доступ да дакладнага месцазнаходжання толькі ў асноўным рэжыме"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Гэта праграма можа атрымліваць звесткі пра ваша дакладнае месцазнаходжанне толькі ў асноўным рэжыме. Службы геалакацыі павінны быць уключаны і даступныя на вашым тэлефоне, каб праграма магла імі карыстацца. Гэта можа павялічыць спажыванне зараду акумулятара."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"доступ да прыблізнага месцазнаходжання (на падставе сеткі) толькі ў актыўным рэжыме"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Гэта праграма можа атрымліваць звесткі пра ваша месцазнаходжанне толькі ў актыўным рэжыме на падставе даных сеткавых крыніц, такіх як вышкі сотавай сувязі і сеткі Wi-Fi. Каб праграма магла карыстацца гэтымі службамі геалакацыі, неабходна ўключыць і зрабіць іх даступнымі на планшэце."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Гэта праграма можа атрымліваць звесткі пра ваша месцазнаходжанне толькі ў актыўным рэжыме на падставе даных сеткавых крыніц, такіх як вышкі сотавай сувязі і сеткі Wi-Fi. Уключыце гэтыя службы геалакацыі і зрабіце іх даступнымі на прыладзе Android TV, каб праграма магла выкарыстоўваць іх даныя."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Гэта праграма можа атрымліваць звесткі пра ваша месцазнаходжанне толькі ў актыўным рэжыме на падставе даных сеткавых крыніц, такіх як вышкі сотавай сувязі і сеткі Wi-Fi. Каб праграма магла карыстацца гэтымі службамі геалакацыі, неабходна ўключыць і зрабіць іх даступнымі на тэлефоне."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Гэта праграма можа атрымліваць звесткі пра ваша дакладнае месцазнаходжанне толькі ў актыўным рэжыме. Службы геалакацыі павінны быць уключаны і даступныя на вашай прыладзе, каб праграма магла імі карыстацца. Гэта можа павялічыць спажыванне зараду акумулятара."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"доступ да прыблізнага месцазнаходжання толькі ў актыўным рэжыме"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Гэта праграма можа атрымліваць звесткі пра ваша прыблізнае месцазнаходжанне толькі ў актыўным рэжыме. Службы геалакацыі павінны быць уключаны і даступныя на вашай прыладзе, каб праграма магла імі карыстацца."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"доступ да вызначэння месцазнаходжання ў фонавым рэжыме"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Акрамя доступу да прыкладнага ці дакладнага месцазнаходжання праграма можа мець доступ да вызначэння геалакацыі ў фонавым рэжыме працы. На гэта патрабуецца дазвол."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Гэта праграма можа мець доступ да даных пра месцазнаходжанне не толькі ў актыўным, але і ў фонавым рэжыме."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"змяняць налады аудыё"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Дазваляе прыкладанням змяняць глабальныя налады гуку, такія як моц і тое, што дынамік выкарыстоўваецца для выхаду."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"запіс аўдыя"</string>
@@ -500,6 +497,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Дазваляе прыкладанню праглядаць канфігурацыю Bluetooth на планшэце , а таксама здзяйсняць і прымаць злучэнні са спалучанымі прыладамі."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Дазваляе праграме праглядаць канфігурацыю Bluetooth на прыладзе Android TV, а таксама выконваць і дазваляць злучэнні са спалучанымі прыладамі."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Дазваляе прыкладанню праглядаць канфігурацыю Bluetooth на тэлефоне , а таксама здзяйсняць і прымаць злучэнні са спалучанымі прыладамі."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Інфармацыя пра прыярытэтны сэрвіс аплаты NFC"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Дазваляе праграме атрымаць доступ да інфармацыі пра прыярытэтны сэрвіс аплаты NFC, напрыклад зарэгістраваныя ідэнтыфікатары праграм і маршруты адпраўкі даных."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"кантроль Near Field Communication"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Дазваляе прыкладаннzv спалучацца з тэгамі, картамі і счытваючымі прыладамі Near Field Communication (NFC)."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"адключэнне блакiроўкi экрана"</string>
@@ -1662,12 +1661,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> быў уключаны з дапамогай камбінацыі хуткага доступу для спецыяльных магчымасцей"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"<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>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Выберыце службу для выкарыстання пры націску кнопкі \"Спецыяльныя магчымасці\":"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Выберыце службу, дзе будзе выкарыстоўвацца жэст спецыяльных магчымасцей (правесці двума пальцамі па экране знізу ўверх):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Выберыце службу, дзе будзе выкарыстоўвацца жэст спецыяльных магчымасцей (правесці двума пальцамі па экране знізу ўверх):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Каб пераключыцца на другую службу, націсніце і ўтрымлівайце кнопку спецыяльных магчымасцей."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Каб пераключыцца на другую службу, правядзіце ўверх двума пальцамі, утрымліваючы іх на экране."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Каб пераключыцца на іншую службу, правядзіце ўверх трыма пальцамі, утрымліваючы іх на экране."</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>
@@ -1926,7 +1919,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Падлучана да <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Краніце для прагляду файлаў"</string>
<string name="pin_target" msgid="8036028973110156895">"Замацаваць"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Замацаваць праграму \"<xliff:g id="LABEL">%1$s</xliff:g>\""</string>
<string name="unpin_target" msgid="3963318576590204447">"Адмацаваць"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Адмацаваць праграму \"<xliff:g id="LABEL">%1$s</xliff:g>\""</string>
<string name="app_info" msgid="6113278084877079851">"Інфармацыя пра праграму"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Ідзе запуск дэманстрацыі…"</string>
@@ -1971,6 +1966,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Абнавіць наступныя элементы ў сэрвісе "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <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>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Захаваць"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Не, дзякуй"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Не зараз"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Ніколі"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Абнавіць"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Працягнуць"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"пароль"</string>
@@ -2068,5 +2065,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Пераключальнік падзеленага экрана"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Экран блакіроўкі"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Здымак экрана"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"Праграма \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" ва ўсплывальным акне."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Панэль субцітраў праграмы \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"."</string>
</resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 69c998d2afd0..dfa4a2f28844 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Приложението за администриране на служебния потребителски профил липсва или е повредено. В резултат на това той и свързаните с него данни са изтрити. За съдействие се свържете с администратора си."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Служебният ви потребителски профил вече не е налице на това устройство"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Опитите за паролата са твърде много"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Администраторът предостави устройствотото за лична употреба"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Устройството се управлява"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Организацията ви управлява това устройство и може да наблюдава мрежовия трафик. Докоснете за подробности."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Данните на устройството ви ще бъдат изтрити"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Дава възможност на приложението да изпраща оставащи излъчвания, които се запазват след края на излъчването. Прекалената употреба може да причини бавна или нестабилна работа на устройството ви с Android TV, като го накара да използва твърде много памет."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Разрешава на приложението да изпраща оставащи излъчвания, които се запазват след края на излъчването. Прекалената употреба може да причини бавна или нестабилна работа на телефона, като го накара да използва твърде много памет."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"четене на контактите ви"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Разрешава на приложението да чете данни за съхранените на таблета ви контакти, включително честотата на обаждане, изпращане на имейли или общуване по друг начин с конкретни лица. Това разрешение позволява на приложенията да запазват информацията за контактите ви, а злонамерените могат да я споделят без ваше знание."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Дава възможност на приложението да чете данните за съхраняваните на устройството ви с Android TV контакти, включително колко често сте се обаждали на конкретни хора, изпращали сте им имейли или сте общували с тях по други начини. Това разрешение позволява на приложенията да запазват информация за контактите ви, а злонамерените приложения може да я споделят без знанието ви."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Разрешава на приложението да чете данни за съхранените на телефона ви контакти, включително честотата на обаждане, изпращане на имейли или общуване по друг начин с конкретни лица. Това разрешение позволява на приложенията да запазват информацията за контактите ви, а злонамерените могат да я споделят без ваше знание."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Разрешава на приложението да чете данните за съхраняваните в таблета ви контакти. Приложенията ще имат достъп и до профилите на таблета ви, в които са създадени контакти. Това може да включва и профилите, създадени от инсталирани от вас приложения. Така приложенията могат да запазват данните за контактите ви, а злонамерените приложения – да ги споделят без ваше знание."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Разрешава на приложението да чете данните за съхраняваните в устройството ви с Android TV контакти. Приложенията ще имат достъп и до профилите на устройството ви с Android TV, в които са създадени контакти. Това може да включва и профилите, създадени от инсталирани от вас приложения. Така приложенията могат да запазват данните за контактите ви, а злонамерените приложения – да ги споделят без ваше знание."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Разрешава на приложението да чете данните за съхраняваните в телефона ви контакти. Приложенията ще имат достъп и до профилите на телефона ви, в които са създадени контакти. Това може да включва и профилите, създадени от инсталирани от вас приложения. Така приложенията могат да запазват данните за контактите ви, а злонамерените приложения – да ги споделят без ваше знание."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"промяна на контактите ви"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Разрешава на приложението да променя данните за съхранените на таблета ви контакти, включително честотата на обаждане, изпращане на имейли или общуване по друг начин с конкретни контакти. Това разрешение му позволява да изтрива информацията за тях."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Дава възможност на приложението да променя данните за съхраняваните на устройството ви с Android TV контакти, включително колко често сте се обаждали на конкретни хора, изпращали сте им имейли или сте общували с тях по други начини. Това разрешение позволява на приложенията да изтриват данните за контактите."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Разрешава на приложението да променя данните за съхранените на телефона ви контакти, включително честотата на обаждане, изпращане на имейли или общуване по друг начин с конкретни контакти. Това разрешение му позволява да изтрива информацията за тях."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Разрешава на приложението да променя данните за съхраняваните на таблета ви контакти. Това разрешение позволява на приложенията да изтриват данните за контактите."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Разрешава на приложението да променя данните за съхраняваните на устройството ви с Android TV контакти. Това разрешение позволява на приложенията да изтриват данните за контактите."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Разрешава на приложението да променя данните за съхраняваните на телефона ви контакти. Това разрешение позволява на приложенията да изтриват данните за контактите."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"четене на списъка с обаждания"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Това приложение може да чете историята на обажданията ви."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"запис на списъка с обаждания"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"достъп до допълнителни команди на доставчика на местоположение"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Разрешава на приложението достъп до допълнителни команди на доставчика на местоположение. Това може да позволи на приложението да смущава работата на GPS или на другите източници на местоположение."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"достъп до точното местоположение само на преден план"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Приложението може да получава данни за точното ви местоположение само когато работи на преден план. Тези услуги за местоположение трябва да са включени и налице на телефона ви, за да могат да се използват от приложението. Това може да увеличи потреблението на батерията."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"достъп до приблизителното местоположение (основано на мрежи) само на преден план"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Приложението може да получава данни за местоположението ви въз основа на мрежови източници, като клетъчни базови станции и Wi-Fi мрежи, само когато работи на преден план. Тези услуги за местоположение трябва да са включени и налице на таблета ви, за да могат да се използват от приложението."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Това приложение може да получава данни за местоположението ви въз основа на мрежови източници, като клетъчни базови станции и Wi-Fi мрежи, само когато работи на преден план. Тези услуги за местоположение трябва да са включени и налични на устройството ви с Android TV, за да могат да се използват от приложението."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Приложението може да получава данни за местоположението ви въз основа на мрежови източници, като клетъчни базови станции и Wi-Fi мрежи, само когато работи на преден план. Тези услуги за местоположение трябва да са включени и налице на телефона ви, за да могат да се използват от приложението."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Приложението може да получава данни за точното ви местоположение само когато работи на преден план. Услугите за местоположение трябва да са включени и налице на устройството ви, за да могат да се използват от приложението. Това може да увеличи потреблението на батерията."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"достъп до приблизителното местоположение само на преден план"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Приложението може да получава данни за приблизителното ви местоположение само когато работи на преден план. Услугите за местоположение трябва да са включени и налице на устройството ви, за да могат да се използват от приложението."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"достъп до местоположението на заден план"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Ако разрешението бъде предоставено в допълнение към достъпа до приблизителното или точното местоположение, приложението може да осъществява достъп до местоположението, докато се изпълнява на заден план."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Това приложение освен на преден план може да осъществява достъп до местоположението, докато работи на заден план."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"промяна на настройките ви за звука"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Разрешава на приложението да променя глобалните настройки за звука, като например силата и това, кой високоговорител се използва за изход."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"записва звук"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Разрешава на приложението да вижда конфигурацията на Bluetooth на таблета и да изгражда и приема връзки със сдвоени устройства."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Дава възможност на приложението да преглежда конфигурацията на Bluetooth на устройството ви с Android TV и да създава и приема връзки със сдвоени устройства."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Разрешава на приложението да вижда конфигурацията на Bluetooth на телефона и да изгражда и приема връзки със сдвоени устройства."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Информация за предпочитаната услуга за плащане чрез NFC"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Дава възможност на приложението да получава информация за предпочитаната услуга за плащане чрез NFC, като например регистрирани помощни средства и местоназначение."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"контролиране на комуникацията в близкото поле"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Разрешава на приложението да комуникира с маркери, карти и четци, ползващи комуникация в близкото поле (NFC)."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"деактивиране на заключването на екрана ви"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"Прекият път за достъпност включи <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"Прекият път за достъпност изключи <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"За да използвате <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, натиснете двата бутона за силата на звука и ги задръжте за 3 секунди"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Изберете коя услуга да се използва при докосване на бутона за достъпност:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Изберете коя услуга да се използва с жеста за достъпност (прекарване на два пръста нагоре от долната част на екрана):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Изберете коя услуга да се използва с жеста за достъпност (прекарване на три пръста нагоре от долната част на екрана):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"За превключване между услугите докоснете и задръжте бутона за достъпност."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"За превключване между услугите прекарайте два пръста нагоре и задръжте."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"За превключване между услугите прекарайте три пръста нагоре и задръжте."</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>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Установена е връзка с <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Докоснете, за да прегледате файловете"</string>
<string name="pin_target" msgid="8036028973110156895">"Фиксиране"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Фиксиране на <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Освобождаване"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Премахване на фиксирането на <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Информация за приложението"</string>
<string name="negative_duration" msgid="1938335096972945232">"-<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Демонстрацията се стартира…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Искате ли да актуализирате тези елементи в(ъв) "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <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>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Запазване"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Не, благодаря"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Не сега"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Никога"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Актуализиране"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Напред"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"Паролата"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Превключване на разделения екран"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Заключен екран"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Екранна снимка"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"Приложението <xliff:g id="APP_NAME">%1$s</xliff:g> в изскачащ прозорец."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Лента за надписи на <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index e3353962aa8c..150fc7dfdd4c 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"কর্মস্থলের প্রোফাইলের প্রশাসক অ্যাপটি হয় নেই, অথবা সেটি ক্ষতিগ্রস্ত হয়েছে৷ এর ফলে আপনার কর্মস্থলের প্রোফাইল এবং সম্পর্কিত ডেটা মুছে ফেলা হয়েছে৷ সহায়তার জন্য আপনার প্রশাসকের সাথে যোগাযোগ করুন৷"</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"আপনার কর্মস্থলের প্রোফাইলটি আর এই ডিভাইসে নেই"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"বহুবার ভুল পাসওয়ার্ড দিয়েছেন"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"ব্যক্তিগত কাজের জন্য অ্যাডমিন এই ডিভাইস ব্যবহার করার অনুমতি দেয়নি"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"ডিভাইসটি পরিচালনা করা হচ্ছে"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"আপনার প্রতিষ্ঠান এই ডিভাইসটি পরিচালনা করে এবং এটির নেটওয়ার্ক ট্রাফিকের উপরে নজর রাখতে পারে। বিশদ বিবরণের জন্য ট্যাপ করুন।,"</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"আপনার ডিভাইসটি মুছে ফেলা হবে"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"অ্যাপটিকে স্টিকি সম্প্রচার পাঠানোর অনুমতি দেয়। সম্প্রচার শেষ হয়ে যাওয়ার পরেও সেটি সরে যায় না। এটির অতিরিক্ত ব্যবহার করা হলে, অত্যধিক মেমরি ব্যবহার হওয়ার ফলে আপনার Android TV ডিভাইস স্লো হয়ে যেতে পারে অথবা স্থিতিশীলতা হারাতে পারে।"</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"স্টিকি সম্প্রচারগুলি পাঠাতে অ্যাপ্লিকেশানটিকে মঞ্জুর করে, যা সম্প্রচার শেষ হয়ে যাওয়ার পরও উপলব্ধ থাকে৷ খুব বেশি পরিমাণে ব্যবহার করার ফলে ফোনটিকে ধীরগতির করে দিতে পারে অথবা খুব বেশি পরিমাণ মেমরি ব্যবহারের ফলে এটি যথাযথভাবে কাজ নাও করতে পারে৷"</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"আপনার পরিচিতিগুলি পড়ুন"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"অ্যাপ্লিকেশনটিকে আপনি নির্দিষ্ট একজন স্বতন্ত্র ব্যক্তির সঙ্গে ফ্রিকোয়েন্সি দিয়ে কল, ইমেল বা যোগাযোগ করেছেন তা সহ আপনার ট্যাবলেটে সঞ্চিত পরিচিতিগুলি সম্পর্কে ডেটা পড়তে অনুমতি দেয়৷ এই অনুমতি অ্যাপ্লিকেশনগুলিকে আপনার পরিচিতি ডেটা সংরক্ষণ করতে দেয় এবং ক্ষতিকারক অ্যাপ্লিকেশনগুলি আপনাকে না জানিয়ে পরিচিতি ডেটা ভাগ করতে পারে৷"</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"এই অ্যাপকে Android TV ডিভাইসে পরিচিতি সম্পর্কে সেভ করা ডেটা পড়ার অনুমতি দেয়, এক্ষেত্রে যেকোনও নির্দিষ্ট ব্যক্তিকে আপনি কত ঘন ঘন কল, ইমেল বা তার সাথে অন্য কোনও মাধ্যমে যোগাযোগ করেছেন তাও অন্তর্ভুক্ত। এই অনুমতির পেলে কোনও অ্যাপ আপনার পরিচিতির ডেটা সেভ করতে পারে এবং ক্ষতিকারক অ্যাপ আপনার অজান্তে পরিচিতির ডেটা শেয়ার করতে পারে।"</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"অ্যাপ্লিকেশনটিকে আপনি নির্দিষ্ট একজন স্বতন্ত্র ব্যক্তির সঙ্গে ফ্রিকোয়েন্সি দিয়ে কল, ইমেল বা যোগাযোগ করেছেন তা সহ আপনার ফোনে সঞ্চিত পরিচিতিগুলি সম্পর্কে ডেটা পড়তে অনুমতি দেয়৷ এই অনুমতি অ্যাপ্লিকেশনগুলিকে আপনার পরিচিতি ডেটা সংরক্ষণ করতে দেয় এবং ক্ষতিকারক অ্যাপ্লিকেশনগুলি আপনাকে না জানিয়ে পরিচিতি ডেটা ভাগ করতে পারে৷"</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"এই অ্যাপকে আপনার ট্যাবলেটে পরিচিতি সম্পর্কে সেভ করা ডেটা পড়ার অনুমতি দেয়। আপনার ট্যাবলেটের যেসব অ্যাকাউন্ট পরিচিতি তৈরি করা হয়েছে, এই অ্যাপ সেই অ্যাকাউন্টও অ্যাক্সেস করতে পারবে। আপনার ইনস্টল করা কোনও অ্যাপ অ্যাকাউন্ট তৈরি করলে এটির মধ্যে সেটিও থাকতে পারে। এই অনুমতি অ্যাপকে আপনার পরিচিতি সংক্রান্ত ডেটা সেভ করতে দেয় এবং ক্ষতিকারক অ্যাপ আপনাকে না জানিয়ে পরিচিতি সংক্রান্ত ডেটা শেয়ার করতে পারে।"</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"এই অ্যাপকে Android TV ডিভাইসে পরিচিতি সম্পর্কে সেভ করা ডেটা পড়ার অনুমতি দেয়। আপনার Android TV ডিভাইসে যেসব অ্যাকাউন্টে পরিচিতি তৈরি করা হয়েছে, এই অ্যাপ সেই অ্যাকাউন্টও অ্যাক্সেস করতে পারবে। আপনার ইনস্টল করা কোনও অ্যাপ অ্যাকাউন্ট তৈরি করলে এটির মধ্যে সেটিও থাকতে পারে। এই অনুমতি অ্যাপকে আপনার পরিচিতি সংক্রান্ত ডেটা সেভ করতে দেয় এবং ক্ষতিকারক অ্যাপ আপনাকে না জানিয়ে পরিচিতি সংক্রান্ত ডেটা শেয়ার করতে পারে।"</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"এই অ্যাপকে আপনার ফোনে পরিচিতি সম্পর্কে সেভ করা ডেটা পড়ার অনুমতি দেয়। আপনার ফোনের যেসব অ্যাকাউন্ট পরিচিতি তৈরি করা হয়েছে, এই অ্যাপ সেই অ্যাকাউন্টও অ্যাক্সেস করতে পারবে। আপনার ইনস্টল করা কোনও অ্যাপ অ্যাকাউন্ট তৈরি করলে এটির মধ্যে সেটিও থাকতে পারে। এই অনুমতি অ্যাপকে আপনার পরিচিতি সংক্রান্ত ডেটা সেভ করতে দেয় এবং ক্ষতিকারক অ্যাপ আপনাকে না জানিয়ে পরিচিতি সংক্রান্ত ডেটা শেয়ার করতে পারে।"</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"আপনার পরিচিতিগুলি সংশোধন করুন"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"অ্যাপ্লিকেশনটিকে আপনি নির্দিষ্ট একজন পরিচিতির সঙ্গে যে ফ্রিকোয়েন্সিতে কল, ইমেল বা যোগাযোগ করেছেন তা সহ আপনার ট্যাবলেটে সঞ্চিত পরিচিতিগুলি সম্পর্কে ডেটা পরিবর্তন করতে অনুমতি দেয়৷ এই অনুমতি অ্যাপ্লিকেশনগুলিকে আপনার পরিচিতি ডেটা মুছতে দেয়৷"</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"এই অ্যাপকে Android TV ডিভাইসে পরিচিতি সম্পর্কে সেভ করা ডেটা পরিবর্তন করার অনুমতি দেয়, এক্ষেত্রে নির্দিষ্ট পরিচিতিকে আপনি কত ঘন ঘন কল, ইমেল বা তার সাথে অন্য কোনও মাধ্যমে যোগাযোগ করেছেন তাও অন্তর্ভুক্ত। এই অনুমতি পেলে কোনও অ্যাপ আপনার পরিচিতির ডেটা মুছে ফেলতে পারে।"</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"অ্যাপ্লিকেশনটিকে আপনি নির্দিষ্ট একজন পরিচিতির সঙ্গে যে ফ্রিকোয়েন্সিতে কল, ইমেল বা যোগাযোগ করেছেন তা সহ আপনার ফোনে সঞ্চিত পরিচিতিগুলি সম্পর্কে ডেটা পরিবর্তন করতে অনুমতি দেয়৷ এই অনুমতি অ্যাপ্লিকেশনগুলিকে আপনার পরিচিতি ডেটা মুছতে দেয়৷"</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"এই অ্যাপকে আপনার ট্যাবলেটে পরিচিতি সম্পর্কে সেভ করা ডেটা পরিবর্তন করার অনুমতি দেয়। এই অনুমতি অ্যাপকে যোগাযোগ সংক্রান্ত ডেটা মুছতে দেয়।"</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"এই অ্যাপকে Android TV ডিভাইসে পরিচিতি সম্পর্কে সেভ করা ডেটা পরিবর্তন করার অনুমতি দেয়। এই অনুমতি অ্যাপকে যোগাযোগ সংক্রান্ত ডেটা মুছতে দেয়।"</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"এই অ্যাপকে আপনার ফোনে পরিচিতি সম্পর্কে সেভ করা ডেটা পরিবর্তন করার অনুমতি দেয়। এই অনুমতি অ্যাপকে যোগাযোগ সংক্রান্ত ডেটা মুছতে দেয়।"</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"কল লগ পড়ুন"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"এই অ্যাপটি আপনার কলের ইতিহাস পড়তে পারে৷"</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"কল লগ লিখুন"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"অতিরিক্ত লোকেশন প্রদানকারী কমান্ডগুলি অ্যাক্সেস করে"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"লোকেশনের সাথে সম্পর্কিত তথ্য প্রদানকারীর অতিরিক্ত কম্যান্ডগুলিকে অ্যাপ্লিকেশানটিকে মঞ্জুর করে৷ এটি অ্যাপ্লিকেশানটিকে GPS অথবা অন্যান্য লোকেশন নির্ণয়ের সাথে সম্পর্কিত উৎসগুলির ক্রিয়াপ্রণালীর নিয়ন্ত্রণকে মঞ্জুর করতে পারে৷"</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"শুধুমাত্র অ্যাপটি খোলা থাকলে আপনার যথাযথ লোকেশন অ্যাক্সেস করা"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"এই অ্যাপটি ফোরগ্রাউন্ডে চলতে থাকলে যেকোনও সময়ে আপনার যথাযথ লোকেশন জানতে পারবে। এই লোকেশন পরিষেবাগুলি অবশ্যই চালু রাখতে হবে এবং আপনার ফোনে সেগুলি উপলভ্য থাকতে হবে যাতে অ্যাপটি সেগুলি ব্যবহার করতে পারে। এর জন্য অতিরিক্ত ব্যাটারি খরচ হতে পারে।"</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"শুধুমাত্র খোলা অবস্থায় আনুমানিক লোকেশন (নেটওয়ার্ক ভিত্তিক) অ্যাক্সেস করবে"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"অ্যাপটি শুধুমাত্র খোলা অবস্থায় সেল টাওয়ার এবং ওয়াই-ফাইয়ের মতো নেটওয়ার্ক সোর্স ব্যবহার করে আপনার লোকেশন জানতে পারবে। লোকেশন সংক্রান্ত এই পরিষেবাগুলি অবশ্যই চালু থাকতে হবে এবং আপনার ট্যাবলেটে সেগুলি উপলভ্য থাকতে হবে যাতে অ্যাপটি সেগুলি ব্যবহার করতে পারে।"</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"এই অ্যাপ ফোরগ্রাউন্ডে থাকার সময় সেল টাওয়ার ও ওয়াই-ফাই নেটওয়ার্কের মতো নেটওয়ার্ক সোর্স ব্যবহার করে আপনার লোকেশন জানতে পারে। অ্যাপটিকে সেটি ব্যবহার করতে হলে Android TV ডিভাইসে এই লোকেশন পরিষেবা চালু ও উপলভ্য থাকতে হবে।"</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"অ্যাপটি শুধুমাত্র খোলা অবস্থায় সেল টাওয়ার এবং ওয়াই-ফাইয়ের মতো নেটওয়ার্ক সোর্স ব্যবহার করে আপনার লোকেশন জানতে পারবে। লোকেশন সংক্রান্ত এই পরিষেবাগুলি অবশ্যই চালু থাকতে হবে এবং আপনার ফোনে সেগুলি উপলভ্য থাকতে হবে যাতে অ্যাপটি সেগুলি ব্যবহার করতে পারে।"</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"এই অ্যাপটি ফোরগ্রাউন্ডে চলতে থাকলে যেকোনও সময়ে আপনার যথাযথ লোকেশন জানতে পারবে। তাছাড়াও লোকেশন পরিষেবাগুলি অবশ্যই চালু রাখতে হবে এবং আপনার ডিভাইসে সেগুলি উপলভ্য থাকতে হবে যাতে অ্যাপটি সেগুলি ব্যবহার করতে পারে। এর জন্য অতিরিক্ত ব্যাটারি খরচ হতে পারে।"</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"শুধুমাত্র অ্যাপটি খোলা থাকলে আপনার আনুমানিক লোকেশন অ্যাক্সেস করা"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"এই অ্যাপটি যদি ফোরগ্রাউন্ডে চলতে থাকে তবেই শুধুমাত্র আপনার আনুমানিক লোকেশন জানতে পারবে। আপনার ডিভাইসে লোকেশন পরিষেবা চালু ও উপলভ্য থাকতে হবে, তবেই অ্যাপটি সেগুলি ব্যবহার করতে পারবে।"</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"ব্যাকগ্রাউন্ডে লোকেশন অ্যাক্সেস করা"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"আনুমানিক বা একদম যথাযথ লোকেশন অ্যাক্সেস করার অনুমতি দেওয়া হলে এই অ্যাপটি ব্যাকগ্রাউন্ডে চালু থাকাকালীন আপনার লোকেশন অ্যাক্সেস করতে পারবে।"</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"ফোরগ্রাউন্ড লোকেশন অ্যাক্সেস করা ছাড়াও, ব্যাকগ্রাউন্ডে চলাকালীন এই অ্যাপটি লোকেশন অ্যাক্সেস করতে পারে।"</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"আপনার অডিও সেটিংস পরিবর্তন করে"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"ভলিউম এবং যেখানে স্পিকার আউটপুট হিসাবে ব্যবহৃত হয় সেই সব ক্ষেত্রে গ্লোবাল অডিও সেটিংসের সংশোধন করতে অ্যাপ্লিকেশনটিকে মঞ্জুর করে৷"</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"অডিও রেকর্ড"</string>
@@ -494,6 +491,8 @@
<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_preferredPaymentInfo" msgid="5274423844767445054">"পছন্দের NFC পেমেন্ট পরিষেবার তথ্য"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"অ্যাপের মাধ্যমে পছন্দসই এনএফসি পেমেন্ট পরিষেবার তথ্য, যেমন রেজিস্ট্রার করার সহায়তা এবং রুট ডেস্টিনেশন সম্পর্কিত তথ্য অ্যাক্সেস করার অনুমতি দেয়।"</string>
<string name="permlab_nfc" msgid="1904455246837674977">"নিয়ার ফিল্ড কমিউনিকেশন নিয়ন্ত্রণ করে"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"অ্যাপ্লিকেশানকে নিয়ার ফিল্ড কমিউনিকেশন (NFC) ট্যাগ, কার্ড এবং রিডারগুলির সাথে যোগাযোগ করতে দেয়৷"</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"আপনার স্ক্রিন লক অক্ষম করুন"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"অ্যাক্সেসযোগ্যতা শর্টকাট <xliff:g id="SERVICE_NAME">%1$s</xliff:g> কে চালু করেছে"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"অ্যাক্সেসযোগ্যতা শর্টকাট <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>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"অ্যাক্সেসিবিলিটি বোতামে ট্যাপ করে ব্যবহার করার জন্য এই পরিষেবাটি বেছে নিন:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"অ্যাক্সেসিবিলিটি জেসচারের সাহায্যে ব্যবহার করার জন্য এই পরিষেবা বেছে নিন (দুটি আঙুল দিয়ে স্ক্রিনের নিচ থেকে উপরের দিকে সোয়াইপ করুন):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"অ্যাক্সেসিবিলিটি জেসচারের সাহায্যে ব্যবহার করার জন্য এই পরিষেবা বেছে নিন (তিনটি আঙ্গুল দিয়ে স্ক্রিনের নিচ থেকে উপরের দিকে সোয়াইপ করুন):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"একটি পরিষেবা থেকে অন্য পরিষেবায় পাল্টাতে অ্যাক্সেসিবিলিটি বোতামটি টাচ করে ধরে রাখুন।"</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"একটি পরিষেবা থেকে অন্য পরিষেবায় পাল্টাতে, দুটি আঙ্গুল দিয়ে উপরের দিকে সোয়াইপ করে ধরে রাখুন।"</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"একটি পরিষেবা থেকে অন্য পরিষেবায় পাল্টাতে, তিনটি আঙ্গুল দিয়ে উপরের দিকে সোয়াইপ করে ধরে রাখুন।"</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>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> এর সাথে সংযুক্ত হয়েছে"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"ফাইলগুলি দেখতে আলতো চাপ দিন"</string>
<string name="pin_target" msgid="8036028973110156895">"পিন করুন"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"<xliff:g id="LABEL">%1$s</xliff:g> অ্যাপ পিন করুন"</string>
<string name="unpin_target" msgid="3963318576590204447">"আনপিন করুন"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"<xliff:g id="LABEL">%1$s</xliff:g> অ্যাপ আনপিন করুন"</string>
<string name="app_info" msgid="6113278084877079851">"অ্যাপের তথ্য"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"ডেমো শুরু করা হচ্ছে…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291"><b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"-এ এই আইটেমগুলি আপডেট করতে চান: <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>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"সেভ করুন"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"না থাক"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"এখনই নয়"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"কখনই নয়"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"আপডেট করুন"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"চালিয়ে যান"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"পাসওয়ার্ড"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"স্প্লিট স্ক্রিন টগল করুন"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"লক স্ক্রিন"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"স্ক্রিনশট"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"পপ-আপ উইন্ডোতে <xliff:g id="APP_NAME">%1$s</xliff:g> অ্যাপ।"</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g>-এর ক্যাপশন বার।"</string>
</resources>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index d7bd7a17add9..36608245b513 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -190,8 +190,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Nedostaje aplikacija administratora za radni profil ili je neispravna. Zbog toga su vaš radni profil i povezani podaci izbrisani. Obratite administratoru za pomoć."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Radni profil više nije dostupan na ovom uređaju"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Previše puta ste pokušali otključati uređaj"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Administrator je ustupio uređaj za ličnu upotrebu"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Uređajem se upravlja."</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Vaša organizacija upravlja ovim uređajem i može pratiti mrežni saobraćaj. Dodirnite za detalje."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Uređaj će biti izbrisan"</string>
@@ -384,13 +383,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Omogućava aplikaciji slanje ljepljivih informacija koje ostaju nakon prestanka emitiranja. Pretjeranom upotrebom može se usporiti ili destabilizirati rad Android TV uređaja zbog korištenja previše memorije."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Omogućava aplikaciji slanje ljepljivih informacija koje ostaju nakon prestanka emitiranja. Njihova pretjerana upotreba može usporiti ili destabilizirati rad telefona jer troši previše memorije."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"čitanje vaših kontakata"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Omogućava aplikaciji čitanje podataka o kontaktima koji su pohranjeni na vašem tabletu, uključujući učestalost vaših poziva, slanja e-pošte ili nekog drugog vida komunikacije sa određenim pojedincima. Ovo odobrenje omogućava aplikacijama da pohrane podatke o vašim kontaktima tako da ih zlonamjerne aplikacije mogu podijeliti bez vašeg znanja."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Omogućava aplikaciji da čita podatke o vašim kontaktima pohranjenim na Android TV uređaju, uključujući učestalost poziva, slanja e-poruka ili komuniciranja na bilo koji način s određenim osobama. Ovo odobrenje omogućava aplikacijama da pohrane podatke o vašim kontaktima, a zlonamjerne aplikacije mogu bez vašeg znanja podijeliti ove podatke."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Omogućava aplikaciji čitanje podataka o kontaktima koji su pohranjeni na vašem telefonu, uključujući učestalost vaših poziva, slanja e-pošte ili nekog drugog vida komunikacije sa određenim pojedincima. Ovo odobrenje omogućava aplikacijama da pohrane podatke o vašim kontaktima tako da ih zlonamjerne aplikacije mogu podijeliti bez vašeg znanja."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Dozvoljava aplikaciji da čita podatke o kontaktima pohranjenim na tabletu. Aplikacije će također imati pristup računima na tabletu koji su kreirali kontakte. Ovo može uključivati račune koje su kreirale aplikacije koje ste instalirali. Ovo odobrenje dozvoljava aplikacijama da sačuvaju podatke o kontaktima, a zlonamjerne aplikacije mogu dijeliti te podatke bez vašeg znanja."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Dozvoljava aplikaciji da čita podatke o kontaktima pohranjenim na Android TV uređaju. Aplikacije će također imati pristup računima na Android TV uređaju koji su kreirali kontakte. Ovo može uključivati račune koje su kreirale aplikacije koje ste instalirali. Ovo odobrenje dozvoljava aplikacijama da sačuvaju podatke o kontaktima, a zlonamjerne aplikacije mogu dijeliti te podatke bez vašeg znanja."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Dozvoljava aplikaciji da čita podatke o kontaktima pohranjenim na telefonu. Aplikacije će također imati pristup računima na telefonu koji su kreirali kontakte. Ovo može uključivati račune koje su kreirale aplikacije koje ste instalirali. Ovo odobrenje dozvoljava aplikacijama da sačuvaju podatke o kontaktima, a zlonamjerne aplikacije mogu dijeliti te podatke bez vašeg znanja."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"izmjena podataka o kontaktima"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Omogućava aplikaciji da izmijeni podatke o kontaktima koji su pohranjeni na vašem tabletu, uključujući učestalost vaših poziva, slanje e-pošte, ili neki drugi vid komunikacije sa određenim kontaktima. Ovo odobrenje omogućava aplikaciji da obriše podatke o kontaktima."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Omogućava aplikaciji izmjenu podataka o vašim kontaktima pohranjenim na Android TV uređaju, uključujući učestalost poziva, slanja e-poruka ili komuniciranja na bilo koji način s određenim kontaktima. Ovom dozvolom se aplikacijama omogućava brisanje podataka o kontaktima."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Omogućava aplikaciji da izmijeni podatke o kontaktima koji su pohranjeni na vašem telefonu, uključujući učestalost vaših poziva, slanje e-pošte, ili neki drugi vid komunikacije sa određenim kontaktima. Ovo odobrenje omogućava aplikaciji da izbriše podatke o kontaktima."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Dozvoljava aplikaciji da vrši izmjene podataka o kontaktima pohranjenim na tabletu. Ovo odobrenje dozvoljava aplikacijama da izbrišu podatke o kontaktima."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Dozvoljava aplikaciji da vrši izmjene podataka o kontaktima pohranjenim na Android TV uređaju. Ovo odobrenje dozvoljava aplikacijama da izbrišu podatke o kontaktima."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Dozvoljava aplikaciji da vrši izmjene podataka o kontaktima pohranjenim na telefonu. Ovo odobrenje dozvoljava aplikacijama da izbrišu podatke o kontaktima."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"čitanje zapisnika poziva"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Ova aplikacija može čitati historiju vaših poziva."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"pisanje zapisnika poziva"</string>
@@ -410,13 +409,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"pristup dodatnim informacijama o lokaciji"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Dozvoljava aplikaciji pristup dodatnim naredbama pružatelja lokacija. Ovim se aplikaciji može dozvoliti da ometa rad GPS-a ili drugih izvora lokacija."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"pristup tačnoj lokaciji samo u prvom planu"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Ova aplikacija može odrediti vašu tačnu lokaciju samo kada je u prvom planu. Ove usluge lokacije moraju biti uključene i dostupne na vašem telefonu da ih aplikacija može koristiti. To može dovesti do povećane potrošnje baterije."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"pristup približnoj lokaciji (utvrđena preko mreže) samo u prvom planu"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Ova aplikacija može odrediti vašu lokaciju na osnovu izvora mreže kao što su predajnici za mobilnu mrežu i WiFi mreže ali samo kada je aplikacija u prvom planu. Ove usluge za određivanje lokacije moraju biti uključene i omogućene na vašem tabletu kako bi ih aplikacija mogla koristiti."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Ova aplikacija može odrediti vašu lokaciju na osnovu izvora mreže kao što su predajnici za mobilnu mrežu i WiFi mreže, ali samo kada je aplikacija u prvom planu. Te usluge za određivanje lokacije moraju biti uključene i omogućene na vašem Android TV uređaju kako bi ih aplikacija mogla koristiti."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Ova aplikacija može odrediti vašu lokaciju na osnovu izvora mreže kao što su predajnici za mobilnu mrežu i WiFi mreže ali samo kada je aplikacija u prvom planu. Ove usluge za određivanje lokacije moraju biti uključene i omogućene na vašem telefonu kako bi ih aplikacija mogla koristiti."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Ova aplikacija može odrediti vašu tačnu lokaciju samo kada je u prvom planu. Usluge lokacije moraju biti uključene i dostupne na uređaju da ih aplikacija može koristiti. To može dovesti do povećane potrošnje baterije."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"pristup približnoj lokaciji samo u prvom planu"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Ova aplikacija može odrediti vašu približnu lokaciju samo kada je u prvom planu. Usluge lokacije moraju biti uključene i dostupne na uređaju da ih aplikacija može koristiti."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"pristup lokaciji u pozadini"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Ako je ovo odobreno, pored pristupa približnoj ili tačnoj lokaciji, aplikacija može pristupiti lokaciji dok radi u pozadini."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Ova aplikacija može pristupati lokaciji dok radi u pozadini, pored pristupa lokaciji u prvom planu."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"izmjene postavki zvuka"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Omogućava aplikaciji izmjenu općih postavki zvuka, kao što su jačina zvuka i izbor izlaznog zvučnika."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"snimanje audiozapisa"</string>
@@ -497,6 +494,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Omogućava aplikaciji prikaz konfiguracije za Bluetooth na tabletu, kao i uspostavljanje i prihvatanje veza sa uparenim uređajima."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Omogućava aplikaciji da prikaže konfiguraciju Bluetootha na Android TV uređaju te uspostavi i prihvati vezu s uparenim uređajima."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Omogućava aplikaciji prikaz konfiguracije za Bluetooth na telefonu, kao i uspostavljanje i prihvatanje veza sa uparenim uređajima."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Informacije o preferiranoj usluzi plaćanja putem NFC-a"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Dozvoljava aplikaciji da dobije informacije o preferiranoj usluzi plaćanja putem NFC-a kao što su registrirana pomagala i odredište rute."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"upravljanje NFC-om"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Dozvoljava aplikaciji komuniciranje sa NFC (komunikacija bliskog polja) oznakama, karticama i čitačima."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"deaktivacija zaključavanja ekrana"</string>
@@ -1642,12 +1641,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"Prečica za pristupačnost je uključila uslugu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"Prečica za pristupačnost je isključila uslugu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Pritisnite obje tipke za podešavanje jačine zvuka i držite ih pritisnutim tri sekunde da koristite uslugu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Odaberite uslugu koja će se koristiti kada dodirnete dugme za pristupačnost:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Odaberite uslugu koja će se koristiti kada izvedete pokret za pristupačnost (s dva prsta prevucite prema gore s dna ekrana):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Odaberite uslugu koja će se koristiti kada izvedete pokret za pristupačnost (s tri prsta prevucite prema gore s dna ekrana):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Da prebacujete između usluga, dodirnite i zadržite dugme za pristupačnost."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Da prebacujete između usluga, s dva prsta prevucite prema gore i zadržite."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Da prebacujete između usluga, s tri prsta prevucite prema gore i zadržite."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Uvećavanje"</string>
<string name="user_switched" msgid="7249833311585228097">"Trenutni korisnik <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="1912993630661332336">"Prebacivanje na korisnika <xliff:g id="NAME">%1$s</xliff:g>..."</string>
@@ -1896,7 +1889,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Povezan na uređaj <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Dodirnite za prikaz fajlova"</string>
<string name="pin_target" msgid="8036028973110156895">"Zakači"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Zakači aplikaciju <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Otkači"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Otkači aplikaciju <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Informacije o aplikaciji"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Pokretanje demonstracije…"</string>
@@ -1940,6 +1935,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Ažurirati ove stavke u "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> i <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Sačuvaj"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Ne, hvala"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Ne sada"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Nikada"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Ažuriraj"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Nastavi"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"lozinka"</string>
@@ -2036,5 +2033,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Uključi/isključi podijeljeni ekran"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Zaključavanje ekrana"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Snimak ekrana"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> u skočnom prozoru."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Traka za natpis aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 1f7d82e05961..b265f66baee3 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Falta l\'aplicació d\'administració del perfil professional o està malmesa. Com a conseqüència, s\'han suprimit el teu perfil professional i les dades relacionades. Contacta amb l\'administrador per obtenir ajuda."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"El teu perfil professional ja no està disponible en aquest dispositiu"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Has intentat introduir la contrasenya massa vegades"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"L\'administrador ha cedit el dispositiu per a ús personal"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"El dispositiu està gestionat"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"La teva organització gestiona aquest dispositiu i és possible que supervisi el trànsit de xarxa. Toca per obtenir més informació."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"El contingut del dispositiu s\'esborrarà"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Permet que l\'aplicació enviï emissions fixes, que es conserven després de finalitzar l\'emissió. L\'ús excessiu pot provocar que el dispositiu Android TV utilitzi massa memòria i s\'alenteixi o es desestabilitzi."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Permet que l\'aplicació enviï emissions permanents, que es conserven després de finalitzar l\'emissió. L\'ús excessiu pot alentir o desestabilitzar el telèfon si li fan utilitzar massa memòria."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"consultar els contactes"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Permet que l\'aplicació llegeixi dades sobre els contactes que tinguis emmagatzemats a la tauleta, inclosa la freqüència amb què has trucat, has enviat correus electrònics o t\'has comunicat d\'altres maneres amb persones concretes. Aquest permís permet que les aplicacions desin les dades dels teus contactes, i és possible que les aplicacions malicioses comparteixin dades dels contactes sense el teu coneixement."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Permet que l\'aplicació llegeixi dades sobre els contactes emmagatzemades al dispositiu Android TV, inclosa la freqüència amb què has trucat a contactes concrets, els has enviat correus electrònics o t\'hi has comunicat d\'altres maneres. Aquest permís permet que les aplicacions desin les dades dels teus contactes; és possible que les aplicacions malicioses comparteixin dades dels contactes sense que ho sàpigues."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Permet que l\'aplicació llegeixi dades sobre els contactes que tinguis emmagatzemats al telèfon, inclosa la freqüència amb què has trucat, has enviat correus electrònics o t\'has comunicat d\'altres maneres amb persones concretes. Aquest permís permet que les aplicacions desin les dades dels teus contactes, i és possible que les aplicacions malicioses comparteixin dades dels contactes sense el teu coneixement."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Permet que l\'aplicació llegeixi les dades dels contactes que tens emmagatzemats a la tauleta. Les aplicacions també tindran accés als comptes de la tauleta que hagin creat contactes. Això pot incloure els comptes creats per les aplicacions que hi tens instal·lades. Les aplicacions amb aquest permís poden desar les dades dels teus contactes, i és possible que les aplicacions malicioses comparteixin dades dels contactes sense el teu coneixement."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Permet que l\'aplicació llegeixi les dades dels contactes que tens emmagatzemats al dispositiu Android TV. Les aplicacions també tindran accés als comptes del teu dispositiu Android TV que hagin creat contactes. Això pot incloure els comptes creats per les aplicacions que hi tens instal·lades. Les aplicacions amb aquest permís poden desar les dades dels teus contactes, i és possible que les aplicacions malicioses comparteixin dades dels contactes sense el teu coneixement."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Permet que l\'aplicació llegeixi les dades dels contactes que tens emmagatzemats al telèfon. Les aplicacions també tindran accés als comptes del telèfon que hagin creat contactes. Això pot incloure els comptes creats per les aplicacions que hi tens instal·lades. Les aplicacions amb aquest permís poden desar les dades dels teus contactes, i és possible que les aplicacions malicioses comparteixin dades dels contactes sense el teu coneixement."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"modificar els teus contactes"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Permet que l\'aplicació modifiqui les dades sobre contactes emmagatzemades a la tauleta, inclosa la freqüència amb què has trucat, has enviat correus electrònics o t\'has comunicat d\'altres maneres amb contactes concrets. Aquest permís permet que les aplicacions suprimeixin dades de contactes."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Permet que l\'aplicació modifiqui les dades sobre els contactes emmagatzemades al dispositiu Android TV, com ara la freqüència amb què has trucat a contactes concrets, els has enviat correus electrònics o t\'hi has comunicat d\'altres maneres. Amb aquest permís, les aplicacions poden suprimir les dades dels contactes."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Permet que l\'aplicació modifiqui les dades sobre contactes emmagatzemades al telèfon, inclosa la freqüència amb què has trucat, has enviat correus electrònics o t\'has comunicat d\'altres maneres amb contactes concrets. Aquest permís permet que les aplicacions suprimeixin dades de contactes."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Permet que l\'aplicació modifiqui les dades dels contactes que tens emmagatzemats a la tauleta. Amb aquest permís, les aplicacions poden suprimir les dades dels contactes."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Permet que l\'aplicació modifiqui les dades dels contactes que tens emmagatzemats al dispositiu Android TV. Amb aquest permís, les aplicacions poden suprimir les dades dels contactes."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Permet que l\'aplicació modifiqui les dades dels contactes que tens emmagatzemats al telèfon. Amb aquest permís, les aplicacions poden suprimir les dades dels contactes."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"lectura del registre de trucades"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Aquesta aplicació pot llegir el teu historial de trucades."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"escriptura del registre de trucades"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"accedir a ordres del proveïdor d\'ubicació addicionals"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Permet que l\'aplicació accedeixi a ordres addicionals del proveïdor d\'ubicacions; per tant, és possible que l\'aplicació pugui interferir en el funcionament del GPS o d\'altres fonts d\'ubicacions."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"accedeix a la ubicació exacta només en primer pla"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Aquesta aplicació pot obtenir la teva ubicació exacta només quan està en primer pla. Aquests serveis d\'ubicació han d\'estar activats i disponibles al telèfon perquè l\'aplicació els pugui utilitzar, i això pot fer que el consum de bateria augmenti."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"accedeix a la ubicació aproximada (basada en xarxa) només en primer pla"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Aquesta aplicació pot obtenir la teva ubicació a partir de fonts de xarxa, com ara torres de telefonia mòbil i xarxes Wi‑Fi, però només quan està en primer pla. Aquests serveis d\'ubicació han d\'estar activats i disponibles a la tauleta perquè l\'aplicació els pugui utilitzar."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Aquesta aplicació pot obtenir la teva ubicació a partir de fonts de xarxa, com ara torres de telefonia mòbil i xarxes Wi‑Fi, però només quan està en primer pla. Aquests serveis d\'ubicació han d\'estar activats i disponibles al dispositiu Android TV perquè l\'aplicació els pugui utilitzar."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Aquesta aplicació pot obtenir la teva ubicació a partir de fonts de xarxa, com ara torres de telefonia mòbil i xarxes Wi‑Fi, però només quan està en primer pla. Aquests serveis d\'ubicació han d\'estar activats i disponibles al telèfon perquè l\'aplicació els pugui utilitzar."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Aquesta aplicació pot obtenir la teva ubicació exacta només quan està en primer pla. Els serveis d\'ubicació han d\'estar activats i disponibles al dispositiu perquè l\'aplicació els pugui utilitzar, i això pot fer que el consum de bateria augmenti."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"accedeix a la ubicació aproximada només en primer pla"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Aquesta aplicació pot obtenir la teva ubicació aproximada només quan està en primer pla. Els serveis d\'ubicació han d\'estar activats i disponibles al dispositiu perquè l\'aplicació els pugui utilitzar."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"accedir a la ubicació en segon pla"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Si es concedeix aquest permís, a més de l\'accés a la ubicació aproximada o exacta, l\'aplicació pot accedir a la ubicació mentre s\'executa en segon pla."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Aquesta aplicació pot accedir a la ubicació mentre s\'executa en segon pla, a més de poder fer-ho en primer pla."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"canviar la configuració d\'àudio"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Permet que l\'aplicació modifiqui la configuració d\'àudio general, com ara el volum i l\'altaveu de sortida que es fa servir."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"gravar àudio"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Permet que l\'aplicació visualitzi la configuració del Bluetooth de la tauleta i que estableixi i accepti connexions amb dispositius sincronitzats."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Permet que l\'aplicació visualitzi la configuració del Bluetooth del dispositiu Android TV i que estableixi i accepti connexions amb dispositius vinculats."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Permet que una aplicació visualitzi la configuració del Bluetooth del telèfon i que estableixi i accepti connexions amb els dispositius sincronitzats."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Informació preferent sobre el servei de pagament per NFC"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Permet que l\'aplicació obtingui informació preferent sobre el servei de pagament per NFC, com ara complements registrats i destinacions de rutes."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"controlar Comunicació de camp proper (NFC)"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Permet que l\'aplicació es comuniqui amb les etiquetes, les targetes i els lectors de Comunicació de camp proper (NFC)."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"desactivació del bloqueig de pantalla"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"La drecera d\'accessibilitat ha activat <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"La drecera d\'accessibilitat ha desactivat <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Mantén premudes les dues tecles de volum durant 3 segons per fer servir <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Tria el servei que s\'utilitzarà quan toquis el botó d\'accessibilitat:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Tria el servei que s\'utilitzarà amb el gest d\'accessibilitat (fes lliscar dos dits cap amunt des de la part inferior de la pantalla)."</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Tria el servei que s\'utilitzarà amb el gest d\'accessibilitat (fes lliscar tres dits cap amunt des de la part inferior de la pantalla)."</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Per canviar de servei, mantén premut el botó d\'accessibilitat."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Per canviar de servei, fes lliscar dos dits i mantén premut."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Per canviar de servei, fes lliscar tres dits i mantén premut."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Ampliació"</string>
<string name="user_switched" msgid="7249833311585228097">"Usuari actual: <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="1912993630661332336">"S\'està canviant a <xliff:g id="NAME">%1$s</xliff:g>…"</string>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"S\'ha connectat a <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Toca per veure els fitxers"</string>
<string name="pin_target" msgid="8036028973110156895">"Fixa"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Fixa <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"No fixis"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"No fixis <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Informació de l\'aplicació"</string>
<string name="negative_duration" msgid="1938335096972945232">"-<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"S\'està iniciant la demostració…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Vols actualitzar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> i <xliff:g id="TYPE_2">%3$s</xliff:g> a "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Desa"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"No, gràcies"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Ara no"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Mai"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Actualitza"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Continua"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"contrasenya"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Commuta Pantalla dividida"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Pantalla de bloqueig"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Captura de pantalla"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"Aplicació <xliff:g id="APP_NAME">%1$s</xliff:g> a la finestra emergent."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Barra de títol de l\'aplicació <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index e05f29945ee6..806cb7e1b7f9 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -192,8 +192,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Aplikace pro správu pracovního profilu chybí nebo je poškozena. Váš pracovní profil a související data proto byla smazána. Požádejte o pomoc administrátora."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Váš pracovní profil v tomto zařízení již není k dispozici"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Příliš mnoho pokusů o zadání hesla"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Administrátor zařízení uvolnil k osobnímu používání"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Zařízení je spravováno"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Toto zařízení je spravováno vaší organizací, která může sledovat síťový provoz. Podrobnosti zobrazíte klepnutím."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Zařízení bude vymazáno"</string>
@@ -387,13 +386,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Umožňuje aplikaci odesílat trvalá vysílání, která přetrvávají i po skončení. Nadměrné používání může zařízení Android TV zpomalit či způsobit jeho nestabilitu, protože bude používat příliš mnoho paměti."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Umožňuje aplikaci odesílat trvalá vysílání, která přetrvávají i po skončení vysílání. Nadměrné používání může telefon zpomalit či způsobit jeho nestabilitu, protože bude používat příliš mnoho paměti."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"čtení kontaktů"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Umožňuje aplikaci číst údaje o kontaktech uložených v tabletu, včetně toho, jak často voláte, posíláte e‑maily nebo jinak komunikujete s konkrétními osobami. Toto oprávnění umožňuje aplikacím ukládat údaje o kontaktech. Škodlivé aplikace mohou tyto údaje bez vašeho vědomí sdílet."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Umožňuje aplikaci číst údaje o kontaktech uložených v zařízení Android TV, včetně toho, jak často voláte, posíláte e‑maily nebo jinými způsoby komunikujete s konkrétními osobami. Toto oprávnění aplikacím umožňuje ukládat údaje o kontaktech. Škodlivé aplikace mohou tyto údaje bez vašeho vědomí sdílet."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Umožňuje aplikaci číst údaje o kontaktech uložených v telefonu, včetně toho, jak často voláte, posíláte e‑maily nebo komunikujete jinými způsoby s konkrétními osobami. Toto oprávnění umožňuje aplikacím ukládat údaje o kontaktech. Škodlivé aplikace mohou tyto údaje bez vašeho vědomí sdílet."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Umožňuje aplikaci číst údaje o kontaktech uložené v tabletu. Aplikace také budou mít přístup k účtům v tabletu, pomocí kterých byly vytvořeny kontakty. Může se jednat i o účty vytvořené aplikacemi, které jste nainstalovali. Toto oprávnění aplikacím umožňuje ukládat údaje o kontaktech. Škodlivé aplikace mohou tyto údaje bez vašeho vědomí sdílet."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Umožňuje aplikaci číst údaje o kontaktech uložené v zařízení Android TV. Aplikace také budou mít přístup k účtům v zařízení Android TV, pomocí kterých byly vytvořeny kontakty. Může se jednat i o účty vytvořené aplikacemi, které jste nainstalovali. Toto oprávnění aplikacím umožňuje ukládat údaje o kontaktech. Škodlivé aplikace mohou tyto údaje bez vašeho vědomí sdílet."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Umožňuje aplikaci číst údaje o kontaktech uložené v telefonu. Aplikace také budou mít přístup k účtům v telefonu, pomocí kterých byly vytvořeny kontakty. Může se jednat i o účty vytvořené aplikacemi, které jste nainstalovali. Toto oprávnění aplikacím umožňuje ukládat údaje o kontaktech. Škodlivé aplikace mohou tyto údaje bez vašeho vědomí sdílet."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"úprava kontaktů"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Umožňuje aplikaci upravit údaje o kontaktech uložených v tabletu včetně toho, jak často voláte, posíláte e‑maily nebo komunikujete jinými způsoby s konkrétními kontakty. Toto oprávnění aplikacím umožňuje mazat údaje o kontaktech."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Umožňuje aplikaci upravit údaje o kontaktech uložených v zařízení Android TV včetně toho, jak často voláte, posíláte e‑maily nebo komunikujete jinými způsoby s konkrétními kontakty. Toto oprávnění aplikacím umožňuje mazat údaje o kontaktech."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Umožňuje aplikaci upravit údaje o kontaktech uložených v telefonu včetně toho, jak často voláte, posíláte e‑maily nebo komunikujete jinými způsoby s konkrétními kontakty. Toto oprávnění aplikacím umožňuje mazat údaje o kontaktech."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Umožňuje aplikaci upravovat údaje o kontaktech uložené v tabletu. Toto oprávnění aplikacím umožňuje mazat údaje o kontaktech."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Umožňuje aplikaci upravovat údaje o kontaktech uložené v zařízení Android TV. Toto oprávnění aplikacím umožňuje mazat údaje o kontaktech."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Umožňuje aplikaci upravovat údaje o kontaktech uložení v telefonu. Toto oprávnění aplikacím umožňuje mazat údaje o kontaktech."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"čtení seznamu hovorů"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Tato aplikace může číst historii volání."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"zápis do seznamu hovorů"</string>
@@ -413,13 +412,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"přístup k dalším příkazům poskytovatele polohy"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Umožňuje aplikaci přístup k dalším příkazům poskytovatele polohy. To aplikaci umožní zasahovat do fungování systému GPS a dalších zdrojů polohy."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"přístup k přesné poloze jen na popředí"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Tato aplikace může zjistit vaši přesnou polohu, jen když běží na popředí. Aby tyto služby určování polohy mohla aplikace používat, musí být v telefonu dostupné a musí být zapnuté. Tyto služby mohou způsobit rychlejší vybíjení baterie."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"přístup k přibližené poloze (na základě sítě) jen na popředí"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Tato aplikace může zjistit vaši polohu podle zdrojů sítě, jako jsou vysílací věže nebo sítě Wi-Fi (ale pouze pokud je aplikace na popředí). Aby tyto služby určování polohy mohla aplikace používat, musí být v tabletu dostupné a musí být zapnuté."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Tato aplikace může zjistit vaši polohu podle zdrojů sítě, jako jsou vysílací věže nebo sítě Wi-Fi (ale pouze pokud je aplikace na popředí). Aby tyto služby určování polohy mohla aplikace používat, musí být v zařízení Android TV dostupné a musí být zapnuté."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Tato aplikace může zjistit vaši polohu podle zdrojů sítě, jako jsou vysílací věže nebo sítě Wi-Fi (ale pouze pokud je aplikace na popředí). Aby tyto služby určování polohy mohla aplikace používat, musí být v telefonu dostupné a musí být zapnuté."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Tato aplikace může zjistit vaši přesnou polohu, jen když běží na popředí. Aby aplikace mohla služby určování polohy používat, musí být v zařízení dostupné a musí být zapnuté. To může vést k rychlejšímu vybíjení baterie."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"přístup k přibližné poloze jen na popředí"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Tato aplikace může zjistit vaši přibližnou polohu, jen když běží na popředí. Aby aplikace mohla služby určování polohy používat, musí být v zařízení dostupné a musí být zapnuté."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"přístup k poloze na pozadí"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Bude-li oprávnění uděleno dodatečně k přístupu k přibližné nebo přesné poloze, aplikace bude moci používat polohu při spuštění na pozadí."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Tato aplikace má přístup k poloze, nejen když je v popředí, ale i když běží na pozadí."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"změna nastavení zvuku"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Umožňuje aplikaci změnit globální nastavení zvuku, například hlasitost či reproduktor pro výstup zvuku."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"nahrávání zvuku"</string>
@@ -500,6 +497,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Umožňuje aplikaci zobrazit konfiguraci tabletu s rozhraním Bluetooth, vytvářet připojení ke spárovaným zařízením a přijímat tato připojení."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Umožňuje aplikaci zobrazit konfiguraci rozhraním Bluetooth na zařízení Android TV a vytvářet a přijímat připojení ke spárovaným zařízením."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Umožňuje aplikaci zobrazit konfiguraci telefonu s rozhraním Bluetooth, vytvářet připojení ke spárovaným zařízením a přijímat tato připojení."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Informace o preferované platební službě NFC"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Umožňuje aplikaci získat informace o preferované platební službě NFC, například o registrovaných pomůckách a cíli směrování."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"ovládání technologie NFC"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Umožňuje aplikaci komunikovat se štítky, kartami a čtečkami s podporou technologie NFC."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"vypnutí zámku obrazovky"</string>
@@ -1662,12 +1661,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"Zkratka přístupnosti zapnula službu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"Zkratka přístupnosti vypnula službu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Chcete-li používat službu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, tři sekundy podržte stisknutá obě tlačítka hlasitosti"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Určete, jakou službu aktivujete klepnutím na tlačítko Přístupnost:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Určete, jakou službu aktivujete pomocí gesta přístupnosti (přejetí dvěma prsty ze spodní části obrazovky nahoru):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Určete, jakou službu aktivujete pomocí gesta přístupnosti (přejetí třemi prsty ze spodní části obrazovky nahoru):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Chcete-li přepnout mezi službami, podržte tlačítko Přístupnost."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Chcete-li přepnout mezi službami, přejeďte nahoru dvěma prsty a podržte je."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Chcete-li přepnout mezi službami, přejeďte nahoru třemi prsty a podržte je."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Zvětšení"</string>
<string name="user_switched" msgid="7249833311585228097">"Aktuální uživatel je <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="1912993630661332336">"Přepínání na účet <xliff:g id="NAME">%1$s</xliff:g>…"</string>
@@ -1926,7 +1919,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Připojeno k zařízení <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Klepnutím zobrazíte soubory"</string>
<string name="pin_target" msgid="8036028973110156895">"Připnout"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Připnout: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Odepnout"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Odepnout: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"O aplikaci"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Spouštění ukázky…"</string>
@@ -1971,6 +1966,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Aktualizovat tyto položky ve službě "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> a <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Uložit"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Ne, děkuji"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Teď ne"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Nikdy"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Aktualizovat"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Pokračovat"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"heslo"</string>
@@ -2068,5 +2065,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Přepnout rozdělenou obrazovku"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Obrazovka uzamčení"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Snímek obrazovky"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> ve vyskakovacím okně."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Popisek aplikace <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 772b7b054070..81449ad5ca8a 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Administrationsappen til arbejdsprofilen mangler eller er beskadiget. Derfor er din arbejdsprofil og dine relaterede data blevet slettet. Kontakt din administrator for at få hjælp."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Din arbejdsprofil er ikke længere tilgængelig på denne enhed"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"For mange mislykkede adgangskodeforsøg"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Administratoren har gjort personlig brug af enheden utilgængelig"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Dette er en administreret enhed"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Din organisation administrerer denne enhed og kan overvåge netværkstrafik. Tryk for at se info."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Enheden slettes"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Tillader, at appen kan sende klæbende udsendelser, der forbliver, når udsendelsen er slut. Overdreven brug kan gøre din Android TV-enhed langsom eller ustabil, da det tvinger den til at bruge for meget hukommelse."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Tillader, at appen kan sende klæbende udsendelser, der forbliver tilbage, når udsendelsen er slut. Overdreven brug kan gøre din telefon langsom eller ustabil ved at tvinge den til at bruge for meget hukommelse."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"læse dine kontakter"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Tillader, at appen kan læse data om de kontakter, der er gemt på din tablet, f.eks. hvor ofte du har ringet til, sendt mail til eller på anden måde kommunikeret med bestemte personer. Med denne tilladelse kan apps gemme dine kontaktdata, og skadelige apps kan dele kontaktdata uden din viden."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Tillader, at appen kan læse gemte data på din Android TV-enhed om dine kontakter, bl.a. hvor ofte du har ringet til dem, sendt mail til dem eller på anden måde kommunikeret med bestemte personer. Denne tilladelse giver apps mulighed for at gemme dine kontaktdata, og skadelige apps kan dele kontaktdata uden din viden."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Tillader, at appen kan læse data om de kontakter, der er gemt på din telefon, f.eks. hvor ofte du har ringet til, sendt mail til eller på anden måde kommunikeret med bestemte personer. Med denne tilladelse kan apps gemme dine kontaktdata, og skadelige apps kan dele kontaktdata uden din viden."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Tillader, at appen kan læse data om de kontakter, der er gemt på din tablet. Apps får også adgang til de konti på din tablet, som har oprettet kontakter. Dette kan omfatte konti, som er oprettet af apps, du har installeret. Med denne tilladelse kan apps gemme dine kontaktdata, og skadelige apps kan dele kontaktdata uden din viden."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Tillader, at appen kan læse data om de kontakter, der er gemt på din Android TV-enhed. Apps får også adgang til de konti på din Android TV-enhed, som har oprettet kontakter. Dette kan omfatte konti, som er oprettet af apps, du har installeret. Med denne tilladelse kan apps gemme dine kontaktdata, og skadelige apps kan dele kontaktdata uden din viden."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Tillader, at appen læser data om de kontakter, der er gemt på din telefon. Apps får også adgang til de konti på din telefon, som har oprettet kontakter. Dette kan omfatte konti, som er oprettet af apps, du har installeret. Med denne tilladelse kan apps gemme dine kontaktdata, og skadelige apps kan dele kontaktdata uden din viden."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"ændre dine kontakter"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Tillader, at appen kan ændre data om de kontakter, der er gemt på din tablet, f.eks. hvor ofte du har ringet til dem, sendt dem en mail eller på anden måde kommunikeret med bestemte kontakter. Med denne tilladelse kan apps slette kontaktoplysninger."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Tillader, at appen kan ændre data om de kontakter, der er gemt på din Android TV-enhed, bl.a. hvor ofte du har ringet til dem, sendt en mail til dem eller på anden måde kommunikeret med bestemte kontakter. Med denne tilladelse kan apps slette kontaktoplysninger."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Tillader, at appen kan ændre data om de kontakter, der er gemt på din telefon, f.eks. hvor ofte du har ringet til dem, sendt en mail til dem eller på anden måde kommunikeret med bestemte kontakter. Med denne tilladelse kan apps slette kontaktoplysninger."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Tillader, at appen kan ændre data om de kontakter, der er gemt på din tablet. Denne tilladelse giver apps mulighed for at slette kontaktdata."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Tillader, at appen kan ændre data om de kontakter, der er gemt på din Android TV-enhed. Denne tilladelse giver apps mulighed for at slette kontaktdata."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Tillader, at appen kan ændre data om de kontakter, der er gemt på din telefon. Denne tilladelse giver apps mulighed for at slette kontaktdata."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"læse opkaldsliste"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Denne app kan læse din opkaldshistorik."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"skriv opkaldsliste"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"få adgang til yderligere kommandoer for placeringsudbyder"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Tillader, at appen kan få adgang til yderligere kommandoer for placeringsudbydere. Dette kan gøre det muligt for appen at forstyrre GPS-funktionen eller andre placeringskilder."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"få kun adgang til nøjagtig placering i forgrunden"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Denne app kan kun få din nøjagtige placering, når den er i forgrunden. Disse placeringstjenester skal være aktiverede og tilgængelige på din telefon, før appen kan bruge dem. Dette kan øge batteriforbruget."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"få kun adgang til omtrentlig placering (netværksbaseret) i forgrunden"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Denne app kan fastslå din placering ved hjælp af netværkskilder som f.eks. mobilmaster og Wi-Fi-netværk, men kun når appen er i forgrunden. Disse placeringstjenester skal være aktiverede og tilgængelige på din tablet, før appen kan bruge dem."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Denne app kan fastslå din placering ved hjælp af netværkskilder som f.eks. mobilmaster og Wi-Fi-netværk, men kun når appen er i forgrunden. Disse placeringstjenester skal være aktiverede og tilgængelige på din Android TV-enhed, før appen kan bruge dem."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Denne app kan fastslå din placering ved hjælp af netværkskilder som f.eks. mobilmaster og Wi-Fi-netværk, men kun når appen er i forgrunden. Disse placeringstjenester skal være aktiveret og tilgængelige på din telefon, før appen kan bruge dem."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Denne app kan kun finde din nøjagtige placering, når den er i forgrunden. Placeringstjenester skal være aktiverede og tilgængelige på din telefon, før appen kan anvende dem. Dette kan øge batteriforbruget."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"få kun adgang til omtrentlig placering i forgrunden"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Denne app kan kun finde din omtrentlige placering, når den er i forgrunden. Placeringstjenester skal være aktiverede og tilgængelige på din enhed, før appen kan anvende dem."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"adgang til placering i baggrunden"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Hvis appen godkendes, og der gives adgang til den omtrentlige eller nøjagtige placering, kan appen registrere placeringen, mens den kører i baggrunden."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Foruden adgang til placering ved kørsel i forgrunden har denne app også adgang til din placering, mens den kører i baggrunden."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"skifte dine lydindstillinger"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Tillader, at appen kan ændre globale lydindstillinger, som f.eks. lydstyrke og hvilken højttaler der bruges til output."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"optage lyd"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Tillader, at appen kan læse konfigurationen af ​​Bluetooth på tabletten samt kan oprette og acceptere forbindelser med parrede enheder."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Tillader, at appen kan se konfigurationen af Bluetooth på din Android TV-enhed samt oprette og acceptere forbindelser med parrede enheder."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Tillader, at appen kan læse konfigurationen af ​​Bluetooth på telefonen samt kan oprette og acceptere forbindelser med parrede enheder."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Foretrukne oplysninger vedrørende NFC-betalingstjeneste"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Tillader, at appen får foretrukne oplysninger vedrørende NFC-betalingstjeneste, f.eks. registrerede hjælpemidler og rutedestinationer."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"administrere Near Field Communication"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Tillader, at appen kan kommunikere med NFC-tags (Near Field Communication), -kort og -læsere."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"deaktivere din skærmlås"</string>
@@ -900,7 +899,7 @@
<string name="factorytest_no_action" msgid="339252838115675515">"Der blev ikke fundet nogen pakke, som leverer handlingen FACTORY_TEST."</string>
<string name="factorytest_reboot" msgid="2050147445567257365">"Genstart"</string>
<string name="js_dialog_title" msgid="7464775045615023241">"På siden på \"<xliff:g id="TITLE">%s</xliff:g>\" står der:"</string>
- <string name="js_dialog_title_default" msgid="3769524569903332476">"Javascript"</string>
+ <string name="js_dialog_title_default" msgid="3769524569903332476">"JavaScript"</string>
<string name="js_dialog_before_unload_title" msgid="7012587995876771246">"Bekræft navigation"</string>
<string name="js_dialog_before_unload_positive_button" msgid="4274257182303565509">"Forlad denne side"</string>
<string name="js_dialog_before_unload_negative_button" msgid="3873765747622415310">"Bliv på denne side"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"Genvejen til hjælpefunktioner aktiverede <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"Genvejen til hjælpefunktioner deaktiverede <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Hold begge lydstyrkeknapper nede i tre sekunder for at bruge <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Vælg, hvilken funktion du vil bruge, når du trykker på knappen Hjælpefunktioner:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Vælg, hvilken funktion du vil bruge, når du laver bevægelsen for hjælpefunktioner (stryger opad fra bunden af skærmen med to fingre):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Vælg, hvilken funktion du vil bruge, når du laver bevægelsen for hjælpefunktioner (stryger opad fra bunden af skærmen med tre fingre):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Du kan skifte mellem funktioner ved at holde knappen Hjælpefunktioner nede."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Du kan skifte mellem funktioner ved at stryge opad med to fingre og holde dem nede."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Du kan skifte mellem funktioner ved at stryge opad med tre fingre og holde dem nede."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Forstørrelse"</string>
<string name="user_switched" msgid="7249833311585228097">"Nuværende bruger <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="1912993630661332336">"Skifter til <xliff:g id="NAME">%1$s</xliff:g>…"</string>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Tilsluttet <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Tryk for at se filer"</string>
<string name="pin_target" msgid="8036028973110156895">"Fastgør"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Fastgør <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Frigør"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Frigør <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Appinfo"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Starter demoen…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Vil du opdatere disse elementer i "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> og <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Gem"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Nej tak"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Ikke nu"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Aldrig"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Opdater"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Fortsæt"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"adgangskode"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Slå Opdelt skærm til eller fra"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Låseskærm"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Screenshot"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"<xliff:g id="APP_NAME">%1$s</xliff:g>-appen i et pop op-vindue."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Titellinje for <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index bb29a0e2d607..857cdbdcabc5 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Die Admin-App für das Arbeitsprofil fehlt oder ist beschädigt. Daher wurden dein Arbeitsprofil und alle zugehörigen Daten gelöscht. Bitte wende dich für weitere Hilfe an deinen Administrator."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Dein Arbeitsprofil ist auf diesem Gerät nicht mehr verfügbar"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Zu viele falsche Passworteingaben"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Administrator hat das Gerät zur persönlichen Nutzung abgegeben"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Dies ist ein verwaltetes Gerät"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Deine Organisation verwaltet dieses Gerät und überprüft unter Umständen den Netzwerkverkehr. Tippe hier, um weitere Informationen zu erhalten."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Die Daten auf deinem Gerät werden gelöscht."</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Ermöglicht der App, dauerhafte Broadcasts zu senden, die auch nach dem Ende des Broadcasts bestehen bleiben. Ein zu intensiver Einsatz kann das Android TV-Gerät langsam oder instabil machen, weil zu viel Arbeitsspeicher belegt wird."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Ermöglicht der App, dauerhafte Broadcasts zu senden, die auch nach Ende des Broadcasts bestehen bleiben. Ein zu intensiver Einsatz kann das Telefon langsam oder instabil machen, weil zu viel Arbeitsspeicher belegt wird."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"Kontakte lesen"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Ermöglicht der App, Daten zu den auf deinem Tablet gespeicherten Kontakten zu lesen, einschließlich der Häufigkeit, mit der du bestimmte Personen angerufen, diesen E-Mails gesendet oder anderweitig mit ihnen kommuniziert hast. Die Berechtigung erlaubt Apps, deine Kontaktdaten zu speichern, und schädliche Apps können Kontaktdaten ohne dein Wissen weiterleiten."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Ermöglicht der App, Daten zu den auf deinem Android TV-Gerät gespeicherten Kontakten zu lesen, einschließlich der Häufigkeit, mit der du mit den einzelnen Kontakten telefonisch, per E‑Mail, oder anderweitig kommuniziert hast. Diese Berechtigung erlaubt Apps, deine Kontaktdaten zu speichern, weshalb schädliche Apps damit Kontaktdaten ohne dein Wissen teilen können."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Ermöglicht der App, Daten zu den auf deinem Telefon gespeicherten Kontakten zu lesen, einschließlich der Häufigkeit, mit der du bestimmte Personen angerufen, diesen E-Mails gesendet oder anderweitig mit ihnen kommuniziert hast. Die Berechtigung erlaubt Apps, deine Kontaktdaten zu speichern, und schädliche Apps können Kontaktdaten ohne dein Wissen weiterleiten."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Ermöglicht der App, Daten zu den auf deinem Tablet gespeicherten Kontakten zu lesen. Darüber hinaus haben Apps Zugriff auf die Konten auf deinem Tablet, über die Kontakte erstellt wurden. Dabei kann es sich auch um Konten handeln, die von installierten Apps erstellt wurden. Diese Berechtigung erlaubt Apps, deine Kontaktdaten zu speichern. Schädliche Apps könnten dadurch ohne dein Wissen Kontaktdaten teilen."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Ermöglicht der App, Daten zu den auf deinem Android TV-Gerät gespeicherten Kontakten zu lesen. Darüber hinaus haben Apps Zugriff auf die Konten auf deinem Android TV-Gerät, über die Kontakte erstellt wurden. Dabei kann es sich auch um Konten handeln, die von installierten Apps erstellt wurden. Diese Berechtigung erlaubt Apps, deine Kontaktdaten zu speichern. Schädliche Apps könnten dadurch ohne dein Wissen Kontaktdaten teilen."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Ermöglicht der App, Daten zu den auf deinem Smartphone gespeicherten Kontakten zu lesen. Darüber hinaus haben Apps Zugriff auf die Konten auf deinem Smartphone, über die Kontakte erstellt wurden. Dabei kann es sich auch um Konten handeln, die von installierten Apps erstellt wurden. Diese Berechtigung erlaubt Apps, deine Kontaktdaten zu speichern. Schädliche Apps könnten dadurch ohne dein Wissen Kontaktdaten teilen."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"Kontakte ändern"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Ermöglicht der App, Daten zu Kontakten, die auf deinem Tablet gespeichert sind, zu ändern, einschließlich der Häufigkeit, mit der du bestimmte Kontakte angerufen, diesen E-Mails gesendet oder anderweitig mit ihnen kommuniziert hast. Die Berechtigung erlaubt Apps, Kontaktdaten zu löschen."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Ermöglicht der App, Daten zu den auf deinem Android TV-Gerät gespeicherten Kontakten zu ändern, einschließlich der Häufigkeit, mit der du mit den einzelnen Kontakten telefonisch, per E‑Mail, oder anderweitig kommuniziert hast. Diese Berechtigung ermöglicht Apps, Kontaktdaten zu löschen."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Ermöglicht der App, Daten zu Kontakten, die auf deinem Telefon gespeichert sind, zu ändern, einschließlich der Häufigkeit, mit der du bestimmte Kontakte angerufen, diesen E-Mails gesendet oder anderweitig mit ihnen kommuniziert hast. Die Berechtigung erlaubt Apps, Kontaktdaten zu löschen."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Ermöglicht der App, Daten zu den auf deinem Tablet gespeicherten Kontakten zu ändern. Diese Berechtigung erlaubt Apps, Kontaktdaten zu löschen."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Ermöglicht der App, Daten zu den auf deinem Android TV-Gerät gespeicherten Kontakten zu ändern. Diese Berechtigung erlaubt Apps, Kontaktdaten zu löschen."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Ermöglicht der App, Daten zu den auf deinem Smartphone gespeicherten Kontakten zu ändern. Diese Berechtigung erlaubt Apps, Kontaktdaten zu löschen."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"Anrufliste lesen"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Diese App kann deine Anrufliste lesen."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"Anrufliste bearbeiten"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"Auf zusätzliche Dienstanbieterbefehle für Standort zugreifen"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Ermöglicht der App, auf zusätzliche Standortanbieterbefehle zuzugreifen. Damit könnte die App die Funktionsweise von GPS oder anderen Standortquellen beeinträchtigen."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"Nur bei Ausführung im Vordergrund auf den genauen Standort zugreifen"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Diese App kann deinen genauen Standort nur dann ermitteln, wenn sie im Vordergrund ausgeführt wird. Die App kann diese Standortdienste nur verwenden, wenn sie auf deinem Smartphone aktiviert und verfügbar sind. Hierdurch kann sich der Akkuverbrauch erhöhen."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"Nur bei Ausführung im Vordergrund auf den ungefähren Standort (netzwerkbasiert) zugreifen"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Diese App kann deinen Standort anhand von Netzwerkquellen wie Mobilfunkmasten und WLANs ermitteln, allerdings nur, wenn sie im Vordergrund ausgeführt wird. Diese Standortdienste müssen auf deinem Tablet aktiviert und verfügbar sein, damit die App sie nutzen kann."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Diese App kann deinen Standort anhand von Netzwerkquellen wie Mobilfunkmasten und WLANs ermitteln, allerdings nur, wenn sie im Vordergrund ausgeführt wird. Damit die App sie nutzen kann, müssen diese Standortdienste auf deinem Android TV-Gerät aktiviert und verfügbar sein."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Diese App kann deinen Standort anhand von Netzwerkquellen wie Mobilfunkmasten und WLANs ermitteln, allerdings nur, wenn sie im Vordergrund ausgeführt wird. Diese Standortdienste müssen auf deinem Smartphone aktiviert und verfügbar sein, damit die App sie nutzen kann."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Diese App kann deinen genauen Standort nur dann ermitteln, wenn sie im Vordergrund ausgeführt wird. Damit die App Standortdienste nutzen kann, müssen sie auf deinem Gerät aktiviert und verfügbar sein. Hierdurch kann sich der Akkuverbrauch erhöhen."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"Nur bei Ausführung im Vordergrund auf den ungefähren Standort zugreifen"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Diese App kann deinen ungefähren Standort nur dann ermitteln, wenn sie im Vordergrund ausgeführt wird. Damit die App Standortdienste nutzen kann, müssen sie auf deinem Gerät aktiviert und verfügbar sein."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"Im Hintergrund auf den Standort zugreifen"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Wenn zusätzlich zum Zugriff auf den ungefähren oder genauen Standort diese Erlaubnis erteilt wird, kann die App bei Ausführung im Hintergrund auf den Standort zugreifen."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Diese App kann bei Ausführung im Vorder- und Hintergrund auf den Standort zugreifen."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"Audio-Einstellungen ändern"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Ermöglicht der App, globale Audio-Einstellungen zu ändern, etwa die Lautstärke und den Lautsprecher für die Ausgabe."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"Audio aufnehmen"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Ermöglicht der App, die Bluetooth-Konfiguration eines Tablets einzusehen und Verbindungen zu gekoppelten Geräten herzustellen und zu akzeptieren."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Ermöglicht der App, die Bluetooth-Konfiguration des Android TV-Geräts abzurufen und Verbindungen zu gekoppelten Geräten herzustellen und zu akzeptieren."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Ermöglicht der App, die Bluetooth-Konfiguration des Telefons einzusehen und Verbindungen mit gekoppelten Geräten herzustellen und zu akzeptieren."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Informationen zum bevorzugten NFC-Zahlungsdienst"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Ermöglicht der App, Informationen zum bevorzugten NFC-Zahlungsdienst abzurufen, etwa registrierte Hilfsmittel oder das Routenziel."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"Nahfeldkommunikation steuern"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Ermöglicht der App die Kommunikation mit Tags für die Nahfeldkommunikation, Karten und Readern"</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"Displaysperre deaktivieren"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> wurde durch die Bedienungshilfenverknüpfung aktiviert"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> wurde durch die Bedienungshilfenverknüpfung deaktiviert"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Halten Sie beide Lautstärketasten drei Sekunden lang gedrückt, um <xliff:g id="SERVICE_NAME">%1$s</xliff:g> zu verwenden"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Wähle den Dienst aus, der verwendet werden soll, wenn du auf die Schaltfläche für die Bedienungshilfen tippst:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Wähle den Dienst aus, der mit der Touch-Geste für die Bedienungshilfen verwendet werden soll (mit zwei Fingern vom unteren Bildschirmrand nach oben wischen):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Wähle den Dienst aus, der mit der Touch-Geste für die Bedienungshilfen verwendet werden soll (mit drei Fingern vom unteren Bildschirmrand nach oben wischen):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Wenn du zwischen den Diensten wechseln möchtest, halte die Schaltfläche für die Bedienungshilfen gedrückt."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Wenn du zwischen den Diensten wechseln möchtest, wische mit zwei Fingern nach oben und halte sie gedrückt."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Wenn du zwischen den Diensten wechseln möchtest, wische mit drei Fingern nach oben und halte sie gedrückt."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Vergrößerung"</string>
<string name="user_switched" msgid="7249833311585228097">"Aktueller Nutzer <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="user_switching_message" msgid="1912993630661332336">"Wechseln zu <xliff:g id="NAME">%1$s</xliff:g>…"</string>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Verbunden mit <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Zum Ansehen der Dateien tippen"</string>
<string name="pin_target" msgid="8036028973110156895">"Markieren"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"<xliff:g id="LABEL">%1$s</xliff:g> anpinnen"</string>
<string name="unpin_target" msgid="3963318576590204447">"Markierung entfernen"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"<xliff:g id="LABEL">%1$s</xliff:g> loslösen"</string>
<string name="app_info" msgid="6113278084877079851">"App-Informationen"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Demo wird gestartet…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> und <xliff:g id="TYPE_2">%3$s</xliff:g> in "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" aktualisieren?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Speichern"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Nein danke"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Nicht jetzt"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Nie"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Aktualisieren"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Fortsetzen"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"Passwort"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"\"Bildschirm teilen\" ein-/ausschalten"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Sperrbildschirm"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Screenshot"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"App \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" im Pop-up-Fenster."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Untertitelleiste von <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 807c4c279903..817df16b6c3a 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Η εφαρμογή διαχείρισης προφίλ εργασίας είτε λείπει είτε είναι κατεστραμμένη. Ως αποτέλεσμα, διαγράφηκε το προφίλ εργασίας και τα σχετικά δεδομένα. Επικοινωνήστε με τον διαχειριστή σας για βοήθεια."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Το προφίλ εργασίας σας δεν είναι πια διαθέσιμο σε αυτήν τη συσκευή"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Πάρα πολλές προσπάθειες εισαγωγής κωδικού πρόσβασης"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Συσκευή από την οποία αποσύρθηκε ο διαχειριστής για προσωπική χρήση"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Η συσκευή είναι διαχειριζόμενη"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Ο οργανισμός σας διαχειρίζεται αυτήν τη συσκευή και ενδέχεται να παρακολουθεί την επισκεψιμότητα δικτύου. Πατήστε για λεπτομέρειες."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Η συσκευή σας θα διαγραφεί"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Επιτρέπει στην εφαρμογή την αποστολή μεταδόσεων που παραμένουν μετά το τέλος της διαδικασίας μετάδοσης. Η υπερβολική χρήση αυτής της δυνατότητας μπορεί να καταστήσει τη λειτουργία της συσκευής Android TV αργή ή ασταθή λόγω της χρήσης πολλής μνήμης."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Επιτρέπει στην εφαρμογή την αποστολή εκπομπών sticky, οι οποίες παραμένουν μετά το τέλος της εκπομπής. Η υπερβολική χρήση ενδέχεται να καταστήσει τη λειτουργία του τηλεφώνου αργή ή ασταθή, προκαλώντας τη χρήση μεγάλου τμήματος της μνήμης."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"διαβάζει τις επαφές σας"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Επιτρέπει στην εφαρμογή την ανάγνωση δεδομένων σχετικά με τις επαφές σας που είναι αποθηκευμένες στο tablet σας, συμπεριλαμβανομένης της συχνότητας με την οποία έχετε καλέσει συγκεκριμένα άτομα ή έχετε επικοινωνήσει μαζί τους μέσω ηλεκτρονικού ταχυδρομείου ή άλλου τρόπου. Αυτή η άδεια δίνει τη δυνατότητα σε εφαρμογές να αποθηκεύουν τα δεδομένα των επαφών σας και οι κακόβουλες εφαρμογές ενδέχεται να μοιράζονται δεδομένα επαφών χωρίς να το γνωρίζετε."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Επιτρέπει στην εφαρμογή να διαβάζει τα δεδομένα που αποθηκεύονται στη συσκευή Android TV σχετικά με τις επαφές σας, συμπεριλαμβανομένης της συχνότητας με την οποία κάνετε κλήσεις, στέλνετε μηνύματα ηλεκτρονικού ταχυδρομείου ή επικοινωνείτε με άλλους τρόπους με συγκεκριμένα άτομα. Αυτή η άδεια δίνει τη δυνατότητα στις εφαρμογές να αποθηκεύουν τα δεδομένα των επαφών σας. Οι κακόβουλες εφαρμογές ενδέχεται να μοιράζονται τα δεδομένα επαφών χωρίς να το γνωρίζετε."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Επιτρέπει στην εφαρμογή την ανάγνωση δεδομένων σχετικά με τις επαφές σας που είναι αποθηκευμένες στο τηλέφωνό σας, συμπεριλαμβανομένης της συχνότητας με την οποία έχετε καλέσει συγκεκριμένα άτομα ή έχετε επικοινωνήσει μαζί τους μέσω ηλεκτρονικού ταχυδρομείου ή άλλου τρόπου. Αυτή η άδεια δίνει τη δυνατότητα σε εφαρμογές να αποθηκεύουν τα δεδομένα των επαφών σας και οι κακόβουλες εφαρμογές ενδέχεται να μοιράζονται δεδομένα επαφών χωρίς να το γνωρίζετε."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Επιτρέπει στην εφαρμογή να διαβάζει δεδομένα σχετικά με τις επαφές σας που έχουν αποθηκευτεί στο tablet. Οι εφαρμογές θα έχουν επίσης πρόσβαση στους λογαριασμούς στο tablet, οι οποίοι έχουν δημιουργήσει επαφές. Σε αυτούς ενδέχεται να περιλαμβάνονται λογαριασμοί που δημιουργήθηκαν από εφαρμογές που έχετε εγκαταστήσει. Αυτή η άδεια δίνει τη δυνατότητα στις εφαρμογές να αποθηκεύουν τα δεδομένα των επαφών σας. Οι κακόβουλες εφαρμογές ενδέχεται να μοιράζονται τα δεδομένα επαφών χωρίς να το γνωρίζετε."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Επιτρέπει στην εφαρμογή να διαβάζει δεδομένα σχετικά με τις επαφές σας που έχουν αποθηκευτεί στη συσκευή σας Android TV. Οι εφαρμογές θα έχουν επίσης πρόσβαση στους λογαριασμούς στη συσκευή σας Android TV, οι οποίοι έχουν δημιουργήσει επαφές. Σε αυτούς ενδέχεται να περιλαμβάνονται λογαριασμοί που δημιουργήθηκαν από εφαρμογές που έχετε εγκαταστήσει. Αυτή η άδεια δίνει τη δυνατότητα στις εφαρμογές να αποθηκεύουν τα δεδομένα των επαφών σας. Οι κακόβουλες εφαρμογές ενδέχεται να μοιράζονται τα δεδομένα επαφών χωρίς να το γνωρίζετε."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Επιτρέπει στην εφαρμογή να διαβάζει δεδομένα σχετικά με τις επαφές σας που έχουν αποθηκευτεί στο τηλέφωνό σας. Οι εφαρμογές θα έχουν επίσης πρόσβαση στους λογαριασμούς στο τηλέφωνό σας, οι οποίοι έχουν δημιουργήσει επαφές. Σε αυτούς ενδέχεται να περιλαμβάνονται λογαριασμοί που δημιουργήθηκαν από εφαρμογές που έχετε εγκαταστήσει. Αυτή η άδεια δίνει τη δυνατότητα στις εφαρμογές να αποθηκεύουν τα δεδομένα των επαφών σας. Οι κακόβουλες εφαρμογές ενδέχεται να μοιράζονται τα δεδομένα επαφών χωρίς να το γνωρίζετε."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"τροποποιεί τις επαφές σας"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Επιτρέπει στην εφαρμογή την τροποποίηση των δεδομένων σχετικά με τις επαφές σας που είναι αποθηκευμένες στο tablet σας, συμπεριλαμβανομένης της συχνότητας με την οποία έχετε καλέσει συγκεκριμένες επαφές ή έχετε επικοινωνήσει μαζί τους μέσω ηλεκτρονικού ταχυδρομείου ή άλλου τρόπου. Αυτή η άδεια δίνει τη δυνατότητα σε εφαρμογές να διαγράφουν δεδομένα επαφών."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Επιτρέπει στην εφαρμογή να τροποποιεί τα δεδομένα που αποθηκεύονται στη συσκευή Android TV σχετικά με τις επαφές σας, συμπεριλαμβανομένης της συχνότητας με την οποία κάνετε κλήσεις, στέλνετε μηνύματα ηλεκτρονικού ταχυδρομείου ή επικοινωνείτε με άλλους τρόπους με συγκεκριμένες επαφές. Αυτή η άδεια επιτρέπει στις εφαρμογές να διαγράφουν δεδομένα επαφών."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Επιτρέπει στην εφαρμογή την τροποποίηση των δεδομένων σχετικά με τις επαφές σας που είναι αποθηκευμένες στο τηλέφωνό σας, συμπεριλαμβανομένης της συχνότητας με την οποία έχετε καλέσει συγκεκριμένες επαφές ή έχετε επικοινωνήσει μαζί τους μέσω ηλεκτρονικού ταχυδρομείου ή άλλου τρόπου. Αυτή η άδεια δίνει τη δυνατότητα σε εφαρμογές να διαγράφουν δεδομένα επαφών."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Επιτρέπει στην εφαρμογή να τροποποιεί δεδομένα σχετικά με τις επαφές σας που έχουν αποθηκευτεί στο tablet. Αυτή η άδεια επιτρέπει στις εφαρμογές να διαγράφουν δεδομένα επαφών."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Επιτρέπει στην εφαρμογή να τροποποιήσει τα δεδομένα σχετικά με τις επαφές σας που έχουν αποθηκευτεί στη συσκευή σας Android TV. Αυτή η άδεια επιτρέπει στις εφαρμογές να διαγράφουν δεδομένα επαφών."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Επιτρέπει στην εφαρμογή να τροποποιεί τα δεδομένα σχετικά με τις επαφές σας που έχουν αποθηκευτεί στο tablet. Αυτή η άδεια επιτρέπει στις εφαρμογές να διαγράφουν δεδομένα επαφών."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"διαβάζει το αρχείο καταγραφής κλήσεων"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Αυτή η εφαρμογή μπορεί να διαβάσει το ιστορικό κλήσεων."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"εγγράφει αρχείο καταγραφής κλήσεων"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"έχει πρόσβαση σε επιπλέον εντολές παρόχου τοποθεσίας"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Επιτρέπει στην εφαρμογή την πρόσβαση σε επιπλέον εντολές παρόχου τοποθεσίας. Αυτό μπορεί να δώσει τη δυνατότητα στην εφαρμογή να παρέμβει στη λειτουργία του GPS ή άλλων πηγών τοποθεσίας."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"πρόσβαση στην ακριβή τοποθεσία μόνο στο προσκήνιο"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Αυτή η εφαρμογή μπορεί να ανιχνεύσει την ακριβή τοποθεσία σας όταν βρίσκεται στο προσκήνιο. Αυτές οι υπηρεσίες τοποθεσίας θα πρέπει να είναι ενεργοποιημένες και διαθέσιμες στο τηλέφωνό σας, προκειμένου να μπορεί να τις χρησιμοποιήσει η εφαρμογή. Με την ενεργοποίηση αυτής της ρύθμισης, μπορεί να αυξηθεί η κατανάλωση μπαταρίας."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"πρόσβαση στην κατά προσέγγιση τοποθεσία (βάσει δικτύου) μόνο στο προσκήνιο"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Αυτή η εφαρμογή μπορεί να ανιχνεύσει την τοποθεσία σας βάσει πηγών δικτύου, όπως κεραίες κινητής τηλεφωνίας και δίκτυα Wi-Fi, αλλά μόνο όταν η εφαρμογή βρίσκεται στο προσκήνιο. Αυτές οι υπηρεσίες τοποθεσίας θα πρέπει να είναι ενεργοποιημένες και διαθέσιμες στο tablet που χρησιμοποιείτε, προκειμένου να μπορεί να τις χρησιμοποιήσει η εφαρμογή."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Αυτή η εφαρμογή μπορεί να ανιχνεύσει την τοποθεσία σας βάσει πηγών δικτύου, όπως οι κεραίες κινητής τηλεφωνίας και τα δίκτυα Wi-Fi, αλλά μόνο όταν η εφαρμογή βρίσκεται στο προσκήνιο. Αυτές οι υπηρεσίες τοποθεσίας θα πρέπει να είναι ενεργοποιημένες και διαθέσιμες στη συσκευή Android TV, προκειμένου να μπορεί να τις χρησιμοποιήσει η εφαρμογή."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Αυτή η εφαρμογή μπορεί να ανιχνεύσει την τοποθεσία σας βάσει πηγών δικτύου, όπως κεραίες κινητής τηλεφωνίας και δίκτυα Wi-Fi, αλλά μόνο όταν η εφαρμογή βρίσκεται στο προσκήνιο. Αυτές οι υπηρεσίες τοποθεσίας θα πρέπει να είναι ενεργοποιημένες και διαθέσιμες στο τηλέφωνό σας, προκειμένου να μπορεί να τις χρησιμοποιήσει η εφαρμογή."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Αυτή η εφαρμογή μπορεί να ανιχνεύσει την ακριβή τοποθεσία σας μόνο όταν βρίσκεται στο προσκήνιο. Οι υπηρεσίες τοποθεσίας θα πρέπει να είναι ενεργοποιημένες και διαθέσιμες στη συσκευή σας, προκειμένου να μπορεί να τις χρησιμοποιήσει η εφαρμογή. Με την ενεργοποίηση αυτής της ρύθμισης, μπορεί να αυξηθεί η κατανάλωση μπαταρίας."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"πρόσβαση στην κατά προσέγγιση τοποθεσία μόνο στο προσκήνιο"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Αυτή η εφαρμογή έχει πρόσβαση στην τοποθεσία κατά προσέγγιση, μόνο όταν βρίσκεται στο προσκήνιο. Οι υπηρεσίες τοποθεσίας πρέπει να έχουν ενεργοποιηθεί και να είναι διαθέσιμες στη συσκευή σας, για να μπορεί να τις χρησιμοποιήσει η εφαρμογή."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"πρόσβαση στην τοποθεσία στο παρασκήνιο"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Εάν εκχωρηθεί επιπρόσθετα σε μια καταπροσέγγιση ή ακριβή πρόσβαση τοποθεσίας, η εφαρμογή μπορεί να έχει πρόσβαση στην τοποθεσία κατά την εκτέλεση στο παρασκήνιο."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Εκτός από την πρόσβαση τοποθεσίας ενώ βρίσκεται στο προσκήνιο, αυτή η εφαρμογή μπορεί να αποκτήσει πρόσβαση στην τοποθεσία ενώ εκτελείται στο παρασκήνιο."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"αλλάζει τις ρυθμίσεις ήχου"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Επιτρέπει στην εφαρμογή την τροποποίηση καθολικών ρυθμίσεων ήχου, όπως η ένταση και ποιο ηχείο χρησιμοποιείται για έξοδο."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"εγγράφει ήχο"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Επιτρέπει στην εφαρμογή να προβάλλει τη διαμόρφωση του Bluetooth στο tablet, καθώς και να πραγματοποιεί και να αποδέχεται συνδέσεις με συνδεδεμένες συσκευές."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Επιτρέπει στην εφαρμογή να βλέπει τη διαμόρφωση του Bluetooth στη συσκευή Android TV και να κάνει και να αποδέχεται συνδέσεις με συζευγμένες συσκευές."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Επιτρέπει στην εφαρμογή να προβάλλει τη διαμόρφωση του Bluetooth στο τηλέφωνο, καθώς και να πραγματοποιεί και να αποδέχεται συνδέσεις με συνδεδεμένες συσκευές."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Πληροφορίες προτιμώμενης υπηρεσίας πληρωμών NFC"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Επιτρέπει στην εφαρμογή να λαμβάνει πληροφορίες προτιμώμενης υπηρεσίας πληρωμής NFC, όπως καταχωρημένα βοηθήματα και προορισμό διαδρομής."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"ελέγχει την Επικοινωνία κοντινού πεδίου (FNC)"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Επιτρέπει στην εφαρμογή την επικοινωνία με ετικέτες, κάρτες και αναγνώστες της Επικοινωνίας κοντινού πεδίου (NFC)."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"απενεργοποιεί το κλείδωμα οθόνης"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"Η συντόμευση προσβασιμότητας ενεργοποίησε την υπηρεσία <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"Η συντόμευση προσβασιμότητας απενεργοποίησε την υπηρεσία <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>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Επιλέξτε μια υπηρεσία που θα χρησιμοποιείται κατά το πάτημα του κουμπιού προσβασιμότητας:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Επιλέξτε μια υπηρεσία που θα χρησιμοποιείται με την κίνηση προσβασιμότητας (σύρετε με δύο δάχτυλα προς τα επάνω από το κάτω μέρος της οθόνης):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Επιλέξτε μια υπηρεσία που θα χρησιμοποιείται με την κίνηση προσβασιμότητας (σύρετε με τρία δάχτυλα προς τα επάνω από το κάτω μέρος της οθόνης):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Για εναλλαγή μεταξύ υπηρεσιών, αγγίξτε παρατεταμένα το κουμπί προσβασιμότητας."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Για εναλλαγή μεταξύ υπηρεσιών, σύρετε παρατεταμένα με δύο δάχτυλα προς τα επάνω και μην τα απομακρύνετε από την οθόνη."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Για εναλλαγή μεταξύ υπηρεσιών, σύρετε παρατεταμένα με τρία δάχτυλα προς τα επάνω."</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>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Συνδέθηκε με το <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Πατήστε για να δείτε τα αρχεία"</string>
<string name="pin_target" msgid="8036028973110156895">"Καρφίτσωμα"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Καρφίτσωμα <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Ξεκαρφίτσωμα"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Ξεκαρφίτσωμα <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Πληροφορίες εφαρμογής"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Έναρξη επίδειξης…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Ενημέρωση αυτών των στοιχείων "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <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>;"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Αποθήκευση"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Όχι, ευχαριστώ"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Όχι τώρα"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Ποτέ"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Ενημέρωση"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Συνέχεια"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"κωδικός πρόσβασης"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Εναλλαγή διαχωρισμού οθόνης"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Οθόνη κλειδώματος"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Στιγμιότυπο οθόνης"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> σε αναδυόμενο παράθυρο."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Γραμμή υποτίτλων για την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 8d2f80541c59..33a84883c791 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"The work profile admin app is either missing or corrupted. As a result, your work profile and related data have been deleted. Contact your admin for assistance."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Your work profile is no longer available on this device"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Too many password attempts"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Admin relinquished device for personal use"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Device is managed"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Your organisation manages this device and may monitor network traffic. Tap for details."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Your device will be erased"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Allows the app to send sticky broadcasts, which remain after the broadcast ends. Excessive use may make your Android TV device slow or unstable by causing it to use too much memory."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Allows the app to send sticky broadcasts, which remain after the broadcast ends. Excessive use may make the phone slow or unstable by causing it to use too much memory."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"read your contacts"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Allows the app to read data about your contacts stored on your tablet, including the frequency with which you\'ve called, emailed or communicated in other ways with specific individuals. This permission allows apps to save your contact data, and malicious apps may share contact data without your knowledge."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Allows the app to read data about your contacts stored on your Android TV device, including the frequency with which you\'ve called, emailed or communicated in other ways with specific individuals. This permission allows apps to save your contact data, and malicious apps may share contact data without your knowledge."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Allows the app to read data about your contacts stored on your phone, including the frequency with which you\'ve called, emailed or communicated in other ways with specific individuals. This permission allows apps to save your contact data, and malicious apps may share contact data without your knowledge."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Allows the app to read data about your contacts stored on your tablet. Apps will also have access to the accounts on your tablet that have created contacts. This may include any accounts created by apps that you have installed. This permission allows any apps to save your contact data, and malicious apps may share contact data without your knowledge."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Allows the app to read data about your contacts stored on your Android TV device. Apps will also have access to the accounts on your Android TV device that have created contacts. This may include any accounts created by apps that you have installed. This permission allows any apps to save your contact data, and malicious apps may share contact data without your knowledge."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Allows the app to read data about your contacts stored on your phone. Apps will also have access to the accounts on your phone that have created contacts. This may include any accounts created by apps that you have installed. This permission allows any apps to save your contact data, and malicious apps may share contact data without your knowledge."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"modify your contacts"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Allows the app to modify the data about your contacts stored on your tablet, including the frequency with which you\'ve called, emailed or communicated in other ways with specific contacts. This permission allows apps to delete contact data."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Allows the app to modify the data about your contacts stored on your Android TV device, including the frequency with which you\'ve called, emailed or communicated in other ways with specific contacts. This permission allows apps to delete contact data."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Allows the app to modify the data about your contacts stored on your phone, including the frequency with which you\'ve called, emailed or communicated in other ways with specific contacts. This permission allows apps to delete contact data."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Allows the app to modify the data about your contacts stored on your tablet. This permission allows apps to delete contact data."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Allows the app to modify the data about your contacts stored on your Android TV device. This permission allows apps to delete contact data."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Allows the app to modify the data about your contacts stored on your phone. This permission allows apps to delete contact data."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"read call log"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"This app can read your call history."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"write call log"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"access extra location provider commands"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Allows the app to access extra location provider commands. This may allow the app to interfere with the operation of the GPS or other location sources."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"access precise location only in the foreground"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"This app can get your exact location only when it is in the foreground. These location services must be turned on and available on your phone for the app to be able to use them. This may increase battery consumption."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"access approximate location (network-based) only in the foreground"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"This app can get your location based on network sources such as phone masts and Wi-Fi networks, but only when the app is in the foreground. These location services must be turned on and available on your tablet for the app to be able to use them."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"This app can get your location based on network sources such as phone masts and Wi-Fi networks, but only when the app is in the foreground. These location services must be turned on and available on your Android TV device for the app to be able to use them."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"This app can get your location based on network sources such as phone masts and Wi-Fi networks, but only when the app is in the foreground. These location services must be turned on and available on your phone for the app to be able to use them."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"This app can get your exact location only when it is in the foreground. Location Services must be turned on and available on your device for the app to be able to use them. This may increase battery consumption."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"access approximate location only in the foreground"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"This app can get your approximate location only when it is in the foreground. Location Services must be turned on and available on your device for the app to be able to use them."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"access location in the background"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"If this is granted additionally to the approximate or precise location access, the app can access the location while running in the background."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"This app can access location while running in the background, in addition to foreground location access."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"change your audio settings"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Allows the app to modify global audio settings such as volume and which speaker is used for output."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"record audio"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Allows the app to view the configuration of Bluetooth on the tablet and to make and accept connections with paired devices."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Allows the app to view the configuration of Bluetooth on your Android TV device and to make and accept connections with paired devices."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Allows the app to view the configuration of the Bluetooth on the phone and to make and accept connections with paired devices."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Preferred NFC payment service information"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Allows the app to get preferred NFC payment service information, such as registered aids and route destination."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"control Near-Field Communication"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Allows the app to communicate with Near Field Communication (NFC) tags, cards and readers."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"disable your screen lock"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"Accessibility Shortcut turned <xliff:g id="SERVICE_NAME">%1$s</xliff:g> on"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"Accessibility Shortcut turned <xliff:g id="SERVICE_NAME">%1$s</xliff:g> off"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Press and hold both volume keys for three seconds to use <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Choose a service to use when you tap the accessibility button:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Choose a service to use with the accessibility gesture (swipe up from the bottom of the screen with two fingers):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Choose a service to use with the accessibility gesture (swipe up from the bottom of the screen with three fingers):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"To switch between services, touch &amp; hold the accessibility button."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"To switch between services, swipe up with two fingers and hold."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"To switch between services, swipe up with three fingers and hold."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Magnification"</string>
<string name="user_switched" msgid="7249833311585228097">"Current user <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="1912993630661332336">"Switching to <xliff:g id="NAME">%1$s</xliff:g>…"</string>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Connected to <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Tap to view files"</string>
<string name="pin_target" msgid="8036028973110156895">"Pin"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Pin <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Unpin"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Unpin <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"App info"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Starting demo…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Update these items in "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> and <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Save"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"No, thanks"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Not now"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Never"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Update"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Continue"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"password"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Toggle Split Screen"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Lock Screen"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Screenshot"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"<xliff:g id="APP_NAME">%1$s</xliff:g> app in pop-up window."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Caption bar of <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index e53858750de9..b2ba41946f0b 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"The work profile admin app is either missing or corrupted. As a result, your work profile and related data have been deleted. Contact your admin for assistance."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Your work profile is no longer available on this device"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Too many password attempts"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Admin relinquished device for personal use"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Device is managed"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Your organisation manages this device and may monitor network traffic. Tap for details."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Your device will be erased"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Allows the app to send sticky broadcasts, which remain after the broadcast ends. Excessive use may make your Android TV device slow or unstable by causing it to use too much memory."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Allows the app to send sticky broadcasts, which remain after the broadcast ends. Excessive use may make the phone slow or unstable by causing it to use too much memory."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"read your contacts"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Allows the app to read data about your contacts stored on your tablet, including the frequency with which you\'ve called, emailed or communicated in other ways with specific individuals. This permission allows apps to save your contact data, and malicious apps may share contact data without your knowledge."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Allows the app to read data about your contacts stored on your Android TV device, including the frequency with which you\'ve called, emailed or communicated in other ways with specific individuals. This permission allows apps to save your contact data, and malicious apps may share contact data without your knowledge."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Allows the app to read data about your contacts stored on your phone, including the frequency with which you\'ve called, emailed or communicated in other ways with specific individuals. This permission allows apps to save your contact data, and malicious apps may share contact data without your knowledge."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Allows the app to read data about your contacts stored on your tablet. Apps will also have access to the accounts on your tablet that have created contacts. This may include any accounts created by apps that you have installed. This permission allows any apps to save your contact data, and malicious apps may share contact data without your knowledge."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Allows the app to read data about your contacts stored on your Android TV device. Apps will also have access to the accounts on your Android TV device that have created contacts. This may include any accounts created by apps that you have installed. This permission allows any apps to save your contact data, and malicious apps may share contact data without your knowledge."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Allows the app to read data about your contacts stored on your phone. Apps will also have access to the accounts on your phone that have created contacts. This may include any accounts created by apps that you have installed. This permission allows any apps to save your contact data, and malicious apps may share contact data without your knowledge."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"modify your contacts"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Allows the app to modify the data about your contacts stored on your tablet, including the frequency with which you\'ve called, emailed or communicated in other ways with specific contacts. This permission allows apps to delete contact data."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Allows the app to modify the data about your contacts stored on your Android TV device, including the frequency with which you\'ve called, emailed or communicated in other ways with specific contacts. This permission allows apps to delete contact data."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Allows the app to modify the data about your contacts stored on your phone, including the frequency with which you\'ve called, emailed or communicated in other ways with specific contacts. This permission allows apps to delete contact data."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Allows the app to modify the data about your contacts stored on your tablet. This permission allows apps to delete contact data."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Allows the app to modify the data about your contacts stored on your Android TV device. This permission allows apps to delete contact data."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Allows the app to modify the data about your contacts stored on your phone. This permission allows apps to delete contact data."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"read call log"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"This app can read your call history."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"write call log"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"access extra location provider commands"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Allows the app to access extra location provider commands. This may allow the app to interfere with the operation of the GPS or other location sources."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"access precise location only in the foreground"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"This app can get your exact location only when it is in the foreground. These location services must be turned on and available on your phone for the app to be able to use them. This may increase battery consumption."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"access approximate location (network-based) only in the foreground"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"This app can get your location based on network sources such as phone masts and Wi-Fi networks, but only when the app is in the foreground. These location services must be turned on and available on your tablet for the app to be able to use them."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"This app can get your location based on network sources such as phone masts and Wi-Fi networks, but only when the app is in the foreground. These location services must be turned on and available on your Android TV device for the app to be able to use them."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"This app can get your location based on network sources such as phone masts and Wi-Fi networks, but only when the app is in the foreground. These location services must be turned on and available on your phone for the app to be able to use them."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"This app can get your exact location only when it is in the foreground. Location Services must be turned on and available on your device for the app to be able to use them. This may increase battery consumption."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"access approximate location only in the foreground"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"This app can get your approximate location only when it is in the foreground. Location Services must be turned on and available on your device for the app to be able to use them."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"access location in the background"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"If this is granted additionally to the approximate or precise location access, the app can access the location while running in the background."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"This app can access location while running in the background, in addition to foreground location access."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"change your audio settings"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Allows the app to modify global audio settings such as volume and which speaker is used for output."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"record audio"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Allows the app to view the configuration of Bluetooth on the tablet and to make and accept connections with paired devices."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Allows the app to view the configuration of Bluetooth on your Android TV device and to make and accept connections with paired devices."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Allows the app to view the configuration of the Bluetooth on the phone and to make and accept connections with paired devices."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Preferred NFC payment service information"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Allows the app to get preferred NFC payment service information, such as registered aids and route destination."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"control Near-Field Communication"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Allows the app to communicate with Near Field Communication (NFC) tags, cards and readers."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"disable your screen lock"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"Accessibility Shortcut turned <xliff:g id="SERVICE_NAME">%1$s</xliff:g> on"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"Accessibility Shortcut turned <xliff:g id="SERVICE_NAME">%1$s</xliff:g> off"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Press and hold both volume keys for three seconds to use <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Choose a service to use when you tap the accessibility button:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Choose a service to use with the accessibility gesture (swipe up from the bottom of the screen with two fingers):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Choose a service to use with the accessibility gesture (swipe up from the bottom of the screen with three fingers):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"To switch between services, touch &amp; hold the accessibility button."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"To switch between services, swipe up with two fingers and hold."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"To switch between services, swipe up with three fingers and hold."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Magnification"</string>
<string name="user_switched" msgid="7249833311585228097">"Current user <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="1912993630661332336">"Switching to <xliff:g id="NAME">%1$s</xliff:g>…"</string>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Connected to <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Tap to view files"</string>
<string name="pin_target" msgid="8036028973110156895">"Pin"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Pin <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Unpin"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Unpin <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"App info"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Starting demo…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Update these items in "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> and <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Save"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"No, thanks"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Not now"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Never"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Update"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Continue"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"password"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Toggle Split Screen"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Lock Screen"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Screenshot"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"<xliff:g id="APP_NAME">%1$s</xliff:g> app in pop-up window."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Caption bar of <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 8d2f80541c59..33a84883c791 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"The work profile admin app is either missing or corrupted. As a result, your work profile and related data have been deleted. Contact your admin for assistance."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Your work profile is no longer available on this device"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Too many password attempts"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Admin relinquished device for personal use"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Device is managed"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Your organisation manages this device and may monitor network traffic. Tap for details."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Your device will be erased"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Allows the app to send sticky broadcasts, which remain after the broadcast ends. Excessive use may make your Android TV device slow or unstable by causing it to use too much memory."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Allows the app to send sticky broadcasts, which remain after the broadcast ends. Excessive use may make the phone slow or unstable by causing it to use too much memory."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"read your contacts"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Allows the app to read data about your contacts stored on your tablet, including the frequency with which you\'ve called, emailed or communicated in other ways with specific individuals. This permission allows apps to save your contact data, and malicious apps may share contact data without your knowledge."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Allows the app to read data about your contacts stored on your Android TV device, including the frequency with which you\'ve called, emailed or communicated in other ways with specific individuals. This permission allows apps to save your contact data, and malicious apps may share contact data without your knowledge."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Allows the app to read data about your contacts stored on your phone, including the frequency with which you\'ve called, emailed or communicated in other ways with specific individuals. This permission allows apps to save your contact data, and malicious apps may share contact data without your knowledge."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Allows the app to read data about your contacts stored on your tablet. Apps will also have access to the accounts on your tablet that have created contacts. This may include any accounts created by apps that you have installed. This permission allows any apps to save your contact data, and malicious apps may share contact data without your knowledge."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Allows the app to read data about your contacts stored on your Android TV device. Apps will also have access to the accounts on your Android TV device that have created contacts. This may include any accounts created by apps that you have installed. This permission allows any apps to save your contact data, and malicious apps may share contact data without your knowledge."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Allows the app to read data about your contacts stored on your phone. Apps will also have access to the accounts on your phone that have created contacts. This may include any accounts created by apps that you have installed. This permission allows any apps to save your contact data, and malicious apps may share contact data without your knowledge."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"modify your contacts"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Allows the app to modify the data about your contacts stored on your tablet, including the frequency with which you\'ve called, emailed or communicated in other ways with specific contacts. This permission allows apps to delete contact data."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Allows the app to modify the data about your contacts stored on your Android TV device, including the frequency with which you\'ve called, emailed or communicated in other ways with specific contacts. This permission allows apps to delete contact data."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Allows the app to modify the data about your contacts stored on your phone, including the frequency with which you\'ve called, emailed or communicated in other ways with specific contacts. This permission allows apps to delete contact data."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Allows the app to modify the data about your contacts stored on your tablet. This permission allows apps to delete contact data."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Allows the app to modify the data about your contacts stored on your Android TV device. This permission allows apps to delete contact data."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Allows the app to modify the data about your contacts stored on your phone. This permission allows apps to delete contact data."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"read call log"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"This app can read your call history."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"write call log"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"access extra location provider commands"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Allows the app to access extra location provider commands. This may allow the app to interfere with the operation of the GPS or other location sources."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"access precise location only in the foreground"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"This app can get your exact location only when it is in the foreground. These location services must be turned on and available on your phone for the app to be able to use them. This may increase battery consumption."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"access approximate location (network-based) only in the foreground"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"This app can get your location based on network sources such as phone masts and Wi-Fi networks, but only when the app is in the foreground. These location services must be turned on and available on your tablet for the app to be able to use them."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"This app can get your location based on network sources such as phone masts and Wi-Fi networks, but only when the app is in the foreground. These location services must be turned on and available on your Android TV device for the app to be able to use them."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"This app can get your location based on network sources such as phone masts and Wi-Fi networks, but only when the app is in the foreground. These location services must be turned on and available on your phone for the app to be able to use them."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"This app can get your exact location only when it is in the foreground. Location Services must be turned on and available on your device for the app to be able to use them. This may increase battery consumption."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"access approximate location only in the foreground"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"This app can get your approximate location only when it is in the foreground. Location Services must be turned on and available on your device for the app to be able to use them."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"access location in the background"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"If this is granted additionally to the approximate or precise location access, the app can access the location while running in the background."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"This app can access location while running in the background, in addition to foreground location access."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"change your audio settings"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Allows the app to modify global audio settings such as volume and which speaker is used for output."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"record audio"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Allows the app to view the configuration of Bluetooth on the tablet and to make and accept connections with paired devices."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Allows the app to view the configuration of Bluetooth on your Android TV device and to make and accept connections with paired devices."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Allows the app to view the configuration of the Bluetooth on the phone and to make and accept connections with paired devices."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Preferred NFC payment service information"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Allows the app to get preferred NFC payment service information, such as registered aids and route destination."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"control Near-Field Communication"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Allows the app to communicate with Near Field Communication (NFC) tags, cards and readers."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"disable your screen lock"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"Accessibility Shortcut turned <xliff:g id="SERVICE_NAME">%1$s</xliff:g> on"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"Accessibility Shortcut turned <xliff:g id="SERVICE_NAME">%1$s</xliff:g> off"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Press and hold both volume keys for three seconds to use <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Choose a service to use when you tap the accessibility button:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Choose a service to use with the accessibility gesture (swipe up from the bottom of the screen with two fingers):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Choose a service to use with the accessibility gesture (swipe up from the bottom of the screen with three fingers):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"To switch between services, touch &amp; hold the accessibility button."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"To switch between services, swipe up with two fingers and hold."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"To switch between services, swipe up with three fingers and hold."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Magnification"</string>
<string name="user_switched" msgid="7249833311585228097">"Current user <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="1912993630661332336">"Switching to <xliff:g id="NAME">%1$s</xliff:g>…"</string>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Connected to <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Tap to view files"</string>
<string name="pin_target" msgid="8036028973110156895">"Pin"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Pin <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Unpin"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Unpin <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"App info"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Starting demo…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Update these items in "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> and <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Save"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"No, thanks"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Not now"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Never"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Update"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Continue"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"password"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Toggle Split Screen"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Lock Screen"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Screenshot"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"<xliff:g id="APP_NAME">%1$s</xliff:g> app in pop-up window."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Caption bar of <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 8d2f80541c59..33a84883c791 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"The work profile admin app is either missing or corrupted. As a result, your work profile and related data have been deleted. Contact your admin for assistance."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Your work profile is no longer available on this device"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Too many password attempts"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Admin relinquished device for personal use"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Device is managed"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Your organisation manages this device and may monitor network traffic. Tap for details."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Your device will be erased"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Allows the app to send sticky broadcasts, which remain after the broadcast ends. Excessive use may make your Android TV device slow or unstable by causing it to use too much memory."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Allows the app to send sticky broadcasts, which remain after the broadcast ends. Excessive use may make the phone slow or unstable by causing it to use too much memory."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"read your contacts"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Allows the app to read data about your contacts stored on your tablet, including the frequency with which you\'ve called, emailed or communicated in other ways with specific individuals. This permission allows apps to save your contact data, and malicious apps may share contact data without your knowledge."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Allows the app to read data about your contacts stored on your Android TV device, including the frequency with which you\'ve called, emailed or communicated in other ways with specific individuals. This permission allows apps to save your contact data, and malicious apps may share contact data without your knowledge."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Allows the app to read data about your contacts stored on your phone, including the frequency with which you\'ve called, emailed or communicated in other ways with specific individuals. This permission allows apps to save your contact data, and malicious apps may share contact data without your knowledge."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Allows the app to read data about your contacts stored on your tablet. Apps will also have access to the accounts on your tablet that have created contacts. This may include any accounts created by apps that you have installed. This permission allows any apps to save your contact data, and malicious apps may share contact data without your knowledge."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Allows the app to read data about your contacts stored on your Android TV device. Apps will also have access to the accounts on your Android TV device that have created contacts. This may include any accounts created by apps that you have installed. This permission allows any apps to save your contact data, and malicious apps may share contact data without your knowledge."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Allows the app to read data about your contacts stored on your phone. Apps will also have access to the accounts on your phone that have created contacts. This may include any accounts created by apps that you have installed. This permission allows any apps to save your contact data, and malicious apps may share contact data without your knowledge."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"modify your contacts"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Allows the app to modify the data about your contacts stored on your tablet, including the frequency with which you\'ve called, emailed or communicated in other ways with specific contacts. This permission allows apps to delete contact data."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Allows the app to modify the data about your contacts stored on your Android TV device, including the frequency with which you\'ve called, emailed or communicated in other ways with specific contacts. This permission allows apps to delete contact data."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Allows the app to modify the data about your contacts stored on your phone, including the frequency with which you\'ve called, emailed or communicated in other ways with specific contacts. This permission allows apps to delete contact data."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Allows the app to modify the data about your contacts stored on your tablet. This permission allows apps to delete contact data."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Allows the app to modify the data about your contacts stored on your Android TV device. This permission allows apps to delete contact data."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Allows the app to modify the data about your contacts stored on your phone. This permission allows apps to delete contact data."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"read call log"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"This app can read your call history."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"write call log"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"access extra location provider commands"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Allows the app to access extra location provider commands. This may allow the app to interfere with the operation of the GPS or other location sources."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"access precise location only in the foreground"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"This app can get your exact location only when it is in the foreground. These location services must be turned on and available on your phone for the app to be able to use them. This may increase battery consumption."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"access approximate location (network-based) only in the foreground"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"This app can get your location based on network sources such as phone masts and Wi-Fi networks, but only when the app is in the foreground. These location services must be turned on and available on your tablet for the app to be able to use them."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"This app can get your location based on network sources such as phone masts and Wi-Fi networks, but only when the app is in the foreground. These location services must be turned on and available on your Android TV device for the app to be able to use them."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"This app can get your location based on network sources such as phone masts and Wi-Fi networks, but only when the app is in the foreground. These location services must be turned on and available on your phone for the app to be able to use them."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"This app can get your exact location only when it is in the foreground. Location Services must be turned on and available on your device for the app to be able to use them. This may increase battery consumption."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"access approximate location only in the foreground"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"This app can get your approximate location only when it is in the foreground. Location Services must be turned on and available on your device for the app to be able to use them."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"access location in the background"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"If this is granted additionally to the approximate or precise location access, the app can access the location while running in the background."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"This app can access location while running in the background, in addition to foreground location access."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"change your audio settings"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Allows the app to modify global audio settings such as volume and which speaker is used for output."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"record audio"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Allows the app to view the configuration of Bluetooth on the tablet and to make and accept connections with paired devices."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Allows the app to view the configuration of Bluetooth on your Android TV device and to make and accept connections with paired devices."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Allows the app to view the configuration of the Bluetooth on the phone and to make and accept connections with paired devices."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Preferred NFC payment service information"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Allows the app to get preferred NFC payment service information, such as registered aids and route destination."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"control Near-Field Communication"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Allows the app to communicate with Near Field Communication (NFC) tags, cards and readers."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"disable your screen lock"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"Accessibility Shortcut turned <xliff:g id="SERVICE_NAME">%1$s</xliff:g> on"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"Accessibility Shortcut turned <xliff:g id="SERVICE_NAME">%1$s</xliff:g> off"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Press and hold both volume keys for three seconds to use <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Choose a service to use when you tap the accessibility button:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Choose a service to use with the accessibility gesture (swipe up from the bottom of the screen with two fingers):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Choose a service to use with the accessibility gesture (swipe up from the bottom of the screen with three fingers):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"To switch between services, touch &amp; hold the accessibility button."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"To switch between services, swipe up with two fingers and hold."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"To switch between services, swipe up with three fingers and hold."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Magnification"</string>
<string name="user_switched" msgid="7249833311585228097">"Current user <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="1912993630661332336">"Switching to <xliff:g id="NAME">%1$s</xliff:g>…"</string>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Connected to <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Tap to view files"</string>
<string name="pin_target" msgid="8036028973110156895">"Pin"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Pin <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Unpin"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Unpin <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"App info"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Starting demo…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Update these items in "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> and <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Save"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"No, thanks"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Not now"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Never"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Update"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Continue"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"password"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Toggle Split Screen"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Lock Screen"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Screenshot"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"<xliff:g id="APP_NAME">%1$s</xliff:g> app in pop-up window."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Caption bar of <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index 1436692bd319..e256605e61f0 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‎‎‏‏‎‎‏‎‏‏‏‎‏‏‏‎‎‏‏‏‏‎‎‏‎‎‎‎‎‏‎‎‎‏‎‏‏‏‏‏‎‎‎‎‎‎The work profile admin app is either missing or corrupted. As a result, your work profile and related data have been deleted. Contact your admin for assistance.‎‏‎‎‏‎"</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‎‎‏‏‎‎‎‎‎‏‏‏‏‎‎‎‏‎‎‏‎‏‏‎‎‏‎‎‏‏‎‏‎‎‏‏‎‎‎‎‎‏‎‎‎‏‏‏‏‎‏‎‎‎‎‎‎‎Your work profile is no longer available on this device‎‏‎‎‏‎"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‏‏‏‏‏‏‎‎‎‎‏‎‏‎‎‎‎‏‏‎‎‎‎‎‏‎‎‏‏‏‎‎‎‎‎‏‎‎‎‎‏‏‏‏‏‏‏‎‎‏‏‏‏‏‏‎Too many password attempts‎‏‎‎‏‎"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‎‏‎‏‎‎‎‏‎‎‎‏‏‏‎‎‏‎‎‎‏‏‎‎‏‎‎‎‏‎‎‎‏‏‎‎‏‎‏‏‏‎‏‏‏‏‎‎‎‎‏‎‎‏‏‎‎‎Admin relinquished device for personal use‎‏‎‎‏‎"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‏‏‎‏‏‎‎‏‏‏‎‏‏‎‎‏‎‎‏‎‎‎‏‎‎‏‏‎‎‎‏‏‎‎‏‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‎‎Device is managed‎‏‎‎‏‎"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‎‏‏‎‏‎‏‏‏‏‎‎‎‏‏‎‏‏‎‎‎‏‏‎‏‎‎‎‎‏‎‏‎‏‎‎‎‏‏‎‏‎‎‏‎‏‎‎‎‏‎‏‎‎‎‎‎Your organization manages this device and may monitor network traffic. Tap for details.‎‏‎‎‏‎"</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‎‏‎‏‏‏‏‎‎‎‎‎‏‎‎‎‏‎‏‎‏‏‎‏‎‏‎‏‎‏‏‎‏‏‎‏‎‎‏‎‎‏‎‎‏‎‎‎‏‎‎‎‎‎‏‎Your device will be erased‎‏‎‎‏‎"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‎‎‏‏‏‎‎‏‎‏‏‏‎‎‏‏‏‏‎‏‏‎‏‎‎‏‏‎‎‎‏‏‎‏‎‎‏‏‏‎‎‏‏‎‎‎‎‏‏‎‏‎‎‏‎‏‎‎Allows the app to send sticky broadcasts, which remain after the broadcast ends. Excessive use may make your Android TV device slow or unstable by causing it to use too much memory.‎‏‎‎‏‎"</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‎‏‏‏‏‎‏‏‏‎‏‏‏‏‏‎‎‎‏‏‎‏‏‏‎‎‎‏‎‏‏‏‏‏‏‎‏‏‎‏‏‎‏‏‏‏‏‎‎‏‏‏‎‏‎‏‏‎‏‎Allows the app to send sticky broadcasts, which remain after the broadcast ends. Excessive use may make the phone slow or unstable by causing it to use too much memory.‎‏‎‎‏‎"</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‏‎‎‎‎‎‎‎‏‎‎‏‏‎‏‏‎‏‎‏‏‎‏‎‏‏‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‎‏‏‎read your contacts‎‏‎‎‏‎"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‏‎‏‎‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‎‏‏‎‏‏‏‎‏‎‎‏‎‏‎‎‎‏‏‎‏‏‏‎‎‎‎‎‎‎Allows the app to read data about your contacts stored on your tablet, including the frequency with which you\'ve called, emailed, or communicated in other ways with specific individuals. This permission allows apps to save your contact data, and malicious apps may share contact data without your knowledge.‎‏‎‎‏‎"</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‏‎‎‏‎‎‎‏‏‎‏‎‎‎‎‎‎‎‏‏‏‎‏‏‎‎‎‎‏‎‎‎‏‎‎‏‎‏‏‎‏‎‏‎‏‎‏‏‎‏‏‎‎‎‎‎‏‎Allows the app to read data about your contacts stored on your Android TV device, including the frequency with which you\'ve called, emailed, or communicated in other ways with specific individuals. This permission allows apps to save your contact data, and malicious apps may share contact data without your knowledge.‎‏‎‎‏‎"</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‏‎‎‏‎‏‎‎‎‏‏‎‏‎‎‏‏‎‏‎‎‎‏‏‎‎‏‏‏‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‎‏‎‏‏‏‏‎Allows the app to read data about your contacts stored on your phone, including the frequency with which you\'ve called, emailed, or communicated in other ways with specific individuals. This permission allows apps to save your contact data, and malicious apps may share contact data without your knowledge.‎‏‎‎‏‎"</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‎‎‏‏‏‏‎‎‎‏‎‎‎‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‎‏‏‎‏‏‏‎‎‏‏‎‎‎‎‎‏‎‏‎‎‏‏‏‎‏‎‎‎Allows the app to read data about your contacts stored on your tablet. Apps will also have access to the accounts on your tablet that have created contacts. This may include accounts created by apps you have installed. This permission allows apps to save your contact data, and malicious apps may share contact data without your knowledge.‎‏‎‎‏‎"</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‎‏‎‎‏‏‎‏‎‎‏‎‎‏‏‎‎‎‏‎‏‎‏‏‏‏‎‏‎‎‏‎‏‎‏‏‏‏‎‏‎‏‏‏‎‎‏‏‏‎‎‏‎‏‎Allows the app to read data about your contacts stored on your Android TV device. Apps will also have access to the accounts on your Android TV device that have created contacts. This may include accounts created by apps you have installed. This permission allows apps to save your contact data, and malicious apps may share contact data without your knowledge.‎‏‎‎‏‎"</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‎‎‎‏‎‏‎‏‎‏‏‏‎‎‏‎‎‏‎‏‎‏‏‎‏‎‎‏‏‎‏‏‎‏‏‏‏‎‎‎‏‎‏‎‏‎‎‏‏‏‏‎‏‏‏‎‎‎Allows the app to read data about your contacts stored on your phone. Apps will also have access to the accounts on your phone that have created contacts. This may include accounts created by apps you have installed. This permission allows apps to save your contact data, and malicious apps may share contact data without your knowledge.‎‏‎‎‏‎"</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‎‏‎‎‎‎‎‏‎‏‏‏‎‏‏‎‏‎‎‎‎‏‏‎‏‎‎‎‏‎‎‏‎‏‏‏‎‏‎‎‎‏‎‎‎‏‏‎‏‏‏‏‎‎modify your contacts‎‏‎‎‏‎"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‏‏‏‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‏‎‎‎‎‎‎‏‏‏‎‎‎‏‏‎‏‏‎‎‎‏‏‎‎‎‎‏‏‏‏‎‎Allows the app to modify the data about your contacts stored on your tablet, including the frequency with which you\'ve called, emailed, or communicated in other ways with specific contacts. This permission allows apps to delete contact data.‎‏‎‎‏‎"</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‏‎‏‏‏‎‎‎‎‏‎‏‎‏‎‏‎‎‎‏‎‎‎‎‎‎‎‏‎‏‎‎‎‎‎‎‎‏‎‎‏‎‎‏‏‎‏‏‎‏‏‏‏‎‎‏‎Allows the app to modify the data about your contacts stored on your Android TV device, including the frequency with which you\'ve called, emailed, or communicated in other ways with specific contacts. This permission allows apps to delete contact data.‎‏‎‎‏‎"</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‎‏‎‏‎‏‏‎‏‏‎‎‏‎‏‎‎‏‏‎‎‎‎‏‏‎‏‎‎‎‎‎‎‎‏‎‎Allows the app to modify the data about your contacts stored on your phone, including the frequency with which you\'ve called, emailed, or communicated in other ways with specific contacts. This permission allows apps to delete contact data.‎‏‎‎‏‎"</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‎‎‏‎‎‎‎‏‎‎‎‎‎‏‎‎‎‏‎‎‏‏‏‏‎‎‎‏‏‏‎‎‎‎‏‎‎‎‎‎‎‎‎‎‎‏‏‎‎‎‎‎‎‏‎‏‎Allows the app to modify the data about your contacts stored on your tablet. This permission allows apps to delete contact data.‎‏‎‎‏‎"</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‎‎‎‎‏‏‎‏‎‎‎‏‏‎‏‏‎‏‎‏‏‏‏‏‏‎‎‏‎‎‎‏‎‎‎‎‏‎‏‎‎‏‏‏‏‎‏‎‏‎‏‏‎‏‏‏‎Allows the app to modify the data about your contacts stored on your Android TV device. This permission allows apps to delete contact data.‎‏‎‎‏‎"</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‎‎‎‎‎‏‎‎‎‏‏‏‏‏‎‏‎‏‏‏‏‎‏‎‏‏‏‏‎‎‏‏‎‎‏‏‏‎‎‏‏‎‏‎‎‎‏‎‎‎‎‎‏‎Allows the app to modify the data about your contacts stored on your phone. This permission allows apps to delete contact data.‎‏‎‎‏‎"</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‏‏‎‏‎‏‏‏‏‏‏‏‎‎‎‎‎‏‎‎‏‏‏‎‏‎‎‏‏‎‎‏‏‏‎‎‏‏‏‏‏‏‎‎‏‏‏‎‎‎read call log‎‏‎‎‏‎"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‎‎‏‎‏‎‎‎‎‏‏‏‎‏‎‎‎‎‏‏‏‎‎‏‎‏‎‏‎‎‏‏‏‏‎‏‎‏‎‎‏‏‎‎‎‎‏‏‎‎‏‎This app can read your call history.‎‏‎‎‏‎"</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‏‎‏‎‎‏‏‎‏‎‏‎‏‏‎‏‏‏‏‏‎‏‎‎‎‏‏‎‏‎‏‏‎‏‎‎‎‎‏‎‏‎‎‎‏‏‎‎‎‎‎‎‎‏‏‏‏‎write call log‎‏‎‎‏‎"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‏‎‏‎‎‏‎‎‎‏‎‏‎‎‎‎‏‎‏‏‎‏‎‏‎‎‏‏‎‎‏‏‏‎‎‏‎‎‏‎‏‎‏‎‏‎‏‏‏‏‏‏‎‏‎‎‎access extra location provider commands‎‏‎‎‏‎"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‎‏‏‏‎‏‏‏‎‏‎‎‎‎‏‏‎‏‏‎‎‎‏‏‏‎‏‏‏‏‏‏‎‎‎‎‎‎‏‏‏‏‏‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎Allows the app to access extra location provider commands. This may allow the app to interfere with the operation of the GPS or other location sources.‎‏‎‎‏‎"</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‎‎‏‎‏‏‏‎‏‏‎‏‏‏‏‎‏‎‎‏‎‎‏‎‎‏‎‎‏‎‏‎‎‎‏‏‎‎‎‏‎‏‏‏‎‏‎‎‎‎‏‏‎‏‏‎‎access precise location only in the foreground‎‏‎‎‏‎"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‎‏‏‎‏‎‎‏‏‎‎‏‏‎‎‎‎‎‎‏‏‎‎‎‎‏‎‏‏‎‏‏‏‎‏‎‏‎‏‎‎‏‎‏‏‎‏‎‏‎‏‎‏‏‎‏‎This app can get your exact location only when it is in the foreground. These location services must be turned on and available on your phone for the app to be able to use them. This may increase battery consumption.‎‏‎‎‏‎"</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‎‎‎‏‎‏‏‎‎‏‎‏‎‏‎‏‏‎‏‏‎‎‎‎‎‎‏‎‎‏‏‏‎‎‏‏‎‏‏‎‎‏‏‎‎‎‎‏‏‎‎‎‎‎access approximate location (network-based) only in the foreground‎‏‎‎‏‎"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‏‎‎‏‏‎‎‎‏‎‏‎‏‏‏‎‏‎‎‎‎‏‏‎‎‎‏‎‎‏‏‎‎‎‏‎‏‎‎‎‏‎‏‏‏‏‏‏‎‏‏‎‎‏‏‎This app can get your location based on network sources such as cell towers and Wi-Fi networks, but only when when the app is in the foreground. These location services must be turned on and available on your tablet for the app to be able to use them.‎‏‎‎‏‎"</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‎‏‎‎‎‏‏‎‎‎‎‏‎‏‏‎‎‏‏‎‏‎‎‏‏‏‏‎‎‏‎‏‎‎‏‎‏‏‏‎‏‎‏‎‎‏‏‎‎‎‎‏‎‏‎This app can get your location based on network sources such as cell towers and Wi-Fi networks, but only when when the app is in the foreground. These location services must be turned on and available on your Android TV device for the app to be able to use them.‎‏‎‎‏‎"</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‎‏‎‏‏‏‏‎‏‏‏‎‏‎‎‏‎‎‏‎‏‎‎‎‎‎‎‎‎‎‎‏‏‏‏‎‏‎‎‎‏‎‏‏‎‏‏‎‏‎‏‎This app can get your location based on network sources such as cell towers and Wi-Fi networks, but only when the app is in the foreground. These location services must be turned on and available on your phone for the app to be able to use them.‎‏‎‎‏‎"</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‏‏‎‏‎‏‏‏‏‏‎‎‎‏‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‎‎This app can get your exact location only when it is in the foreground. Location services must be turned on and available on your device for the app to be able to use them. This may increase battery consumption.‎‏‎‎‏‎"</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‏‎‏‎‏‎‎‏‏‏‏‏‎‎‎‎‎‏‎‎‎‏‎‏‎‎‎‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‎‎‏‎‎‏‏‎‏‏‏‏‎‏‎access approximate location only in the foreground‎‏‎‎‏‎"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‏‎‎‏‎‏‎‎‎‏‎‎‎‏‏‏‏‎‏‏‎‏‎‏‏‏‎‎‏‏‏‎‏‎‏‎‏‎‏‏‏‏‏‎‏‎‎This app can get your approximate location only when it is in the foreground. Location services must be turned on and available on your device for the app to be able to use them.‎‏‎‎‏‎"</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‏‏‏‏‎‎‎‏‎‏‏‎‎‏‏‏‎‎‎‏‎‏‏‎‏‏‎‎‏‎‏‎‎‏‏‏‏‏‏‎‎‎‏‎‏‎‏‏‎‎‏‏‏‏‎‏‎‎access location in the background‎‏‎‎‏‎"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‏‎‏‎‎‏‎‏‎‏‏‏‏‎‎‎‎‏‏‎‎‏‏‎‏‏‏‏‏‏‏‎‎‎‏‎‏‎‏‏‏‎‏‎‎‎‏‏‏‏‏‎‎‎‎‎If this is granted additionally to the approximate or precise location access the app can access the location while running in the background.‎‏‎‎‏‎"</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‎‏‎‏‎‎‏‏‏‏‎‏‏‏‏‏‎‏‏‎‎‏‎‎‎‏‎‎‏‎‏‎‏‏‎‏‎‎‏‏‎‏‎‎‎‎‏‏‎‎‎‏‏‎‏‎‏‎This app can access location while running in the background, in addition to foreground location access.‎‏‎‎‏‎"</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‎‏‏‏‎‏‎‏‏‏‎‎‏‎‎‏‏‎‏‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‏‏‎‏‏‏‎‎‏‏‎‏‏‎‎‎‏‏‏‎change your audio settings‎‏‎‎‏‎"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‎‏‏‏‏‎‎‏‏‏‎‏‏‎‏‏‏‏‎‏‏‏‏‏‎‏‏‎‎‏‏‏‎‏‏‏‏‏‎‏‏‎‏‎‏‏‎‏‏‏‎‎‏‎Allows the app to modify global audio settings such as volume and which speaker is used for output.‎‏‎‎‏‎"</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‏‏‎‎‎‏‎‏‎‏‎‎‏‏‎‏‏‎‎‏‏‏‏‏‏‎‏‎‎‎‏‏‎‏‎‏‎‏‎‎‏‎‏‎‎‏‏‏‏‎‎‎‏‎‏‏‎record audio‎‏‎‎‏‎"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‎‏‎‏‏‏‏‏‎‎‏‏‏‎‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‎‎‏‏‏‏‏‎‎‏‏‎‎‏‎‎‎‏‏‏‎‎‎‏‎‏‏‎Allows the app to view the configuration of Bluetooth on the tablet, and to make and accept connections with paired devices.‎‏‎‎‏‎"</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‎‏‏‎‏‏‏‏‎‏‏‏‏‎‏‏‏‎‏‎‎‎‏‎‏‎‎‎‏‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‏‏‏‏‎‏‏‎‎Allows the app to view the configuration of Bluetooth on your Android TV device, and to make and accept connections with paired devices.‎‏‎‎‏‎"</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‎‏‎‎‏‎‎‏‏‎‎‏‎‎‏‎‏‏‎‎‏‎‏‎‎‎‏‎‏‏‎‎‎‏‎‏‏‎‎‏‏‏‎‎‎‏‎‎‏‏‏‎‎‏‎‏‎‎Allows the app to view the configuration of the Bluetooth on the phone, and to make and accept connections with paired devices.‎‏‎‎‏‎"</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‎‏‏‎‎‏‎‏‎‎‎‎‏‎‎‏‎‎‎‏‎‏‎‏‎‏‎‏‏‏‎‎‎‏‏‎‏‏‎‏‎‏‏‎‎‎‎‎‎‏‏‏‏‏‎‎Preferred NFC Payment Service Information‎‏‎‎‏‎"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‏‏‏‏‎‏‏‏‎‎‏‏‏‎‏‏‏‏‏‏‎‎‏‏‎‎‎‎‏‏‏‎‎‏‎‏‎‎‏‏‎‏‎‎‏‏‏‏‏‎‏‏‏‎Allows the app to get preferred nfc payment service information like registered aids and route destination.‎‏‎‎‏‎"</string>
<string name="permlab_nfc" msgid="1904455246837674977">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‎‏‏‎‏‏‎‏‏‏‏‏‏‎‏‏‏‏‏‏‎‏‎‎‏‏‏‎‏‏‏‎‎‏‏‎‎‎‏‏‎‏‏‏‎‎‏‏‏‏‏‎‎‎‎‏‎control Near Field Communication‎‏‎‎‏‎"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‏‎‏‎‏‎‏‏‏‎‎‎‏‎‏‎‏‎‏‎‏‎‎‏‏‏‎‏‏‏‏‏‎‏‏‏‎‏‎‎‎‎‎‎‏‎‏‏‏‎‎‏‎‏‎Allows the app to communicate with Near Field Communication (NFC) tags, cards, and readers.‎‏‎‎‏‎"</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‎‎‎‎‏‎‎‎‎‏‏‎‏‏‏‏‎‎‎‎‎‎‏‎‏‎‏‎‏‏‏‎‏‎‏‎‎‏‏‏‏‎‏‏‏‏‎‏‏‏‏‏‏‎‎‏‎disable your screen lock‎‏‎‎‏‎"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‏‏‏‎‏‏‎‏‏‎‏‎‏‏‎‎‏‏‎‏‎‏‏‏‎‏‏‎‏‏‏‏‎‏‎‏‏‎‏‏‎‎‏‏‎‏‎‎‎‎‎‎‎‏‎Accessibility Shortcut turned ‎‏‎‎‏‏‎<xliff:g id="SERVICE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ on‎‏‎‎‏‎"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‏‏‏‎‏‏‏‎‏‏‎‎‎‏‏‎‏‎‏‎‎‏‏‎‎‏‏‏‎‏‎‎‏‎‎‎‏‎‎‏‎‏‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‎Accessibility Shortcut turned ‎‏‎‎‏‏‎<xliff:g id="SERVICE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ off‎‏‎‎‏‎"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‎‏‎‏‏‎‎‎‎‎‏‏‎‏‎‏‎‎‏‏‎‎‏‏‏‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‎‏‎‏‎‎‏‎‏‏‏‏‎‎‏‎‎Press and hold both volume keys for three seconds to use ‎‏‎‎‏‏‎<xliff:g id="SERVICE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‎‏‎‏‎‏‏‏‎‎‎‏‏‎‎‏‎‎‎‏‎‎‏‏‎‎‎‎‏‏‎‎‏‏‎‏‎‏‎‎‎‎‏‎‎‎‏‏‎‎‎‎‏‎‎‏‏‎Choose a service to use when you tap the accessibility button:‎‏‎‎‏‎"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‎‏‏‎‏‎‎‎‎‎‏‏‏‎‎‎‏‏‎‏‎‏‎‏‏‎‏‎‏‏‏‏‎‏‏‏‏‎‏‎‏‎‎‎‏‏‎‎‎‎‏‎‏‏‎‎‎Choose a service to use with the accessibility gesture (swipe up from the bottom of the screen with two fingers):‎‏‎‎‏‎"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‏‎‎‎‎‎‏‏‏‏‎‎‎‏‎‏‎‏‏‏‏‏‏‎‎‎‏‎‏‎‏‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‎‏‏‏‎‎‏‏‎‎Choose a service to use with the accessibility gesture (swipe up from the bottom of the screen with three fingers):‎‏‎‎‏‎"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‎‎‏‎‏‎‎‎‎‎‏‎‎‎‏‏‏‎‎‎‎‏‏‎‏‎‎‎‎‏‎‎‏‎‏‎‏‎‎‏‏‏‏‏‎‏‎‏‎‎‎‎‎‏‎To switch between services, touch &amp; hold the accessibility button.‎‏‎‎‏‎"</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‎‎‎‎‏‏‎‎‏‏‏‎‎‏‏‎‎‎‏‎‏‏‎‎‏‏‎‎‏‎‎‎‎‏‏‎‎‏‎‏‏‎‎To switch between services, swipe up with two fingers and hold.‎‏‎‎‏‎"</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‏‏‎‏‏‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‎‏‎‎‏‏‎‎‎‏‏‎‎‏‎‎‏‎‎‏‏‎‏‎‎‏‏‎‎‎‏‎To switch between services, swipe up with three fingers and hold.‎‏‎‎‏‎"</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‎‏‏‎‏‏‎‎‎‎‏‏‏‎‎‎‏‏‏‎‎‏‎‎‎‏‎‎‏‏‏‎‎‏‎‏‏‏‎‏‎‏‎‎‏‎‏‎‎‎‎‎‎‏‏‎‎‎Magnification‎‏‎‎‏‎"</string>
<string name="user_switched" msgid="7249833311585228097">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‎‏‏‏‎‎‏‎‎‏‎‏‎‎‏‏‏‏‏‏‎‎‎‏‎‏‎‎‎‏‏‏‎‏‎‏‎‎‏‏‎‏‎‏‎‏‎‏‎‎‎‎‎‏‎Current user ‎‏‎‎‏‏‎<xliff:g id="NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎.‎‏‎‎‏‎"</string>
<string name="user_switching_message" msgid="1912993630661332336">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‏‎‎‎‏‏‎‎‎‏‎‏‎‎‎‏‏‎‎‏‎‎‏‎‎‏‎‏‎‏‎‏‎‎‏‎‎‏‏‏‎‏‎‎‏‏‎‏‎‏‏‏‎‎‎‎‎Switching to ‎‏‎‎‏‏‎<xliff:g id="NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎…‎‏‎‎‏‎"</string>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‎‏‎‏‏‏‏‏‎‏‏‏‎‏‏‏‏‏‎‎‏‏‎‏‏‏‏‎‎‎‏‎‎‏‏‏‎‎‏‏‎‎‏‏‎‎‏‏‎‏‎‎‏‏‎‏‏‎Connected to ‎‏‎‎‏‏‎<xliff:g id="PRODUCT_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‏‎‏‏‎‎‎‏‏‎‏‎‏‏‏‎‏‏‏‎‎‏‎‏‏‎‎‏‎‏‏‎‏‎‏‏‏‏‎‏‏‎‏‎‏‎‎‎‎‎‎‏‏‎‎‎Tap to view files‎‏‎‎‏‎"</string>
<string name="pin_target" msgid="8036028973110156895">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‎‎‎‏‎‏‏‎‏‏‎‏‎‏‏‏‎‎‎‏‏‎‎‎‏‏‏‎‏‎‏‏‏‏‏‎‏‎‎‏‎‏‏‏‏‎‎‏‎‏‏‏‏‏‎Pin‎‏‎‎‏‎"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‎‎‏‎‏‏‎‏‏‎‏‎‎‎‏‎‎‎‎‏‎‎‏‎‏‎‏‎‏‎‏‏‎‏‏‏‎‎‏‏‎‏‎‏‎‏‎‎‎‏‎‎‏‏‏‎Pin ‎‏‎‎‏‏‎<xliff:g id="LABEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
<string name="unpin_target" msgid="3963318576590204447">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‏‎‎‎‎‎‎‎‎‏‎‎‎‏‎‎‏‎‎‏‏‏‏‏‏‎‎‏‏‎‎‎‏‎‏‎‏‏‏‎‏‏‎‏‎‏‏‏‎‎‎‎‏‏‏‏‏‎Unpin‎‏‎‎‏‎"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‏‎‎‏‎‎‎‎‏‏‎‏‏‏‎‏‎‏‎‏‏‎‎‎‎‏‎‏‏‎‎‎‎‎‎‏‎‎‎‏‎‏‎‏‏‎‏‏‎‏‏‏‎‎‏‎‎Unpin ‎‏‎‎‏‏‎<xliff:g id="LABEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
<string name="app_info" msgid="6113278084877079851">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‏‎‏‎‏‏‎‏‎‏‏‏‎‏‎‎‎‎‎‎‏‏‏‎‏‎‏‎‏‏‎‎‏‎‎‎‏‏‏‎‏‎‏‎‏‎‏‎‎‏‎‏‎‏‏‎App info‎‏‎‎‏‎"</string>
<string name="negative_duration" msgid="1938335096972945232">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‏‏‏‎‎‏‏‎‎‏‎‏‏‎‎‏‏‎‎‎‎‎‎‎‎‎‏‏‏‏‏‎‏‎‏‏‏‏‏‎‏‎‏‎‎‏‏‏‎‏‎‏‎‎‎‎‎−‎‏‎‎‏‏‎<xliff:g id="TIME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‏‎‏‎‎‏‎‎‎‎‏‎‎‎‎‏‏‎‏‎‎‎‏‎‎‎‎‏‏‏‏‎‎‎‏‏‏‎‏‎‏‏‏‏‎‎‏‎‏‎‏‎‏‎‎‎‏‎Starting demo…‎‏‎‎‏‎"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‎‎‎‎‏‏‎‎‎‎‏‏‎‏‎‎‏‎‏‏‏‏‎‏‎‎‎‎‏‎‎‎‏‎‎‏‎‎‎‎‏‏‎Update these items in ‎‏‎‎‏‏‎"<b>"‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="LABEL">%4$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎"</b>"‎‏‎‎‏‏‏‎: ‎‏‎‎‏‏‎<xliff:g id="TYPE_0">%1$s</xliff:g>‎‏‎‎‏‏‏‎, ‎‏‎‎‏‏‎<xliff:g id="TYPE_1">%2$s</xliff:g>‎‏‎‎‏‏‏‎, and ‎‏‎‎‏‏‎<xliff:g id="TYPE_2">%3$s</xliff:g>‎‏‎‎‏‏‏‎ ?‎‏‎‎‏‎"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‎‎‎‏‎‎‏‎‏‏‎‎‎‏‏‎‏‏‎‎‏‎‏‏‏‏‏‎‎‏‎‏‏‎‎‎‎‏‎‏‏‎‎‏‏‏‏‎‏‏‎‎‏‎‎Save‎‏‎‎‏‎"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‎‎‎‏‎‎‎‏‏‎‎‎‏‏‎‏‎‎‏‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‎‏‎‎‏‏‎‏‏‏‎‎‎‎No thanks‎‏‎‎‏‎"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‏‏‎‎‏‏‎‏‏‎‎‏‏‎‏‎‎‏‎‏‎‎‏‎‎‏‏‏‏‏‎‎‏‎‎‏‎‏‎‏‏‏‏‎‏‏‏‏‏‏‏‎‎‎‎‏‏‎Not now‎‏‎‎‏‎"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‎‏‎‏‏‎‎‎‎‎‎‏‏‎‏‎‎‎‏‎‏‎‏‎‎‎‏‏‎‎‏‎‏‏‎‏‎‏‏‎‏‏‎‏‎‎‎‎‎‎‏‏‏‏‎‎Never‎‏‎‎‏‎"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‎‏‎‏‎‎‎‏‏‎‏‎‏‏‏‎‏‎‎‏‎‎‎‏‏‏‎‎‏‎‎‏‎‎‎‏‏‎‎‏‏‎‏‎Update‎‏‎‎‏‎"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‎‏‎‏‏‏‏‎‏‎‏‏‎‏‎‏‏‏‏‎‎‏‎‎‎‎‏‏‎‎‎‎‏‏‎‏‏‎‏‏‏‎‏‏‎‏‎‎‏‏‎‎‎‏‎Continue‎‏‎‎‏‎"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‎‎‎‏‏‏‎‎‏‎‏‎‏‏‏‎‎‏‎‎‎‎‏‏‎‎‎‎‏‏‏‎‎‎‏‏‎‏‎‏‎‏‏‎‏‎‏‎‎‏‎‏‎‎‎‎password‎‏‎‎‏‎"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‏‏‏‎‏‎‎‏‏‏‎‏‎‎‏‎‎‎‎‎‏‏‎‎‎‎‎‎‏‏‎‎‎‎‎‏‏‎‎‎‏‎‎‏‏‏‎‏‏‏‎‎‏‎‎‎Toggle Split Screen‎‏‎‎‏‎"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‎‎‎‎‏‏‎‏‏‏‏‎‎‎‎‏‎‎‏‏‎‎‎‎‎‏‎‏‏‏‎‎‏‏‏‏‎‏‎‏‏‎‏‎‎‎‏‏‎‏‎‏‏‏‏‏‎‎Lock Screen‎‏‎‎‏‎"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‏‏‎‏‏‎‏‎‎‎‏‎‎‎‏‏‏‏‏‎‎‎‏‎‎‏‏‏‏‏‏‎‏‏‎‏‏‏‏‏‏‏‎‎‏‏‎‏‎‏‎‏‎‏‏‎‎‎Screenshot‎‏‎‎‏‎"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‎‎‎‎‏‏‎‎‏‏‎‏‎‎‏‎‎‏‏‎‏‏‏‎‏‎‏‏‏‏‎‎‏‏‏‏‎‎‏‎‏‎‎‎‏‏‏‏‎‏‏‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ app in Pop-up window.‎‏‎‎‏‎"</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‎‎‎‎‏‎‏‏‏‎‏‏‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‎‏‎‏‏‏‎‏‎‎‏‎‏‎‎Caption bar of ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎.‎‏‎‎‏‎"</string>
</resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index b04882ac3902..ad861f255e4d 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"La app de administración de perfil de trabajo no se encuentra o está dañada. Por lo tanto, se borraron tu perfil de trabajo y los datos relacionados. Para obtener asistencia, comunícate con el administrador."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Tu perfil de trabajo ya no está disponible en este dispositivo"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Demasiados intentos para ingresar la contraseña"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"El administrador no permite hacer un uso personal del dispositivo"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Dispositivo administrado"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Tu organización administra este dispositivo y es posible que controle el tráfico de red. Presiona para obtener más información."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Se borrarán los datos del dispositivo"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Permite que la app envíe transmisiones persistentes que permanecen después de que finaliza la emisión. Un uso excesivo podría ralentizar el dispositivo Android TV o forzarlo a utilizar demasiada memoria, lo que generaría un funcionamiento inestable."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Permite que la aplicación envíe transmisiones persistentes que permanecen después de que finaliza la transmisión. Un uso excesivo podría ralentizar el dispositivo o hacer que funcione de manera inestable al forzarlo a utilizar mucha memoria."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"leer tus contactos"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Permite que la aplicación consulte información sobre los contactos almacenados en la tablet, incluida la frecuencia con la que los has llamado, les has enviado correos o te has puesto en contacto con ellos de otro modo. Las aplicaciones pueden utilizar este permiso para guardar los datos de los contactos, y las aplicaciones malintencionadas podrían compartirlos sin tu consentimiento."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Permite que la app lea datos sobre los contactos almacenados en el dispositivo Android TV, incluida la frecuencia con la que llamaste a una persona específica, le enviaste correos electrónicos o te comunicaste con ella de cualquier otra manera. Las apps pueden utilizar este permiso para guardar los datos de los contactos, y aquellas apps maliciosas podrían compartir esa información sin tu conocimiento."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Permite que la aplicación consulte información sobre contactos almacenados en el dispositivo, incluida la frecuencia con la que los has llamado, les has enviado correos o te has puesto en contacto con ellos de otro modo. Las aplicaciones pueden utilizar este permiso para guardar los datos de los contactos, y las aplicaciones malintencionadas podrían compartirlos sin tu consentimiento."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Permite que la app lea datos sobre los contactos almacenados en la tablet. Las apps también tendrán acceso a las cuentas de tu tablet en las que se hayan creado contactos. Pueden incluirse cuentas creadas por apps que hayas instalado. Las apps pueden utilizar este permiso para guardar los datos de los contactos, y las apps maliciosas podrían compartir esa información sin tu conocimiento."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Permite que la app lea datos sobre los contactos almacenados en el dispositivo Android TV. Las apps también tendrán acceso a las cuentas de tu dispositivo Android TV en las que se hayan creado contactos. Pueden incluirse cuentas creadas por apps que hayas instalado. Las apps pueden utilizar este permiso para guardar los datos de los contactos, y las apps maliciosas podrían compartir esa información sin tu conocimiento."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Permite que la app lea datos sobre los contactos almacenados en el teléfono. Las apps también tendrán acceso a las cuentas de tu teléfono en las que se hayan creado contactos. Pueden incluirse cuentas creadas por apps que hayas instalado. Las apps pueden utilizar este permiso para guardar los datos de los contactos, y las apps maliciosas podrían compartir esa información sin tu conocimiento."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"modificar tus contactos"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Permite que la aplicación modifique los datos de los contactos almacenados en la tablet, incluida la frecuencia con la que los has llamado, les has enviado correos o te has puesto en contacto con ellos de otro modo. Las aplicaciones pueden utilizar este permiso para eliminar datos de contactos."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Permite que la app modifique datos sobre los contactos almacenados en el dispositivo Android TV, incluida la frecuencia con la que llamaste a una persona específica, le enviaste correos electrónicos o te comunicaste con ella de cualquier otra manera. Las apps pueden utilizar este permiso para borrar los datos de los contactos."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Permite que la aplicación modifique los datos de los contactos almacenados en el dispositivo, incluida la frecuencia con la que los has llamado, les has enviado correos o te has puesto en contacto con ellos de otro modo. Las aplicaciones pueden utilizar este permiso para eliminar datos de contactos."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Permite que la app modifique datos sobre los contactos almacenados en la tablet. Las apps pueden utilizar este permiso para borrar los datos de los contactos."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Permite que la app modifique datos sobre los contactos almacenados en el dispositivo Android TV. Las apps pueden utilizar este permiso para borrar los datos de los contactos."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Permite que la app modifique datos sobre los contactos almacenados en el teléfono. Las apps pueden utilizar este permiso para borrar los datos de los contactos."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"leer el registro de llamadas"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Esta app puede leer tu historial de llamadas."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"escribir en el registro de llamadas"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"acceder a comandos adicionales del proveedor del lugar"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Permite que la aplicación acceda a comandos adicionales del proveedor de ubicación. Esto puede permitirle a la aplicación interferir con el funcionamiento del GPS o de otras fuentes de ubicación."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"acceder a la ubicación exacta solo en primer plano"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Esta app puede obtener tu ubicación exacta solo cuando está en primer plano. Los servicios de ubicación deben estar activados y disponibles en el teléfono para que la app pueda usarlos. Es posible que aumente el consumo de batería."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"acceso a la ubicación aproximada (mediante red) solo en primer plano"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Esta app puede obtener tu ubicación desde fuentes de red, como torres de telefonía celular y redes Wi-Fi, pero solo en primer plano. Los servicios de ubicación deben estar activados y disponibles en tu tablet para que la app pueda usarlos."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Esta app puede obtener tu ubicación desde fuentes de red, como torres de telefonía celular y redes Wi-Fi, pero solo cuando está en primer plano. Los servicios de ubicación deben estar activados y disponibles en el dispositivo Android TV para que pueda usarlos la app."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Esta app puede obtener tu ubicación desde fuentes de red, como torres de telefonía celular y redes Wi-Fi, pero solo en primer plano. Los servicios de ubicación deben estar activados y disponibles en tu teléfono para que la app pueda usarlos."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Esta app puede obtener tu ubicación exacta solo cuando está en primer plano. Los servicios de ubicación deben estar activados y disponibles en el dispositivo para que la app pueda usarlos. Es posible que aumente el consumo de batería."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"acceder a la ubicación aproximada solo en primer plano"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Esta app puede obtener tu ubicación aproximada únicamente cuando está en primer plano. Los servicios de ubicación deben estar activados y disponibles en el dispositivo para que la app pueda usarlos."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"acceder a la ubicación en segundo plano"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Si este permiso se otorga de manera adicional para aproximar o precisar el acceso a la ubicación, la app podrá acceder a la ubicación mientras se ejecuta en segundo plano."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Esta app puede acceder a una ubicación mientras se ejecuta en segundo plano, además de proporcionar acceso a la ubicación en primer plano."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"cambiar tu configuración de audio"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Permite que la aplicación modifique la configuración de audio global, por ejemplo, el volumen y el altavoz de salida."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"grabar audio"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Permite que la aplicación vea la configuración de Bluetooth de la tablet y que cree y acepte conexiones con los dispositivos sincronizados."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Permite que la app vea la configuración de Bluetooth del dispositivo Android TV, así como que cree y acepte conexiones con los dispositivos sincronizados."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Permite que la aplicación vea la configuración de Bluetooth del dispositivo y que cree y acepte conexiones con los dispositivos sincronizados."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Información sobre servicio de pago NFC preferido"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Permite que la app reciba información del servicio de pago NFC preferido, como el servicio de asistencia registrado y el destino de la ruta."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"controlar la Transmisión de datos en proximidad"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Permite que la aplicación se comunique con lectores, tarjetas y etiquetas de Comunicación de campo cercano (NFC)."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"desactivar el bloqueo de pantalla"</string>
@@ -1298,7 +1297,7 @@
<string name="usb_supplying_notification_title" msgid="5378546632408101811">"Cargando el dispositivo conectado mediante USB"</string>
<string name="usb_mtp_notification_title" msgid="1065989144124499810">"Se activó la transferencia de archivos mediante USB"</string>
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"Se activó el modo PTP mediante USB"</string>
- <string name="usb_tether_notification_title" msgid="8828527870612663771">"Se activó la conexión mediante dispositivo portátil por USB"</string>
+ <string name="usb_tether_notification_title" msgid="8828527870612663771">"Se activó la conexión mediante dispositivo móvil por USB"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"Se activó el modo MIDI mediante USB"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"Accesorio USB conectado"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Presiona para ver más opciones."</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"El acceso directo de accesibilidad activó <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"El acceso directo de accesibilidad desactivó <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Mantén presionadas ambas teclas de volumen durante tres segundos para usar <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Elige un servicio para usar cuando presiones el botón de accesibilidad:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Elige un servicio para usar cuando realices el gesto de accesibilidad (deslizar dos dedos hacia arriba desde la parte inferior de la pantalla):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Elige el servicio que se usará cuando realices el gesto de accesibilidad (deslizar tres dedos hacia arriba desde la parte inferior de la pantalla):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Para cambiar de servicio, mantén presionado el botón de accesibilidad."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Para cambiar de servicio, desliza dos dedos hacia arriba y mantén presionado."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Para cambiar de servicio, desliza tres dedos hacia arriba y mantén presionado."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Ampliación"</string>
<string name="user_switched" msgid="7249833311585228097">"Usuario actual: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="user_switching_message" msgid="1912993630661332336">"Cambiando a <xliff:g id="NAME">%1$s</xliff:g>…"</string>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Conectado a <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Presiona para ver archivos"</string>
<string name="pin_target" msgid="8036028973110156895">"Fijar"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Fijar <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"No fijar"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"No fijar <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Información de apps"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Iniciando demostración…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"¿Quieres actualizar estos elementos en "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> y <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Guardar"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"No, gracias"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Ahora no"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Nunca"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Actualizar"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Continuar"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"contraseña"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Activar o desactivar pantalla dividida"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Bloquear pantalla"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Captura de pantalla"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"App de <xliff:g id="APP_NAME">%1$s</xliff:g> en una ventana emergente."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Barra de subtítulos de <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 81f210ba03b3..9c64369bced3 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Falta la aplicación de administración del perfil de trabajo o está dañada. Por ello, se han eliminado tu perfil de trabajo y los datos relacionados. Ponte en contacto con el administrador para obtener ayuda."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Tu perfil de trabajo ya no está disponible en este dispositivo"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Has fallado demasiadas veces al introducir la contraseña"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"El administrador no permite hacer un uso personal del dispositivo"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"El dispositivo está administrado"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Tu organización administra este dispositivo y puede supervisar el tráfico de red. Toca la notificación para obtener más información."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Tu dispositivo se borrará"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Permite que la aplicación envíe emisiones que permanecen en el dispositivo una vez finalizadas. Si esta función se utiliza en exceso, podría ralentizar tu dispositivo Android TV o volverlo inestable al hacer que se ocupe demasiada memoria."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Permite que la aplicación envíe emisiones que permanecen en el dispositivo una vez que la emisión ha finalizado. Un uso excesivo podría ralentizar el teléfono o volverlo inestable al hacer que use demasiada memoria."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"consultar tus contactos"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Permite que la aplicación consulte información sobre contactos almacenados en el tablet, incluida la frecuencia con la que los has llamado, les has enviado un correo electrónico o te has puesto en contacto con ellos de otro modo. Este permiso permite guardar los datos de los contactos, y las aplicaciones malintencionadas pueden utilizarlo para compartir datos de contactos del usuario sin su consentimiento."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Permite que la aplicación consulte los datos de los contactos almacenados en tu dispositivo Android TV, incluida la frecuencia con la que los has llamado, les has enviado un correo electrónico o te has puesto en contacto de cualquier otro modo con cada uno. Las aplicaciones que tengan este permiso pueden guardar los datos de tus contactos, y las aplicaciones maliciosas puede que compartan estos datos sin tu conocimiento."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Permite que la aplicación consulte información sobre contactos almacenados en el teléfono, incluida la frecuencia con la que los has llamado, les has enviado un correo electrónico o te has puesto en contacto con ellos de otro modo. Este permiso permite guardar los datos de los contactos, y las aplicaciones malintencionadas pueden utilizarlo para compartir datos de contactos del usuario sin su consentimiento."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Permite que la aplicación lea datos de los contactos almacenados en tu tablet. Las aplicaciones también podrán acceder a las cuentas de tu tablet que hayan creado contactos, y quizá tengan acceso a las cuentas creadas por aplicaciones que hayas descargado. Las aplicaciones que tengan este permiso pueden guardar los datos de tus contactos, y las aplicaciones maliciosas puede que compartan estos datos sin que lo sepas."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Permite que la aplicación lea datos de los contactos almacenados en tu dispositivo Android TV. Las aplicaciones también podrán acceder a las cuentas de tu dispositivo Android TV que hayan creado contactos, y quizá tengan acceso a las cuentas creadas por aplicaciones que hayas descargado. Las aplicaciones que tengan este permiso pueden guardar los datos de tus contactos, y las aplicaciones maliciosas puede que compartan estos datos sin que lo sepas."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Permite que la aplicación lea datos de los contactos almacenados en tu teléfono. Las aplicaciones también podrán acceder a las cuentas de tu teléfono que hayan creado contactos, y quizá tengan acceso a las cuentas creadas por aplicaciones que hayas descargado. Las aplicaciones que tengan este permiso pueden guardar los datos de tus contactos, y las aplicaciones maliciosas puede que compartan estos datos sin que lo sepas."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"modificar tus contactos"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Permite que la aplicación modifique los datos de los contactos almacenados en el tablet, incluida la frecuencia con la que los has llamado, les has enviado un correo electrónico o te has puesto en contacto con ellos de otro modo. Las aplicaciones pueden utilizar este permiso para eliminar datos de contactos."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Permite que la aplicación cambie los datos de los contactos almacenados en tu dispositivo Android TV, incluida la frecuencia con la que los has llamado, les has enviado un correo electrónico o te has puesto en contacto de cualquier otro modo con cada uno. Las aplicaciones que tengan este permiso pueden eliminar datos de contactos."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Permite que la aplicación modifique los datos de los contactos almacenados en el teléfono, incluida la frecuencia con la que los has llamado, les has enviado un correo electrónico o te has puesto en contacto con ellos de otro modo. Las aplicaciones pueden utilizar este permiso para eliminar datos de contactos."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Permite que la aplicación cambie los datos de los contactos almacenados en tu tablet. Las aplicaciones que tengan este permiso pueden eliminar datos de contactos."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Permite que la aplicación cambie los datos de los contactos almacenados en tu dispositivo Android TV. Las aplicaciones que tengan este permiso pueden eliminar datos de contactos."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Permite que la aplicación cambie los datos de los contactos almacenados en tu teléfono. Las aplicaciones que tengan este permiso pueden eliminar datos de contactos."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"leer el registro de llamadas"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Esta aplicación puede leer tu historial de llamadas."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"escribir en el registro de llamadas"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"acceder a comandos de proveedor de ubicación adicional"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Permite que la aplicación acceda a otros comandos del proveedor de ubicación. De esta forma, la aplicación podrá interferir en el funcionamiento del GPS o de otras fuentes de ubicación."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"acceder a la ubicación exacta solo en primer plano"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Esta aplicación solo puede obtener tu ubicación exacta cuando está en primer plano. Estos servicios de ubicación deben estar activados y disponibles en tu teléfono para que la aplicación pueda utilizarlos. Es posible que aumente el consumo de batería."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"acceder a la ubicación aproximada (a partir de la red) solo en primer plano"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Esta aplicación puede obtener tu ubicación a partir de fuentes de red como las antenas de telefonía móvil y las redes Wi‑Fi, pero únicamente si la aplicación está en primer plano. Estos servicios de ubicación deben estar activados y disponibles en el tablet para que la aplicación pueda usarlos."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Esta aplicación puede obtener tu ubicación a partir de fuentes de red como las antenas de telefonía móvil y las redes Wi‑Fi, pero únicamente si la aplicación está en primer plano. Estos servicios de ubicación deben estar activados y disponibles en tu dispositivo Android TV para que la aplicación pueda usarlos."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Esta aplicación puede obtener tu ubicación a partir de fuentes de red como las antenas de telefonía móvil y las redes Wi‑Fi, pero únicamente si la aplicación está en primer plano. Estos servicios de ubicación deben estar activados y disponibles en el teléfono para que la aplicación pueda usarlos."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Esta aplicación solo puede obtener tu ubicación exacta cuando está en primer plano. Los servicios de ubicación deben estar activados y disponibles en tu dispositivo para que la aplicación pueda utilizarlos. Es posible que aumente el consumo de batería."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"acceder a la ubicación aproximada solo al estar en primer plano"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Esta aplicación puede obtener tu ubicación aproximada solo cuando está en primer plano. Para que la aplicación pueda utilizar los servicios de ubicación, deben estar activados y disponibles en tu dispositivo."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"acceder a la ubicación en segundo plano"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Si se concede este permiso además del acceso a la ubicación exacta o aproximada, la aplicación podrá acceder a la ubicación mientras se ejecuta en segundo plano."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Esta aplicación puede acceder a la ubicación tanto cuando se ejecuta en segundo plano como cuando está en primer plano."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"cambiar la configuración de audio"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Permite que la aplicación modifique la configuración de audio global (por ejemplo, el volumen y el altavoz de salida)."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"grabar sonido"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Permite que la aplicación acceda a la configuración de Bluetooth del tablet y que establezca y acepte conexiones con los dispositivos sincronizados."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Permite que la aplicación vea la configuración de Bluetooth de tu dispositivo Android TV y que cree y acepte conexiones con los dispositivos vinculados."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Permite que la aplicación acceda a la configuración de Bluetooth del teléfono y que establezca y acepte conexiones con los dispositivos sincronizados."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Información sobre el servicio de pago por NFC preferido"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Permite que la aplicación obtenga información sobre el servicio de pago por NFC preferido, como identificadores de aplicación registrados y destinos de rutas."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"controlar Comunicación de campo cercano (NFC)"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Permite que la aplicación se comunique con lectores, tarjetas y etiquetas de Comunicación de campo cercano (NFC)."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"inhabilitar el bloqueo de pantalla"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"El acceso directo a accesibilidad ha activado <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"El acceso directo a accesibilidad ha desactivado <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Para utilizar <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, mantén pulsadas ambas teclas de volumen durante 3 segundos"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Selecciona el servicio que se utilizará cuando toques el botón Accesibilidad:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Elige el servicio que se utilizará con el gesto de accesibilidad (deslizar dos dedos hacia arriba desde la parte inferior de la pantalla):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Elige el servicio que se utilizará con el gesto de accesibilidad (deslizar tres dedos hacia arriba desde la parte inferior de la pantalla):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Para cambiar de un servicio a otro, mantén pulsado el botón de accesibilidad."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Para cambiar de un servicio a otro, desliza dos dedos hacia arriba y mantén pulsada la pantalla."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Para cambiar de un servicio a otro, desliza tres dedos hacia arriba y mantén pulsada la pantalla."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Ampliar"</string>
<string name="user_switched" msgid="7249833311585228097">"Usuario actual: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="user_switching_message" msgid="1912993630661332336">"Cambiando a <xliff:g id="NAME">%1$s</xliff:g>…"</string>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Conectado a <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Toca para ver archivos"</string>
<string name="pin_target" msgid="8036028973110156895">"Fijar"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Fijar <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"No fijar"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"No fijar <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Acerca de la aplicación"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Iniciando demostración…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"¿Actualizar estos elementos en "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" (<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> y <xliff:g id="TYPE_2">%3$s</xliff:g>)?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Guardar"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"No, gracias"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Ahora no"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Nunca"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Actualizar"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Continuar"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"contraseña"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Activar o desactivar la pantalla dividida"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Pantalla de bloqueo"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Captura de pantalla"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"La aplicación <xliff:g id="APP_NAME">%1$s</xliff:g> se muestra en una ventana emergente."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Barra de subtítulos de <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 61b18bbb9b39..c9e74b3f9bae 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Tööprofiili administraatori rakendus puudub või on rikutud. Seetõttu on teie tööprofiil ja seotud andmed kustutatud. Abi saamiseks võtke ühendust administraatoriga."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Teie tööprofiil pole selles seadmes enam saadaval"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Liiga palju paroolikatseid"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Administraator keelas seadme isikliku kasutamise"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Seade on hallatud"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Teie organisatsioon haldab seda seadet ja võib jälgida võrguliiklust. Puudutage üksikasjade vaatamiseks."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Seade kustutatakse"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Võimaldab rakendusel saata püsivaid teadaandeid, mis jäävad pärast ülekande lõppemist alles. Ülemäärane kasutamine võib muuta teie Android TV seadme aeglaseks või ebastabiilseks, põhjustades selle liiga suure mälukasutuse."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Võimaldab rakendusel saata püsivaid edastusi, mis jäävad pärast saate lõppemist alles. Ülemäärane kasutamine võib muuta telefoni aeglaseks või ebastabiilseks, põhjustades selle liiga suure mälukasutuse."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"Kontaktide lugemine"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Võimaldab rakendusel lugeda andmeid teie tahvelarvutisse salvestatud kontaktide kohta, näiteks seda, kui tihti te kellelegi helistate, meilite või nendega muul viisil suhtlete. See luba võimaldab rakendustel salvestada teie kontaktandmeid ja pahatahtlikud rakendused võivad teie teadmata kontaktandmeid jagada."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Lubab rakendusel lugeda kõikide Android TV seadmesse salvestatud kontaktide andmeid, sh seda, kui sageli olete nendele isikutele helistanud, meili saatnud või nendega muul viisil suhelnud. See luba võimaldab rakendustel salvestada teie kontaktandmeid ja pahatahtlikud rakendused võivad teie teadmata kontaktandmeid jagada."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Võimaldab rakendusel lugeda andmeid teie telefoni salvestatud kontaktide kohta, näiteks seda, kui tihti te kellelegi helistate, meilite või nendega muul viisil suhtlete. See luba võimaldab rakendustel salvestada teie kontaktandmeid ja pahatahtlikud rakendused võivad teie teadmata kontaktandmeid jagada."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Lubab rakendusel lugeda tahvelarvutisse salvestatud kontaktide andmeid. Rakendustel on ka juurdepääs teie tahvelarvutis olevatele kontodele, millel on loodud kontakte. See võib hõlmata kontosid, mille lõid teie installitud rakendused. See luba võimaldab rakendustel salvestada teie kontaktandmeid ja pahatahtlikud rakendused võivad teie teadmata kontaktandmeid jagada."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Lubab rakendusel lugeda Android TV seadmesse salvestatud kontaktide andmeid. Rakendustel on ka juurdepääs teie Android TV seadmes olevatele kontodele, millel on loodud kontakte. See võib hõlmata kontosid, mille lõid teie installitud rakendused. See luba võimaldab rakendustel salvestada teie kontaktandmeid ja pahatahtlikud rakendused võivad teie teadmata kontaktandmeid jagada."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Lubab rakendusel lugeda telefoni salvestatud kontaktide andmeid. Rakendustel on ka juurdepääs teie telefonis olevatele kontodele, millel on loodud kontakte. See võib hõlmata kontosid, mille lõid teie installitud rakendused. See luba võimaldab rakendustel salvestada teie kontaktandmeid ja pahatahtlikud rakendused võivad teie teadmata kontaktandmeid jagada."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"muutke oma kontakte"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Võimaldab rakendusel muuta tahvelarvutisse salvestatud kontaktide andmeid, sealhulgas seda, kui tihti olete konkreetsetele kontaktidele helistanud, meilinud või nendega muul viisil suhelnud. See luba võimaldab rakendustel kustutada kontaktandmeid."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Lubab rakendusel muuta kõikide Android TV seadmesse salvestatud kontaktide andmeid, sh seda, kui sageli olete nendele kontaktidele helistanud, meili saatnud või nendega muul viisil suhelnud. See luba võimaldab rakendustel kontaktandmeid kustutada."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Võimaldab rakendusel muuta telefoni salvestatud kontaktide andmeid, sealhulgas seda, kui tihti olete konkreetsetele kontaktidele helistanud, meilinud või nendega muul viisil suhelnud. See luba võimaldab rakendustel kustutada kontaktandmeid."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Lubab rakendusel muuta tahvelarvutisse salvestatud kontaktide andmeid. See luba võimaldab rakendustel kontaktandmeid kustutada."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Lubab rakendusel muuta Android TV seadmesse salvestatud kontaktide andmeid. See luba võimaldab rakendustel kontaktandmeid kustutada."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Lubab rakendusel muuta telefoni salvestatud kontaktide andmeid. See luba võimaldab rakendustel kontaktandmeid kustutada."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"kõnelogi lugemine"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"See rakendus saab teie kõneajalugu lugeda."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"kõnelogi kirjutamine"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"juurdepääs asukohapakkuja lisakäskudele"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Võimaldab rakendusel juurde pääseda asukohapakkuja erikäskudele. See võib lubada rakendusel mõjutada GPS-i või muude asukohaallikate tööd."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"juurdepääs täpsele asukohale ainult esiplaanil"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"See rakendus hangib teie täpse asukoha ainult siis, kui see töötab esiplaanil. Need asukohateenused peavad olema sisse lülitatud ja teie telefonis saadaval, et rakendus saaks neid kasutada. See võib suurendada akutoite tarbimist."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"pääseda juurde ligikaudsele asukohale (võrgupõhiselt) ainult esiplaanil"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"See rakendus näeb võrguallikate (nt mobiilimastid ja WiFi-võrgud) abil teie asukohta, kuid ainult siis, kui rakendus töötab esiplaanil. Need asukohateenused peavad olema sisse lülitatud ja teie tahvelarvutis saadaval, et rakendus saaks neid kasutada."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"See rakendus näeb võrguallikate (nt mobiilimastid ja WiFi-võrgud) abil teie asukohta, kuid ainult siis, kui rakendus töötab esiplaanil. Need asukohateenused peavad olema sisse lülitatud ja teie Android TV seadmes saadaval, et rakendus saaks neid kasutada."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"See rakendus näeb võrguallikate (nt mobiilimastid ja WiFi-võrgud) abil teie asukohta, kuid ainult siis, kui rakendus töötab esiplaanil. Need asukohateenused peavad olema sisse lülitatud ja teie telefonis saadaval, et rakendus saaks neid kasutada."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"See rakendus hangib teie täpse asukoha ainult siis, kui see töötab esiplaanil. Asukohateenused peavad olema sisse lülitatud ja teie seadmes saadaval, et rakendus saaks neid kasutada. See võib suurendada akutoite tarbimist."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"juurdepääs ligikaudsele asukohale ainult esiplaanil"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"See rakendus hangib teie ligikaudse asukoha ainult siis, kui see töötab esiplaanil. Asukohateenused peavad olema sisse lülitatud ja teie seadmes saadaval, et rakendus saaks neid kasutada."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"juurdepääs asukohale taustal"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Kui see on antud ka umbkaudsele või täpsele asukohale juurdepääsu puhul, saab rakendus taustal käitamisel juurdepääsu asukohale."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"See rakendus pääseb asukohale lisaks esiplaanil töötamise ajal juurde ka taustal töötamise ajal."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"muuda heliseadeid"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Võimaldab rakendusel muuta üldiseid heliseadeid, näiteks helitugevust ja seda, millist kõlarit kasutatakse väljundiks."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"salvesta heli"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Võimaldab rakendusel vaadata tahvelarvuti Bluetooth-konfiguratsiooni ning luua ja heaks kiita ühendusi seotud seadmetega."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Võimaldab rakendusel vaadata Android TV seadme Bluetoothi seadistust ning luua ja vastu võtta ühendusi seotud seadmetega."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Võimaldab rakendusel vaadata telefoni Bluetooth-konfiguratsiooni ning luua ja heaks kiita ühendusi seotud seadmetega."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Eelistatud NFC-makseteenuse teave"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Võimaldab rakendusel hankida eelistatud NFC-makseteenuse teavet (nt registreeritud abi ja marsruudi sihtkoht)."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"lähiväljaside juhtimine"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Võimaldab rakendusel suhelda lähiväljaside (NFC) märgendite, kaartide ja lugeritega."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"keelake ekraanilukk"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"Juurdepääsetavuse otsetee lülitas teenuse <xliff:g id="SERVICE_NAME">%1$s</xliff:g> sisse"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"Juurdepääsetavuse otsetee lülitas teenuse <xliff:g id="SERVICE_NAME">%1$s</xliff:g> välja"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Teenuse <xliff:g id="SERVICE_NAME">%1$s</xliff:g> kasutamiseks hoidke kolm sekundit all mõlemat helitugevuse klahvi"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Valige, millist teenust kasutada, kui puudutate juurdepääsetavuse nuppu:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Valige, millist teenust kasutada koos juurdepääsetavuse liigutusega (kahe sõrmega ekraanikuval alt üles pühkimine):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Valige, millist teenust kasutada koos juurdepääsetavuse liigutusega (kolme sõrmega ekraanikuval alt üles pühkimine):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Teenuste vahel vahetamiseks vajutage pikalt juurdepääsetavuse nuppu."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Teenuste vahel vahetamiseks pühkige kahe sõrmega üles ja hoidke."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Teenuste vahel vahetamiseks pühkige kolme sõrmega üles ja hoidke."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Suurendus"</string>
<string name="user_switched" msgid="7249833311585228097">"Praegune kasutaja <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="1912993630661332336">"Üleminek kasutajale <xliff:g id="NAME">%1$s</xliff:g> ..."</string>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Ühendatud seadmega <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Failide vaatamiseks puudutage"</string>
<string name="pin_target" msgid="8036028973110156895">"Kinnita"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"PIN-kood <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Vabasta"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Vabasta <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Rakenduse teave"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Demo käivitamine …"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Kas värskendada teenuses "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" neid üksusi: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ja <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Salvesta"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Tänan, ei"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Hiljem"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Mitte kunagi"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Värskenda"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Jätka"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"parool"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Vaheta jagatud ekraanikuva"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Lukustuskuva"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Ekraanipilt"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"Rakendus <xliff:g id="APP_NAME">%1$s</xliff:g> on hüpikaknas."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Rakenduse <xliff:g id="APP_NAME">%1$s</xliff:g> pealkirjariba."</string>
</resources>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index fda8565cbfa3..cae6b9986582 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Laneko profila administratzeko aplikazioa falta da edo hondatuta dago. Ondorioz, ezabatu egin dira laneko profila bera eta harekin erlazionatutako datuak. Laguntza lortzeko, jarri administratzailearekin harremanetan."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Laneko profila ez dago erabilgarri gailu honetan"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Gehiegitan saiatu zara pasahitza idazten"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Erabilera pertsonalerako utzi du gailua administratzaileak"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Jabeak kudeatzen du gailua"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Erakundeak kudeatzen du gailua eta baliteke sareko trafikoa gainbegiratzea. Sakatu hau xehetasunak ikusteko."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Gailuko datuak ezabatu egingo dira"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Igorpen iraunkorrak egiteko baimena ematen die aplikazioei. Igorpena amaitu ondoren ere igortzen jarraitzen dute igorpen iraunkorrek. Gehiegi erabiliz gero, Android TV gailua motel edo ezegonkor ibiliko da, memoria gehiago erabiliko delako."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Igorpen iraunkorrak emateko baimena ematen die; horiek igorpena amaitu ondoren mantentzen dira. Gehiegi erabiliz gero, telefonoa motel edo ezegonkor ibiliko da, memoria gehiago erabiliko delako."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"irakurri kontaktuak"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Tabletan gordetako kontaktuei buruzko datuak irakurtzeko baimena ematen die aplikazioei, besteak beste, pertsona zehatzei zer maiztasunekin deitu diezun, mezu elektronikoak bidali dizkiezun edo haiekin harremanetan beste modutara nola jarri zaren. Baimen horrekin, aplikazioek kontaktuen datuak gorde ditzakete, eta aplikazio gaiztoek haiek parteka ditzakete zuk jakin gabe."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Android TV gailuan gordetako kontaktuei buruzko datuak irakurtzeko baimena ematen die aplikazioei; besteak beste, pertsona zehatzei zer maiztasunekin deitu diezun edo bidali dizkiezun mezu elektronikoak, edo haiekin zer beste modutara jarri zaren harremanetan. Baimen horrekin, aplikazioek kontaktuen datuak gorde ditzakete, eta baliteke aplikazio gaiztoek zuk jakin gabe partekatzea datu horiek."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Telefonoan gordetako kontaktuei buruzko datuak irakurtzeko baimena ematen die aplikazioei, besteak beste, pertsona zehatzei zer maiztasunekin deitu diezun, mezu elektronikoak bidali dizkiezun edo haiekin harremanetan beste modutara nola jarri zaren. Baimen horrekin, aplikazioek kontaktuen datuak gorde ditzakete, eta aplikazio gaiztoek haiek parteka ditzakete zuk jakin gabe."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Tabletan gordetako kontaktuei buruzko datuak irakurtzeko baimena ematen dio aplikazioari. Kontaktuak sortu dituzten tabletako kontuak ere atzitu ahalko dituzte aplikazioek. Horrek barnean hartuko ditu instalatutako aplikazioek sortutako kontuak, agian. Baimen horrekin, kontaktuen datuak gorde ditzakete aplikazioek, eta baliteke aplikazio gaiztoek zuk jakin gabe partekatzea datu horiek."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Android TV gailuan gordetako kontaktuei buruzko datuak irakurtzeko baimena ematen dio aplikazioari. Kontaktuak sortu dituzten Android TV gailuko kontuak ere atzitu ahalko dituzte aplikazioek. Horrek barnean hartuko ditu instalatutako aplikazioek sortutako kontuak, agian. Baimen horrekin, kontaktuen datuak gorde ditzakete aplikazioek, eta baliteke aplikazio gaiztoek zuk jakin gabe partekatzea datu horiek."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Telefonoan gordetako kontaktuei buruzko datuak irakurtzeko baimena ematen dio aplikazioari. Kontaktuak sortu dituzten telefonoko kontuak ere atzitu ahalko dituzte aplikazioek. Horrek barnean hartuko ditu instalatutako aplikazioek sortutako kontuak, agian. Baimen horrekin, kontaktuen datuak gorde ditzakete aplikazioek, eta baliteke aplikazio gaiztoek zuk jakin gabe partekatzea datu horiek."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"aldatu kontaktuak"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Tabletan gordetako kontaktuei buruzko datuak aldatzeko baimena ematen die aplikazioei, besteak beste, kontatu zehatzei zer maiztasunekin deitu diezun, mezu elektronikoak bidali dizkiezun edo haiekin harremanetan beste modutara nola jarri zaren. Baimen horrekin, aplikazioek kontaktuen datuak ezaba ditzakete."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Android TV gailuan gordetako kontaktuei buruzko datuak aldatzeko baimena ematen die aplikazioei; besteak beste, kontaktu zehatzei zer maiztasunekin deitu diezun edo bidali dizkiezun mezu elektronikoak, edo haiekin harremanetan zer beste modutara jarri zaren. Baimen horrekin, kontaktuen datuak ezaba ditzakete aplikazioek."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Telefonoan gordetako kontaktuei buruzko datuak aldatzeko baimena ematen die aplikazioei, besteak beste, kontatu zehatzei zer maiztasunekin deitu diezun, mezu elektronikoak bidali dizkiezun edo haiekin harremanetan beste modutara nola jarri zaren. Baimen horrekin, aplikazioek kontaktuen datuak ezaba ditzakete."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Tabletan gordetako kontaktuei buruzko datuak aldatzeko baimena ematen dio aplikazioari. Baimen horrekin, aplikazioek kontaktuen datuak ezaba ditzakete."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Android TV gailuan gordetako kontaktuei buruzko datuak aldatzeko baimena ematen dio aplikazioari. Baimen horrekin, aplikazioek kontaktuen datuak ezaba ditzakete."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Telefonoan gordetako kontaktuei buruzko datuak aldatzeko baimena ematen dio aplikazioari. Baimen horrekin, aplikazioek kontaktuen datuak ezaba ditzakete."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"irakurri deien erregistroa"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Aplikazioak deien historia irakur dezake."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"idatzi deien erregistroan"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"atzitu kokapen-hornitzaileen komando gehigarriak"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Kokapen-hornitzailearen agindu gehigarriak atzitzeko baimena ematen die aplikazioei. Horrela, agian aplikazioek GPSaren edo bestelako kokapenaren iturburuen funtzionamenduan eragina izan dezakete."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"lortu kokapen zehatza aurreko planoan bakarrik"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Aplikazioak zure kokapen zehatza lor dezake aurreko planoan funtzionatzen duenean bakarrik. Kokapen-zerbitzu horiek aktibatuta eta erabilgarri izan behar dituzu telefonoan, aplikazioak erabil ditzan. Baliteke bateria gehiago erabiltzea."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"Atzitu sarean oinarritutako gutxi gorabeherako kokapena aurreko planoan bakarrik"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Aplikazioa aurreko planoan dagoenean, zure kokapenaren berri izan dezake sareen iturburuak erabilita; adibidez, telefonia mugikorreko dorreak eta Wi-Fi sareak. Kokapen-zerbitzu horiek aktibatuta eta erabilgarri izan behar dituzu tabletan, aplikazioak erabil ditzan."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Aurreko planoan daudenean, aplikazioek zure kokapenaren berri izan dezakete sareen iturburuak erabilita; adibidez, telefonia mugikorreko dorreak eta wifi-sareak. Kokapen-zerbitzu horiek aktibatuta eta erabilgarri izan behar dituzu Android TV gailuan, aplikazioek erabil ditzaten."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Aplikazioa aurreko planoan dagoenean, zure kokapenaren berri izan dezake sareen iturburuak erabilita; adibidez, telefonia mugikorreko dorreak eta Wi-Fi sareak. Kokapen-zerbitzu horiek aktibatuta eta erabilgarri izan behar dituzu telefonoan, aplikazioak erabil ditzan."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Aplikazioak aurreko planoan funtzionatzen duenean bakarrik lor dezake zure kokapen zehatza. Kokapen-zerbitzuak aktibatuta eta erabilgarri eduki behar dituzu gailuan, aplikazioak erabil ditzan. Baliteke bateria gehiago erabiltzea."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"atzitu gutxi gorabeherako kokapena aurreko planoan bakarrik"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Aplikazioak aurreko planoan funtzionatzen duenean bakarrik lor dezake zure gutxi gorabeherako kokapena. Kokapen-zerbitzuak aktibatuta eta erabilgarri eduki behar dituzu gailuan, aplikazioak erabil ditzan."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"Atzitu kokapena atzeko planoan"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Baimen hau ematen bada kokapen zehatz edo gutxi gorabeherakorako sarbideaz gain, atzeko planoan abian den bitartean atzitu ahalko du aplikazioak kokapena."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Aurreko planoan egotean bezala, aplikazioak kokapena atzi dezake atzeko planoan egotean."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"aldatu audio-ezarpenak"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Audio-ezarpen orokorrak aldatzeko baimena ematen dio; besteak beste, bolumena eta irteerarako zer bozgorailu erabiltzen den."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"grabatu audioa"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Tabletaren Bluetooth konfigurazioa ikusteko eta parekatutako gailuekin konexioak egiteko eta onartzeko baimena ematen die aplikazioei."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Android TV gailuaren Bluetooth konexioaren konfigurazioa ikusteko eta parekatutako gailuekin konexioak sortzeko eta onartzeko baimena ematen die aplikazioei."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Telefonoaren Bluetooth konfigurazioa ikusteko eta parekatutako gailuekin konexioak egiteko eta onartzeko baimena ematen die aplikazioei."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"NFC bidezko ordainketa-zerbitzu lehenetsiari buruzko informazioa"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Aplikazioari baimena ematen dio NFC bidezko ordainketa-zerbitzu lehenetsiari buruzko informazioa jasotzeko, hala nola erregistratutako laguntzaileak eta ibilbidearen helmuga."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"kontrolatu Near Field Communication komunikazioa"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Near Field Communication (NFC) etiketekin, txartelekin eta irakurgailuekin komunikatzea baimentzen die aplikazioei."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"desgaitu pantailaren blokeoa"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"Erabilerraztasun-lasterbideak <xliff:g id="SERVICE_NAME">%1$s</xliff:g> aktibatu du"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"Erabilerraztasun-lasterbideak <xliff:g id="SERVICE_NAME">%1$s</xliff:g> desaktibatu du"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> erabiltzeko, eduki sakatuta bolumen-tekla biak hiru segundoz"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Aukeratu zer zerbitzu erabili nahi duzun Erabilerraztasuna botoia sakatzean:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Aukeratu zer zerbitzu erabili nahi duzun erabilerraztasun-keinua egitean (hau da, bi hatz pantailaren behealdetik gora pasatzean):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Aukeratu zer zerbitzu erabili nahi duzun erabilerraztasun-keinua egitean (hau da, hiru hatz pantailaren behealdetik gora pasatzean):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Zerbitzu batetik bestera aldatzeko, eduki sakatuta Erabilerraztasuna botoia."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Zerbitzu batetik bestera aldatzeko, pasatu bi hatz pantailaren behealdetik gora eta eduki sakatuta une batez."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Zerbitzu batetik bestera aldatzeko, pasatu hiru hatz pantailaren behealdetik gora eta eduki sakatuta une batez."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Lupa"</string>
<string name="user_switched" msgid="7249833311585228097">"Uneko erabiltzailea: <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="1912993630661332336">"<xliff:g id="NAME">%1$s</xliff:g> erabiltzailera aldatzen…"</string>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> zerbitzura konektatuta"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Sakatu fitxategiak ikusteko"</string>
<string name="pin_target" msgid="8036028973110156895">"Ainguratu"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Ainguratu <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Kendu aingura"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Kendu aingura <xliff:g id="LABEL">%1$s</xliff:g> aplikazioari"</string>
<string name="app_info" msgid="6113278084877079851">"Aplikazioari buruzko informazioa"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Demoa abiarazten…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291"><b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" zerbitzuan eguneratu nahi dituzu <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> eta <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Gorde"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Ez, eskerrik asko"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Orain ez"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Inoiz ez"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Eguneratu"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Egin aurrera"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"pasahitza"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Aktibatu/Desaktibatu pantaila zatitua"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Pantaila blokeatua"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Pantaila-argazkia"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioa dago leiho gainerakor batean"</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioko azpitituluen barra."</string>
</resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 433d4f3def2e..b45c6f92fe56 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"برنامه سرپرست نمایه کاری یا وجود ندارد یا خراب است. در نتیجه، نمایه کاری شما و داده‌های مرتبط با آن حذف شده است. برای دریافت راهنمایی با سرپرست سیستم تماس بگیرید."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"نمایه کاری شما دیگر در این دستگاه دردسترس نیست"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"تلاش‌های بسیار زیادی برای وارد کردن گذرواژه انجام شده است"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"سرپرست از این دستگاه برای استفاده شخصی چشم‌پوشی کرد"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"دستگاه مدیریت می‌شود"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"سازمانتان این دستگاه را مدیریت می‌کند و ممکن است ترافیک شبکه را پایش کند. برای اطلاع از جزئیات، ضربه بزنید."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"دستگاهتان پاک خواهد شد"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"‏به برنامه اجازه می‌دهد همه‌فرستی‌های چسبان ارسال کند که پس از اتمام همه‌فرستی باقی می‌مانند. استفاده بیش‌ازحد از این مجوز می‌تواند باعث استفاده خیلی زیاد از حافظه شود که به کندی یا ناپایداری Android TV منجر می‌شود."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"‏به برنامه اجازه می‎دهد تا پخش‌های ماندگار را که پس از اتمام پخش باقی می‎مانند ارسال کند. استفاده بیش از حد این ویژگی ممکن است باعث مصرف بیش از حد حافظه و در نتیجه کندی یا ناپایداری تلفن شود."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"خواندن مخاطبین شما"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"به برنامه اجازه می‌دهد داده‌های مربوط به مخاطبین ذخیره شده در رایانهٔ لوحی شما را بخواند از جمله، تعداد دفعات تماس‌هایی که برقرار کرده‌اید، ایمیل‌هایی که ارسال کرده‌اید یا به روش‌های دیگری به افراد خاصی ارتباط برقرار کرده‌اید. این با برنامه‌ها امکان می‌دهد داده‌های مخاطب شما را ذخیره کنند و برنامه‌های مخرب ممکن است داده‌های مخاطب را بدون اطلاع شما به اشتراک بگذارند."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"‏به برنامه اجازه می‌دهد داده‌های مربوط به مخاطبین ذخیره‌شده در دستگاه Android TV شما را بخواند، ازجمله تعداد دفعاتی که با افراد خاصی تماس گرفته‌اید، برایشان ایمیل ارسال کرده‌اید، یا به روش‌های دیگری با آن‌ها ارتباط برقرار کرده‌اید. این مجوز به برنامه‌ها اجازه می‌دهد داده‌های مخاطب شما را ذخیره کنند، و ممکن است برنامه‌های مخرب بدون اطلاع شما داده‌های مخاطب را هم‌رسانی کنند."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"به برنامه اجازه می‌دهد داده‌های مربوط به مخاطبین ذخیره شده در تلفن شما را بخواند از جمله، تعداد دفعات تماس‌هایی که برقرار کرده‌اید، ایمیل‌هایی که ارسال کرده‌اید یا به روش‌های دیگری با افراد خاصی ارتباط برقرار کرده‌اید. این به برنامه‌ها امکان می‌دهد داده‌های مخاطب شما را ذخیره کنند و برنامه‌های مخرب ممکن است داده‌های مخاطب را بدون اطلاع شما به اشتراک بگذارند."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"به برنامه اجازه می‌دهد داده‌های مربوط به مخاطبین ذخیره‌شده در رایانه لوحی شما را بخواند. برنامه‌ها همچنین به حساب‌های موجود در رایانه لوحی که مخاطبین ایجاد کرده‌اند دسترسی خواهند داشت. می‌تواند شامل حساب‌هایی باشد که توسط برنامه‌هایی که نصب کرده‌اید، ایجاد شده است. این مجوز به برنامه‌ها اجازه می‌دهد داده‌های مخاطب شما را ذخیره کنند، و ممکن است برنامه‌های مخرب بدون اطلاع شما داده‌های مخاطب را هم‌رسانی کنند."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"‏به برنامه اجازه می‌دهد داده‌های مربوط به مخاطبین ذخیره‌شده در دستگاه Android TV شما را بخواند. برنامه‌ها همچنین به حساب‌های موجود در دستگاه Android TV که مخاطبین ایجاد کرده‌اند دسترسی خواهد داشت. می‌تواند شامل حساب‌هایی باشد که توسط برنامه‌هایی که نصب کرده‌اید، ایجاد شده است. این مجوز به برنامه‌ها اجازه می‌دهد داده‌های مخاطب شما را ذخیره کنند، و ممکن است برنامه‌های مخرب بدون اطلاع شما داده‌های مخاطب را هم‌رسانی کنند."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"به برنامه اجازه می‌دهد داده‌های مربوط به مخاطبین ذخیره‌شده در تلفن را بخواند. برنامه‌ها همچنین به حساب‌های موجود در تلفن که مخاطبین ایجاد کرده‌اند دسترسی خواهند داشت. می‌تواند شامل حساب‌هایی باشد که توسط برنامه‌هایی که نصب کرده‌اید، ایجاد شده است. این مجوز به برنامه‌ها اجازه می‌دهد داده‌های مخاطب شما را ذخیره کنند، و ممکن است برنامه‌های مخرب بدون اطلاع شما داده‌های مخاطب را هم‌رسانی کنند."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"تغییر مخاطبین"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"به برنامه اجازه می‌دهد داده‌های مربوط به مخاطبین ذخیره شده در رایانهٔ لوحی شما را از جمله تعداد تماس‌‌هایی که برقرار کرده‌اید، ایمیل‌هایی که ارسال کرده‌اید یا ارتباطاتی را که به هر شکل با مخاطبین خاصی برقرار کردید تغییر دهد. این مجوز به برنامه اجازه می‌دهد داده‌های مخاطب را حذف نماید."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"‏به برنامه اجازه می‌دهد داده‌های مربوط به مخاطبین ذخیره‌شده در دستگاه Android TV شما را تغییر دهد، ازجمله تعداد دفعاتی که با مخاطبین خاصی تماس گرفته‌اید، برایشان ایمیل ارسال کرده‌اید، یا به روش‌های دیگری با آن‌ها ارتباط برقرار کرده‌اید. این مجوز به برنامه‌ها اجازه می‌دهد داده‌های مخاطب را حذف کنند."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"به برنامه اجازه می‌دهد داده‌های مربوط به مخاطبین ذخیره شده در تلفن شما را از جمله تعداد تماس‌‌هایی که برقرار کرده‌اید، ایمیل‌هایی که ارسال کرده‌اید یا ارتباطاتی را که به هر شکل با مخاطبین خاصی برقرار کردید تغییر دهد. این مجوز به برنامه اجازه می‌دهد داده‌های مخاطب را حذف نماید."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"به برنامه اجازه می‌دهد داده‌های مربوط به مخاطبین ذخیره‌شده در رایانه لوحی شما را تغییر دهد. این مجوز به برنامه‌ها اجازه می‌دهد داده‌های مخاطب را حذف کنند."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"‏به برنامه اجازه می‌دهد داده‌های مربوط به مخاطبین ذخیره‌شده در دستگاه Android TV شما را تغییر دهد. این مجوز به برنامه‌ها اجازه می‌دهد داده‌های مخاطب را حذف کنند."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"به برنامه اجازه می‌دهد داده‌های مربوط به مخاطبین ذخیره‌شده در تلفنتان را تغییر دهد. این مجوز به برنامه‌ها اجازه می‌دهد داده‌های مخاطب را حذف کنند."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"خواندن گزارش تماس"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"این برنامه می‌تواند سابقه تماس شما را بخواند."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"نوشتن گزارش تماس"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"دسترسی به فرمان‌های بیشتر ارائه دهنده مکان"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"‏به برنامه اجازه می‌دهد به دستورات ارائه‌دهنده مکان تکمیلی دسترسی داشته باشد. این کار ممکن است به برنامه امکان دهد با کارکرد GPS یا منابع دیگر مکان تداخل داشته باشد."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"دسترسی به مکان دقیق فقط در پیش‌زمینه"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"این برنامه فقط زمانی می‌تواند موقعیت مکانی دقیق شما را دریافت کند که در پیش‌زمینه باشد. برای اینکه برنامه بتواند از خدمات مکان استفاده کند، این خدمات باید در تلفنتان روشن و دردسترس باشد. ممکن است با این کار مصرف باتری افزایش یابد."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"دسترسی به مکان تقریبی (مبتنی بر شبکه) فقط در پیش‌زمینه"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"‏این برنامه می‌تواند براساس منابع شبکه مانند دکل‌های مخابراتی و شبکه‌های Wi-Fi، مکانتان را تشخیص دهد، اما فقط درصورتی‌که برنامه در پیش‌زمینه باشد. این خدمات مکان باید روشن و در رایانه لوحی شما دردسترس باشند تا برنامه بتواند از آن‌ها استفاده کند."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"‏این برنامه می‌تواند براساس منابع شبکه، مانند دکل‌های مخابراتی و شبکه‌های Wi-Fi، مکانتان را تشخیص دهد، اما فقط درصورتی‌که برنامه در پیش‌زمینه باشد. این خدمات مکان باید در دستگاه Android TV شما روشن و دردسترس باشد تا برنامه بتواند از آن‌ها استفاده کند."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"‏این برنامه می‌تواند براساس منابع شبکه مانند دکل‌های مخابراتی و شبکه‌های Wi-Fi، مکانتان را تشخیص دهد، اما فقط درصورتی‌که برنامه در پیش‌زمینه است. این خدمات مکان باید روشن و در تلفن شما دردسترس باشند تا برنامه بتواند از آن‌ها استفاده کند."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"این برنامه فقط زمانی می‌تواند موقعیت مکانی دقیق شما را دریافت کند که در پیش‌زمینه باشد. برای اینکه برنامه بتواند از خدمات مکان استفاده کند، این خدمات باید در دستگاهتان روشن و در دسترس باشد. ممکن است با این کار مصرف باتری افزایش یابد."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"دسترسی به مکان تقریبی فقط در پیش‌زمینه"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"این برنامه فقط هنگامی‌که در پیش‌زمینه است می‌تواند مکان تقریبی شما را دریافت کند. برای اینکه برنامه بتواند از خدمات مکان استفاده کند، این خدمات باید روشن و در دستگاهتان در دسترس باشند."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"دسترسی به مکان در پس‌زمینه"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"اگر این مجوز نیز برای دسترسی دقیق یا تقریبی به مکان داده شود، برنامه می‌تواند درحین اجرا در پس‌زمینه به مکان دسترسی پیدا کند."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"این برنامه علاوه‌بر دسترسی به مکان در پیش‌زمینه، می‌تواند هنگام اجرا در پس‌زمینه نیز به مکان دسترسی داشته باشد."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"تغییر تنظیمات صوتی"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"به برنامه امکان می‌دهد تنظیمات صوتی کلی مانند میزان صدا و بلندگوی مورد استفاده برای پخش صدا را تغییر دهد."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"ضبط صدا"</string>
@@ -494,6 +491,8 @@
<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_preferredPaymentInfo" msgid="5274423844767445054">"‏اطلاعات ترجیحی سرویس پولی NFC"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"‏به برنامه اجازه می‌دهد اطلاعات ترجیحی «سرویس پولی NFC»، مانند کمک‌های ثبت‌شده و مقصد مسیر را دریافت کند."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"کنترل ارتباط راه نزدیک"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"‏به برنامه اجازه می‎دهد تا با تگ‌های «ارتباط میدان نزدیک» (NFC)، کارت‌ها و فایل‌خوان ارتباط برقرار کند."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"غیرفعال کردن قفل صفحه شما"</string>
@@ -1177,7 +1176,7 @@
<string name="screen_compat_mode_scale" msgid="8627359598437527726">"مقیاس"</string>
<string name="screen_compat_mode_show" msgid="5080361367584709857">"همیشه نشان داده شود"</string>
<string name="screen_compat_mode_hint" msgid="4032272159093750908">"‏در تنظیمات سیستم &gt;برنامه‎ها &gt; مورد بارگیری شده آن را دوباره فعال کنید."</string>
- <string name="unsupported_display_size_message" msgid="7265211375269394699">"<xliff:g id="APP_NAME">%1$s</xliff:g> از تنظیم فعلی اندازه نمایشگر پشتیبانی نمی‌کند و ممکن است رفتار غیرمنتظره‌ای داشته باشد."</string>
+ <string name="unsupported_display_size_message" msgid="7265211375269394699">"<xliff:g id="APP_NAME">%1$s</xliff:g> از تنظیم فعلی اندازه نمایش پشتیبانی نمی‌کند و ممکن است رفتار غیرمنتظره‌ای داشته باشد."</string>
<string name="unsupported_display_size_show" msgid="980129850974919375">"همیشه نشان داده شود"</string>
<string name="unsupported_compile_sdk_message" msgid="7326293500707890537">"‏<xliff:g id="APP_NAME">%1$s</xliff:g> برای نسخه ناسازگار سیستم‌عامل Android ساخته شده است و ممکن است رفتاری برخلاف انتظار داشته باشد. ممکن است نسخه به‌روزی از برنامه در دسترس باشد."</string>
<string name="unsupported_compile_sdk_show" msgid="1601210057960312248">"همیشه نشان داده شود"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"«میان‌بر دسترس‌پذیری» <xliff:g id="SERVICE_NAME">%1$s</xliff:g> را روشن کرد"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"«میان‌بر دسترس‌پذیری» <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>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"سرویسی را انتخاب کنید که می‌خواهید هنگام ضربه زدن روی دکمه دسترس‌پذیری استفاده شود:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"سرویسی را برای استفاده با اشاره دسترس‌پذیری انتخاب کنید (با دو انگشت صفحه را از پایین تند به بالا بکشید):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"سرویسی را برای استفاده با اشاره دسترس‌پذیری انتخاب کنید (با سه انگشت صفحه را از پایین تند به بالا بکشید):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"برای جابه‌جایی بین سرویس‌ها، دکمه دسترس‌پذیری را لمس کنید و نگه‌دارید."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"برای جابه‌جایی بین سرویس‌ها، با دو انگشت صفحه را تند به بالا بکشید و نگه‌دارید."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"برای جابه‌جایی بین سرویس‌ها، با سه انگشت صفحه را تند به بالا بکشید و نگه‌دارید."</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>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"به <xliff:g id="PRODUCT_NAME">%1$s</xliff:g> متصل شد"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"برای دیدن فایل‌ها، ضربه بزنید"</string>
<string name="pin_target" msgid="8036028973110156895">"پین کردن"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"پین کردن <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"برداشتن پین"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"برداشتن پین <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"اطلاعات برنامه"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"در حال شروع نسخه نمایشی…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"این موارد در "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <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> به‌روزرسانی شود؟"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"ذخیره"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"نه سپاسگزارم"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"حالا نه"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"هیچ‌وقت"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"به‌روزرسانی"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"ادامه"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"گذرواژه"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"تغییر وضعیت صفحهٔ دونیمه"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"صفحه قفل"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"عکس صفحه‌نمایش"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"برنامه <xliff:g id="APP_NAME">%1$s</xliff:g> در پنجره بالاپر."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"نوار شرح <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 0c7bd77fae4a..c1df18e23839 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Työprofiilin hallintasovellus puuttuu tai se on vioittunut. Tästä syystä työprofiilisi ja siihen liittyvät tiedot on poistettu. Pyydä ohjeita järjestelmänvalvojaltasi."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Työprofiilisi ei ole enää käytettävissä tällä laitteella."</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Liikaa salasanayrityksiä"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Järjestelmänvalvoja luovutti laitteen henkilökohtaiseen käyttöön"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Hallinnoitu laite"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Organisaatiosi hallinnoi tätä laitetta ja voi tarkkailla verkkoliikennettä. Katso lisätietoja napauttamalla."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Laitteen tiedot poistetaan"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Antaa sovelluksen lähettää pysyviä lähetyksiä, jotka säilyvät lähetyksen päätyttyä. Liiallinen käyttö voi tehdä Android TV ‑laitteesta hitaan tai epävakaan lisäämällä sen muistinkäyttöä liikaa."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Antaa sovelluksen lähettää pysyviä lähetyksiä, jotka säilyvät lähetyksen päätyttyä. Liiallinen käyttö voi tehdä puhelimesta hitaan tai epävakaan kasvattamalla sen muistinkäyttöä liikaa."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"lue yhteystietoja"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Antaa sovelluksen lukea tablet-laitteeseesi tallennettuja kontaktitietoja sekä tarkastella, kuinka usein olet soittanut, lähettänyt sähköpostia tai muuten viestinyt tiettyjen kontaktien kanssa. Tämän luvan saaneet sovellukset voivat tallentaa kontaktitietoja. Haitalliset sovellukset voivat jakaa kontaktitietoja ilman lupaasi."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Antaa sovelluksen lukea Android TV ‑laitteeseen tallennettuja kontaktitietoja sekä nähdä, kuinka usein olet soitellut, lähettänyt sähköpostia tai muuten viestinyt tiettyjen kontaktien kanssa. Tämän luvan saaneet sovellukset voivat tallentaa kontaktitietoja. Haitalliset sovellukset voivat jakaa kontaktitietoja ilman lupaasi."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Antaa sovelluksen lukea puhelimeesi tallennettuja kontaktitietoja sekä tarkastella, kuinka usein olet soittanut, lähettänyt sähköpostia tai muuten viestinyt tiettyjen kontaktien kanssa. Tämän luvan saaneet sovellukset voivat tallentaa kontaktitietoja. Haitalliset sovellukset voivat jakaa kontaktitietoja ilman lupaasi."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Antaa sovelluksen lukea tabletille tallennettujen kontaktien tietoja. Sovellukset saavat myös pääsyn tablettisi tileille, joilla on luotu kontaktitietoja. Tilit voivat olla myös asentamiesi sovellusten luomia. Tämän luvan saaneet sovellukset voivat tallentaa kontaktitietoja. Haitalliset sovellukset voivat jakaa kontaktitietoja ilman lupaasi."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Antaa sovelluksen lukea Android TV ‑laitteelle tallennettujen kontaktien tietoja. Sovellukset saavat myös pääsyn Android TV ‑laitteesi tileille, joilla on luotu kontaktitietoja. Tilit voivat olla myös asentamiesi sovellusten luomia. Tämän luvan saaneet sovellukset voivat tallentaa kontaktitietoja. Haitalliset sovellukset voivat jakaa kontaktitietoja ilman lupaasi."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Antaa sovelluksen lukea puhelimelle tallennettujen kontaktien tietoja. Sovellukset saavat myös pääsyn puhelimen tileille, joilla on luotu kontaktitietoja. Tilit voivat olla myös asentamiesi sovellusten luomia. Tämän luvan saaneet sovellukset voivat tallentaa kontaktitietoja. Haitalliset sovellukset voivat jakaa kontaktitietoja ilman lupaasi."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"muokkaa yhteystietoja"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Antaa sovelluksen muokata tablet-laitteeseesi tallennettuja kontaktitietoja sekä tarkastella, kuinka usein olet soittanut, lähettänyt sähköpostia tai muuten viestinyt tiettyjen kontaktien kanssa. Tämän luvan saaneet sovellukset voivat poistaa kontaktitietoja."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Antaa sovelluksen muokata Android TV ‑laitteeseen tallennettujen kontaktiesi dataa sekä nähdä, kuinka usein olet soitellut, lähettänyt sähköpostia tai muuten viestinyt tiettyjen kontaktien kanssa. Tämän luvan saaneet sovellukset voivat poistaa kontaktitietoja."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Antaa sovelluksen muokata puhelimeesi tallennettuja kontaktitietoja sekä tarkastella, kuinka usein olet soittanut, lähettänyt sähköpostia tai muuten viestinyt tiettyjen kontaktien kanssa. Tämän luvan saaneet sovellukset voivat poistaa kontaktitietoja."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Antaa sovelluksen muokata tabletille tallennettujen kontaktien tietoja. Käyttöluvan saaneet sovellukset voivat myös poistaa kontaktitietoja."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Antaa sovelluksen muokata Android TV ‑laitteelle tallennettujen kontaktien tietoja. Käyttöluvan saaneet sovellukset voivat myös poistaa kontaktitietoja."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Antaa sovelluksen muokata puhelimelle tallennettujen kontaktien tietoja. Käyttöluvan saaneet sovellukset voivat myös poistaa kontaktitietoja."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"lue puhelulokia"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Tämä sovellus voi lukea puheluhistoriaasi."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"kirjoita puhelulokiin"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"käytä lisää sijainnintarjoajakomentoja"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Antaa sovelluksen käyttää ylimääräisiä sijaintipalvelukomentoja. Sovellus saattaa tällöin häiritä GPS:n tai muiden sijaintilähteiden toimintaa."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"käyttää tarkkaa sijaintia vain etualalla"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Tämä sovellus saa tarkat sijaintitietosi käyttöönsä vain etualalla. Näiden sijaintipalveluiden tulee olla käytössä ja käytettävissä puhelimellasi, jotta sovellus voi käyttää niitä. Tämä voi lisätä akun kulutusta."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"käyttää karkeaa verkkoon perustuvaa sijaintia vain etualalla"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Tämä sovellus voi määrittää sijaintisi matkapuhelinverkon tukiasemien, Wi-Fi-verkkojen ja muiden verkkolähteiden perusteella vain jos sovellus on etualalla. Näiden sijaintipalveluiden tulee olla päällä ja käytettävissä tabletilla, jotta sovellus voi käyttää niitä."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Tämä sovellus voi määrittää sijaintisi matkapuhelinverkon tukiasemien, Wi-Fi-verkkojen ja muiden verkkolähteiden perusteella vain jos sovellus on etualalla. Näiden sijaintipalveluiden tulee olla päällä ja käytettävissä Android TV ‑laitteessa, jotta sovellus voi käyttää niitä."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Tämä sovellus voi määrittää sijaintisi matkapuhelinverkon tukiasemien, Wi-Fi-verkkojen ja muiden verkkolähteiden perusteella vain jos sovellus on etualalla. Näiden sijaintipalveluiden tulee olla päällä ja käytettävissä puhelimessa, jotta sovellus voi käyttää niitä."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Tämä sovellus saa tarkat sijaintitietosi käyttöönsä vain etualalla. Sijaintipalveluiden tulee olla päällä ja käytettävissä laitteella, jotta sovellus voi käyttää niitä. Tämä voi lisätä akun kulutusta."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"käyttää karkeaa sijaintia vain etualalla"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Tämä sovellus saa karkean sijaintisi käyttöönsä vain ollessaan etualalla. Sijaintipalveluiden tulee olla päällä ja käytettävissä laitteellasi, jotta sovellus voi käyttää niitä."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"käytä sijaintia taustalla"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Jos tämä myönnetään karkean tai tarkan sijainnin käyttöoikeuden lisäksi, sovellus voi käyttää sijaintia toimiessaan taustalla."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Tämä sovellus voi käyttää sijaintia taustalla ja etualalla."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"muuta ääniasetuksia"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Antaa sovelluksen muokata yleisiä ääniasetuksia, kuten äänenvoimakkuutta ja käytettävää kaiutinta."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"tallentaa ääntä"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Antaa sovelluksen tarkastella tablet-laitteen Bluetooth-asetuksia sekä muodostaa ja hyväksyä laitepariyhteyksiä."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Antaa sovelluksen nähdä Android TV ‑laitteen Bluetooth-asetukset sekä muodostaa ja hyväksyä laitepariyhteyksiä."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Antaa sovelluksen tarkastella puhelimen Bluetooth-asetuksia sekä muodostaa ja hyväksyä laitepariyhteyksiä muihin laitteisiin."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Ensisijaiset NFC-maksupalvelutiedot"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Sallii sovelluksen noutaa tietoja rekisteröidyistä sovellustunnuksista, maksureitin kohteesta ja muita ensisijaisia NFC-maksupalvelutietoja."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"hallitse Near Field Communication -tunnistusta"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Antaa sovelluksen kommunikoida NFC (Near Field Communication) -tagien, -korttien ja -lukijoiden kanssa."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"poista näytön lukitus käytöstä"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> otettiin käyttöön esteettömyystilan pikanäppäimellä."</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> poistettiin käytöstä esteettömyystilan pikanäppäimellä."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Voit käyttää palvelua <xliff:g id="SERVICE_NAME">%1$s</xliff:g> painamalla molempia äänenvoimakkuuspainikkeita kolmen sekunnin ajan"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Valitse palvelu, jonka esteettömyyspainike aktivoi:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Valitse palvelu, jota käytetään esteettömyyseleellä (pyyhkäise näytön alalaidasta ylös kahdella sormella):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Valitse palvelu, jota käytetään esteettömyyseleellä (pyyhkäise näytön alalaidasta ylös kolmella sormella):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Vaihda palveluiden välillä painamalla painiketta pitkään."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Vaihda palveluiden välillä pyyhkäisemällä ylös kahdella sormella ja koskettamalla pitkään."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Vaihda palveluiden välillä pyyhkäisemällä ylös kolmella sormella ja koskettamalla pitkään."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Suurennus"</string>
<string name="user_switched" msgid="7249833311585228097">"Nykyinen käyttäjä: <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="1912993630661332336">"Vaihdetaan käyttäjään <xliff:g id="NAME">%1$s</xliff:g>…"</string>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> yhdistetty"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Näytä tiedostot koskettamalla"</string>
<string name="pin_target" msgid="8036028973110156895">"Kiinnitä"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Kiinnitä <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Irrota"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Irrota <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Sovelluksen tiedot"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Aloitetaan esittelyä…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Päivitetäänkö nämä ("<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"): <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ja <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Tallenna"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Ei kiitos"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Ei nyt"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Ei koskaan"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Muuta"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Jatka"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"salasana"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Jaettu näyttö päälle/pois"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Lukitusnäyttö"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Kuvakaappaus"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"Sovellus (<xliff:g id="APP_NAME">%1$s</xliff:g>) ponnahdusikkunassa"</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Tekstityspalkki: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 3c8f75fd83a7..9f2647d026e3 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Le profil professionnel de l\'application d\'administration est manquant ou corrompu. Votre profil professionnel et ses données connexes ont donc été supprimés. Communiquez avec votre administrateur pour obtenir de l\'assistance."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Votre profil professionnel n\'est plus accessible sur cet appareil"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Trop de tentatives d\'entrée du mot de passe"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"L\'administrateur a libéré l\'appareil pour un usage personnel"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"L\'appareil est géré"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Votre organisation gère cet appareil et peut surveiller le trafic réseau. Touchez ici pour obtenir plus d\'information."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Le contenu de votre appareil sera effacé"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Permet à l\'application d\'envoyer des intentions de diffusion persistantes, qui perdurent une fois la diffusion terminée. Une utilisation excessive peut ralentir votre appareil Android TV ou le rendre instable en l\'obligeant à utiliser trop de mémoire."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Permet à l\'application d\'envoyer des intentions de diffusion \"persistantes\", qui perdurent une fois la diffusion terminée. Une utilisation excessive peut ralentir le téléphone ou le rendre instable en l\'obligeant à utiliser trop de mémoire."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"lire vos contacts"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Permet à l\'application de lire les données relatives aux contacts stockés sur votre tablette, y compris la fréquence à laquelle vous avez appelé des personnes spécifiques, leur avez envoyé des courriels ou avez communiqué avec elles par d\'autres moyens. Cette autorisation permet aux applications d\'enregistrer ces données. Les applications malveillantes peuvent les partager à votre insu."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Permet à l\'application de lire les données relatives aux contacts stockés sur votre appareil Android TV, y compris la fréquence à laquelle vous avez appelé certaines personnes, leur avez envoyé des courriels ou avez communiqué avec elles par d\'autres moyens. Cette autorisation permet aux applications d\'enregistrer ces données. Les applications malveillantes peuvent les partager à votre insu."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Permet à l\'application de lire les données relatives aux contacts stockés sur votre téléphone, y compris la fréquence à laquelle vous avez appelé des personnes spécifiques, leur avez envoyé des courriels ou avez communiqué avec elles par d\'autres moyens. Cette autorisation permet aux applications d\'enregistrer ces données. Les applications malveillantes peuvent les partager à votre insu."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Permet à l\'application de lire les données relatives aux contacts stockés sur votre tablette. Les applications auront aussi accès aux comptes sur votre tablette qui ont créé des contacts. Cela peut comprendre des comptes créés par des applications que vous avez installées. Cette autorisation permet aux applications d\'enregistrer ces données. Les applications malveillantes peuvent les partager à votre insu."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Permet à l\'application de lire les données relatives aux contacts stockés sur votre appareil Android TV. Les applications auront aussi accès aux comptes sur votre appareil Android TV qui ont créé des contacts. Cela peut comprendre des comptes créés par des applications que vous avez installées. Cette autorisation permet aux applications d\'enregistrer ces données. Les applications malveillantes peuvent les partager à votre insu."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Permet à l\'application de lire les données relatives aux contacts stockés sur votre téléphone. Les applications auront aussi accès aux comptes sur votre téléphone qui ont créé des contacts. Cela peut comprendre des comptes créés par des applications que vous avez installées. Cette autorisation permet aux applications d\'enregistrer ces données. Les applications malveillantes peuvent les partager à votre insu."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"modifier vos contacts"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Permet à l\'application de modifier les données relatives aux contacts stockés sur votre tablette, y compris la fréquence à laquelle vous avez appelé des personnes spécifiques, leur avez envoyé des courriels ou avez communiqué avec elles par d\'autres moyens. Cette autorisation permet aux applications de supprimer ces données."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Permet à l\'application de modifier les données relatives aux contacts stockés sur votre appareil Android TV, y compris la fréquence à laquelle vous avez appelé certaines personnes, leur avez envoyé des courriels ou avez communiqué avec elles par d\'autres moyens. Cette autorisation permet aux applications de supprimer ces données."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Permet à l\'application de modifier les données relatives aux contacts stockés sur votre téléphone, y compris la fréquence à laquelle vous avez appelé des personnes spécifiques, leur avez envoyé des courriels ou avez communiqué avec elles par d\'autres moyens. Cette autorisation permet aux applications de supprimer ces données."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Permet à l\'application de modifier les données relatives aux contacts stockés sur votre tablette. Cette autorisation permet aux applications de supprimer des données relatives aux contacts."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Permet à l\'application de modifier les données relatives aux contacts stockés sur votre appareil Android TV. Cette autorisation permet aux applications de supprimer des données relatives aux contacts."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Permet à l\'application de modifier les données relatives aux contacts stockés sur votre téléphone. Cette autorisation permet aux applications de supprimer des données relatives aux contacts."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"lire le journal d\'appels"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Cette application peut lire votre historique d\'appel."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"modifier le journal d\'appels"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"accéder aux commandes de fournisseur de position géographique supplémentaires"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Permet à l\'application d\'accéder à des commandes de localisation supplémentaires offertes par le fournisseur. Elle est ainsi susceptible d\'interférer avec le bon fonctionnement du GPS ou de toute autre source de localisation."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"accéder à votre position précise seulement en avant-plan"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Cette application peut obtenir votre position exacte seulement lorsqu\'elle fonctionne en avant-plan. Ces services de localisation doivent être activés et accessibles sur votre téléviseur pour que l\'application puisse les utiliser. Cela peut entraîner une utilisation accrue de la pile."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"accéder à la position approximative (selon les données réseau), mais uniquement lorsque l\'application s\'exécute au premier plan"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Cette application peut déterminer votre position à l\'aide de différentes sources de localisation sur le réseau, comme les tours de téléphonie cellulaire et les réseaux Wi-Fi, mais uniquement lorsqu\'elle s\'exécute au premier plan. Ces services de localisation doivent être activés et accessibles sur votre tablette pour que l\'application puisse les utiliser."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Cette application peut déterminer votre position à l\'aide de différentes sources de localisation sur le réseau, comme les tours de téléphonie cellulaire et les réseaux Wi-Fi, mais uniquement lorsqu\'elle s\'exécute au premier plan. Ces services de localisation doivent être activés et accessibles sur votre appareil Android TV pour que l\'application puisse les utiliser."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Cette application peut déterminer votre position à l\'aide de différentes sources de localisation sur le réseau, comme les tours de téléphonie cellulaire et les réseaux Wi-Fi, mais uniquement lorsqu\'elle s\'exécute au premier plan. Ces services de localisation doivent être activés et accessibles sur votre téléphone pour que l\'application puisse les utiliser."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Cette application peut obtenir votre position exacte seulement lorsqu\'elle fonctionne en avant-plan. Les services de localisation doivent être activés et accessibles sur votre appareil pour que l\'application puisse les utiliser. Cela peut entraîner une utilisation accrue de la pile."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"accéder à votre position approximative seulement en avant-plan"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Cette application peut seulement obtenir votre position approximative lorsqu\'elle fonctionne en avant-plan. Les services de localisation doivent être activés et accessibles sur votre appareil pour que l\'application puisse les utiliser."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"accès à la localisation en arrière-plan"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Si cette autorisation est accordée en plus de l\'accès approximatif ou précis à la localisation, alors l\'application peut accéder à la localisation lorsqu\'elle fonctionne en arrière-plan."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Cette application peut accéder à la position en arrière-plan, en plus d\'en avant-plan."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"modifier vos paramètres audio"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Permet à l\'application de modifier les paramètres audio généraux, tels que le volume et la sortie audio utilisée."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"enregistrer des fichiers audio"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Permet à l\'application d\'accéder à la configuration du Bluetooth sur la tablette, et d\'établir et accepter des connexions avec les appareils associés."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Permet à l\'application d\'afficher la configuration du Bluetooth sur votre appareil Android TV, de se connecter à des appareils associés et d\'accepter leur connexion."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Permet à l\'application d\'accéder à la configuration du Bluetooth sur le téléphone, et d\'établir et accepter des connexions avec les appareils associés."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Information sur le service préféré de paiement NFC"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Permet à l\'application d\'obtenir de l\'information sur le service préféré de paiement NFC comme les aides enregistrées et la route de destination."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"gérer la communication en champ proche"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Permet à l\'application de communiquer avec des bornes, des cartes et des lecteurs compatibles avec la technologie NFC (communication en champ proche)."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"désactiver le verrouillage de l\'écran"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"Le raccourci d\'accessibilité a activé la fonction <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"Le raccourci d\'accessibilité a désactivé la fonction <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Maintenez enfoncées les deux touches de volume pendant trois secondes pour utiliser <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Choisissez un service à utiliser lorsque vous touchez le bouton d\'accessibilité :"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Choisissez un service à utiliser lorsque vous utilisez le geste d\'accessibilité (balayer l\'écran de bas en haut avec deux doigts) :"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Choisissez un service à utiliser lorsque vous utilisez le geste d\'accessibilité (balayer l\'écran de bas en haut avec trois doigts) :"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Pour basculer entre les services, maintenez le doigt sur le bouton d\'accessibilité."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Pour basculer entre les services, balayez l\'écrfan vers le haut avec deux doigts et maintenez-les-y."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Pour changer de service, balayez trois doigts vers le haut et maintenez-les sur l\'écran."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Zoom"</string>
<string name="user_switched" msgid="7249833311585228097">"Utilisateur actuel : <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="user_switching_message" msgid="1912993630661332336">"Changement d\'utilisateur (<xliff:g id="NAME">%1$s</xliff:g>) en cours…"</string>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Connecté à <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Touchez ici pour afficher les fichiers"</string>
<string name="pin_target" msgid="8036028973110156895">"Épingler"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Épingler <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Annuler l\'épinglage"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Annuler l\'épinglage de <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Détails de l\'application"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Démarrage de la démonstration en cours…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Mettre à jour ces éléments sous "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" : <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> et <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Enregistrer"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Non, merci"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Pas maintenant"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Jamais"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Mettre à jour"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Continuer"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"mot de passe"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Basculer l\'écran partagé"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Écran de verrouillage"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Capture d\'écran"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"Application <xliff:g id="APP_NAME">%1$s</xliff:g> dans une fenêtre contextuelle."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Barre de légende de l\'application <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 1b53bd9ecd7f..7d8065363eb4 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"L\'application d\'administration du profil professionnel est manquante ou endommagée. Par conséquent, votre profil professionnel et toutes les données associées ont été supprimés. Pour obtenir de l\'aide, contactez l\'administrateur."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Votre profil professionnel n\'est plus disponible sur cet appareil"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Trop de tentatives de saisie du mot de passe"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"L\'administrateur a mis l\'appareil à disposition pour un usage personnel"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"L\'appareil est géré"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Votre organisation gère cet appareil et peut surveiller le trafic réseau. Appuyez ici pour obtenir plus d\'informations."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Les données de votre appareil vont être effacées"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Permet à l\'application d\'envoyer des diffusions \"persistantes\", qui perdurent une fois la diffusion effectuée. Une utilisation excessive peut ralentir votre appareil Android TV ou le rendre instable en l\'obligeant à utiliser trop de mémoire."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Permet à l\'application d\'envoyer des intentions de diffusion \"persistantes\", qui perdurent une fois la diffusion terminée. Une utilisation excessive peut ralentir le téléphone ou le rendre instable en l\'obligeant à utiliser trop de mémoire."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"Voir les contacts"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Permet à l\'application de lire les données relatives aux contacts stockés sur votre tablette, y compris la fréquence à laquelle vous avez appelé des personnes spécifiques, leur avez envoyé des e-mails ou avez communiqué avec elles par d\'autres moyens. Cette autorisation permet aux applications d\'enregistrer ces données. Les applications malveillantes peuvent les partager à votre insu."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Permet à l\'application de lire les données liées aux contacts stockés sur votre appareil Android TV, y compris la fréquence à laquelle vous avez appelé des personnes spécifiques, leur avez envoyé des e-mails ou avez communiqué avec elles par d\'autres moyens. Cette autorisation permet aux applications d\'enregistrer ces données. Des applications malveillantes peuvent exploiter cette fonctionnalité pour partager ces données à votre insu."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Permet à l\'application de lire les données relatives aux contacts stockés sur votre téléphone, y compris la fréquence à laquelle vous avez appelé des personnes spécifiques, leur avez envoyé des e-mails ou avez communiqué avec elles par d\'autres moyens. Cette autorisation permet aux applications d\'enregistrer ces données. Les applications malveillantes peuvent les partager à votre insu."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Permet à l\'application de lire les données liées aux contacts stockés sur votre tablette. Les applications auront également accès aux comptes de votre tablette pour lesquels des contacts ont été créés. Cela peut inclure les comptes créés via des applications que vous avez installées. Cette autorisation permet aux applications d\'enregistrer les données liées à vos contacts. Des applications malveillantes peuvent exploiter cette fonctionnalité pour partager ces données à votre insu."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Permet à l\'application de lire les données liées aux contacts stockés sur votre appareil Android TV. Les applications auront également accès aux comptes de votre appareil Android TV pour lesquels des contacts ont été créés. Cela peut inclure les comptes créés via des applications que vous avez installées. Cette autorisation permet aux applications d\'enregistrer les données liées à vos contacts. Des applications malveillantes peuvent exploiter cette fonctionnalité pour partager ces données à votre insu."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Permet à l\'application de lire les données liées aux contacts stockés sur votre téléphone. Les applications auront également accès aux comptes de votre téléphone pour lesquels des contacts ont été créés. Cela peut inclure les comptes créés via des applications que vous avez installées. Cette autorisation permet aux applications d\'enregistrer les données liées à vos contacts. Des applications malveillantes peuvent exploiter cette fonctionnalité pour partager ces données à votre insu."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"modifier les contacts"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Permet à l\'application de modifier les données relatives aux contacts stockés sur votre tablette, y compris la fréquence à laquelle vous avez appelé des personnes spécifiques, leur avez envoyé des e-mails ou avez communiqué avec elles par d\'autres moyens. Cette autorisation permet aux applications de supprimer ces données."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Permet à l\'application de modifier les données liées aux contacts stockés sur votre appareil Android TV, y compris la fréquence à laquelle vous avez appelé des personnes spécifiques, leur avez envoyé des e-mails ou avez communiqué avec elles par d\'autres moyens. Cette autorisation permet aux applications de supprimer ces données."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Permet à l\'application de modifier les données relatives aux contacts stockés sur votre téléphone, y compris la fréquence à laquelle vous avez appelé des personnes spécifiques, leur avez envoyé des e-mails ou avez communiqué avec elles par d\'autres moyens. Cette autorisation permet aux applications de supprimer ces données."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Permet à l\'application de modifier les données liées aux contacts stockés sur votre tablette. Cette autorisation permet aux applications de supprimer ces données."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Permet à l\'application de modifier les données liées aux contacts stockés sur votre appareil Android TV. Cette autorisation permet aux applications de supprimer ces données."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Permet à l\'application de modifier les données liées aux contacts stockés sur votre téléphone. Cette autorisation permet aux applications de supprimer ces données."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"lire le journal d\'appels"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Cette application peut lire l\'historique de vos appels."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"modifier le journal d\'appels"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"Accès aux commandes de fournisseur de position géographique supplémentaires"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Permet à l\'application d\'accéder à des commandes de localisation supplémentaires offertes par le fournisseur. Elle est ainsi susceptible d\'interférer avec le bon fonctionnement du GPS ou de toute autre source de localisation."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"accéder à la position exacte au premier plan uniquement"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Cette application peut obtenir votre position exacte uniquement lorsqu\'elle s\'exécute au premier plan. Ces services de localisation doivent être activés et disponibles sur votre téléphone pour que l\'application puisse les utiliser. Ceci peut réduire l\'autonomie de la batterie."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"accéder à la position approximative (à l\'aide des réseaux) au premier plan uniquement"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Cette application peut obtenir votre position à l\'aide de sources de réseau telles que les antennes-relais et les réseaux Wi-Fi, mais uniquement lorsqu\'elle s\'exécute au premier plan. Ces services de localisation doivent être activés et disponibles sur votre tablette pour que l\'application puisse les utiliser."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Cette application peut obtenir votre position à l\'aide de sources de réseau telles que les antennes-relais et les réseaux Wi-Fi, mais uniquement lorsqu\'elle s\'exécute au premier plan. Ces services de localisation doivent être activés et disponibles sur votre appareil Android TV pour que l\'application puisse les utiliser."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Cette application peut obtenir votre position à l\'aide de sources de réseau telles que les antennes-relais et les réseaux Wi-Fi, mais uniquement lorsqu\'elle s\'exécute au premier plan. Ces services de localisation doivent être activés et disponibles sur votre téléphone pour que l\'application puisse les utiliser."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Cette application peut obtenir votre position exacte uniquement lorsqu\'elle s\'exécute au premier plan. Les services de localisation doivent être activés et disponibles sur votre appareil pour que l\'application puisse les utiliser. Ceci peut réduire l\'autonomie de la batterie."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"accéder à la position approximative au premier plan uniquement"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Cette application peut obtenir votre position approximative uniquement lorsqu\'elle s\'exécute au premier plan. Les services de localisation doivent être activés et disponibles sur votre appareil pour que l\'application puisse les utiliser."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"accéder à la position en arrière-plan"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Si vous lui accordez cette autorisation en plus de l\'accès à la position approximative ou précise, l\'application peut accéder à votre position lorsqu\'elle est s\'exécute en arrière-plan."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"En plus de l\'accès à la position en premier plan, cette application peut y accéder lorsqu\'elle s\'exécute en arrière-plan."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"modifier vos paramètres audio"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Permet à l\'application de modifier les paramètres audio généraux, tels que le volume et la sortie audio utilisée."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"enregistrer des fichiers audio"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Permet à l\'application d\'accéder à la configuration du Bluetooth sur la tablette, et d\'établir et accepter des connexions avec les appareils associés."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Permet à l\'application d\'afficher la configuration du Bluetooth sur votre appareil Android TV, de se connecter à des appareils associés et d\'accepter leur connexion."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Permet à l\'application d\'accéder à la configuration du Bluetooth sur le téléphone, et d\'établir et accepter des connexions avec les appareils associés."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Informations sur le service de paiement NFC préféré"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Permet à l\'application d\'obtenir des informations sur le service de paiement NFC préféré, y compris les ID d\'applications et les destinations de routage enregistrés."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"contrôler la communication en champ proche"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Permet à l\'application de communiquer avec des tags, des cartes et des lecteurs compatibles avec la technologie NFC (communication en champ proche)."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"Désactiver le verrouillage de l\'écran"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"Le raccourci d\'accessibilité a activé <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"Le raccourci d\'accessibilité a désactivé <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Appuyez de manière prolongée sur les deux touches de volume pendant trois secondes pour utiliser <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Choisissez un service à utiliser lorsque vous appuyez sur le bouton Accessibilité :"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Choisissez un service à utiliser avec le geste d\'accessibilité (balayez l\'écran de bas en haut avec deux doigts) :"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Choisissez un service à utiliser avec le geste d\'accessibilité (balayer l\'écran de bas en haut avec trois doigts) :"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Pour changer de service, appuyez de manière prolongée sur le bouton Accessibilité."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Pour changer de service, balayez l\'écran vers le haut avec deux doigts et appuyez de manière prolongée."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Pour changer de service, balayez l\'écran vers le haut avec trois doigts et appuyez de manière prolongée."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Agrandissement"</string>
<string name="user_switched" msgid="7249833311585228097">"Utilisateur actuel : <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="user_switching_message" msgid="1912993630661332336">"Chargement du profil de <xliff:g id="NAME">%1$s</xliff:g>..."</string>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Connecté à <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Appuyez ici pour voir les fichiers."</string>
<string name="pin_target" msgid="8036028973110156895">"Épingler"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Épingler <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Retirer"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Retirer <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Infos sur l\'appli"</string>
<string name="negative_duration" msgid="1938335096972945232">"− <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Lancement de la démo…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Mettre à jour les éléments <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> et <xliff:g id="TYPE_2">%3$s</xliff:g> dans "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" ?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Enregistrer"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Non, merci"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Pas maintenant"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Jamais"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Mettre à jour"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Continuer"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"mot de passe"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Activer/Désactiver l\'écran partagé"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Verrouiller l\'écran"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Capture d\'écran"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"Application <xliff:g id="APP_NAME">%1$s</xliff:g> dans la fenêtre pop-up."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Barre de légende de l\'application <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index 4572db728bc0..eebe5ab20185 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Falta a aplicación de administración do perfil de traballo ou ben está danada. Como resultado, eliminouse o teu perfil de traballo e os datos relacionados. Para obter asistencia, contacta co administrador."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"O teu perfil de traballo xa non está dispoñible neste dispositivo"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Demasiados intentos de introdución do contrasinal"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"O administrador renunciou ao dispositivo para uso persoal"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"O dispositivo está xestionado"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"A túa organización xestiona este dispositivo e pode controlar o tráfico de rede. Toca para obter máis detalles."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Borrarase o teu dispositivo"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Permite que a aplicación envíe emisións permanentes que continúan unha vez finalizada a emisión. Un uso excesivo pode provocar que o dispositivo Android TV funcione con lentitude ou de forma inestable debido á necesidade de utilizar demasiada memoria."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Permite á aplicación enviar difusións permanentes que continúan unha vez finalizada a difusión. Un uso excesivo pode provocar que o teléfono funcione con lentitude ou de forma inestable debido á necesidade de utilizar demasiada memoria."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"ler os teus contactos"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Permite á aplicación ler datos acerca dos teus contactos almacenados na tableta, incluída a frecuencia coa que os chamaches, lles enviaches un correo electrónico ou te comunicaches con individuos específicos doutras formas. Con este permiso as aplicacións poden gardar os teus datos de contacto e as aplicacións maliciosas poden compartir os datos de contacto sen o teu coñecemento."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Permite que a aplicación lea datos acerca dos contactos que tes almacenados no dispositivo Android TV, incluída a frecuencia coa que lles chamaches, lles enviaches un correo electrónico ou te comunicaches con individuos específicos doutras formas. Con este permiso as aplicacións poden gardar os teus datos de contacto e as aplicacións maliciosas poden compartir os datos de contacto sen o teu coñecemento."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Permite á aplicación ler datos acerca dos teus contactos almacenados no teléfono, incluída a frecuencia coa que os chamaches, lles enviaches un correo electrónico ou te comunicaches con individuos específicos doutras formas. Con este permiso as aplicacións poden gardar os teus datos de contacto e as aplicacións maliciosas poden compartir os datos de contacto sen o teu coñecemento."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Permite que a aplicación lea datos sobre os contactos almacenados na túa tableta. As aplicacións tamén terán acceso ás contas da túa tableta que creasen contactos, entre as que se poden incluír as creadas polas aplicacións que instalases. Con este permiso as aplicacións poden gardar os teus datos de contacto e as aplicacións maliciosas poden compartir os datos mencionados sen o teu coñecemento."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Permite que a aplicación lea datos sobre os contactos almacenados no teu dispositivo Android TV. As aplicacións tamén terán acceso ás contas do teu dispositivo Android TV que creasen contactos, entre as que se poden incluír as creadas polas aplicacións que instalases. Con este permiso as aplicacións poden gardar os teus datos de contacto e as aplicacións maliciosas poden compartir os datos mencionados sen o teu coñecemento."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Permite que a aplicación lea datos sobre os contactos almacenados no teu teléfono. As aplicacións tamén terán acceso ás contas do teu teléfono que creasen contactos, entre as que se poden incluír as creadas polas aplicacións que instalases. Con este permiso as aplicacións poden gardar os teus datos de contacto e as aplicacións maliciosas poden compartir os datos mencionados sen o teu coñecemento."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"modificar os teus contactos"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Permite á aplicación modificar os datos acerca dos teus contactos almacenados na tableta, incluído a frecuencia coa que os chamaches, lles enviaches un correo electrónico ou te comunicaches con contactos específicos doutras formas. Con este permiso as aplicacións poden eliminar datos de contactos."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Permite que a aplicación modifique os datos sobre os contactos almacenados no dispositivo Android TV, incluída a frecuencia coa que lles chamaches, lles enviaches un correo electrónico ou te comunicaches con eles doutra forma. Con este permiso as aplicacións poden eliminar datos de contactos."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Permite á aplicación modificar os datos acerca dos teus contactos almacenados no teléfono, incluída a frecuencia coa que chamaches, enviaches correos electrónicos ou te comunicaches doutras maneiras con contactos específicos. Con este permiso as aplicacións poden eliminar datos de contactos."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Permite que a aplicación modifique datos sobre os contactos almacenados na túa tableta. Con este permiso as aplicacións poden eliminar datos de contactos."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Permite que a aplicación modifique datos sobre os contactos almacenados no teu dispositivo Android TV. Con este permiso as aplicacións poden eliminar datos de contactos."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Permite que a aplicación modifique datos sobre os contactos almacenados no teu teléfono. Con este permiso as aplicacións poden eliminar datos de contactos."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"ler rexistro de chamadas"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Esta aplicación pode ler o teu historial de chamadas."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"escribir no rexistro de chamadas"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"acceder a comandos adicionais do provedor de localización"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Permite á aplicación acceder a comandos adicionais de fornecedor de localizacións. É posible que isto provoque que a aplicación interfira co funcionamento do GPS ou doutras fontes da localización."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"acceder á localización exacta só en primeiro plano"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Esta aplicación pode obter a túa localización exacta só cando se atope en primeiro plano. É necesario activar estes servizos de localización e deben estar dispoñibles no teléfono para que a aplicación poida utilizalos. Ademais, poden supoñer un aumento do consumo de batería."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"acceder á localización aproximada a partir de fontes de rede só en primeiro plano"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Esta aplicación pode obter a túa localización a partir de fontes de rede, como torres de telecomunicacións e redes wifi, pero só mentres está en primeiro plano. Para que a aplicación poida utilizar os servizos de localización, deben estar activados e dispoñibles na túa tableta."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Esta aplicación pode obter a túa localización a partir de fontes de rede, como antenas de telefonía móbil e redes wifi, pero só mentres está en primeiro plano. É necesario activar estes servizos de localización e deben estar dispoñibles no dispositivo Android TV para que a aplicación poida utilizalos."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Esta aplicación pode obter a túa localización a partir de fontes de rede, como torres de telecomunicacións e redes wifi, pero só mentres está en primeiro plano. Para que a aplicación poida utilizar os servizos de localización, deben estar activados e dispoñibles no teu teléfono."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Esta aplicación pode obter a túa localización exacta só cando se atope en primeiro plano. É necesario activar os servizos de localización e deben estar dispoñibles no teléfono para que a aplicación poida utilizalos. Ademais, poden supoñer un aumento do consumo de batería."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"acceder á localización aproximada só en primeiro plano"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Esta aplicación pode obter a túa localización aproximada, pero só mentres está en primeiro plano. Para que a aplicación poida utilizar os servizos de localización, deben estar activados e dispoñibles no teu dispositivo."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"acceder á localización en segundo plano"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Se a aplicación ten acceso á localización aproximada ou exacta e lle concedes este permiso, poderá consultar onde te atopas cando estea en segundo plano."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Esta aplicación pode acceder á localización mentres se executa en segundo plano, ademais de acceder á localización en primeiro plano."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"cambiar a configuración de son"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Permite á aplicación modificar a configuración de audio global, como o volume e que altofalante se utiliza para a saída."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"gravar audio"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Permite á aplicación ver a configuración do Bluetooth na tableta e efectuar e aceptar conexións con dispositivos sincronizados."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Permite que a aplicación consulte a configuración do Bluetooth no dispositivo Android TV, e efectúe e acepte conexións con dispositivos vinculados."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Permite á aplicación ver a configuración do Bluetooth no teléfono e efectuar e aceptar conexións con dispositivos sincronizados."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Información do servizo de pago de NFC preferido"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Permite que a aplicación obteña información do servizo de pago de NFC preferido, como as axudas rexistradas e o destino da ruta."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"controlar Near Field Communication"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Permite á aplicación comunicarse con etiquetas, tarxetas e lectores Near Field Communication (NFC)."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"desactivar o bloqueo da pantalla"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"O atallo de accesibilidade activou <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"O atallo de accesibilidade desactivou <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Mantén premidas as teclas do volume durante tres segudos para usar <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Escolle o servizo que queres utilizar cando toques o botón de accesibilidade:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Escolle o servizo que queres usar co xesto de accesibilidade (pasa dous dedos cara arriba desde a parte inferior da pantalla):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Escolle o servizo que queres usar co xesto de accesibilidade (pasa tres dedos cara arriba desde a parte inferior da pantalla):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Para cambiar de servizo, mantén premido o botón de accesibilidade."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Para cambiar de servizo, pasa dous dedos cara arriba e mantén premida a pantalla."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Para cambiar de servizo, pasa tres dedos cara arriba pola pantalla e mantén premido."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Ampliación"</string>
<string name="user_switched" msgid="7249833311585228097">"Usuario actual <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="1912993630661332336">"Cambiando a <xliff:g id="NAME">%1$s</xliff:g>…"</string>
@@ -1759,8 +1752,8 @@
<string name="confirm_battery_saver" msgid="5247976246208245754">"Aceptar"</string>
<string name="battery_saver_description_with_learn_more" msgid="1817385558636532621">"Para aumentar a duración da batería, a función Aforro de batería fai o seguinte:\n·Activa o tema escuro\n·Desactiva ou restrinxe a actividade en segundo plano, algúns efectos visuais e outras funcións, como \"Ok Google\"\n\n"<annotation id="url">"Máis información"</annotation></string>
<string name="battery_saver_description" msgid="7618492104632328184">"Para aumentar a duración da batería, a función Aforro de batería fai o seguinte:\n·Activa o tema escuro\n·Desactiva ou restrinxe a actividade en segundo plano, algúns efectos visuais e outras funcións, como \"Ok Google\""</string>
- <string name="data_saver_description" msgid="4995164271550590517">"Para contribuír a reducir o uso de datos, o Economizador de datos impide que algunhas aplicacións envíen ou reciban datos en segundo plano. Cando esteas utilizando unha aplicación, esta poderá acceder aos datos, pero é posible que o faga con menos frecuencia. Por exemplo, é posible que as imaxes non se mostren ata que as toques."</string>
- <string name="data_saver_enable_title" msgid="7080620065745260137">"Queres activar o economizador de datos?"</string>
+ <string name="data_saver_description" msgid="4995164271550590517">"Para contribuír a reducir o uso de datos, o aforro de datos impide que algunhas aplicacións envíen ou reciban datos en segundo plano. Cando esteas utilizando unha aplicación, esta poderá acceder aos datos, pero é posible que o faga con menos frecuencia. Por exemplo, é posible que as imaxes non se mostren ata que as toques."</string>
+ <string name="data_saver_enable_title" msgid="7080620065745260137">"Queres activar o aforro de datos?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Activar"</string>
<plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="2877101784123058273">
<item quantity="other">Durante %1$d minutos (ata as <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Conectado a <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Toca para ver os ficheiros"</string>
<string name="pin_target" msgid="8036028973110156895">"Fixar"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Fixar a <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Deixar de fixar"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Deixar de fixar a <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Info. da aplicación"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Iniciando demostración…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Queres actualizar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g> en "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Gardar"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Non, grazas"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Agora non"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Nunca"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Actualizar"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Continuar"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"contrasinal"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Activar/desactivar pantalla dividida"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Pantalla de bloqueo"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Captura de pantalla"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"Aplicación <xliff:g id="APP_NAME">%1$s</xliff:g> nunha ventá emerxente."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Barra de subtítulos de <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 5e4f753f4018..869a7528dda6 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"કાર્ય પ્રોફાઇલ વ્યવસ્થાપક ઍપ્લિકેશન ખૂટે છે અથવા તો દૂષિત છે. પરિણામે, તમારી કાર્યાલયની પ્રોફાઇલ અને તે સંબંધિત ડેટા કાઢી નાખવામાં આવ્યો છે. સહાયતા માટે તમારા વ્યવસ્થાપકનો સંપર્ક કરો."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"આ ઉપકરણ પર તમારી કાર્યાલયની પ્રોફાઇલ હવે ઉપલબ્ધ નથી"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"પાસવર્ડના ઘણા વધુ પ્રયત્નો"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"વ્યવસ્થાપકે ડિવાઇસ વ્યક્તિગત ઉપયોગ માટે આપી દીધું છે"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"ઉપકરણ સંચાલિત છે"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"તમારી સંસ્થા આ ઉપકરણનું સંચાલન કરે છે અને નેટવર્ક ટ્રાફિફનું નિયમન કરી શકે છે. વિગતો માટે ટૅપ કરો."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"તમારું ઉપકરણ કાઢી નાખવામાં આવશે"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"ઍપને સ્ટીકી બ્રોડકાસ્ટ મોકલવાની મંજૂરી આપે છે, જે બ્રોડકાસ્ટ સમાપ્ત થયા પછી પણ રહે છે. અતિશય ઉપયોગ તમારા Android TV ડિવાઇસને વધુ પડતી મેમરીનો ઉપયોગ કરવાને કારણે તેને ધીમું અથવા અસ્થિર બનાવી શકે છે."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"એપ્લિકેશનને સ્ટિકી બ્રોડકાસ્ટ્સ મોકલવાની મંજૂરી આપે છે, જે બ્રોડકાસ્ટ્સ સમાપ્ત થયા પછી પણ રહે છે. અતિરિક્ત ઉપયોગ ફોનને વધુ પડતી મેમરીનો ઉપયોગ કરવાને કારણે તેને ધીમું અથવા અસ્થિર બનાવી શકે છે."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"તમારા સંપર્કો વાંચો"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"એપ્લિકેશનને તમે કઈ આવૃત્તિ પર કૉલ કર્યો, ઇમેઇલ કરી અથવા વિશિષ્ટ વ્યક્તિઓ સાથે અન્ય રીતે સંચાર કર્યો તે સહિત તમારા ટેબ્લેટ પર સંગ્રહિત તમારા સંપર્કો વિશેનો ડેટા વાંચવાની મંજૂરી આપે છે. આ પરવાનગી ઍપ્લિકેશનોને તમારો સંપર્ક ડેટા સાચવવાની મંજૂરી આપે છે અને દુર્ભાવનાપૂર્ણ ઍપ્લિકેશનો તમારી જાણ વગર સંપર્ક ડેટાને શેર કરી શકે છે."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"ઍપને તમે કઈ આવૃત્તિ પર કૉલ કર્યો, ઇમેઇલ કર્યો અથવા વિશિષ્ટ વ્યક્તિઓ સાથે અન્ય રીતે સંચાર કર્યો તે સહિત તમારા Android TV ડિવાઇસ પર સંગ્રહિત તમારા સંપર્કો વિશેનો ડેટા વાંચવાની મંજૂરી આપે છે. આ પરવાનગી ઍપને તમારો સંપર્ક ડેટા સાચવવાની મંજૂરી આપે છે અને દુર્ભાવનાપૂર્ણ ઍપ તમારી જાણ વગર સંપર્ક ડેટા શેર કરી શકે છે."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"એપ્લિકેશનને તમે કઈ આવૃત્તિ પર કૉલ કર્યો, ઇમેઇલ કરી અથવા વિશિષ્ટ વ્યક્તિઓ સાથે અન્ય રીતે સંચાર કર્યો તે સહિત તમારા ફોન પર સંગ્રહિત તમારા સંપર્કો વિશેનો ડેટા વાંચવાની મંજૂરી આપે છે. આ પરવાનગી ઍપ્લિકેશનોને તમારો સંપર્ક ડેટા સાચવવાની મંજૂરી આપે છે અને દુર્ભાવનાપૂર્ણ ઍપ્લિકેશનો તમારી જાણ વગર સંપર્ક ડેટાને શેર કરી શકે છે."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"ઍપને તમારા ટૅબ્લેટમાં સ્ટોર કરેલા તમારા સંપર્કો વિશેનો ડેટા વાંચવાની મંજૂરી આપે છે. ઍપને તમારા ટૅબ્લેટ પર સંપર્કો બનાવનારાં એકાઉન્ટનો પણ ઍક્સેસ રહેશે. તેમાં તમે ઇન્સ્ટૉલ કરેલી ઍપ દ્વારા બનાવાયેલાં એકાઉન્ટનો પણ સમાવેશ થઈ શકે છે. આ પરવાનગી ઍપને તમારા સંપર્કનો ડેટા સાચવવાની મંજૂરી આપે છે અને દુર્ભાવનાપૂર્ણ ઍપ તમારી જાણ બહાર સંપર્કનો ડેટા શેર કરે તેમ બની શકે છે."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"ઍપને તમારા Android TV ડિવાઇસમાં સ્ટોર કરેલા તમારા સંપર્કો વિશેનો ડેટા વાંચવાની મંજૂરી આપે છે. ઍપને તમારા Android TV ડિવાઇસ પર સંપર્કો બનાવનારાં એકાઉન્ટનો પણ ઍક્સેસ રહેશે. તેમાં તમે ઇન્સ્ટૉલ કરેલી ઍપ દ્વારા બનાવાયેલાં એકાઉન્ટનો પણ સમાવેશ થઈ શકે છે. આ પરવાનગી ઍપને તમારા સંપર્કનો ડેટા સાચવવાની મંજૂરી આપે છે અને દુર્ભાવનાપૂર્ણ ઍપ તમારી જાણ બહાર સંપર્કનો ડેટા શેર કરે તેમ બની શકે છે."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"ઍપને તમારા ફોનમાં સ્ટોર કરેલા તમારા સંપર્કો વિશેનો ડેટા વાંચવાની મંજૂરી આપે છે. ઍપને તમારા ફોન પર સંપર્કો બનાવનારાં એકાઉન્ટનો પણ ઍક્સેસ રહેશે. તેમાં તમે ઇન્સ્ટૉલ કરેલી ઍપ દ્વારા બનાવાયેલાં એકાઉન્ટનો પણ સમાવેશ થઈ શકે છે. આ પરવાનગી ઍપને તમારા સંપર્કનો ડેટા સાચવવાની મંજૂરી આપે છે અને દુર્ભાવનાપૂર્ણ ઍપ તમારી જાણ બહાર સંપર્કનો ડેટા શેર કરે તેમ બની શકે છે."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"તમારા સંપર્કો સંશોધિત કરો"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"એપ્લિકેશનને તમે કઈ આવૃત્તિ પર કૉલ કર્યો, ઇમેઇલ કરી અથવા વિશિષ્ટ સંપર્કો સાથે અન્ય રીતે સંચાર કર્યો તે સહિત તમારા ટેબ્લેટ પર સંગ્રહિત તમારા સંપર્કો વિશેનો ડેટા સંશોધિત કરવાની મંજૂરી આપે છે. આ પરવાનગી એપ્લિકેશન્સને સંપર્ક ડેટા કાઢી નાખવાની મંજૂરી આપે છે."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"ઍપને તમે કઈ આવૃત્તિ પર કૉલ કર્યો, ઇમેઇલ કર્યો અથવા વિશિષ્ટ સંપર્કો સાથે અન્ય રીતે સંચાર કર્યો તે સહિત તમારા Android TV ડિવાઇસ પર સંગ્રહિત તમારા સંપર્કો વિશેનો ડેટા સંશોધિત કરવાની મંજૂરી આપે છે. આ પરવાનગી ઍપને સંપર્ક ડેટા ડિલીટ કરવાની મંજૂરી આપે છે."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"એપ્લિકેશનને તમે કઈ આવૃત્તિ પર કૉલ કર્યો, ઇમેઇલ કરી અથવા વિશિષ્ટ સંપર્કો સાથે અન્ય રીતે સંચાર કર્યો તે સહિત તમારા ફોન પર સંગ્રહિત તમારા સંપર્કો વિશેનો ડેટા સંશોધિત કરવાની મંજૂરી આપે છે. આ પરવાનગી એપ્લિકેશન્સને સંપર્ક ડેટા કાઢી નાખવાની મંજૂરી આપે છે."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"ઍપને તમારા ટૅબ્લેટ પર સ્ટોર કરેલા તમારા સંપર્કો વિશેનો ડેટા સંશોધિત કરવાની મંજૂરી આપે છે. આ પરવાનગી ઍપને સંપર્ક ડેટા ડિલીટ કરવાની મંજૂરી આપે છે."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"ઍપને તમારા Android TV ડિવાઇસ પર સ્ટોર કરેલા તમારા સંપર્કો વિશેનો ડેટા સંશોધિત કરવાની મંજૂરી આપે છે. આ પરવાનગી ઍપને સંપર્ક ડેટા ડિલીટ કરવાની મંજૂરી આપે છે."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"ઍપને તમારા ફોનમાં સ્ટોર કરેલા તમારા સંપર્કો વિશેનો ડેટા સંશોધિત કરવાની મંજૂરી આપે છે. આ પરવાનગી ઍપને સંપર્ક ડેટા ડિલીટ કરવાની મંજૂરી આપે છે."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"કૉલ લૉગ વાંચો"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"આ ઍપ્લિકેશન, તમારો કૉલ ઇતિહાસ વાંચી શકે છે."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"કૉલ લૉગ લખો"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"વધારાના સ્થાન પ્રદાતા આદેશોને ઍક્સેસ કરો"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"એપ્લિકેશનને વધારાના સ્થાન પ્રદાતા આદેશોને ઍક્સેસ કરવાની મંજૂરી આપે છે. આ એપ્લિકેશનને GPS અથવા અન્ય સ્થાન સ્રોતોના ઓપરેશનમાં દખલ કરવાની મંજૂરી આપી શકે છે."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"ફૉરગ્રાઉન્ડમાં ફક્ત ચોક્કસ સ્થાન ઍક્સેસ કરો"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"આ ઍપ ફક્ત બૅકગ્રાઉન્ડમાં હોય ત્યારે જ તમારું ચોક્કસ સ્થાન મેળવી શકે છે. ઍપ આ સ્થાન સેવાઓનો ઉપયોગ કરી શકે તે માટે તમારા ફોન પર આ સેવાઓ ઉપલબ્ધ અને ચાલુ હોવી આવશ્યક છે. આ બૅટરી વપરાશ વધારી શકે છે."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"અંદાજિત જગ્યાને (નેટવર્ક આધારિત) માત્ર ફૉરગ્રાઉન્ડમાંથી ઍક્સેસ કરો"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"સેલ ટાવર અને વાઇ-ફાઇ નેટવર્ક જેવા નેટવર્ક સૉર્સનો ઉપયોગ કરીને આ અ‍ૅપ તમારી જગ્યા જાણી શકે છે, પરંતુ આ માત્ર ત્યારે શક્ય છે જ્યારે આ અ‍ૅપ ફૉરગ્રાઉન્ડમાં ચાલુ હોય. ઍપ આ જગ્યાની સેવાઓનો ઉપયોગ કરી શકે તે માટે તમારા ટૅબ્લેટ પર આ સેવાઓ ઉપલબ્ધ અને ચાલુ હોવી આવશ્યક છે."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"સેલ ટાવર અને વાઇ-ફાઇ નેટવર્ક જેવા નેટવર્ક સૉર્સનો ઉપયોગ કરીને આ ઍપ તમારું સ્થાન જાણી શકે છે, પરંતુ આ માત્ર ત્યારે શક્ય છે જ્યારે આ ઍપ ફૉરગ્રાઉન્ડમાં ચાલુ હોય. ઍપ આ સ્થાન સેવાઓનો ઉપયોગ કરી શકે તે માટે તમારા Android TV ડિવાઇસ પર આ સેવાઓ ઉપલબ્ધ અને ચાલુ હોવી જરૂરી છે."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"સેલ ટાવર અને વાઇ-ફાઇ નેટવર્ક જેવા નેટવર્ક સૉર્સનો ઉપયોગ કરીને આ અ‍ૅપ તમારી જગ્યા જાણી શકે છે, પરંતુ આ માત્ર ત્યારે શક્ય છે જ્યારે આ અ‍ૅપ ફૉરગ્રાઉન્ડમાં ચાલુ હોય. ઍપ આ જગ્યાની સેવાઓનો ઉપયોગ કરી શકે તે માટે તમારા ફોન પર આ સેવાઓ ઉપલબ્ધ અને ચાલુ હોવી આવશ્યક છે."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"આ ઍપ ફક્ત ફૉરગ્રાઉન્ડમાંમાં હોય ત્યારે જ તમારું ચોક્કસ સ્થાન મેળવી શકે છે. ઍપ આ સ્થાન સેવાઓનો ઉપયોગ કરી શકે તે માટે તે સેવાઓ ચાલુ કરેલી અને તમારા ડિવાઇસમાં ઉપલબ્ધ હોવી જોઈએ. આ બૅટરી વપરાશ વધારી શકે છે."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"ફૉરગ્રાઉન્ડમાં ફક્ત અંદાજિત સ્થાન ઍક્સેસ કરો"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"આ ઍપ ફોરગ્રાઉન્ડમાં હોય, ત્યારે જ તે તમારું અંદાજિત સ્થાન મેળવી શકે છે. ઍપ આ સ્થાન સેવાઓનો ઉપયોગ કરી શકે તે માટે તે સેવાઓ ચાલુ કરેલી અને તમારા ડિવાઇસમાં ઉપલબ્ધ હોવી જોઈએ."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"બૅકગ્રાઉન્ડમાં સ્થાન ઍક્સેસ કરો"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"જો અંદાજિત અથવા ચોક્કસ સ્થાનના ઍક્સેસ ઉપરાંત આને પરવાનગી આપવામાં આવી હશે, તો ઍપ બૅકગ્રાઉન્ડમાં ચાલતી હોય ત્યારે સ્થાનને ઍક્સેસ કરી શકશે."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"આ ઍપ ફૉરગ્રાઉન્ડમાં સ્થાનને ઍક્સેસ કરવા ઉપરાંત બૅકગ્રાઉન્ડમાં ચાલતી હોય ત્યારે પણ સ્થાનને ઍક્સેસ કરી શકે છે."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"તમારી ઑડિઓ સેટિંગ્સ બદલો"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"એપ્લિકેશનને વૈશ્વિક ઑડિઓ સેટિંગ્સને સંશોધિત કરવાની મંજૂરી આપે છે, જેમ કે વૉલ્યૂમ અને આઉટપુટ માટે કયા સ્પીકરનો ઉપયોગ કરવો."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"ઑડિઓ રેકોર્ડ કરવાની"</string>
@@ -494,6 +491,8 @@
<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_preferredPaymentInfo" msgid="5274423844767445054">"પસંદગીની NFC ચુકવણીની સેવા વિશે માહિતી"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"આ મંજૂરીને આપવાથી, ઍપ તમારી પસંદગીની NFC ચુકવણીની સેવા વિશે માહિતી મેળવી શકે છે, જેમ કે રજિસ્ટર થયેલી સહાય અને નિર્ધારિત સ્થાન."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"નિઅર ફીલ્ડ કમ્યુનિકેશન નિયંત્રિત કરો"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"ઍપ્લિકેશનને નિઅર ફીલ્ડ કમ્યુનિકેશન (NFC) ટૅગ, કાર્ડ અને રીડર સાથે સંચાર કરવાની મંજૂરી આપે છે."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"તમારું સ્ક્રીન લૉક અક્ષમ કરો"</string>
@@ -900,7 +899,7 @@
<string name="factorytest_no_action" msgid="339252838115675515">"FACTORY_TEST ક્રિયા પ્રદાન કરનાર કોઈ પૅકેજ મળ્યું નહોતું."</string>
<string name="factorytest_reboot" msgid="2050147445567257365">"રીબૂટ કરો"</string>
<string name="js_dialog_title" msgid="7464775045615023241">"\"<xliff:g id="TITLE">%s</xliff:g>\" પરનું પૃષ્ઠ કહે છે કે:"</string>
- <string name="js_dialog_title_default" msgid="3769524569903332476">"Javascript"</string>
+ <string name="js_dialog_title_default" msgid="3769524569903332476">"JavaScript"</string>
<string name="js_dialog_before_unload_title" msgid="7012587995876771246">"નેવિગેશનની પુષ્ટિ કરો"</string>
<string name="js_dialog_before_unload_positive_button" msgid="4274257182303565509">"આ પૃષ્ઠ છોડો"</string>
<string name="js_dialog_before_unload_negative_button" msgid="3873765747622415310">"આ પૃષ્ઠ પર રહો"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"ઍક્સેસિબિલિટી શૉર્ટકટે <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ચાલુ કરી"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"ઍક્સેસિબિલિટી શૉર્ટકટે <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>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"જ્યારે તમે ઍક્સેસિબિલિટી બટન પર ટૅપ કરો, ત્યારે ઉપયોગ કરવાની સેવા પસંદ કરો:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"ઍક્સેસિબિલિટી સંકેત સાથે ઉપયોગ કરવાની સેવા પસંદ કરો (બે આંગળીઓ વડે સ્ક્રીનના નીચેના ભાગથી ઉપરની તરફ સ્વાઇપ કરવા માટે):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"ઍક્સેસિબિલિટી સંકેત સાથે ઉપયોગ કરવાની સેવા પસંદ કરો (ત્રણ આંગળીઓ વડે સ્ક્રીનના નીચેના ભાગથી ઉપરની તરફ સ્વાઇપ કરવા માટે):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"કોઈ એક સેવાથી બીજી સેવા પર સ્વિચ કરવા માટે, ઍક્સેસિબિલિટી બટનને ટચ કરીને દબાવી રાખો."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"કોઈ એક સેવાથી બીજી સેવા પર સ્વિચ કરવા માટે, બે આંગળીઓ વડે સ્ક્રીનની ઉપરની તરફ સ્વાઇપ કરીને દબાવી રાખો."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"કોઈ એક સેવાથી બીજી સેવા પર સ્વિચ કરવા માટે, ત્રણ આંગળીઓ વડે સ્ક્રીનની ઉપરની તરફ સ્વાઇપ કરીને દબાવી રાખો."</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>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> થી કનેક્ટ કરેલું છે"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"ફાઇલો જોવા માટે ટૅપ કરો"</string>
<string name="pin_target" msgid="8036028973110156895">"પિન"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"<xliff:g id="LABEL">%1$s</xliff:g>ને પિન કરો"</string>
<string name="unpin_target" msgid="3963318576590204447">"અનપિન કરો"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"<xliff:g id="LABEL">%1$s</xliff:g>ને અનપિન કરો"</string>
<string name="app_info" msgid="6113278084877079851">"ઍપ્લિકેશન માહિતી"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"ડેમો પ્રારંભ કરી રહ્યાં છે…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291"><b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"માંની: <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> બાબતોને અપડેટ કરીએ?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"સાચવો"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"ના, આભાર"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"હમણાં નહીં"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"ક્યારેય નહીં"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"અપડેટ કરો"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"ચાલુ રાખો"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"પાસવર્ડ"</string>
@@ -1972,7 +1969,7 @@
<string name="mime_type_audio" msgid="4933450584432509875">"ઑડિયો"</string>
<string name="mime_type_audio_ext" msgid="2615491023840514797">"<xliff:g id="EXTENSION">%1$s</xliff:g> ઑડિયો"</string>
<string name="mime_type_video" msgid="7071965726609428150">"વીડિયો"</string>
- <string name="mime_type_video_ext" msgid="185438149044230136">"<xliff:g id="EXTENSION">%1$s</xliff:g> વીડિઓ"</string>
+ <string name="mime_type_video_ext" msgid="185438149044230136">"<xliff:g id="EXTENSION">%1$s</xliff:g> વીડિયો"</string>
<string name="mime_type_image" msgid="2134307276151645257">"છબી"</string>
<string name="mime_type_image_ext" msgid="5743552697560999471">"<xliff:g id="EXTENSION">%1$s</xliff:g> છબી"</string>
<string name="mime_type_compressed" msgid="8737300936080662063">"આર્કાઇવ"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"સ્ક્રીનને વિભાજિત કરવાની ક્રિયા ટૉગલ કરો"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"લૉક સ્ક્રીન"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"સ્ક્રીનશૉટ"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"પૉપ-અપ વિંડોમાં <xliff:g id="APP_NAME">%1$s</xliff:g> ઍપ."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g>નું કૅપ્શન બાર."</string>
</resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index eecfd5b500db..6928a14b70a3 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"वर्क प्रोफ़ाइल व्यवस्थापक ऐप्लिकेशन या तो मौजूद नहीं है या वह खराब हो गया है. परिणामस्वरूप, आपकी वर्क प्रोफ़ाइल और उससे जुड़े डेटा को हटा दिया गया है. सहायता के लिए अपने व्यवस्थापक से संपर्क करें."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"आपकी वर्क प्रोफ़ाइल अब इस डिवाइस पर उपलब्‍ध नहीं है"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"कई बार गलत पासवर्ड डाला गया"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"एडमिन ने निजी इस्तेमाल के लिए डिवाइस दे दिया है"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"डिवाइस प्रबंधित है"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"आपका संगठन इस डिवाइस का प्रबंधन करता है और वह नेटवर्क ट्रैफ़िक की निगरानी भी कर सकता है. विवरण के लिए टैप करें."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"आपके डिवाइस को मिटा दिया जाएगा"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"यह ऐप्लिकेशन को स्टिकी ब्रॉडकास्ट भेजने की अनुमति देता है जो ब्रॉडकास्ट खत्म होने के बाद भी बने रहते हैं. इस सुविधा के ज़्यादा इस्तेमाल से आपके Android TV डिवाइस की मेमोरी कम हो सकती है जिससे टीवी की परफ़ॉर्मेंस पर असर पड़ सकता है और उसे इस्तेमाल करने में समस्याएं आ सकती हैं."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"ऐप्स को स्‍टिकी प्रसारण भेजने देता है, जो प्रसारण खत्म होने के बाद भी बने रहते हैं. अत्यधिक उपयोग, फ़ोन की बहुत ज़्यादा मेमोरी का उपयोग करके उसे धीमा या अस्‍थिर कर सकता है."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"अपने संपर्क पढ़ें"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"ऐप को आपके टैबलेट पर मौजूद आपके संपर्कों का डेटा पढ़ने देती है, जिसमें ये भी शामिल है कि आपने कुछ ख़ास लोगों से कितनी बार कॉल, ईमेल, या कुछ और तरीकों से बातचीत की. यह अनुमति ऐप को आपका संपर्क डेटा सेव करने देती है और धोखा देने वाले ऐप संपर्क डेटा को आपकी जानकारी के बिना शेयर कर सकते हैं."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"यह ऐप्लिकेशन को आपके Android TV डिवाइस पर सेव किए हुए संपर्कों के डेटा में बदलाव करने की अनुमति देता है. साथ ही, संपर्क में शामिल कुछ खास लोगों को आप कितना कॉल करते हैं, कितने ईमेल भेजते हैं या संपर्क करने के दूसरे तरीकों का कितना इस्तेमाल करते हैं, इससे जुड़ी जानकारी भी हासिल कर सकता है. यह अनुमति देने के बाद ऐप्लिकेशन आपके संपर्क का डेटा सेव कर सकता है. हालांकि, नुकसान पहुंचाने वाले ऐप्लिकेशन, बिना आपको बताए संपर्क से जुड़ा डेटा शेयर कर सकते हैं."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"ऐप को आपके फ़ोन पर मौजूद आपके संपर्कों का डेटा पढ़ने देती है, जिसमें ये भी शामिल है कि आपने कुछ ख़ास लोगों से कितनी बार कॉल, ईमेल, या कुछ और तरीकों से बातचीत की. यह अनुमति ऐप को आपका संपर्क डेटा सेव करने देती है और धोखा देने वाले ऐप, संपर्क डेटा को आपकी जानकारी के बिना शेयर कर सकते हैं."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"यह ऐप्लिकेशन को आपके टैबलेट पर मौजूद संपर्कों का डेटा देखने की अनुमति देता है. ऐप्लिकेशन को आपके टैबलेट पर मौजूद उन खातों को ऐक्सेस करने की अनुमति भी होगी जिनसे संपर्क बनाए गए हैं. इसमें वे खाते भी शामिल हो सकते हैं जिन्हें आपके इंस्टॉल किए हुए ऐप्लिकेशन ने बनाया है. इस अनुमति के बाद, ऐप्लिकेशन आपके संपर्कों का डेटा सेव कर सकते हैं. हालांकि, नुकसान पहुंचाने वाले ऐप्लिकेशन, आपको बताए बिना ही संपर्कों का डेटा शेयर कर सकते हैं."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"यह ऐप्लिकेशन को आपके Android TV डिवाइस पर सेव किए संपर्कों का डेटा देखने की अनुमति देता है. ऐप्लिकेशन को आपके Android TV डिवाइस पर मौजूद उन खातों को ऐक्सेस करने की अनुमति भी होगी जिनसे संपर्क बनाए गए हैं. इसमें वे खाते भी शामिल हो सकते हैं जिन्हें आपके इंस्टॉल किए हुए ऐप्लिकेशन ने बनाया है. इस अनुमति के बाद, ऐप्लिकेशन आपके संपर्कों का डेटा सेव कर सकते हैं. हालांकि, नुकसान पहुंचाने वाले ऐप्लिकेशन, आपको बताए बिना ही संपर्कों का डेटा शेयर कर सकते हैं."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"यह ऐप्लिकेशन को आपके फ़ोन पर मौजूद संपर्कों का डेटा देखने की अनुमति देता है. ऐप्लिकेशन को आपके फ़ोन पर मौजूद उन खातों को ऐक्सेस करने की अनुमति भी होगी जिनसे संपर्क बनाए गए हैं. इसमें वे खाते भी शामिल हो सकते हैं जिन्हें आपके इंस्टॉल किए हुए ऐप्लिकेशन ने बनाया है. इस अनुमति के बाद, ऐप्लिकेशन आपके संपर्कों का डेटा सेव कर सकते हैं. हालांकि, नुकसान पहुंचाने वाले ऐप्लिकेशन, आपको बताए बिना ही संपर्कों का डेटा शेयर कर सकते हैं."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"अपने संपर्क बदलें"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"ऐप्स को आपके टैबलेट में संग्रहित संपर्कों के डेटा को, साथ ही विशिष्ट व्यक्तियों को कॉल करने, ईमेल करने, या अन्‍य तरीके से डॉयलॉग करने की आवृत्ति को संशोधित करने देता है. यह अनुमति ऐप्स को आपके संपर्क डेटा को हटाने देती है."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"यह ऐप्लिकेशन को आपके Android TV डिवाइस पर सेव किए संपर्कों के डेटा में बदलाव करने की अनुमति देता है. साथ ही, संपर्क में शामिल कुछ खास लोगों को आप कितना कॉल करते हैं, कितने ईमेल भेजते हैं या संपर्क करने के दूसरे तरीकों का कितना इस्तेमाल करते हैं, इससे जुड़ी जानकारी में भी बदलाव कर सकता है. इस अनुमति से, ऐप्लिकेशन आपके संपर्क के डेटा को मिटा सकता है."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"ऐप्स को आपके फ़ोन में संग्रहित संपर्कों के डेटा को, साथ ही विशिष्ट व्यक्तियों को कॉल करने, ईमेल करने, या अन्‍य तरीके से डॉयलॉग करने की आवृत्ति को संशोधित करने देता है. यह अनुमति ऐप्स को आपके संपर्क डेटा को हटाने देती है."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"यह ऐप्लिकेशन को आपके टैबलेट पर सेव किए संपर्कों के डेटा में बदलाव करने की अनुमति देता है. इस अनुमति के बाद, ऐप्लिकेशन आपके संपर्कों का डेटा मिटा सकते हैं."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"यह ऐप्लिकेशन को आपके Android TV डिवाइस पर सेव किए संपर्कों के डेटा में बदलाव करने की अनुमति देता है. इस अनुमति के बाद, ऐप्लिकेशन आपके संपर्कों का डेटा मिटा सकते हैं."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"यह ऐप्लिकेशन को आपके फ़ोन पर सेव किए संपर्कों के डेटा में बदलाव करने की अनुमति देता है. इस अनुमति के बाद, ऐप्लिकेशन आपके संपर्कों का डेटा मिटा सकते हैं."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"कॉल लॉग पढ़ें"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"यह ऐप्लिकेशन आपका कॉल इतिहास पढ़ सकता है."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"कॉल लॉग लिखें"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"कुछ और जगह बताने वाले आदेशों तक पहुंच"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"ऐप को कुछ और जगह की जानकारी देने वाले आदेशों की पहुंच पाने देता है. इससे ऐप जीपीएस या जगह की जानकारी देने वाले दूसरे स्रोतों के काम में रोक-टोक कर सकता है."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"ऐप्लिकेशन \'जगह की सटीक जानकारी\' सिर्फ़ सामने खुली होने पर ऐक्सेस करे"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"यह ऐप्लिकेशन सिर्फ़ तब आपकी \'जगह की सटीक जानकारी\' का इस्तेमाल कर सकता है जब यह स्क्रीन पर दिखाई दे रहा हो. यह ज़रूरी है कि \'जगह की जानकारी\' वाली ये सेवाएं आपके फ़ोन में मौजूद हों और चालू की गई हों ताकि ऐप्लिकेशन उनका इस्तेमाल कर पाए. ऐसा करने से ज़्यादा बैटरी खर्च हो सकती है."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"स्क्रीन पर दिखाई देते समय \'जगह की अनुमानित जानकारी\' (नेटवर्क-आधारित) ऐक्सेस करें"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"यह ऐप्लिकेशन सेल टावर और वाई-फ़ाई नेटवर्क जैसे नेटवर्क स्रोतों के आधार पर आपकी जगह का पता लगा सकता है, लेकिन सिर्फ़ तब, जब ऐप्लिकेशन स्क्रीन पर दिखाई दे रहा हो. यह ज़रूरी है कि \'जगह की जानकारी\' वाली ये सेवाएं आपके टैबलेट में मौजूद हों और चालू की गई हों ताकि ऐप्लिकेशन उनका इस्तेमाल कर पाए."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"यह ऐप्लिकेशन मोबाइल टावर और वाई-फ़ाई नेटवर्क जैसे स्रोतों के आधार पर आपकी जगह की जानकारी ले सकता है. हालांकि, ऐसा तब होगा, जब ऐप्लिकेशन स्क्रीन पर दिखाई दे रहा हो. जगह की जानकारी वाली ये सुविधाएं आपके Android TV डिवाइस पर उपलब्ध होनी चाहिए और चालू स्थिति में होनी चाहिए, ताकि यह ऐप्लिकेशन उनका इस्तेमाल कर सके."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"यह ऐप्लिकेशन सेल टावर और वाई-फ़ाई नेटवर्क जैसे नेटवर्क स्रोतों के आधार पर आपकी जगह का पता लगा सकता है, लेकिन सिर्फ़ तब, जब ऐप्लिकेशन स्क्रीन पर दिखाई दे रहा हो. यह ज़रूरी है कि \'जगह की जानकारी\' वाली ये सेवाएं आपके फ़ोन में मौजूद हों और चालू की गई हों ताकि ऐप्लिकेशन उनका इस्तेमाल कर पाए."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"यह ऐप्लिकेशन सिर्फ़ तब आपकी जगह की सटीक जानकारी का इस्तेमाल कर सकता है, जब यह स्क्रीन पर खुला हो. यह ज़रूरी है कि जगह की जानकारी वाली ये सुविधाएं आपके फ़ोन में मौजूद हों और चालू की गई हों, ताकि ऐप्लिकेशन उनका इस्तेमाल कर पाए. ऐसा करने से ज़्यादा बैटरी खर्च हो सकती है."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"अनुमानित जगह की जानकारी सिर्फ़ तब ऐक्सेस करें, जब ऐप्लिकेशन स्क्रीन पर खुला हो"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"यह ऐप्लिकेशन आपकी अनुमानित जगह की जानकारी का इस्तेमाल सिर्फ़ तब कर सकता है, जब यह स्क्रीन पर दिखाई दे रहा हो. यह ज़रूरी है कि आपके डिवाइस में, जगह की जानकारी वाली सुविधाएं हों और उन्हें चालू किया गया हो, ताकि ऐप्लिकेशन उनका इस्तेमाल कर पाए."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"बैकग्राउंड में जगह की जानकारी ऐक्सेस करना"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"अनुमानित या बिल्कुल सही जगह की जानकारी का ऐक्सेस करने की अनुमति अलग से दिए जाने पर, बैकग्राउंड में चलने के दौरान ऐप्लिकेशन आपकी जगह की जानकारी ऐक्सेस कर सकता है."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"यह ऐप्लिकेशन स्क्रीन पर खुले होने के साथ-साथ बैकग्राउंड में चलते हुए भी जगह की जानकारी ऐक्सेस कर सकता है."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"अपनी ऑडियो सेटिंग बदलें"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"ऐप्स को वैश्विक ऑडियो सेटिंग, जैसे वॉल्‍यूम और कौन-सा स्पीकर आउटपुट के लिए उपयोग किया गया, संशोधित करने देता है."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"ऑडियो रिकॉर्ड करने"</string>
@@ -494,6 +491,8 @@
<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_preferredPaymentInfo" msgid="5274423844767445054">"NFC का इस्तेमाल करने वाली पैसे चुकाने की पसंदीदा सेवा की जानकारी"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"अगर ऐप्लिकेशन को अनुमति दी जाती है, तो वह पैसे चुकाने की आपकी उस पसंदीदा सेवा के बारे में जानकारी पा सकता है जो NFC का इस्तेमाल करती है. इसमें रजिस्टर किए गए डिवाइस और उनके आउटपुट के रूट जैसी जानकारी शामिल होती है."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"नियर फ़ील्‍ड कम्‍यूनिकेशन नियंत्रित करें"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"ऐप्स को नियर फ़ील्ड कम्यूनिकेशन (NFC) टैग, कार्ड, और रीडर के साथ संचार करने देता है."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"अपना स्‍क्रीन लॉक अक्षम करें"</string>
@@ -901,11 +900,11 @@
<string name="factorytest_reboot" msgid="2050147445567257365">"रीबूट करें"</string>
<string name="js_dialog_title" msgid="7464775045615023241">"\'<xliff:g id="TITLE">%s</xliff:g>\' पर यह पेज दर्शाता है:"</string>
<string name="js_dialog_title_default" msgid="3769524569903332476">"JavaScript"</string>
- <string name="js_dialog_before_unload_title" msgid="7012587995876771246">"मार्गदर्शक की दुबारा पूछें"</string>
+ <string name="js_dialog_before_unload_title" msgid="7012587995876771246">"नेविगेशन की पुष्टि करें"</string>
<string name="js_dialog_before_unload_positive_button" msgid="4274257182303565509">"इस पेज से आगे बढ़ें"</string>
<string name="js_dialog_before_unload_negative_button" msgid="3873765747622415310">"इस पेज पर बने रहें"</string>
<string name="js_dialog_before_unload" msgid="7213364985774778744">"<xliff:g id="MESSAGE">%s</xliff:g>\n\nक्या आप वाकई इस पेज से दूर नेविगेट करना चाहते हैं?"</string>
- <string name="save_password_label" msgid="9161712335355510035">"दुबारा पूछें"</string>
+ <string name="save_password_label" msgid="9161712335355510035">"पुष्टि करें"</string>
<string name="double_tap_toast" msgid="7065519579174882778">"सलाह: ज़ूम इन और आउट करने के लिए दो बार छूएं."</string>
<string name="autofill_this_form" msgid="3187132440451621492">"अपने आप भरने की सुविधा"</string>
<string name="setup_autofill" msgid="5431369130866618567">"अपने आप भरें जाना सेट करें"</string>
@@ -1579,7 +1578,7 @@
<string name="kg_password_instructions" msgid="7179782578809398050">"पासवर्ड डालें"</string>
<string name="kg_puk_enter_puk_hint" msgid="6696187482616360994">"सिम अब अक्षम हो गई है. जारी रखने के लिए PUK कोड डालें. विवरण के लिए कैरियर से संपर्क करें."</string>
<string name="kg_puk_enter_pin_hint" msgid="8190982314659429770">"इच्छित पिन कोड डालें"</string>
- <string name="kg_enter_confirm_pin_hint" msgid="6372557107414074580">"इच्छित पिन कोड की दुबारा पूछें"</string>
+ <string name="kg_enter_confirm_pin_hint" msgid="6372557107414074580">"पिन कोड की पुष्टि करें"</string>
<string name="kg_sim_unlock_progress_dialog_message" msgid="8871937892678885545">"सिम कार्ड अनलॉक कर रहा है…"</string>
<string name="kg_password_wrong_pin_code" msgid="9013856346870572451">"गलत PIN कोड."</string>
<string name="kg_invalid_sim_pin_hint" msgid="4821601451222564077">"ऐसा PIN लिखें, जो 4 से 8 अंकों का हो."</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"सुलभता शॉर्टकट ने <xliff:g id="SERVICE_NAME">%1$s</xliff:g> को चालू किया"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"सुलभता शॉर्टकट ने <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>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"\'सुलभता\' बटन पर टैप करके इस्तेमाल करने के लिए सेवा चुनें:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"सुलभता वाले जेस्चर के साथ इस्तेमाल करने के लिए सेवा चुनें (दो उंगलियों से स्क्रीन पर सबसे नीचे से ऊपर की ओर स्वाइप करें):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"सुलभता वाले जेस्चर के साथ इस्तेमाल करने के लिए सेवा चुनें (तीन उंगलियों से स्क्रीन पर सबसे नीचे से ऊपर की ओर स्वाइप करें):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"एक सेवा से दूसरी सेवा पर जाने के लिए, \'सुलभता\' बटन को कुछ देर दबाकर रखें."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"एक सेवा से दूसरी सेवा पर जाने के लिए, स्क्रीन पर दो उंगलियों से ऊपर की ओर स्वाइप करें और थोड़ी देर तक स्क्रीन पर उंगलियां रखे रहें."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"एक सेवा से दूसरी सेवा पर जाने के लिए, स्क्रीन पर तीन उंगलियों से ऊपर की ओर स्वाइप करें और थोड़ी देर तक स्क्रीन पर उंगलियां रखे रहें."</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>
@@ -1727,7 +1720,7 @@
<string name="restr_pin_incorrect" msgid="3861383632940852496">"गलत"</string>
<string name="restr_pin_enter_old_pin" msgid="7537079094090650967">"वर्तमान पिन"</string>
<string name="restr_pin_enter_new_pin" msgid="3267614461844565431">"नया पिन"</string>
- <string name="restr_pin_confirm_pin" msgid="7143161971614944989">"नए पिन की दुबारा पूछें"</string>
+ <string name="restr_pin_confirm_pin" msgid="7143161971614944989">"नए पिन की पुष्टि करें"</string>
<string name="restr_pin_create_pin" msgid="917067613896366033">"प्रतिबंधों को बदलने के लिए PIN बनाएं"</string>
<string name="restr_pin_error_doesnt_match" msgid="7063392698489280556">"PIN मेल नहीं खाते हैं. फिर से कोशिश करें."</string>
<string name="restr_pin_error_too_short" msgid="1547007808237941065">"PIN बहुत छोटा है. कम से कम 4 अंकों का होना चाहिए."</string>
@@ -1862,7 +1855,11 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> से कनेक्ट किया गया"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"फ़ाइलें देखने के लिए टैप करें"</string>
<string name="pin_target" msgid="8036028973110156895">"पिन करें"</string>
+ <!-- no translation found for pin_specific_target (7824671240625957415) -->
+ <skip />
<string name="unpin_target" msgid="3963318576590204447">"अनपिन करें"</string>
+ <!-- no translation found for unpin_specific_target (3859828252160908146) -->
+ <skip />
<string name="app_info" msgid="6113278084877079851">"ऐप्लिकेशन की जानकारी"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"डेमो प्रारंभ हो रहा है…"</string>
@@ -1905,6 +1902,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"क्या आप "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" में इन आइटम को अपडेट करना चाहते हैं: <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>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"सेव करें"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"नहीं, धन्यवाद"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"अभी नहीं"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"कभी नहीं"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"अपडेट करें"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"जारी रखें"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"पासवर्ड"</string>
@@ -2000,5 +1999,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"स्प्लिट स्क्रीन पर टॉगल करें"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"स्क्रीन लॉक करें"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"स्क्रीनशॉट लें"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"पॉप-अप विंडो में <xliff:g id="APP_NAME">%1$s</xliff:g> ऐप्लिकेशन."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> का कैप्शन बार."</string>
</resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index e8f02b276cf0..0b7a3571450f 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -190,8 +190,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Administratorska aplikacija radnog profila nedostaje ili je oštećena. Zbog toga su radni profil i povezani podaci izbrisani. Za pomoć se obratite svom administratoru."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Vaš radni profil više nije dostupan na ovom uređaju"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Previše pokušaja unosa zaporke"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Administrator je ustupio uređaj za osobnu upotrebu"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Uređaj je upravljan"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Vaša organizacija upravlja ovim uređajem i može nadzirati mrežni promet. Dodirnite za pojedinosti."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Uređaj će se izbrisati"</string>
@@ -384,13 +383,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Aplikaciji omogućuje slanje \"ljepljivih\" emitiranja koja se zadržavaju nakon završetka emitiranja. Prekomjerna upotreba može usporiti Android TV uređaj ili ga učiniti nestabilnim uzrokujući pretjeranu upotrebu memorije."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Aplikaciji omogućuje slanje \"ljepljivih\" emitiranja koja se zadržavaju nakon završetka emitiranja. Prekomjerna upotreba može usporiti telefon ili ga učiniti nestabilnim uzrokujući pretjeranu upotrebu memorije."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"čitanje kontakata"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Aplikaciji omogućuje čitanje podataka o vašim kontaktima pohranjenim na tabletnom računalu, uključujući učestalost poziva, e-poruka ili drugih načina komunikacije s određenim pojedincima. Ta dozvola aplikaciji omogućuje spremanje podataka kontakata, a zlonamjerne aplikacije mogu dijeliti podatke kontakata bez vašeg znanja."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Aplikaciji omogućuje čitanje podataka o vašim kontaktima pohranjenima na vašem Android TV uređaju, uključujući učestalost poziva, e-poruka ili drugih načina komunikacije s određenim osobama. To dopuštenje omogućuje aplikaciji spremanje vaših podataka o kontaktima, a zlonamjerne aplikacije mogu dijeliti podatke o kontaktima bez vašeg znanja."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Aplikaciji omogućuje čitanje podataka o vašim kontaktima pohranjenim na telefonu, uključujući učestalost poziva, e-poruka ili drugih načina komunikacije s određenim pojedincima. Ta dozvola aplikaciji omogućuje spremanje podataka kontakata, a zlonamjerne aplikacije mogu dijeliti podatke kontakata bez vašeg znanja."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Aplikaciji omogućuje čitanje podataka o vašim kontaktima pohranjenim na vašem tabletu. Aplikacije će također imati pristup računima na vašem tabletu na kojima su izrađeni kontakti. To može uključivati račune izrađene u aplikacijama koje ste instalirali. To dopuštenje omogućuje aplikacijama spremanje podataka o kontaktima, a zlonamjerne aplikacije mogu dijeliti podatke o kontaktima bez vašeg znanja."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Aplikaciji omogućuje čitanje podataka o vašim kontaktima pohranjenim na vašem Android TV uređaju. Aplikacije će također imati pristup računima na vašem Android TV uređaju na kojima su izrađeni kontakti. To može uključivati račune izrađene u aplikacijama koje ste instalirali. To dopuštenje omogućuje aplikacijama spremanje podataka o kontaktima, a zlonamjerne aplikacije mogu dijeliti podatke o kontaktima bez vašeg znanja."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Aplikaciji omogućuje čitanje podataka o vašim kontaktima pohranjenim na vašem telefonu. Aplikacije će također imati pristup računima na vašem telefonu na kojima su izrađeni kontakti. To može uključivati račune izrađene u aplikacijama koje ste instalirali. To dopuštenje omogućuje aplikacijama spremanje podataka o kontaktima, a zlonamjerne aplikacije mogu dijeliti podatke o kontaktima bez vašeg znanja."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"izmjena kontakata"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Aplikaciji omogućuje izmjenu podataka o vašim kontaktima pohranjenim na tabletnom računalu, uključujući učestalost poziva, e-poruka ili drugih načina komunikacije s određenim kontaktima. Ta dozvola aplikacijama omogućuje brisanje kontaktnih podataka."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Aplikaciji omogućuje izmjenu podataka o vašim kontaktima pohranjenim na Android TV uređaju, uključujući učestalost poziva, e-poruka ili drugih načina komunikacije s određenim kontaktima. To dopuštenje aplikacijama omogućuje brisanje podataka o kontaktima."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Aplikaciji omogućuje izmjenu podataka o vašim kontaktima pohranjenim na telefonu, uključujući učestalost poziva, e-poruka ili drugih načina komunikacije s određenim kontaktima. Ta dozvola aplikacijama omogućuje brisanje kontaktnih podataka."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Aplikaciji omogućuje izmjenu podataka o vašim kontaktima pohranjenim na vašem tabletu. To dopuštenje aplikacijama omogućuje da brišu podatke o kontaktima."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Aplikaciji omogućuje izmjenu podataka o vašim kontaktima pohranjenim na vašem Android TV uređaju. To dopuštenje aplikacijama omogućuje da brišu podatke o kontaktima."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Aplikaciji omogućuje izmjenu podataka o vašim kontaktima pohranjenim na vašem telefonu. To dopuštenje aplikacijama omogućuje da brišu podatke o kontaktima."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"čitanje dnevnika poziva"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Aplikacija može čitati vašu povijest poziva."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"pisanje u dnevnik poziva"</string>
@@ -410,13 +409,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"pristup dodatnim naredbama davatelja lokacije"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Omogućuje aplikaciji pristup dodatnim naredbama davatelja usluga lokacije. To može omogućiti aplikaciji ometanje rada GPS-a ili drugih izvora lokacije."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"pristupiti preciznoj lokaciji samo u prednjem planu"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Aplikacija može dobiti vašu točnu lokaciju samo kada je u prednjem planu. Te usluge lokacije moraju biti uključene i dostupne na telefonu da bi ih aplikacija mogla upotrebljavati. To može pojačati potrošnju baterije."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"pristupiti približnoj lokaciji (na temelju mreže) samo u prednjem planu"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Ova aplikacija može dobiti vašu lokaciju na temelju mrežnih izvora kao što su bazne stanice i Wi-Fi mreže, no samo kad je u prednjem planu. Te usluge lokacije moraju biti uključene i dostupne na vašem tabletu da bi ih aplikacija mogla upotrebljavati."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Ova aplikacija može dobiti vašu lokaciju na temelju mrežnih izvora kao što su bazne stanice i Wi-Fi mreže, no samo kad je u prednjem planu. Te usluge lokacije moraju biti uključene i dostupne na vašem Android TV uređaju da bi ih aplikacija mogla upotrebljavati."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Ova aplikacija može dobiti vašu lokaciju na temelju mrežnih izvora kao što su bazne stanice i Wi-Fi mreže, no samo kad je u prednjem planu. Te usluge lokacije moraju biti uključene i dostupne na vašem telefonu da bi ih aplikacija mogla upotrebljavati."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Aplikacija može dobiti vašu točnu lokaciju samo kad je u prednjem planu. Usluge lokacije moraju biti uključene i dostupne na uređaju da bi ih aplikacija mogla upotrebljavati. To može pojačati potrošnju baterije."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"pristupiti približnoj lokaciji samo u prednjem planu"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Aplikacija može dobiti vašu približnu lokaciju samo kad je u prednjem planu. Usluge lokacije moraju biti uključene i dostupne na uređaju da bi ih aplikacija mogla upotrebljavati."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"pristup lokaciji u pozadini"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Ako se ovo odobrava dodatno za pristup približnoj ili preciznoj lokaciji, aplikacija može pristupiti lokaciji tijekom rada u pozadini."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Ta aplikacija može pristupiti lokaciji dok se izvodi u pozadini, uz pristup lokaciji u prednjem planu."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"promjena postavki zvuka"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Aplikaciji omogućuje izmjenu globalnih postavki zvuka, primjerice glasnoće i zvučnika koji se upotrebljava za izlaz."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"snimanje zvuka"</string>
@@ -497,6 +494,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Aplikaciji omogućuje pregled konfiguracije Bluetootha na tabletnom računalu te uspostavljanje i prihvaćanje veza s uparenim uređajima."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Aplikaciji omogućuje pregled konfiguracije Bluetootha na Android TV uređaju te uspostavljanje i prihvaćanje veza s uparenim uređajima."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Aplikaciji omogućuje pregled konfiguracije Bluetootha na telefonu te uspostavljanje i prihvaćanje veza s uparenim uređajima."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Informacije o preferiranoj usluzi plaćanja NFC"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Omogućuje aplikaciji primanje informacija o preferiranoj usluzi plaćanja NFC kao što su registrirana pomagala i odredište."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"upravljanje beskontaktnom komunikacijom (NFC)"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Aplikaciji omogućuje komunikaciju s oznakama, karticama i čitačima komunikacije kratkog dometa (NFC)."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"onemogućavanje zaključavanja zaslona"</string>
@@ -1640,12 +1639,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"Prečac pristupačnosti uključio je uslugu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"Prečac pristupačnosti isključio je uslugu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Pritisnite i zadržite tipke za glasnoću na tri sekunde da biste koristili uslugu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Odaberite uslugu koju ćete upotrebljavati kad dodirnete gumb pristupačnosti:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Odaberite za što će se upotrebljavati pokret pristupačnosti (prelazak s dva prsta prema gore od dna zaslona):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Odaberite uslugu koju ćete upotrebljavati uz pokret pristupačnosti (prelazak s tri prsta prema gore od dna zaslona):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Da biste prešli na neku drugu uslugu, dodirnite i zadržite gumb pristupačnosti."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Da biste prešli na neku drugu uslugu, prijeđite s dva prsta prema gore i zadržite."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Da biste prešli na neku drugu uslugu, prijeđite s tri prsta prema gore i zadržite."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Povećavanje"</string>
<string name="user_switched" msgid="7249833311585228097">"Trenutačni korisnik <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="1912993630661332336">"Prebacivanje na korisnika <xliff:g id="NAME">%1$s</xliff:g>…"</string>
@@ -1894,7 +1887,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> – veza je uspostavljena"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Dodirnite da biste pregledali datoteke"</string>
<string name="pin_target" msgid="8036028973110156895">"Prikvači"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Prikvačite korisnika <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Otkvači"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Otkvači sudionika <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Informacije o aplikaciji"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Pokretanje demo-načina..."</string>
@@ -1938,6 +1933,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Želite li ažurirati ove stavke u oznaci "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> i <xliff:g id="TYPE_2">%3$s</xliff:g> ?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Spremi"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Ne, hvala"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Ne sad"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Nikad"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Ažuriraj"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Nastavi"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"zaporku"</string>
@@ -2034,5 +2031,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Uključite ili isključite podijeljeni zaslon"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Zaključajte zaslon"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Snimka zaslona"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> u skočnom prozoru."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Traka naslova aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 1d1b99474938..cc53c7b43419 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"A munkaprofil rendszergazdai alkalmazása hiányzik vagy sérült. A rendszer ezért törölte a munkaprofilt, és az ahhoz kapcsolódó adatokat. Ha segítségre van szüksége, vegye fel a kapcsolatot rendszergazdájával."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Munkaprofilja már nem hozzáférhető ezen az eszközön."</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Túl sok jelszómegadási kísérlet"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Az adminisztrátor átadta az eszközt személyes használatra"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Felügyelt eszköz"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Ezt az eszközt szervezete kezeli, és lehetséges, hogy a hálózati forgalmat is figyelik. További részletekért koppintson."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"A rendszer törölni fogja eszközét"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Lehetővé teszi az alkalmazás számára ragadós üzenetek küldését, amelyek az üzenetszórás után is megmaradnak. A túlzott használat nagy mennyiségű memóriát igényel, ezért lelassíthatja vagy instabillá teheti az Android TV eszközt."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Lehetővé teszi az alkalmazás számára ragadós üzenetek küldését, amelyek a sugárzás után is megmaradnak. A túlzott használat lelassíthatja vagy instabillá teheti a telefont a nagymértékű memóriahasználattal."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"saját névjegyek olvasása"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Lehetővé teszi az alkalmazás számára a táblagépen tárolt névjegyekre vonatkozó összes adat -- például az egyes személyekkel telefonon, e-mailben vagy más módon folytatott kommunikáció gyakoriságára vonatkozó adatok -- beolvasását. Az engedéllyel rendelkező alkalmazások menthetik a névjegyadatokat, és a rosszindulatú alkalmazások az Ön tudta nélkül oszthatják meg a névjegyadatokat."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Lehetővé teszi az alkalmazás számára, hogy beolvassa az Android TV eszközön tárolt névjegyek adatait, beleértve az egyes személyekkel kapcsolatos hívások, e-mailek és egyéb kommunikáció gyakoriságára vonatkozó adatokat. Ez az engedély lehetővé teszi az alkalmazások számára a névjegyadatok mentését, így a rosszindulatú alkalmazások az Ön tudta nélkül megoszthatják őket."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Lehetővé teszi az alkalmazás számára a telefonon tárolt névjegyekre vonatkozó összes adat -- például az egyes személyekkel telefonon, e-mailben vagy más módon folytatott kommunikáció gyakoriságára vonatkozó adatok -- beolvasását. Az engedéllyel rendelkező alkalmazások menthetik a névjegyadatokat, és a rosszindulatú alkalmazások az Ön tudta nélkül oszthatják meg a névjegyadatokat."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Lehetővé teszi az alkalmazás számára a táblagépen tárolt névjegyekre vonatkozó adatok olvasását. Az alkalmazások ezenkívül hozzáférnek azokhoz a fiókokhoz is a táblagépen, amelyek létrehoztak névjegyeket. Ebbe beletartozhatnak a telepített alkalmazások által létrehozott fiókok is. Ez az engedély lehetővé teszi az alkalmazások számára a névjegyadatok mentését, így a rosszindulatú alkalmazások az Ön tudta nélkül megoszthatják őket."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Lehetővé teszi az alkalmazás számára az Android TV-n tárolt névjegyekre vonatkozó adatok olvasását. Az alkalmazások ezenkívül hozzáférnek azokhoz a fiókokhoz is az Android TV-eszközön, amelyek létrehoztak névjegyeket. Ebbe beletartozhatnak a telepített alkalmazások által létrehozott fiókok is. Ez az engedély lehetővé teszi az alkalmazások számára a névjegyadatok mentését, így a rosszindulatú alkalmazások az Ön tudta nélkül megoszthatják őket."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Lehetővé teszi az alkalmazás számára a telefonon tárolt névjegyekre vonatkozó adatok olvasását. Az alkalmazások ezenkívül hozzáférnek azokhoz a fiókokhoz is a telefonon, amelyek létrehoztak névjegyeket. Ebbe beletartozhatnak a telepített alkalmazások által létrehozott fiókok is. Ez az engedély lehetővé teszi az alkalmazások számára a névjegyadatok mentését, így a rosszindulatú alkalmazások az Ön tudta nélkül megoszthatják őket."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"kapcsolatok módosítása"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Lehetővé teszi az alkalmazás számára a táblagépen tárolt névjegyekre vonatkozó adatok -- például az egyes személyekkel telefonon, e-mailben vagy más módon folytatott kommunikáció gyakoriságára vonatkozó adatok -- módosítását. Az engedéllyel rendelkező alkalmazás törölheti a névjegyadatokat."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Lehetővé teszi az alkalmazás számára az Android TV eszközön tárolt névjegyekre vonatkozó adatok módosítását – ilyenek például az egyes személyekkel telefonon, e-mailben vagy más módon folytatott kommunikáció gyakoriságára vonatkozó adatok. Ezzel az engedéllyel az alkalmazások törölhetik a névjegyadatokat."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Lehetővé teszi az alkalmazás számára a telefonon tárolt névjegyekre vonatkozó adatok -- például az egyes személyekkel telefonon, e-mailben vagy más módon folytatott kommunikáció gyakoriságára vonatkozó adatok -- módosítását. Az engedéllyel rendelkező alkalmazás törölheti a névjegyadatokat."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Lehetővé teszi az alkalmazás számára a táblagépen tárolt névjegyekre vonatkozó adatok módosítását. Ezzel az engedéllyel az alkalmazások törölhetik a névjegyadatokat."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Lehetővé teszi az alkalmazás számára az Android TV-n tárolt névjegyekre vonatkozó adatok módosítását. Ezzel az engedéllyel az alkalmazások törölhetik a névjegyadatokat."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Lehetővé teszi az alkalmazás számára a telefonon tárolt névjegyekre vonatkozó adatok módosítását. Ezzel az engedéllyel az alkalmazások törölhetik a névjegyadatokat."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"Híváslista beolvasása"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Az alkalmazás olvashatja az Ön híváslistáját."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"Híváslista készítése"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"további helyszolgáltatói parancsok elérése"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Lehetővé teszi az alkalmazás számára további helyszolgáltatói parancsok elérését. Ezáltal az alkalmazás beavatkozhat a GPS vagy más helyforrások működésébe."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"pontos helyadatokhoz való hozzáférés csak előtérben"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Ez az alkalmazás csak akkor férhet hozzá az eszköz pontos helyadataihoz, amikor az előtérben fut. A helyszolgáltatásoknak bekapcsolt és hozzáférhető állapotban kell lenniük a telefonon ahhoz, hogy az alkalmazás használhassa őket. Ez növelheti az akkumulátorhasználatot."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"hozzávetőleges (hálózaton alapuló) helyadatokhoz való hozzáférés csak előtérben"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Ez az alkalmazás hozzáférhet a hálózati forrásokon (például az adótornyokon és a Wi-Fi-hálózatokon) alapuló helyadataihoz, de csak akkor, amikor az előtérben fut. A helyszolgáltatásoknak bekapcsolt és hozzáférhető állapotban kell lenniük a táblagépen ahhoz, hogy az alkalmazás használhassa őket."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Ez az alkalmazás hozzáférhet a hálózati forrásokon (például az adótornyokon és a Wi-Fi-hálózatokon) alapuló helyadataihoz, de csak akkor, amikor az előtérben fut. A helyszolgáltatásoknak bekapcsolt és hozzáférhető állapotban kell lenniük az Android TV eszközön ahhoz, hogy az alkalmazás használhassa őket."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Ez az alkalmazás hozzáférhet a hálózati forrásokon (például az adótornyokon és a Wi-Fi-hálózatokon) alapuló helyadataihoz, de csak akkor, amikor az előtérben fut. A helyszolgáltatásoknak bekapcsolt és hozzáférhető állapotban kell lenniük a telefonon ahhoz, hogy az alkalmazás használhassa őket."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Ez az alkalmazás csak akkor férhet hozzá az eszköz pontos helyadataihoz, amikor az előtérben fut. Az alkalmazás csak akkor használhatja a helyszolgáltatásokat, ha be vannak kapcsolva, és hozzáférhetők az eszköz számára. Ez növelheti az akkumulátorhasználatot."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"megközelítőleges helyadatokhoz való hozzáférés csak előtérben"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Ez az alkalmazás csak akkor férhet hozzá az eszköz megközelítőleges helyadataihoz, amikor az előtérben fut. Az alkalmazás csak akkor használhatja a helyszolgáltatásokat, ha be vannak kapcsolva, és hozzáférhetők az eszköz számára."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"Hozzáférés a helyadatokhoz a háttérben"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Ha engedélyezi ezt a hozzávetőleges vagy pontos helyadatokhoz való hozzáférés mellett, akkor az alkalmazás hozzáférhet a helyadatokhoz, miközben a háttérben fut."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Ez az alkalmazás nem csak akkor férhet hozzá a helyadatokhoz, amikor az előtérben van, hanem akkor is, amikor a háttérben fut."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"hangbeállítások módosítása"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Lehetővé teszi az alkalmazás számára az általános hangbeállítások, például a hangerő és a használni kívánt kimeneti hangszóró módosítását."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"hanganyag rögzítése"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Lehetővé teszi az alkalmazás számára a táblagépen lévő Bluetooth beállításainak megtekintését, valamint kapcsolatok kezdeményezését és fogadását a párosított eszközökkel."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Lehetővé teszi az alkalmazás számára az Android TV eszköz Bluetooth-konfigurációjának megtekintését, valamint párosított eszközökkel való kapcsolatok kezdeményezését és fogadását."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Lehetővé teszi az alkalmazás számára a telefonon lévő Bluetooth beállításainak megtekintését, valamint kapcsolatok kezdeményezését és fogadását a párosított eszközökkel."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Preferált NFC fizetési szolgáltatási információk"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Lehetővé teszi az alkalmazás számára preferált NFC fizetési szolgáltatási információk (pl. regisztrált alkalmazásazonosítók és útvonali cél) lekérését."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"NFC technológia vezérlése"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Lehetővé teszi az alkalmazás számára, hogy NFC (Near Field Communication - kis hatósugarú vezeték nélküli kommunikáció) technológiát használó címkékkel, kártyákkal és leolvasókkal kommunikáljon."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"képernyőzár kikapcsolása"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"A Kisegítő lehetőségek gyorsparancsa bekapcsolta a következő szolgáltatást: <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"A Kisegítő lehetőségek gyorsparancsa kikapcsolta a következő szolgáltatást: <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"A(z) <xliff:g id="SERVICE_NAME">%1$s</xliff:g> használatához tartsa lenyomva három másodpercig a két hangerőgombot"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Válassza ki a kisegítő lehetőségek gombra koppintáskor használni kívánt szolgáltatást:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Válassza ki a kisegítő kézmozdulattal használni kívánt szolgáltatást (csúsztassa felfelé két ujját a képernyő aljáról):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Válassza ki a kisegítő kézmozdulattal használni kívánt szolgáltatást (csúsztassa felfelé három ujját a képernyő aljáról):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"A szolgáltatások közötti váltáshoz tartsa lenyomva a kisegítő lehetőségek gombot."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"A szolgáltatások közötti váltáshoz csúsztassa felfelé két ujját, és ne engedje el a képernyőt."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"A szolgáltatások közötti váltáshoz csúsztassa felfelé három ujját, és ne engedje el a képernyőt."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Nagyítás"</string>
<string name="user_switched" msgid="7249833311585228097">"<xliff:g id="NAME">%1$s</xliff:g> az aktuális felhasználó."</string>
<string name="user_switching_message" msgid="1912993630661332336">"Átváltás erre: <xliff:g id="NAME">%1$s</xliff:g>..."</string>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Csatlakoztatva a(z) <xliff:g id="PRODUCT_NAME">%1$s</xliff:g> eszközhöz"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Koppintson ide a fájlok megtekintéséhez"</string>
<string name="pin_target" msgid="8036028973110156895">"Rögzítés"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"<xliff:g id="LABEL">%1$s</xliff:g> rögzítése"</string>
<string name="unpin_target" msgid="3963318576590204447">"Feloldás"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"<xliff:g id="LABEL">%1$s</xliff:g> rögzítésének feloldása"</string>
<string name="app_info" msgid="6113278084877079851">"Alkalmazásinformáció"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Bemutató indítása…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Frissíti a(z) "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" szolgáltatásban a következőket: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> és <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Mentés"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Nem, köszönöm"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Ne most"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Soha"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Frissítés"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Tovább"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"jelszó"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Osztott képernyő be- vagy kikapcsolása"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Lezárási képernyő"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Képernyőkép"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"<xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazás előugró ablakban."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazás címsora."</string>
</resources>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 599ce864a4d3..e69329898807 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Աշխատանքային պրոֆիլի ադմինիստրատորի հավելվածը բացակայում է կամ վնասված է: Արդյունքում ձեր աշխատանքային պրոֆիլը և առնչվող տվյալները ջնջվել են: Օգնության համար դիմեք ձեր ադմինիստրատորին:"</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Ձեր աշխատանքային պրոֆիլն այս սարքում այլևս հասանելի չէ"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Գաղտնաբառը մուտքագրելու չափից շատ փորձեր են կատարվել"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Ադմինիստրատորը տրամադրել է սարքը անձնական օգտագործման համար"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Սարքը կառավարվում է"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Ձեր կազմակերպությունը կառավարում է այս սարքը և կարող է վերահսկել ցանցի թրաֆիկը: Հպեք՝ մանրամասները դիտելու համար:"</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Ձեր սարքը ջնջվելու է"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Թույլ է տալիս հավելվածին կատարել անընդմեջ հեռարձակումներ, որոնցից հետո տվյալները հասանելի են մնում: Չափից դուրս օգտագործումը կարող է դանդաղեցնել Android TV սարքի աշխատանքը կամ դարձնել այն անկայուն՝ ավելացնելով հիշողության ծախսը:"</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Թույլ է տալիս հավելվածին ուղարկել կպչուն հաղորդումներ, որոնք մնում են հաղորդման ավարտից հետո: Չափազանց շատ օգտագործումը կարող է հեռախոսի աշխատանքը դանդաղեցնել կամ դարձնել անկայուն` պատճառ դառնալով չափազանց մեծ հիշողության օգտագործման:"</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"կարդալ ձեր կոնտակտները"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Թույլ է տալիս հավելվածին կարդալ ձեր պլանշետում պահված կոնտակտների մասին տվյալները, այդ թվում` ձեր կատարած զանգերի, գրած նամակների կամ որոշակի անհատների հետ այլ եղանակով շփման հաճախականությունը: Այս թույլտվությունը հնարավորություն է տալիս հավելվածներին պահել ձեր կոնտակտային տվյալները, իսկ վնասարար հավելվածները կարող են տարածել կոնտակտային տվյալները` առանց ձեր իմացության:"</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Թույլ է տալիս հավելվածին կարդալ Android TV սարքում պահված կոնտակտների տվյալները, այդ թվում նաև՝ թե ինչ հաճախականությամբ եք զանգեր կատարել, օգտվել էլփոստից կամ այլ կերպ հաղորդակցվել որոշակի մարդկանց հետ: Այս թույլտվության միջոցով հավելվածները կարող են պահել ձեր կոնտակտների տվյալները, իսկ վնասարար հավելվածները կարող են օգտագործել դրանք առանց ձեր իմացության:"</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Թույլ է տալիս հավելվածին կարդալ ձեր հեռախոսում պահված կոնտակտների մասին տվյալները, այդ թվում` ձեր կատարած զանգերի, գրած նամակների կամ որոշակի անհատների հետ այլ եղանակով շփման հաճախականությունը: Այս թույլտվությունը հնարավորություն է տալիս հավելվածներին պահել ձեր կոնտակտային տվյալները, իսկ վնասարար հավելվածները կարող են տարածել կոնտակտային տվյալները` առանց ձեր իմացության:"</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Թույլ է տալիս հավելվածին կարդալ ձեր պլանշետում պահված կոնտակտների մասին տվյալները։ Հավելվածներին նաև հասանելի կլինեն հաշիվները ձեր պլանշետում, որտեղ ստեղծվել են կոնտակտներ։ Այդ հաշիվները կարող են ստեղծված լինել ձեր տեղադրած հավելվածների կողմից։ Այս թույլտվության միջոցով հավելվածները կարող են պահել ձեր կոնտակտների մասին տվյալները, իսկ վնասարար հավելվածները կարող են օգտագործել դրանք առանց ձեր իմացության։"</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Թույլ է տալիս հավելվածին կարդալ Android TV սարքում պահված կոնտակտների մասին տվյալները։ Հավելվածներին նաև հասանելի կլինեն հաշիվներն Android TV սարքում, որտեղ ստեղծվել են կոնտակտներ։ Այդ հաշիվները կարող են ստեղծված լինել ձեր տեղադրած հավելվածների կողմից։ Այս թույլտվության միջոցով հավելվածները կարող են պահել ձեր կոնտակտների մասին տվյալները, իսկ վնասարար հավելվածները կարող են օգտագործել դրանք առանց ձեր իմացության։"</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Թույլ է տալիս հավելվածին կարդալ ձեր հեռախոսում պահված կոնտակտների մասին տվյալները։ Հավելվածներին նաև հասանելի կլինեն հաշիվները ձեր հեռախոսում, որտեղ ստեղծվել են կոնտակտներ։ Այդ հաշիվները կարող են ստեղծված լինել ձեր տեղադրած հավելվածների կողմից։ Այս թույլտվության միջոցով հավելվածները կարող են պահել ձեր կոնտակտների մասին տվյալները, իսկ վնասարար հավելվածները կարող են օգտագործել դրանք առանց ձեր իմացության։"</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"փոփոխել ձեր կոնտակտները"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Թույլ է տալիս հավելվածին փոփոխել ձեր պլանշետում պահված կոնտակտների մասին տվյալները, այդ թվում` ձեր կատարած զանգերի, գրած նամակների կամ որոշակի անհատների հետ այլ եղանակով շփման հաճախականությունը: Այս թույլտվությունը հնարավորություն է տալիս հավելվածներին ջնջել կոնտակտային տվյալները:"</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Թույլ է տալիս հավելվածին փոփոխել Android TV սարքում պահված կոնտակտների տվյալները, այդ թվում նաև՝ թե ինչ հաճախականությամբ եք զանգեր կատարել, օգտվել էլփոստից կամ այլ կերպ հաղորդակցվել որոշակի մարդկանց հետ: Այս թույլտվությունը հնարավորություն է տալիս հավելվածներին ջնջել կոնտակտային տվյալները:"</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Թույլ է տալիս հավելվածին փոփոխել ձեր պլանշետում պահված կոնտակտների տվյալները, այդ թվում` ձեր կատարած զանգերի, գրած նամակների կամ որոշակի անհատների հետ այլ եղանակով շփման հաճախականությունը: Այս թույլտվությունը հնարավորություն է տալիս հավելվածներին ջնջել կոնտակտային տվյալները:"</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Թույլ է տալիս հավելվածին փոփոխել ձեր պլանշետում պահված կոնտակտների մասին տվյալները։ Այս թույլտվությունը հնարավորություն է տալիս հավելվածներին ջնջել կոնտակտների մասին տվյալները։"</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Թույլ է տալիս հավելվածին փոփոխել ձեր Android TV սարքում պահված կոնտակտների մասին տվյալները։ Այս թույլտվությունը հնարավորություն է տալիս հավելվածներին ջնջել կոնտակտների մասին տվյալները։"</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Թույլ է տալիս հավելվածին փոփոխել ձեր հեռախոսում պահված կոնտակտների մասին տվյալները։ Այս թույլտվությունը հնարավորություն է տալիս հավելվածներին ջնջել կոնտակտների մասին տվյալները։"</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"կարդալ զանգերի մատյանը"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Այս հավելվածը կարող է կարդալ ձեր զանգերի պատմությունը:"</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"տեսնել զանգերի գրանցամատյանը"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"օգտագործել տեղադրություն տրամադրող հավելվյալ հրամաններ"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Ծրագրին թույլ է տալիս օգտագործել տեղադրության մասին տվյալների աղբյուրների կառավարման լրացուցիչ հրահանգներ: Սա կարող է ծրագրին թույլ տալ միջամտել GPS-ի կամ տեղադրության մասին տվյալների այլ աղբյուրների գործառույթներին:"</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"Տեղադրության ճշգրիտ տվյալների հասանելիություն միայն ֆոնային ռեժիմում"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Հավելվածը կարող է ստանալ ձեր տեղադրության տվյալները ֆոնային ռեժիմում։ Այս տեղորոշման ծառայությունները պետք է միացված և հասանելի լինեն ձեր հեռախոսում, որպեսզի հավելվածը կարողանա օգտագործել դրանք: Սա կարող է արագացնել մարտկոցի լիցքի սպառումը:"</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"Մոտավոր տեղադրությունը (ցանցային) հասանելի է միայն ֆոնային ռեժիմում"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Այս հավելվածը կարող է ստանալ ձեր տեղադրության տվյալները ցանցային տարբեր աղբյուրներից, օրինակ՝ բջջային աշտարակներից և Wi-Fi ցանցերից, սակայն միայն երբ հավելվածն աշխատում է ֆոնային ռեժիմում: Այս տեղորոշման ծառայությունները պետք է միացված և հասանելի լինեն ձեր պլանշետում, որպեսզի հավելվածը կարողանա օգտագործել դրանք:"</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Այս հավելվածը կարող է ստանալ ձեր տեղադրության տվյալները ցանցային տարբեր աղբյուրներից, օրինակ՝ բջջային աշտարակներից և Wi-Fi ցանցերից, սակայն միայն երբ հավելվածն աշխատում է ֆոնային ռեժիմում: Այս տեղորոշման ծառայությունները պետք է միացված և հասանելի լինեն ձեր Android TV սարքում, որպեսզի հավելվածը կարողանա օգտագործել դրանք:"</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Այս հավելվածը կարող է ստանալ ձեր տեղադրության տվյալները ցանցային տարբեր աղբյուրներից, օրինակ՝ բջջային աշտարակներից և Wi-Fi ցանցերից, սակայն միայն երբ հավելվածն աշխատում է ֆոնային ռեժիմում: Այս տեղորոշման ծառայությունները պետք է միացված և հասանելի լինեն ձեր հեռախոսում, որպեսզի հավելվածը կարողանա օգտագործել դրանք:"</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Հավելվածը կարող է ստանալ ձեր տեղադրության տվյալները ակտիվ ռեժիմում։ Տեղորոշման ծառայությունները պետք է միացված և հասանելի լինեն ձեր սարքում, որպեսզի հավելվածը կարողանա օգտագործել դրանք։ Սա կարող է արագացնել մարտկոցի լիցքի սպառումը։"</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"տեղադրության մոտավոր տվյալների հասանելիություն միայն ակտիվ ռեժիմում"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Հավելվածը կարող է ստանալ ձեր մոտավոր տեղադրության տվյալները ակտիվ ռեժիմում։ Տեղորոշման ծառայությունները պետք է միացված և հասանելի լինեն ձեր սարքում, որպեսզի հավելվածը կարողանա օգտագործել դրանք։"</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"տեղադրության մասին տվյալների հասանելիություն ֆոնային ռեժիմում"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Եթե բացի մոտավոր կամ ճշգրիտ տեղորոշման տվյալների հասանելիությունից հավելվածին տրամադրեք այս թույլտվությունը, հավելվածին տեղադրության մասին տվյալները հասանելի կլինեն ֆոնային ռեժիմում։"</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Այս հավելվածը ինչպես ակտիվ, այնպես էլ ֆոնային ռեժիմում աշխատելիս կարող է տեսնել տեղադրության տվյալները։"</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"փոխել ձեր աուդիո կարգավորումները"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Թույլ է տալիս հավելվածին փոփոխել ձայնանյութի գլոբալ կարգավորումները, ինչպես օրինակ` ձայնը և թե որ խոսափողն է օգտագործված արտածման համար:"</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"ձայնագրել աուդիո ֆայլ"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Թույլ է տալիս հավելվածին տեսնել Bluetooth-ի կարգավորումը պլանշետի վրա և կապվել ու կապեր ընդունել զուգակցված սարքերի հետ:"</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Թույլ է տալիս հավելվածին տեսնել Bluetooth-ի կազմաձևումը Android TV սարքի վրա և կապվել ու թույլ տալ կապակցումները զուգակցված սարքերի հետ:"</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Թույլ է տալիս հավելվածին տեսնել Bluetooth-ի կարգավորումը հեռախոսի վրա և կապվել ու կապեր ընդունել զուգակցված սարքերի հետ:"</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Տեղեկություններ NFC վճարային ծառայության մասին"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Թույլ է տալիս հավելվածին ստանալ նախընտրելի NFC վճարային ծառայության մասին տեղեկություններ (օր․՝ գրանցված լրացուցիչ սարքերի և երթուղու նպատակակետի մասին տվյալներ)։"</string>
<string name="permlab_nfc" msgid="1904455246837674977">"վերահսկել Մոտ Տարածությամբ Հաղորդակցումը"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Թույլ է տալիս հավելվածին հաղորդակցվել Մոտ տարածությամբ հաղորդակցման (NFC) պիտակների, քարտերի և ընթերցիչների հետ:"</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"անջատել ձեր էկրանի կողպեքը"</string>
@@ -827,7 +826,7 @@
<string name="lockscreen_transport_stop_description" msgid="1449552232598355348">"Դադարեցնել"</string>
<string name="lockscreen_transport_rew_description" msgid="7680106856221622779">"Հետ փաթաթել"</string>
<string name="lockscreen_transport_ffw_description" msgid="4763794746640196772">"Արագ առաջ անցնել"</string>
- <string name="emergency_calls_only" msgid="3057351206678279851">"Միայն արտակարգ իրավիճակների զանգեր"</string>
+ <string name="emergency_calls_only" msgid="3057351206678279851">"Միայն շտապ կանչեր"</string>
<string name="lockscreen_network_locked_message" msgid="2814046965899249635">"Ցանցը կողպված է"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="6618356415831082174">"SIM քարտը PUK-ով կողպված է:"</string>
<string name="lockscreen_sim_puk_locked_instructions" msgid="5307979043730860995">"Տեսեք Օգտատիրոջ ուղեցույցը կամ դիմեք Բաժանորդների սպասարկման կենտրոն:"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"Մատչելիության դյուրանցումն միացրել է <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ծառայությունը"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"Մատչելիության դյուրանցումն անջատել է <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ծառայությունը"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"«<xliff:g id="SERVICE_NAME">%1$s</xliff:g>» ծառայությունն օգտագործելու համար սեղմեք և 3 վայրկյան պահեք ձայնի ուժգնության երկու կոճակները"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Ընտրեք ծառայությունը, որը կգործարկվի «Հատուկ գործառույթներ» կոճակին հպելու դեպքում՝"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Ընտրեք ծառայությունը, որը կգործարկվի հատուկ գործառույթների ժեստն անելու դեպքում (երկու մատը էկրանի ներքևից սահեցրեք վերև)՝"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Ընտրեք ծառայությունը, որը կգործարկվի հատուկ գործառույթների ժեստն անելու դեպքում (երեք մատը էկրանի ներքևից սահեցրեք վերև)՝"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Մեկ ծառայությունից մյուսին անցնելու համար հպեք «Հատուկ գործառույթներ» կոճակին և պահեք:"</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Մեկ ծառայությունից մյուսին անցնելու համար երկու մատը սահեցրեք վերև և պահեք:"</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Մեկ ծառայությունից մյուսին անցնելու համար երեք մատը սահեցրեք վերև և պահեք:"</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>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Միացված է <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>-ին"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Հպեք՝ ֆայլերը տեսնելու համար"</string>
<string name="pin_target" msgid="8036028973110156895">"Ամրացնել"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Ամրացնել <xliff:g id="LABEL">%1$s</xliff:g> հավելվածը"</string>
<string name="unpin_target" msgid="3963318576590204447">"Ապամրացնել"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Ապամրացնել <xliff:g id="LABEL">%1$s</xliff:g> հավելվածը"</string>
<string name="app_info" msgid="6113278084877079851">"Հավելվածի տվյալներ"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Ցուցադրական օգտատերը գործարկվում է…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Թարմացնե՞լ տվյալները (<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_save_yes" msgid="8035743017382012850">"Պահել"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Ոչ"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Ոչ հիմա"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Երբեք"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Թարմացնել"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Շարունակել"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"գաղտնաբառ"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Միացնել/անջատել էկրանի տրոհումը"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Կողպէկրան"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Սքրինշոթ"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածը ելնող պատուհանում։"</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածի ենթագրերի գոտին։"</string>
</resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 1f81eb508bf3..299f23b817a7 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Aplikasi admin profil kerja tidak ada atau rusak. Akibatnya, profil kerja dan data terkait telah dihapus. Hubungi admin untuk meminta bantuan."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Profil kerja tidak tersedia lagi di perangkat ini"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Terlalu banyak percobaan memasukkan sandi"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Admin melepaskan perangkat untuk penggunaan pribadi"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Perangkat ini ada yang mengelola"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Organisasi mengelola perangkat ini dan mungkin memantau traffic jaringan. Ketuk untuk melihat detailnya."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Perangkat akan dihapus"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Mengizinkan aplikasi mengirim siaran permanen, yang tetap ada setelah siaran berakhir. Penggunaan yang berlebihan dapat membuat perangkat Android TV menjadi lambat atau tidak stabil dengan memicu penggunaan memori yang terlalu banyak."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Memungkinkan aplikasi mengirim siaran permanen, yang tetap ada setelah siaran berakhir. Penggunaan yang berlebihan dapat membuat ponsel menjadi lambat atau tidak stabil dengan memicu penggunaan memori yang terlalu banyak."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"baca kontak Anda"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Memungkinkan aplikasi membaca data tentang kontak yang disimpan pada tablet Anda, termasuk frekuensi Anda dalam melakukan panggilan, mengirim email, atau berkomunikasi dengan cara lain dengan individu tertentu. Izin ini memungkinkan aplikasi menyimpan data kontak, dan aplikasi berbahaya dapat berbagi data kontak tanpa sepengetahuan Anda."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Mengizinkan aplikasi membaca data tentang kontak yang disimpan di perangkat Android TV, termasuk frekuensi yang Anda gunakan saat melakukan panggilan, mengirim email, atau berkomunikasi dalam cara lain dengan individu tertentu. Izin ini memungkinkan aplikasi menyimpan data kontak, dan aplikasi berbahaya dapat membagikan data kontak tanpa sepengetahuan Anda."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Memungkinkan aplikasi membaca data tentang kontak yang disimpan pada ponsel Anda, termasuk frekuensi Anda dalam melakukan panggilan, mengirim email, atau berkomunikasi dengan cara lain dengan individu tertentu. Izin ini memungkinkan aplikasi menyimpan data kontak, dan aplikasi berbahaya dapat berbagi data kontak tanpa sepengetahuan Anda."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Mengizinkan aplikasi membaca data tentang kontak yang disimpan di tablet Anda. Aplikasi juga akan memiliki akses ke akun di tablet Anda yang telah membuat kontak. Ini mungkin mencakup akun yang dibuat oleh aplikasi yang telah diinstal. Izin ini mengizinkan aplikasi menyimpan data kontak, dan aplikasi berbahaya dapat membagikan data kontak tanpa sepengetahuan Anda."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Mengizinkan aplikasi membaca data tentang kontak yang disimpan di perangkat Android TV Anda. Aplikasi juga akan memiliki akses ke akun di perangkat Android TV Anda yang telah membuat kontak. Ini mungkin mencakup akun yang dibuat oleh aplikasi yang telah diinstal. Izin ini mengizinkan aplikasi menyimpan data kontak, dan aplikasi berbahaya dapat membagikan data kontak tanpa sepengetahuan Anda."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Mengizinkan aplikasi membaca data tentang kontak yang disimpan di ponsel Anda. Aplikasi juga akan memiliki akses ke akun di ponsel Anda yang telah membuat kontak. Ini mungkin mencakup akun yang dibuat oleh aplikasi yang telah diinstal. Izin ini mengizinkan aplikasi menyimpan data kontak, dan aplikasi berbahaya dapat membagikan data kontak tanpa sepengetahuan Anda."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"ubah kontak Anda"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Memungkinkan aplikasi mengubah data tentang kontak yang tersimpan dalam tablet Anda, termasuk frekuensi Anda dalam melakukan panggilan, mengirim email, atau berkomunikasi dalam cara lain dengan kontak tertentu. Izin ini memungkinkan aplikasi menghapus data kontak."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Mengizinkan aplikasi mengubah data tentang kontak yang disimpan di perangkat Android TV Anda, termasuk frekuensi yang Anda gunakan saat melakukan panggilan, mengirim email, atau berkomunikasi dalam cara lain dengan kontak tertentu. Izin ini memungkinkan aplikasi menghapus data kontak."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Memungkinkan aplikasi mengubah data tentang kontak yang tersimpan dalam ponsel Anda, termasuk frekuensi Anda dalam melakukan panggilan, mengirim email, atau berkomunikasi dalam cara lain dengan kontak tertentu. Izin ini memungkinkan aplikasi menghapus data kontak."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Mengizinkan aplikasi mengubah data tentang kontak yang disimpan di tablet Anda. Izin ini mengizinkan aplikasi menghapus data kontak."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Mengizinkan aplikasi mengubah data tentang kontak yang disimpan di perangkat Android TV Anda. Izin ini mengizinkan aplikasi menghapus data kontak."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Mengizinkan aplikasi mengubah data tentang kontak yang disimpan di ponsel Anda. Izin ini mengizinkan aplikasi menghapus data kontak."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"membaca log panggilan"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Aplikasi ini dapat membaca histori panggilan."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"menulis log panggilan"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"akses perintah penyedia lokasi ekstra"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Memungkinkan aplikasi mengakses perintah penyedia lokasi ekstra. Tindakan ini memungkinkan aplikasi mengganggu pengoperasian GPS atau sumber lokasi lain."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"akses lokasi pasti hanya saat di latar depan"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Aplikasi ini bisa mendapatkan lokasi pasti Anda ketika aplikasi berada di latar depan. Fitur layanan lokasi ini harus diaktifkan dan tersedia di ponsel agar dapat digunakan oleh aplikasi. Fitur ini dapat meningkatkan konsumsi baterai."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"akses perkiraan lokasi (berbasis jaringan) hanya di latar depan"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Aplikasi ini dapat mengetahui lokasi berdasarkan sumber jaringan seperti menara seluler dan jaringan Wi-Fi, namun hanya jika aplikasi berada di latar depan. Layanan lokasi tersebut harus diaktifkan dan tersedia di tablet agar aplikasi dapat menggunakannya."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Aplikasi ini dapat mengetahui lokasi Anda berdasarkan sumber jaringan seperti menara seluler dan jaringan Wi-Fi, tetapi hanya jika aplikasi berada di latar depan. Layanan lokasi ini harus diaktifkan dan tersedia di perangkat Android TV agar dapat digunakan oleh aplikasi."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Aplikasi ini dapat mengetahui lokasi berdasarkan sumber jaringan seperti menara seluler dan jaringan Wi-Fi, namun hanya jika aplikasi berada di latar depan. Layanan lokasi tersebut harus diaktifkan dan tersedia di ponsel agar aplikasi dapat menggunakannya."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Aplikasi ini bisa mendapatkan lokasi pasti Anda saat berada di latar depan. Fitur layanan lokasi harus diaktifkan dan tersedia di perangkat agar dapat digunakan oleh aplikasi. Fitur ini dapat meningkatkan konsumsi baterai."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"akses perkiraan lokasi hanya saat berada di latar depan"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Aplikasi ini bisa mendapatkan perkiraan lokasi Anda hanya saat berada di latar depan. Layanan lokasi harus diaktifkan dan tersedia di perangkat agar aplikasi dapat menggunakannya."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"akses lokasi di latar belakang"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Jika aplikasi diberi izin tambahan ke akses lokasi perkiraan atau akurat, aplikasi dapat mengakses lokasi saat bekerja di latar belakang."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Aplikasi ini dapat mengakses lokasi saat berjalan di latar belakang, selain akses lokasi latar depan."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"ubah setelan audio Anda"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Memungkinkan aplikasi mengubah setelan audio global, misalnya volume dan pengeras suara mana yang digunakan untuk keluaran."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"rekam audio"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Memungkinkan aplikasi melihat konfigurasi Bluetooth di tablet, dan membuat serta menerima sambungan dengan perangkat yang disandingkan."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Mengizinkan aplikasi melihat konfigurasi Bluetooth di perangkat Android TV, serta melakukan dan menerima sambungan dengan perangkat yang tersambung."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Memungkinkan aplikasi melihat konfigurasi Bluetooth di ponsel, dan membuat serta menerima sambungan dengan perangkat yang disandingkan."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Informasi Layanan Pembayaran NFC Pilihan"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Mengizinkan aplikasi untuk mendapatkan informasi layanan pembayaran NFC pilihan seperti bantuan terdaftar dan tujuan rute."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"kontrol NFC"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Mengizinkan apl berkomunikasi dengan tag, kartu, dan alat pembaca Komunikasi Nirkabel Jarak Dekat (NFC)."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"nonaktifkan kunci layar Anda"</string>
@@ -1535,8 +1534,8 @@
<string name="launchBrowserDefault" msgid="6328349989932924119">"Luncurkan Browser?"</string>
<string name="SetupCallDefault" msgid="5581740063237175247">"Terima panggilan?"</string>
<string name="activity_resolver_use_always" msgid="5575222334666843269">"Selalu"</string>
- <string name="activity_resolver_set_always" msgid="4142825808921411476">"Setel untuk selalu membuka"</string>
- <string name="activity_resolver_use_once" msgid="948462794469672658">"Hanya sekali"</string>
+ <string name="activity_resolver_set_always" msgid="4142825808921411476">"Selalu gunakan"</string>
+ <string name="activity_resolver_use_once" msgid="948462794469672658">"Sekali ini saja"</string>
<string name="activity_resolver_app_settings" msgid="6758823206817748026">"Setelan"</string>
<string name="activity_resolver_work_profiles_support" msgid="4071345609235361269">"%1$s tidak mendukung profil kerja"</string>
<string name="default_audio_route_name" product="tablet" msgid="367936735632195517">"Tablet"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"Pintasan Aksesibilitas mengaktifkan <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"Pintasan Aksesibilitas menonaktifkan <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Tekan dan tahan kedua tombol volume selama tiga detik untuk menggunakan <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Pilih layanan yang akan digunakan saat mengetuk tombol aksesibilitas:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Pilih layanan yang akan digunakan dengan gestur aksesibilitas (geser ke atas dari bawah layar dengan dua jari):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Pilih layanan yang akan digunakan dengan gestur aksesibilitas (geser ke atas dari bawah layar dengan tiga jari):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Sentuh lama tombol aksesibilitas untuk beralih layanan."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Geser dengan dua jari dan tahan untuk beralih layanan."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Geser ke atas dengan tiga jari dan tahan untuk beralih layanan."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Pembesaran"</string>
<string name="user_switched" msgid="7249833311585228097">"Pengguna saat ini <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="1912993630661332336">"Beralih ke <xliff:g id="NAME">%1$s</xliff:g>…"</string>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Tersambung ke <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Ketuk untuk melihat file"</string>
<string name="pin_target" msgid="8036028973110156895">"Pasang pin"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Pasang pin <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Lepas pin"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Lepas pin <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Info aplikasi"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Memulai demo..."</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Perbarui item-item berikut di "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, dan <xliff:g id="TYPE_2">%3$s</xliff:g> ?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Simpan"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Lain kali"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Lain kali"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Tidak pernah"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Update"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Lanjutkan"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"sandi"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Aktifkan/Nonaktifkan Layar Terpisah"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Layar Kunci"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Screenshot"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"Aplikasi <xliff:g id="APP_NAME">%1$s</xliff:g> di Jendela pop-up."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Kolom teks <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index d23cf5fff4a9..fe55b4ca566a 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Stjórnunarforrit vinnusniðsins vantar eða er skemmt. Vinnusniðinu og gögnum því tengdu hefur því verið eytt. Hafðu samband við kerfisstjórann til að fá frekari aðstoð."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Vinnusniðið þitt er ekki lengur í boði á þessu tæki"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Of margar tilraunir til að slá inn aðgangsorð"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Kerfisstjóri lét af hendi tæki til einkanota"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Tækinu er stjórnað"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Fyrirtækið þitt stjórnar þessu tæki og kann að fylgjast með netnotkun. Ýttu hér til að fá upplýsingar."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Tækið verður hreinsað"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Leyfir forritinu að senda viðvarandi tilkynningar, sem eru áfram í gangi eftir birtingu. Of mikil notkun þeirra getur hægt á virkni Android TV tækisins eða gert það óstöðugt með því að nota of mikið af minni þess."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Leyfir forriti að senda viðvarandi tilkynningar, sem eru áfram í gangi eftir birtingu. Of mikil notkun þeirra getur hægt á virkni símans eða gert hann óstöðugan með því að nota of mikið af minni hans."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"lesa tengiliði"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Leyfir forriti að lesa gögn um tengiliði sem vistuð eru í spjaldtölvunni, þ. á m. tíðni samskipta þinna við tiltekna tengiliði með símtölum, tölvupósti eða öðrum hætti. Þessi heimild gerir forritum kleift að vista tengiliðagögnin þín og spilliforrit kunna að deila tengiliðaupplýsingum án þinnar vitundar."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Leyfir forriti að lesa gögn um tengiliði sem vistuð eru í Android TV, þ. á m. tíðni samskipta þinna við tiltekna tengiliði með símtölum, tölvupósti eða öðrum hætti. Þessi heimild gerir forritum kleift að vista tengiliðagögnin þín og spilliforrit kunna að deila tengiliðaupplýsingum án þinnar vitundar."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Leyfir forriti að lesa gögn um tengiliði sem vistuð eru í símanum, þ. á m. tíðni samskipta þinna við tiltekna tengiliði með símtölum, tölvupósti eða öðrum hætti. Þessi heimild gerir forritum kleift að vista tengiliðagögnin þín og spilliforrit kunna að deila tengiliðaupplýsingum án þinnar vitundar."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Leyfir forritinu að lesa gögn um tengiliði sem vistuð eru í spjaldtölvunni þinni. Forrit munu einnig hafa aðgang að reikningum í spjaldtölvunni sem hafa búið til tengiliði. Þar á meðal geta verið reikningar sem forrit sem þú hefur sett upp hafa stofnað. Þessi heimild gerir forritum kleift að vista tengiliðagögnin þín og spilliforrit kunna að deila tengiliðaupplýsingum án þinnar vitundar."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Leyfir forritinu að lesa gögn um tengiliði sem vistuð eru í Android TV tækinu. Forrit munu einnig hafa aðgang að reikningum í Android TV tækinu sem hafa búið til tengiliði. Þar á meðal geta verið reikningar sem forrit sem þú hefur sett upp hafa stofnað. Þessi heimild gerir forritum kleift að vista tengiliðagögnin þín og spilliforrit kunna að deila tengiliðaupplýsingum án þinnar vitundar."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Leyfir forritinu að lesa gögn um tengiliði sem vistuð eru í símanum þínum. Forrit munu einnig hafa aðgang að reikningum í símanum sem hafa búið til tengiliði. Þar á meðal geta verið reikningar sem forrit sem þú hefur sett upp hafa stofnað. Þessi heimild gerir forritum kleift að vista tengiliðagögnin þín og spilliforrit kunna að deila tengiliðaupplýsingum án þinnar vitundar."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"breyta tengiliðunum þínum"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Leyfir forriti að breyta gögnum um tengiliði sem vistuð eru í spjaldtölvunni, þ. á m. tíðni samskipta þinna við tiltekna tengiliði með símtölum, tölvupósti eða öðrum hætti. Þessi heimild gerir forritum kleift að eyða tengiliðagögnum."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Leyfir forriti að breyta gögnum um tengiliði sem vistuð eru í Android TV, þ. á m. tíðni samskipta þinna við tiltekna tengiliði með símtölum, tölvupósti eða öðrum hætti. Þessi heimild gerir forritum kleift að eyða tengiliðagögnum."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Leyfir forriti að breyta gögnum um tengiliði sem vistuð eru í símanum, þ. á m. tíðni samskipta þinna við tiltekna tengiliði með símtölum, tölvupósti eða öðrum hætti. Þessi heimild gerir forritum kleift að eyða tengiliðagögnum."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Leyfir forriti að breyta gögnum um tengiliði sem vistuð eru í spjaldtölvunni. Þessi heimild gerir forritum kleift að eyða tengiliðagögnum."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Leyfir forriti að breyta gögnum um tengiliði sem vistuð eru í Android TV tækinu. Þessi heimild gerir forritum kleift að eyða tengiliðagögnum."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Leyfir forriti að breyta gögnum um tengiliði sem vistuð eru í símanum þínum. Þessi heimild gerir forritum kleift að eyða tengiliðagögnum."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"lesa símtalaskrá"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Þetta forrit getur lesið símtalaferilinn þinn."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"skrifa símtalaskrá"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"aðgangur að viðbótarskipunum staðsetningarveitu"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Leyfir forriti að fá aðgang að fleiri skipunum staðsetningarveitu. Þetta getur gert forritinu kleift að hafa áhrif á virkni GPS og annars staðsetningarbúnaðar."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"aðgangur að nákvæmri staðsetningu aðeins í forgrunni"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Þetta forrit getur aðeins séð staðsetningu þína þegar það er í forgrunni. Það verður að vera kveikt á þessari staðsetningarþjónustu og hún þarf að vera aðgengileg í símanum til að forritið geti notað hana. Þetta getur aukið rafhlöðunotkun."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"aðgangur að áætlaðri staðsetningu (út frá netkerfi), aðeins í forgrunni"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Þetta forrit getur séð staðsetningu þína út frá netkerfum á borð við farsímasenda og Wi-Fi net, en þó aðeins þegar það er í forgrunni. Það verður að vera kveikt á þessari staðsetningarþjónustu og hún þarf að vera aðgengileg spjaldtölvunni til að forritið geti notað hana."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Þetta forrit getur séð staðsetningu þína út frá netkerfum á borð við farsímasenda og Wi-Fi net, en þó aðeins þegar það er í forgrunni. Það verður að vera kveikt á þessari staðsetningarþjónustu og hún þarf að vera aðgengileg Android TV tækinu til að forritið geti notað hana."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Þetta forrit getur séð staðsetningu þína út frá netkerfum á borð við farsímasenda og Wi-Fi net, en þó aðeins þegar það er í forgrunni. Það verður að vera kveikt á þessari staðsetningarþjónustu og hún þarf að vera aðgengileg símanum til að forritið geti notað hana."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Þetta forrit getur aðeins séð staðsetningu þína þegar það er í forgrunni. Það verður að vera kveikt á staðsetningarþjónustu og hún þarf að vera tiltæk í tækinu til að forritið geti notað hana. Þetta getur aukið rafhlöðunotkun."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"aðgangur að áætlaðri staðsetningu aðeins í forgrunni"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Þetta forrit getur aðeins séð áætlaða staðsetningu þína þegar það er í forgrunni. Það verður að vera kveikt á staðsetningarþjónustu og hún þarf að vera tiltæk í tækinu til að forritið geti notað hana."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"aðgangur að staðsetningu í bakgrunni"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Ef þetta er veitt til viðbótar við aðgang að áætlaðri eða nákvæmri staðsetningu getur forritið fengið aðgang að staðsetningu á meðan það keyrir í bakgrunni."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Þetta forrit hefur aðgang að staðsetningu þegar það er í gangi í bakgrunni, og auk þess þegar það er í forgrunni."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"breyta hljóðstillingum"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Leyfir forriti að breyta altækum hljóðstillingum, s.s. hljóðstyrk og hvaða hátalari er notaður sem úttak."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"taka upp hljóð"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Leyfir forriti að skoða grunnstillingu Bluetooth í spjaldtölvunni og koma á og samþykkja tengingar við pöruð tæki."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Leyfir forriti að skoða stillingu Bluetooth í Android TV og tengjast og samþykkja tengingar við pöruð tæki."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Leyfir forriti að skoða grunnstillingu Bluetooth í símanum og koma á og samþykkja tengingar við pöruð tæki."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Upplýsingar um valda NFC-greiðsluþjónustu"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Gerir forritinu kleift að fá valda NFC-greiðsluþjónustu, svo sem skráða aðstoð og áfangastað leiðar."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"stjórna nándarsamskiptum (NFC)"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Leyfir forriti að eiga samskipti við NFC-merki, -spjöld og -lesara (nándarsamskipti)."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"slökkva á skjálásnum"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"Flýtileið aðgengisstillingar kveikti á <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"Flýtileið aðgengisstillingar slökkti á <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Haltu báðum hljóðstyrkstökkunum inni í þrjár sekúndur til að nota <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Veldu þjónustu sem á að nota þegar ýtt er á aðgengishnappinn:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Veldu þjónustu sem á að nota með aðgengisbendingunni (strjúka upp frá neðri hluta skjásins með tveimur fingrum):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Veldu þjónustu sem á að nota með aðgengisbendingunni (strjúka upp frá neðri hluta skjásins með þremur fingrum):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Til að skipta á milli þjónusta skaltu halda aðgengishnappinum inni."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Til að skipta á milli þjónusta skaltu strjúka upp með tveimur fingrum og halda inni."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Til að skipta á milli þjónusta skaltu strjúka upp með þremur fingrum og halda inni."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Stækkun"</string>
<string name="user_switched" msgid="7249833311585228097">"Núverandi notandi <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="1912993630661332336">"Skiptir yfir á <xliff:g id="NAME">%1$s</xliff:g>…"</string>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Tengt við <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Ýttu til að skoða skrárnar"</string>
<string name="pin_target" msgid="8036028973110156895">"Festa"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Festa <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Losa"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Losa <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Forritsupplýsingar"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Byrjar kynningu…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Uppfæra þessi atriði í "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> og <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Vista"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Nei, takk"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Ekki núna"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Aldrei"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Uppfæra"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Áfram"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"aðgangsorð"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Breyta skjáskiptingu"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Lásskjár"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Skjámynd"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"Forritið <xliff:g id="APP_NAME">%1$s</xliff:g> í sprettiglugga."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Skjátextastika <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 8ebcb0e07405..87a1191da101 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -142,7 +142,7 @@
<string name="wfcSpnFormat_wifi" msgid="1376356951297043426">"Wi-Fi"</string>
<string name="wfcSpnFormat_wifi_calling_wo_hyphen" msgid="7178561009225028264">"Chiamate Wi-Fi"</string>
<string name="wfcSpnFormat_vowifi" msgid="8371335230890725606">"VoWifi"</string>
- <string name="wifi_calling_off_summary" msgid="5626710010766902560">"Off"</string>
+ <string name="wifi_calling_off_summary" msgid="5626710010766902560">"OFF"</string>
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Chiamata tramite Wi-Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Chiamata su rete mobile"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Solo Wi-Fi"</string>
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"L\'app di amministrazione dei profili di lavoro manca o è danneggiata. Di conseguenza, il tuo profilo di lavoro e i relativi dati sono stati eliminati. Contatta l\'amministratore per ricevere assistenza."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Il tuo profilo di lavoro non è più disponibile sul dispositivo"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Troppi tentativi di inserimento della password"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"L\'amministratore ha abbandonato il dispositivo per uso personale"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Il dispositivo è gestito"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Questo dispositivo è gestito dalla tua organizzazione, che potrebbe monitorare il traffico di rete. Tocca per i dettagli."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Il dispositivo verrà resettato"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Consente all\'app di inviare annunci permanenti, che permangono anche al termine dell\'annuncio. Un uso eccessivo potrebbe rendere il dispositivo Android TV lento o instabile causando un uso eccessivo della memoria."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Consente all\'applicazione di inviare broadcast permanenti, che permangono anche al termine del broadcast. Un uso eccessivo potrebbe rendere il telefono lento o instabile causando un uso eccessivo della memoria."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"lettura contatti personali"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Consente all\'applicazione di leggere i dati relativi ai tuoi contatti memorizzati sul tablet, inclusa la frequenza con cui hai effettuato chiamate, inviato email o comunicato in altri modi con individui specifici. Questa autorizzazione consente alle applicazioni di salvare i dati dei tuoi contatti e applicazioni dannose potrebbero condividere i dati dei contatti a tua insaputa."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Consente all\'app di leggere i dati relativi ai contatti memorizzati sul dispositivo Android TV, inclusa la frequenza con cui hai chiamato contatti specifici, hai inviato loro email o hai comunicato con loro in altri modi. Questa autorizzazione consente alle app di salvare i dati dei tuoi contatti e app dannose potrebbero condividere i dati dei contatti a tua insaputa."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Consente all\'applicazione di leggere i dati relativi ai tuoi contatti memorizzati sul telefono, inclusa la frequenza con cui hai effettuato chiamate, inviato email o comunicato in altri modi con individui specifici. Questa autorizzazione consente alle applicazioni di salvare i dati dei tuoi contatti e applicazioni dannose potrebbero condividere i dati dei contatti a tua insaputa."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Consente all\'app di leggere i dati relativi ai contatti memorizzati sul tablet. Le app avranno inoltre accesso agli account memorizzati sul tablet su cui sono stati creati contatti. Potrebbero essere inclusi gli account creati da app installate. Questa autorizzazione consente alle app di salvare i dati dei tuoi contatti e app dannose potrebbero condividere i dati dei contatti a tua insaputa."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Consente all\'app di leggere i dati relativi ai contatti memorizzati sul dispositivo Android TV. Le app avranno inoltre accesso agli account memorizzati sul dispositivo Android TV su cui sono stati creati contatti. Potrebbero essere inclusi gli account creati da app installate. Questa autorizzazione consente alle app di salvare i dati dei tuoi contatti e app dannose potrebbero condividere i dati dei contatti a tua insaputa."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Consente all\'app di leggere i dati relativi ai contatti memorizzati sul telefono. Le app avranno inoltre accesso agli account memorizzati sul telefono su cui sono stati creati contatti. Potrebbero essere inclusi gli account creati da app installate. Questa autorizzazione consente alle app di salvare i dati dei tuoi contatti e app dannose potrebbero condividere i dati dei contatti a tua insaputa."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"modifica dei contatti personali"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Consente all\'applicazione di modificare i dati relativi ai contatti memorizzati sul tablet, inclusa la frequenza con cui hai effettuato chiamate, inviato email o comunicato in altri modi con contatti specifici. Questa autorizzazione consente alle applicazioni di eliminare i dati dei contatti."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Consente all\'app di modificare i dati relativi ai contatti memorizzati sul dispositivo Android TV, inclusa la frequenza con cui hai chiamato contatti specifici, hai inviato loro email o hai comunicato con loro in altri modi. Questa autorizzazione consente all\'app di eliminare i dati dei contatti."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Consente all\'applicazione di modificare i dati relativi ai contatti memorizzati sul telefono, inclusa la frequenza con cui hai effettuato chiamate, inviato email o comunicato in altri modi con contatti specifici. Questa autorizzazione consente alle applicazioni di eliminare i dati dei contatti."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Consente all\'app di modificare i dati relativi ai contatti memorizzati sul tablet. Questa autorizzazione consente alle app di eliminare i dati dei contatti."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Consente all\'app di modificare i dati relativi ai contatti memorizzati sul dispositivo Android TV. Questa autorizzazione consente alle app di eliminare i dati dei contatti."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Consente all\'app di modificare i dati relativi ai contatti memorizzati sul telefono. Questa autorizzazione consente alle app di eliminare i dati dei contatti."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"lettura del registro chiamate"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Questa app può leggere la cronologia chiamate."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"scrittura del registro chiamate"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"accesso a comandi aggiuntivi provider di geolocalizz."</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Consente all\'app di accedere a ulteriori comandi del fornitore di posizione. Ciò potrebbe consentire all\'app di interferire con il funzionamento del GPS o di altre fonti di geolocalizzazione."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"accesso alla posizione esatta solo in primo piano"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Questa app può recuperare la tua posizione esatta solo quando è in primo piano. Questi servizi di geolocalizzazione devono essere attivi e disponibili sul telefono affinché l\'app possa usarli. Potrebbe aumentare il consumo della batteria."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"accesso alla posizione approssimativa (in base alla rete) solo in primo piano"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Questa app può recuperare la tua posizione tramite fonti di rete quali ripetitori di telefonia mobile e reti Wi-Fi, ma soltanto quando l\'app è in primo piano. Questi servizi di geolocalizzazione devono essere attivi e disponibili sul tablet affinché l\'app possa usarli."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Questa app può recuperare la tua posizione tramite fonti di rete quali ripetitori di telefonia mobile e reti Wi-Fi, ma soltanto quando l\'app è in primo piano. Questi servizi di geolocalizzazione devono essere attivi e disponibili sul dispositivo Android TV affinché l\'app possa usarli."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Questa app può recuperare la tua posizione tramite fonti di rete quali ripetitori di telefonia mobile e reti Wi-Fi, ma soltanto quando l\'app è in primo piano. Questi servizi di geolocalizzazione devono essere attivi e disponibili sul telefono affinché l\'app possa usarli."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Questa app può recuperare la tua posizione esatta solo quando è in primo piano. I servizi di geolocalizzazione devono essere attivi e disponibili sul dispositivo affinché l\'app possa usarli. Potrebbe aumentare il consumo della batteria."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"Accesso alla posizione approssimativa solo in primo piano"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Questa app può recuperare la tua posizione approssimativa solo quando è in primo piano. I servizi di geolocalizzazione devono essere attivi e disponibili sull\'auto affinché l\'app possa usarli."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"accesso alla posizione in background"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Se concedi l\'autorizzazione insieme all\'accesso alla posizione precisa o approssimativa, l\'app potrà accedere alla posizione mentre viene eseguita in background."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Questa app può accedere alla posizione in background, oltre ad accedervi in primo piano."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"modifica impostazioni audio"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Consente all\'applicazione di modificare le impostazioni audio globali, come il volume e quale altoparlante viene utilizzato per l\'uscita."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"registrazione audio"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Consente all\'applicazione di visualizzare la configurazione del Bluetooth sul tablet e di stabilire e accettare connessioni con dispositivi accoppiati."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Consente all\'app di visualizzare la configurazione del Bluetooth del dispositivo Android TV, nonché di stabilire e accettare connessioni con dispositivi accoppiati."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Consente all\'applicazione di visualizzare la configurazione del Bluetooth sul telefono e di stabilire e accettare connessioni con dispositivi accoppiati."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Informazioni del servizio di pagamento NFC preferito"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Consente all\'app di recuperare informazioni del servizio di pagamento NFC preferito, quali destinazione della route e identificatori applicazione registrati."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"controllo Near Field Communication"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Consente all\'applicazione di comunicare con tag, schede e lettori NFC (Near Field Communication)."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"disattivazione blocco schermo"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"La scorciatoia Accessibilità ha attivato <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"La scorciatoia Accessibilità ha disattivato <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Tieni premuti entrambi i tasti del volume per tre secondi per utilizzare <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Scegli un servizio da usare quando tocchi il pulsante Accessibilità:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Scegli un servizio da usare con il gesto di accessibilità (scorrimento verso l\'alto dalla parte inferiore dello schermo con due dita):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Scegli un servizio da usare con il gesto di accessibilità (scorrimento verso l\'alto dalla parte inferiore dello schermo con tre dita):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Per spostarti tra i servizi, tocca e tieni premuto il pulsante Accessibilità."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Per spostarti tra i servizi, scorri verso l\'alto con due dita e tieni premuto."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Per spostarti tra i servizi, scorri verso l\'alto con tre dita e tieni premuto."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Ingrandimento"</string>
<string name="user_switched" msgid="7249833311585228097">"Utente corrente <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="1912993630661332336">"Passaggio a <xliff:g id="NAME">%1$s</xliff:g>…"</string>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Connesso a <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Tocca per visualizzare i file"</string>
<string name="pin_target" msgid="8036028973110156895">"Blocca"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Blocca <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Sgancia"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Sblocca <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Informazioni app"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Avvio della demo…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Vuoi aggiornare questi elementi su "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Salva"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"No, grazie"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Non ora"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Mai"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Aggiorna"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Continua"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"password"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Attiva/disattiva schermo diviso"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Schermata di blocco"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Screenshot"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"App <xliff:g id="APP_NAME">%1$s</xliff:g> in una finestra popup."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Barra del titolo di <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 85d0f3b5fee7..f4624ba1a0cf 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -192,8 +192,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"אפליקציית הניהול של פרופיל העבודה חסרה או פגומה. כתוצאה מכך, פרופיל העבודה שלך נמחק, כולל כל הנתונים הקשורים אליו. לקבלת עזרה, פנה למנהל המערכת."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"פרופיל העבודה שלך אינו זמין עוד במכשיר הזה"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"בוצעו ניסיונות רבים מדי להזנת סיסמה"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"מנהל המערכת ביטל את המכשיר לצורכי שימוש אישי"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"המכשיר מנוהל"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"הארגון שלך מנהל מכשיר זה ועשוי לנטר את התנועה ברשת. הקש לקבלת פרטים."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"תתבצע מחיקה של המכשיר"</string>
@@ -387,13 +386,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"‏מאפשרת לאפליקציה לשלוח שידורים \"דביקים\" (sticky), שנותרים לאחר שהשידור מסתיים. בעקבות שימוש מופרז באפשרות זו, שיעור ניצול הזיכרון יהיה גבוה מדי ומכשיר ה-Android TV עלול לפעול בצורה איטית או בלתי יציבה."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"מאפשר לאפליקציה לשלוח שידורים דביקים, אשר נותרים לאחר סיום השידור. אפליקציות זדוניות עלולות להאט את פעילות הטלפון או להפוך אותה לבלתי יציבה על ידי אילוץ המכשיר להשתמש ביותר מדי זיכרון."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"קריאת אנשי הקשר שלך"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"מאפשר לאפליקציה לקרוא נתונים לגבי אנשי הקשר שלך המאוחסנים בטאבלט, כולל את התדירות שבה התקשרת, שלחת אימייל או יצרת קשר בדרכים אחרות עם אנשים ספציפיים. אישור זה מתיר לאפליקציות לשמור את נתוני אנשי הקשר שלך. כמו כן, אפליקציות זדוניות עשויות לשתף נתוני אנשי קשר ללא ידיעתך."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"‏מאפשרת לאפליקציה לקרוא נתונים על אנשי הקשר השמורים במכשיר ה-Android TV, כולל התדירות שבה התקשרת, שלחת אימייל או יצרת קשר בדרכים אחרות עם אנשי קשר ספציפיים. הרשאה זו מאפשרת לאפליקציות לשמור נתונים של אנשי הקשר שלך, ואפליקציות זדוניות עלולות לשתף נתונים של אנשי קשר ללא ידיעתך."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"מאפשר לאפליקציה לקרוא נתונים לגבי אנשי הקשר שלך המאוחסנים בטלפון, כולל את התדירות שבה התקשרת, שלחת אימייל או יצרת קשר בדרכים אחרות עם אנשים ספציפיים. אישור זה מתיר לאפליקציות לשמור את נתוני אנשי הקשר שלך. כמו כן, אפליקציות זדוניות עשויות לשתף נתוני אנשי קשר ללא ידיעתך."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"מאפשרת לאפליקציה לקרוא נתונים על אנשי הקשר השמורים בטאבלט שלך. לאפליקציות תהיה גם גישה לחשבונות בטאבלט שיצרו אנשי קשר. פעולה זו עשויה לכלול חשבונות שנוצרו על ידי אפליקציות שהתקנת. הרשאה זו מאפשרת לאפליקציות לשמור נתונים של אנשי הקשר שלך, ואפליקציות זדוניות עלולות לשתף נתונים של אנשי קשר ללא ידיעתך."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"‏מאפשרת לאפליקציה לקרוא נתונים על אנשי הקשר השמורים במכשיר ה-Android TV שלך. לאפליקציות תהיה גם גישה לחשבונות במכשיר ה-Android TV שיצרו אנשי קשר. פעולה זו עשויה לכלול חשבונות שנוצרו על ידי אפליקציות שהתקנת. הרשאה זו מאפשרת לאפליקציות לשמור נתונים של אנשי הקשר שלך, ואפליקציות זדוניות עלולות לשתף נתונים של אנשי קשר ללא ידיעתך."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"מאפשרת לאפליקציה לקרוא נתונים על אנשי הקשר השמורים בטלפון שלך. לאפליקציות תהיה גם גישה לחשבונות בטלפון שיצרו אנשי קשר. פעולה זו עשויה לכלול חשבונות שנוצרו על ידי אפליקציות שהתקנת. הרשאה זו מאפשרת לאפליקציות לשמור נתונים של אנשי הקשר שלך, ואפליקציות זדוניות עלולות לשתף נתונים של אנשי קשר ללא ידיעתך."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"שינוי אנשי הקשר שלך"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"מאפשר לאפליקציה לשנות את הנתונים לגבי אנשי הקשר שלך המאוחסנים בטאבלט, כולל התדירות שבה התקשרת, שלחת אימייל או יצרת קשר בדרכים אחרות עם אנשי קשר ספציפיים. אישור זה מתיר לאפליקציות למחוק נתוני אנשי קשר."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"‏מאפשרת לאפליקציה לשנות נתונים לגבי אנשי הקשר שלך השמורים במכשיר Android TV, כולל התדירות שבה התקשרת, שלחת אימייל או יצרת קשר בדרכים אחרות עם אנשי קשר ספציפיים. הרשאה זו מאפשרת לאפליקציות למחוק נתונים של אנשי קשר."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"מאפשר לאפליקציה לשנות את הנתונים לגבי אנשי הקשר שלך המאוחסנים בטלפון, כולל התדירות שבה התקשרת, שלחת אימייל או יצרת קשר בדרכים אחרות עם אנשי קשר ספציפיים. אישור זה מתיר לאפליקציות למחוק נתוני אנשי קשר."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"מאפשרת לאפליקציה לשנות את הנתונים לגבי אנשי הקשר המאוחסנים בטאבלט שלך. הרשאה זו מאפשרת לאפליקציות למחוק נתונים של אנשי קשר."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"‏מאפשרת לאפליקציה לשנות את הנתונים לגבי אנשי הקשר המאוחסנים במכשיר ה-Android TV שלך. הרשאה זו מאפשרת לאפליקציות למחוק נתונים של אנשי קשר."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"מאפשרת לאפליקציה לשנות את הנתונים לגבי אנשי הקשר המאוחסנים בטלפון שלך. הרשאה זו מאפשרת לאפליקציות למחוק נתונים של אנשי קשר."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"קריאת יומן שיחות"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"אפליקציה זו יכולה לקרוא את היסטוריית השיחות שלך."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"כתיבת יומן שיחות"</string>
@@ -413,13 +412,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"גישה לפקודות ספק מיקום נוספות"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"‏מאפשרת לאפליקציה לגשת לפקודות נוספות של ספק המיקום. הרשאה זו עשויה לאפשר לאפליקציה לשבש את פעולת ה-GPS או מקורות מיקום אחרים."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"קבלת גישה למיקום מדויק בחזית בלבד"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"אפליקציה זו יכולה לזהות את המיקום המדויק שלך רק כאשר היא פועלת בחזית. כדי שהאפליקציה תוכל להשתמש בשירותי המיקום, עליהם להיות מופעלים וזמינים בטלפון. ייתכן שפעולה זו תגביר את צריכת הסוללה."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"קבלת גישה למיקום המשוער (מבוסס-רשת) רק במצב פעיל"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"‏אפליקציה זו יכולה לזהות את המיקום שלך על סמך מקורות מיקום ברשת, כגון אנטנות סלולריות ורשתות Wi-Fi, אבל רק כשהאפליקציה במצב פעיל. שירותי מיקום אלה חייבים להיות מופעלים וזמינים בטאבלט כדי שהאפליקציה תוכל להשתמש בהם."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"‏אפליקציה זו יכולה לזהות את המיקום שלך על סמך מקורות מיקום ברשת, כגון אנטנות סלולריות ורשתות Wi-Fi, אבל רק כשהאפליקציה במצב פעיל. שירותי מיקום אלה חייבים להיות מופעלים וזמינים במכשיר ה-Android TV כדי שהאפליקציה תוכל להשתמש בהם."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"‏אפליקציה זו יכולה לזהות את המיקום שלך על סמך מקורות מיקום ברשת, כגון אנטנות סלולריות ורשתות Wi-Fi, אבל רק כשהאפליקציה במצב פעיל. שירותי מיקום אלה חייבים להיות מופעלים וזמינים בטלפון כדי שהאפליקציה תוכל להשתמש בהם."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"אפליקציה זו יכולה לזהות את המיקום המדויק שלך רק כאשר היא פועלת בחזית. כדי שהאפליקציה תוכל להשתמש בשירותי המיקום, עליהם להיות מופעלים וזמינים במכשיר. ייתכן שפעולה זו תגביר את צריכת הסוללה."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"קבלת גישה למיקום משוער תתבצע בחזית בלבד"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"אפליקציה זו יכולה לזהות את המיקום המשוער שלך רק כאשר היא פועלת בחזית. שירותי מיקום חייבים להיות מופעלים וזמינים במכשיר שלך כדי שהאפליקציה תוכל להשתמש בהם."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"גישה למיקום ברקע"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"אם מתקבל אישור, בנוסף לגישה למיקום משוער או מדויק, תהיה לאפליקציה גישה למיקום גם כשהיא פועלת ברקע."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"האפליקציה הזו יכולה לגשת למיקום כשהיא רצה ברקע, בנוסף לקבלת גישה למיקום בחזית."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"שנה את הגדרות האודיו שלך"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"מאפשר לאפליקציה לשנות הגדרות אודיו גלובליות כמו עוצמת קול ובחירת הרמקול המשמש לפלט."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"הקלט אודיו"</string>
@@ -500,6 +497,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"‏מאפשר לאפליקציה להציג את תצורת ה-Bluetooth בטאבלט, וכן ליצור ולקבל חיבורים עם מכשירים מותאמים."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"‏מאפשרת לאפליקציה להציג את הגדרת ה-Bluetooth במכשיר ה-Android TV, וליצור ולקבל חיבורים עם מכשירים מותאמים."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"‏מאפשר לאפליקציה להציג את תצורת ה-Bluetooth בטלפון, וכן ליצור ולקבל חיבורים עם מכשירים מותאמים."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"‏פרטים על שירות תשלום מועדף ב-NFC"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"‏מאפשרת לאפליקציה לקבל פרטים על שירות תשלום מועדף ב-NFC, כמו עזרים רשומים ויעד של נתיב."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"‏שלוט ב-Near Field Communication"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"מאפשר לאפליקציה נהל תקשורת עם תגים, כרטיסים וקוראים מסוג \'תקשורת מטווח קצר\'."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"ביטול נעילת המסך שלך"</string>
@@ -543,7 +542,7 @@
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"פעולת טביעת האצבע בוטלה בידי המשתמש."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"יותר מדי ניסיונות. נסה שוב מאוחר יותר."</string>
<string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"יותר מדי ניסיונות. חיישן טביעות האצבע הושבת."</string>
- <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"נסה שוב."</string>
+ <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"כדאי לנסות שוב."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"לא נרשמו טביעות אצבע."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"במכשיר זה אין חיישן טביעות אצבע."</string>
<string name="fingerprint_name_template" msgid="8941662088160289778">"אצבע <xliff:g id="FINGERID">%d</xliff:g>"</string>
@@ -814,8 +813,8 @@
<string name="lockscreen_emergency_call" msgid="7500692654885445299">"חירום"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"חזרה לשיחה"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"נכון!"</string>
- <string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"נסה שוב"</string>
- <string name="lockscreen_password_wrong" msgid="8605355913868947490">"נסה שוב"</string>
+ <string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"כדאי לנסות שוב"</string>
+ <string name="lockscreen_password_wrong" msgid="8605355913868947490">"כדאי לנסות שוב"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"בטל את הנעילה לכל התכונות והנתונים"</string>
<string name="faceunlock_multiple_failures" msgid="681991538434031708">"חרגת ממספר הניסיונות המרבי של זיהוי פנים"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"‏אין כרטיס SIM"</string>
@@ -1662,12 +1661,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> הופעל על-ידי קיצור הדרך לנגישות"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"<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>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"יש לבחור שירות שיופעל באמצעות הקשה על לחצן הנגישות:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"יש לבחור שירות שיופעל באמצעות תנועת הנגישות (החלקה למעלה מתחתית המסך בעזרת שתי אצבעות):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"יש לבחור שירות שיופעל באמצעות תנועת הנגישות (החלקה למעלה מתחתית המסך בעזרת שלוש אצבעות):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"כדי לעבור בין שירותים, יש ללחוץ לחיצה ארוכה על לחצן הנגישות."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"כדי לעבור בין שירותים, יש להחליק כלפי מעלה בעזרת שתי אצבעות ולהחזיק."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"כדי לעבור בין שירותים, יש להחליק כלפי מעלה בעזרת שלוש אצבעות ולהחזיק."</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>
@@ -1926,7 +1919,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"מחובר אל <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"הקש כדי להציג קבצים"</string>
<string name="pin_target" msgid="8036028973110156895">"הצמד"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"הצמדה של‏ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"בטל הצמדה"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"ביטול ההצמדה של <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"פרטי אפליקציה"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"מתחיל בהדגמה…"</string>
@@ -1971,6 +1966,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"האם לעדכן פריטים אלה ב-"<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <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> ?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"שמירה"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"לא, תודה"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"לא עכשיו"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"אף פעם"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"עדכון"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"המשך"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"סיסמה"</string>
@@ -2068,5 +2065,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"החלפת מצב של מסך מפוצל"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"מסך הנעילה"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"צילום מסך"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"האפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> בחלון קופץ."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"סרגל כיתוב של <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index e21035f06ac4..79d9faa107e4 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"仕事用プロファイルの管理アプリがないか、破損しています。そのため仕事用プロファイルと関連データが削除されました。管理者にサポートをご依頼ください。"</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"お使いの仕事用プロファイルはこのデバイスで使用できなくなりました"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"パスワード入力回数が上限を超えました"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"管理者により、デバイスの個人使用が許可されました"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"管理対象のデバイス"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"このデバイスは組織によって管理され、ネットワーク トラフィックが監視される場合があります。詳しくはタップしてください。"</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"デバイスのデータが消去されます"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"配信が終了してもメモリに残る sticky ブロードキャストの配信をアプリに許可します。この許可を使用しすぎると、メモリの使用量が増えて Android TV デバイスの動作が遅くなったり不安定になったりすることがあります。"</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"配信が終了してもメモリに残るstickyブロードキャストの配信をアプリに許可します。この許可を使用し過ぎると、メモリの使用量が増えてモバイル デバイスの動作が遅くなったり不安定になったりする恐れがあります。"</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"連絡先の読み取り"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"タブレットに保存されている連絡先に関するデータの読み取りをアプリに許可します。このデータには、電話、メール、または他の手段で特定の相手と連絡をとった頻度も含まれます。これにより、アプリに連絡先データの保存を許可することになり、悪意のあるアプリによって知らないうちに連絡先データが共有される恐れがあります。"</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Android TV デバイスに保存されている連絡先に関するデータの読み取りをアプリに許可します。このデータには、電話、メール、または他の手段で特定の相手と連絡をとった頻度も含まれます。これにより、連絡先データの保存をアプリに許可することになり、悪意のあるアプリによって知らないうちに連絡先データが共有される恐れがあります。"</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"モバイル デバイスに保存されている連絡先に関するデータの読み取りをアプリに許可します。このデータには、電話、メール、または他の手段で特定の相手と連絡をとった頻度も含まれます。これにより、アプリに連絡先データの保存を許可することになり、悪意のあるアプリによって知らないうちに連絡先データが共有される恐れがあります。"</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"タブレットに保存されている連絡先に関するデータの読み取りをアプリに許可します。また、この読み取りを許可したアプリは、連絡先を作成したタブレット上のアカウントにもアクセスできます。これには、インストールしたアプリによって作成されたアカウントも含まれます。これにより、連絡先データの保存をアプリに許可することになり、悪意のあるアプリによって知らないうちに連絡先データが共有される恐れがあります。"</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Android TV デバイスに保存されている連絡先に関するデータの読み取りをアプリに許可します。また、この読み取りを許可したアプリは、連絡先を作成した Android TV デバイス上のアカウントにもアクセスできます。これには、インストールしたアプリによって作成されたアカウントも含まれます。これにより、連絡先データの保存をアプリに許可することになり、悪意のあるアプリによって知らないうちに連絡先データが共有される恐れがあります。"</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"スマートフォンに保存されている連絡先に関するデータの読み取りをアプリに許可します。また、この読み取りを許可したアプリは、連絡先を作成したスマートフォン上のアカウントにもアクセスできます。これには、インストールしたアプリによって作成されたアカウントも含まれます。これにより、連絡先データの保存をアプリに許可することになり、悪意のあるアプリによって知らないうちに連絡先データが共有される恐れがあります。"</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"連絡先の変更"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"タブレットに保存されている連絡先に関するデータの変更をアプリに許可します。このデータには、電話、メール、または他の手段で特定の相手と連絡をとった頻度も含まれます。これにより、アプリが連絡先データを削除できるようになります。"</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Android TV デバイスに保存されている連絡先に関するデータの変更をアプリに許可します。このデータには、電話、メール、または他の手段で特定の相手と連絡をとった頻度も含まれます。これにより、連絡先データの削除をアプリに許可することになります。"</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"モバイルデバイスに保存されている連絡先に関するデータの変更をアプリに許可します。このデータには、電話、メール、または他の手段で特定の相手と連絡をとった頻度も含まれます。これにより、アプリが連絡先データを削除できるようになります。"</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"タブレットに保存されている連絡先に関するデータの変更をアプリに許可します。これにより、連絡先データの削除をアプリに許可することになります。"</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Android TV デバイスに保存されている連絡先に関するデータの変更をアプリに許可します。これにより、連絡先データの削除をアプリに許可することになります。"</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"スマートフォンに保存されている連絡先に関するデータの変更をアプリに許可します。これにより、連絡先データの削除をアプリに許可することになります。"</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"通話履歴の読み取り"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"このアプリは通話履歴を読み取ることができます。"</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"通話履歴の書き込み"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"位置情報提供者の追加コマンドアクセス"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"位置情報提供元の追加のコマンドにアクセスすることをアプリに許可します。許可すると、アプリがGPSなどの位置情報源の動作を妨害する恐れがあります。"</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"フォアグラウンドでのみ正確な位置情報にアクセス"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"このアプリは、フォアグラウンド状態でのみユーザーの正確な位置情報を取得できます。この位置情報サービスは ON の状態にして、スマートフォンでアプリがサービスを利用できるようにする必要があります。これにより、電池の消費量が増える可能性があります。"</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"フォアグラウンドでのみ(ネットワークに基づく)おおよその位置情報にアクセス"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"このアプリは、フォアグラウンドでのみ、ネットワーク位置情報源(携帯基地局や Wi-Fi ネットワークなど)に基づいて、ユーザーの位置情報を取得できます。これらの位置情報サービスは ON の状態にして、タブレットでアプリがサービスを利用できるようにする必要があります。"</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"このアプリは、フォアグラウンドでのみ、ネットワーク位置情報源(携帯基地局や Wi-Fi ネットワークなど)に基づいて、ユーザーの位置情報を取得できます。これらの位置情報サービスは ON の状態にして、Android TV デバイスでアプリがサービスを利用できるようにする必要があります。"</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"このアプリは、フォアグラウンドでのみ、ネットワーク位置情報源(携帯基地局や Wi-Fi ネットワークなど)に基づいて、ユーザーの位置情報を取得できます。これらの位置情報サービスは ON の状態にして、スマートフォンでアプリがサービスを利用できるようにする必要があります。"</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"このアプリは、フォアグラウンドでのみユーザーの正確な位置情報を取得できます。位置情報サービスを ON にして、デバイスでアプリがサービスを利用できるようにする必要があります。これにより、電池の消費量が増える可能性があります。"</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"フォアグラウンドでのみおおよその位置情報にアクセス"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"このアプリは、フォアグラウンドでのみユーザーのおおよその位置情報を取得できます。位置情報サービスを ON にして、デバイスでアプリがサービスを利用できるようにする必要があります。"</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"バックグラウンドでの位置情報へのアクセス"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"これが、おおよその位置情報または正確な位置情報へのアクセスの追加権限の場合、アプリはバックグラウンドでの実行中も位置情報にアクセスできます。"</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"このアプリは、フォアグラウンドで位置情報にアクセスできるだけでなく、バックグラウンドでの実行中も位置情報にアクセスできます。"</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"音声設定の変更"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"音声全般の設定(音量、出力に使用するスピーカーなど)の変更をアプリに許可します。"</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"録音"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"タブレットのBluetooth設定を表示すること、ペアのデバイスに接続すること/ペアのデバイスからの接続を受け入れることをアプリに許可します。"</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Android TV デバイスの Bluetooth 設定の表示と、ペア設定されたデバイスへの接続の確立、またはペア設定されたデバイスからの接続の受け入れをアプリに許可します。"</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"モバイルデバイスのBluetooth設定を表示すること、ペアのデバイスに接続すること/ペアのデバイスからの接続を受け入れることをアプリに許可します。"</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"優先される NFC お支払いサービスの情報"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"登録されている支援やルートの目的地など、優先される NFC お支払いサービスの情報を取得することをアプリに許可します。"</string>
<string name="permlab_nfc" msgid="1904455246837674977">"NFCの管理"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"NFCタグ、カード、リーダーとの通信をアプリに許可します。"</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"画面ロックの無効化"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"ユーザー補助機能のショートカットにより <xliff:g id="SERVICE_NAME">%1$s</xliff:g> は ON になっています"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"ユーザー補助機能のショートカットにより <xliff:g id="SERVICE_NAME">%1$s</xliff:g> は OFF になっています"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> を使用するには、音量大と音量小の両方のボタンを 3 秒間長押ししてください"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"ユーザー補助機能ボタンをタップした場合に使用するサービスを選択してください。"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"ユーザー補助操作(2 本の指で画面の下から上にスワイプ)で使用するサービスを選択してください。"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"ユーザー補助操作(3 本の指で画面の下から上にスワイプ)で使用するサービスを選択してください。"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"サービスを切り替えるには、ユーザー補助機能ボタンを長押しします。"</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"サービスを切り替えるには、2 本の指で上にスワイプしたまま長押しします。"</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"サービスを切り替えるには、3 本の指で上にスワイプしたまま長押しします。"</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>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> に接続しました"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"タップしてファイルを表示"</string>
<string name="pin_target" msgid="8036028973110156895">"固定"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"<xliff:g id="LABEL">%1$s</xliff:g> を固定"</string>
<string name="unpin_target" msgid="3963318576590204447">"固定を解除"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"<xliff:g id="LABEL">%1$s</xliff:g> の固定を解除"</string>
<string name="app_info" msgid="6113278084877079851">"アプリ情報"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"デモを開始しています…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"<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_save_yes" msgid="8035743017382012850">"はい"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"いいえ"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"後で"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"なし"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"更新"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"続行"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"パスワード"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"分割画面の切り替え"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"ロック画面"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"スクリーンショット"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"<xliff:g id="APP_NAME">%1$s</xliff:g> アプリがポップアップ ウィンドウで開きます。"</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> のキャプション バーです。"</string>
</resources>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index 941dbbd208ab..a0f631e4c992 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"სამსახურის პროფილის ადმინისტრატორის აპი მიუწვდომელია ან დაზიანებულია. ამის გამო, თქვენი სამსახურის პროფილი და დაკავშირებული მონაცემები წაიშალა. დახმარებისთვის დაუკავშირდით თქვენს ადმინისტრატორს."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"თქვენი სამსახურის პროფილი აღარ არის ხელმისაწვდომი ამ მოწყობილობაზე"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"დაფიქსირდა პაროლის შეყვანის ზედმეტად ბევრი მცდელობა"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"ადმინისტრატორმა გაათავისუფლა მოწყობილობა პირადი გამოყენებისთვის"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"მოწყობილობა მართულია"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"ამ მოწყობილობას თქვენი ორგანიზაცია მართავს და მას ქსელის ტრაფიკის მონიტორინგი შეუძლია. შეეხეთ დამატებითი დეტალებისთვის."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"თქვენი მოწყობილობა წაიშლება"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"ნებას რთავს აპს, გაგზავნოს ფიქსირებული მაუწყებლობა, რომელიც მაუწყებლობის დასრულების შემდეგაც რჩება. ჭარბმა გამოყენებამ, შესაძლოა, თქვენი Android TV მოწყობილობა ნელი ან არასტაბილური გახადოს, რადგან მეტისმეტად დიდი მეხსიერების გამოყენებას აიძულებს მას."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"აპს შეეძლება არასაჩქარო შეტყობინებების გაგზავნა, რომელიც რჩებიან გაგზავნის დასრულების შემდეგაც. მავნე აპლიკაციებს შეუძლიათ თქვენი ტელეფონის მუშაობის შენელება ან შეფერხება ზედმეტად დიდი მოცულობის მეხსიერების გამოყენების შედეგად."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"თქვენი კონტაქტების წაკითხვა"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"აპს შეეძლება, წაიკითხოს თქვენ ტაბლეტზე შენახული კონტაქტების მონაცემები, მათ შორის ინფორმაცია კონკრეტულ ადამიანებთან თქვენი დარეკვის, ელფოსტის გაგზავნის ან კომუნიკაციის სიხშირის შესახებ. ეს ნებართვა უფლებას აძლევს აპებს, შეინახონ თქვენი კონტაქტების მონაცემები და მავნე აპებმა შეიძლება გააზიარონ საკონტაქტო მონაცემები თქვენგან დამოუკიდებლად. "</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"ნებას რთავს აპს, წაიკითხოს Android TV მოწყობილობაში შენახული კონტაქტების მონაცემები, მათ შორის, მონაცემები იმის შესახებ, თუ რა სიხშირით ურეკავდით, ელფოსტას უგზავნიდით, თუ სხვა გზით უკავშირდებოდით კონკრეტულ ადამიანებს. ეს ნებართვა, აპებს საშუალებას აძლევს, შეინახონ თქვენი კონტაქტების მონაცემები, ამის გამო, მავნე აპებს შეეძლებათ გააზიარონ კონტაქტების მონაცემები, ისე რომ თქვენ ამის შესახებ არ იცოდეთ."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"აპს შეეძლება, წაიკითხოს თქვენ ტელეფონზე შენახული კონტაქტების მონაცემები, მათ შორის ინფორმაცია კონკრეტულ ადამიანებთან თქვენი დარეკვის, ელფოსტის გაგზავნის ან კომუნიკაციის სიხშირის შესახებ. ეს ნებართვა უფლებას აძლევს აპებს, შეინახონ თქვენი კონტაქტების მონაცემები და მავნე აპებმა შეიძლება გააზიარონ საკონტაქტო მონაცემები თქვენგან დამოუკიდებლად. "</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"აპს საშუალებას აძლევს, წაიკითხოს თქვენს ტაბლეტზე შენახული კონტაქტების მონაცემები. აპს, ასევე, ექნება წვდომა თქვენს ტაბლეტზე არსებულ ანგარიშებზე, რომლებსაც კონტაქტები აქვთ შექმნილი. ეს შეიძლება მოიცავდეს თქვენ მიერ ინსტალირებული აპების მიერ შექმნილ ანგარიშებს. ეს ნებართვა უფლებას აძლევს აპებს, შეინახონ თქვენი კონტაქტების მონაცემები და მავნე აპებმა შეიძლება თქვენთვის შეუტყობინებლად გააზიარონ საკონტაქტო მონაცემები."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"აპს საშუალებას აძლევს, წაიკითხოს თქვენს Android TV მოწყობილობაზე შენახული კონტაქტების მონაცემები. აპს, ასევე, ექნება წვდომა თქვენს Android TV მოწყობილობებზე არსებულ ანგარიშებზე, რომლებსაც კონტაქტები აქვთ შექმნილი. ეს შეიძლება მოიცავდეს თქვენ მიერ ინსტალირებული აპების მიერ შექმნილ ანგარიშებს. ეს ნებართვა უფლებას აძლევს აპებს, შეინახონ თქვენი კონტაქტების მონაცემები და მავნე აპებმა შეიძლება თქვენთვის შეუტყობინებლად გააზიარონ საკონტაქტო მონაცემები."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"აპს საშუალებას აძლევს, წაიკითხოს თქვენს ტელეფონზე შენახული კონტაქტების მონაცემები. აპს, ასევე, ექნება წვდომა თქვენს ტელეფონზე არსებულ ანგარიშებზე, რომლებსაც კონტაქტები აქვთ შექმნილი. ეს შეიძლება მოიცავდეს თქვენ მიერ ინსტალირებული აპების მიერ შექმნილ ანგარიშებს. ეს ნებართვა უფლებას აძლევს აპებს, შეინახონ თქვენი კონტაქტების მონაცემები და მავნე აპებმა შეიძლება თქვენთვის შეუტყობინებლად გააზიარონ საკონტაქტო მონაცემები."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"თქვენი კონტაქტების შეცვლა"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"აპს შეეძლება, შეცვალოს თქვენ ტაბლეტზე შენახული კონტაქტების მონაცემები, მათ შორის ინფორმაცია კონკრეტულ ინდივიდუალებთან თქვენი დარეკვის, ელფოსტის გაგზავნის ან კომუნიკაციის სიხშირის შესახებ. ეს ნებართვა უფლებას აძლევს აპებს, წაშალოს საკონტაქტო მონაცემები. "</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"ნებას რთავს აპს, შეცვალოს Android TV მოწყობილობაში შენახული კონტაქტების მონაცემები, მათ შორის, მონაცემები იმის შესახებ, თუ რა სიხშირით ურეკავდით, ელფოსტას უგზავნიდით, თუ სხვა გზით უკავშირდებოდით კონკრეტულ კონტაქტებს. ეს ნებართვა აპებს კონტაქტების მონაცემების წაშლის საშუალებას აძლევს."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"აპს შეეძლება, შეცვალოს თქვენ ტელეფონზე შენახული კონტაქტების მონაცემები, მათ შორის ინფორმაცია კონკრეტულ ინდივიდუალებთან თქვენი დარეკვის, ელფოსტის გაგზავნის ან კომუნიკაციის სიხშირის შესახებ. ეს ნებართვა უფლებას აძლევს აპებს, წაშალოს საკონტაქტო მონაცემები. "</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"აპს საშუალებას აძლევს, შეცვალოს თქვენს ტაბლეტზე შენახული კონტაქტების მონაცემები. ეს ნებართვა საშუალებას აძლევს აპებს, წაშალონ კონტაქტის მონაცემები."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"აპს საშუალებას აძლევს, შეცვალოს თქვენს Android TV მოწყობილობაზე შენახული კონტაქტების მონაცემები. ეს ნებართვა საშუალებას აძლევს აპებს, წაშალონ კონტაქტის მონაცემები."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"აპს საშუალებას აძლევს, შეცვალოს თქვენს ტელეფონზე შენახული კონტაქტების მონაცემები. ეს ნებართვა საშუალებას აძლევს აპებს, წაშალონ კონტაქტის მონაცემები."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"ზარების ჟურნალის წაკითხვა"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"ამ აპს შეუძლია თქვენი საუბრის ისტორიის წაკითხვა."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"ზარების ჟურნალში ჩაწერა"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"მდებარეობის პროვაიდერის დამატებით ბრძანებებზე წვდომა"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"აპს შეეძლება წვდომა ჰქონდეს მდებარეობის სერვისის დამატებით ბრძანებებზე. შესაძლოა აპმა ეს გამოიყენოს GPS-ისა და მდებარეობის სხვა წყაროების მუშაობის პროცესში ჩარევისთვის."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"ზუსტ მდებარეობაზე წვდომა მხოლოდ წინა პლანზე"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"ამ აპს შეუძლია თქვენი ზუსტი მდებარეობის შესახებ ინფორმაციის მიღება მხოლოდ მაშინ, როცა გაშვებულია წინა პლანზე. თქვენს ტელეფონზე ჩართული და ხელმისაწვდომი უნდა იყოს მდებარეობის სერვისები, აპმა მათი გამოყენება რომ შეძლოს. ამან შეიძლება გაზარდოს ბატარეის მოხმარება."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"მიახლოებით მდებარეობაზე (ქსელის კოორდინატების მიხედვით) წვდომა მხოლოდ წინა პლანზე"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"ამ აპს შეუძლია თქვენი მდებარეობის შესახებ ინფორმაციის მიღება ისეთი წყაროებიდან, როგორიცაა მობილური კავშირგაბმულობის ანძები და Wi-Fi ქსელები (თუმცა მხოლოდ მაშინ, როცა აპი გაშვებულია წინა პლანზე). მდებარეობის აღნიშნული სერვისები თქვენს ტაბლეტზე ჩართული და ხელმისაწვდომი უნდა იყოს, აპმა მათი გამოყენება რომ შეძლოს."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"ამ აპს შეუძლია თქვენი მდებარეობის შესახებ ინფორმაციის მიღება ისეთი წყაროებიდან, როგორიცაა მობილური კავშირგაბმულობის ანძები და Wi-Fi ქსელები (თუმცა მხოლოდ მაშინ, როცა აპი გაშვებულია წინა პლანზე). მდებარეობის აღნიშნული სერვისები თქვენს Android TV მოწყობილობაზე ჩართული და ხელმისაწვდომი უნდა იყოს, აპმა მათი გამოყენება რომ შეძლოს."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"ამ აპს შეუძლია თქვენი მდებარეობის შესახებ ინფორმაციის მიღება ისეთი წყაროებიდან, როგორიცაა მობილური კავშირგაბმულობის ანძები და Wi-Fi ქსელები (თუმცა მხოლოდ მაშინ, როცა აპი გაშვებულია წინა პლანზე). მდებარეობის აღნიშნული სერვისები თქვენს ტელეფონზე ჩართული და ხელმისაწვდომი უნდა იყოს, აპმა მათი გამოყენება რომ შეძლოს."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"ამ აპს შეუძლია თქვენი ზუსტი მდებარეობის შესახებ ინფორმაციის მიღება მხოლოდ მაშინ, როცა გაშვებულია წინა პლანზე. თქვენს მოწყობილობაზე ჩართული და ხელმისაწვდომი უნდა იყოს მდებარეობის სერვისები, აპმა მათი გამოყენება რომ შეძლოს. ამან შეიძლება გაზარდოს ბატარეის მოხმარება."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"მიახლოებით მდებარეობაზე წვდომა მხოლოდ წინა პლანზე"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"ამ აპს შეუძლია თქვენი მიახლოებითი მდებარეობის შესახებ ინფორმაციის მიღება მხოლოდ მაშინ, როცა გაშვებულია წინა პლანზე. თქვენს მოწყობილობაზე ჩართული და ხელმისაწვდომი უნდა იყოს მდებარეობის სერვისები, აპმა მათი გამოყენება რომ შეძლოს."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"მდებარეობაზე წვდომა ფონურ რეჟიმში"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"ამ ნებართვის მიახლოებით ან ზუსტ მდებარეობაზე წვდომის ნებართვასთან ერთად მინიჭების შემთხვევაში, აპს შეეძლება მდებარეობაზე წვდომა ფონურ რეჟიმში."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"წინა პლანზე ყოფნისას მდებარეობაზე წვდომის გარდა, ამ აპს შეუძლია, ჰქონდეს წვდომა მდებარეობაზე ფონურ რეჟიმში მუშაობისას."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"თქვენი აუდიო პარამეტრების შეცვლა"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"აპს შეეძლება აუდიოს გლობალური პარამეტრების შეცვლა. მაგ.: ხმის სიმაღლე და რომელი დინამიკი გამოიყენება სიგნალის გამოსტანად."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"აუდიოს ჩაწერა"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"აპს შეეძლება, ნახოს Bluetooth-ის კონფიგურაცია ტაბლეტზე, შექმნას და მიიღოს კავშირები დაწყვილებულ მოწყობილობებთან."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"ნებას რთავს აპს, თქვენს Android TV მოწყობილობაზე ნახოს Bluetooth-ის კონფიგურაცია, ასევე, დაამყაროს და მიიღოს კავშირები დაწყვილებულ მოწყობილობებთან."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"აპს შეეძლება, ნახოს Bluetooth-ის კონფიგურაცია ტელეფონზე და შექმნას და მიიღოს კავშირები დაწყვილებულ მოწყობილობებთან."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"უპირატესი NFC გადახდის სერვისის ინფორმაცია"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"საშუალებას აძლევს აპს, მიიღოს უპირატესი NFC გადახდის სერვისის ინფორმაცია, მაგალითად, რეგისტრირებული დახმარება და დანიშნულება."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"ახლო მოქმედების რადიოკავშირი (NFC) მართვა"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"აპს შეეძლება ახლო მოქმედების რადიოკავშირის (NFC) მეშვეობით ტეგების, ბარათებისა და წამკითხველების შემცველი მონაცემების მიმოცვლა."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"თქვენი ეკრანის ბლოკის გათიშვა"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"მარტივი წვდომის მალსახმობმა ჩართო <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"მარტივი წვდომის მალსახმობმა გამორთო <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> რომ გამოიყენოთ, დააჭირეთ ხმის ორივე ღილაკზე 3 წამის განმავლობაში"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"აირჩიეთ მარტივი წვდომის ღილაკზე შეხებისას გამოსაყენებელი სერვისი:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"აირჩიეთ მარტივი წვდომის ჟესტთან (ორი თითით გადაფურცვლა ეკრანის ქვედა კიდიდან ზემოთ) გამოსაყენებელი სერვისი:"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"აირჩიეთ მარტივი წვდომის ჟესტთან (სამი თითით გადაფურცვლა ეკრანის ქვედა კიდიდან ზემოთ) გამოსაყენებელი სერვისი:"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"სერვისების გადასართავად, ხანგრძლივად შეეხეთ მარტივი წვდომის ღილაკს."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"სერვისების გადასართავად, ორი თითით გადაფურცლეთ ზემოთ და დააყოვნეთ."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"სერვისების გადასართავად, სამი თითით გადაფურცლეთ ზემოთ და დააყოვნეთ."</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>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"დაკავშირებულია <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>-თან"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"შეეხეთ ფაილების სანახავად"</string>
<string name="pin_target" msgid="8036028973110156895">"ჩამაგრება"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"<xliff:g id="LABEL">%1$s</xliff:g>-ის ჩამაგრება"</string>
<string name="unpin_target" msgid="3963318576590204447">"ჩამაგრების მოხსნა"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"<xliff:g id="LABEL">%1$s</xliff:g>-ის ჩამაგრების მოხსნა"</string>
<string name="app_info" msgid="6113278084877079851">"აპის შესახებ"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"მიმდინარეობს დემონსტრაციის დაწყება…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"გსურთ, "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"-ში განაახლოთ <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>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"შენახვა"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"არა, გმადლობთ"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"ახლა არა"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"არასოდეს"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"განახლება"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"გაგრძელება"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"პაროლი"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"გაყოფილი ეკრანის გადართვა"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"ჩაკეტილი ეკრანი"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"ეკრანის ანაბეჭდი"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"<xliff:g id="APP_NAME">%1$s</xliff:g> აპი ამომხტარ ფანჯარაში."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g>-ის სუბტიტრების ზოლი."</string>
</resources>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index b142e5851f8c..e6562c4c93e5 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Жұмыс профилінің әкімші қолданбасы жоқ немесе бүлінген. Нәтижесінде жұмыс профиліңіз және қатысты деректер жойылды. Көмек алу үшін әкімшіге хабарласыңыз."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Жұмыс профиліңіз осы құрылғыда енді қолжетімді емес"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Құпия сөз көп рет қате енгізілді"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Әкімші құрылғыны жеке пайдалануға ұсынды."</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Құрылғы басқарылады"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Ұйымыңыз осы құрылғыны басқарады және желі трафигін бақылауы мүмкін. Мәліметтер алу үшін түртіңіз."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Құрылғыңыздағы деректер өшіріледі"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Қолданба трансляция біткеннен кейін сақталатын бекітілген трансляцияларды жібере алатын болады. Тым жиі пайдалансаңыз, жад толып, Android TV құрылғысы баяу немесе тұрақсыз жұмыс істеуі мүмкін."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Қолданбаға хабар тарату аяқталғанда сақталатын жабысқақ хабар тарату мүмкіндігін береді. Тым көп қолдану телефон жұмысын баяулатады немесе жадты көп қолдану арқылы жұмысын тұрақсыздандырады."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"контактілерді оқу"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Қолданбаға планшетте сақталған байланыстар, белгілі тұлғаларға шалынған қоңырау, хаттар немесе басқа байланыс түрінің жиіліктерін қоса, туралы ақпаратты оқу мүмкіндігін береді. Бұл рұқсат қолданбаға байланыстар туралы деректерді сақтау мүмкіндігін береді және залалды қолданбалар байланыстар туралы деректерді сіздің келісіміңізсіз бөлісуі ықтимал."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Қолданба Android TV құрылғыңызда сақталған контактілер туралы деректі оқи алатын болады. Бұл деректерге белгілі бір адамдарға қаншалықты жиі қоңырау шалатыныңыз, электрондық хабар жазатыныңыз немесе басқа жолмен хабарласатыныңыз туралы ақпарат кіреді. Бұл рұқсат арқылы қолданбалар контакт туралы деректерді сақтай алады. Ал зиянды қолданбалар контакт туралы деректерді сіздің рұқсатыңызсыз бөлісуі мүмкін."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Қолданбаға телефонда сақталған байланыстар, белгілі тұлғаларға шалынған қоңырау, хаттар немесе басқа байланыс түрінің жиіліктерін қоса, туралы ақпаратты оқу мүмкіндігін береді. Бұл рұқсат қолданбаға байланыстар туралы деректерді сақтау мүмкіндігін береді және залалды қолданбалар байланыстар туралы деректерді сіздің келісіміңізсіз бөлісуі ықтимал."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Қолданбаға планшетте сақталған контактілеріңіз туралы деректерді оқуға рұқсат етеді. Қолданбалар контактілер жасалған планшеттегі есептік жазбаларды пайдалана алады. Бұған сіз орнатқан қолданбалар арқылы жасалған есептік жазбалар кіруі мүмкін. Бұл рұқсат қолданбаларға контакт деректерін сақтау мүмкіндігін береді және зиянды қолданбалар контакт деректерін сіздің келісіміңізсіз бөлісуі ықтимал."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Қолданбаға Android TV құрылғысында сақталған контактілеріңіз туралы деректерді оқуға рұқсат етеді. Қолданба контактілер жасалған Android TV құрылғысындағы есептік жазбаларды пайдалана алады. Бұған сіз орнатқан қолданбалар арқылы жасалған есептік жазбалар кіруі мүмкін. Бұл рұқсат қолданбаларға контакт деректерін сақтау мүмкіндігін береді және зиянды қолданбалар контакт деректерін сіздің келісіміңізсіз бөлісуі ықтимал."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Қолданбаға телефонда сақталған контактілеріңіз туралы деректерді оқуға рұқсат етеді. Қолданбалар контактілер жасалған телефондағы есептік жазбаларды пайдалана алады. Бұған сіз орнатқан қолданбалар арқылы жасалған есептік жазбалар кіруі мүмкін. Бұл рұқсат қолданбаларға контакт деректерін сақтау мүмкіндігін береді және зиянды қолданбалар контакт деректерін сіздің келісіміңізсіз бөлісуі ықтимал."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"контактілерді өзгерту"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Қолданбаға планшетте сақталған байланыстар, белгілі тұлғаларға шалынған қоңырау, хаттар немесе басқа байланыс түрінің жиіліктерін қоса, туралы ақпаратты өзгерту мүмкіндігін береді. Бұл рұқсат қолданбаға байланыстар туралы деректерді өшіру мүмкіндігін береді."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Қолданба Android TV құрылғыңызда сақталған контактілер туралы деректі өзгерте алатын болады. Бұл деректерге белгілі бір контактіге қаншалықты жиі қоңырау шалатыныңыз, электрондық хабар жазатыныңыз немесе басқа жолмен хабарласатыныңыз туралы ақпарат кіреді. Бұл рұқсаттың көмегімен қолданбалар контакт туралы деректерді жоя алады."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Қолданбаға телефонда сақталған байланыстар, белгілі тұлғаларға шалынған қоңырау, хаттар немесе басқа байланыс түрінің жиіліктерін қоса, туралы ақпаратты өзгерту мүмкіндігін береді. Бұл рұқсат қолданбаға байланыстар туралы деректерді өшіру мүмкіндігін береді."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Қолданбаға планшетте сақталған контактілеріңіз туралы деректерді өзгертуге рұқсат етеді. Бұл рұқсат қолданбаларға контактілер туралы деректерді жоюға рұқсат береді."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Қолданбаға Android TV құрылғысында сақталған контактілеріңіз туралы деректерді өзгертуге рұқсат етеді. Бұл рұқсат қолданбаларға контактілер туралы деректерді жоюға рұқсат береді."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Қолданбаға телефонда сақталған контактілеріңіз туралы деректерді өзгертуге рұқсат етеді. Бұл рұқсат қолданбаларға контактілер туралы деректерді жоюға рұқсат береді."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"қоңыраулар тіркеуін оқу"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Бұл қолданба қоңыраулар тарихын оқи алады."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"қоңырау тіркеуді жазу"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"қосымша аймақ жабдықтаушы пәрмендеріне қол жетімділік"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Қолданбаға орын жеткізушісінің қосымша пәрмендеріне қатынасуға рұқсат береді. Бұл қолданбаға GPS немесе басқа орын көздерінің жұмысына кедергі келтіруге рұқсат беруі мүмкін."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"нақты орналасқан жер туралы ақпаратқа тек ашық экранда кіру"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Бұл қолданба нақты орналасқан жеріңіз туралы ақпаратты экранда ашық тұрғанда ғана анықтай алады. Қолданба бұл орынды анықтау қызметтерін пайдалана алуы үшін, олар қосулы әрі телефонда қолжетімді болуы керек. Батарея көбірек тұтынылуы мүмкін."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"болжалды геодерекке (желі негізінде) тек экрандық режимде кіру"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Бұл қолданба орналасқан жеріңізді ұялы байланыс мұнаралары мен Wi-Fi желілері сияқты желі көздерінің негізінде анықтайды. Бірақ бұл үшін қолданба экрандық режимде жұмыс істеп тұруы керек. Қолданба бұл орынды анықтау қызметтерін пайдалана алуы үшін, олар қосулы әрі планшетте қолжетімді болуы керек."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Бұл қолданба орналасқан жеріңізді ұялы байланыс мұнаралары мен Wi-Fi желілері сияқты желі көздерінің негізінде анықтайды. Бірақ бұл үшін қолданба ашық тұруы керек. Қолданба орынды анықтау қызметтерін пайдалана алуы үшін, олар қосулы әрі Android TV құрылғысында қолжетімді болуы керек."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Бұл қолданба орналасқан жеріңізді ұялы байланыс мұнаралары мен Wi-Fi желілері сияқты желі көздерінің негізінде анықтайды. Бірақ бұл үшін қолданба экранда ашық тұруы керек. Қолданба бұл орынды анықтау қызметтерін пайдалана алуы үшін, олар қосулы әрі телефонда қолжетімді болуы керек."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Бұл қолданба нақты орналасқан жеріңіз туралы ақпаратты экранда ашық тұрғанда ғана анықтай алады. Қолданба орынды анықтау қызметтерін пайдалана алуы үшін, олар қосулы әрі құрылғыда қолжетімді болуы керек. Батарея көбірек тұтынылуы мүмкін."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"болжалды орналасқан жер туралы ақпаратқа тек ашық экранда кіру"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Бұл қолданба орналасқан жеріңіз туралы болжалды ақпаратты экранда ашық тұрғанда ғана анықтай алады. Қолданба орынды анықтау қызметтерін пайдалана алуы үшін, олар қосулы әрі құрылғыда қолжетімді болуы керек."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"геодеректерді фондық режимде пайдалану"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Егер ол шамамен есептегендегі немесе нақты орынды пайдалануға рұқсат алса, қолданба фондық режимде жұмыс істеп тұрып-ақ геодеректерді пайдалана алады."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Қолданба фондық және белсенді режимде де орналасқан жеріңіз мәліметін ала алады."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"аудио параметрлерін өзгерту"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Қолданбаға дыбыс қаттылығы және аудио шығыс үндеткішін таңдау сияқты жаһандық аудио параметрлерін өзгерту мүмкіндігін береді."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"аудио жазу"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Қолданбаға планшеттегі Bluetooth конфигурациясын көру және жұпталған құрылғымен байланыс орнату немесе қабылдау мүмкіндігін береді."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Қолданба Android TV құрылғыңыздағы Bluetooth конфигурациясын көре алады және жұпталған құрылғылармен байланыс орнатып, оларды қабылдай алатын болады."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Қолданбаға телефондағы Bluetooth конфигурациясын көру және жұпталған құрылғымен байланыс орнату немесе қабылдау мүмкіндігін береді"</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Таңдаулы NFC төлеу қызметі туралы ақпарат"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Қолданба тіркелген көмектер және баратын жер маршруты сияқты таңдаулы NFC төлеу қызметі туралы ақпаратты ала алатын болады."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"NFC функциясын басқару"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Қолданбаға NFC белгілерімен, карталармен және оқу құралдарымен байланысуға рұқсат береді."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"экран бекітпесін істен шығару"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"Арнайы мүмкіндіктер таңбашасы <xliff:g id="SERVICE_NAME">%1$s</xliff:g> қызметін қосты"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"Арнайы мүмкіндіктер таңбашасы <xliff:g id="SERVICE_NAME">%1$s</xliff:g> қызметін өшірді"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> қызметін пайдалану үшін дыбыс деңгейін реттейтін екі түймені де 3 секунд басып тұрыңыз"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"\"Арнайы мүмкіндіктер\" түймесін түрткенде пайдаланатын қызметті таңдаңыз:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Арнайы мүмкіндіктер қимылымен пайдаланатын қызметті таңдаңыз (екі саусақпен экранның төменгі жағынан жоғары қарай сырғытыңыз):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Арнайы мүмкіндіктер қимылымен пайдаланатын қызметті таңдаңыз (үш саусақпен экранның төменгі жағынан жоғары қарай сырғытыңыз):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Бір қызметтен екінші қызметке ауысу үшін арнайы мүмкіндіктер түймесін түртіп, оны ұстап тұрыңыз."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Бір қызметтен екінші қызметке ауысу үшін екі саусақпен жоғары қарай сырғытып, ұстап тұрыңыз."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Бір қызметтен екінші қызметке ауысу үшін үш саусақпен жоғары қарай сырғытып, ұстап тұрыңыз."</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>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> қосылу орындалды"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Файлдарды көру үшін түртіңіз"</string>
<string name="pin_target" msgid="8036028973110156895">"PIN коды"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"<xliff:g id="LABEL">%1$s</xliff:g> бекіту"</string>
<string name="unpin_target" msgid="3963318576590204447">"Босату"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"<xliff:g id="LABEL">%1$s</xliff:g> босату"</string>
<string name="app_info" msgid="6113278084877079851">"Қолданба ақпараты"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Демо нұсқасы іске қосылуда..."</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291"><b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" қызметіндегі <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> деректері жаңартылсын ба?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Сақтау"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Жоқ, рақмет"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Қазір емес"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Ешқашан"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Жаңарту"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Жалғастыру"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"құпия сөз"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Экранды бөлу мүмкіндігін қосу/өшіру"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Құлып экраны"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Скриншот"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"Қалқымалы терезедегі <xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасы"</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасының жазу жолағы."</string>
</resources>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 43289eb4dffe..e6397ad253f2 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"កម្មវិធី​អ្នកគ្រប់គ្រង​កម្រងព័ត៌មាន​ការងារនេះ​អាច​បាត់ ឬ​មាន​បញ្ហា។ ដូច្នេះហើយ​ទើប​កម្រងព័ត៌មាន​ការងារ​របស់អ្នក និង​ទិន្នន័យ​ដែល​ពាក់ព័ន្ធត្រូវ​បានលុប។ សូមទាក់ទង​ទៅអ្នក​គ្រប់គ្រង​របស់អ្នក ដើម្បី​ទទួល​បាន​ជំនួយ។"</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"កម្រងព័ត៌មាន​ការងារ​របស់អ្នក​លែងមាន​នៅលើ​ឧបករណ៍​នេះទៀត​ហើយ"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"ការព្យាយាមបញ្ចូលពាក្យសម្ងាត់ច្រើនដងពេកហើយ"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"អ្នកគ្រប់គ្រង​បានបោះបង់​ឧបករណ៍​ចោល​ដោយសារ​ការប្រើប្រាស់​ផ្ទាល់ខ្លួន"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"ឧបករណ៍ស្ថិតក្រោមការគ្រប់គ្រង"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"ស្ថាប័នរបស់អ្នកគ្រប់គ្រងឧបករណ៍នេះ ហើយអាចនឹងតាមដានចរាចរណ៍បណ្តាញ។ ចុចដើម្បីទទួលបានព័ត៌មានលម្អិត។"</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"ឧបករណ៍របស់អ្នកនឹងត្រូវបានលុប"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"អនុញ្ញាត​ឱ្យកម្មវិធីផ្ញើការផ្សាយស្អិត ដែលមានបន្ទាប់​ពីការផ្សាយចប់។ ការប្រើប្រាស់​ច្រើនពេកអាចធ្វើ​ឱ្យឧបករណ៍ Android TV របស់អ្នកប្រើ​អង្គចងចាំច្រើន​ជ្រុល ដែលធ្វើឱ្យវាដើរយឺត ឬគ្មាន​ស្ថិរភាព​។"</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"ឲ្យ​កម្មវិធី​ផ្ញើ​ការប្រកាស​​ដែល​ទាក់ទាញ ដែល​មាន​បន្ទាប់​ពី​ការ​ប្រកាស​ចប់។ ការ​ប្រើ​លើស​​អាច​ធ្វើឲ្យ​ទូរស័ព្ទ​យឺត ឬ​មិន​ស្ថិតស្ថេរ​ដោយធ្វើ​ឲ្យ​វា​ប្រើ​អង្គ​ចងចាំ​ធំ​ពេក។"</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"អាន​ទំនាក់ទំនង​របស់​អ្នក"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"ឲ្យ​កម្មវិធី​អាន​ទិន្នន័យ​អំពី​ទំនាក់ទំនង​របស់​អ្នក​ដែល​មាន​ក្នុង​កុំព្យូទ័រ​បន្ទះ​របស់​អ្នក រួមមាន​ប្រេកង់​ដែល​អ្នក​បាន​ហៅ​ អ៊ីមែល ឬ​ទាក់ទង​តាម​វិធី​ផ្សេងៗ​ជា​មួយ​មនុស្ស​ណា​ម្នាក់។ សិទ្ធិ​នេះ​អនុញ្ញាត​ឲ្យ​កម្មវិធី​រក្សាទុក​ទិន្នន័យ​ទំនាក់ទំនង​របស់​អ្នក ហើយ​កម្មវិធី​ព្យាបាទ​អាច​ចែករំលែក​ទិន្នន័យ​ទំនាក់ទំនង​ដោយ​មិន​ឲ្យ​អ្នក​ដឹង។"</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"អនុញ្ញាតឱ្យ​កម្មវិធីអាន​ទិន្នន័យអំពី​ទំនាក់ទំនង​ ដែលអ្នកបានរក្សាទុក​នៅក្នុងឧបករណ៍ Android TV របស់អ្នក រួមទាំង​ភាពញឹកញាប់​ដែលអ្នកបានហៅទូរសព្ទ ផ្ញើអ៊ីមែល ឬទាក់ទងតាមវិធីផ្សេង​ទៀតជាមួយបុគ្គល​ជាក់លាក់។ ការអនុញ្ញាតនេះអនុញ្ញាតឱ្យកម្មវិធីរក្សាទុក​ទិន្នន័យទំនាក់ទំនង​របស់អ្នក ហើយកម្មវិធី​គ្រោះថ្នាក់អាចនឹងចែករំលែកទិន្នន័យ​ទំនាក់ទំនង​ដោយមិនឱ្យអ្នកដឹង។"</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"ឲ្យ​​កម្មវិធី​អាន​ទិន្នន័យ​អំពី​ទំនាក់ទំនង​របស់​អ្នក​ដែល​បាន​រក្សាទុក​ក្នុង​ទូរស័ព្ទ រួមមាន​ប្រេកង់​ដែល​អ្នក​បាន​ហៅ អ៊ីមែល ឬ​ទាក់ទង​តាម​វិធី​ផ្សេងៗ​ជា​មួយ​​អ្នក​ណា​ម្នាក់។ សិទ្ធិ​នេះ​ឲ្យ​កម្មវិធី​រក្សាទុក​ទិន្នន័យ​ទំនាក់ទំនង​របស់​អ្នក ហើយ​កម្មវិធី​ព្យាបាទ​អាច​ចែករំលែក​ទិន្នន័យ​ទំនាក់ទំនង​​ដោយ​មិន​ឲ្យ​អ្នកដឹង។"</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"អនុញ្ញាតឱ្យ​កម្មវិធី​អាន​ទិន្នន័យអំពី​ទំនាក់ទំនង​ ដែលអ្នក​បានរក្សាទុក​នៅក្នុង​ថេប្លេត​របស់អ្នក។ កម្មវិធីក៏នឹងមានសិទ្ធិចូលប្រើគណនី​នៅលើថេប្លេត ដែលអ្នកបានបង្កើតទំនាក់ទំនងផងដែរ។ គណនីទាំងនោះអាចរួមបញ្ចូលទាំងគណនី ដែលបង្កើតដោយកម្មវិធីដែលអ្នកបានដំឡើង។ ការអនុញ្ញាតនេះអនុញ្ញាតឱ្យកម្មវិធីរក្សាទុក​ទិន្នន័យទំនាក់ទំនង​របស់អ្នក ហើយកម្មវិធី​គ្រោះថ្នាក់អាចនឹងចែករំលែកទិន្នន័យ​ទំនាក់ទំនង​ដោយមិនឱ្យអ្នកដឹង។"</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"អនុញ្ញាតឱ្យ​កម្មវិធីអាន​ទិន្នន័យអំពី​ទំនាក់ទំនង​ ដែលអ្នក​បានរក្សាទុក​នៅក្នុង​ឧបករណ៍ Android TV របស់អ្នក។ កម្មវិធីក៏នឹងមានសិទ្ធិចូលប្រើគណនី​នៅលើឧបករណ៍ Android TV ដែលអ្នកបានបង្កើតទំនាក់ទំនងផងដែរ។ គណនីទាំងនោះអាចរួមបញ្ចូលទាំងគណនី ដែលបង្កើតដោយកម្មវិធីដែលអ្នកបានដំឡើង។ ការអនុញ្ញាតនេះអនុញ្ញាតឱ្យកម្មវិធីរក្សាទុក​ទិន្នន័យទំនាក់ទំនង​របស់អ្នក ហើយកម្មវិធី​គ្រោះថ្នាក់អាចនឹងចែករំលែកទិន្នន័យ​ទំនាក់ទំនង​ដោយមិនឱ្យអ្នកដឹង។"</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"អនុញ្ញាតឱ្យ​កម្មវិធីអាន​ទិន្នន័យអំពី​ទំនាក់ទំនង​ ដែលអ្នក​បានរក្សាទុក​នៅក្នុង​ទូរសព្ទ​របស់អ្នក។ កម្មវិធីក៏នឹងមានសិទ្ធិចូលប្រើគណនី​នៅលើទូរសព្ទ ដែលអ្នកបានបង្កើតទំនាក់ទំនងផងដែរ។ គណនីទាំងនោះអាចរួមបញ្ចូលទាំងគណនី ដែលបង្កើតដោយកម្មវិធីដែលអ្នកបានដំឡើង។ ការអនុញ្ញាតនេះអនុញ្ញាតឱ្យកម្មវិធីរក្សាទុក​ទិន្នន័យទំនាក់ទំនង​របស់អ្នក ហើយកម្មវិធី​គ្រោះថ្នាក់អាចនឹងចែករំលែកទិន្នន័យ​ទំនាក់ទំនង​ដោយមិនឱ្យអ្នកដឹង។"</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"កែ​ទំនាក់ទំនង​របស់​អ្នក"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"ឲ្យ​កម្មវិធី​កែ​ទិន្នន័យ​អំពី​ទំនាក់ទំនង​របស់​អ្នក​ដែល​បាន​រក្សាទុក​ក្នុង​កុំព្យូទ័រ​បន្ទះ រួមមាន​ប្រេកង់​​ដែល​អ្នក​បាន​ហៅ អ៊ីមែល ឬ​ទាក់ទង​តាម​វិធី​ផ្សេងៗ​ជា​មួយ​ទំនាក់ទំនង​ជាក់លាក់។ សិទ្ធិ​​នេះ​អនុញ្ញាត​ឲ្យ​​​កម្មវិធី​លុប​ទិន្នន័យ​ទំនាក់ទំនង​របស់​អ្នក។"</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"អនុញ្ញាតឱ្យ​កម្មវិធីកែ​ទិន្នន័យអំពី​ទំនាក់ទំនង​ដែលអ្នកបានរក្សាទុក​នៅក្នុងឧបករណ៍ Android TV របស់អ្នក រួមទាំង​ភាពញឹកញាប់​ដែលអ្នកបានហៅទូរសព្ទ ផ្ញើអ៊ីមែល ឬទាក់ទង​តាមវិធីផ្សេង​ទៀតជាមួយទំនាក់​ទំនាក់​ជាក់លាក់ផងដែរ។ ការអនុញ្ញាតនេះអនុញ្ញាតឱ្យកម្មវិធីលុប​ទិន្នន័យទំនាក់ទំនង​។"</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"ឲ្យ​កម្មវិធី​កែ​ទិន្នន័យ​អំពី​ទំនាក់ទំនង​របស់​អ្នក​ដែល​បាន​រក្សាទុក​ក្នុង​ទូរស័ព្ទ​របស់​អ្នក រួមមាន​ប្រេកង់​ដែល​អ្នក​បាន​ហៅ អ៊ីមែល ឬ​បាន​ទាក់ទង​​តាម​វិធី​ផ្សេងៗ​ជា​មួយ​ទំនាក់​ទំនាក់​ជាក់លាក់។ សិទ្ធិ​នេះ​ឲ្យ​កម្មវិធី​លុប​ទិន្នន័យ​ទំនាក់ទំនង។"</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"អនុញ្ញាតឱ្យ​កម្មវិធីកែ​ទិន្នន័យអំពី​ទំនាក់ទំនង ​ដែលអ្នក​បានរក្សាទុក​នៅក្នុង​ថេប្លេត​របស់អ្នក។ ការអនុញ្ញាត​នេះ​អនុញ្ញាត​ឱ្យ​កម្មវិធី​លុប​ទិន្នន័យ​ទំនាក់ទំនង។"</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"អនុញ្ញាតឱ្យ​កម្មវិធីកែទិន្នន័យអំពី​ទំនាក់ទំនង​ ដែលអ្នកបានរក្សាទុក​នៅក្នុង​ឧបករណ៍ Android TV របស់អ្នក។ ការអនុញ្ញាត​នេះ​អនុញ្ញាត​ឱ្យ​កម្មវិធី​លុប​ទិន្នន័យ​ទំនាក់ទំនង។"</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"អនុញ្ញាតឱ្យ​កម្មវិធីកែ​ទិន្នន័យអំពី​ទំនាក់ទំនង ​ដែលអ្នកបានរក្សាទុក​នៅក្នុង​ទូរសព្ទ​របស់អ្នក។ ការអនុញ្ញាត​នេះ​អនុញ្ញាត​ឱ្យ​កម្មវិធី​លុប​ទិន្នន័យ​ទំនាក់ទំនង។"</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"អាន​​កំណត់​ហេតុ​​​ហៅ"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"កម្មវិធី​នេះ​អាច​អាន​ប្រវត្តិ​ហៅ​ទូរសព្ទ​របស់​អ្នក​បាន​។"</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"សរសេរ​បញ្ជី​ហៅ"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"ចូល​ដំណើរការ​ពាក្យ​បញ្ជា​ក្រុមហ៊ុន​ផ្ដល់​ទីតាំង"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"ឲ្យ​កម្មវិធី​ចូល​ដំណើរការ​ពាក្យ​បញ្ជា​កម្មវិធី​ផ្ដល់​​ទីតាំង​បន្ថែម។ វា​អាច​អនុញ្ញាត​ឲ្យ​កម្មវិធី​ទាក់ទង​ជា​មួយ​ប្រតិបត្តិការ​ជីភីអេស ឬ​ប្រភព​ទីតាំង​ផ្សេង។"</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"ចូល​ប្រើ​ទីតាំង​ជាក់លាក់​តែ​នៅផ្ទៃ​ខាងមុខ​ប៉ុណ្ណោះ"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"កម្មវិធីនេះ​អាចទទួល​បានទីតាំង​ពិតប្រាកដ​របស់អ្នក​តែនៅពេល​វាស្ថិតនៅ​ផ្ទៃខាងមុខប៉ុណ្ណោះ។ សេវាកម្ម​ទីតាំង​ទាំងនេះ​ត្រូវតែ​បើក និងមាន​នៅលើ​ទូរសព្ទ​របស់អ្នក ដើម្បីឱ្យ​កម្មវិធី​នេះអាចប្រើ​ពួកវាបាន។ វាអាចប្រើ​ថាមពល​ច្រើន​ជាងមុន។"</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"ចូលប្រើ​ទីតាំង​ប្រហាក់ប្រហែល (ផ្អែកលើ​បណ្តាញ) នៅផ្ទៃ​ខាងមុខ​តែប៉ុណ្ណោះ"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"កម្មវិធី​នេះ​អាច​ទទួល​បាន​ទីតាំង​របស់​អ្នក ដោយ​ផ្អែកលើ​ប្រភព​បណ្តាញ​ដូចជា អង់តែន​បណ្តាញ​ទូរសព្ទ និង​បណ្តាញ Wi-Fi ជាដើម ប៉ុន្តែនៅពេល​កម្មវិធីស្ថិតនៅ​ផ្ទៃខាងមុខ​តែប៉ុណ្ណោះ។ សេវាកម្ម​ទីតាំង​ទាំងនេះ​ត្រូវតែ​បើក និងមាន​នៅលើ​ថេប្លេត​របស់អ្នក ដើម្បីឱ្យ​កម្មវិធី​នេះអាចប្រើ​វាបាន។"</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"កម្មវិធីនេះ​អាច​ទទួល​បាន​ទីតាំង​របស់អ្នក ដោយ​ផ្អែកលើ​ប្រភព​បណ្តាញ​ដូចជា អង់តែន​បណ្តាញ​ទូរសព្ទ និង​បណ្តាញ Wi-Fi ជាដើម ប៉ុន្តែនៅពេល​​កម្មវិធីស្ថិតនៅ​ផ្ទៃខាងមុខ​តែប៉ុណ្ណោះ។ សេវាកម្ម​ទីតាំង​ទាំងនេះ​ត្រូវតែ​បើក និងមាន​នៅលើឧបករណ៍ Android TV របស់អ្នក ដើម្បីអាចឱ្យ​កម្មវិធី​ប្រើ​វាបាន។"</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"កម្មវិធី​នេះ​អាច​ទទួល​បាន​ទីតាំង​របស់​អ្នក ដោយ​ផ្អែកលើ​ប្រភព​បណ្តាញ​ដូចជា អង់តែន​បណ្តាញ​ទូរសព្ទ និង​បណ្តាញ Wi-Fi ជាដើម ប៉ុន្តែនៅពេល​កម្មវិធីស្ថិតនៅ​ផ្ទៃខាងមុខ​តែប៉ុណ្ណោះ។ សេវាកម្ម​ទីតាំង​ទាំងនេះ​ត្រូវតែ​បើក និងមាន​នៅលើ​ទូរសព្ទ​របស់អ្នក ដើម្បីឱ្យ​កម្មវិធី​នេះអាចប្រើ​វាបាន។"</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"កម្មវិធីនេះ​អាចទទួល​បានទីតាំង​ជាក់លាក់​របស់អ្នក​ តែនៅពេល​វាស្ថិតនៅ​ផ្ទៃខាងមុខប៉ុណ្ណោះ។ សេវាកម្ម​ទីតាំង​ត្រូវតែ​បើក និងមាន​នៅលើ​ឧបករណ៍​របស់អ្នក ដើម្បីអាចឱ្យ​កម្មវិធីប្រើ​វា​បាន។ សកម្មភាពនេះអាចបង្កើនការប្រើប្រាស់​ថ្ម។"</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"ចូលប្រើ​ទីតាំង​ប្រហាក់ប្រហែល​តែនៅផ្ទៃ​ខាងមុខប៉ុណ្ណោះ"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"កម្មវិធីនេះ​អាច​ទទួលបាន​ទីតាំង​ប្រហាក់ប្រហែល​របស់អ្នក​ តែនៅពេល​វា​ស្ថិតនៅ​ផ្ទៃ​ខាងមុខ​ប៉ុណ្ណោះ។ សេវាកម្ម​ទីតាំង​ត្រូវតែបើក និងមាន​នៅលើ​ឧបករណ៍​របស់អ្នក ដើម្បីអាច​ឱ្យ​កម្មវិធី​ប្រើវា​បាន។"</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"ចូល​ប្រើ​ទីតាំង​នៅ​ផ្ទៃខាងក្រោយ"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"ប្រសិនបើ​ផ្ដល់​ការអនុញ្ញាត​នេះ​បន្ថែម​ពីលើ​ការចូលប្រើទីតាំងជាក់លាក់ ឬប្រហាក់ប្រហែល កម្មវិធី​នឹងអាចចូលប្រើទីតាំងនោះ ខណៈពេលដំណើរការនៅផ្ទៃខាងក្រោយ។"</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"កម្មវិធី​នេះ​អាច​ចូលប្រើ​ទីតាំង ពេលកំពុង​ដំណើរការ​នៅផ្ទៃ​ខាងក្រោយ បន្ថែមពីលើ​ការចូល​ប្រើ​ទីតាំង​នៅផ្ទៃខាងមុខ។"</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"ប្ដូរ​ការ​កំណត់​អូឌីយូ​របស់​អ្នក"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"ឲ្យ​កម្មវិធី​កែ​ការ​កំណត់​សំឡេង​សកល ដូច​ជា​កម្រិត​សំឡេង និង​អូប៉ាល័រ​ដែល​បាន​ប្រើ​សម្រាប់​លទ្ធផល។"</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"ថត​សំឡេង"</string>
@@ -494,6 +491,8 @@
<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_preferredPaymentInfo" msgid="5274423844767445054">"ព័ត៌មានអំពី​សេវាបង់ប្រាក់តាម NFC ជាអាទិភាព"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"អនុញ្ញាតឱ្យ​កម្មវិធី​ទទួលបាន​ព័ត៌មានអំពី​សេវាបង់ប្រាក់តាម nfc ជាអាទិភាព​ដូចជា គោលដៅផ្លូវ និង​ព័ត៌មាន​កំណត់អត្តសញ្ញាណ​កម្មវិធី ដែលបានចុះឈ្មោះ​ជាដើម។"</string>
<string name="permlab_nfc" msgid="1904455246837674977">"ពិនិត្យ​ការ​ទាក់ទង​នៅ​ក្បែរ (NFC)"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"ឲ្យ​កម្មវិធី​ទាក់ទង​ជា​មួយ​ស្លាក (NFC) កាត និង​កម្មវិធី​អាន។"</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"បិទ​ការ​ចាក់​សោ​អេក្រង់​របស់​អ្នក"</string>
@@ -1620,12 +1619,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"ផ្លូវកាត់​ភាព​ងាយ​ស្រួល​បាន​បើក <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"ផ្លូវកាត់​ភាព​ងាយ​ស្រួល​បាន​បិទ <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>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"ជ្រើសរើស​សេវាកម្ម​ដែលត្រូវ​ប្រើ នៅពេល​ដែល​អ្នក​ចុច​ប៊ូតុង​ភាពងាយស្រួល៖"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"ជ្រើសរើស​សេវាកម្ម​ដែលត្រូវប្រើជាមួយចលនា​ភាពងាយស្រួល (អូស​ឡើងលើ​ពី​ផ្នែកខាងក្រោម​នៃ​អេក្រង់​ដោយប្រើ​ម្រាមដៃ​ពីរ)៖"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"ជ្រើសរើស​សេវាកម្ម​ដែលត្រូវប្រើជាមួយ​ចលនា​ភាពងាយស្រួល (អូស​ឡើងលើ​ពី​ផ្នែកខាងក្រោម​នៃ​អេក្រង់​ដោយប្រើ​ម្រាមដៃ​បី)៖"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"ដើម្បី​ប្ដូរឆ្លាស់​រវាង​សេវាកម្មផ្សេងៗ សូមចុច​ប៊ូតុង​ភាពងាយស្រួល​ឱ្យជាប់។"</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"ដើម្បី​ប្ដូរឆ្លាស់​រវាង​សេវាកម្មផ្សេងៗ សូមអូស​ឡើងលើ​ដោយប្រើ​ម្រាមដៃ​ពីរ ហើយ​សង្កត់ឱ្យជាប់។"</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"ដើម្បី​ប្ដូរឆ្លាស់​រវាង​សេវាកម្មផ្សេងៗ សូមអូស​ឡើងលើ​ដោយប្រើ​ម្រាមដៃ​បី ហើយ​សង្កត់ឱ្យជាប់។"</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>
@@ -1864,7 +1857,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"បានភ្ជាប់ទៅ <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"ប៉ះដើម្បីមើលឯកសារ"</string>
<string name="pin_target" msgid="8036028973110156895">"ខ្ទាស់"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"ខ្ទាស់ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"មិនខ្ទាស់"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"ដកខ្ទាស់ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"ព័ត៌មាន​កម្មវិធី"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"កំពុងចាប់ផ្តើមការបង្ហាញសាកល្បង…"</string>
@@ -1907,6 +1902,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"ធ្វើ​បច្ចុប្បន្នភាព​ធាតុ​ទាំងនេះ​នៅក្នុង "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <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>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"រក្សាទុក"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"ទេ អរគុណ"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"កុំ​ទាន់"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"កុំឱ្យសោះ"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"ធ្វើ​បច្ចុប្បន្នភាព"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"បន្ត"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"ពាក្យ​សម្ងាត់"</string>
@@ -2002,5 +1999,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"បិទ/បើក​មុខងារ​បំបែកអេក្រង់"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"អេក្រង់ចាក់សោ"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"រូបថតអេក្រង់"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"កម្មវិធី <xliff:g id="APP_NAME">%1$s</xliff:g> នៅក្នុងវិនដូ​លោតឡើង។"</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"របារពណ៌នា​អំពី <xliff:g id="APP_NAME">%1$s</xliff:g>។"</string>
</resources>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 6ebe7b490800..22edcae82312 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್‌ ನಿರ್ವಾಹಕ ಅಪ್ಲಿಕೇಶನ್ ಕಳೆದು ಹೋಗಿದೆ ಅಥವಾ ಹಾಳಾಗಿದೆ. ಇದರ ಪರಿಣಾಮವಾಗಿ ನಿಮ್ಮ ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್‌ ಮತ್ತು ಅದಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಡೇಟಾವನ್ನು ಅಳಿಸಲಾಗಿದೆ. ಸಹಾಯಕ್ಕಾಗಿ ನಿಮ್ಮ ನಿರ್ವಾಹಕರನ್ನು ಸಂಪರ್ಕಿಸಿ."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"ನಿಮ್ಮ ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್‌ ಈ ಸಾಧನದಲ್ಲಿ ಈಗ ಲಭ್ಯವಿಲ್ಲ"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"ಹಲವಾರು ಪಾಸ್‌ವರ್ಡ್ ಪ್ರಯತ್ನಗಳು"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"ವೈಯಕ್ತಿಕ ಬಳಕೆಗಾಗಿ ನಿರ್ವಾಹಕರು ತೊರೆದ ಸಾಧನ"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"ಸಾಧನವನ್ನು ನಿರ್ವಹಿಸಲಾಗುತ್ತಿದೆ"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"ನಿಮ್ಮ ಸಂಸ್ಥೆಯು ಈ ಸಾಧನವನ್ನು ನಿರ್ವಹಿಸುತ್ತದೆ ಮತ್ತು ಅದು ನೆಟ್‌ವರ್ಕ್ ಟ್ರಾಫಿಕ್ ಮೇಲೆ ಗಮನವಿರಿಸಬಹುದು. ವಿವರಗಳಿಗಾಗಿ ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"ನಿಮ್ಮ ಸಾಧನವನ್ನು ಅಳಿಸಲಾಗುತ್ತದೆ"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"ಪ್ರಸಾರವು ಮುಕ್ತಾಯಗೊಂಡ ನಂತರ ಉಳಿದಿರುವ ಜಿಗುಟಾದ ಪ್ರಸಾರಗಳನ್ನು ಕಳುಹಿಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ. ಇದರ ಹೆಚ್ಚಿನ ಬಳಕೆಯು Android TV ಸಾಧನವನ್ನು ನಿಧಾನಗೊಳಿಸುತ್ತದೆ ಅಥವಾ ಅತಿಯಾಗಿ ಮೆಮೊರಿಯನ್ನು ಬಳಸುವಂತೆ ಮಾಡುವ ಮೂಲಕ ಅಸ್ಥಿರಗೊಳಿಸುತ್ತದೆ."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"ಪ್ರಸಾರ ಕೊನೆಗೊಂಡ ನಂತರ ಹಾಗೆಯೇ ಉಳಿಯುವ ಸ್ಟಿಕಿ ಪ್ರಸಾರಗಳನ್ನು ಕಳುಹಿಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅನುಮತಿಸುತ್ತದೆ. ಮಿತಿಮೀರಿದ ಬಳಕೆಯು ಫೋನ್‍ ಅನ್ನು ನಿಧಾನಗೊಳಿಸಬಹುದು ಅಥವಾ ಅತಿಯಾದ ಮೆಮೊರಿ ಬಳಕೆಯು ಅಸ್ಥಿರತೆಯನ್ನು ಉಂಟುಮಾಡಬಹುದು."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"ನಿಮ್ಮ ಸಂಪರ್ಕಗಳನ್ನು ಓದಿರಿ"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"ನಿಮ್ಮ ಟ್ಯಾಬ್ಲೆಟ್‍ನಲ್ಲಿ ನಿರ್ದಿಷ್ಟ ವ್ಯಕ್ತಿಗಳೊಂದಿಗೆ ನೀವು ಇತರ ಮಾರ್ಗಗಳಲ್ಲಿ ಮಾಡಿರುವ ಕರೆ, ಇಮೇಲ್ ಅಥವಾ ಸಂವಹನ ನಡೆಸಿರುವ ಆವರ್ತನವೂ ಸೇರಿದಂತೆ, ನಿಮ್ಮ ಟ್ಯಾಬ್ಲೆಟ್‌ನಲ್ಲಿ ಸಂಗ್ರಹಿಸಲಾಗಿರುವ ನಿಮ್ಮ ಸಂಪರ್ಕಗಳ ಕುರಿತ ಡೇಟಾವನ್ನು ರೀಡ್ ಮಾಡಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುವು ಮಾಡಿಕೊಡುತ್ತದೆ. ಈ ಅನುಮತಿಯು ನಿಮ್ಮ ಸಂಪರ್ಕದ ಡೇಟಾವನ್ನು ಉಳಿಸಿಕೊಳ್ಳಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ ಮತ್ತು ದುರುದ್ದೇಶಪೂರಿತ ಅಪ್ಲಿಕೇಶನ್‍‍ಗಳು ನಿಮ್ಮ ಗಮನಕ್ಕೆ ತರದೆಯೇ ಸಂಪರ್ಕ ಡೇಟಾವನ್ನು ಹಂಚಿಕೊಳ್ಳಬಹುದು."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"ನಿರ್ದಿಷ್ಟ ವ್ಯಕ್ತಿಗಳೊಂದಿಗೆ ಇತರ ವಿಧಾನಗಳಲ್ಲಿ ನೀವು ಕರೆ ಮಾಡಿದ, ಇಮೇಲ್ ಮಾಡಿದ ಅಥವಾ ಸಂವಹನ ಮಾಡಿದ ಆವರ್ತನ ಪ್ರಮಾಣ ಸೇರಿದಂತೆ ನಿಮ್ಮ Android TV ಸಾಧನದಲ್ಲಿ ಸಂಗ್ರಹಿಸಲಾಗಿರುವ ನಿಮ್ಮ ಸಂಪರ್ಕಗಳ ಕುರಿತಾದ ಡೇಟಾವನ್ನು ಓದಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅನುಮತಿಸುತ್ತದೆ. ಈ ಅನುಮತಿಯು ನಿಮ್ಮ ಸಂಪರ್ಕದ ಡೇಟಾವನ್ನು ಉಳಿಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗಳಿಗೆ ಅನುಮತಿಸುತ್ತದೆ, ಮತ್ತು ದುರುದ್ದೇಶಪೂರಿತ ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ನಿಮ್ಮ ಸಂಪರ್ಕ ಡೇಟಾವನ್ನು ನಿಮಗೆ ತಿಳಿಯದಂತೆ ಹಂಚಿಕೊಳ್ಳಬಹುದು."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"ನಿಮ್ಮ ಫೋನ್‍‍ನಲ್ಲಿ ನಿರ್ದಿಷ್ಟ ವ್ಯಕ್ತಿಗಳ ಜೊತೆಗೆ ನೀವು ವಿವಿಧ ಮಾರ್ಗಗಳಲ್ಲಿ ಮಾಡಿರುವ ಕರೆ, ಇಮೇಲ್ ಮತ್ತು ಸಂವಹನವನ್ನು ನಡೆಸಿರುವ ಆವರ್ತನವೂ ಸೇರಿದಂತೆ, ನಿಮ್ಮ ಫೋನ್‌ನಲ್ಲಿ ಸಂಗ್ರಹಿಸಲಾಗಿರುವ ನಿಮ್ಮ ಸಂಪರ್ಕಗಳ ಕುರಿತ ಡೇಟಾವನ್ನು ರೀಡ್ ಮಾಡಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುವು ಮಾಡಿಕೊಡುತ್ತದೆ. ಈ ಅನುಮತಿಯು ನಿಮ್ಮ ಸಂಪರ್ಕದ ಡೇಟಾವನ್ನು ಉಳಿಸಿಕೊಳ್ಳಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ ಮತ್ತು ದುರುದ್ದೇಶಪೂರಿತ ಅಪ್ಲಿಕೇಶನ್‍‍ಗಳು ನಿಮ್ಮ ಗಮನಕ್ಕೆ ತರದೆಯೇ ಸಂಪರ್ಕ ಡೇಟಾವನ್ನು ಹಂಚಿಕೊಳ್ಳಬಹುದು."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"ನಿಮ್ಮ ಟ್ಯಾಬ್ಲೆಟ್‌ನಲ್ಲಿ ಸಂಗ್ರಹಿಸಲಾಗಿರುವ ನಿಮ್ಮ ಸಂಪರ್ಕಗಳ ಕುರಿತಾದ ಡೇಟಾವನ್ನು ರೀಡ್ ಮಾಡಲು ಆ್ಯಪ್‌ಗೆ ಅನುವು ಮಾಡಿಕೊಡುತ್ತದೆ. ಸಂಪರ್ಕಗಳನ್ನು ರಚಿಸಿದ ನಿಮ್ಮ ಟ್ಯಾಬ್ಲೆಟ್‌ನಲ್ಲಿನ ಖಾತೆಗಳಿಗೂ ಸಹ ಆ್ಯಪ್‌ಗಳು ಪ್ರವೇಶ ಹೊಂದಿರುತ್ತವೆ. ಇದರಲ್ಲಿ ನೀವು ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಿದ ಆ್ಯಪ್‌ಗಳು ರಚಿಸಿದ ಖಾತೆಗಳನ್ನು ಒಳಗೊಂಡಿರಬಹುದು. ಈ ಅನುಮತಿಯು ನಿಮ್ಮ ಸಂಪರ್ಕ ಡೇಟಾವನ್ನು ಉಳಿಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಅನುಮತಿಸುತ್ತದೆ, ಆದರೆ ದುರುದ್ದೇಶಪೂರಿತ ಆ್ಯಪ್‌ಗಳಿಗೆ ನಿಮ್ಮ ಗಮನಕ್ಕೆ ಬಾರದೇ ಸಂಪರ್ಕ ಡೇಟಾವನ್ನು ಹಂಚಿಕೊಳ್ಳಬಹುದು."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"ನಿಮ್ಮ Android TV ಸಾಧನದಲ್ಲಿ ಸಂಗ್ರಹಿಸಿರುವ ನಿಮ್ಮ ಸಂಪರ್ಕಗಳ ಕುರಿತಾದ ಡೇಟಾವನ್ನು ರೀಡ್ ಮಾಡಲು ಆ್ಯಪ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ. ನಿಮ್ಮ Android TV ಸಾಧನದಲ್ಲಿ ರಚಿಸಲಾದ ಸಂಪರ್ಕಗಳಿಗೆ ಖಾತೆಗಳಿಗೆ ಆ್ಯಪ್‌ಗಳು ಪ್ರವೇಶವನ್ನು ಹೊಂದಿರುತ್ತವೆ. ಇದರಲ್ಲಿ ನೀವು ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಿದ ಆ್ಯಪ್‌ಗಳು ರಚಿಸಿದ ಖಾತೆಗಳನ್ನು ಒಳಗೊಂಡಿರಬಹುದು. ಈ ಅನುಮತಿಯು ನಿಮ್ಮ ಸಂಪರ್ಕ ಡೇಟಾವನ್ನು ಉಳಿಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಅನುಮತಿಸುತ್ತದೆ, ಆದರೆ ದುರುದ್ದೇಶಪೂರಿತ ಆ್ಯಪ್‌ಗಳಿಗೆ ನಿಮ್ಮ ಗಮನಕ್ಕೆ ಬಾರದೇ ಸಂಪರ್ಕ ಡೇಟಾವನ್ನು ಹಂಚಿಕೊಳ್ಳಬಹುದು."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"ನಿಮ್ಮ ಫೋನ್‌ನಲ್ಲಿ ಸಂಗ್ರಹಿಸಲಾಗಿರುವ ನಿಮ್ಮ ಸಂಪರ್ಕಗಳ ಕುರಿತಾದ ಡೇಟಾವನ್ನು ರೀಡ್ ಮಾಡಲು ಆ್ಯಪ್‌ಗೆ ಅನುವು ಮಾಡಿಕೊಡುತ್ತದೆ. ಸಂಪರ್ಕಗಳನ್ನು ರಚಿಸಿದ ನಿಮ್ಮ ಫೋನ್‌ನಲ್ಲಿನ ಖಾತೆಗಳಿಗೂ ಸಹ ಆ್ಯಪ್‌ಗಳು ಪ್ರವೇಶ ಹೊಂದಿರುತ್ತವೆ. ಇದರಲ್ಲಿ ನೀವು ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಿದ ಆ್ಯಪ್‌ಗಳು ರಚಿಸಿದ ಖಾತೆಗಳನ್ನು ಒಳಗೊಂಡಿರಬಹುದು. ಈ ಅನುಮತಿಯು ನಿಮ್ಮ ಸಂಪರ್ಕ ಡೇಟಾವನ್ನು ಉಳಿಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಅನುಮತಿಸುತ್ತದೆ, ಆದರೆ ದುರುದ್ದೇಶಪೂರಿತ ಆ್ಯಪ್‌ಗಳಿಗೆ ನಿಮ್ಮ ಗಮನಕ್ಕೆ ಬಾರದೇ ಸಂಪರ್ಕ ಡೇಟಾವನ್ನು ಹಂಚಿಕೊಳ್ಳಬಹುದು."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"ನಿಮ್ಮ ಸಂಪರ್ಕಗಳನ್ನು ಮಾರ್ಪಡಿಸಿ"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"ನಿರ್ದಿಷ್ಟ ಸಂಪರ್ಕಗಳೊಂದಿಗೆ ಇತರ ಮಾರ್ಗಗಳಲ್ಲಿ ನೀವು ಕರೆ, ಇಮೇಲ್, ಅಥವಾ ಸಂವಹನ ನಡೆಸಿರುವ ಆವರ್ತನವೂ ಒಳಗೊಂಡಂತೆ, ನಿಮ್ಮ ಟ್ಯಾಬ್ಲೆಟ್‌ನಲ್ಲಿ ಸಂಗ್ರಹಿಸಲಾಗಿರುವ ನಿಮ್ಮ ಸಂಪರ್ಕಗಳ ಕುರಿತಾದ ಡೇಟಾವನ್ನು ಮಾರ್ಪಡಿಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅವಕಾಶ ನೀಡುತ್ತದೆ. ಈ ಅನುಮತಿಯು ಸಂಪರ್ಕದ ಡೇಟಾವನ್ನು ಅಳಿಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"ನಿರ್ದಿಷ್ಟ ವ್ಯಕ್ತಿಗಳೊಂದಿಗೆ ಇತರ ವಿಧಾನಗಳಲ್ಲಿ ನೀವು ಕರೆ ಮಾಡಿದ, ಇಮೇಲ್ ಮಾಡಿದ ಅಥವಾ ಸಂವಹನ ಮಾಡಿದ ಆವರ್ತನ ಪ್ರಮಾಣ ಸೇರಿದಂತೆ ನಿಮ್ಮ Android TV ಸಾಧನದಲ್ಲಿ ಸಂಗ್ರಹಿಸಲಾಗಿರುವ ನಿಮ್ಮ ಸಂಪರ್ಕಗಳ ಕುರಿತಾದ ಡೇಟಾವನ್ನು ಮಾರ್ಪಡಿಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅನುಮತಿಸುತ್ತದೆ. ಈ ಅನುಮತಿಯು ಸಂಪರ್ಕ ಡೇಟಾವನ್ನು ಅಳಿಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗಳಿಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"ನಿರ್ದಿಷ್ಟ ಸಂಪರ್ಕಗಳೊಂದಿಗೆ ಇತರ ಮಾರ್ಗಗಳಲ್ಲಿ ನೀವು ಕರೆ, ಇಮೇಲ್, ಅಥವಾ ಸಂವಹನ ನಡೆಸಿರುವ ಆವರ್ತನವೂ ಒಳಗೊಂಡಂತೆ, ನಿಮ್ಮ ಫೋನ್‍ನಲ್ಲಿ ಸಂಗ್ರಹಿಸಲಾಗಿರುವ ನಿಮ್ಮ ಸಂಪರ್ಕಗಳ ಕುರಿತಾದ ಡೇಟಾವನ್ನು ಮಾರ್ಪಡಿಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅವಕಾಶ ನೀಡುತ್ತದೆ. ಈ ಅನುಮತಿಯು ಸಂಪರ್ಕದ ಡೇಟಾವನ್ನು ಅಳಿಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"ನಿಮ್ಮ ಟ್ಯಾಬ್ಲೆಟ್‌ನಲ್ಲಿ ಸಂಗ್ರಹಿಸಲಾಗಿರುವ ನಿಮ್ಮ ಸಂಪರ್ಕಗಳ ಕುರಿತಾದ ಡೇಟಾವನ್ನು ಮಾರ್ಪಡಿಸಲು ಆ್ಯಪ್‌ಗೆ ಅವಕಾಶ ನೀಡುತ್ತದೆ. ಈ ಅನುಮತಿಯು ಸಂಪರ್ಕ ಡೇಟಾವನ್ನು ಅಳಿಸಲು ಆ್ಯಪ್‌ಗಳಿಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"ನಿಮ್ಮ Android TV ಸಾಧನದಲ್ಲಿ ಸಂಗ್ರಹಿಸಲಾಗಿರುವ ನಿಮ್ಮ ಸಂಪರ್ಕಗಳ ಕುರಿತಾದ ಡೇಟಾವನ್ನು ಮಾರ್ಪಡಿಸಲು ಆ್ಯಪ್‌ಗೆ ಅವಕಾಶ ನೀಡುತ್ತದೆ. ಈ ಅನುಮತಿಯು ಸಂಪರ್ಕ ಡೇಟಾವನ್ನು ಅಳಿಸಲು ಆ್ಯಪ್‌ಗಳಿಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"ನಿಮ್ಮ ಫೋನ್‍ನಲ್ಲಿ ಸಂಗ್ರಹಿಸಲಾಗಿರುವ ನಿಮ್ಮ ಸಂಪರ್ಕಗಳ ಕುರಿತಾದ ಡೇಟಾವನ್ನು ಮಾರ್ಪಡಿಸಲು ಆ್ಯಪ್‌ಗೆ ಅವಕಾಶ ನೀಡುತ್ತದೆ. ಈ ಅನುಮತಿಯು ಸಂಪರ್ಕ ಡೇಟಾವನ್ನು ಅಳಿಸಲು ಆ್ಯಪ್‌ಗಳಿಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"ಕರೆಯ ಲಾಗ್‌ ಓದಿ"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"ಈ ಅಪ್ಲಿಕೇಶನ್ ನಿಮ್ಮ ಕರೆಯ ಇತಿಹಾಸ ಓದಬಹುದು."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"ಕರೆ ಲಾಗ್ ಬರೆಯಿರಿ"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"ಹೆಚ್ಚುವರಿ ಸ್ಥಳ ಪೂರೈಕೆದಾರರ ಆದೇಶಗಳನ್ನು ಪ್ರವೇಶಿಸಿ"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"ಹೆಚ್ಚಿನ ಸ್ಥಳ ಪೂರೈಕೆದಾರ ಆದೇಶಗಳನ್ನು ಪ್ರವೇಶಿಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅವಕಾಶ ನೀಡುತ್ತದೆ. ಇದು GPS ಅಥವಾ ಇತರ ಸ್ಥಳ ಮೂಲಗಳ ಕಾರ್ಯಾಚರಣೆಯಲ್ಲಿ ಮಧ್ಯ ಪ್ರವೇಶಿಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅನುಮತಿಸಬಹುದು."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"ಮುನ್ನೆಲೆಯಲ್ಲಿ ಮಾತ್ರ ನಿಖರವಾದ ಸ್ಥಳವನ್ನು ಪ್ರವೇಶಿಸಿ"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"ಈ ಅಪ್ಲಿಕೇಶನ್‌ ಮುಂಭಾಗದಲ್ಲಿರುವಾಗ ಮಾತ್ರ ನಿಮ್ಮ ನಿಖರ ಸ್ಥಳವನ್ನು ಪಡೆಯಬಹುದು. ಈ ಸ್ಥಳ ಸೇವೆಗಳನ್ನು ಆನ್ ಮಾಡಿರಬೇಕು ಮತ್ತು ಅವುಗಳನ್ನು ಬಳಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಸಾಧ್ಯವಾಗುವಂತೆ ನಿಮ್ಮ ಫೋನ್‌ನಲ್ಲಿ ಅವುಗಳು ಲಭ್ಯವಿರಬೇಕು."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"ಮುನ್ನೆಲೆಯಲ್ಲಿ ಮಾತ್ರ ಅಂದಾಜು ಸ್ಥಳವನ್ನು (ನೆಟ್‌ವರ್ಕ್-ಆಧಾರಿತ) ಪ್ರವೇಶಿಸಿ"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"ಈ ಆ್ಯಪ್‌ ನಿಮ್ಮ ಸ್ಥಳವನ್ನು ಸೆಲ್ ಟವರ್‌ಗಳು ಮತ್ತು ವೈ-ಫೈ ನೆಟ್‍‍ವರ್ಕ್‌ಗಳಂತಹ ನೆಟ್‍‍ವರ್ಕ್ ಮೂಲಗಳ ಆಧಾರದ ಮೇಲೆ ಪಡೆಯಬಹುದು, ಆದರೆ ಆ್ಯಪ್‌ ಮುನ್ನೆಲೆಯಲ್ಲಿದ್ದಾಗ ಮಾತ್ರ. ಈ ಸ್ಥಳ ಸೇವೆಗಳನ್ನು ಆನ್ ಮಾಡಿರಬೇಕು ಮತ್ತು ಅವುಗಳನ್ನು ಬಳಸಲು ಆ್ಯಪ್‌ಗೆ ಸಾಧ್ಯವಾಗುವಂತೆ ನಿಮ್ಮ ಟ್ಯಾಬ್ಲೆಟ್‌ನಲ್ಲಿ ಅವುಗಳು ಲಭ್ಯವಿರಬೇಕು."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"ಈ ಅಪ್ಲಿಕೇಶನ್ ನಿಮ್ಮ ಸ್ಥಳವನ್ನು ಸೆಲ್ ಟವರ್‌ಗಳು ಮತ್ತು ವೈ-ಫೈ ನೆಟ್‍‍ವರ್ಕ್‌ಗಳಂತಹ ನೆಟ್‍‍ವರ್ಕ್ ಮೂಲಗಳ ಆಧಾರದ ಮೇಲೆ ಪಡೆಯಬಹುದು, ಆದರೆ ಅದು ಅಪ್ಲಿಕೇಶನ್ ಮುನ್ನೆಲೆಯಲ್ಲಿದ್ದಾಗ ಮಾತ್ರ. ಅವುಗಳನ್ನು ಬಳಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಸಾಧ್ಯವಾಗಲು ಈ ಸ್ಥಳ ಸೇವೆಗಳನ್ನು ಆನ್ ಮಾಡಿರಬೇಕು ಮತ್ತು ನಿಮ್ಮ Android TV ಸಾಧನದಲ್ಲಿ ಅವು ಲಭ್ಯವಿರಬೇಕು."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"ಈ ಆ್ಯಪ್‌ ನಿಮ್ಮ ಸ್ಥಳವನ್ನು ಸೆಲ್ ಟವರ್‌ಗಳು ಮತ್ತು ವೈ-ಫೈ ನೆಟ್‍‍ವರ್ಕ್‌ಗಳಂತಹ ನೆಟ್‍‍ವರ್ಕ್ ಮೂಲಗಳ ಆಧಾರದ ಮೇಲೆ ಪಡೆಯಬಹುದು, ಆದರೆ ಆ್ಯಪ್‌ ಮುನ್ನೆಲೆಯಲ್ಲಿದ್ದಾಗ ಮಾತ್ರ. ಈ ಸ್ಥಳ ಸೇವೆಗಳನ್ನು ಆನ್ ಮಾಡಿರಬೇಕು ಮತ್ತು ಅವುಗಳನ್ನು ಬಳಸಲು ಆ್ಯಪ್‌ಗೆ ಸಾಧ್ಯವಾಗುವಂತೆ ನಿಮ್ಮ ಫೋನ್‌ನಲ್ಲಿ ಅವುಗಳು ಲಭ್ಯವಿರಬೇಕು."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"ಈ ಆ್ಯಪ್ ಮುಂಭಾಗದಲ್ಲಿರುವಾಗ ಮಾತ್ರ ನಿಮ್ಮ ನಿಖರ ಸ್ಥಳವನ್ನು ಪಡೆಯಬಲ್ಲದು. ಸ್ಥಳ ಸೇವೆಗಳನ್ನು ಆನ್ ಮಾಡಿರಬೇಕು ಮತ್ತು ಅವುಗಳನ್ನು ಬಳಸಲು ಆ್ಯಪ್‌ಗೆ ಬಳಸಲು ಸಾಧ್ಯವಾಗುವಂತೆ ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಅವುಗಳು ಲಭ್ಯವಿರಬೇಕು. ಇದು ಬ್ಯಾಟರಿ ಬಳಕೆಯನ್ನು ಹೆಚ್ಚಿಸಬಹುದು."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"ಮುನ್ನೆಲೆಯಲ್ಲಿ ಮಾತ್ರ ಅಂದಾಜು ಸ್ಥಳವನ್ನು ಪ್ರವೇಶಿಸಿ"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"ಈ ಆ್ಯಪ್ ಮುನ್ನೆಲೆಯಲ್ಲಿರುವಾಗ ಮಾತ್ರ ನಿಮ್ಮ ಅಂದಾಜು ಸ್ಥಳವನ್ನು ಪಡೆಯಬಲ್ಲದು. ಸ್ಥಳ ಸೇವೆಗಳನ್ನು ಆನ್ ಮಾಡಿರಬೇಕು ಮತ್ತು ಅವುಗಳನ್ನು ಬಳಸಲು ಆ್ಯಪ್‌ಗೆ ಸಾಧ್ಯವಾಗುವಂತೆ ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಅವುಗಳು ಲಭ್ಯವಿರಬೇಕು."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"ಹಿನ್ನೆಲೆಯಲ್ಲಿ ಸ್ಥಳವನ್ನು ಪ್ರವೇಶಿಸಿ"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"ಇದನ್ನು ಅಂದಾಜು ಅಥವಾ ನಿಖರವಾದ ಸ್ಥಳ ಪ್ರವೇಶಕ್ಕೆ ಹೆಚ್ಚುವರಿಯಾಗಿ ಅನುಮತಿಸಿದರೆ, ಆ್ಯಪ್ ಹಿನ್ನೆಲೆಯಲ್ಲಿ ರನ್ ಆಗುತ್ತಿರುವಾಗ ಅದು ಸ್ಥಳವನ್ನು ಪ್ರವೇಶಿಸಬಹುದು."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"ಈ ಆ್ಯಪ್ ಹಿನ್ನೆಲೆಯಲ್ಲಿ ರನ್ ಆಗುವಾಗ ಸ್ಥಳದ ಜೊತೆಗೆ ಮುನ್ನೆಲೆಯಲ್ಲಿನ ಸ್ಥಳವನ್ನು ಪ್ರವೇಶಿಸಬಹುದು."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"ನಿಮ್ಮ ಆಡಿಯೊ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಬದಲಾಯಿಸಿ"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"ವಾಲ್ಯೂಮ್ ರೀತಿಯ ಮತ್ತು ಔಟ್‍‍ಪುಟ್‍‍ಗಾಗಿ ಯಾವ ಸ್ಪೀಕರ್ ಬಳಸಬೇಕು ಎಂಬ ರೀತಿಯ ಜಾಗತಿಕ ಆಡಿಯೊ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಮಾರ್ಪಡಿಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"ಆಡಿಯೊ ರೆಕಾರ್ಡ್ ಮಾಡಿ"</string>
@@ -494,6 +491,8 @@
<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_preferredPaymentInfo" msgid="5274423844767445054">"ಆದ್ಯತೆಯ NFC ಪಾವತಿ ಸೇವಾ ಮಾಹಿತಿ"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"ನೋಂದಾಯಿತ ಅಪ್ಲಿಕೇಶನ್ ಗುರುತಿಸುವಿಕೆಗಳು ಮತ್ತು ಮಾರ್ಗ ಗಮ್ಯಸ್ಥಾನಗಳಂತಹ ಆದ್ಯತೆಯ NFC ಪಾವತಿ ಸೇವೆಗಳ ಬಗ್ಗೆ ಮಾಹಿತಿಯನ್ನು ಪಡೆಯಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"ಸಮೀಪ ಕ್ಷೇತ್ರ ಸಂವಹನವನ್ನು ನಿಯಂತ್ರಿಸಿ"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"ಸಮೀಪದ ಕ್ಷೇತ್ರ ಸಂವಹನ (NFC) ಟ್ಯಾಗ್‌ಗಳು, ಕಾರ್ಡ್‌ಗಳು, ಮತ್ತು ಓದುಗರನ್ನು ಅಪ್ಲಿಕೇಶನ್‌ ಅನುಮತಿಸುತ್ತದೆ."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ ಲಾಕ್ ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ"</string>
@@ -1257,7 +1256,7 @@
<item msgid="9177085807664964627">"VPN"</item>
</string-array>
<string name="network_switch_type_name_unknown" msgid="3665696841646851068">"ಅಪರಿಚಿತ ನೆಟ್‌ವರ್ಕ್ ಪ್ರಕಾರ"</string>
- <string name="accept" msgid="5447154347815825107">"ಸ್ವೀಕರಿಸು"</string>
+ <string name="accept" msgid="5447154347815825107">"ಸ್ವೀಕರಿಸಿ"</string>
<string name="decline" msgid="6490507610282145874">"ನಿರಾಕರಿಸಿ"</string>
<string name="select_character" msgid="3352797107930786979">"ಅಕ್ಷರವನ್ನು ಸೇರಿಸಿ"</string>
<string name="sms_control_title" msgid="4748684259903148341">"SMS ಸಂದೇಶಗಳನ್ನು ಕಳುಹಿಸಲಾಗುತ್ತಿದೆ"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"ಪ್ರವೇಶಿಸುವಿಕೆ ಶಾರ್ಟ್‌ಕಟ್‌, <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ಅನ್ನು ಆನ್ ಮಾಡಿದೆ"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"ಪ್ರವೇಶಿಸುವಿಕೆ ಶಾರ್ಟ್‌ಕಟ್‌, <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>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"ನೀವು ಪ್ರವೇಶಿಸುವಿಕೆ ಬಟನ್ ಟ್ಯಾಪ್ ಮಾಡಿದಾಗ ಬಳಸುವುದಕ್ಕಾಗಿ ಸೇವೆಯೊಂದನ್ನು ಆರಿಸಿ:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"ಪ್ರವೇಶಿಸುವಿಕೆ ಗೆಸ್ಚರ್‌ನೊಂದಿಗೆ ಬಳಸಲು ಸೇವೆಯೊಂದನ್ನು ಆಯ್ಕೆಮಾಡಿ (ಎರಡು ಬೆರಳುಗಳನ್ನು ಬಳಸಿ ಪರದೆಯ ಕೆಳಭಾಗದಿಂದ ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"ಪ್ರವೇಶಿಸುವಿಕೆ ಗೆಸ್ಚರ್‌ನೊಂದಿಗೆ ಬಳಸಲು ಸೇವೆಯೊಂದನ್ನು ಆಯ್ಕೆಮಾಡಿ (ಮೂರು ಬೆರಳುಗಳನ್ನು ಬಳಸಿ ಪರದೆಯ ಕೆಳಭಾಗದಿಂದ ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"ಸೇವೆಗಳ ನಡುವೆ ಬದಲಿಸಲು, ಸ್ಪರ್ಶಿಸಿ ಮತ್ತು ಪ್ರವೇಶಿಸುವಿಕೆ ಬಟನ್ ಅನ್ನು ಒತ್ತಿ ಹಿಡಿಯಿರಿ."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"ಸೇವೆಗಳ ನಡುವೆ ಬದಲಿಸಲು, ಎರಡು ಬೆರಳುಗಳನ್ನು ಬಳಸಿ ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ ಮತ್ತು ಒತ್ತಿ ಹಿಡಿಯಿರಿ."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"ಸೇವೆಗಳ ನಡುವೆ ಬದಲಿಸಲು, ಮೂರು ಬೆರಳುಗಳನ್ನು ಬಳಸಿ ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ ಮತ್ತು ಒತ್ತಿ ಹಿಡಿಯಿರಿ."</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>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> ಗೆ ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆ"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"ಫೈಲ್‌ಗಳನ್ನು ವೀಕ್ಷಿಸಲು ಟ್ಯಾಪ್‌ ಮಾಡಿ"</string>
<string name="pin_target" msgid="8036028973110156895">"ಪಿನ್ ಮಾಡು"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"<xliff:g id="LABEL">%1$s</xliff:g> ಗೆ ಪಿನ್ ಮಾಡಿ"</string>
<string name="unpin_target" msgid="3963318576590204447">"ಅನ್‌ಪಿನ್"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"<xliff:g id="LABEL">%1$s</xliff:g> ಅನ್ನು ಅನ್‌ಪಿನ್ ಮಾಡಿ"</string>
<string name="app_info" msgid="6113278084877079851">"ಅಪ್ಲಿಕೇಶನ್ ಮಾಹಿತಿ"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"ಡೆಮೋ ಪ್ರಾರಂಭಿಸಲಾಗುತ್ತಿದೆ..."</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"ಈ ಮುಂದಿನ ಐಟಂಗಳನ್ನು "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" ನಲ್ಲಿ ಅಪ್‌ಡೇಟ್ ಮಾಡುವುದೇ: <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> ?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"ಉಳಿಸಿ"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"ಬೇಡ"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"ಸದ್ಯಕ್ಕೆ ಬೇಡ"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"ಎಂದೂ ಇಲ್ಲ"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"ಅಪ್‌ಡೇಟ್"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"ಮುಂದುವರಿಯಿರಿ"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"ಪಾಸ್‌ವರ್ಡ್"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"ಸ್ಪ್ಲಿಟ್-ಸ್ಕ್ರೀನ್ ಟಾಗಲ್ ಮಾಡಿ"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"ಲಾಕ್ ಸ್ಕ್ರೀನ್"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"ಪಾಪ್-ಅಪ್ ಸ್ಪೇಸ್ ವಿಂಡೋದಲ್ಲಿ <xliff:g id="APP_NAME">%1$s</xliff:g> ಆ್ಯಪ್."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಆ್ಯಪ್‌ನ ಶೀರ್ಷಿಕೆಯ ಪಟ್ಟಿ."</string>
</resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index c6caedf170cd..df26c4eee099 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"직장 프로필 관리 앱이 없거나 손상되어 직장 프로필 및 관련 데이터가 삭제되었습니다. 도움이 필요한 경우 관리자에게 문의하세요."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"직장 프로필을 이 기기에서 더 이상 사용할 수 없습니다."</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"비밀번호 입력을 너무 많이 시도함"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"관리자가 기기를 개인용으로 전환했습니다."</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"관리되는 기기"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"조직에서 이 기기를 관리하며 네트워크 트래픽을 모니터링할 수도 있습니다. 자세한 내용을 보려면 탭하세요."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"기기가 삭제됩니다."</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"앱에서 브로드캐스트가 끝난 후에도 남아 있는 스티키 브로드캐스트를 허용합니다. 지나치게 사용하면 Android TV 기기에서 메모리를 너무 많이 사용하여 기기가 불안정해지거나 속도가 저하될 수 있습니다."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"앱이 브로드캐스트가 끝난 후에 남은 브로드캐스트를 보낼 수 있도록 허용합니다. 앱을 지나치게 사용하면 휴대전화에서 메모리를 너무 많이 사용하도록 하여 속도를 저하시키거나 불안정하게 만들 수 있습니다."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"연락처 읽기"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"특정인과 전화, 이메일 또는 기타 수단으로 연락한 빈도를 포함하여 사용자 태블릿에 저장된 연락처에 대한 데이터를 앱이 읽도록 허용합니다. 이 권한을 사용하면 앱이 연락처 데이터를 저장할 수 있으며, 악성 앱이 사용자 모르게 연락처 데이터를 공유할 수도 있습니다."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"특정인과 전화, 이메일 또는 기타 방법으로 연락한 빈도를 비롯하여 Android TV 기기에 저장된 연락처에 관한 데이터를 앱이 읽도록 허용합니다. 이 권한을 사용하면 앱이 연락처 데이터를 저장할 수 있으며, 악성 앱이 사용자가 모르게 연락처 데이터를 공유할 수도 있습니다."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"특정인과 전화, 이메일 또는 기타 수단으로 연락한 빈도를 포함하여 사용자 휴대전화에 저장된 연락처에 대한 데이터를 앱이 읽도록 허용합니다. 이 권한을 사용하면 앱이 연락처 데이터를 저장할 수 있으며, 악성 앱이 사용자 모르게 연락처 데이터를 공유할 수도 있습니다."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"태블릿에 저장된 연락처에 관한 데이터를 앱이 읽도록 허용합니다. 또한 앱은 태블릿에서 연락처가 생성된 계정에도 액세스할 수 있습니다. 여기에는 설치한 앱에서 생성한 계정이 포함될 수 있습니다. 이 권한을 사용하면 앱이 연락처 데이터를 저장할 수 있으며, 악성 앱이 사용자가 모르게 연락처 데이터를 공유할 수도 있습니다."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Android TV 기기에 저장된 연락처에 관한 데이터를 앱이 읽도록 허용합니다. 또한 앱은 Android TV 기기에서 연락처가 생성된 계정에도 액세스할 수 있습니다. 여기에는 설치한 앱에서 생성한 계정이 포함될 수 있습니다. 이 권한을 사용하면 앱이 연락처 데이터를 저장할 수 있으며, 악성 앱이 사용자가 모르게 연락처 데이터를 공유할 수도 있습니다."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"휴대전화에 저장된 연락처에 관한 데이터를 앱이 읽도록 허용합니다. 또한 앱은 휴대전화에서 연락처가 생성된 계정에도 액세스할 수 있습니다. 여기에는 설치한 앱에서 생성한 계정이 포함될 수 있습니다. 이 권한을 사용하면 앱이 연락처 데이터를 저장할 수 있으며, 악성 앱이 사용자가 모르게 연락처 데이터를 공유할 수도 있습니다."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"연락처 수정"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"특정인과 전화, 이메일 또는 기타 수단으로 연락한 빈도를 포함하여 사용자 태블릿에 저장된 연락처에 대한 데이터를 앱이 수정할 수 있도록 허용합니다. 이 권한을 사용하면 앱이 연락처 데이터를 삭제할 수 있습니다."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"특정인과 전화, 이메일 또는 기타 방법으로 연락한 빈도를 비롯하여 Android TV 기기에 저장된 연락처에 관한 데이터를 앱이 수정하도록 허용합니다. 이 권한을 사용하면 앱에서 연락처 데이터를 삭제할 수 있습니다."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"특정인과 전화, 이메일 또는 기타 수단으로 연락한 빈도를 포함하여 사용자 휴대전화에 저장된 연락처에 대한 데이터를 앱이 수정할 수 있도록 허용합니다. 이 권한을 사용하면 앱이 연락처 데이터를 삭제할 수 있습니다."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"태블릿에 저장된 연락처에 관한 데이터를 앱이 수정하도록 허용합니다. 이 권한을 사용하면 앱에서 연락처 데이터를 삭제할 수 있습니다."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Android TV 기기에 저장된 연락처에 관한 데이터를 앱이 수정하도록 허용합니다. 이 권한을 사용하면 앱에서 연락처 데이터를 삭제할 수 있습니다."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"휴대전화에 저장된 연락처에 관한 데이터를 앱이 수정하도록 허용합니다. 이 권한을 사용하면 앱에서 연락처 데이터를 삭제할 수 있습니다."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"통화 기록 읽기"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"이 앱은 통화 기록을 읽을 수 있습니다."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"통화 기록 쓰기"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"추가 위치 제공업체 명령에 접근"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"앱이 추가 위치 정보 제공 기능의 명령에 접근하도록 허용합니다. 이 경우 앱이 GPS 또는 기타 위치 소스의 작동을 방해할 수 있습니다."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"포그라운드에서만 정확한 위치에 액세스"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"이 앱은 포그라운드에 있을 때만 나의 정확한 위치를 알 수 있습니다. 앱에서 위치 서비스를 사용하려면 휴대전화에서 위치 서비스가 사용 설정되어 있으며 사용할 수 있어야 합니다. 배터리 사용량이 늘어날 수 있습니다."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"포그라운드에서만 대략적인 위치(네트워크 기반)에 액세스"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"앱이 포그라운드에 있을 때만 휴대전화 기지국과 Wi-Fi 네트워크 등의 네트워크 소스를 바탕으로 사용자의 위치를 파악할 수 있습니다. 앱에서 위치 서비스를 사용하려면 태블릿에서 위치 서비스가 켜져 있으며 사용 가능해야 합니다."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"앱이 포그라운드에 있을 때만 휴대전화 기지국과 Wi-Fi 네트워크 등의 네트워크 소스를 바탕으로 사용자의 위치를 파악할 수 있습니다. 앱에서 위치 서비스를 사용하려면 Android TV 기기에서 위치 서비스를 지원하며 사용 설정되어 있어야 합니다."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"앱이 포그라운드에 있을 때만 휴대전화 기지국과 Wi-Fi 네트워크 등의 네트워크 소스를 바탕으로 사용자의 위치를 파악할 수 있습니다. 앱에서 위치 서비스를 사용하려면 휴대전화에서 위치 서비스가 켜져 있으며 사용 가능해야 합니다."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"이 앱은 포그라운드에 있을 때만 나의 정확한 위치를 확인할 수 있습니다. 앱에서 위치 서비스를 사용하려면 기기에서 위치 서비스가 지원되며 사용 설정되어 있어야 합니다. 배터리 사용량이 늘어날 수 있습니다."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"포그라운드에서만 대략적인 위치에 액세스"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"이 앱은 포그라운드에 있을 때만 나의 대략적인 위치를 확인할 수 있습니다. 앱에서 위치 서비스를 사용하려면 기기에서 위치 서비스가 지원되며 사용 설정되어 있어야 합니다."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"백그라운드에서 위치 정보 액세스"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"이 권한이 대략적인 위치 정보 또는 정확한 위치 정보 액세스 권한에 추가적으로 부여되면 앱이 백그라운드에서 실행되는 동안 위치에 액세스할 수 있습니다."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"이 앱이 포그라운드뿐만 아니라 백그라운드에서 실행되는 동안에도 위치에 액세스할 수 있습니다."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"오디오 설정 변경"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"앱이 음량이나 출력을 위해 사용하는 스피커 등 전체 오디오 설정을 변경할 수 있도록 허용합니다."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"오디오 녹음"</string>
@@ -494,6 +491,8 @@
<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_preferredPaymentInfo" msgid="5274423844767445054">"기본 NFC 결제 서비스 정보"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"앱이 등록된 AID와 경로 목적지 같은 기본 NFC 결제 서비스 정보를 확인하도록 허용합니다."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"NFC(Near Field Communication) 제어"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"앱이 NFC(근거리 무선 통신) 태그, 카드 및 리더와 통신할 수 있도록 허용합니다."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"화면 잠금 사용 중지"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"접근성 단축키로 인해 <xliff:g id="SERVICE_NAME">%1$s</xliff:g>이(가) 사용 설정되었습니다."</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"접근성 단축키로 인해 <xliff:g id="SERVICE_NAME">%1$s</xliff:g>이(가) 사용 중지되었습니다."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> 서비스를 사용하려면 두 볼륨 키를 3초 동안 길게 누르세요"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"접근성 버튼을 탭했을 때 실행할 서비스를 선택하세요."</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"접근성 동작(두 손가락을 사용하여 화면 하단에서 위로 스와이프)으로 실행할 서비스를 선택하세요."</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"접근성 동작(세 손가락을 사용하여 화면 하단에서 위로 스와이프)으로 실행할 서비스를 선택하세요."</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"서비스 간에 전환하려면 접근성 버튼을 길게 터치합니다."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"서비스 간에 전환하려면 두 손가락을 사용하여 위로 스와이프한 다음 잠시 기다립니다."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"서비스 간에 전환하려면 세 손가락을 사용하여 위로 스와이프한 다음 잠시 기다립니다."</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>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g>에 연결됨"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"파일을 확인하려면 탭하세요."</string>
<string name="pin_target" msgid="8036028973110156895">"고정"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"<xliff:g id="LABEL">%1$s</xliff:g> 고정"</string>
<string name="unpin_target" msgid="3963318576590204447">"고정 해제"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"<xliff:g id="LABEL">%1$s</xliff:g> 고정 해제"</string>
<string name="app_info" msgid="6113278084877079851">"앱 정보"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"데모 시작 중..."</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291"><b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"에서 <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> 업데이트"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"저장"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"사용 안함"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"나중에"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"사용 안함"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"업데이트"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"계속"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"비밀번호"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"화면 분할 모드 전환"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"잠금 화면"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"스크린샷"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"팝업 창의 <xliff:g id="APP_NAME">%1$s</xliff:g> 앱"</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g>의 자막 표시줄입니다."</string>
</resources>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 341c99618633..adcc4c1b46e1 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Жумуш профилинин башкаруучу колдонмосу жок же бузулгандыктан, жумуш профилиңиз жана ага байланыштуу дайындар жок кылынды. Жардам алуу үчүн администраторуңузга кайрылыңыз."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Жумуш профилиңиз бул түзмөктөн жок кылынды"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Өтө көп жолу сырсөздү киргизүү аракети жасалды"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Админ түзмөктөн жеке колдонуу үчүн баш тартты"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Түзмөктү ишкана башкарат"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Ишканаңыз бул түзмөктү башкарат жана тармак трафигин көзөмөлдөшү мүмкүн. Чоо-жайын көрүү үчүн таптап коюңуз."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Түзмөгүңүз тазаланат"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Колдонмого таркатма аяктагандан кийин калган кадалган таркатмаларды жөнөтүүгө уруксат берет. Ашыкча колдонуу Android TV түзмөгүңүздүн өтө көп эстутумду пайдалануу менен жай же туруксуз иштешине алып келиши мүмкүн."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Колдонмого берүү токтогондон кийин улантыла берүүчү жабышкак берүүлөрдү жөнөтүү уруксатын берет. Муну ашыкча колдонуу, эстутумду өтө көп пайдаланууга алып келип, телефондун жай же туруксуз иштөөсүнүнө себепкер болушу мүмкүн."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"байланыштарыңызды окуу"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Колдонмо планшетиңиздеги байланыштар, ошондой эле белгилүү бир адамдар менен канчалык көп чалышып, кат жазышып жана башка жолдор менен байланышып жаткандыгыңыз тууралуу маалыматты көрүп, сактай алат. Мындай уруксатты алган колдонмолор байланыштар тууралуу маалыматты сактай алышат, ал эми зыянкеч программалар байланыштар тууралуу маалыматты алдын ала эскертүүсүз бөлүшүүсү мүмкүн."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Колдонмого Android TV түзмөгүңүздө сакталган байланыштар тууралуу дайындарды, анын ичинде белгилүү бир байланыштарга канча убакытта бир чалып, электрондук кат жөнөтүп же башка ыкмалар менен баарлашканыңызды өзгөртүүгө колдонмого уруксат берет. Бул уруксат колдонмолорго байланыштарыңыздын дайындарын сактоого уруксат берет жана зыянкеч колдонмолор ал дайындарды сизге кабарлабастан башкалар менен бөлүшүүсү мүмкүн."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Колдонмо түзмөктөгү байланыштар, ошондой эле белгилүү бир адамдар менен канчалык көп чалышып, кат жазышып жана башка жолдор менен байланышып жаткандыгыңыз тууралуу маалыматты көрүп, сактай алат. Зыянкеч программалар байланыштар тууралуу маалыматты алдын ала эскертүүсүз бөлүшүүсү мүмкүн."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Колдонмо планшетиңизде сакталган байланыштардын дайын-даректерин көрө алат. Мындан тышкары, колдонмолорго планшетиңиздеги байланыштар камтылган аккаунттар да жеткиликтүү болот. Алардын катарына сиз орноткон колдонмолордо түзүлгөн аккаунттар кириши мүмкүн. Байланыштардын чоо-жайын сактоо мүмкүнчүлүгүнө ээ болгон зыянкеч программалар ал маалыматты сиздин уруксатыңызсыз башкаларга бериши мүмкүн."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Колдонмо Android TV түзмөгүңүздө сакталган байланыштардын дайын-даректерин көрө алат. Мындан тышкары, колдонмолорго Android TV түзмөгүңүздөгү байланыштар камтылган аккаунттар да жеткиликтүү болот. Алардын катарына сиз орноткон колдонмолордо түзүлгөн аккаунттар кириши мүмкүн. Байланыштардын чоо-жайын сактоо мүмкүнчүлүгүнө ээ болгон зыянкеч программалар ал маалыматты сиздин уруксатыңызсыз башкаларга бериши мүмкүн."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Колдонмо телефонуңузда сакталган байланыштардын дайын-даректерин көрө алат. Мындан тышкары, колдонмолорго телефонуңуздагы байланыштар камтылган аккаунттар да жеткиликтүү болот. Алардын катарына сиз орноткон колдонмолордо түзүлгөн аккаунттар кириши мүмкүн. Байланыштардын чоо-жайын сактоо мүмкүнчүлүгүнө ээ болгон зыянкеч программалар ал маалыматты сиздин уруксатыңызсыз башкаларга бериши мүмкүн."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"байланыштарыңызды өзгөртүү"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Колдонмо планшетиңиздеги байланыштар, ошондой эле белгилүү бир адамдар менен канчалык көп чалышып, кат жазышып жана башка жолдор менен байланышып жаткандыгыңыз тууралуу маалыматты өзгөртө алат. Мындай уруксатты алган колдонмолор байланыштар тууралуу маалыматты жок кыла алышат."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Android TV түзмөгүңүздө сакталган байланыштар тууралуу дайындарды, анын ичинде белгилүү бир байланыштарга канча убакытта бир чалып, электрондук кат жөнөтүп же башка ыкмалар менен баарлашканыңызды өзгөртүүгө колдонмого уруксат берет. Бул уруксат колдонмолорго байланыштардын дайындарын өчүрүүгө уруксат берет."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Колдонмо телефонуңуздагы байланыштар, ошондой эле белгилүү бир адамдар менен канчалык көп чалышып, кат жазышып жана башка жолдор менен байланышып жаткандыгыңыз тууралуу маалыматты өзгөртө алат. Мындай уруксатты алган колдонмолор байланыштар тууралуу маалыматты жок кыла алышат."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Колдонмо планшетиңизде сакталган байланыштарыңыздын дайын-даректерин өзгөртө алат. Мындан тышкары, бул уруксат колдонмолорго байланыштардын дайын-даректерин өчүрүүгө уруксат берет."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Колдонмо Android TV түзмөгүңүздө сакталган байланыштарыңыздын дайын-даректерин өзгөртө алат. Мындан тышкары, бул уруксат колдонмолорго байланыштардын дайын-даректерин өчүрүүгө уруксат берет."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Колдонмо телефонуңузда сакталган байланыштарыңыздын дайын-даректерин өзгөртө алат. Мындан тышкары, бул уруксат колдонмолорго байланыштардын дайын-даректерин өчүрүүгө уруксат берет."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"чалуулар тизмегин окуу"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Бул колдонмо чалууларыңыздын таржымалын окуй алат."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"чалуулар тизмегин жаздыруу"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"жайгашкан жерди аныктагычтын кошумча буйруктарын пайдалануу"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Колдонмого жайгашкан жерди табуучу кошумча жабдуучулардын буйруктарын колдонуу мүмкүнчүлүгүн берет. Ушуну менен колдонмо GPS\'тин ишине жана башка жайгашкан жерлерди аныктоо кызматтарына кийлигише алат."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"так аныкталган жайгашкан жерге активдүү режимде гана кирүүгө уруксат берүү"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Бул колдонмонун активдүү режимде гана жайгашкан жериңиздин дайындарын алууга мүмкүнчүлүгү бар. Колдонмо бул кызматтарды пайдаланышы үчүн аларды күйгүзүп, телефонуңузга туташтырып коюшуңуз керек. Ушуну менен батареянын кубаты көбүрөөк сарпталышы мүмкүн."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"болжолдуу аныкталган жайгашкан жерге (тармактын негизинде) автивдүү режимде гана кирүүгө уруксат берүү"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Бул колдонмо байланыш мунаралары жана Wi-Fi сыяктуу тармактык булактар аркылуу жайгашкан жериңизди аныктай алат, бирок ал үчүн колдонмо ачылып турушу керек. Колдонмо бул кызматтарды пайдаланышы үчүн, аларды күйгүзүп, планшетиңизге туташтырып коюшуңуз керек."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Бул колдонмо байланыш мунаралары жана Wi-Fi сыяктуу тармактык булактар аркылуу жайгашкан жериңизди аныктай алат, бирок ал үчүн колдонмо ачылып турушу керек. Колдонмо бул кызматтарды пайдаланышы үчүн жайгашкан жерди аныктоо кызматтарын күйгүзүп, Android TV түзмөгүңүзгө туташтырып коюшуңуз керек."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Бул колдонмо байланыш мунаралары жана Wi-Fi сыяктуу тармактык булактар аркылуу жайгашкан жериңизди аныктай алат, бирок ал үчүн колдонмо ачылып турушу керек. Колдонмо бул кызматтарды пайдаланышы үчүн, аларды күйгүзүп, телефонуңузга туташтырып коюшуңуз керек."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Колдонмо кайда жүргөнүңүздү активдүү режимде гана аныктай алат. Ал үчүн түзмөгүңүздө жайгашкан жерди аныктоо кызматын иштетип, колдонмого кайда жүргөнүңүздү аныктоого уруксат беришиңиз керек. Батареяңыз тез отуруп калышы мүмкүн."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"кайда жүргөнүмдү активдүү режимде божомолдоого уруксат берүү"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Колдонмо кайда жүргөнүңүздү активдүү режимде гана аныктай алат. Ал үчүн түзмөгүңүздө жайгашкан жерди аныктоо кызматын иштетип, колдонмого кайда жүргөнүңүздү аныктоого уруксат беришиңиз керек."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"жайгашкан жерди фондо аныктоо"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Эгер колдонмого жайгашкан жерди болжолдуу же так аныктоого уруксат берилсе, ал фондо иштеп жатып эле жайгашкан жерди аныктап турат."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Колдонмо кайда жүргөнүңүздү активдүү режимде гана эмес, фондук режимде да аныктай алат."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"аудио жөндөөлөрүңүздү өзгөртүңүз"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Колдонмого үн деңгээли жана кайсы динамик аркылуу үн чыгарылышы керек сыяктуу түзмөктүн аудио тууралоолорун өзгөртүүгө уруксат берет."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"аудио жаздыруу"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Колдонмого планшеттин Bluetooth конфигурацияларын көрүү, жупталган түзмөктөр менен байланыш түзүү жана кабыл алуу уруксатын берет."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Android TV түзмөгүңүздөгү Bluetooth конфигурациясын көрүп, жупташтырылган түзмөктөргө туташууга жана туташуу сурамын кабыл алууга колдонмого уруксат берет."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Колдонмого телефондун Bluetooth конфигурацияларын көрүү, жупташкан түзмөктөр менен туташуу түзүү жана кабыл алуу уруксатын берет."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Тандалган NFC төлөм кызматы жөнүндө маалымат"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Колдонмого катталган жардам же көздөлгөн жерге маршрут сыяктуу тандалган nfc төлөм кызматы жөнүндө маалыматты алууга уруксат берүү."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"Near Field Communication көзөмөлү"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Колдонмого Жакынкы аралыкта байланышуу (NFC) белгилери, карталары жана окугучтары менен байланышуу мүмкүнчүлүгүн берет."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"экранды бөгөттөөнү өчүрүү"</string>
@@ -605,8 +604,8 @@
<string name="permdesc_register_call_provider" msgid="4201429251459068613">"Колдонмого жаңы телеком туташууларын каттоо мүмкүнчүлүгүн берет."</string>
<string name="permlab_connection_manager" msgid="3179365584691166915">"телеком туташууларын башкаруу"</string>
<string name="permdesc_connection_manager" msgid="1426093604238937733">"Колдонмого телеком туташууларын башкаруу мүмкүнчүлүгүн берет."</string>
- <string name="permlab_bind_incall_service" msgid="5990625112603493016">"чалуу экраны менен байланыштыруу"</string>
- <string name="permdesc_bind_incall_service" msgid="4124917526967765162">"Колдонмого чалуу экраны качан жана кандай көрүнө тургандыгын башкаруу мүмкүнчүлүгүн берет."</string>
+ <string name="permlab_bind_incall_service" msgid="5990625112603493016">"сүйлөшүп жатканда экранды башкара аласыз"</string>
+ <string name="permdesc_bind_incall_service" msgid="4124917526967765162">"Сүйлөшүп жатканда экранды башкара аласыз."</string>
<string name="permlab_bind_connection_service" msgid="5409268245525024736">"телефония кызматтары"</string>
<string name="permdesc_bind_connection_service" msgid="6261796725253264518">"Колдонмого чалууларды жасоо/кабыл алуу үчүн телефония кызматтары менен байланышууга уруксат берет."</string>
<string name="permlab_control_incall_experience" msgid="6436863486094352987">"чалуу ичиндеги колдонуучу тажрыйбасын камсыз кылуу"</string>
@@ -827,7 +826,7 @@
<string name="lockscreen_transport_stop_description" msgid="1449552232598355348">"Токтотуу"</string>
<string name="lockscreen_transport_rew_description" msgid="7680106856221622779">"Артка түрүү"</string>
<string name="lockscreen_transport_ffw_description" msgid="4763794746640196772">"Алдыга түрүү"</string>
- <string name="emergency_calls_only" msgid="3057351206678279851">"Өзгөчө кырдаалда гана чалууга болот"</string>
+ <string name="emergency_calls_only" msgid="3057351206678279851">"Кырсыктаганда гана чалуу"</string>
<string name="lockscreen_network_locked_message" msgid="2814046965899249635">"Тармак кулпуланган"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="6618356415831082174">"SIM-карта PUK-бөгөттө."</string>
<string name="lockscreen_sim_puk_locked_instructions" msgid="5307979043730860995">"Колдонуучунун нускамасын караңыз же Кардарларды тейлөө борборуна кайрылыңыз."</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"Атайын мүмкүнчүлүктөр кыска жолу <xliff:g id="SERVICE_NAME">%1$s</xliff:g> кызматын күйгүздү"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"Атайын мүмкүнчүлүктөр кыска жолу <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>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Атайын мүмкүнчүлүктөр баскычын таптаганыңызда иштей турган кызматты тандаңыз:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Атайын мүмкүнчүлүктөр жаңсоосу үчүн кызматты тандаңыз (эки манжаңыз менен экрандын ылдый жагынан өйдө карай сүрүңүз):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Атайын мүмкүнчүлүктөр жаңсоосу аркылуу иштетиле турган кызматты тандаңыз (үч манжаңыз менен экрандын ылдый жагынан өйдө карай сүрүңүз):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Кызматтарды которуштуруу үчүн Атайын мүмкүнчүлүктөр баскычын басып, кармап туруңуз."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Кызматтарды которуштуруу үчүн эки манжаңыз менен өйдө сүрүп, кармап туруңуз."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Башка кызматка которулуу үчүн үч манжаңыз менен экранды өйдө сүрүп, кармап туруңуз."</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>
@@ -1757,8 +1750,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="1817385558636532621">"Батареянын кубатынын мөөнөтүн узартуу үчүн Батареяны үнөмдөгүч режими төмөнкүлөрдү аткарат:\n·Түнкү режимди күйгүзөт\n·Фондогу аракеттерди, айрым визуалдык эффекттерди жана \"Окей Google\" сыяктуу башка функцияларды өчүрөт же чектейт\n\n"<annotation id="url">"Кеңири маалымат"</annotation></string>
- <string name="battery_saver_description" msgid="7618492104632328184">"Батареянын кубатынын мөөнөтүн узартуу үчүн Батареяны үнөмдөгүч режими төмөнкүлөрдү аткарат:\n·Түнкү режимди күйгүзөт\n·Фондогу аракеттерди, айрым визуалдык эффекттерди жана \"Окей Google\" сыяктуу башка функцияларды өчүрөт же чектейт"</string>
+ <string name="battery_saver_description_with_learn_more" msgid="1817385558636532621">"Батареяны үнөмдөө үчүн Батареяны үнөмдөгүч:\n·Караңгы теманы күйгүзөт\n·Фондогу аракеттерди, айрым визуалдык эффекттерди жана \"Окей Google\" сыяктуу башка функцияларды өчүрөт же чектейт\n\n"<annotation id="url">"Кеңири маалымат"</annotation></string>
+ <string name="battery_saver_description" msgid="7618492104632328184">"Батареяны үнөмдөө үчүн Батареяны үнөмдөгүч режими:\n·Караңгы теманы күйгүзөт\n·Фондогу аракеттерди, айрым визуалдык эффекттерди жана \"Окей Google\" сыяктуу башка функцияларды өчүрөт же чектейт"</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>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> менен туташты"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Файлдарды көрүү үчүн таптап коюңуз"</string>
<string name="pin_target" msgid="8036028973110156895">"Кадоо"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"<xliff:g id="LABEL">%1$s</xliff:g> кадоо"</string>
<string name="unpin_target" msgid="3963318576590204447">"Кадоодон алып коюу"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"<xliff:g id="LABEL">%1$s</xliff:g> бошотуу"</string>
<string name="app_info" msgid="6113278084877079851">"Колдонмо тууралуу"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Демо режим башталууда…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291"><b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" кызматындагы төмөнкүлөр жаңыртылсынбы: <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>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Сактоо"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Жок, рахмат"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Азыр эмес"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Эч качан"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Жаңыртуу"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Улантуу"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"сырсөз"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Экранды бөлүүнү күйгүзүү же өчүрүү"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Кулпуланган экран"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Скриншот"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосу Калкыма терезеде көрүндү."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосунун маалымат тилкеси."</string>
</resources>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index e0da2064301c..230f2b52a3d6 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"ບໍ່ມີແອັບຜູ້ເບິ່ງແຍງລະບົບໂປຣໄຟລ໌ບ່ອນເຮັດວຽກ ຫຼື ເສຍຫາຍ. ຜົນກໍຄື, ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກ ແລະ ຂໍ້ມູນທີ່ກ່ຽວຂ້ອງຂອງທ່ານຖືກລຶບອອກແລ້ວ. ໃຫ້ຕິດຕໍ່ຜູ້ເບິ່ງແຍງລະບົບສຳລັບການຊ່ວຍເຫຼືອ."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກຂອງທ່ານບໍ່ສາມາດໃຊ້ໄດ້ໃນອຸປະກອນນີ້ອີກຕໍ່ໄປ"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"ລອງໃສ່ລະຫັດຜ່ານຫຼາຍເທື່ອເກີນໄປ"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"ອຸປະກອນທີ່ຍົກເລີກແລ້ວສຳລັບການໃຊ້ສ່ວນບຸກຄົນ"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"ອຸປະກອນມີການຈັດການ"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"ອົງກອນຂອງທ່ານຈັດການອຸປະກອນນີ້ ແລະ ອາດກວດສອບທຣາບຟິກເຄືອຂ່າຍນຳ. ແຕະເພື່ອເບິ່ງລາຍລະອຽດ."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"ອຸ​ປະ​ກອນ​ຂອງ​ທ່ານ​ຈະ​ຖືກ​ລຶບ"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"ອະນຸຍາດໃຫ້ແອັບສົ່ງການອອກອາກາດແບບຍຶດຕິດ, ເຊິ່ງຍັງຄົງຢູ່ຫຼັງຈາກການອອກອາກາດສິ້ນສຸດ. ການໃຊ້ເກີນອາດຈະເຮັດໃຫ້ອຸປະກອນ Android TV ຂອງທ່ານຊ້າລົງ ຫຼື ບໍ່ໝັ້ນຄົງເນື່ອງຈາກມັນໃຊ້ໜ່ວຍຄວາມຈຳຫຼາຍເກີນໄປ."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"ອະນຸຍາດໃຫ້ແອັບພລິເຄຊັນສົ່ງການກະຈາຍສັນຍານແບບຍຶດຕິດ, ທີ່ຍັງຄົງເຫຼືອຫຼັງຈາກການກະຈາຍສັນຍານສິ້ນສຸດລົງ. ການນຳໃຊ້ແບບມະຫາສານອາດເຮັດໃຫ້ໂທລະສັບຊ້າ ຫຼືບໍ່ສະຖຽນ ໂດຍການໃຊ້ໜ່ວຍຄວາມຈຳຫຼາຍເກີນໄປ."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"ອ່ານລາຍຊື່ຜູ່ຕິດຕໍ່ຂອງທ່ານ"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"ອະນຸຍາດໃຫ້ແອັບຯອ່ານຂໍ້ມູນກ່ຽວກັບລາຍຊື່ຜູ່ຕິດຕໍ່ໃນແທັບເລັດຂອງທ່ານ, ຮວມເຖິງຂໍ້ມູນການຈຳນວນການຕິດຕໍ່ຕ່າງໆເຊັ່ນ: ການໂທ, ອີເມວ, ຫຼືຕິດຕໍ່ຫາໃນທາງອື່ນໆກັບບຸກຄົນໃດນຶ່ງໄດ້. ການອະນຸຍາດນີ້ເຮັດໃຫ້ແອັບຯ ສາມາດບັນທຶກຂໍ້ມູນຜູ່ຕິດຕໍ່ຂອງທ່ານ ແລະແອັບຯທີ່ເປັນອັນຕະລາຍ ອາດສົ່ງຕໍ່ຂໍ້ມູນເຫຼົ່ານັ້ນໂດຍທີ່ທ່ານບໍ່ຮູ້ໂຕ."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"ອະນຸຍາດໃຫ້ແອັບອ່ານຂໍ້ມູນກ່ຽວກັບລາຍຊື່ຜູ້ຕິດຕໍ່ຂອງທ່ານທີ່ບັນທຶກໄວ້ຢູ່ໃນອຸປະກອນ Android TV ຂອງທ່ານ, ຮວມທັງຄວາມຖີ່ທີ່ທ່ານໄດ້ໂທ, ອີເມວ ຫຼື ສື່ສານກັບບຸກຄົນສະເພາະດ້ວຍວິທີອື່ນ. ສິດອະນຸຍາດນີ້ຈະເຮັດໃຫ້ແອັບຕ່າງໆສາມາດບັນທຶກຂໍ້ມູນລາຍຊື່ຜູ້ຕິດຕໍ່ຂອງທ່ານ ແລະ ແອັບທີ່ເປັນອັນຕະລາຍອາດສາມາດແບ່ງປັນຂໍ້ມູນລາຍຊື່ຜູ້ຕິດຕໍ່ໂດຍທີ່ທ່ານບໍ່ຮູ້ໄດ້."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"ອະນຸຍາດໃຫ້ແອັບຯ ອ່ານຂໍ້ມູນກ່ຽວກັບລາຍຊື່ຜູ່ຕິດຕໍ່ທີ່ເກັບໄວ້ໃນໂທລະສັບຂອງທ່ານ ຮວມເຖິງຄວາມຖີ່ການໂທ, ການສົ່ງສົ່ງອີເມວ ຫຼືການສື່ສານໃນຮູບແບບອື່ນກັບບຸກຄົນໃດນຶ່ງ. ການອະນຸຍາດເຮັດໃຫ້ແອັບຯ ສາມາດບັນທຶກຂໍ້ມູນລາຍຊື່ຜູ່ຕິດຕໍ່ຂອງທ່ານ ແລະແອັບຯທີ່ເປັນອັນຕະລາຍ ອາດເຜີຍແຜ່ຂໍ້ມູນຂອງທ່ານໂດຍທີ່ທ່ານບໍ່ໄດ້ຮັບຮູ້."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"ອະນຸຍາດໃຫ້ແອັບອ່ານຂໍ້ມູນກ່ຽວກັບລາຍຊື່ຜູ້ຕິດຕໍ່ທີ່ບັນທຶກໄວ້ຢູ່ແທັບເລັດຂອງທ່ານ. ນອກຈາກນັ້ນ, ແອັບຕ່າງໆຍັງມີສິດເຂົ້າເຖິງບັນຊີຢູ່ແທັບເລັດຂອງທ່ານທີ່ສ້າງລາຍຊື່ຜູ້ຕິດຕໍ່ໄດ້ນຳ. ນີ້ອາດຮວມເຖິງບັນຊີທີ່ສ້າງຂຶ້ນມາໂດຍແອັບທີ່ທ່ານຕິດຕັ້ງໄວ້ນຳ. ສິດອະນຸຍາດນີ້ຈະເຮັດໃຫ້ແອັບຕ່າງໆສາມາດບັນທຶກຂໍ້ມູນລາຍຊື່ຜູ້ຕິດຕໍ່ຂອງທ່ານ ແລະ ແອັບທີ່ເປັນອັນຕະລາຍອາດແບ່ງປັນຂໍ້ມູນລາຍຊື່ຜູ້ຕິດຕໍ່ໄດ້ໂດຍທີ່ທ່ານບໍ່ຮູ້ໄດ້."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"ອະນຸຍາດໃຫ້ແອັບອ່ານຂໍ້ມູນກ່ຽວກັບລາຍຊື່ຜູ້ຕິດຕໍ່ທີ່ຈັດເກັບໄວ້ຢູ່ອຸປະກອນ Android TV ຂອງທ່ານ. ນອກຈາກນັ້ນ, ແອັບຕ່າງໆຍັງມີສິດເຂົ້າເຖິງບັນຊີຢູ່ອຸປະກອນ Android TV ຂອງທ່ານທີ່ສ້າງລາຍຊື່ຜູ້ຕິດຕໍ່ໄດ້ນຳ. ນີ້ອາດຮວມເຖິງບັນຊີທີ່ສ້າງຂຶ້ນມາໂດຍແອັບທີ່ທ່ານຕິດຕັ້ງໄວ້ນຳ. ສິດອະນຸຍາດນີ້ຈະເຮັດໃຫ້ແອັບຕ່າງໆສາມາດບັນທຶກຂໍ້ມູນລາຍຊື່ຜູ້ຕິດຕໍ່ຂອງທ່ານ ແລະ ແອັບທີ່ເປັນອັນຕະລາຍອາດແບ່ງປັນຂໍ້ມູນລາຍຊື່ຜູ້ຕິດຕໍ່ໄດ້ໂດຍທີ່ທ່ານບໍ່ຮູ້ໄດ້."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"ອະນຸຍາດໃຫ້ແອັບອ່ານຂໍ້ມູນກ່ຽວກັບລາຍຊື່ຜູ້ຕິດຕໍ່ທີ່ບັນທຶກໄວ້ຢູ່ໂທລະສັບຂອງທ່ານ. ນອກຈາກນັ້ນ, ແອັບຕ່າງໆຍັງມີສິດເຂົ້າເຖິງບັນຊີຢູ່ໂທລະສັບຂອງທ່ານທີ່ສ້າງລາຍຊື່ຜູ້ຕິດຕໍ່ໄດ້ນຳ. ນີ້ອາດຮວມເຖິງບັນຊີທີ່ສ້າງຂຶ້ນມາໂດຍແອັບທີ່ທ່ານຕິດຕັ້ງໄວ້ນຳ. ສິດອະນຸຍາດນີ້ຈະເຮັດໃຫ້ແອັບຕ່າງໆສາມາດບັນທຶກຂໍ້ມູນລາຍຊື່ຜູ້ຕິດຕໍ່ຂອງທ່ານ ແລະ ແອັບທີ່ເປັນອັນຕະລາຍອາດແບ່ງປັນຂໍ້ມູນລາຍຊື່ຜູ້ຕິດຕໍ່ໄດ້ໂດຍທີ່ທ່ານບໍ່ຮູ້ໄດ້."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"ແກ້ໄຂລາຍຊື່ຜູ່ຕິດຕໍ່ຂອງທ່ານ"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"ອະນຸຍາດໃຫ້ແອັບຯ ແກ້ໄຂຂໍ້ມູນກ່ຽວກັບລາຍຊື່ຜູ່ຕິດຕໍ່ຂອງທ່ານທີ່ເກັບໄວ້ໃນແທັບເລັດ ຮວມທັງຄວາມຖີ່ໃນການໂທ, ການສົ່ງອີເມວ ຫຼືການສື່ສານໃນຮູບແບບອື່ນຂອງທ່ານກັບລາຍຊື່ຜູ່ຕິດຕໍ່ໃດນຶ່ງ. ການກຳນົດສິດນີ້ເຮັດໃຫ້ແອັບຯສາມາດລຶບຂໍ້ມູນລາຍຊື່ຜູ່ຕິດຕໍ່ໄດ້."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"ອະນຸຍາດໃຫ້ແອັບແກ້ໄຂຂໍ້ມູນກ່ຽວກັບລາຍຊື່ຕິດຕໍ່ຂອງທ່ານທີ່ບັນທຶກຢູ່ໃນອຸປະກອນ Android TV ທ່ານ, ຮວມທັງຄວາມຖີ່ ທີທ່ານໂທ, ອີເມວ ຫຼື ການສື່ ສານກັບລາຍຊື່ຕິດຕໍ່ສະເພາະໃນຮູບແບບອື່ນນຳ. ສິດອະນຸຍາດນີ້ຈະເຮັດໃຫ້ແອັບສາມາດລຶບຂໍ້ມູນລາຍຊື່ຕິດຕໍ່ໄດ້."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"ອະນຸຍາດໃຫ້ແອັບຯແກ້ໄຂຂໍ້ມູນກ່ຽວກັບລາຍຊື່ຜູ່ຕິດຕໍ່ ທີ່ບັນທຶກໃນໂທລະສັບຂອງທ່ານ ຮວມທັງຄວາມຖີ່ຂອງການໂທ, ການອີເມວ ຫຼືການຕິດຕໍ່ໃນຮູບແບບອື່ນກັບລາຍຊື່ຜູ່ຕິດຕໍ່ໃດນຶ່ງນຳ. ການອະນຸຍາດນີ້ຈະເຮັດໃຫ້ແອັບຯ ສາມາດລຶບຂໍ້ມູນລາຍຊື່ຜູ່ຕິດຕໍ່ໄດ້."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"ອະນຸຍາດໃຫ້ແອັບແກ້ໄຂຂໍ້ມູນກ່ຽວກັບລາຍຊື່ຜູ້ຕິດຕໍ່ທີ່ບັນທຶກໄວ້ຢູ່ແທັບເລັດຂອງທ່ານ. ສິດອະນຸຍາດນີ້ຈະເຮັດໃຫ້ແອັບສາມາດລຶບຂໍ້ມູນລາຍຊື່ຜູ້ຕິດຕໍ່ອອກໄດ້."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"ອະນຸຍາດໃຫ້ແອັບແກ້ໄຂຂໍ້ມູນກ່ຽວກັບລາຍຊື່ຕິດຕໍ່ຂອງທ່ານທີ່ບັນທຶກຢູ່ໃນອຸປະກອນ Android TV ທ່ານ. ສິດອະນຸຍາດນີ້ຈະເຮັດໃຫ້ແອັບສາມາດລຶບຂໍ້ມູນລາຍຊື່ຜູ້ຕິດຕໍ່ອອກໄດ້."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"ອະນຸຍາດໃຫ້ແອັບແກ້ໄຂຂໍ້ມູນກ່ຽວກັບລາຍຊື່ຜູ້ຕິດຕໍ່ທີ່ບັນທຶກໄວ້ຢູ່ໂທລະສັບຂອງທ່ານ. ສິດອະນຸຍາດນີ້ຈະເຮັດໃຫ້ແອັບສາມາດລຶບຂໍ້ມູນລາຍຊື່ຜູ້ຕິດຕໍ່ອອກໄດ້."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"ອ່ານບັນທຶກການໂທ"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"This app can read your call history."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"ຂຽນຂໍ້ມູນການໂທ"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"ເຂົ້າເຖິງຄຳສັ່ງຜູ່ໃຫ້ບໍລິການພິກັດສະຖານທີ່"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"ອະນຸຍາດ​ໃຫ້​ແອັບຯ​ເຂົ້າເຖິງ​ຄຳສັ່ງ​ເພີ່ມເຕີມ​ຂອງ​ຜູ່​ໃຫ້​ບໍລິການ​ສະຖານທີ່. ນີ້​ອາດ​ຈະ​ເປັນ​ການ​ເຮັດ​ໃຫ້​ແອັບຯ ລົບກວນ​ການ​ເຮັດ​ວຽກ​ຂອງ GPS ຫຼື​ແຫລ່ງ​ຂໍ້ມູນ​ສະຖານທີ່​ອື່ນໆ​ໄດ້."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"ເຂົ້າເຖິງສະຖານທີ່ແນ່ນອນໃນພື້ນໜ້າເທົ່ານັ້ນ"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"ແອັບນີ້ສາມາດຮັບເອົາສະຖານທີ່ແນ່ນອນຂອງທ່ານໄດ້ທຸກເວລາທີ່ມັນຢູ່ໃນພື້ນໜ້າ. ການບໍລິການສະຖານທີ່ເຫຼົ່ານີ້ຕ້ອງເປີດຢູ່ ແລະ ສາມາດໃຊ້ໄດ້ໃນໂທລະສັບຂອງທ່ານເພື່ອໃຫ້ແອັບສາມາດໃຊ້ພວກມັນໄດ້. ນີ້ອາດຈະເຮັດໃຫ້ການໃຊ້ແບັດເຕີຣີເພີ່ມຂຶ້ນ."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"ເຂົ້າເຖິງສະຖານທີ່ໂດຍປະມານ (ອ້າງອີງຈາກເຄືອຂ່າຍ) ສະເພາະໃນພື້ນໜ້າ"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"ແອັບນີ້ສາມາດເບິ່ງສະຖານທີ່ຂອງທ່ານໂດຍອ້າງອີງຈາກແຫລ່ງທີ່ມເຄືອຂ່າຍ ເຊັ່ນ: ເສົາສັນຍານໂທລະສັບ ແລະ ເຄືອຂ່າຍ Wi-Fi ໄດ້, ແຕ່ສະເພາະເມື່ອແອັບເຮັດວຽກໂດຍປາກົດຢູ່ໜ້າເທົ່ານັ້ນ. ບໍລິການສະຖານທີ່ເຫຼົ່ານີ້ຈະຕ້ອງຖືກເປີດໃຊ້ ແລະ ສາມາດໃຊ້ໄດ້ຢູ່ແທັບເລັດຂອງທ່ານ, ແອັບຈຶ່ງຈະສາມາດໃຊ້ພວກມັນໄດ້."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"ແອັບນີ້ສາມາດດຶງຂໍ້ມູນສະຖານທີ່ຂອງທ່ານໂດຍອ້າງອີງແຫລ່ງຂໍ້ມູນເຄືອຂ່າຍ ເຊັ່ນ: ເສົາສັນຍານໂທລະສັບມືຖື ແລະ ເຄືອຂ່າຍ Wi-Fi, ແຕ່ສະເພາະເມື່ອແອັບຢູ່ໃນພື້ນໜ້າເທົ່ານັ້ນ. ບໍລິການສະຖານທີ່ເຫຼົ່ານີ້ຈະຕ້ອງຖືກເປີດໃຊ້ກ່ອນ ແລະ ສາມາດໃຊ້ໄດ້ຢູ່ອຸປະກອນ Android TV ຂອງທ່ານເພື່ອໃຫ້ແອັບສາມາດໃຊ້ພວກມັນໄດ້."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"ແອັບນີ້ສາມາດເບິ່ງສະຖານທີ່ຂອງທ່ານໂດຍອ້າງອີງຈາກແຫລ່ງທີ່ມເຄືອຂ່າຍ ເຊັ່ນ: ເສົາສັນຍານໂທລະສັບ ແລະ ເຄືອຂ່າຍ Wi-Fi ໄດ້, ແຕ່ສະເພາະເມື່ອແອັບເຮັດວຽກໂດຍປາກົດຢູ່ໜ້າເທົ່ານັ້ນ. ບໍລິການສະຖານທີ່ເຫຼົ່ານີ້ຈະຕ້ອງຖືກເປີດໃຊ້ ແລະ ສາມາດໃຊ້ໄດ້ຢູ່ໂທລະສັບຂອງທ່ານ, ແອັບຈຶ່ງຈະສາມາດໃຊ້ພວກມັນໄດ້."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"ແອັບນີ້ສາມາດຮັບເອົາສະຖານທີ່ແນ່ນອນຂອງທ່ານໄດ້ທຸກເວລາທີ່ມັນຢູ່ໃນພື້ນໜ້າ. ການບໍລິການສະຖານທີ່ຕ້ອງເປີດຢູ່ ແລະ ສາມາດໃຊ້ໄດ້ໃນອຸປະກອນຂອງທ່ານເພື່ອໃຫ້ແອັບສາມາດໃຊ້ພວກມັນໄດ້. ນີ້ອາດຈະເຮັດໃຫ້ການໃຊ້ແບັດເຕີຣີເພີ່ມຂຶ້ນ."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"ເຂົ້າເຖິງສະຖານທີ່ໂດຍປະມານເມື່ອຢູ່ໃນພື້ນໜ້າເທົ່ານັ້ນ"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"ແອັບນີ້ສາມາດລະບຸສະຖານທີ່ໂດຍປະມານການຂອງທ່ານໄດ້ສະເພາະເມື່ອມັນຢູ່ໃນພື້ນຫຼັງເທົ່ານັ້ນ. ຈະຕ້ອງເປີດໃຊ້ບໍລິການສະຖານທີ່ ແລະ ໃຊ້ໄດ້ຢູ່ລົດຂອງທ່ານເພື່ອໃຫ້ແອັບສາມາດໃຊ້ພວກມັນໄດ້."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"ເຂົ້າເຖິງສະຖານທີ່ໃນພື້ນຫຼັງ"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"ຖ້າອະນຸຍາດສິ່ງນີ້ນອກຈາກການເຂົ້າເຖິງສະຖານທີ່ໂດຍປະມານ ຫຼື ທີ່ແນ່ນອນ ແອັບສາມາດເຂົ້າເຖິງສະຖານທີ່ໄດ້ໃນຂະນະທີ່ເປີດໃຊ້ໃນພື້ນຫຼັງ."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"ແອັບນີ້ສາມາດເຂົ້າເຖິງສະຖານທີ່ໃນເວລາເຮັດວຽກໃນພື້ນຫຼັງ, ນອກເໜືອໄປຈາກການເຂົ້າເຖິງສະຖານທີ່ໃນພື້ນໜ້າ."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"ປ່ຽນການຕັ້ງຄ່າສຽງຂອງທ່ານ"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"ອະນຸຍາດໃຫ້ແອັບຯແກ້ໄຂການຕັ້ງຄ່າສຽງສ່ວນກາງ ເຊັ່ນ: ລະດັບສຽງ ແລະລຳໂພງໃດທີ່ຖືກໃຊ້ສົ່ງສຽງອອກ."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"ບັນທຶກສຽງ"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"ອະນຸຍາດໃຫ້ແອັບຯເບິ່ງການຕັ້ງຄ່າຂອງ Bluetooth ໃນແທັບເລັດ ຕະຫຼອດຈົນເຊື່ອມຕໍ່ ແລະຍອມຮັບການເຊື່ອມຕໍ່ກັບອຸປະກອນທີ່ຈັບຄູ່ກັນແລ້ວ."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"ອະນຸຍາດໃຫ້ແອັບເບິ່ງການຕັ້ງຄ່າ Bluetooth ຢູ່ອຸປະກອນ Android TV ຂອງທ່ານ ແລະ ຕອບຮັບການເຊື່ອມຕໍ່ກັບອຸປະກອນທີ່ຈັບຄູ່ໄວ້."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"ອະນຸຍາດໃຫ້ແອັບຯເບິ່ງການຕັ້ງຄ່າຂອງ Bluetooth ໃນໂທລະສັບ, ຮວມທັງໃຫ້ສ້າງ ແລະຮັບການເຊື່ອມຕໍ່ຈາກອຸປະກອນທີ່ຈັບຄູ່ກັນ."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"ຂໍ້ມູນບໍລິການການຈ່າຍເງິນ NFC ທີ່ຕ້ອງການ"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"ອະນຸຍາດໃຫ້ແອັບຮັບຂໍ້ມູນບໍລິການການຈ່າຍເງິນ NFC ທີ່ຕ້ອງການໄດ້ ເຊັ່ນ: ການຊ່ວຍເຫຼືອແບບລົງທະບຽນ ແລະ ປາຍທາງເສັ້ນທາງ."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"ຄວບຄຸມ Near Field Communication"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"ອະນຸຍາດໃຫ້ແອັບຯຕິດຕໍ່ສື່ສານກັບປ້າຍກຳກັບ, ບັດ ແລະໂຕອ່ານຂອງການສື່ສານໄລຍະສັ້ນ (NFC)."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"ປິດການລັອກໜ້າຈໍ"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"Accessibility Shortcut turned <xliff:g id="SERVICE_NAME">%1$s</xliff:g> on"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"Accessibility Shortcut turned <xliff:g id="SERVICE_NAME">%1$s</xliff:g> off"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"ກົດປຸ່ມສຽງທັງສອງພ້ອມກັນຄ້າງໄວ້ສາມວິນາທີເພື່ອໃຊ້ <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"ເລືອກບໍລິການເພື່ອໃຊ້ເມື່ອທ່ານແຕະໃສ່ປຸ່ມການຊ່ວຍເຂົ້າເຖິງ:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"ເລືອກບໍລິການເພື່ອໃຊ້ກັບທ່າທາງການຊ່ວຍເຂົ້າເຖິງ (ປັດຂຶ້ນຈາກລຸ່ມສຸດຂອງໜ້າຈໍດ້ວຍສອງນິ້ວ):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"ເລືອກບໍລິການເພື່ອໃຊ້ກັບທ່າທາງການຊ່ວຍເຂົ້າເຖິງ (ປັດຂຶ້ນຈາກລຸ່ມສຸດຂອງໜ້າຈໍດ້ວຍສາມນິ້ວ):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"ເພື່ອສະຫຼັບລະຫວ່າງບໍລິການຕ່າງໆ, ໃຫ້ແຕະໃສ່ປຸ່ມການຊ່ວຍເຂົ້າເຖິງຄ້າງໄວ້."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"ເພື່ອສະຫຼັບລະຫວ່າງບໍລິການຕ່າງໆ, ໃຫ້ປັດຂຶ້ນດ້ວຍສອງນິ້ວຄ້າງໄວ້."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"ເພື່ອສະຫຼັບລະຫວ່າງບໍລິການຕ່າງໆ, ໃຫ້ປັດຂຶ້ນດ້ວຍສາມນິ້ວຄ້າງໄວ້."</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>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"ເຊື່ອມຕໍ່ກັບ <xliff:g id="PRODUCT_NAME">%1$s</xliff:g> ແລ້ວ"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"ແຕະເພື່ອເບິ່ງໄຟລ໌"</string>
<string name="pin_target" msgid="8036028973110156895">"ປັກໝຸດ"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"ປັກໝຸດ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"ຖອນປັກໝຸດ"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"ຖອດປັກມຸດ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"ຂໍ້ມູນແອັບ"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"ກຳລັງເລີ່ມເດໂມ…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"ອັບເດດລາຍການເຫຼົ່ານີ້ໃນ "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <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> ບໍ?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"ບັນທຶກ"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"ບໍ່, ຂອບໃຈ"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"ບໍ່ຟ້າວເທື່ອ"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"ຢ່າບັນທຶກ"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"ອັບເດດ"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"ສືບຕໍ່"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"​ລະ​ຫັດ​ຜ່ານ"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"ເປີດ/ປິດການແບ່ງໜ້າຈໍ"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"ໜ້າຈໍລັອກ"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"ຮູບໜ້າຈໍ"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"ແອັບ <xliff:g id="APP_NAME">%1$s</xliff:g> ໃນໜ້າຈໍປັອບອັບ."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"ແຖບຄຳບັນຍາຍຂອງ <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 1212aa44fa93..5a85f481e73b 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -192,8 +192,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Trūksta darbo profilio administratoriaus programos arba ji sugadinta. Todėl darbo profilis ir susiję duomenys buvo ištrinti. Jei reikia pagalbos, susisiekite su administratoriumi."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Darbo profilis nebepasiekiamas šiame įrenginyje"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Per daug slaptažodžio bandymų"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Administratorius atmetė prašymą įrenginį naudoti asmeniniais tikslais"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Įrenginys yra tvarkomas"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Šį įrenginį tvarko organizacija ir gali stebėti tinklo srautą. Palieskite, kad gautumėte daugiau informacijos."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Įrenginys bus ištrintas"</string>
@@ -387,13 +386,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Programai leidžiama siųsti užsifiksuojančias transliacijas, kurios išlieka pasibaigus transliacijai. Per dažnas jų naudojimas gali sulėtinti „Android TV“ įrenginio veikimą ar padaryti jį nestabilų verčiant naudoti per daug atminties."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Leidžiama programai siųsti užsifiksuojančias transliacijas, kurios išlieka pasibaigus transliacijai. Per dažnas jų naudojimas gali sulėtinti telefono veikimą ar padaryti jį nestabilų verčiant naudoti per daug atminties."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"skaityti kontaktus"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Leidžiama programai skaityti duomenis apie planšetiniame kompiuteryje saugomus kontaktus, įskaitant dažnį, kuriuo konkretiems asmenims skambinote, siuntėte el. laiškus ar bendravote kitais būdais. Šis leidimas suteikia teisę programoms saugoti kontaktinius duomenis, o kenkėjiškos programos gali bendrinti kontaktinius duomenis be jūsų žinios."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Programai leidžiama skaityti duomenis apie „Android TV“ įrenginyje saugomus kontaktus, įskaitant dažnį, kuriuo konkretiems asmenims skambinote, siuntėte el. laiškus ar bendravote kitais būdais. Šis leidimas suteikia teisę programoms saugoti kontaktinius duomenis, o kenkėjiškos programos gali bendrinti kontaktinius duomenis be jūsų žinios."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Leidžiama programai skaityti duomenis apie telefone saugomus kontaktus, įskaitant dažnį, kuriuo konkretiems asmenims skambinote, siuntėte el. laiškus ar bendravote kitais būdais. Šis leidimas suteikia teisę programoms saugoti kontaktinius duomenis, o kenkėjiškos programos gali bendrinti kontaktinius duomenis be jūsų žinios."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Programai leidžiama skaityti duomenis apie planšetiniame kompiuteryje saugomus kontaktus. Programos taip pat galės pasiekti planšetiniame kompiuteryje esančias paskyras, kuriose buvo sukurta kontaktų. Gali būti įtrauktos paskyros, kurias sukūrė jūsų įdiegtos programos. Šis leidimas suteikia teisę programoms saugoti kontaktinius duomenis, o kenkėjiškos programos gali bendrinti kontaktinius duomenis be jūsų žinios."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Programai leidžiama skaityti duomenis apie „Android TV“ įrenginyje saugomus kontaktus. Programos taip pat galės pasiekti „Android TV“ įrenginyje esančias paskyras, kuriose buvo sukurta kontaktų. Gali būti įtrauktos paskyros, kurias sukūrė jūsų įdiegtos programos. Šis leidimas suteikia teisę programoms saugoti kontaktinius duomenis, o kenkėjiškos programos gali bendrinti kontaktinius duomenis be jūsų žinios."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Programai leidžiama skaityti duomenis apie telefone saugomus kontaktus. Programos taip pat galės pasiekti telefone esančias paskyras, kuriose buvo sukurta kontaktų. Gali būti įtrauktos paskyros, kurias sukūrė jūsų įdiegtos programos. Šis leidimas suteikia teisę programoms saugoti kontaktinius duomenis, o kenkėjiškos programos gali bendrinti kontaktinius duomenis be jūsų žinios."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"keisti kontaktus"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Leidžiama programai keisti duomenis apie planšetiniame kompiuteryje saugomus kontaktus, įskaitant dažnį, kuriuo konkretiems asmenims skambinote, siuntėte el. laiškus ar bendravote kitais būdais. Šis leidimas suteikia teisę programoms ištrinti kontaktinius duomenis."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Leidžiama programai keisti duomenis apie „Android TV“ įrenginyje saugomus kontaktus, įskaitant dažnį, kuriuo konkretiems asmenims skambinote, siuntėte el. laiškus ar bendravote kitais būdais. Šis leidimas suteikia teisę programoms ištrinti kontaktinius duomenis."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Leidžiama programai keisti duomenis apie telefone saugomus kontaktus, įskaitant dažnį, kuriuo konkretiems asmenims skambinote, siuntėte el. laiškus ar bendravote kitais būdais. Šis leidimas suteikia teisę programoms ištrinti kontaktinius duomenis."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Programai leidžiama keisti duomenis apie planšetiniame kompiuteryje saugomus kontaktus. Su šiuo leidimu programos gali ištrinti kontaktinius duomenis."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Programai leidžiama keisti duomenis apie „Android TV“ įrenginyje saugomus kontaktus. Su šiuo leidimu programos gali ištrinti kontaktinius duomenis."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Programai leidžiama keisti duomenis apie telefone saugomus kontaktus. Su šiuo leidimu programos gali ištrinti kontaktinius duomenis."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"skaityti skambučių žurnalą"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Ši programa gali nuskaityti skambučių istoriją."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"rašyti skambučių žurnalą"</string>
@@ -413,13 +412,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"pasiekti papildomas vietos teikimo įrankio komandas"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Programai leidžiama pasiekti papildomas vietovės nustatymo paslaugų teikėjų komandas. Dėl to programa gali trukdyti veikti GPS ar kitiems vietovės nustatymo šaltiniams."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"pasiekti tikslią vietovę, tik kai programa veikia priekiniame plane"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Ši programa gali gauti tikslius jūsų vietovės duomenis bet kuriuo metu, kai veikia priekiniame plane. Šios vietovės paslaugos turi būti įjungtos ir pasiekiamos telefone, kad programa galėtų jas naudoti. Tai gali padidinti akumuliatoriaus energijos suvartojimą."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"pasiekti apytikslę vietovę (pagal tinklo duomenis), tik kai programa veikia priekiniame plane"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Ši programa gali gauti jūsų vietos informaciją naudodamasi tinklo šaltinių, pvz., mobiliojo ryšio bokštų ir „Wi-Fi“ tinklų, duomenimis, bet tik kai ji yra naudojama priekiniame plane. Šios vietovės paslaugos turi būti įjungtos ir pasiekiamos planšetiniame kompiuteryje, kad programa galėtų jas naudoti."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Ši programa gali gauti jūsų vietos informaciją naudodamasi tinklo šaltinių, pvz., mobiliojo ryšio bokštų ir „Wi-Fi“ tinklų, duomenimis, bet tik kai ji yra naudojama priekiniame plane. Šios vietovės paslaugos turi būti įjungtos ir pasiekiamos „Android TV“ įrenginyje, kad programa galėtų jas naudoti."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Ši programa gali gauti jūsų vietos informaciją naudodamasi tinklo šaltinių, pvz., mobiliojo ryšio bokštų ir „Wi-Fi“ tinklų, duomenimis, bet tik kai ji yra naudojama priekiniame plane. Šios vietovės paslaugos turi būti įjungtos ir pasiekiamos telefone, kad programa galėtų jas naudoti."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Ši programa gali gauti tikslius jūsų vietovės duomenis, tik kai veikia priekiniame plane. Vietovės paslaugos turi būti įjungtos ir pasiekiamos įrenginyje, kad programa galėtų jas naudoti. Dėl to akumuliatoriui gali reikėti daugiau energijos."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"pasiekti apytikslę vietovę, tik kai programa veikia priekiniame plane"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Ši programa gali gauti apytikslius jūsų vietovės duomenis, tik kai veikia priekiniame plane. Vietovės paslaugos turi būti įjungtos ir pasiekiamos įrenginyje, kad programa galėtų jas naudoti."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"prieiga prie vietovės fone"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Jei papildomai suteikiama prieiga prie apytikslės arba tikslios vietovės, programa gali pasiekti vietovės duomenis veikdama fone."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Ši programa gali pasiekti vietovę, kai veikia fone ar priekiniame plane."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"keisti garso nustatymus"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Leidžiama programai keisti visuotinius garso nustatymus, pvz., garsumą ir tai, kuris garsiakalbis naudojamas išvesčiai."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"įrašyti garsą"</string>
@@ -500,6 +497,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Leidžiama programai peržiūrėti „Bluetooth“ konfigūraciją planšetiniame kompiuteryje ir užmegzti bei priimti ryšius iš susietų įrenginių."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Programai leidžiama peržiūrėti „Bluetooth“ konfigūraciją „Android TV“ įrenginyje ir užmegzti bei priimti ryšius iš susietų įrenginių."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Leidžiama programai peržiūrėti „Bluetooth“ konfigūraciją telefone ir užmegzti bei priimti ryšius iš susietų įrenginių."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Pageidaujama ARL mokėjimo paslaugos informacija"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Programai leidžiama gauti pageidaujamą ARL mokamos paslaugos informaciją, pvz., užregistruotą pagalbą ir maršrutų tikslus."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"valdyti artimo lauko perdavimą (angl. „Near Field Communication“)"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Leidžiama programai perduoti artimojo lauko ryšių technologijos (ALR) žymas, korteles ir skaitymo programas."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"išjungti ekrano užraktą"</string>
@@ -1662,12 +1661,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"Pritaikymo neįgaliesiems sparčiuoju klavišu buvo įjungta „<xliff:g id="SERVICE_NAME">%1$s</xliff:g>“"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"Pritaikymo neįgaliesiems sparčiuoju klavišu buvo išjungta „<xliff:g id="SERVICE_NAME">%1$s</xliff:g>“"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Jei norite naudoti „<xliff:g id="SERVICE_NAME">%1$s</xliff:g>“, paspauskite abu garsumo klavišus ir palaikykite tris sekundes"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Pasirinkite paslaugą, kuri bus naudojama, kai paliesite pritaikomumo mygtuką:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Pasirinkite paslaugą, kuri bus naudojama su pritaikomumo gestu (perbraukimas aukštyn dviem pirštais iš ekrano apačios):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Pasirinkite paslaugą, kuri bus naudojama su pritaikomumo gestu (perbraukimas aukštyn trimis pirštais iš ekrano apačios):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Norėdami perjungti paslaugas, palieskite ir palaikykite pritaikomumo mygtuką."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Norėdami perjungti paslaugas, perbraukite aukštyn dviem pirštais ir palaikykite."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Norėdami perjungti paslaugas, perbraukite aukštyn trimis pirštais ir palaikykite."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Didinimas"</string>
<string name="user_switched" msgid="7249833311585228097">"Dabartinis naudotojas: <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="1912993630661332336">"Perjungiama į <xliff:g id="NAME">%1$s</xliff:g>…"</string>
@@ -1926,7 +1919,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Prisijungta prie „<xliff:g id="PRODUCT_NAME">%1$s</xliff:g>“"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Palieskite, kad peržiūrėtumėte failus"</string>
<string name="pin_target" msgid="8036028973110156895">"Prisegti"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"PIN kodas <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Atsegti"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Atsegti <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Programos informacija"</string>
<string name="negative_duration" msgid="1938335096972945232">"–<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Paleidžiama demonstracinė versija…"</string>
@@ -1971,6 +1966,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Atnaujinti šiuos elementus paslaugoje "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ir <xliff:g id="TYPE_2">%3$s</xliff:g> ?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Išsaugoti"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Ne, ačiū"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Ne dabar"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Niekada"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Atnaujinti"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Tęsti"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"slaptažodį"</string>
@@ -2068,5 +2065,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Perjungti išskaidyto ekrano režimą"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Užrakinimo ekranas"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Ekrano kopija"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"Programa „<xliff:g id="APP_NAME">%1$s</xliff:g>“ iššokančiajame lange."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Programos „<xliff:g id="APP_NAME">%1$s</xliff:g>“ antraštės juosta."</string>
</resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 547b6c9bfbe3..17c0c17a7769 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -190,8 +190,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Trūkst darba profila administratora lietotnes, vai šī lietotne ir bojāta. Šī iemesla dēļ jūsu darba profils un saistītie dati tika dzēsti. Lai saņemtu palīdzību, sazinieties ar administratoru."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Jūsu darba profils šai ierīcē vairs nav pieejams."</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Veikts pārāk daudz paroles ievadīšanas mēģinājumu."</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Administrators atteicās no tādas ierīces pārvaldības, ko var izmantot personiskām vajadzībām"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Ierīce tiek pārvaldīta"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Jūsu organizācija pārvalda šo ierīci un var uzraudzīt tīkla datplūsmu. Pieskarieties, lai saņemtu detalizētu informāciju."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Jūsu ierīces dati tiks dzēsti"</string>
@@ -384,13 +383,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Ļauj lietotnei sūtīt piesaistošas apraides, kas tiek saglabātas pēc apraides pabeigšanas. Pārmērīga izmantošana var palēnināt Android TV ierīces darbību vai padarīt tās darbību nestabilu, liekot izmantot pārāk daudz atmiņas."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Ļauj lietotnei sūtīt piesaistošas apraides, kas tiek saglabātas pēc apraides pabeigšanas. Pārmērīga izmantošana var palēnināt tālruņa darbību vai padarīt tā darbību nestabilu, liekot izmantot pārāk daudz atmiņas."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"lasīt kontaktpersonu informāciju"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Ļauj lietotnei lasīt datus par jūsu planšetdatorā saglabātajām kontaktpersonām, tostarp to, cik bieži esat zvanījis, sazinājies pa e-pastu vai citādi sazinājies ar konkrētām personām. Ar šo atļauju lietotnes var saglabāt jūsu kontaktpersonu datus, un ļaunprātīgas lietotnes var kopīgot kontaktpersonu datus bez jūsu atļaujas."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Ļauj lietotnei lasīt datus par Android TV ierīcē glabātajām kontaktpersonām, tostarp par zvanu un e-pasta ziņojumu apjomu vai saziņu citos veidos, kas veikta ar konkrētām kontaktpersonām. Ar šo atļauju lietotnes var saglabāt jūsu kontaktpersonu datus, un ļaunprātīgas lietotnes var kopīgot kontaktpersonu datus, jums nezinot."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Ļauj lietotnei lasīt datus par jūsu tālrunī saglabātajām kontaktpersonām, tostarp to, cik bieži esat zvanījis, sazinājies pa e-pastu vai citādi sazinājies ar konkrētām personām. Ar šo atļauju lietotnes var saglabāt jūsu kontaktpersonu datus, un ļaunprātīgas lietotnes var kopīgot kontaktpersonu datus bez jūsu atļaujas."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Ļauj lietotnei lasīt datus par planšetdatorā glabātajām kontaktpersonām. Lietotnēm būs arī piekļuve kontiem jūsu planšetdatorā, kuros ir izveidotas kontaktpersonas. Tas var ietvert kontus, ko izveidojušas jūsu instalētās lietotnes. Ar šo atļauju lietotnes var saglabāt jūsu kontaktpersonu datus, savukārt ļaunprātīgas lietotnes var kopīgot kontaktpersonu datus, jums nezinot."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Ļauj lietotnei lasīt datus par Android TV ierīcē glabātajām kontaktpersonām. Lietotnēm būs arī piekļuve kontiem jūsu Android TV ierīcē, kuros ir izveidotas kontaktpersonas. Tas var ietvert kontus, ko izveidojušas jūsu instalētās lietotnes. Ar šo atļauju lietotnes var saglabāt jūsu kontaktpersonu datus, savukārt ļaunprātīgas lietotnes var kopīgot kontaktpersonu datus, jums nezinot."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Ļauj lietotnei lasīt datus par tālrunī glabātajām kontaktpersonām. Lietotnēm būs arī piekļuve kontiem jūsu tālrunī, kuros ir izveidotas kontaktpersonas. Tas var ietvert kontus, ko izveidojušas jūsu instalētās lietotnes. Ar šo atļauju lietotnes var saglabāt jūsu kontaktpersonu datus, savukārt ļaunprātīgas lietotnes var kopīgot kontaktpersonu datus, jums nezinot."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"mainīt kontaktpersonu informāciju"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Ļauj lietotnei mainīt datus par planšetdatorā saglabātajām kontaktpersonām, tostarp par zvanu un e-pasta ziņojumu apjomu vai saziņu citos veidos, kas veikta ar konkrētām kontaktpersonām. Ar šo atļauju lietotne var dzēst kontaktpersonu datus."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Ļauj lietotnei mainīt datus par Android TV ierīcē saglabātajām kontaktpersonām, tostarp par zvanu un e-pasta ziņojumu apjomu vai saziņu citos veidos, kas veikta ar konkrētām kontaktpersonām. Ar šo atļauju lietotnes var dzēst kontaktpersonu datus."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Ļauj lietotnei mainīt datus par tālrunī saglabātajām kontaktpersonām, tostarp par zvanu un e-pasta ziņojumu apjomu vai saziņu citos veidos, kas veikta ar konkrētām kontaktpersonām. Ar šo atļauju lietotne var dzēst kontaktpersonu datus."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Ļauj lietotnei mainīt datus par planšetdatorā glabātajām kontaktpersonām. Ar šo atļauju lietotnes var dzēst kontaktpersonu datus."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Ļauj lietotnei mainīt datus par Android TV ierīcē glabātajām kontaktpersonām. Ar šo atļauju lietotnes var dzēst kontaktpersonu datus."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Ļauj lietotnei mainīt datus par tālrunī glabātajām kontaktpersonām. Ar šo atļauju lietotnes var dzēst kontaktpersonu datus."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"nolasīt zvanu žurnālu"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Šī lietotne var lasīt jūsu zvanu vēsturi."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"rakstīt zvanu žurnālā"</string>
@@ -410,13 +409,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"piekļūt atrašanās vietas nodrošinātāja papildu komandām"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Ļauj lietotnei piekļūt papildu atrašanās vietas noteikšanas nodrošinātāju komandām. Tas var ļaut lietotnei traucēt GPS vai citu atrašanās vietas noteikšanas avotu darbību."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"piekļuve precīzai atrašanās vietai, tikai darbojoties priekšplānā"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Šī lietotne var iegūt precīzu jūsu atrašanās vietu, tikai darbojoties priekšplānā. Šiem atrašanās vietu pakalpojumiem ir jābūt ieslēgtiem un pieejamiem jūsu tālrunī, lai lietotne varētu tos izmantot. Tādējādi var palielināties akumulatora jaudas patēriņš."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"piekļuve aptuvenai atrašanās vietai (pēc tīkla datiem), tikai darbojoties priekšplānā"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Kad šī lietotne darbojas priekšplānā, tā var noteikt jūsu atrašanās vietu, izmantojot tīkla resursus, piemēram, mobilo sakaru torņus un Wi-Fi tīklus. Šiem atrašanās vietu pakalpojumiem ir jābūt ieslēgtiem un pieejamiem jūsu planšetdatorā, lai lietotne varētu tos izmantot."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Kad šī lietotne darbojas priekšplānā, tā var noteikt jūsu atrašanās vietu, izmantojot tīkla resursus, piemēram, mobilo sakaru torņus un Wi-Fi tīklus. Šiem atrašanās vietu pakalpojumiem ir jābūt ieslēgtiem un pieejamiem jūsu Android TV ierīcē, lai lietotne varētu tos izmantot."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Kad šī lietotne darbojas priekšplānā, tā var noteikt jūsu atrašanās vietu, izmantojot tīkla resursus, piemēram, mobilo sakaru torņus un Wi-Fi tīklus. Šiem atrašanās vietu pakalpojumiem ir jābūt ieslēgtiem un pieejamiem jūsu tālrunī, lai lietotne varētu tos izmantot."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Šī lietotne var iegūt precīzu jūsu atrašanās vietu, tikai darbojoties priekšplānā. Jūsu ierīcē ir jābūt ieslēgtiem un pieejamiem atrašanās vietu pakalpojumiem, lai lietotne varētu tos izmantot. Tādējādi var palielināties akumulatora jaudas patēriņš."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"piekļuve aptuvenai atrašanās vietai, tikai darbojoties priekšplānā"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Šī lietotne var iegūt aptuvenu jūsu atrašanās vietu, tikai darbojoties priekšplānā. Jūsu ierīcē ir jābūt ieslēgtiem un pieejamiem atrašanās vietu pakalpojumiem, lai lietotne varētu tos izmantot."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"piekļūt atrašanās vietai fonā"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Ja šī atļauja tiek piešķirta līdz ar piekļuvi aptuvenai vai precīzai atrašanās vietai, lietotne var piekļūt atrašanās vietai, darbojoties fonā."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Šī lietotne var piekļūt atrašanās vietas datiem, darbojoties ne tikai priekšplānā, bet arī fonā."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"mainīt audio iestatījumus"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Ļauj lietotnei mainīt globālos audio iestatījumus, piemēram, skaļumu un izejai izmantoto skaļruni."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"ierakstīt audio"</string>
@@ -497,6 +494,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Ļauj lietotnei skatīt Bluetooth konfigurāciju planšetdatorā, kā arī veidot un pieņemt savienojumus ar pārī savienotām ierīcēm."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Ļauj lietotnei skatīt Bluetooth konfigurāciju Android TV ierīcē, kā arī veidot un pieņemt savienojumus ar pārī savienotām ierīcēm."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Ļauj lietotnei skatīt Bluetooth konfigurāciju tālrunī, kā arī veidot un pieņemt savienojumus ar pārī savienotām ierīcēm."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Informācija par vēlamo NFC maksājumu pakalpojumu"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Ļauj lietotnei iegūt informāciju par vēlamo NFC maksājumu pakalpojumu, piemēram, par reģistrētajiem lietojumprogrammu ID un maršruta galamērķi."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"kontrolē tuvlauka saziņu"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Ļauj lietotnei sazināties ar tuva darbības lauka sakaru (Near Field Communication — NFC) atzīmēm, kartēm un lasītājiem."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"atspējot ekrāna bloķēšanu"</string>
@@ -1640,12 +1639,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"Pieejamības saīsne aktivizēja lietotni <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"Pieejamības saīsne deaktivizēja lietotni <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Lai izmantotu pakalpojumu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, nospiediet abus skaļuma taustiņus un turiet tos trīs sekundes."</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Izvēlieties pakalpojumu, ko izmantot, kad pieskaraties pieejamības pogai."</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Izvēlieties pakalpojumu, ko izmantot ar pieejamības žestu (vilkšana ar diviem pirkstiem augšup no ekrāna apakšdaļas)."</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Izvēlieties pakalpojumu, ko izmantot ar pieejamības žestu (vilkšana ar trīs pirkstiem augšup no ekrāna apakšdaļas)."</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Lai pārslēgtu pakalpojumus, pieskarieties pieejamības pogai un turiet to."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Lai pārslēgtu pakalpojumus, velciet ar diviem pirkstiem augšup un turiet."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Lai pārslēgtu pakalpojumus, velciet ar trīs pirkstiem augšup un turiet."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Palielinājums"</string>
<string name="user_switched" msgid="7249833311585228097">"Pašreizējais lietotājs: <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="1912993630661332336">"Notiek pāriešana uz: <xliff:g id="NAME">%1$s</xliff:g>"</string>
@@ -1894,7 +1887,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Izveidots savienojums ar: <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Pieskarieties, lai skatītu failus."</string>
<string name="pin_target" msgid="8036028973110156895">"Piespraust"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Piespraust lietotni <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Atspraust"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Atspraust lietotni <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Lietotnes informācija"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Notiek demonstrācijas palaišana..."</string>
@@ -1938,6 +1933,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Vai atjaunināt šos vienumus pakalpojumā "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> un <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Saglabāt"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Nē, paldies"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Vēlāk"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Nekad"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Atjaunināt"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Turpināt"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"paroli"</string>
@@ -2034,5 +2031,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Pārslēgt ekrāna sadalīšanu"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Bloķēt ekrānu"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Ekrānuzņēmums"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"Lietotne <xliff:g id="APP_NAME">%1$s</xliff:g> uznirstošajā logā."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Lietotnes <xliff:g id="APP_NAME">%1$s</xliff:g> subtitru josla."</string>
</resources>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 93f2da11e7bb..2898129efd8c 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Апликацијата на администраторот за работниот профил или исчезна или е оштетена. Како резултат на тоа, вашиот работен профил и поврзаните податоци ќе се избришат. За помош, контактирајте со администраторот."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Вашиот работен профил веќе не е достапен на уредов"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Премногу обиди за внесување лозинка"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Уред откажан од администраторот за лична употреба"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Некој управува со уредот"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Вашата организација управува со уредов и можно е да го следи сообраќајот на мрежата. Допрете за детали."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Уредот ќе се избрише"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Дозволува апликацијата да испраќа лепливи емитувања, што остануваат по завршување на емитувањето. Прекумерното користење може да го направи вашиот уред Android TV бавен или нестабилен, така што ќе предизвика користење премногу меморија."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Овозможува апликацијата да испраќа лепливи емитувања, кои остануваат по завршувањето на емитувањето. Прекумерна употреба може да предизвика телефонот да биде бавен или нестабилен со тоа што предизвикува да користи премногу меморија."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"прочитај контакти"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Овозможува апликацијата да чита податоци за контактите зачувани на вашиот таблет, вклучувајќи ја и фреквенцијата со која сте повикувале, сте праќале е-пошта или сте комуницирале на други начини со конкретни поединци. Оваа дозвола овозможува апликациите да ги зачуваат вашите податоци за контакт и злонамерните апликации може да споделат податоци за контакт без ваше знаење."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Дозволува апликацијата да чита податоци за вашите контакти кои се складирани во вашиот уред Android TV, вклучувајќи ја зачестеноста со која сте повикувале, сте испраќале е-пораки или сте комуницирале на друг начин со конкретни поединци. Оваа дозвола овозможува апликациите да ги зачувуваат вашите податоци на контактите, а злонамерните апликации можат да ги споделуваат податоците на контактите без ваше знаење."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Овозможува апликацијата да чита податоци за контактите зачувани во вашиот телефон, вклучувајќи ја и фреквенцијата со која сте повикувале, сте праќале е-пошта или сте комуницирале на други начини со конкретни поединци. Оваа дозвола овозможува апликациите да ги зачуваат вашите податоци за контакт и злонамерните апликации може да споделат податоци за контакт без ваше знаење."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Овозможува апликацијата да чита податоци за контактите складирани во вашиот таблет. Апликациите ќе имаат пристап и до сметките на вашиот таблет што создале контакти. Тука може да спаѓаат сметките создадени од апликациите што сте ги инсталирале. Оваа дозвола им овозможува на апликациите да ги зачувуваат податоците за вашите контакти, а злонамерните апликации може да споделуваат податоци за контактите без ваше знаење."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Овозможува апликацијата да чита податоци за контактите складирани во вашиот уред со Android TV. Апликациите ќе имаат пристап и до сметките на вашиот уред со Android TV што создале контакти. Тука може да спаѓаат сметките создадени од апликациите што сте ги инсталирале. Оваа дозвола им овозможува на апликациите да ги зачувуваат податоците за вашите контакти, а злонамерните апликации може да споделуваат податоци за контактите без ваше знаење."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Овозможува апликацијата да чита податоци за контактите складирани во вашиот телефон. Апликациите ќе имаат пристап и до сметките на вашиот телефон што создале контакти. Тука може да спаѓаат сметките создадени од апликациите што сте ги инсталирале. Оваа дозвола им овозможува на апликациите да ги зачувуваат податоците за вашите контакти, а злонамерните апликации може да споделуваат податоци за контактите без ваше знаење."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"измени ги своите контакти"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Овозможува апликацијата да менува податоци за контактите зачувани во вашиот таблет, вклучувајќи ја и колку често сте повикувале, сте праќале е-пошта или сте комуницирале на други начини со конкретни контакти. Оваа дозвола овозможува апликациите да бришат податоци за контакти."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Дозволува апликацијата да чита податоци за вашите контакти кои се складирани во вашиот уред Android TV, вклучувајќи ја зачестеноста со која сте повикувале, испраќале е-пораки или комуницирале на друг начин со конкретни контакти. Оваа дозвола овозможува апликациите да бришат податоци на контактите."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Овозможува апликацијата да менува податоци за контактите зачувани во вашиот телефон, вклучувајќи и колку често сте повикувале, сте праќале е-пошта или сте комуницирале на други начини со конкретни контакти. Оваа дозвола овозможува апликациите да бришат податоци за контакти."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Овозможува апликацијата да менува податоци за контактите складирани во вашиот таблет. Оваа дозвола им овозможува на апликациите да бришат податоци за контактите."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Овозможува апликацијата да менува податоци за контактите складирани во вашиот уред со Android TV. Оваа дозвола им овозможува на апликациите да бришат податоци за контактите."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Овозможува апликацијата да менува податоци за контактите складирани во вашиот телефон. Оваа дозвола им овозможува на апликациите да бришат податоци за контактите."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"прочитај дневник на повици"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Апликацијава може да ја чита историјата на повиците."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"напиши дневник на повици"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"пристапи кон наредби на давателот на дополнителна локација"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Овозможува апликацијата да пристапи кон дополнителни наредби на давател на локација. Ова може да овозможи апликацијата да го попечи функционирањето на GPS или други извори на локација."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"пристап до прецизната локација само во преден план"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Апликацијава може да ја добие вашата точна локација само кога е во преден план. Услугиве според локација мора да се вклучени и достапни на телефонот за да може да ги користи апликацијата. Ова може да го зголеми трошењето на батеријата."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"пристап до приближна локација (според мрежа) само во преден план"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Апликацијава може да ја добие вашата локација од мрежните извори како што се репетиторите за мобилни мрежи и Wi-Fi мрежите, но само кога апликацијата е во преде план. Овие услуги за локација мора да се вклучени и достапни на таблетот за да може да ги користи апликацијата."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Апликацијава може да ја добие вашата локација од мрежните извори како што се репетиторите за мобилни мрежи и Wi-Fi мрежите, но само кога апликацијата е во преден план. Овие услуги според локација мора да се вклучени и достапни на уредот Android TV за да може да ги користи апликацијата."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Апликацијава може да ја добие вашата локација од мрежните извори како што се репетиторите за мобилни мрежи и Wi-Fi мрежите, но само кога апликацијата е во преде план. Овие услуги за локација мора да се вклучени и достапни на телефонот за да може да ги користи апликацијата."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Апликацијава може да ја добие вашата точна локација само кога е во преден план. Услугите според локација мора да се вклучени и достапни на уредот за да може да ги користи апликацијата. Ова може да го зголеми трошењето на батеријата."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"пристап до приближната локација само во преден план"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Апликацијава може да ја добие вашата приближна локација само кога е во преден план. Услугите според локација мора да се вклучени и достапни на уредот за да може да ги користи апликацијата."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"пристап до локацијата во заднина"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Ако покрај дозволата за пристап до приближната или прецизната локација е доделена и оваа дозвола, тогаш апликацијата ќе може да пристапува до локацијата додека се извршува во заднина."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Оваа апликација, покрај тоа што може да пристапува до локацијата кога е во преден план, има пристап и кога се извршува во заднина."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"менува аудио поставки"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Овозможува апликацијата да ги менува глобалните аудио поставки, како што се јачината на звукот и кој звучник се користи за излез."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"снимај аудио"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Овозможува апликацијата да ја види конфигурацијата на Bluetooth на таблетот и да прави и да прифаќа врски со спарени уреди."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Дозволува апликацијата да ја прикажува конфигурацијата на Bluetooth на вашиот уред Android TV и да прави и прифаќа врски со спарените уреди."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Овозможува апликацијата да ја види конфигурацијата на Bluetooth на телефонот и да прави и да прифаќа врски со спарени уреди."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Информации за претпочитаната услуга за плаќање преку NFC"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Дозволува апликацијата да добие информации за претпочитаната услуга за плаќање преку NFC, како регистрирани помагала и дестинација на маршрутата."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"контролирај комуникација на блиско поле"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Дозволува апликацијата да комуницира со ознаки, картички и читачи за Комуникација при непосредна близина (NFC)."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"оневозможи заклучување на екран"</string>
@@ -1620,12 +1619,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"Кратенката за пристапност ја вклучи <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"Кратенката за пристапност ја исклучи <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>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Изберете ја услугата што ќе ја користите кога ќе го допрете копчето за пристапност:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Изберете ја услугата што ќе ја користите со движењето за пристапност (повлекување нагоре од дното на екранот со два прста):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Изберете ја услугата што ќе ја користите со движењето за пристапност (повлекување нагоре од дното на екранот со три прста):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"За да се префрлате помеѓу услуги, допрете и задржете го копчето за пристапност."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"За да се префрлате помеѓу услуги, лизгајте нагоре со два прста и задржете."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"За да се префрлате помеѓу услуги, лизгајте нагоре со три прста и задржете."</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>
@@ -1864,7 +1857,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Поврзан на <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Допрете за да ги погледнете датотеките"</string>
<string name="pin_target" msgid="8036028973110156895">"Прикачете"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Прикачи <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Откачете"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Откачи <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Информации за апликација"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Се вклучува демонстрацијата…"</string>
@@ -1907,6 +1902,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Да се ажурираат овие ставки во "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <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>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Зачувај"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Не, фала"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Не сега"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Никогаш"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Ажурирај"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Продолжи"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"лозинка"</string>
@@ -2002,5 +1999,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Вклучи/исклучи поделен екран"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Заклучен екран"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Слика од екранот"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"Апликацијата <xliff:g id="APP_NAME">%1$s</xliff:g> во скокачки прозорец."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Насловна лента на <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index c220cddd9f07..1abf88d03c20 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"ഔദ്യോഗിക പ്രൊഫൈൽ അഡ്‌മിൻ ആപ്പ് വിട്ടുപോയിരിക്കുന്നു അല്ലെങ്കിൽ കേടായിരിക്കുന്നു. ഫലമായി, നിങ്ങളുടെ ഔദ്യോഗിക പ്രൊഫൈലും ബന്ധപ്പെട്ട വിവരങ്ങളും ഇല്ലാതാക്കിയിരിക്കുന്നു. സഹായത്തിന് അഡ്‌മിനെ ബന്ധപ്പെടുക."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"ഈ ഉപകരണത്തിൽ തുടർന്നങ്ങോട്ട് നിങ്ങളുടെ ഔദ്യോഗിക പ്രൊഫൈൽ ലഭ്യമല്ല"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"വളരെയധികം പാസ്‌വേഡ് ശ്രമങ്ങൾ"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"വ്യക്തിപരമായ ഉപയോഗത്തിനായി, ഉപകരണത്തിന്റെ ഔദ്യോഗിക ഉപയോഗം അഡ്‌മിൻ അവസാനിപ്പിച്ചു"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"ഉപകരണം മാനേജുചെയ്യുന്നുണ്ട്"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"നിങ്ങളുടെ സ്ഥാപനമാണ് ഈ ഉപകരണം മാനേജുചെയ്യുന്നത്, നെറ്റ്‌വർക്ക് ട്രാഫിക്ക് നിരീക്ഷിക്കുകയും ചെയ്തേക്കാം, വിശദാംശങ്ങൾ അറിയാൻ ടാപ്പുചെയ്യുക."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"നിങ്ങളുടെ ഉപകരണം മായ്‌ക്കും"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"പ്രക്ഷേപണം അവസാനിച്ച ശേഷവും അവശേഷിക്കുന്ന സ്‌റ്റിക്കി പ്രക്ഷേപണങ്ങൾ അയയ്‌ക്കാൻ ആപ്പിനെ അനുവദിക്കുന്നു. Android ടിവിയുടെ അമിതമായ ഉപയോഗം ഒരുപാട് മെമ്മറി ഉപയോഗിക്കാൻ കാരണമാകുകയും ടിവിയുടെ വേഗത കുറയ്‌ക്കുകയോ അതിനെ അസ്ഥിരമാക്കുകയോ ചെയ്‌തേക്കാം."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"സ്റ്റിക്കി പ്രക്ഷേപണങ്ങൾ അയയ്‌ക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു, പ്രക്ഷേപണം അവസാനിച്ചതിനുശേഷവും അത് നിലനിൽക്കുന്നു. അമിതോപയോഗം വളരെയധികം മെമ്മറി ഉപയോഗിക്കുന്നതിനാൽ, അത് ഫോണിന്റെ പ്രവർത്തനത്തെ മന്ദഗതിയിലാക്കുകയോ അസ്ഥിരമാക്കുകയോ ചെയ്യാം."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"നിങ്ങളുടെ കോൺടാക്റ്റുകൾ റീഡുചെയ്യുക"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"നിശ്ചിത ആളുകളെ മറ്റ് മാർഗങ്ങളിൽ നിങ്ങൾ എത്ര തവണ വിളിച്ചിട്ടുണ്ടെന്നതോ അവർക്ക് ഇമെയിൽ ചെയ്‌തിട്ടുണ്ടെന്നതോ ആശയവിനിമയം നടത്തിയിട്ടുണ്ടെന്നതോ ഉൾപ്പെടെ, നിങ്ങളുടെ ടാബ്‌ലെറ്റിൽ സംഭരിച്ചിരിക്കുന്ന നിങ്ങളുടെ കോൺടാക്റ്റുകളെക്കുറിച്ചുള്ള ഡാറ്റ റീഡുചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. നിങ്ങളുടെ കോൺടാക്റ്റ് ഡാറ്റ സംരക്ഷിക്കാൻ ഈ അനുമതി അപ്ലിക്കേഷനുകളെ അനുവദിക്കുന്നു, ക്ഷുദ്രകരമായ അപ്ലിക്കേഷനുകൾ നിങ്ങളുടെ അറിവില്ലാതെ കോൺടാക്റ്റ് ഡാറ്റ പങ്കിടാനിടയുണ്ട്."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"നിർദ്ദിഷ്‌ട വ്യക്തികളെ നിങ്ങൾ എത്ര തവണ വിളിച്ചിട്ടുണ്ടെന്നും അവർക്ക് ഇമെയിൽ അയച്ചിട്ടുണ്ടെന്നും മറ്റ് മാർഗങ്ങളിലൂടെ അവരുമായി എത്ര തവണ ആശയവിനിമയം നടത്തിയിട്ടുണ്ടെന്നും ഉൾപ്പെടെ നിങ്ങളുടെ Android ടിവിയിൽ സംഭരിച്ചിരിക്കുന്ന കോൺടാക്‌റ്റുകളെക്കുറിച്ചുള്ള ഡാറ്റ പരിഷ്‌ക്കരിക്കാൻ ആപ്പിനെ അനുവദിക്കുന്നു. ഈ അനുമതി നിങ്ങളുടെ കോൺടാക്‌റ്റ് ഡാറ്റ സംരക്ഷിക്കാൻ ആപ്പുകളെ അനുവദിക്കുന്നു, നിങ്ങളുടെ അറിവില്ലാതെ ദോഷകരമായ ആപ്പുകൾ കോൺടാക്‌റ്റ് ഡാറ്റ പങ്കിടുകയും ചെയ്‌തേക്കാം."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"നിശ്ചിത ആളുകളെ മറ്റ് മാർഗങ്ങളിൽ നിങ്ങൾ എത്ര തവണ വിളിച്ചിട്ടുണ്ടെന്നതോ അവർക്ക് ഇമെയിൽ ചെയ്‌തിട്ടുണ്ടെന്നതോ ആശയവിനിമയം നടത്തിയിട്ടുണ്ടെന്നതോ ഉൾപ്പെടെ, നിങ്ങളുടെ ഫോണിൽ സംഭരിച്ചിരിക്കുന്ന നിങ്ങളുടെ കോൺടാക്റ്റുകളെക്കുറിച്ചുള്ള ഡാറ്റ റീഡുചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. നിങ്ങളുടെ കോൺടാക്റ്റ് ഡാറ്റ സംരക്ഷിക്കാൻ ഈ അനുമതി അപ്ലിക്കേഷനുകളെ അനുവദിക്കുന്നു, ക്ഷുദ്രകരമായ അപ്ലിക്കേഷനുകൾ നിങ്ങളുടെ അറിവില്ലാതെ കോൺടാക്റ്റ് ഡാറ്റ പങ്കിടാനിടയുണ്ട്."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"ടാബ്‌ലെറ്റിൽ സംഭരിച്ച നിങ്ങളുടെ കോൺടാക്റ്റുകളെക്കുറിച്ചുള്ള ഡാറ്റ വായിക്കാൻ ആപ്പിനെ അനുവദിക്കുന്നു. നിങ്ങളുടെ ടാബ്‌ലെറ്റിൽ കോണ്ടാക്റ്റുകൾ സൃഷ്ടിച്ച അക്കൗണ്ടുകളിലേക്കുള്ള ആക്സസും ആപ്പുകൾക്ക് ഉണ്ടായിരിക്കും. നിങ്ങൾ ഇൻസ്റ്റാൾ ചെയ്‍ത ആപ്പുകൾ സൃഷ്ടിച്ച അക്കൗണ്ടുകളും ഇതിൽ ഉൾപ്പെട്ടേക്കാം. നിങ്ങളുടെ കോണ്ടാക്റ്റ് ഡാറ്റ സംരക്ഷിക്കാൻ ആപ്പുകളെ ഈ അനുമതി അനുവദിക്കുന്നു, നിങ്ങളുടെ അറിവില്ലാതെ, ദോഷകരമായ ആപ്പുകൾ കോണ്ടാക്റ്റ് ഡാറ്റ പങ്കിടുകയും ചെയ്‌തേക്കാം."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"നിങ്ങളുടെ Android ടിവിയിൽ സംഭരിച്ച കോൺടാക്റ്റുകളെക്കുറിച്ചുള്ള ഡാറ്റ വായിക്കാൻ ആപ്പിനെ അനുവദിക്കുന്നു. നിങ്ങളുടെ Android ടിവിയിൽ കോണ്ടാക്റ്റുകൾ സൃഷ്ടിച്ച അക്കൗണ്ടുകളിലേക്കുള്ള ആക്സസും ആപ്പുകൾക്ക് ഉണ്ടായിരിക്കും. നിങ്ങൾ ഇൻസ്റ്റാൾ ചെയ്‍ത ആപ്പുകൾ സൃഷ്ടിച്ച അക്കൗണ്ടുകളും ഇതിൽ ഉൾപ്പെട്ടേക്കാം. നിങ്ങളുടെ കോണ്ടാക്റ്റ് ഡാറ്റ സംരക്ഷിക്കാൻ ആപ്പുകളെ ഈ അനുമതി അനുവദിക്കുന്നു, നിങ്ങളുടെ അറിവില്ലാതെ, ദോഷകരമായ ആപ്പുകൾ കോണ്ടാക്റ്റ് ഡാറ്റ പങ്കിടുകയും ചെയ്‌തേക്കാം."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"ഉപകരണത്തിൽ സംഭരിച്ച നിങ്ങളുടെ കോൺടാക്റ്റുകളെക്കുറിച്ചുള്ള ഡാറ്റ വായിക്കാൻ ആപ്പിനെ അനുവദിക്കുന്നു. നിങ്ങളുടെ ഫോണിൽ കോണ്ടാക്റ്റുകൾ സൃഷ്ടിച്ച അക്കൗണ്ടുകളിലേക്കുള്ള ആക്സസും ആപ്പുകൾക്ക് ഉണ്ടായിരിക്കും. നിങ്ങൾ ഇൻസ്റ്റാൾ ചെയ്‍ത ആപ്പുകൾ സൃഷ്ടിച്ച അക്കൗണ്ടുകളും ഇതിൽ ഉൾപ്പെട്ടേക്കാം. നിങ്ങളുടെ കോണ്ടാക്റ്റ് ഡാറ്റ സംരക്ഷിക്കാൻ ആപ്പുകളെ ഈ അനുമതി അനുവദിക്കുന്നു, നിങ്ങളുടെ അറിവില്ലാതെ, ദോഷകരമായ ആപ്പുകൾ കോണ്ടാക്റ്റ് ഡാറ്റ പങ്കിടുകയും ചെയ്‌തേക്കാം."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"നിങ്ങളുടെ കോൺടാക്റ്റുകൾ പരിഷ്‌ക്കരിക്കുക"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"നിശ്ചിത കോൺടാക്റ്റുകളെ മറ്റ് മാർഗങ്ങളിൽ നിങ്ങൾ എത്ര തവണ വിളിച്ചിട്ടുണ്ടെന്നതോ അവർക്ക് ഇമെയിൽ ചെയ്‌തിട്ടുണ്ടെന്നതോ ആശയവിനിമയം നടത്തിയിട്ടുണ്ടെന്നതോ ഉൾപ്പെടെ, നിങ്ങളുടെ ടാബ്‌ലെറ്റിൽ സംഭരിച്ചിരിക്കുന്ന നിങ്ങളുടെ കോൺടാക്റ്റുകളെക്കുറിച്ചുള്ള ഡാറ്റ പരിഷ്‌ക്കരിക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. ഈ അനുമതി കോൺടാക്റ്റ് ഡാറ്റ ഇല്ലാതാക്കാൻ അപ്ലിക്കേഷനുകളെ അനുവദിക്കുന്നു."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"നിർദ്ദിഷ്‌ട കോൺടാക്റ്റുകളെ നിങ്ങൾ എത്ര തവണ വിളിച്ചിട്ടുണ്ടെന്നും അവർക്ക് ഇമെയിൽ അയച്ചിട്ടുണ്ടെന്നും മറ്റ് മാർഗങ്ങളിലൂടെ അവരുമായി എത്ര തവണ ആശയവിനിമയം നടത്തിയിട്ടുണ്ടെന്നും ഉൾപ്പെടെ നിങ്ങളുടെ Android ടിവിയിൽ സംഭരിച്ചിരിക്കുന്ന കോൺടാക്‌റ്റുകളെക്കുറിച്ചുള്ള ഡാറ്റ പരിഷ്‌ക്കരിക്കാൻ ആപ്പിനെ അനുവദിക്കുന്നു. കോൺടാക്‌റ്റ് ഡാറ്റ ഇല്ലാതാക്കാൻ ഈ അനുമതി ആപ്പുകളെ അനുവദിക്കുന്നു."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"നിശ്ചിത കോൺടാക്റ്റുകളെ മറ്റ് മാർഗങ്ങളിൽ നിങ്ങൾ എത്ര തവണ വിളിച്ചിട്ടുണ്ടെന്നതോ അവർക്ക് ഇമെയിൽ ചെയ്‌തിട്ടുണ്ടെന്നതോ ആശയവിനിമയം നടത്തിയിട്ടുണ്ടെന്നതോ ഉൾപ്പെടെ, നിങ്ങളുടെ ഫോണിൽ സംഭരിച്ചിരിക്കുന്ന നിങ്ങളുടെ കോൺടാക്റ്റുകളെക്കുറിച്ചുള്ള ഡാറ്റ പരിഷ്‌ക്കരിക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. ഈ അനുമതി കോൺടാക്റ്റ് ഡാറ്റ ഇല്ലാതാക്കാൻ അപ്ലിക്കേഷനുകളെ അനുവദിക്കുന്നു."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"ടാബ്‌ലെറ്റിൽ സംഭരിച്ച നിങ്ങളുടെ കോൺടാക്റ്റുകളെക്കുറിച്ചുള്ള ഡാറ്റ പരിഷ്ക്കരിക്കാൻ ആപ്പിനെ അനുവദിക്കുന്നു. കോൺടാക്റ്റ് ഡാറ്റ ഇല്ലാതാക്കാൻ അപ്പുകളെ ഈ അനുമതി അനുവദിക്കുന്നു."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"നിങ്ങളുടെ Android ടിവിയിൽ സംഭരിച്ച കോൺടാക്റ്റുകളെക്കുറിച്ചുള്ള ഡാറ്റ പരിഷ്‌ക്കരിക്കാൻ ആപ്പിനെ അനുവദിക്കുന്നു. കോൺടാക്റ്റ് ഡാറ്റ ഇല്ലാതാക്കാൻ അപ്പുകളെ ഈ അനുമതി അനുവദിക്കുന്നു."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"ഫോണിൽ സംഭരിച്ച നിങ്ങളുടെ കോൺടാക്റ്റുകളെക്കുറിച്ചുള്ള ഡാറ്റ പരിഷ്ക്കരിക്കാൻ ആപ്പിനെ അനുവദിക്കുന്നു. കോൺടാക്റ്റ് ഡാറ്റ ഇല്ലാതാക്കാൻ അപ്പുകളെ ഈ അനുമതി അനുവദിക്കുന്നു."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"കോൾ ചരിത്രം റീഡ് ചെയ്യുക"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"ഈ ആപ്പിന് നിങ്ങളുടെ കോൾ ചരിത്രം വായിക്കാൻ കഴിയും."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"കോൾ ചരിത്രം റൈറ്റ് ചെയ്യുക"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"ലൊക്കേഷൻ ദാതാവിന്റെ അധിക കമാൻഡുകൾ ആക്‌സസ്സുചെയ്യുക"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"ലൊക്കേഷൻ ദാതാവിന്റെ അധിക കമാൻഡുകൾ ആക്‌സസ്സുചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. ഇത് GPS-ന്റെയോ മറ്റ് ലൊക്കേഷൻ ഉറവിടങ്ങളുടെയോ പ്രവർത്തനത്തിൽ ഇടപെടാൻ അപ്ലിക്കേഷനെ അനുവദിക്കാനിടയുണ്ട്."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"ഫോർഗ്രൗണ്ടിൽ മാത്രം കൃത്യമായ ലൊക്കേഷൻ ആക്‌സസ് ചെയ്യുക"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"ഫോർഗ്രൗണ്ടിൽ ഉള്ളപ്പോൾ മാത്രമേ ഈ ആപ്പിന് നിങ്ങളുടെ കൃത്യമായ ലൊക്കേഷൻ നേടാനാവൂ. ആപ്പിന് ഉപയോഗിക്കാനായി, ഈ ലൊക്കേഷൻ സേവനങ്ങൾ ഓണായിരിക്കുകയും നിങ്ങളുടെ ഫോണിൽ ലഭ്യമാവുകയും വേണം. ഇതിലൂടെ ബാറ്ററി ഉപഭോഗം വർദ്ധിച്ചേക്കാം."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"ഫോർഗ്രൗണ്ടിൽ മാത്രം, ഏകദേശ ലൊക്കേഷൻ (നെറ്റ്‌വർക്ക്-അടിസ്ഥാനമാക്കി) ആക്‌സസ് ചെയ്യുക"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"സെൽ ടവറുകളും വൈഫൈ നെറ്റ്‌വർക്കുകളും പോലുള്ള നെറ്റ്‌വർക്ക് ഉറവിടങ്ങൾ അടിസ്ഥാനമാക്കി, ഈ ആപ്പിന് നിങ്ങളുടെ ലൊക്കേഷൻ നേടാൻ‌ കഴിയും. എന്നാൽ, ഫോർഗ്രൗണ്ടിൽ ഉള്ളപ്പോൾ മാത്രമേ ആപ്പിന് ഇതിന് കഴിയൂ. ആപ്പിന് ഉപയോഗിക്കാനായി, ഈ ലൊക്കേഷൻ സേവനങ്ങൾ ഓണായിരിക്കുകയും നിങ്ങളുടെ ടാബ്‌ലെറ്റിൽ ലഭ്യമാവുകയും വേണം."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"സെൽ ടവറുകളും വൈഫൈ നെറ്റ്‌വർക്കുകളും പോലെയുള്ള നെറ്റ്‌വർക്ക് ഉറവിടങ്ങളുടെ അടിസ്ഥാനത്തിൽ ഈ ആപ്പിന് നിങ്ങളുടെ ലൊക്കേഷൻ നേടാനാവും, എന്നാൽ ആപ്പ് ഫോർഗ്രൗണ്ടിൽ ആയിരിക്കുമ്പോൾ മാത്രമേ ഇത് സാധ്യമാവൂ. ആപ്പിന് ഉപയോഗിക്കാനായി ഈ ലൊക്കേഷൻ സേവനങ്ങൾ ഓണായിരിക്കുകയും നിങ്ങളുടെ Android ടിവിയിൽ ലഭ്യമാവുകയും വേണം."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"സെൽ ടവറുകളും വൈഫൈ നെറ്റ്‌വർക്കുകളും പോലുള്ള നെറ്റ്‌വർക്ക് ഉറവിടങ്ങൾ അടിസ്ഥാനമാക്കി, ഈ ആപ്പിന് നിങ്ങളുടെ ലൊക്കേഷൻ നേടാൻ‌ കഴിയും. എന്നാൽ, ഫോർഗ്രൗണ്ടിൽ ഉള്ളപ്പോൾ മാത്രമേ ആപ്പിന് ഇതിന് കഴിയൂ. ആപ്പിന് ഉപയോഗിക്കാനായി, ഈ ലൊക്കേഷൻ സേവനങ്ങൾ ഓണായിരിക്കുകയും നിങ്ങളുടെ ഫോണിൽ ലഭ്യമാവുകയും വേണം."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"ഫോർഗ്രൗണ്ടിൽ ഉള്ളപ്പോൾ മാത്രമേ ഈ ആപ്പിന് നിങ്ങളുടെ കൃത്യമായ ലൊക്കേഷൻ ലഭിക്കൂ. ഈ ആപ്പിന് ലൊക്കേഷൻ സേവനങ്ങൾ ഉപയോഗിക്കാൻ കഴിയണമെങ്കിൽ, അവ നിങ്ങളുടെ ഉപകരണത്തിൽ ലഭ്യമായിരിക്കുകയും ഓണായിരിക്കുകയും വേണം. ഇത് ബാറ്ററി ഉപഭോഗം വർദ്ധിപ്പിച്ചേക്കാം."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"ഫോർഗ്രൗണ്ടിൽ മാത്രം ഏകദേശ ലൊക്കേഷൻ ആക്‌സസ് ചെയ്യുക"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"ഫോർഗ്രൗണ്ടിൽ ഉള്ളപ്പോൾ മാത്രമേ ഈ ആപ്പിന് നിങ്ങളുടെ ഏകദേശ ലൊക്കേഷൻ ലഭിക്കൂ. ഈ ആപ്പിന് ലൊക്കേഷൻ സേവനങ്ങൾ ഉപയോഗിക്കാൻ കഴിയണമെങ്കിൽ, അവ നിങ്ങളുടെ ഉപകരണത്തിൽ ലഭ്യമായിരിക്കുകയും ഓണായിരിക്കുകയും വേണം."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"പശ്ചാത്തലത്തിൽ ലൊക്കേഷൻ ആക്‌സസ് ചെയ്യുക"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"ഏകദേശം അല്ലെങ്കിൽ കൃത്യമായ ലൊക്കേഷൻ ആക്‌സസിന് ഇത് അധികമായി അനുവദിച്ചതാണെങ്കിൽ, പശ്ചാത്തലത്തിൽ റൺ ചെയ്യുമ്പോഴും ആപ്പിന് ലൊക്കേഷൻ ആക്‌സസ് ചെയ്യാനാവും."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"പശ്ചാത്തലത്തിൽ പ്രവർത്തിക്കുമ്പോൾ, ഫോർഗ്രൗണ്ട് ലൊക്കേഷന് പുറമെ, ലൊക്കേഷൻ ആക്സസ് ചെയ്യാനും ഈ ആപ്പിന് കഴിയും."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"നിങ്ങളുടെ ഓഡിയോ ക്രമീകരണങ്ങൾ മാറ്റുക"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"വോളിയവും ഔട്ട്പുട്ടിനായി ഉപയോഗിച്ച സ്‌പീക്കറും പോലുള്ള ആഗോള ഓഡിയോ ക്രമീകരണങ്ങൾ പരിഷ്‌ക്കരിക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"ഓഡിയോ റെക്കോർഡ് ചെയ്യുക"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"ടാബ്‌ലെറ്റിലെ ബ്ലൂടൂത്ത് കോൺഫിഗറേഷൻ കാണാനും ജോടിയാക്കിയ ഉപകരണങ്ങളുമായി കണക്ഷനുകൾ നടത്തി അംഗീകരിക്കാനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"നിങ്ങളുടെ Android ടിവിയിലെ Bluetooth കോൺഫിഗറേഷൻ കാണാനും ജോടിയാക്കിയ ഉപകരണങ്ങളുമായി കണക്ഷനുകൾ സൃഷ്‌ടിക്കാനും അംഗീകരിക്കാനും ആപ്പിനെ അനുവദിക്കുന്നു."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"ഫോണിലെ ബ്ലൂടൂത്ത് കോൺഫിഗറേഷൻ കാണാനും ജോടിയാക്കിയ ഉപകരണങ്ങളുമായി കണക്ഷനുകൾ നടത്തി അംഗീകരിക്കാനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"തിരഞ്ഞെടുത്ത NFC പേയ്‌മെന്റ് സേവനത്തെ സംബന്ധിച്ച വിവരങ്ങൾ"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"റൂട്ട് ലക്ഷ്യസ്ഥാനം, രജിസ്‌റ്റർ ചെയ്തിരിക്കുന്ന സഹായങ്ങൾ എന്നിവ പോലുള്ള, തിരഞ്ഞെടുത്ത NFC പേയ്‌മെന്റ് സേവനത്തെ സംബന്ധിച്ച വിവരങ്ങൾ ലഭിക്കാൻ ആപ്പിനെ അനുവദിക്കുന്നു."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"സമീപ ഫീൽഡുമായുള്ള ആശയവിനിമയം നിയന്ത്രിക്കുക"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"നിയർ ഫീൽഡ് കമ്മ്യൂണിക്കേഷൻ (NFC) ടാഗുകളുമായും കാർഡുകളുമായും റീഡറുകളുമായുള്ള ആശയവിനിമയത്തിന് അപ്ലിക്കേഷനുകളെ അനുവദിക്കുന്നു."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"നിങ്ങളുടെ സ്‌ക്രീൻ ലോക്ക് പ്രവർത്തനരഹിതമാക്കുക"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"ഉപയോഗസഹായിക്കുള്ള കുറുക്കുവഴി <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ഓൺ ചെയ്തിരിക്കുന്നു"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"ഉപയോഗസഹായിക്കുള്ള കുറുക്കുവഴി <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>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"നിങ്ങൾ ഉപയോഗസഹായി ബട്ടൺ ടാപ്പ് ചെയ്യുമ്പോൾ ഉപയോഗിക്കാൻ ഒരു ഫീച്ചർ തിരഞ്ഞെടുക്കുക:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"ഉപയോഗസഹായി വിരൽചലനത്തോടൊപ്പം ഉപയോഗിക്കാൻ ഒരു സർവീസ് തിരഞ്ഞെടുക്കുക (രണ്ട് വിരലുകളുപയോഗിച്ച് സ്‌ക്രീനിന്റെ താഴെ നിന്ന് മുകളിലോട്ട് സ്വൈപ്പ് ചെയ്യുക):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"ഉപയോഗസഹായി വിരൽചലനത്തോടൊപ്പം ഉപയോഗിക്കാൻ ഒരു സർവീസ് തിരഞ്ഞെടുക്കുക (മൂന്ന് വിരലുകളുപയോഗിച്ച് സ്‌ക്രീനിന്റെ താഴെ നിന്ന് മുകളിലോട്ട് സ്വൈപ്പ് ചെയ്യുക):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"സർവീസുകൾക്കിടയിൽ മാറാൻ, ഉപയോഗസഹായി ബട്ടൺ സ്‌പർശിച്ചുപിടിക്കുക."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"സർവീസുകൾക്കിടയിൽ മാറാൻ, രണ്ട് വിരലുകളുപയോഗിച്ച് മുകളിലോട്ട് സ്വൈപ്പ് ചെയ്‌ത് പിടിക്കുക."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"സർവീസുകൾക്കിടയിൽ മാറാൻ, മൂന്ന് വിരലുകളുപയോഗിച്ച് മുകളിലോട്ട് സ്വൈപ്പ് ചെയ്‌ത് പിടിക്കുക."</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>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> എന്നതിലേക്ക് കണക്റ്റുചെയ്തു"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"ഫയലുകൾ കാണുന്നതിന് ടാപ്പുചെയ്യുക"</string>
<string name="pin_target" msgid="8036028973110156895">"പിൻ ചെയ്യുക"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"<xliff:g id="LABEL">%1$s</xliff:g> പിൻ ചെയ്യുക"</string>
<string name="unpin_target" msgid="3963318576590204447">"അൺപിൻ ചെയ്യുക"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"<xliff:g id="LABEL">%1$s</xliff:g> അൺപിൻ ചെയ്യുക"</string>
<string name="app_info" msgid="6113278084877079851">"ആപ്പ് വിവരം"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"ഡെമോ ആരംഭിക്കുന്നു…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"ഇനിപ്പറയുന്ന ഇനങ്ങൾ "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" എന്നതിൽ അപ്‌ഡേറ്റ് ചെയ്യണോ: <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> ?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"സംരക്ഷിക്കുക"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"വേണ്ട, നന്ദി"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"ഇപ്പോൾ വേണ്ട"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"ഒരിക്കലും വേണ്ട"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"അപ്ഡേറ്റ് ചെയ്യുക"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"തുടരുക"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"പാസ്‌വേഡ്"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"സ്‌ക്രീൻ വിഭജന മോഡ് മാറ്റുക"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"ലോക്ക് സ്‌ക്രീൻ"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"സ്ക്രീൻഷോട്ട്"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"പോപ്പ്-അപ്പ് വിൻഡോയിലെ <xliff:g id="APP_NAME">%1$s</xliff:g> ആപ്പ്."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> എന്നതിന്റെ അടിക്കുറിപ്പ് ബാർ."</string>
</resources>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 8c261131d103..0f17c00b82c9 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Ажлын профайлын админ апп байхгүй эсвэл эвдэрсэн байна. Үүний улмаас таны ажлын профайл болон холбогдох мэдээллийг устгасан болно. Тусламж хэрэгтэй бол админтай холбогдоно уу."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Таны ажлын профайл энэ төхөөрөмжид боломжгүй байна"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Нууц үгийг хэт олон удаа буруу оруулсан байна"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Админ хувийн хэрэглээнд зориулж төхөөрөмжийн эрхийг хассан"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Төхөөрөмжийг удирдсан"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Таны байгууллага энэ төхөөрөмжийг удирдаж, сүлжээний ачааллыг хянадаг. Дэлгэрэнгүй мэдээлэл авах бол товшино уу."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Таны төхөөрөмж устах болно."</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Аппад нэвтрүүлэг дууссаны дараа үлдэх бэхлэгдсэн нэвтрүүлэг илгээхийг зөвшөөрнө. Хэт их ашиглах нь санах ойн ачааллыг нэмэгдүүлж, улмаар таны Android ТВ төхөөрөмжийг удаан эсвэл тогтворгүй болгож болзошгүй."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Апп нь өргөн дамжуулал дууссаны дараа үлдсэн өргөн дамжуулалыг илгээх боломжтой. Ихээр ашиглах нь хэт их санах ой ашиглан утсыг удаашруулах болон тогтворгүй болгох боломжтой."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"өөрийн харилцагчдыг унших"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Апп нь таны утсаар ярьсан, имэйл илгээсэн давтамж эсвэл тусгай харилцагдчидтайгаа өөр аргаар холбоо барьсан байдал зэргийг агуулсан таблет дээр хадгалагдсан харилцагчдын талаарх датаг унших боломжтой. Энэ зөвшөөрөл нь апп-д таны харилцагчийн датаг хадгалах боломжийг олгох ба хортой апп нь танд мэдэгдэлгүйгээр харилцагчийн датаг хуваалцах боломжтой."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Аппaд таны тодорхой хувь хүн рүү хийсэн дуудлага, бичсэн имэйл эсвэл бусад аргаар харилцсан байдлын давтамж зэрэг таны Android ТВ төхөөрөмжид хадгалсан харилцагчдын талаарх өгөгдлийг өөрчлөхийг зөвшөөрнө. Энэ зөвшөөрөл нь аппуудад таны харилцагчийн өгөгдлийг хадгалахыг зөвшөөрөх бөгөөд хортой аппууд танд мэдэгдэлгүйгээр харилцагчийн өгөгдлийг бусадтай хуваалцаж болзошгүй."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Апп нь таны утсаар ярьсан, имэйл илгээсэн давтамж эсвэл тусгай харилцагчидтайгаа өөр аргаар холбоо барьсан байдал зэргийг агуулсан таны утсан дээр хадгалагдсан харилцагчдын талаарх датаг унших боломжтой. Энэ зөвшөөрөл нь апп-д таны харилцагчийн датаг хадгалах боломжийг олгох ба хортой апп нь танд мэдэгдэлгүйгээр харилцагчийн датаг хуваалцах боломжтой."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Аппaд таны таблет дээр хадгалагдсан харилцагчдын өгөгдлийг уншихыг зөвшөөрнө. Мөн аппууд нь таны таблет дээрх харилцагч үүсгэсэн бүртгэлд хандах боломжтой байна. Үүнд таны суулгасан аппуудын үүсгэсэн бүртгэлийг оролцуулж болзошгүй. Энэ зөвшөөрөл нь аппуудад таны харилцагчийн өгөгдлийг хадгалахыг зөвшөөрөх бөгөөд хортой аппууд нь танд мэдэгдэлгүйгээр харилцагчийн өгөгдлийг хуваалцаж болзошгүй."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Аппaд таны Android TВ төхөөрөмж дээр хадгалагдсан харилцагчдын өгөгдлийг уншихыг зөвшөөрнө. Мөн аппууд нь таны Android TВ төхөөрөмж дээрх харилцагч үүсгэсэн бүртгэлд хандах боломжтой байна. Үүнд таны суулгасан аппуудын үүсгэсэн бүртгэлийг оролцуулж болзошгүй. Энэ зөвшөөрөл нь аппуудад таны харилцагчийн өгөгдлийг хадгалахыг зөвшөөрөх бөгөөд хортой аппууд нь танд мэдэгдэлгүйгээр харилцагчийн өгөгдлийг хуваалцаж болзошгүй."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Аппaд таны утсан дээр хадгалагдсан харилцагчдын өгөгдлийг уншихыг зөвшөөрнө. Мөн аппууд нь таны утсан дээрх харилцагч үүсгэсэн бүртгэлд хандах боломжтой байна. Үүнд таны суулгасан аппуудын үүсгэсэн бүртгэлийг оролцуулж болзошгүй. Энэ зөвшөөрөл нь аппуудад таны харилцагчийн өгөгдлийг хадгалахыг зөвшөөрөх бөгөөд хортой аппууд нь танд мэдэгдэлгүйгээр харилцагчийн өгөгдлийг хуваалцаж болзошгүй."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"таны харилцагчдыг өөрчлөх"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Апп нь таны утсаар ярьсан, имэйл илгээсэн давтамж эсвэл тусгай харилцагчидтайгаа өөр аргаар холбоо барьсан байдал зэргийг агуулсан таны таблет дээр хадгалагдсан харилцагчдын талаарх датаг өөрчлөх боломжтой. Энэ зөвшөөрөл нь апп-д харилцагчийн датаг устгах боломжийг олгоно."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Аппaд таны тодорхой харилцагч руу хийсэн дуудлага, бичсэн имэйл эсвэл бусад аргаар харилцсан байдлын давтамж зэрэг таны Android ТВ төхөөрөмжид хадгалсан харилцагчдын талаарх өгөгдлийг өөрчлөхийг зөвшөөрнө. Энэ зөвшөөрөл нь аппуудад харилцагчийн өгөгдлийг устгахыг зөвшөөрнө."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Апп нь таны утсаар ярьсан, имэйл илгээсэн давтамж эсвэл харилцагдчидтайгаа өөр аргаар холбоо барьсан байдал зэргийг агуулсан утсан дээр хадгалагдсан харилцагчдын талаарх датаг өөрчлөх боломжтой. Энэ зөвшөөрөл нь апп-д харилцагчийн датаг устгах боломжийг олгоно."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Аппад таны таблет дээр хадгалагдсан харилцагчдын өгөгдлийг өөрчлөхийг зөвшөөрнө. Энэ зөвшөөрөл нь харилцагчийн өгөгдлийг устгахыг аппуудад зөвшөөрнө."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Аппaд таны Android TВ төхөөрөмж дээр хадгалагдсан харилцагчдын өгөгдлийг өөрчлөхийг зөвшөөрнө. Энэ зөвшөөрөл нь харилцагчийн өгөгдлийг устгахыг аппуудад зөвшөөрнө."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Аппад таны утсан дээр хадгалагдсан харилцагчдын өгөгдлийг өөрчлөхийг зөвшөөрнө. Энэ зөвшөөрөл нь харилцагчийн өгөгдлийг устгахыг аппуудад зөвшөөрнө."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"дуудлагын логийг унших"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Энэ апп таны дуудлагын түүхийг унших боломжтой."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"дуудлагын логруу бичих"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"байршил нийлүүлэгчийн нэмэлт тушаалд хандах"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Апп нь байршил нийлүүлэгчийн нэмэлт тушаалд хандах боломжтой. Энэ нь апп-д GPS эсвэл бусад байршлын үйлчилгээний ажиллагаанд нөлөөлөх боломжийг олгоно."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"нарийвчилсан байршилд зөвхөн нүүр хэсэгт хандах"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Энэ апп нь зөвхөн нүүр хэсэгт байх үедээ л таны байршлыг нарийн тогтоох боломжтой. Апп эдгээр байршлын үйлчилгээг ашиглахын тулд эдгээрийг таны утсан дээр асааж идэвхтэй байлгах шаардлагатай. Энэ нь батарейны хэрэглээг ихэсгэж болзошгүй."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"ойролцоох байршилд (сүлжээнд суурилсан) зөвхөн дэлгэц дээр хандах"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Энэ апп зөвхөн дэлгэц дээр байх үед үүрэн цамхаг, Wi-Fi сүлжээ зэрэг сүлжээний эх сурвалжид тулгуурлан таны байршлыг мэдэх боломжтой. Та энэ аппад эдгээр байршлын үйлчилгээг ашиглуулахын тулд эдгээрийг таблет дээрээ асааж, боломжтой байлгах шаардлагатай."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Энэ апп зөвхөн дэлгэц дээр байх үед үүрэн цамхаг, Wi-Fi сүлжээ зэрэг сүлжээний эх сурвалжид тулгуурлан таны байршлыг мэдэх боломжтой. Та энэ аппад эдгээр байршлын үйлчилгээг ашиглуулахын тулд эдгээрийг Android TB төхөөрөмж дээрээ асааж, боломжтой байлгах шаардлагатай."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Энэ апп зөвхөн дэлгэц дээр байх үед үүрэн цамхаг, Wi-Fi сүлжээ зэрэг сүлжээний эх сурвалжид тулгуурлан таны байршлыг мэдэх боломжтой. Та энэ аппад эдгээр байршлын үйлчилгээг ашиглуулахын тулд эдгээрийг утсан дээрээ асааж, боломжтой байлгах шаардлагатай."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Энэ апп нь зөвхөн дэлгэц дээр байх үедээ л таны байршлыг нарийн тогтоох боломжтой. Байршлын үйлчилгээ нь таны төхөөрөмж дээр асаалттай, апп ашиглах боломжтой байх ёстой. Энэ нь батарейны хэрэглээг нэмэгдүүлж болзошгүй."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"зөвхөн дэлгэц дээр байхад ойролцоо байршилд хандах"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Энэ апп нь зөвхөн дэлгэц дээр байх үедээ л таны байршлыг ойролцоогоор тогтоох боломжтой. Байршлын үйлчилгээ нь таны төхөөрөмж дээр асаалттай, апп ашиглах боломжтой байх ёстой."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"байршилд ард хандах"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Хэрэв үүнийг ойролцоо эсвэл нарийвчилсан байршлын хандалтад нэмэлтээр зөвшөөрсөн бол энэ апп ард ажиллах явцдаа байршилд хандаж болно."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Энэ апп нь дэлгэц дээр байхдаа байршилд хандахаас гадна арын хэсэгт ажиллах үедээ байршилд хандах боломжтой."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"Аудио тохиргоо солих"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Апп нь дууны хэмжээ, спикерын гаралтад ашиглагдах глобал аудио тохиргоог өөрчлөх боломжтой."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"аудио бичих"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Апп нь таблет дээрх блютүүт тохиргоог харах боломжтой ба хос болох төхөөрөмжтэй холболтыг зөвшөөрөх болон хийх боломжтой."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Аппад таны Android ТВ төхөөрөмж дээрх Bluetooth-н тохируулгыг харах болон хослуулсан төхөөрөмжүүдтэй холболт хийж, холболтыг баталгаажуулахыг зөвшөөрнө."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Апп нь утсан дээрх Bluetooth тохиргоог харах боломжтой ба хос болох төхөөрөмжтэй холболтыг зөвшөөрөх болон хийх боломжтой."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Сонгосон NFC төлбөрийн үйлчилгээний мэдээлэл"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Бүртгүүлсэн төхөөрөмж болон маршрутын хүрэх цэг зэрэг сонгосон nfc төлбөрийн үйлчилгээний мэдээллийг авахыг аппад зөвшөөрдөг."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"ойролцоо талбарын холбоог удирдах"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Апп нь Ойролцоо Талбарын Холболт(NFC) таг, карт, болон уншигчтай холбогдох боломжтой."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"дэлгэцний түгжээг идэвхгүй болгох"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"Хүртээмжийн товчлол <xliff:g id="SERVICE_NAME">%1$s</xliff:g>-г асаасан"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"Хүртээмжийн товчлол <xliff:g id="SERVICE_NAME">%1$s</xliff:g>-г унтраасан"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>-г ашиглахын тулд дууны түвшнийг ихэсгэх, багасгах түлхүүрийг 3 секундийн турш зэрэг дарна уу"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Хандалтын товчлуурыг товшихдоо ашиглах үйлчилгээг сонгоно уу:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Хандалтын зангаатай ашиглах үйлчилгээг сонгоно уу (хоёр хуруугаараа дэлгэцийн доороос дээш шударна уу):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Хандалтын зангаатай ашиглах үйлчилгээг сонгоно уу (гурван хуруугаараа дэлгэцийн доороос дээш шударна уу):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Үйлчилгээнүүд хооронд сэлгэхийн тулд хандалтын товчлуурт хүрээд удаан дарна уу."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Үйлчилгээнүүд хооронд сэлгэхийн тулд хоёр хуруугаараа дээш шудраад удаан дарна уу."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Үйлчилгээнүүд хооронд сэлгэхийн тулд гурван хуруугаараа дээш шудраад удаан дарна уу."</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>
@@ -1757,8 +1750,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="1817385558636532621">"Батарейны ажиллах хугацааг уртасгахын тулд Батарей хэмнэгч нь:\n·Бараан загварыг асаадаг\n·Арын үйл ажиллагаа, зарим визуал эффект болон “Hey Google” зэрэг бусад онцлогийг унтрааж эсвэл хязгаарладаг\n\n"<annotation id="url">"Нэмэлт мэдээлэл авах"</annotation></string>
- <string name="battery_saver_description" msgid="7618492104632328184">"Батарейны ажиллах хугацааг уртасгахын тулд Батарей хэмнэгч нь:\n·Бараан загварыг асаадаг\n·Арын үйл ажиллагаа, зарим визуал эффект болон “Hey Google” зэрэг бусад онцлогийг унтрааж эсвэл хязгаарладаг"</string>
+ <string name="battery_saver_description_with_learn_more" msgid="1817385558636532621">"Батарейн ажиллах хугацааг уртасгахын тулд Батарей хэмнэгч нь:\n·Бараан загварыг асаадаг\n·Арын үйл ажиллагаа, зарим визуал эффект болон “Hey Google” зэрэг бусад онцлогийг унтрааж эсвэл хязгаарладаг\n\n"<annotation id="url">"Нэмэлт мэдээлэл авах"</annotation></string>
+ <string name="battery_saver_description" msgid="7618492104632328184">"Батарейн ажиллах хугацааг уртасгахын тулд Батарей хэмнэгч нь:\n·Бараан загварыг асаадаг\n·Арын үйл ажиллагаа, зарим визуал эффект болон “Hey Google” зэрэг бусад онцлогийг унтрааж эсвэл хязгаарладаг"</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>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g>-д холбогдсон"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Файлыг үзэхийн тулд дарна уу"</string>
<string name="pin_target" msgid="8036028973110156895">"PIN"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"<xliff:g id="LABEL">%1$s</xliff:g>-г бэхлэх"</string>
<string name="unpin_target" msgid="3963318576590204447">"Unpin"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"<xliff:g id="LABEL">%1$s</xliff:g>-г тогтоосныг болиулах"</string>
<string name="app_info" msgid="6113278084877079851">"Апп-н мэдээлэл"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Жишээг эхлүүлж байна…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Эдгээр зүйлийг буюу <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_save_yes" msgid="8035743017382012850">"Хадгалах"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Үгүй, баярлалаа"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Одоо биш"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Хэзээ ч үгүй"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Шинэчлэх"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Үргэлжлүүлэх"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"нууц үг"</string>
@@ -1956,7 +1953,7 @@
<string name="notification_appops_overlay_active" msgid="5571732753262836481">"таны дэлгэцэд бусад аппын дээр харуулж байна"</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>
+ <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Батарейн ажиллах хугацааг уртасгахын тулд Батарей хэмнэгчийг идэвхжүүллээ"</string>
<string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Батарей хэмнэгч"</string>
<string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Батарей хэмнэгч батарейг дахин багасах хүртэл дахин идэвхжихгүй"</string>
<string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Батарейг хангалттай түвшинд цэнэглэлээ. Батарей хэмнэгч батарейг дахин багасах хүртэл дахин идэвхжихгүй."</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Дэлгэц хуваахыг унтраах/асаах"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Дэлгэцийг түгжих"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Дэлгэцийн зураг дарах"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"Үзэгдэх цонхонд байгаа <xliff:g id="APP_NAME">%1$s</xliff:g> апп."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g>-н гарчгийн талбар."</string>
</resources>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 2782cafb7dbe..fa8cbb0208d1 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"कार्य प्रोफाइल प्रशासक अ‍ॅप गहाळ आहे किंवा करप्ट आहे. परिणामी, तुमचे कार्य प्रोफाइल आणि संबंधित डेटा हटवले गेले आहेत. सहाय्यासाठी आपल्या प्रशासकाशी संपर्क साधा."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"तुमचे कार्य प्रोफाइल आता या डिव्हाइसवर उपलब्‍ध नाही"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"बर्‍याचदा पासवर्ड टाकण्‍याचा प्रयत्‍न केला"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"वैयक्तिक वापरासाठी ॲडमिनने नियंत्रण सोडलेले डिव्हाइस"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"डिव्हाइस व्यवस्थापित केले आहे"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"तुमची संस्था हे डिव्हाइस व्यवस्थापित करते आणि नेटवर्क रहदारीचे निरीक्षण करू शकते. तपशीलांसाठी टॅप करा."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"तुमचे डिव्हाइस मिटविले जाईल"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"चिकट प्रसारणे पाठविण्यासाठी ॲपला अनुमती देते, जे प्रसारण समाप्त झाल्यानंतर देखील तसेच राहते. अत्याधिक वापरामुळे बरीच मेमरी वापरली जाऊन तो तुमच्या Android TV डिव्हाइसला धीमा किंवा अस्थिर करू शकतो."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"रोचक प्रसारणे पाठविण्यासाठी अ‍ॅप ला अनुमती देते, जे प्रसारण समाप्त झाल्यानंतर देखील तसेच राहते. अत्याधिक वापरामुळे बरीच मेमरी वापरली जाऊन तो फोनला धीमा किंवा अस्थिर करू शकतो."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"तुमचे संपर्क वाचा"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"तुम्ही कॉल केलेल्या, ईमेल केलेल्या किंवा विशिष्ट लोकांशी अन्य मार्गांनी संवाद प्रस्थापित केलेल्या लोकांच्या फ्रिक्वेन्सीसह, आपल्या टॅब्लेटवर स्टोअर केलेल्या आपल्या संपर्कांविषयीचा डेटा वाचण्यासाठी अ‍ॅप ला अनुमती देते. ही परवानगी तुमचा संपर्क डेटा सेव्ह करण्याची अ‍ॅप्स ला अनुमती देते आणि दुर्भावनापूर्ण अ‍ॅप्स आपल्या माहितीशिवाय संपर्क डेटा शेअर करू शकतात."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"तुम्ही केलेले कॉल, केलेले ईमेल किंवा विशिष्‍ट संपर्कांसह अन्य मार्गांनी केलेले कम्युनिकेशन यांची वारंवारता, यासह तुमच्या Android TV डिव्‍हाइसवर स्टोअर केलेल्‍या तुमच्या संपर्कांविषयीचा डेटा वाचण्याची ॲपला अनुमती देते. ही परवानगी अ‍ॅप्सना तुमचा संपर्क डेटा सेव्ह करण्याची अनुमती देते आणि ही दुर्भावनापूर्ण अ‍ॅप्स तुम्हाला न कळवता संपर्क डेटा शेअर करू शकतात."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"तुम्ही कॉल केलेल्या, ईमेल केलेल्या किंवा विशिष्ट लोकांशी अन्य मार्गांनी संवाद प्रस्थापित केलेल्या लोकांच्या फ्रिक्वेन्सीसह, आपल्या फोनवर स्टोअर केलेल्या आपल्या संपर्कांविषयीचा डेटा वाचण्यासाठी अ‍ॅप ला अनुमती देते. ही परवानगी तुमचा संपर्क डेटा सेव्ह करण्याची अ‍ॅप्स ला अनुमती देते आणि दुर्भावनापूर्ण अ‍ॅप्स आपल्या माहितीशिवाय संपर्क डेटा शेअर करू शकतात."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"तुमच्या टॅबलेटवर स्टोअर केलेल्‍या तुमच्या संपर्कांविषयीचा डेटा वाचण्याची ॲपला अनुमती देते. अ‍ॅप्सना संपर्क तयार केलेल्या तुमच्या टॅबलेटवरील खात्याचा अ‍ॅक्सेसदेखील असेल. यामध्ये तुम्ही इंस्टॉल केलेल्या ॲप्सने तयार केलेल्या खात्यांचा समावेश असू शकतात. ही परवानगी ॲप्सना तुमचा संपर्क डेटा सेव्ह करण्याची अनुमती देते आणि दुर्भावनापूर्ण ॲप्स तुम्हाला न कळवता संपर्क डेटा शेअर करू शकतात."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"तुमच्या Android TV डिव्हाइस स्टोअर केलेल्‍या तुमच्या संपर्कांविषयीचा डेटा वाचण्याची ॲपला अनुमती देते. अ‍ॅप्सना संपर्क तयार केलेल्या तुमच्या Android TV डिव्हाइसवरील खात्याचा अ‍ॅक्सेसदेखील असेल. यामध्ये तुम्ही इंस्टॉल केलेल्या ॲप्सने तयार केलेल्या खात्यांचा समावेश असू शकतात. ही परवानगी ॲप्सना तुमचा संपर्क डेटा सेव्ह करण्याची अनुमती देते आणि दुर्भावनापूर्ण ॲप्स तुम्हाला न कळवता संपर्क डेटा शेअर करू शकतात."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"तुमच्या फोनवर स्टोअर केलेल्‍या तुमच्या संपर्कांविषयीचा डेटा वाचण्याची ॲपला अनुमती देते. अ‍ॅप्सना संपर्क तयार केलेल्या तुमच्या फोनवरील खात्याचा अ‍ॅक्सेसदेखील असेल. यामध्ये तुम्ही इंस्टॉल केलेल्या ॲप्सने तयार केलेल्या खात्यांचा समावेश असू शकतात. ही परवानगी ॲप्सना तुमचा संपर्क डेटा सेव्ह करण्याची अनुमती देते आणि दुर्भावनापूर्ण ॲप्स तुम्हाला न कळवता संपर्क डेटा शेअर करू शकतात."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"तुमचे संपर्क सुधारित करा"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"तुम्ही विशिष्ट संपर्कांशी अन्य मार्गांनी कॉल केलेल्या, ईमेल केलेल्या किंवा संवाद प्रस्थापित केलेल्या फ्रिक्वेन्सीसह, आपल्या टॅब्लेटवर स्टोअर केलेल्या आपल्या संपर्कांविषयीचा डेटा सुधारित करण्यासाठी अ‍ॅप ला अनुमती देते. ही परवानगी संपर्क डेटा हटविण्यासाठी अ‍ॅप ला अनुमती देते."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"तुम्ही विशिष्ट संपर्कांशी कॉल, ईमेल किंवा इतर मार्गांनी संवाद प्रस्थापित केल्याची वारंवारता यांच्या समावेशासह, तुमच्या Android TV वर स्टोअर केलेल्या तुमच्या संपर्कांविषयीचा डेटा सुधारित करण्यासाठी ॲपला अनुमती देते. ही परवानगी ॲपला संपर्क डेटा हटविण्यासाठी अनुमती देते."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"तुम्ही विशिष्ट संपर्कांशी अन्य मार्गांनी कॉल केलेल्या, ईमेल केलेल्या किंवा संवाद प्रस्थापित केलेल्या फ्रिक्वेन्सीसह, आपल्या फोनवर स्टोअर केलेल्या आपल्या संपर्कांविषयीचा डेटा सुधारित करण्यासाठी अ‍ॅप ला अनुमती देते. ही परवानगी संपर्क डेटा हटविण्यासाठी अ‍ॅप ला अनुमती देते."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"तुमच्या टॅबलेटवर स्टोअर केलेल्या तुमच्या संपर्कांविषयीच्या डेटामध्ये बदल करण्यासाठी अ‍ॅपला अनुमती देते. ही परवानगी अ‍ॅप्सला संपर्क डेटा हटवण्याची परवानगी देते."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Android TV वर स्टोअर केलेल्या तुमच्या संपर्कांविषयीच्या डेटामध्ये बदल करण्यासाठी अ‍ॅपला अनुमती देते. ही परवानगी अ‍ॅप्सला संपर्क डेटा हटवण्याची परवानगी देते."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"तुमच्या फोनवर स्टोअर केलेल्या तुमच्या संपर्कांविषयीच्या डेटामध्ये बदल करण्यासाठी अ‍ॅपला अनुमती देते. ही परवानगी अ‍ॅप्सला संपर्क डेटा हटवण्याची परवानगी देते."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"कॉल लॉग वाचा"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"हा अ‍ॅप तुमचा कॉल इतिहास वाचू शकता."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"कॉल लॉग लिहा"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"अतिरिक्त स्थान प्रदाता आदेश अ‍ॅक्सेस करा"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"अ‍ॅपला अतिरिक्त स्‍थान प्रदाता आदेशावर प्रवेश करण्‍याची अनुमती देते. हे कदाचित अ‍ॅपला GPS किंवा इतर स्‍थान स्रोत च्या ऑपरेशनमध्‍ये हस्तक्षेप करण्‍याची अनुमती देऊ शकते."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"फक्त फोरग्राउंडमध्ये अचूकपणे अ‍ॅक्सेस करा"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"हे अ‍ॅप फक्त फोरग्राउंडमध्ये असतानाच तुमचे अचूक स्थान मिळवू शकते. या स्थान सेवा सुरू करणे आणि त्या वापरण्यासाठी अ‍ॅपसाठी तुमच्या फोनवर उपलब्ध करणे आवश्यक आहे, यामुळे बॅटरी वापर वाढू शकतो."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"फक्त फोरग्राउंडमध्ये अंदाजे स्थान (नेटवर्क आधारित) अ‍ॅक्सेस करा"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"हे अ‍ॅप फक्त फोरग्राउंडमध्ये असतानाच, सेल टॉवर आणि वाय-फाय नेटवर्क सारख्या नेटवर्क स्रोतवर आधारित तुमचे स्थान मिळवू शकते. त्या वापरण्याकरता अ‍ॅपसाठी, या स्थान सेवा सुरू करणे आणि त्या तुमच्या टॅबलेटवर उपलब्ध करणे आवश्यक आहे."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"हे ॲप फक्त फोरग्राउंडमध्ये असतानाच, सेल टॉवर आणि वाय-फाय नेटवर्क सारख्या नेटवर्क स्रोतवर आधारित तुमचे स्थान मिळवू शकते. ॲपने वापरण्याकरिता, या स्थान सेवा सुरू करणे आणि त्या तुमच्या Android TV डिव्हाइसवर उपलब्ध करणे आवश्यक आहे."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"हे अ‍ॅप फक्त फोरग्राउंडमध्ये असतानाच, सेल टॉवर आणि वाय-फाय नेटवर्क सारख्या नेटवर्क स्रोतवर आधारित तुमचे स्थान मिळवू शकते. ते वापरण्याकरता अ‍ॅपसाठी, या स्थान सेवा सुरू करणे आणि त्या तुमच्या फोनवर उपलब्ध करणे आवश्यक आहे."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"हे अ‍ॅप फक्त फोरग्राउंडमध्ये असतानाच तुमचे अचूक स्थान मिळवू शकते. स्थातुमच्या डिव्हाइसवर स्थान सेवा सुरू असणे आणि उपलब्ध असणे आवश्यक आहे जेणेकरून ॲप त्यांचा वापर करू शकतील. यामुळे बॅटरी वापर वाढू शकतो."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"फक्त फोअरग्राउंडमध्ये अचूक स्थान अ‍ॅक्सेस करा"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"हे अ‍ॅप फक्त फोरग्राउंडमध्ये असताना तुमचे अचूक स्थान मिळवू शकते. तुमच्या डिव्हाइसवर स्थान सेवा सुरू असणे आणि उपलब्ध असणे आवश्यक आहे जेणेकरून ॲप त्यांचा वापर करू शकतील."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"बॅकग्राउंडमध्ये स्थान अ‍ॅक्सेस करू शकतो"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"याला अंदाजे किंवा अचूक स्थान अ‍ॅक्सेस करण्यास अतिरिक्त मंजूरी दिल्यास, बॅकग्राउंडमध्ये चालतांना अ‍ॅप स्थान अ‍ॅक्सेस करू शकतो."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"हे अ‍ॅप फोरग्राउंड स्थान ॲक्सेस व्यतिरिक्त, बॅकग्राउंडमध्ये सुरू असताना स्थान ॲक्सेस करू शकते."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"आपल्या ऑडिओ सेटिंग्ज बदला"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"व्हॉल्यूम आणि आउटपुटसाठी कोणता स्पीकर वापरला आहे यासारख्या समग्र ऑडिओ सेटिंग्ज सुधारित करण्यासाठी अ‍ॅप ला अनुमती देते."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"ऑडिओ रेकॉर्ड"</string>
@@ -494,6 +491,8 @@
<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_preferredPaymentInfo" msgid="5274423844767445054">"प्राधान्यकृत NFC पेमेंट सेवा माहिती"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"नोंदणीकृत एड्स आणि मार्ग गंतव्यस्थान सारखी प्राधान्यकृत एनएफसी पेमेंट सेवेची माहिती मिळवण्यासाठी अ‍ॅपला अनुमती देते."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"फील्ड जवळील कम्युनिकेशन नियंत्रित करा"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"फील्ड जवळील कम्युनिकेशन (NFC) टॅग, कार्डे आणि वाचक यांच्यासह संवाद करण्यासाठी ॲपला अनुमती देते."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"तुमचे स्क्रीन लॉक अक्षम करा"</string>
@@ -900,7 +899,7 @@
<string name="factorytest_no_action" msgid="339252838115675515">"FACTORY_TEST क्रिया प्रदान करणारे कोणतेही पॅकेज आढळले नाही."</string>
<string name="factorytest_reboot" msgid="2050147445567257365">"रीबूट करा"</string>
<string name="js_dialog_title" msgid="7464775045615023241">"\"<xliff:g id="TITLE">%s</xliff:g>\" वरील पृष्ठ हे म्हणते:"</string>
- <string name="js_dialog_title_default" msgid="3769524569903332476">"Javascript"</string>
+ <string name="js_dialog_title_default" msgid="3769524569903332476">"JavaScript"</string>
<string name="js_dialog_before_unload_title" msgid="7012587995876771246">"नेव्हिगेशनची पुष्टी करा"</string>
<string name="js_dialog_before_unload_positive_button" msgid="4274257182303565509">"हे पृष्ठ सोडा"</string>
<string name="js_dialog_before_unload_negative_button" msgid="3873765747622415310">"या पेजवर रहा"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"प्रवेशयोग्यता शॉर्टकटने <xliff:g id="SERVICE_NAME">%1$s</xliff:g> चालू केली"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"प्रवेशयोग्यता शॉर्टकटने <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>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"तुम्ही अ‍ॅक्सेसिबिलिटी बटण दाबल्यावर वापरण्यासाठी वैशिष्ट्य निवडा:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"अ‍ॅक्सेसिबिलिटी जेश्चर ज्यासोबत वापराचे आहे अशी सेवा निवडा (स्क्रीनच्या खालच्या बाजूने दोन बोटांनी स्वाइप करा):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"अ‍ॅक्सेसिबिलिटी जेश्चर ज्या सोबत वापराचे आहे अशी सेवा निवडा (स्क्रीनच्या खालच्या बाजूने तीन बोटांनी स्वाइप करा):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"सेवांदरम्यान स्विच करण्यासाठी, अ‍ॅक्सेसिबिलिटी बटणाला स्पर्श करा आणि धरून ठेवा."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"सेवांदरम्यान स्विच करण्यासाठी, दोन बोटांनी वरच्या दिशेला स्वाइप करा आणि धरून ठेवा."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"सेवांदरम्यान स्विच करण्यासाठी, तीन बोटांनी वरच्या दिशेला स्वाइप करा आणि धरून ठेवा."</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>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> शी कनेक्ट केलेले"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"फायली पाहण्यासाठी टॅप करा"</string>
<string name="pin_target" msgid="8036028973110156895">"पिन"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"<xliff:g id="LABEL">%1$s</xliff:g> ला पिन करा"</string>
<string name="unpin_target" msgid="3963318576590204447">"अनपिन करा"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"<xliff:g id="LABEL">%1$s</xliff:g> ला अनपिन करा"</string>
<string name="app_info" msgid="6113278084877079851">"अ‍ॅप माहिती"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"डेमो प्रारंभ करत आहे..."</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"हे आयटम "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <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> मध्ये अपडेट करायचे का?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"सेव्ह करा"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"नाही, नको"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"आता नाही"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"कधीही नाही"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"अपडेट करा"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"पुढे सुरू ठेवा"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"पासवर्ड"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"विभाजित स्क्रीन टॉगल करा"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"स्‍क्रीन लॉक करा"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"स्क्रीनशॉट"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"पॉप-अप विंडोमध्ये <xliff:g id="APP_NAME">%1$s</xliff:g> ॲप."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> चा शीर्षक बार."</string>
</resources>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index a40eca089c9a..1386e7a6802d 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Apl pentadbir profil kerja tiada atau rosak. Akibatnya, profil kerja anda dan data yang berkaitan telah dipadamkan. Hubungi pentadbir anda untuk mendapatkan bantuan."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Profil kerja anda tidak lagi tersedia pada peranti ini"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Terlalu banyak percubaan kata laluan"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Pentadbir melepaskan peranti untuk kegunaan peribadi"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Peranti ini diurus"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Organisasi anda mengurus peranti ini dan mungkin memantau trafik rangkaian. Ketik untuk mendapatkan butiran."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Peranti anda akan dipadam"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Membenarkan apl menghantar siaran lekit, yang kekal selepas siaran tamat. Penggunaan secara berlebihan boleh menyebabkan peranti Android TV anda menjadi perlahan atau tidak stabil kerana menggunakan terlalu banyak memori."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Membenarkan apl untuk menghantar siaran melekit, yang kekal selepas siaran berakhir. Penggunaan berlebihan boleh membuat telefon perlahan atau tidak stabil dengan menyebabkannya menggunakan memori yang terlalu banyak."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"baca kenalan anda"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Membenarkan apl membaca data tentang kenalan anda yang tersimpan di tablet anda, termasuk kekerapan anda memanggil, menghantar e-mel atau berkomunikasi dalam cara lain dengan individu tertentu. Kebenaran ini membenarkan apl untuk menyimpan data kenalan anda dan apl hasad boleh berkongsi data kenalan anda tanpa pengetahuan anda."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Membenarkan apl membaca data tentang kenalan anda yang tersimpan pada peranti Android TV, termasuk kekerapan anda membuat panggilan, menghantar e-mel atau berkomunikasi melalui cara lain dengan individu tertentu. Kebenaran ini membenarkan apl menyimpan data kenalan anda dan apl hasad mungkin berkongsi data kenalan tanpa pengetahuan anda."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Membenarkan apl membaca data tentang kenalan anda yang tersimpan di telefon anda, termasuk kekerapan anda memanggil, menghantar e-mel atau berkomunikasi dalam cara lain dengan individu tertentu. Kebenaran ini membenarkan apl untuk menyimpan data kenalan anda dan apl hasad boleh berkongsi data kenalan anda tanpa pengetahuan anda."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Membenarkan apl membaca data tentang kenalan anda yang tersimpan pada tablet anda. Apl juga akan mempunyai akses kepada akaun pada tablet anda yang telah dibuat kenalan. Ini mungkin termasuk akaun yang dibuat oleh apl yang telah anda pasang. Kebenaran ini membolehkan apl menyimpan data kenalan anda dan apl hasad mungkin berkongsi data kenalan tanpa pengetahuan anda."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Membenarkan apl membaca data tentang kenalan anda yang tersimpan pada peranti Android TV anda. Apl juga akan mempunyai akses kepada akaun pada peranti Android TV anda yang telah dibuat kenalan. Ini mungkin termasuk akaun yang dibuat oleh apl yang telah anda pasang. Kebenaran ini membolehkan apl menyimpan data kenalan anda dan apl hasad mungkin berkongsi data kenalan tanpa pengetahuan anda."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Membenarkan apl membaca data tentang kenalan anda yang tersimpan pada telefon anda. Apl juga mempunyai akses kepada akaun pada telefon anda yang telah dibuat kenalan. Ini mungkin termasuk akaun yang dibuat oleh apl yang telah anda pasang. Kebenaran ini membolehkan apl menyimpan data kenalan anda dan apl hasad mungkin berkongsi data kenalan tanpa pengetahuan anda."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"ubah suai kenalan anda"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Membenarkan apl mengubah suai data tentang kenalan anda yang tersimpan pada tablet anda, termasuk kekerapan siapa anda panggil, hantar e-mel atau berkomunikasi dalam cara lain dengan kenalan tertentu. Kebenaran ini membenarkan apl untuk memadam data kenalan."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Membenarkan apl mengubah suai data tentang kenalan anda yang tersimpan pada peranti Android TV anda, termasuk kekerapan anda membuat panggilan, menghantar e-mel atau berkomunikasi melalui cara lain dengan kenalan tertentu. Kebenaran ini membenarkan apl memadam data kenalan."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Membenarkan apl mengubah suai data tentang kenalan anda yang tersimpan pada telefon anda, termasuk kekerapan siapa anda panggil, hantar e-mel atau berkomunikasi dalam cara lain dengan kenalan tertentu. Kebenaran ini membenarkan apl untuk memadam data kenalan."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Membenarkan apl mengubah suai data tentang kenalan anda yang tersimpan pada tablet anda. Kebenaran ini membenarkan apl memadamkan data kenalan."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Membenarkan apl mengubah suai data tentang kenalan anda yang tersimpan pada peranti Android TV anda. Kebenaran ini membenarkan apl memadamkan data kenalan."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Membenarkan apl mengubah suai data tentang kenalan anda yang tersimpan pada telefon anda. Kebenaran ini membenarkan apl memadamkan data kenalan."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"baca log panggilan"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Apl ini boleh membaca sejarah panggilan anda."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"tulis log panggilan"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"akses perintah tambahan pembekal lokasi"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Membenarkan apl mengakses arahan pembekal lokasi tambahan. Ini boleh membenarkan apl untuk campur tangan dengan operasi GPS atau sumber lokasi lain."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"akses lokasi tepat hanya di latar depan"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Apl ini boleh mendapatkan lokasi tepat anda hanya apabila apl tersebut berada di latar depan. Perkhidmatan lokasi ini mesti dihidupkan dan tersedia pada telefon anda untuk membolehkan apl menggunakan perkhidmatan tersebut. Tindakan ini mungkin meningkatkan penggunaan bateri."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"akses lokasi anggaran (berdasarkan rangkaian) hanya di latar depan"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Apl ini boleh mendapatkan lokasi anda berdasarkan sumber rangkaian seperti menara selular dan rangkaian Wi-Fi, tetapi hanya apabila apl itu di latar depan. Perkhidmatan lokasi ini mesti dihidupkan dan tersedia pada tablet anda untuk membolehkan apl menggunakan perkhidmatan tersebut."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Apl ini boleh mendapatkan lokasi anda berdasarkan sumber rangkaian seperti menara selular dan rangkaian Wi-Fi, tetapi hanya apabila apl itu di latar depan. Perkhidmatan lokasi ini mesti dihidupkan dan tersedia pada peranti Android TV anda untuk membolehkan apl menggunakan perkhidmatan tersebut."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Apl ini boleh mendapatkan lokasi anda berdasarkan sumber rangkaian seperti menara selular dan rangkaian Wi-Fi, tetapi hanya apabila apl itu di latar depan. Perkhidmatan lokasi ini mesti dihidupkan dan tersedia pada telefon anda untuk membolehkan apl menggunakan perkhidmatan tersebut."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Apl ini boleh mendapatkan lokasi tepat anda hanya apabila apl tersebut berada di latar depan. Perkhidmatan lokasi mesti dihidupkan dan tersedia pada peranti anda untuk membolehkan apl menggunakan perkhidmatan tersebut. Tindakan ini mungkin meningkatkan penggunaan bateri."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"akses lokasi anggaran hanya di latar depan"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Apl ini boleh mendapatkan lokasi anggaran anda hanya apabila apl tersebut berada di latar depan. Perkhidmatan lokasi mesti dihidupkan dan tersedia pada peranti anda untuk membolehkan apl menggunakan perkhidmatan tersebut."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"akses lokasi di latar belakang"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Jika tindakan ini dibenarkan bagi akses lokasi anggaran atau lokasi tepat, apl tersebut boleh mengakses lokasi itu semasa berjalan di latar belakang."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Apl ini boleh mengakses lokasi semasa berjalan di latar belakang, di samping akses lokasi di latar depan."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"tukar tetapan audio anda"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Membenarkan apl untuk mengubah suai tetapan audio global seperti kelantangan dan pembesar suara mana digunakan untuk output."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"rakam audio"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Membenarkan apl melihat konfigurasi Bluetooth pada tablet dan untuk membuat serta menerima sambungan dengan peranti yang dipasangkan."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Membenarkan apl melihat konfigurasi Bluetooth pada peranti Android TV anda dan membuat serta menerima sambungan dengan peranti yang digandingkan."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Membenarkan apl melihat konfigurasi Bluetooth pada telefon dan membuat serta menerima sambungan dengan peranti yang dipasangkan."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Maklumat Perkhidmatan Pembayaran NFC Pilihan"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Membenarkan apl mendapatkan maklumat perkhidmatan pembayaran nfc pilihan seperti bantuan berdaftar dan destinasi laluan."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"mengawal Komunikasi Medan Dekat"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Membenarkan apl berkomunikasi dengan teg, kad dan pembaca Komunikasi Medan Dekat (NFC)."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"lumpuhkan kunci skrin anda"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"Pintasan kebolehaksesan menghidupkan <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"Pintasan Kebolehaksesan mematikan <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Tekan dan tahan kedua-dua kekunci kelantangan selama tiga saat untuk menggunakan <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Pilih perkhidmatan yang hendak digunakan apabila anda mengetik butang kebolehaksesan:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Pilih perkhidmatan untuk digunakan dengan gerak isyarat kebolehaksesan (leret ke atas dari bahagian bawah skrin menggunakan dua jari):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Pilih perkhidmatan untuk digunakan dengan gerak isyarat kebolehaksesan (leret ke atas dari bahagian bawah skrin menggunakan tiga jari):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Untuk beralih antara perkhidmatan, sentuh &amp; tahan butang kebolehaksesan."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Untuk beralih antara perkhidmatan, leret ke atas menggunakan dua jari dan tahan."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Untuk beralih antara perkhidmatan, leret ke atas menggunakan tiga jari dan tahan."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Pembesaran"</string>
<string name="user_switched" msgid="7249833311585228097">"Pengguna semasa <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="1912993630661332336">"Bertukar kepada <xliff:g id="NAME">%1$s</xliff:g>…"</string>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Disambungkan ke <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Ketik untuk melihat fail"</string>
<string name="pin_target" msgid="8036028973110156895">"Semat"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Semat <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Nyahsemat"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Nyahsemat <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Maklumat apl"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Memulakan tunjuk cara…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Kemas kini item ini dalam "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> dan <xliff:g id="TYPE_2">%3$s</xliff:g> ?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Simpan"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Tidak, terima kasih"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Bukan sekarang"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Jangan"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Kemas kini"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Teruskan"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"kata laluan"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Togol Skrin Pisah"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Skrin Kunci"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Tangkapan skrin"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"Apl <xliff:g id="APP_NAME">%1$s</xliff:g> dalam tetingkap Timbul."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Bar kapsyen <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 64e2376fe7b3..ff08a592a906 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"အလုပ်ပရိုဖိုင် စီမံခန့်ခွဲရန်အက်ပ် မရှိပါ သို့မဟုတ် ပျက်စီးနေပါသည်။ ထို့ကြောင့် သင်၏ အလုပ်ပရိုဖိုင်နှင့် ဆက်စပ်နေသော ဒေတာများကို ဖျက်လိုက်ပါပြီ။ အကူအညီရယူရန် သင်၏စီမံခန့်ခွဲသူကို ဆက်သွယ်ပါ။"</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"ဤစက်ပစ္စည်းတွင် သင်၏ အလုပ်ပရိုဖိုင်မရှိတော့ပါ"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"စကားဝှက်ထည့်သွင်းရန် ကြိုးစားသည့် အကြိမ်အရေအတွက် အလွန်များသွား၍ ဖြစ်ပါသည်"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"ပုဂ္ဂိုလ်ရေးအသုံးပြုရန်အတွက် စီမံခန့်ခွဲသူက စက်ပစ္စည်းထိန်းချုပ်မှုကို ရပ်တန့်လိုက်သည်"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"စက်ပစ္စည်းကို စီမံခန့်ခွဲထားပါသည်"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"ဤစက်ပစ္စည်းကို သင်၏ အဖွဲ့အစည်းက စီမံပြီး ကွန်ရက်အသွားအလာကို စောင့်ကြည့်နိုင်ပါသည်။ ထပ်မံလေ့လာရန် တို့ပါ။"</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"သင့်ကိရိယာအား ပယ်ဖျက်လိမ့်မည်"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"ထုတ်လွှင့်ခြင်းများ ပြီးဆုံးသွားသည့်နောက် ဆက်လက်တည်ရှိနေသည့် ထုတ်လွှင့်မှုများကို အက်ပ်အား ပို့ခွင့်ပြုသည်။ အလွန်အကျွံအသုံးပြုပါက မှတ်ဉာဏ်အသုံးပြုမှု လွန်ကဲပြီး သင့် Android TV စက်ကို နှေးကွေးစေခြင်း သို့မဟုတ် မတည်ငြိမ်ခြင်းတို့ ဖြစ်စေနိုင်သည်။"</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"အက်ပ်အား ကြာရှည်ခံ ထုတ်လွှင့်မှု ပြုပါ။ ဤထုတ်လွှင့်မှုများဟာ ထုတ်လွှင့်မှု ပြီးဆုံးပြီးသွားတည့်တိုင် ကျန်နေမည် ဖြစ်ပါသည်။ အလွန်အကျွံသုံးခြင်းကြောင့် မှတ်ဉာဏ်အသုံးများပြီး ဖုန်းနှေးခြင်း၊ မတည်ငြိမ်ခြင်း ဖြစ်နိုင်ပါသည်"</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"အဆက်အသွယ်များအား ဖတ်ခြင်း"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"အပလီကေးရှင်းအား ခေါ်ဆိုသော အကြိမ်ရေ၊ အီးမေးလ်အကြိမ်ရေ၊ တခြားဆက်သွယ်မှုများစသည်ကဲ့သို့ သင့်တက်ဘလက်မှာ သိမ်းဆည်းထားသော အဆက်အသွယ်များရဲ့ အချက်အလက်ကို ဖတ်ခွင့်ပြုပါ။ ဤသို့ခွင့်ပြုခြင်းအားဖြင့် အပလီကေးရှင်းများကို သင့် အဆက်အသွယ်၏ အချက်မလက်များကို သိမ်းရန် ခွင့်ပြုပြီး အန္တရာယ်ရှိသော အပလီကေးရှင်းများမှ ထိုအချက်အလက်များ ကို သင် မသိစေပဲ ဖြန့်ဝေနိုင််မည် ဖြစ်ပါသည်။"</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"အချို့သော လူပုဂ္ဂိုလ်များသို့ ခေါ်ဆိုသော၊ အီးမေးလ်ပို့သော သို့မဟုတ် အခြားနည်းလမ်းဖြင့် ဆက်သွယ်သော အကြိမ်ရေများအပါအဝင် သင့် Android TV စက်ပေါ်တွင် သိမ်းဆည်းထားသည့် အဆက်အသွယ်များအကြောင်း ဒေတာများကို အက်ပ်အား မွမ်းမံခွင့်ပြုသည်။ ဤခွင့်ပြုချက်သည် သင်၏ အဆက်အသွယ်ဒေတာကို အက်ပ်အား သိမ်းခွင့်ပေးသောကြောင့် သံသယဖြစ်ဖွယ်အက်ပ်များသည် သင်မသိဘဲ အဆက်အသွယ်ဒေတာများကို မျှဝေနိုင်သည်။"</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"အပလီကေးရှင်းအား ခေါ်ဆိုသော အကြိမ်ရေ၊ အီးမေးလ်အကြိမ်ရေ၊ တခြားဆက်သွယ်မှုများစသည်ကဲ့သို့ သင့်ဖုန်းမှာ သိမ်းဆည်းထားသော အဆက်အသွယ်များရဲ့ အချက်အလက်ကို ဖတ်ခွင့်ပြုပါ။ ဤသို့ခွင့်ပြုခြင်းအားဖြင့် အပလီကေးရှင်းများကို သင့် အဆက်အသွယ်၏ အချက်မလက်များကို သိမ်းရန် ခွင့်ပြုပြီး အန္တရာယ်ရှိသော အပလီကေးရှင်းများမှ ထိုအချက်အလက်များ ကို သင် မသိစေပဲ ဖြန့်ဝေနိုင််မည် ဖြစ်ပါသည်။"</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"သင့်တက်ဘလက်ထဲတွင် သိမ်းဆည်းထားသော အဆက်အသွယ်များ၏ အချက်အလက်ကို အက်ပ်အား ဖတ်ခွင့်ပြုသည်။ အက်ပ်သည် သင့်တက်ဘလက် မှတစ်ဆင့် အဆက်အသွယ်များကို ပြုလုပ်ထားသော အကောင့်များကို အသုံးပြုခွင့် ရလိမ့်မည်။ သင်ထည့်သွင်းထားသော အက်ပ်များမှတစ်ဆင့် ပြုလုပ်ထားသော အကောင့်များ ပါဝင်နိုင်ပါသည်။ ဤခွင့်ပြုချက်က သင့်အဆက်အသွယ်၏ အချက်အလက်များကို အက်ပ်များအား သိမ်းခွင့်ပြုပြီး အန္တရာယ်ရှိသော အက်ပ်များက ထိုအချက်အလက်များကို သင်မသိဘဲ ဖြန့်ဝေနိုင်သည်။"</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"သင်၏ Android TV ထဲတွင် သိမ်းဆည်းထားသော အဆက်အသွယ်များ၏ အချက်အလက်ကို အက်ပ်အား ဖတ်ခွင့်ပြုသည်။ အက်ပ်သည် သင့် Android TV မှတစ်ဆင့် အဆက်အသွယ်များကို ပြုလုပ်ထားသော အကောင့်များကို အသုံးပြုခွင့် ရလိမ့်မည်။ သင်ထည့်သွင်းထားသော အက်ပ်များမှတစ်ဆင့် ပြုလုပ်ထားသော အကောင့်များ ပါဝင်နိုင်ပါသည်။ ဤခွင့်ပြုချက်က သင့်အဆက်အသွယ်၏ အချက်အလက်များကို အက်ပ်များအား သိမ်းခွင့်ပြုပြီး အန္တရာယ်ရှိသော အက်ပ်များက ထိုအချက်အလက်များကို သင်မသိဘဲ ဖြန့်ဝေနိုင်သည်။"</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"သင်၏ ဖုန်းထဲတွင် သိမ်းဆည်းထားသော အဆက်အသွယ်များ၏ အချက်အလက်ကို အက်ပ်အား ဖတ်ခွင့်ပြုသည်။ အက်ပ်သည် သင့်ဖုန်းမှတစ်ဆင့် အဆက်အသွယ်များကို ပြုလုပ်ထားသော အကောင့်များကို အသုံးပြုခွင့် ရလိမ့်မည်။ သင်ထည့်သွင်းထားသော အက်ပ်များမှတစ်ဆင့် ပြုလုပ်ထားသော အကောင့်များ ပါဝင်နိုင်ပါသည်။ ဤခွင့်ပြုချက်က သင့်အဆက်အသွယ်၏ အချက်အလက်များကို အက်ပ်များအား သိမ်းခွင့်ပြုပြီး အန္တရာယ်ရှိသော အက်ပ်များက ထိုအချက်အလက်များကို သင်မသိဘဲ ဖြန့်ဝေနိုင်သည်။"</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"အဆက်အသွယ်များအား ပြင်ဆင်ခြင်း"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"အပလီကေးရှင်းအား သင့်တက်ဘလက်မှာ သိမ်းဆည်းထားသော အဆက်အသွယ်များရဲ့ အချက်အလက် (အထူးအဆက်အသွယ်များအား ခေါ်ဆိုသော အကြိမ်ရေ၊ အီးမေးလ်ပို့သောအကြိမ်ရေ သို့ အခြားနည်းလမ်းဖြင့်ဆက်သွယ်မှုများ) ကို ပြင်ဆင်ခွင့်ပြုခြင်း။ ဒီခွင့်ပြုချက်က အပလီကေးရှင်းများအား အဆက်အသွယ် အချက်အလက်များ ဖျက်စီးခြင်း လုပ်ဆောင်စေနိုင်မှာ ဖြစ်ပါသည်။"</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"အချို့သော အဆက်အသွယ်များသို့ ခေါ်ဆိုသော၊ အီးမေးလ်ပို့သော သို့မဟုတ် အခြားနည်းလမ်းဖြင့် ဆက်သွယ်သော အကြိမ်ရေများအပါအဝင် သင့် Android TV စက်ပေါ်တွင် သိမ်းဆည်းထားသည့် အဆက်အသွယ်များအကြောင်း ဒေတာများကို အက်ပ်အား မွမ်းမံခွင့်ပြုသည်။ ဤခွင့်ပြုချက်သည် အဆက်အသွယ်ဒေတာကို အက်ပ်အား ဖျက်ခွင့်ပေးသည်။"</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"အပလီကေးရှင်းအား သင့်ဖုန်းမှာ သိမ်းဆည်းထားသော အဆက်အသွယ်များရဲ့ အချက်အလက် (အထူးအဆက်အသွယ်များအား ခေါ်ဆိုသော အကြိမ်ရေ၊ အီးမေးလ်ပို့သောအကြိမ်ရေ သို့ အခြားနည်းလမ်းဖြင့်ဆက်သွယ်မှုများ) ကို ပြင်ဆင်ခွင့်ပြုခြင်း။ ဒီခွင့်ပြုချက်က အပလီကေးရှင်းများအား အဆက်အသွယ် အချက်အလက်များ ဖျက်စီးခြင်း လုပ်ဆောင်စေနိုင်မှာ ဖြစ်ပါသည်။"</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"သင့်တက်ဘလက်တွင် သိမ်းဆည်းထားသော အဆက်အသွယ်များ၏ အချက်အလက်ကို ပြင်ဆင်ရန် အက်ပ်အား ခွင့်ပြုပါ။ ဤခွင့်ပြုချက်က အက်ပ်အား သင့်အဆက်အသွယ်များ၏ အချက်အလက်ကို ဖျက်ခွင့်ပြုသည်။"</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"သင့် Android TV တွင် သိမ်းဆည်းထားသော အဆက်အသွယ်များ၏ အချက်အလက်ကို ပြင်ဆင်ရန် အက်ပ်အား ခွင့်ပြုပါ။ ဤခွင့်ပြုချက်က အက်ပ်အား သင့်အဆက်အသွယ်များ၏ အချက်အလက်ကို ဖျက်ခွင့်ပြုသည်။"</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"သင့်ဖုန်းတွင် သိမ်းဆည်းထားသော အဆက်အသွယ်များ၏ အချက်အလက်ကို ပြင်ဆင်ရန် အက်ပ်အား ခွင့်ပြုပါ။ ဤခွင့်ပြုချက်က အက်ပ်အား သင့်အဆက်အသွယ်များ၏ အချက်အလက်ကို ဖျက်ခွင့်ပြုသည်။"</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"ခေါ်ဆိုမှု မှတ်တမ်းအား ဖတ်ခြင်း"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"ဤအက်ပ်သည် သင့်ခေါ်ဆိုမှုမှတ်တမ်းကို ကြည့်ရှုနိုင်ပါသည်။"</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"ခေါ်ဆိုမှုမှတ်တမ်း ရေးသားခြင်း"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"တည်နေရာပံ့ပိုးမှုညွှန်ကြားချက်အပိုအား ဝင်ရောက်ကြည့်ခြင်း"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"အက်ပ်အား တည်နေရာ စီမံပေးရေး ညွှန်ကြားချက် အပိုများကို ရယူခွင့်ပြုသည်။ သို့ဖြစ်၍ အက်ပ်သည် GPS သို့မဟုတ် အခြား တည်နေရာ ရင်းမြစ်ကို သုံးကြသူတို့၏ လုပ်ငန်းများကို ဝင်စွက်ခွင့် ပြုနိုင်သည်။"</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"မျက်နှာစာတွင်သာ တည်နေရာအတိအကျ အသုံးပြုခြင်း"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"မျက်နှာစာတွင် ဖွင့်ထားမှသာ ဤအက်ပ်က သင်၏တည်နေရာအတိအကျကို ရယူနိုင်ပါသည်။ သင်၏ဖုန်းတွင် အက်ပ်ကအသုံးပြုရန်အတွက် ဤတည်နေရာဝန်ဆောင်မှုများကို ဖွင့်ထားပြီး အသုံးပြု၍ ရပါမည်။ ၎င်းက ဘက်ထရီ ပိုကုန်နိုင်ပါသည်။"</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"မျက်နှာစာတွင်သာ (ကွန်ရက် အခြေပြု) တည်နေရာခန့်မှန်း အသုံးပြုခြင်း"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"ဤအက်ပ်က ဆဲလ်တာဝါများနှင့် Wi-Fi ကွန်ရက်များကဲ့သို့ ကွန်ရက်ရင်းမြစ်များအပေါ် အခြေခံပြီး သင်၏တည်နေရာကို ရယူနိုင်သော်လည်း အက်ပ်ကို မျက်နှာစာတွင်ဖွင့်ထားမှ ရပါမည်။ အက်ပ်က အသုံးပြုနိုင်ရန်အတွက် ဤတည်နေရာ ဝန်ဆောင်မှုများကို ဖွင့်ထားရမည် ဖြစ်ပြီး သင့်တက်ဘလက်ပေါ်တွင် ရရှိနိုင်ရပါမည်။"</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"ဤအက်ပ်သည် ဆဲလ်တာဝါများနှင့် Wi-Fi ကွန်ရက်များကဲ့သို့ ကွန်ရက်ရင်းမြစ်များပေါ်တွင် အခြေခံပြီး သင်၏တည်နေရာကို ရယူနိုင်သည်၊ သို့သော် အက်ပ်ကို မျက်နှာစာတွင်ဖွင့်ထားရပါမည်။ အက်ပ်က အသုံးပြုနိုင်ရန်အတွက် ဤတည်နေရာ ဝန်ဆောင်မှုများကို ဖွင့်ထားရမည် ဖြစ်ပြီး သင့် Android TV ပေါ်တွင် ရှိမှသာ သုံးနိုင်ပါမည်။"</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"ဤအက်ပ်က ဆဲလ်တာဝါများနှင့် Wi-Fi ကွန်ရက်များကဲ့သို့ ကွန်ရက်ရင်းမြစ်များအပေါ် အခြေခံပြီး သင်၏တည်နေရာကို ရယူနိုင်သော်လည်း အက်ပ်ကို မျက်နှာစာတွင်ဖွင့်ထားမှ ရပါမည်။ အက်ပ်က အသုံးပြုနိုင်ရန်အတွက် ဤတည်နေရာ ဝန်ဆောင်မှုများကို ဖွင့်ထားရမည် ဖြစ်ပြီး သင့်ဖုန်းပေါ်တွင် ရရှိနိုင်ရပါမည်။"</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"မျက်နှာစာတွင် ဖွင့်ထားမှသာ ဤအက်ပ်က သင်၏ တည်နေရာအတိအကျကို ရယူနိုင်ပါသည်။ သင်၏ စက်တွင် အက်ပ်ကအသုံးပြုရန်အတွက် တည်နေရာဝန်ဆောင်မှုများကို ဖွင့်ထားပြီးမှ အသုံးပြု၍ ရပါမည်။ ၎င်းက ဘက်ထရီ ပိုကုန်နိုင်ပါသည်။"</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"မျက်နှာစာတွင်သာ ခန့်မှန်းခြေ တည်နေရာ အသုံးပြုခြင်း"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"မျက်နှာစာတွင် ဖွင့်ထားမှသာ ဤအက်ပ်က သင်၏ အနီးစပ်ဆုံးတည်နေရာကို ရယူနိုင်ပါသည်။ အက်ပ်က ဤတည်နေရာဝန်ဆောင်မှုများကို အသုံးပြုရန်အတွက် သင်၏စက်တွင် ၎င်းတို့ရှိနေပြီး ဖွင့်ထားရပါမည်။"</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"နောက်ခံတွင် တည်နေရာကို အသုံးပြုရန်"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"ခန့်မှန်းခြေ သို့မဟုတ် တိကျသော တည်နေရာ ဝင်သုံးခွင့်အတွက် ၎င်းကို နောက်ဆက်တွဲ ခွင့်ပြုထားပါက နောက်ခံတွင် လုပ်ဆောင်နေစဉ် အက်ပ်က တည်နေရာကို ရယူအသုံးပြုနိုင်ပါသည်။"</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"နောက်ခံတွင် လုပ်ဆောင်နေစဉ် ဤအက်ပ်က တည်နေရာကို ရယူအသုံးပြုနိုင်သည်သာမက မျက်နှာစာတည်နေရာကိုပါ အသုံးပြုနိုင်မည်။"</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"သင့်အသံအပြင်အဆင်အားပြောင်းခြင်း"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"အပလီကေးရှင်းအား အသံအတိုးအကျယ်နှင့် အထွက်ကို မည်သည့်စပီကာကို သုံးရန်စသည်ဖြင့် စက်တစ်ခုလုံးနှင့်ဆိုင်သော အသံဆိုင်ရာ ဆက်တင်များ ပြင်ဆင်ခွင့် ပြုရန်"</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"အသံဖမ်းခြင်း"</string>
@@ -494,6 +491,8 @@
<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_preferredPaymentInfo" msgid="5274423844767445054">"ဦးစားပေး NFC ငွေပေးချေမှုဆိုင်ရာ ဝန်ဆောင်မှု အချက်အလက်များ"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"အက်ပ်အား ဦစားပေး NFC ငွေပေးချေမှုဆိုင်ရာ ဝန်ဆောင်မှု အချက်အလက်များဖြစ်သည့် မှတ်ပုံတင်ထားသော အကူအညီများနှင့် သွားလာရာ လမ်းကြောင်းတို့ကို ရယူရန် ခွင့်ပြုသည်။"</string>
<string name="permlab_nfc" msgid="1904455246837674977">"Near Field Communicationအား ထိန်းချုပ်ရန်"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"အက်ပ်အား တာတို စက်ကွင်း ဆက်သွယ်ရေး (NFC) တဲဂ်များ၊ ကဒ်များ နှင့် ဖတ်ကြသူတို့နှင့် ဆက်သွယ်ပြောဆိုခွင့် ပြုသည်။"</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"ဖန်သားပြင် သော့ချခြင်းအား မလုပ်နိုင်အောင် ပိတ်ရန်"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"အများသုံးစွဲနိုင်မှု ဖြတ်လမ်းလင့်ခ်သည် <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ကို ဖွင့်လိုက်ပါသည်"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"အများသုံးစွဲနိုင်မှု ဖြတ်လမ်းလင့်ခ်သည် <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>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"အများသုံးစွဲနိုင်မှု ခလုတ်ကို တို့သည့်အခါ အသုံးပြုမည့် ဝန်ဆောင်မှုကို ရွေးချယ်ပါ−"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"အများသုံးစွဲနိုင်မှုလက်ဟန်ဖြင့် အသုံးပြုရန် ဝန်ဆောင်မှုတစ်ခုကို ရွေးပါ (မျက်နှာပြင်အောက်ခြေမှနေ၍ လက်နှစ်ချောင်းဖြင့် အပေါ်သို့ ပွတ်ဆွဲပါ)-"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"အများသုံးစွဲနိုင်မှုလက်ဟန်ဖြင့် အသုံးပြုရန် ဝန်ဆောင်မှုတစ်ခုကို ရွေးပါ (မျက်နှာပြင်အောက်ခြေမှနေ၍ လက်သုံးချောင်းဖြင့် အပေါ်သို့ ပွတ်ဆွဲပါ)-"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"ဝန်ဆောင်မှုများအကြား ပြောင်းရန် အများသုံးစွဲနိုင်မှုခလုတ်ကို ဖိထားပါ။"</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"ဝန်ဆောင်မှုများအကြား ပြောင်းရန် လက်နှစ်ချောင်းဖြင့် အပေါ်သို့ ပွတ်ဆွဲပြီး ဖိထားပါ။"</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"ဝန်ဆောင်မှုများအကြား ပြောင်းရန် လက်သုံးချောင်းဖြင့် အပေါ်သို့ ပွတ်ဆွဲပြီး ဖိထားပါ။"</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>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> ချိတ်ဆက်ထားသည်"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"ဖိုင်များကိုကြည့်ရန် တို့ပါ"</string>
<string name="pin_target" msgid="8036028973110156895">"တွဲပါ"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"<xliff:g id="LABEL">%1$s</xliff:g> ကို ပင်ထိုးရန်"</string>
<string name="unpin_target" msgid="3963318576590204447">"ဖြုတ်ပါ"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"<xliff:g id="LABEL">%1$s</xliff:g> ကို ပင်ဖြုတ်ရန်"</string>
<string name="app_info" msgid="6113278084877079851">"အက်ပ်အချက်အလက်"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"သရုပ်ပြချက်ကို စတင်နေသည်…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"ဤအချက်အလက်များကို "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"တွင် အပ်ဒိတ်လုပ်လိုပါသလား- <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>။"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"သိမ်းရန်"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"မလိုပါ"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"ယခုမလုပ်ပါ"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"ဘယ်တော့မှ"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"အပ်ဒိတ်လုပ်ရန်"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"ရှေ့ဆက်ရန်"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"စကားဝှက်"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"မျက်နှာပြင် ခွဲ၍ပြသခြင်းကို နှိပ်ပါ"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"လော့ခ်မျက်နှာပြင်"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"ဖန်သားပြင်ဓာတ်ပုံ"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"ပေါ့ပ်အပ်ဝင်းဒိုးတွင်ရှိသော <xliff:g id="APP_NAME">%1$s</xliff:g>အက်ပ်။"</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g>၏ ခေါင်းစီး ဘား။"</string>
</resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 69e341ecc845..aa28bf2b9644 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Administratorappen for jobbprofilen mangler eller er skadet. Dette har ført til at jobbprofilen og alle data knyttet til den, har blitt slettet. Ta kontakt med administratoren for å få hjelp."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Jobbprofilen din er ikke lenger tilgjengelig på denne enheten"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"For mange passordforsøk"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Administratoren overførte enheten til personlig bruk"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Enheten administreres"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Organisasjonen din kontrollerer denne enheten og kan overvåke nettverkstrafikk. Trykk for å få mer informasjon."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Enheten blir slettet"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Lar appen sende varige kringkastinger («sticky broadcasts»), som ikke avsluttes etter at kringkastingen er over. Overdreven bruk kan gjøre Android TV-enheten din treg eller ustabil ved at den bruker for mye minne."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Lar appen sende faste kringkastinger («sticky broadcasts») som blir værende etter at kringkastingen er over. Overdreven bruk kan gjøre telefonen treg eller ustabil ved å bruke for mye minne."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"lese kontaktene dine"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Lar appen lese informasjon om kontaktene lagret på nettbrettet ditt, inkludert hvor ofte du har ringt, sendt e-post til, eller på andre måter kommunisert med spesifikke personer. Denne tillatelsen lar apper lagre kontaktdata. Merk at skadelige apper kan dele disse dataene uten at du vet om det."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Lar appen lese data om kontaktene som er lagret på Android TV-enheten din, inkludert hvor hyppig du har ringt, sendt e-post eller på andre måter har kommunisert med bestemte kontakter. Denne tillatelsen lar apper lagre kontaktdata, og skadelige apper kan dele dem uten ditt samtykke."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Lar appen lese informasjon om kontaktene lagret på telefonen din, inkludert hvor ofte du har ringt, sendt e-post til eller på andre måter kommunisert med spesifikke personer. Denne tillatelsen lar apper lagre kontaktdata. Merk at skadelige apper kan dele disse dataene uten at du vet om det."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Lar appen lese data om kontaktene dine som er lagret på nettbrettet ditt. Apper får også tilgang til kontoene på nettbrettet ditt som har opprettet kontakter. Dette kan inkludere kontoer som er opprettet av apper du har installert. Denne tillatelsen lar apper lagre kontaktdataene dine. Vær oppmerksom på at skadelige apper kan dele disse dataene uten at du vet om det."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Lar appen lese data om kontaktene dine som er lagret på Android TV-enheten din. Apper får også tilgang til kontoene på Android TV-enheten din som har opprettet kontakter. Dette kan inkludere kontoer som er opprettet av apper du har installert. Denne tillatelsen lar apper lagre kontaktdataene dine. Vær oppmerksom på at skadelige apper kan dele disse dataene uten at du vet om det."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Lar appen lese data om kontaktene dine som er lagret på telefonen din. Apper får også tilgang til kontoene på telefonen din som har opprettet kontakter. Dette kan inkludere kontoer som er opprettet av apper du har installert. Denne tillatelsen lar apper lagre kontaktdataene dine. Vær oppmerksom på at skadelige apper kan dele disse dataene uten at du vet om det."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"endre kontaktene dine"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Lar appen endre informasjon om kontaktene lagret på nettbrettet ditt, inkludert hvor ofte du har ringt, sendt e-post til eller på andre måter kommunisert med bestemte kontakter. Denne tillatelsen lar apper slette kontaktdata."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Lar appen endre informasjon om kontaktene som er lagret på Android TV-enheten din, inkludert hvor ofte du har ringt, sendt e-post til eller på andre måter kommunisert med bestemte kontakter. Denne tillatelsen lar apper slette kontaktdata."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Lar appen endre informasjon om kontaktene lagret på telefonen din, inkludert hvor ofte du har ringt, sendt e-post til eller på andre måter kommunisert med bestemte kontakter. Denne tillatelsen lar apper slette kontaktdata."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Lar appen endre informasjon om kontaktene som er lagret på nettbrettet ditt. Denne tillatelsen lar apper slette kontaktdata."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Lar appen endre informasjon om kontaktene som er lagret på Android TV-enheten din. Denne tillatelsen lar apper slette kontaktdata."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Lar appen endre informasjon om kontaktene som er lagret på telefonen din. Denne tillatelsen lar apper slette kontaktdata."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"lese anropsloggen"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Denne appen kan lese anropsloggen din."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"endre anropsloggen"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"bruke ekstra posisjonskommandoer"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Appen gis tillatelse til å bruke ekstra kommandoer fra posisjonsleverandører. Dette kan gi appen tillatelse til å påvirke bruken av GPS eller andre posisjonskilder."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"bare tilgang til nøyaktig posisjon i forgrunnen"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Denne appen kan bare få den nøyaktige posisjonen din når den er på i forgrunnen. Disse posisjonstjenestene må være slått på og tilgjengelige på telefonen din for at appen skal kunne bruke dem. Dette kan øke batteriforbruket."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"bare tilgang til omtrentlig posisjon (nettverksbasert) i forgrunnen"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Denne appen kan bare få posisjonen din basert på nettverkskilder, for eksempel mobilmaster og Wi-Fi-nettverk, når den er på i forgrunnen. Disse posisjonstjenestene må være slått på og tilgjengelige på nettbrettet ditt for at appen skal kunne bruke dem."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Denne appen kan bare få posisjonen din basert på nettverkskilder, for eksempel mobilmaster og Wi-Fi-nettverk, når den er på i forgrunnen. Disse posisjonstjenestene må være slått på og tilgjengelige på Android TV-en din for at appen skal kunne bruke dem."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Denne appen kan bare få posisjonen din basert på nettverkskilder, for eksempel mobilmaster og Wi-Fi-nettverk, når den er på i forgrunnen. Disse posisjonstjenestene må være slått på og tilgjengelige på telefonen din for at appen skal kunne bruke dem."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Denne appen kan bare få den nøyaktige posisjonen din når den er på i forgrunnen. Posisjonstjenestene må være slått på og tilgjengelige på enheten din for at appen skal kunne bruke dem. Dette kan øke batteriforbruket."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"bare tilgang til omtrentlig posisjon i forgrunnen"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Denne appen kan bare få den omtrentlige posisjonen din når den er i forgrunnen. Posisjonstjenestene må være slått på og tilgjengelige på enheten din for at appen skal kunne bruke dem."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"tilgang til posisjon i bakgrunnen"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Hvis du gir denne tillatelsen, får appen tilgang til posisjonen mens den kjører i bakgrunnen, i tillegg til tilgang til omtrentlig eller presis posisjon."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Denne appen har tilgang til posisjon når den kjører i bakgrunnen, i tillegg til tilgang til posisjonen i forgrunnen."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"endre lydinnstillinger"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Lar appen endre globale lydinnstillinger slik som volum og hvilken høyttaler som brukes for lydavspilling."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"ta opp lyd"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Lar appen se Bluetooth-konfigurasjonen på nettbrettet, samt opprette og godta tilkoblinger med sammenkoblede enheter."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Lar appen se Bluetooth-konfigurasjonen på Android TV-enheten din samt opprette og godta tilkoblinger med sammenkoblede enheter."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Lar appen se Bluetooth-konfigurasjonen på telefonen, samt opprette og godta tilkoblinger med sammenkoblede enheter."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Informasjon om prioritert NFC-betalingstjeneste"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Gir appen tilgang til informasjon om prioritert NFC-betalingstjeneste, for eksempel registrerte hjelpemidler og destinasjon."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"kontroller overføring av data med NFC-teknologi"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Lar appen kommunisere med etiketter, kort og lesere som benytter NFC-teknologi."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"deaktivere skjermlåsen"</string>
@@ -846,7 +845,7 @@
<string name="lockscreen_failed_attempts_now_wiping" product="tv" msgid="2205435033340091883">"Du har prøvd å låse opp Android TV-enheten din <xliff:g id="NUMBER">%d</xliff:g> ganger. Android TV-enheten din tilbakestilles nå til fabrikkstandard."</string>
<string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="2203704707679895487">"Du har foretatt <xliff:g id="NUMBER">%d</xliff:g> mislykkede opplåsinger av telefonen. Telefonen blir nå tilbakestilt til fabrikkinnstillingene."</string>
<string name="lockscreen_too_many_failed_attempts_countdown" msgid="6807200118164539589">"Prøv igjen om <xliff:g id="NUMBER">%d</xliff:g> sekunder."</string>
- <string name="lockscreen_forgot_pattern_button_text" msgid="8362442730606839031">"Glemt mønsteret?"</string>
+ <string name="lockscreen_forgot_pattern_button_text" msgid="8362442730606839031">"Har du glemt mønsteret?"</string>
<string name="lockscreen_glogin_forgot_pattern" msgid="9218940117797602518">"Opplåsing av konto"</string>
<string name="lockscreen_glogin_too_many_attempts" msgid="3775904917743034195">"For mange forsøk på tegning av mønster"</string>
<string name="lockscreen_glogin_instructions" msgid="4695162942525531700">"Logg på med Google-kontoen din for å låse opp."</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"Snarveien for tilgjengelighet slo på <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"Snarveien for tilgjengelighet slo av <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Trykk og hold inne begge volumtastene i tre sekunder for å bruke <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Velg en tjeneste du vil bruke når du trykker på Tilgjengelighet-knappen:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Velg en tjeneste du vil bruke med tilgjengelighetsbevegelsen (sveip opp fra bunnen av skjermen med to fingre):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Velg en tjeneste du vil bruke med tilgjengelighetsbevegelsen (sveip opp fra bunnen av skjermen med tre fingre):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"For å bytte mellom tjenester, trykk og hold på Tilgjengelighet-knappen."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"For å bytte mellom tjenester, sveip opp med to fingre og hold."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"For å bytte mellom tjenester, sveip opp med tre fingre og hold."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Forstørring"</string>
<string name="user_switched" msgid="7249833311585228097">"Gjeldende bruker: <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="1912993630661332336">"Bytter til <xliff:g id="NAME">%1$s</xliff:g> …"</string>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Koblet til <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Trykk for å se filer"</string>
<string name="pin_target" msgid="8036028973110156895">"Fest"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Fest <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Løsne"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Løsne <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Info om appen"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Starter demo …"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Vil du oppdatere disse elementene i "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> og <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Lagre"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Nei takk"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Ikke nå"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Aldri"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Oppdater"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Fortsett"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"passord"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Slå delt skjerm av/på"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Låseskjerm"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Skjermdump"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"<xliff:g id="APP_NAME">%1$s</xliff:g>-appen i forgrunnsvindu."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Tekstingsfelt i <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 0fb2213eea21..d7e121cac6fb 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"उक्त कार्य प्रोफाइलको प्रशासकीय अनुप्रयोग छैन वा बिग्रेको छ। त्यसले गर्दा, तपाईंको कार्य प्रोफाइल र सम्बन्धित डेटालाई मेटिएको छ। सहायताका लागि आफ्ना प्रशासकलाई सम्पर्क गर्नुहोस्।"</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"तपाईंको कार्य प्रोफाइल अब उप्रान्त यस यन्त्रमा उपलब्ध छैन"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"पासवर्ड प्रविष्ट गर्ने अत्यधिक गलत प्रयासहरू भए"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"व्यवस्थापकले यन्त्रलाई व्यक्तिगत प्रयोगका लागि अस्वीकार गर्नुभयो"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"यन्त्र व्यवस्थित गरिएको छ"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"तपाईंको संगठनले यस यन्त्रको व्यवस्थापन गर्दछ र नेटवर्क ट्राफिकको अनुगमन गर्न सक्छ। विवरणहरूका लागि ट्याप गर्नुहोस्।"</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"तपाईंको यन्त्र मेटिनेछ"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"अनुप्रयोगलाई प्रसारण समाप्त भइसकेपछि पनि रहिरहने स्टिकी प्रसारणहरू पठाउने अनुमति दिन्छ। यो सुविधाको अत्यधिक प्रयोगले धेरै मेमोरी प्रयोग हुने भएकाले तपाईंको Android TV यन्त्र सुस्त वा अस्थिर हुन सक्छ।"</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"औपचारिक प्रसारणलाई पठाउनको लागि एक अनुप्रयोगलाई अनुमति दिन्छ, जुन प्रसारण समाप्त भएपछि बाँकी रहन्छ। अत्यधिक प्रयोगले धेरै मेमोरी प्रयोग गरेको कारणले फोनलाई ढिलो र अस्थिर बनाउन सक्छ।"</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"तपाईँका सम्पर्कहरू पढ्नुहोस्"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"अनुप्रयोगलाई निर्दिष्ट व्यक्तिगतसँग अन्य तरिकाहरूबाट कल गर्नु भएका, इमेल गर्नु भएका वा अन्तर्क्रिया गर्नुभएका आवृतिसहितको तपाईंको ट्याब्लेटमा भण्डारण गरिएका सम्पर्कहरूको डेटा पढ्न अनुमति दिन्छ। यो अनुमतिले तपाईंको सम्पर्क डेटा बचत गर्न अनुमति दिन्छ, र खराब अनुप्रयोगहरूले तपाईंको जानकारी बिना सम्पर्क डेटा साझेदारी गर्न सक्दछन्।"</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"अनुप्रयोगलाई तपाईंले निश्चित व्यक्तिहरूलाई कति पटक फोन, इमेल वा अन्य तरिकाले सम्पर्क गर्नुभयो भन्ने डेटासहित तपाईंको Android TV यन्त्रमा भण्डार गरिएका सम्पर्क ठेगानाहरूसँग सम्बन्धित डेटा पढ्ने अनुमति दिन्छ। यस अनुमतिले अनुप्रयोगहरूलाई तपाईंको सम्पर्क ठेगानासम्बन्धी डेटा सुरक्षित गर्न दिने भएकाले हानिकारक अनुप्रयोगहरूले सम्पर्क ठेगानासम्बन्धी डेटा आदान प्रदान गर्न सक्छन्।"</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"तपाईँले विशेष व्यक्तिहरूसँग अर्को तरिकाबाट कल गर्नुभएका, इमेल गर्नुभएका वा संचार गर्नुभएका आवृतिसहित तपाईँको फोनमा भण्डारण भएका डेटाको बारेमा पढ्नको लागि अनुप्रयोगलाई अनुमति दिन्छ। यो अनुमतिले अनुप्रयोगलाई तपाईँको सम्पर्क डेटा बचत गर्नको लागि अनुमति दिन्छ, र तपाईँको ज्ञान बिना नै खराब अनुप्रयोगहरूले सायद सम्पर्क डेटा साझेदारी गर्न सक्छन्।"</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"अनुप्रयोगलाई तपाईंको ट्याब्लेटमा भण्डार गरिएका सम्पर्क ठेगानाहरूसँग सम्बन्धित डेटा पढ्ने अनुमति दिन्छ। अनुप्रयोगहरूले सम्पर्क ठेगानाहरू बनाउने तपाईंको ट्याब्लेटमा भण्डार गरिएका खाताहरूमाथि पनि पहुँच प्राप्त गर्ने छन्। यसमा तपाईंले स्थापना गरेका अनुप्रयोगहरूले बनाएका खाताहरू पर्न सक्छन्। यस अनुमतिले अनुप्रयोगहरूलाई तपाईंको सम्पर्क ठेगानासम्बन्धी डेटा सुरक्षित गर्न दिने भएकाले हानिकारक अनुप्रयोगहरूले तपाईंलाई थाहै नदिइकन सम्पर्क ठेगानासम्बन्धी डेटा आदान प्रदान गर्न सक्छन्।"</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"अनुप्रयोगलाई तपाईंको Android TV यन्त्रमा भण्डारण गरिएका सम्पर्क ठेगानासम्बन्धी डेटा पढ्न अनुमति दिन्छ। अनुप्रयोगहरूले सम्पर्क ठेगानाहरू बनाउने तपाईंको Android TV यन्त्रमा भण्डार गरिएका खाताहरूमाथि पनि पहुँच प्राप्त गर्ने छन्। यसमा तपाईंले स्थापना गरेका अनुप्रयोगहरूले बनाएका खाताहरू पर्न सक्छन्। यस अनुमतिले अनुप्रयोगहरूलाई तपाईंको सम्पर्क ठेगानासम्बन्धी डेटा सुरक्षित गर्न दिने भएकाले हानिकारक अनुप्रयोगहरूले तपाईंलाई थाहै नदिइकन सम्पर्क ठेगानासम्बन्धी डेटा आदान प्रदान गर्न सक्छन्।"</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"अनुप्रयोगलाई तपाईंको फोनमा भण्डार गरिएका सम्पर्क ठेगानाहरूसँग सम्बन्धित डेटा पढ्ने अनुमति दिन्छ। अनुप्रयोगहरूले सम्पर्क ठेगानाहरू बनाउने तपाईंको फोनमा भण्डार गरिएका खाताहरूमाथि पनि पहुँच प्राप्त गर्ने छन्। यसमा तपाईंले स्थापना गरेका अनुप्रयोगहरूले बनाएका खाताहरू पर्न सक्छन्। यस अनुमतिले अनुप्रयोगहरूलाई तपाईंको सम्पर्क ठेगानासम्बन्धी डेटा सुरक्षित गर्न दिने भएकाले हानिकारक अनुप्रयोगहरूले तपाईंलाई थाहै नदिइकन सम्पर्क ठेगानासम्बन्धी डेटा आदान प्रदान गर्न सक्छन्।"</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"तपाईँका सम्पर्कहरू परिवर्तन गर्नुहोस्"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"अन्य तरिकाका आवृतिहरूसँग जुन तपाईँले कल, इमेल, वा विशेष सम्पर्क गर्नुभएकासहित तपाईँको ट्याब्लेटमा भण्डारण भएका सम्पर्कहरूको बारेको डेटालाई परिवर्तन गर्नको लागि अनुप्रयोगलाई अनुमति दिन्छ। यस अनुमतिले सम्पर्क डेटालाई मेटाउनको लागि अनुमति दिन्छ।"</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"अनुप्रयोगलाई तपाईंले सम्पर्क सूचीमा भएका निश्चित व्यक्तिहरूलाई कति पटक फोन, इमेल वा अन्य तरिकाले सम्पर्क गर्नुभयो भन्ने डेटासहित तपाईंको Android TV यन्त्रमा भण्डार गरिएका सम्पर्क ठेगानाहरूसँग सम्बन्धित डेटा परिमार्जन गर्ने अनुमति दिन्छ। यस अनुमतिले अनुप्रयोगहरूलाई सम्पर्क ठेगानासम्बन्धी डेटा मेट्न दिन्छ।"</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"तपाईँले बारम्बार कल गरेका, इमेल गरेका, वा विशेष सम्पर्कहरूसँग सञ्चार गरेका सहित तपाईँको फोनमा भण्डारण गरेका तपाईँका सम्पर्कहरू परिमार्जन गर्न अनुप्रयोगलाई अनुमति दिन्छ। यो अनुमतिले अनुप्रयोगलाई सम्पर्क डेटा मेटाउन दिन्छ।"</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"अनुप्रयोगलाई तपाईंको ट्याब्लेटमा भण्डारण गरिएका सम्पर्क ठेगानासम्बन्धी डेटा परिमार्जन गर्न अनुमति दिन्छ। यो अनुमतिले अनुप्रयोगलाई सम्पर्क ठेगानासम्बन्धी डेटा मेटाउन अनुमति दिन्छ।"</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"अनुप्रयोगलाई तपाईंको Android TV यन्त्रमा भण्डारण गरिएका सम्पर्क ठेगानासम्बन्धी डेटा परिमार्जन गर्न अनुमति दिन्छ। यो अनुमतिले अनुप्रयोगलाई सम्पर्क ठेगानासम्बन्धी डेटा मेटाउन अनुमति दिन्छ।"</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"अनुप्रयोगलाई तपाईंको फोनमा भण्डारण गरिएका सम्पर्क ठेगानासम्बन्धी डेटा परिमार्जन गर्न अनुमति दिन्छ। यो अनुमतिले अनुप्रयोगलाई सम्पर्क ठेगानासम्बन्धी डेटा मेटाउन अनुमति दिन्छ।"</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"कल लग पढ्नुहोस्"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"यस अनुप्रयोगले तपाईंको फोन सम्पर्कको इतिहास पढ्न सक्छ।"</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"कल लग लेख्‍नुहोस्"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"अधिक स्थान प्रदायक आदेशहरू पहुँच गर्नुहोस्"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"अनुप्रयोगलाई अतिरिक्त स्थान प्रदायक आदेशहरू पहुँच गर्न अनुमति दिन्छ। यो अनुप्रयोगलाई GPS वा अन्य स्थान स्रोतहरूको संचालन साथै हस्तक्षेप गर्न अनुमति दिन सक्छ।"</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"अग्रभूमिमा मात्र सटीक स्थानमाथि पहुँच राख्नुहोस्"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"यो अनुप्रयोगले अग्रभागमा चलिरहेको अवस्थामा मात्र तपाईंलाई स्थानको सटिक जानकारी दिन सक्छ। यी स्थानसम्बन्धी सेवाहरू अनिवार्य रूपमा सक्रिय गरिएका हुनु पर्छ र अनुप्रयोगले यिनीहरूको प्रयोग गर्न सकोस् भन्नाका खातिर तपाईंको फोनमै उपलब्ध हुन्छन्। यस कार्यले गर्दा ब्याट्री बढी खर्च हुन सक्छ।"</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"अग्रभूमिमा मात्र अनुमानित स्थान (नेटवर्कमा आधारित) माथि पहुँच राख्नुहोस्"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"यस अनुप्रयोगले सेलका टावर र Wi-Fi नेटवर्कहरू जस्ता नेटवर्कका स्रोतहरूको आधारमा तपाईंको स्थान बारे जानकारी प्राप्त गर्न सक्छ। यो अनुप्रयोग ती स्रोतहरूको प्रयोग गर्न सक्षम होस् भन्नका खातिर यी स्थानसम्बन्धी सेवाहरूलाई अनिवार्य रूपमा सक्रिय पार्नुपर्छ र यी तपाईंको ट्याब्लेटमा उपलब्ध हुनु पर्छ।"</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"यो अनुप्रयोगले अग्रभूमिमा चलिरहेको बेला मात्र यसले मोबाइलको टावर र Wi-Fi का नेटवर्कहरू जस्ता स्रोतहरूका आधारमा तपाईंको स्थानसम्बन्धी जानकारी प्राप्त गर्न सक्छ। यस अनुप्रयोगले स्थानसम्बन्धी जानकारी प्रयोग गर्न सकोस् भन्नाका खातिर तपाईंको Android TV यन्त्रमा यी स्थानसम्बन्धी सेवाहरू अनिवार्य रूपमा उपलब्ध हुनुका साथै सक्रिय गरिएको हुनु पर्छ।"</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"यस अनुप्रयोगले सेलका टावर र Wi-Fi नेटवर्कहरू जस्ता नेटवर्कका स्रोतहरूको आधारमा तपाईंको स्थान बारे जानकारी प्राप्त गर्न सक्छ। यो अनुप्रयोग ती स्रोतहरूको प्रयोग गर्न सक्षम होस् भन्नका खातिर यी स्थानसम्बन्धी सेवाहरूलाई अनिवार्य रूपमा सक्रिय पार्नुपर्छ र यी तपाईंको फोनमा उपलब्ध हुनु पर्छ।"</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"यो अनुप्रयोगले अग्रभागमा चलिरहेको अवस्थामा मात्र तपाईंलाई स्थानको सटिक जानकारी दिन सक्छ। स्थानसम्बन्धी सेवाहरू अनिवार्य रूपमा सक्रिय गरिएका हुनु पर्छ र अनुप्रयोगले यिनीहरूको प्रयोग गर्न सकोस् भन्नाका खातिर तपाईंको यन्त्रमै उपलब्ध हुनु पर्छ। यस कार्यले गर्दा ब्याट्री बढी खर्च हुन सक्छ।"</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"अग्रभागमा मात्र अनुमानित स्थानमाथि पहुँच राख्नुहोस्"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"यो अनुप्रयोगले अग्रभागमा चलिरहेको अवस्थामा मात्र तपाईंको स्थानको अनुमानित जानकारी दिन सक्छ। स्थानसम्बन्धी सेवाहरू अनिवार्य रूपमा सक्रिय गरिएका हुनु पर्छ र अनुप्रयोगले यिनीहरूको प्रयोग गर्न सकोस् भन्नाका खातिर तपाईंको यन्त्रमै उपलब्ध हुनु पर्छ।"</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"पृष्ठभूमिमा स्थानसम्बन्धी पहुँच"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"यसका अतिरिक्त यसलाई अनुमानित वा सटिक स्थानमाथि पहुँच राख्ने अनुमति दिइएको छ भने उक्त अनुप्रयोगले पृष्ठभूमिमा चलिरहेको बेला स्थानमाथि पहुँच राख्न सक्छ।"</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"यो अनुप्रयोगले अग्रभागमा चल्दा स्थानसम्बन्धी पहुँच प्राप्त गर्नुका साथै पृष्ठभूमिमा चल्दा पनि स्थानसम्बन्धी पहुँच प्राप्त गर्न सक्छ।"</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"तपाईँका अडियो सेटिङहरू परिवर्तन गर्नुहोस्"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"अनुप्रयोगलाई ग्लोबल अडियो सेटिङहरू परिमार्जन गर्न अनुमति दिन्छ, जस्तै आवाजको मात्रा र आउटपुटको लागि कुन स्पिकर प्रयोग गर्ने।"</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"अडियो रेकर्ड गर्नुहोस्"</string>
@@ -428,7 +425,7 @@
<string name="permdesc_systemCamera" msgid="544730545441964482">"यस विशेषाधिकार प्राप्त अनुप्रयोगले जुनसुकै समय प्रणालीको क्यामेरा प्रयोग गरी तस्बिर खिच्न र भिडियो रेकर्ड गर्न सक्छ। अनुप्रयोगसँग पनि android.permission.CAMERA सम्बन्धी अनुमति हुनु पर्छ"</string>
<string name="permlab_vibrate" msgid="8596800035791962017">"कम्पन नियन्त्रण गर्नुहोस्"</string>
<string name="permdesc_vibrate" msgid="8733343234582083721">"अनुप्रयोगलाई भाइब्रेटर नियन्त्रण गर्न अनुमति दिन्छ।"</string>
- <string name="permlab_callPhone" msgid="1798582257194643320">"फोन नम्बरहरूमा सिधै कल गर्नुहोस्"</string>
+ <string name="permlab_callPhone" msgid="1798582257194643320">"फोन नम्बरहरूमा सीधै कल गर्नुहोस्"</string>
<string name="permdesc_callPhone" msgid="5439809516131609109">"तपाईँको हस्तक्षेप बेगरै फोन नम्बर कल गर्न अनुप्रयोगलाई अनुमति दिन्छ। यसले अनपेक्षित शुल्क वा कलहरू गराउन सक्छ। यसले अनुप्रयोगलाई आपतकालीन नम्बरहरू कल गर्न अनुमति दिँदैन विचार गर्नुहोस्। खराब अनुप्रयोगहरूले तपाईँको स्वीकार बिना कलहरू गरेर तपाईँलाई बढी पैसा तिराउन सक्छ।"</string>
<string name="permlab_accessImsCallService" msgid="442192920714863782">"IMS कल सेवा पहुँच गर्नुहोस्"</string>
<string name="permdesc_accessImsCallService" msgid="6328551241649687162">"तपाईँको हस्तक्षेप बिना नै कल गर्न IMS सेवा प्रयोग गर्न अनुप्रयोगलाई अनुमति दिन्छ।"</string>
@@ -494,6 +491,8 @@
<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_preferredPaymentInfo" msgid="5274423844767445054">"NFC भुक्तानी सेवासम्बन्धी रुचाइएको जानकारी"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"यसले अनुप्रयोगलाई दर्ता गरिएका सहायता तथा मार्गको गन्तव्य जस्ता रुचाइएका NFC भुक्तानी सेवासम्बन्धी जानकारी प्राप्त गर्न दिन्छ।"</string>
<string name="permlab_nfc" msgid="1904455246837674977">"नजिक क्षेत्र संचार नियन्त्रणहरू"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"अनुप्रयोगलाई नयाँ क्षेत्र संचार (NFC) ट्यागहरू, कार्डहरू र पाठकहरूसँग अन्तर्क्रिया गर्न अनुमति दिन्छ।"</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"स्क्रिन लक असक्षम पार्नुहोस्"</string>
@@ -1624,12 +1623,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"पहुँचको सर्टकटले <xliff:g id="SERVICE_NAME">%1$s</xliff:g> लाई सक्रिय पार्‍यो"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"पहुँचको सर्टकटले <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>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"तपाईंले पहुँचसम्बन्धी बटन ट्याप गर्दा प्रयोग गर्नु पर्ने सुविधा रोज्नुहोस्:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"पहुँचसम्बन्धी इसारासँगै प्रयोग गर्नु पर्ने कुनै सेवा छनौट गर्नुहोस् (दुईवटा औँलाले स्क्रिनको फेदबाट माथितिर स्वाइप गर्नुहोस्):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"पहुँचसम्बन्धी इसारासँगै प्रयोग गर्नु पर्ने कुनै सेवा छनौट गर्नुहोस् (तीनवटा औँलाले स्क्रिनको फेदबाट माथितिर स्वाइप गर्नुहोस्):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"एउटा सेवाबाट अर्को सेवामा जान पहुँचसम्बन्धी बटनमा छोइराख्नुहोस्।"</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"एउटा सेवाबाट अर्को सेवामा जान दुईवटा औँलाले माथितिर स्वाइप गरी थिचिराख्नुहोस्।"</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"एउटा सेवाबाट अर्को सेवामा जान तीनवटा औँलाले माथितिर स्वाइप गरी थिचिराख्नुहोस्।"</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>
@@ -1868,7 +1861,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> मा जडान गरिएको छ"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"फाइलहरू हेर्न ट्याप गर्नुहोस्"</string>
<string name="pin_target" msgid="8036028973110156895">"पिन गर्नुहोस्"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"<xliff:g id="LABEL">%1$s</xliff:g> लाई पिन गर्नुहोस्"</string>
<string name="unpin_target" msgid="3963318576590204447">"अनपिन गर्नुहोस्"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"<xliff:g id="LABEL">%1$s</xliff:g> लाई अनपिन गर्नुहोस्"</string>
<string name="app_info" msgid="6113278084877079851">"अनुप्रयोगका बारे जानकारी"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"डेमो सुरु गर्दै…"</string>
@@ -1911,6 +1906,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"यी वस्तुहरू "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" मा अद्यावधिक गर्नुहोस्‌: <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> हो?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"सुरक्षित गर्नुहोस्"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"पर्दैन, धन्यवाद"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"अहिले होइन"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"कहिल्यै होइन"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"अद्यावधिक गर्नुहोस्"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"जारी राख्नुहोस्"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"पासवर्ड"</string>
@@ -2006,5 +2003,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"विभाजित स्क्रिन टगल गर्नुहोस्"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"लक स्क्रिन"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"स्क्रिनसट"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"पपअप विन्डोमा <xliff:g id="APP_NAME">%1$s</xliff:g> अनुप्रयोग छ।"</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> को क्याप्सन बार।"</string>
</resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 363c3c3184bc..b342941ebadb 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"De beheer-app van het werkprofiel ontbreekt of is beschadigd. Als gevolg hiervan zijn je werkprofiel en alle gerelateerde gegevens verwijderd. Neem contact op met je beheerder voor hulp."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Je werkprofiel is niet meer beschikbaar op dit apparaat"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Te veel wachtwoordpogingen"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"De beheerder heeft het apparaat afgestaan voor persoonlijk gebruik"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Apparaat wordt beheerd"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Dit apparaat wordt beheerd door je organisatie. Het netwerkverkeer kan worden bijgehouden. Tik voor meer informatie."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Je apparaat wordt gewist"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Hiermee kan de app sticky broadcasts verzenden die worden behouden nadat de broadcast is beëindigd. Bij overmatig gebruik kan het Android TV-apparaat traag of instabiel worden omdat er te veel geheugenruimte wordt gebruikt."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Hiermee kan de app sticky broadcasts verzenden die behouden blijven nadat de broadcast is beëindigd. Bij overmatig gebruik kan de telefoon traag of instabiel worden omdat er te veel geheugenruimte wordt gebruikt."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"je contacten lezen"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Hiermee kan de app gegevens lezen over de contacten die zijn opgeslagen op je tablet, inclusief de frequentie waarmee je hebt gebeld, gemaild of op andere manieren hebt gecommuniceerd met specifieke personen. Met deze toestemming kunnen apps je contactgegevens opslaan, en schadelijke apps kunnen zonder je medeweten contactgegevens delen."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Hiermee kan de app gegevens lezen over de contacten die zijn opgeslagen op je Android TV-apparaat, inclusief de frequentie waarmee je hebt gebeld, gemaild of op andere manieren hebt gecommuniceerd met specifieke personen. Met dit recht kunnen apps je contactgegevens opslaan en kunnen schadelijke apps zonder je medeweten contactgegevens delen."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Hiermee kan de app gegevens lezen over de contacten die zijn opgeslagen op je telefoon, inclusief de frequentie waarmee je hebt gebeld, gemaild of op andere manieren hebt gecommuniceerd met specifieke personen. Met deze toestemming kunnen apps je contactgegevens opslaan, en schadelijke apps kunnen zonder je medeweten contactgegevens delen."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Hiermee kan de app gegevens lezen over de contacten die zijn opgeslagen op je tablet. Apps hebben ook toegang tot de accounts op je tablet waarvoor contacten zijn gemaakt. Dit kan accounts omvatten die zijn gemaakt door apps die je hebt geïnstalleerd. Met dit recht kunnen apps je contactgegevens opslaan en kunnen schadelijke apps zonder je medeweten contactgegevens delen."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Hiermee kan de app gegevens lezen over de contacten die zijn opgeslagen op je Android TV. Apps hebben ook toegang tot de accounts op je Android TV-apparaat waarvoor contacten zijn gemaakt. Dit kan accounts omvatten die zijn gemaakt door apps die je hebt geïnstalleerd. Met dit recht kunnen apps je contactgegevens opslaan en kunnen schadelijke apps zonder je medeweten contactgegevens delen."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Hiermee kan de app gegevens lezen over de contacten die zijn opgeslagen op je telefoon. Apps hebben ook toegang tot de accounts op je telefoon waarvoor contacten zijn gemaakt. Dit kan accounts omvatten die zijn gemaakt door apps die je hebt geïnstalleerd. Met dit recht kunnen apps je contactgegevens opslaan en kunnen schadelijke apps zonder je medeweten contactgegevens delen."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"je contacten aanpassen"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Hiermee kan de app gegevens wijzigen over de contacten die zijn opgeslagen op je tablet, inclusief de frequentie waarmee je hebt gebeld, gemaild of op andere manieren hebt gecommuniceerd met specifieke contacten. Met deze toestemming kunnen apps contactgegevens verwijderen."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Hiermee kan de app gegevens wijzigen over de contacten die zijn opgeslagen op je Android TV-apparaat, inclusief de frequentie waarmee je hebt gebeld, gemaild of op andere manieren hebt gecommuniceerd met specifieke contacten. Met dit recht kunnen apps contactgegevens verwijderen."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Hiermee kan de app gegevens wijzigen over de contacten die zijn opgeslagen op je telefoon, inclusief de frequentie waarmee je hebt gebeld, gemaild of op andere manieren hebt gecommuniceerd met specifieke contacten. Met deze toestemming kunnen apps contactgegevens verwijderen."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Hiermee kan de app gegevens wijzigen over de contacten die zijn opgeslagen op je tablet. Met dit recht kunnen apps contactgegevens verwijderen."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Hiermee kan de app gegevens wijzigen over de contacten die zijn opgeslagen op je Android TV. Met dit recht kunnen apps contactgegevens verwijderen."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Hiermee kan de app gegevens wijzigen over de contacten die zijn opgeslagen op je telefoon. Met dit recht kunnen apps contactgegevens verwijderen."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"gesprekslijst lezen"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Deze app kan je gespreksgeschiedenis lezen."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"gesprekslijst schrijven"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"toegang tot extra opdrachten van locatieaanbieder"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Hiermee kan de app toegang krijgen tot extra opdrachten voor de locatieprovider. De app kan hiermee de werking van gps of andere locatiebronnen te verstoren."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"alleen toegang tot precieze locatie op de voorgrond"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Deze app kan je exacte locatie ophalen wanneer de app op de voorgrond wordt uitgevoerd. De app kan alleen gebruikmaken van deze locatieservices als ze zijn ingeschakeld en beschikbaar zijn op je telefoon. Hierdoor kan het batterijverbruik toenemen."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"alleen toegang tot geschatte locatie (op basis van netwerk) op de voorgrond"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Deze app kan je locatie ophalen op basis van netwerkbronnen zoals zendmasten en wifi-netwerken, maar alleen wanneer de app zich op de voorgrond bevindt. De app kan alleen gebruikmaken van deze locatieservices als ze zijn ingeschakeld en beschikbaar zijn op je tablet."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Deze app kan je locatie ophalen op basis van netwerkbronnen zoals zendmasten en wifi-netwerken, maar alleen als de app zich op de voorgrond bevindt. De app kan alleen gebruikmaken van deze locatieservices als ze zijn ingeschakeld en beschikbaar zijn op je Android TV-apparaat."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Deze app kan je locatie ophalen op basis van netwerkbronnen zoals zendmasten en wifi-netwerken, maar alleen wanneer de app zich op de voorgrond bevindt. De app kan alleen gebruikmaken van deze locatieservices als ze zijn ingeschakeld en beschikbaar zijn op je telefoon."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Deze app kan je exacte locatie ophalen als de app op de voorgrond wordt uitgevoerd. De app kan alleen gebruikmaken van de locatieservices als die zijn ingeschakeld en beschikbaar zijn op je apparaat. Hierdoor kan het batterijverbruik toenemen."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"alleen toegang tot geschatte locatie op de voorgrond"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Deze app kan je geschatte locatie alleen opvragen als de app op de voorgrond wordt gebruikt. De app kan de locatieservices alleen gebruiken als ze zijn ingeschakeld en beschikbaar zijn op je apparaat."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"toegang tot locatie op de achtergrond"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Als dit wordt verleend als aanvulling op toegang tot de geschatte of precieze locatie, kan de app toegang tot de locatie krijgen terwijl de app actief is op de achtergrond."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Deze app heeft niet alleen op de voorgrond toegang tot je locatie, maar ook als deze actief is op de achtergrond."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"je audio-instellingen wijzigen"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Hiermee kan de app algemene audio-instellingen wijzigen zoals het volume en welke luidspreker wordt gebruikt voor de uitvoer."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"audio opnemen"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Hiermee kan de app de Bluetooth-configuratie van de tablet bekijken en verbindingen met gekoppelde apparaten maken en accepteren."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Hiermee kan de app de Bluetooth-configuratie van het Android TV-apparaat bekijken en verbindingen met gekoppelde apparaten maken en accepteren."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Hiermee kan de app de Bluetooth-configuratie van de telefoon bekijken en verbindingen met gekoppelde apparaten maken en accepteren."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Informatie over voorkeursservice voor NFC-betaling"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Hiermee kun je zorgen dat de app informatie krijgt over de voorkeursservice voor NFC-betaling, zoals geregistreerde hulpmiddelen en routebestemmingen."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"Near Field Communication regelen"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Hiermee kan de app communiceren met NFC-tags (Near Field Communication), kaarten en lezers."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"je schermvergrendeling uitschakelen"</string>
@@ -1157,7 +1156,7 @@
<string name="aerr_application_repeated" msgid="7804378743218496566">"<xliff:g id="APPLICATION">%1$s</xliff:g> stopt steeds"</string>
<string name="aerr_process_repeated" msgid="1153152413537954974">"<xliff:g id="PROCESS">%1$s</xliff:g> stopt steeds"</string>
<string name="aerr_restart" msgid="2789618625210505419">"App opnieuw openen"</string>
- <string name="aerr_report" msgid="3095644466849299308">"Feedback verzenden"</string>
+ <string name="aerr_report" msgid="3095644466849299308">"Feedback sturen"</string>
<string name="aerr_close" msgid="3398336821267021852">"Sluiten"</string>
<string name="aerr_mute" msgid="2304972923480211376">"Verbergen tot apparaat opnieuw wordt opgestart"</string>
<string name="aerr_wait" msgid="3198677780474548217">"Wachten"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"\'Snelkoppeling toegankelijkheid\' heeft <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ingeschakeld"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"\'Snelkoppeling toegankelijkheid\' heeft <xliff:g id="SERVICE_NAME">%1$s</xliff:g> uitgeschakeld"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Houd beide volumetoetsen drie seconden ingedrukt om <xliff:g id="SERVICE_NAME">%1$s</xliff:g> te gebruiken"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Kies een service om te gebruiken wanneer je op de toegankelijkheidsknop tikt:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Kies een service om te gebruiken met het toegankelijkheidsgebaar (veeg met twee vingers omhoog vanaf de onderkant van het scherm):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Kies een service om te gebruiken met het toegankelijkheidsgebaar (veeg met drie vingers omhoog vanaf de onderkant van het scherm):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Tik op de toegankelijkheidsknop en houd deze vast om tussen services te schakelen."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Veeg met twee vingers omhoog en houd vast om tussen services te schakelen."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Veeg met drie vingers omhoog en houd vast om tussen services te schakelen."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Vergroting"</string>
<string name="user_switched" msgid="7249833311585228097">"Huidige gebruiker <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="1912993630661332336">"Overschakelen naar <xliff:g id="NAME">%1$s</xliff:g>…"</string>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Verbonden met <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Tik om bestanden te bekijken"</string>
<string name="pin_target" msgid="8036028973110156895">"Vastzetten"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"<xliff:g id="LABEL">%1$s</xliff:g> vastzetten"</string>
<string name="unpin_target" msgid="3963318576590204447">"Losmaken"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"<xliff:g id="LABEL">%1$s</xliff:g> losmaken"</string>
<string name="app_info" msgid="6113278084877079851">"App-info"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Demo starten…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Deze items updaten in "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> en <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Opslaan"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Nee, bedankt"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Niet nu"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Nooit"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Updaten"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Doorgaan"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"Wachtwoord"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Gesplitst scherm schakelen"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Scherm vergrendelen"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Screenshot"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"App <xliff:g id="APP_NAME">%1$s</xliff:g> in pop-upvenster."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Ondertitelingsbalk van <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index 566d778e3d60..b12c6553a7ae 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"ଆଡମିନ୍‍ ଆପ୍‍ ନାହିଁ କିମ୍ବା ଭୁଲ ଅଛି। ଫଳସ୍ୱରୂପ, ଆପଣଙ୍କ ୱାର୍କ ପ୍ରୋଫାଇଲ୍‍ ଏବଂ ସମ୍ବନ୍ଧୀୟ ଡାଟା ଡିଲିଟ୍ କରାଯାଇଛି। ସହାୟତା ପାଇଁ ଆପଣଙ୍କ ଆଡମିନଙ୍କୁ ଯୋଗାଯୋଗ କରନ୍ତୁ।"</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"ଏହି ଡିଭାଇସରେ ଆପଣଙ୍କ ୱର୍କ ପ୍ରୋଫାଇଲ୍‍ ଆଉ ଉପଲବ୍ଧ ନାହିଁ"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"ବହୁତ ଥର ଭୁଲ ପାସ୍‌ୱର୍ଡ ଲେଖିଛନ୍ତି"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"ବ୍ୟକ୍ତିଗତ ବ୍ୟବହାର ପାଇଁ ଆଡ୍‌ମିନ୍ ଡିଭାଇସ୍‌କୁ ଅଲଗା କରିଛନ୍ତି"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"ଡିଭାଇସକୁ ପରିଚାଳନା କରାଯାଉଛି"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"ଆପଣଙ୍କ ସଂସ୍ଥା ଏହି ଡିଭାଇସକୁ ପରିଚାଳନା କରନ୍ତି ଏବଂ ନେଟୱର୍କ ଟ୍ରାଫିକ୍‍ ନୀରିକ୍ଷଣ କରନ୍ତି। ବିବରଣୀ ପାଇଁ ଟାପ୍‍ କରନ୍ତୁ।"</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"ଆପଣଙ୍କ ଡିଭାଇସ୍‍ ବର୍ତ୍ତମାନ ଲିଭାଯିବ"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"ଷ୍ଟିକି ବ୍ରଡକାଷ୍ଟ୍ ପଠାଇବା ପାଇଁ ଆପ୍‌କୁ ଅନୁମତି ଦେଇଥାଏ, ଯାହା ବ୍ରଡକାଷ୍ଟ୍ ଶେଷ ହେବାପରେ ରହିଥାଏ। ଅତ୍ୟଧିକ ବ୍ୟବହାର ଦ୍ୱାରା ଅଧିକ ମେମୋରୀ ବ୍ୟବହାର ହୋଇ ଆପଣଙ୍କର Android ଟିଭି ଡିଭାଇସ୍‌କୁ ଧୀର କିମ୍ବା ଅସ୍ଥିର କରିପାରେ।"</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"ଷ୍ଟିକୀ ବ୍ରଡ୍‌କାଷ୍ଟ ପଠାଇବାକୁ ଆପ୍‍କୁ ଅନୁମତି ଦିଏ, ଯାହା ବ୍ରଡ୍‌କାଷ୍ଟ ଶେଷ ହେବାପରେ ରହିଥାଏ। ଅତିରିକ୍ତ ବ୍ୟବହାର ଦ୍ୱାରା ଅଧିକ ମେମୋରୀ ବ୍ୟବହାର ହୋଇ ଫୋନ୍‌କୁ ମନ୍ଥର କିମ୍ବା ଅସ୍ଥିର କରିପାରେ।"</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"ଆପଣଙ୍କ ଯୋଗାଯୋଗ ପଢ଼ନ୍ତୁ"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"ଜଣେ ନିର୍ଦ୍ଦିଷ୍ଟ ବ୍ୟକ୍ତିଙ୍କ ସହ ଆପଣ କେତେଥର କଲ୍‍, ଇମେଲ୍‍, ତଥା ଯୋଗାଯୋଗ କରିଛନ୍ତି, ତାହାର ନିୟମିତତା ସମେତ ଆପଣଙ୍କ ଟାବଲେଟ୍‌ରେ ଷ୍ଟୋର୍ ହୋଇଥିବା ଯୋଗାଯୋଗ ବିଷୟରେ ଡାଟା ପଢ଼ିବାକୁ ଆପ୍‍କୁ ଅନୁମତି ଦିଏ। ଏହ ଅନୁମତି ଦ୍ୱାରା ଆପଣଙ୍କ କଲ୍‍ ଲଗ୍ ସେଭ୍‍ କରିବାକୁ ଆପ୍‍କୁ ଅନୁମତି ଦିଏ ତଥା ହାନୀକାରକ ଆପ୍‍ ଆପଣଙ୍କ ଅଜ୍ଞାତରେ କଲ୍‍ ଲଗ୍‍ ଡାଟା ଶେୟାର କରିପାରନ୍ତି।"</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"ଅନ୍ୟ ପ୍ରକାରରେ ନିର୍ଦ୍ଦିଷ୍ଟ ବ୍ୟକ୍ତିମାନଙ୍କ ସହ ଆପଣ କେତେ ବ୍ୟବଧାନରେ କଲ୍, ଇମେଲ୍ ତଥା ଯୋଗାଯୋଗ କରିଛନ୍ତି, ସେସବୁକୁ ଅନ୍ତର୍ଭୁକ୍ତ କରି ଆପଣଙ୍କ Android ଟିଭିର ଡିଭାଇସ୍‌ରେ ଷ୍ଟୋର୍ କରାଯାଇଥିବା ଯୋଗାଯୋଗ ବିଷୟରେ ଡାଟା ପଢ଼ିବା ପାଇଁ ଆପ୍‍କୁ ଅନୁମତି ଦେଇଥାଏ। ଏହି ଅନୁମତି ଆପଣଙ୍କର ଯୋଗାଯୋଗ ଡାଟାକୁ ସେଭ୍ କରିବା ପାଇଁ ଏବଂ ଆପଣଙ୍କ ବିନା ଜ୍ଞାତସାରରେ କ୍ଷତିକାରକ ଆପ୍‌ଗୁଡ଼ିକୁ ହୁଏତ ସେୟାର୍ କରିବା ପାଇଁ ଆପ୍‌ଗୁଡ଼ିକୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"ଜଣେ ନିର୍ଦ୍ଦିଷ୍ଟ ବ୍ୟକ୍ତିଙ୍କ ସହ ଆପଣ କେତେ ବ୍ୟବଧାନରେ କଲ୍‌, ଇମେଲ ତଥା ଯୋଗାଯୋଗ କରିଛନ୍ତି, ସେସବୁ ଅନ୍ତର୍ଭୁକ୍ତ କରି ଆପଣଙ୍କ ଫୋନ୍‍ରେ ଷ୍ଟୋର୍‍ କରାଯାଇଥିବା ଯୋଗାଯୋଗ ବିଷୟରେ ଡାଟା ପଢିବାକୁ ଆପ୍‍କୁ ଅନୁମତି ଦିଏ। ଏହି ଅନୁମତି ଦ୍ୱାରା ଆପ୍‍ଟି ଆପଣଙ୍କ ଯୋଗାଯୋଗ ଡାଟା ସେଭ୍‍ କରିପାରିବ ଏବଂ ହାନୀକାରକ ଆପ୍‍ ଆପଣଙ୍କ ବିନା ଜ୍ଞାତସାରରେ ଯୋଗାଯୋଗ ଡାଟା ସେୟାର୍‍ କରିପାରନ୍ତି।"</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"ଏହା ଆପଣଙ୍କ ଟାବ୍‌ଲେଟ୍‌ରେ ଷ୍ଟୋର୍ କରାଯାଇଥିବା ଯୋଗାଯୋଗଗୁଡ଼ିକ ବିଷୟରେ ଡାଟା ପଢ଼ିବା ପାଇଁ ଆପ୍‌କୁ ଅନୁମତି ଦେଇଥାଏ। ଆପଣଙ୍କର ଟାବ୍‌ଲେଟ୍‌ରେ ଥିବା ଆକାଉଣ୍ଟଗୁଡ଼ିକ ଯେଉଁଥିରେ ଯୋଗାଯୋଗଗୁଡ଼ିକ ତିଆରି ହୋଇଛି, ସେଗୁଡ଼ିକୁ ଆପ୍ସର ଆକ୍ସେସ୍ ରହିବ। ଆପଣ ଇନ୍‌ଷ୍ଟଲ୍ କରିଥିବା ଆପ୍ସ ମାଧ୍ୟମରେ ତିଆରି କରାଯାଇଥିବା ଆକାଉଣ୍ଟଗୁଡ଼ିକୁ ଏହା ସାମିଲ କରିପାରେ। ଏହି ଅନୁମତି ଆପ୍ସକୁ ଆପଣଙ୍କର ଯୋଗାଯୋଗ ଡାଟା ସେଭ୍ କରିବାକୁ ଦିଏ ଏବଂ ହାନୀକାରକ ଆପ୍ ଆପଣଙ୍କ ଅଜାଣତରେ ଯୋଗାଯୋଗ ଡାଟା ସେୟାର୍ କରିପାରେ।"</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"ଏହା ଆପଣଙ୍କ Android TV ଡିଭାଇସ୍‌ରେ ଷ୍ଟୋର୍ କରାଯାଇଥିବା ଯୋଗାଯୋଗ ବିଷୟରେ ଡାଟା ପଢ଼ିବା ପାଇଁ ଆପ୍‌କୁ ଅନୁମତି ଦେଇଥାଏ। ଆପଣଙ୍କର Android TV ଡିଭାଇସ୍‌ରେ ଥିବା ଆକାଉଣ୍ଟଗୁଡ଼ିକ ଯେଉଁଥିରେ ଯୋଗାଯୋଗଗୁଡ଼ିକ ତିଆରି ହୋଇଛି, ସେଗୁଡ଼ିକୁ ମଧ୍ୟ ଆପ୍ସର ଆକ୍ସେସ୍ ରହିବ। ଆପଣ ଇନ୍‌ଷ୍ଟଲ୍ କରିଥିବା ଆପ୍ସ ମାଧ୍ୟମରେ ତିଆରି କରାଯାଇଥିବା ଆକାଉଣ୍ଟଗୁଡ଼ିକୁ ଏହା ସାମିଲ କରିପାରେ। ଏହି ଅନୁମତି ଆପ୍ସକୁ ଆପଣଙ୍କର ଯୋଗାଯୋଗ ଡାଟା ସେଭ୍ କରିବାକୁ ଦିଏ ଏବଂ ହାନୀକାରକ ଆପ୍ ଆପଣଙ୍କ ଅଜାଣତରେ ଯୋଗାଯୋଗ ଡାଟା ସେୟାର୍ କରିପାରେ।"</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"ଏହା ଆପଣଙ୍କ ଫୋନ୍‌ରେ ଷ୍ଟୋର୍ କରାଯାଇଥିବା ଯୋଗାଯୋଗଗୁଡ଼ିକ ବିଷୟରେ ଡାଟା ପଢ଼ିବା ପାଇଁ ଆପ୍‌କୁ ଅନୁମତି ଦେଇଥାଏ। ଆପଣଙ୍କର ଫୋନ୍‌ରେ ଥିବା ଆକାଉଣ୍ଟଗୁଡ଼ିକ ଯେଉଁଥିରେ ଯୋଗାଯୋଗଗୁଡ଼ିକ ତିଆରି ହୋଇଛି, ସେଗୁଡ଼ିକୁ ଆପ୍ସର ଆକ୍ସେସ୍ ରହିବ। ଆପଣ ଇନ୍‌ଷ୍ଟଲ୍ କରିଥିବା ଆପ୍ସ ମାଧ୍ୟମରେ ତିଆରି କରାଯାଇଥିବା ଆକାଉଣ୍ଟଗୁଡ଼ିକୁ ଏହା ସାମିଲ କରିପାରେ। ଏହି ଅନୁମତି ଆପ୍ସକୁ ଆପଣଙ୍କର ଯୋଗାଯୋଗ ଡାଟା ସେଭ୍ କରିବାକୁ ଦିଏ ଏବଂ ହାନୀକାରକ ଆପ୍ ଆପଣଙ୍କ ଅଜାଣତରେ ଯୋଗାଯୋଗ ଡାଟା ସେୟାର୍ କରିପାରେ।"</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"ନିଜ ଯୋଗାଯୋଗ ସଂଶୋଧନ କରନ୍ତୁ"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"ଜଣେ ନିର୍ଦ୍ଦିଷ୍ଟ ଯୋଗାଯୋଗଙ୍କ ସହ ଆପଣ କେତେ ବ୍ୟବଧାନରେ କଲ୍‌, ଇମେଲ ତଥା ଯୋଗାଯୋଗ କରିଛନ୍ତି, ସେସବୁ ଅନ୍ତର୍ଭୁକ୍ତ କରି ଆପଣଙ୍କ ଟାବଲେଟ୍‌ରେ ଷ୍ଟୋର୍‍ କରାଯାଇଥିବା ଯୋଗାଯୋଗ ବିଷୟକ ଡାଟା ବଦଳାଇବା ପାଇଁ ଆପ୍‍କୁ ଅନୁମତି ଦିଏ। ଏହି ଅନୁମତି ଦ୍ୱାରା ଆପ୍‍ଟି ଯୋଗାଯୋଗ ଡାଟା ଡିଲିଟ୍‍ କରିପାରେ।"</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"ଅନ୍ୟ ପ୍ରକାରରେ ନିର୍ଦ୍ଦିଷ୍ଟ ଯୋଗାଯୋଗ ସହ ଆପଣ କେତେ ବ୍ୟବଧାନରେ କଲ୍, ଇମେଲ୍ ତଥା ଯୋଗାଯୋଗ କରିଛନ୍ତି, ସେସବୁକୁ ଅନ୍ତର୍ଭୁକ୍ତ କରି ଆପଣଙ୍କ Android ଟିଭି ଡିଭାଇସ୍‌ରେ ଷ୍ଟୋର୍ କରାଯାଇଥିବା ଯୋଗାଯୋଗ ବିଷୟରେ ଡାଟା ସଂଶୋଧନ କରିବାକୁ ଆପ୍‍କୁ ଅନୁମତି ଦେଇଥାଏ। ଯୋଗାଯୋଗ ଡାଟା ଡିଲିଟ୍ କରିବା ପାଇଁ ଆପ୍ସକୁ ଏହାର ଅନୁମତି ଦେଇଥାଏ।"</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"ଜଣେ ନିର୍ଦ୍ଦିଷ୍ଟ ଯୋଗାଯୋଗଙ୍କ ସହ ଆପଣ କେତେ ବ୍ୟବଧାନରେ କଲ୍‌, ଇମେଲ ତଥା ଯୋଗାଯୋଗ କରିଛନ୍ତି, ସେସବୁ ଅନ୍ତର୍ଭୁକ୍ତ କରି ଆପଣଙ୍କ ଫୋନ୍‍ରେ ଷ୍ଟୋର୍‍ କରାଯାଇଥିବା ଯୋଗାଯୋଗ ବିଷୟରେ ଡାଟା ବଦଳାଇବାକୁ ଆପ୍‍କୁ ଅନୁମତି ଦିଏ। ଏହି ଅନୁମତି ଦ୍ୱାରା ଆପ୍‍ଟି ଯୋଗାଯୋଗ ଡାଟା ଡିଲିଟ୍‍ କରିପାରେ।"</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"ଏହା ଆପଣଙ୍କ ଟାବ୍‌ଲେଟ୍‌ରେ ଷ୍ଟୋର୍ କରାଯାଇଥିବା ଯୋଗାଯୋଗ ବିଷୟରେ ଡାଟା ସଂଶୋଧନ କରିବା ପାଇଁ ଆପ୍‌କୁ ଅନୁମତି ଦେଇଥାଏ। ଏହି ଅନୁମତି ଆପ୍ସକୁ ଆପଣଙ୍କର ଯୋଗାଯୋଗ ଡାଟା ଡିଲିଟ୍ କରିବାକୁ ଦିଏ।"</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"ଏହା ଆପଣଙ୍କ Android TV ଡିଭାଇସ୍‌ରେ ଷ୍ଟୋର୍ କରାଯାଇଥିବା ଯୋଗାଯୋଗ ବିଷୟରେ ଡାଟା ସଂଶୋଧନ କରିବା ପାଇଁ ଆପ୍‌କୁ ଅନୁମତି ଦେଇଥାଏ। ଏହି ଅନୁମତି ଆପ୍ସକୁ ଆପଣଙ୍କର ଯୋଗାଯୋଗ ଡାଟା ଡିଲିଟ୍ କରିବାକୁ ଦିଏ।"</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"ଏହା ଆପଣଙ୍କ ଫୋନ୍‌ରେ ଷ୍ଟୋର୍ କରାଯାଇଥିବା ଯୋଗାଯୋଗ ବିଷୟରେ ଡାଟା ପରିବର୍ତ୍ତନ କରିବା ପାଇଁ ଆପ୍‌କୁ ଅନୁମତି ଦେଇଥାଏ। ଏହି ଅନୁମତି ଆପ୍ସକୁ ଆପଣଙ୍କର ଯୋଗାଯୋଗ ଡାଟା ଡିଲିଟ୍ କରିବାକୁ ଦିଏ।"</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"କଲ୍‌ ଲଗ୍‌ ପଢ଼ନ୍ତୁ"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"ଏହି ଆପ୍‍ ଆପଣଙ୍କ କଲ୍‍ ହିଷ୍ଟୋରୀ ପଢ଼ିପାରେ।"</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"କଲ୍‍ ଲଗ୍‍ ଲେଖନ୍ତୁ"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"ଅତିରିକ୍ତ ଲୋକେସନ୍ ପ୍ରଦାନକାରୀ କମାଣ୍ଡକୁ ଆକ୍ସେସ୍‍ କରନ୍ତୁ"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"ଅତିରିକ୍ତ ଲୋକେସନ୍‍ ପ୍ରଦାନକାରୀ କମାଣ୍ଡ ଆକ୍ସେସ୍‌ କରିବା ପାଇଁ ଆପ୍‍କୁ ଅନୁମତି ଦିଏ। GPS କିମ୍ବା ଅନ୍ୟ ଲୋକେସନ୍‍ ସୋର୍ସଗୁଡିକରେ ଆପ୍‍ଟି ପ୍ରଭାବ ପକାଇପାରେ।"</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"କେବଳ ସମ୍ମୁଖଭାଗରେ ସଠିକ୍‍ ଲୋକେଶନ୍‍ର ଆକ୍ସେସ୍‍ କରନ୍ତୁ"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"ଏହି ଆପ୍‍ ଯେତେବେଳେ ସମ୍ମୁଖଭାଗରେ ଥିବାବେଳେ ଆପଣଙ୍କର ସଠିକ୍‍ ଲୋକେସନ୍‍ ପ୍ରାପ୍ତ କରିପାରିବ। ଏହି ଲୋକେସନ୍‍ ସେବାଗୁଡ଼ିକ ନିଶ୍ଚିତରୂପେ ଅନ୍‍ ରହିବା ଦରକାର ଏବଂ ଆପ୍‍ର ବ୍ୟବହାର ପାଇଁ ଫୋନ୍‍ରେ ଉପଲବ୍ଧ ଥିବା ଦରକାର। ଏହା ବ୍ୟାଟେରୀ ଅଧିକା ଖର୍ଚ୍ଚ କରିପାରେ।"</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"କେବଳ ସମ୍ମୁଖଭାଗରେ ହାରାହାରି ଲୋକେସନ୍‍ (ନେଟ୍‍ୱର୍କ-ଆଧାରିତ)ର ଆକ୍ସେସ୍‍ କରନ୍ତୁ"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"ସେଲ୍‍ ଟାୱାର ଓ ୱାଇ-ଫାଇ ନେଟ୍‌ୱର୍କ ପରି ଉତ୍ସକୁ ଆଧାର କରି ଏହି ଆପ୍‍ ଆପଣଙ୍କ ଲୋକେସନ୍‍ ପ୍ରାପ୍ତ କରିପାରିବ। ଏହି ଲୋକେସନ୍‍ ସେବାଗୁଡ଼ିକର ବ୍ୟବହାର କରିବାକୁ ସେଗୁଡ଼ିକ ଚାଲୁ କରାଯିବା ଏବଂ ଆପଣଙ୍କ ଟାବ୍‍‍‍ଲେଟ୍‍‍ରେ ଉପଲବ୍ଧ ଥିବା ଜରୁରୀ ଅଟେ।"</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"ଏହି ଆପ୍, ସେଲ୍ ଟାୱାର ଓ ୱାଇ-ଫାଇ ନେଟ୍‌ୱାର୍କ ପରି ଉତ୍ସକୁ ଆଧାର କରି ଆପଣଙ୍କ ଲୋକେସନ୍ ପ୍ରାପ୍ତ କରିପାରିବ, କିନ୍ତୁ ଯେତେବେଳେ ଆପ୍ କେବଳ ସମ୍ମୁଖଭାଗରେ ରହିଥାଏ। ଏହି ଲୋକେସନ୍ ସେବାଗୁଡ଼ିକୁ ଚାଲୁ କରାଯିବା ଏବଂ ଆପ୍ ସେଗୁଡ଼ିକୁ ବ୍ୟବହାର କରିବାକୁ ସକ୍ଷମ ହେବା ପାଇଁ ଆପଣଙ୍କର Android ଟିଭି ଡିଭାଇସ୍‌ରେ ଉପଲବ୍ଧ ହେବା ଉଚିତ।"</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"ସେଲ୍‍ ଟାୱାର ଓ ୱାଇ-ଫାଇ ନେଟ୍‌ୱର୍କ ପରି ଉତ୍ସକୁ ଆଧାର କରି ଏହି ଆପ୍‍ ଆପଣଙ୍କ ଲୋକେସନ୍‍ ପ୍ରାପ୍ତ କରିପାରିବ। ଏହି ଲୋକେସନ୍‍ ସେବାଗୁଡ଼ିକର ବ୍ୟବହାର କରିବାକୁ ସେଗୁଡ଼ିକ ଚାଲୁ କରାଯିବା ଏବଂ ଆପଣଙ୍କ ଫୋନ୍‌ରେ ଉପଲବ୍ଧ ଥିବା ଜରୁରୀ ଅଟେ।"</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"ଏହି ଆପ୍ କେବଳ ସମ୍ମୁଖ ପଟରେ ଥିବାବେଳେ ଆପଣଙ୍କର ସଠିକ୍ ଲୋକେସନ୍ ପ୍ରାପ୍ତ କରିପାରିବ। ଆପଣଙ୍କ ଡିଭାଇସ୍‌ରେ ଲୋକେସନ୍ ସେବା ଚାଲୁ ଏବଂ ଉପଲବ୍ଧ ହେବା ଦରକାର ଯେପରି ଆପ୍ ସେଗୁଡ଼ିକୁ ବ୍ୟବହାର କରିବାକୁ ସକ୍ଷମ ହେବ। ଏହା ବ୍ୟାଟେରୀ ଅଧିକା ଖର୍ଚ୍ଚ କରିପାରେ।"</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"କେବଳ ସମ୍ମୁଖପଟରେ ହାରାହାରି ଲୋକେସନ୍ ଆକ୍ସେସ୍ କରନ୍ତୁ"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"ଏହି ଆପ୍ କେବଳ ସେତେବେଳେ ଆପଣଙ୍କର ଆନୁମାନିକ ଲୋକେସନ୍ ପାଇପାରିବ, ଯେତେବେଳେ ଏହା ସମ୍ମୁଖପଟରେ ଥିବ। ଆପଣଙ୍କ ଡିଭାଇସ୍‌ରେ ଲୋକେସନ୍ ସେବାଗୁଡ଼ିକ ଚାଲୁ ଏବଂ ଉପଲବ୍ଧ ହେବା ଦରକାର ଯେପରି ଆପ୍ ସେଗୁଡ଼ିକୁ ବ୍ୟବହାର କରିବାକୁ ସକ୍ଷମ ହେବ।"</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"ବ୍ୟାକ୍‌ଗ୍ରାଉଣ୍ଡ୍‌ରେ ଲୋକେସନ୍ ଆକ୍ସେସ୍ କରନ୍ତୁ"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"ଅନୁମାନିତ କିମ୍ବା ବିଲ୍‌କୁଲ୍ ସଠିକ୍ ସ୍ଥାନ ଆକ୍ସେସ୍ କରିବାର ଅନୁମତି ଅତିରିକ୍ତ ଭାବରେ ଦିଆଗଲେ, ବ୍ୟାକ୍‌ଗ୍ରାଉଣ୍ଡରେ ଚାଲୁଥିବା ସମୟରେ ଆପ୍ ଆପଣଙ୍କର ସ୍ଥାନର ଆକ୍ସେସ୍ କରିପାରିବ।"</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"ଏହି ଆପ୍ ସମ୍ମୁଖପଟ ଲୋକେସନ୍ ଆକ୍ସେସ୍ କରିବା ସହ ପୃଷ୍ଠପଟରେ ଚାଲିବା ସମୟରେ ଲୋକେସନ୍ ଆକ୍ସେସ୍ କରିପାରିବ।"</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"ଆପଣଙ୍କ ଅଡିଓ ସେଟିଙ୍ଗକୁ ପରିବର୍ତ୍ତନ କରନ୍ତୁ"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"ଆପ୍‌କୁ ଗ୍ଲୋବାଲ୍ ଅଡିଓ ସେଟିଙ୍ଗ, ଯେପରିକି ଭଲ୍ୟୁମ୍‌କୁ ସଂଶୋଧିତ କରିବାକୁ ଏବଂ ଆଉଟପୁଟ୍ ପାଇଁ ସ୍ପିକର୍‌ ବ୍ୟବହାର କରିବାକୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"ଅଡିଓ ରେକର୍ଡ କରନ୍ତୁ"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"ଟାବଲେଟ୍‌ରେ ଥିବା ବ୍ଲୁ-ଟୁଥ୍‌ର କନଫିଗରେଶନ୍‍ ଦେଖିବାକୁ ଏବଂ ପେୟାର୍‍ କରାଯାଇଥିବା ଡିଭାଇସ୍‌ ସହିତ ସଂଯୋଗ ସ୍ୱୀକାର କରିବା ପାଇଁ ଆପ୍‌କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"ଆପଣଙ୍କର Android ଟିଭି ଡିଭାଇସ୍‌ରେ ବ୍ଲୁଟୁଥ୍‍ର କନଫିଗ୍‌ରେସନ୍ ଦେଖିବା ପାଇଁ ଏବଂ ପେୟାର୍ କରାଯାଇଥିବା ଡିଭାଇସ୍‌ଗୁଡ଼ିକ ସହ ସଂଯୋଗଗୁଡ଼ିକୁ ତିଆରି ଏବଂ ସ୍ୱୀକାର କରିବା ପାଇଁ ଆପ୍‌କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"ଫୋନ୍‌ରେ ଥିବା ବ୍ଲୁ-ଟୁଥ୍‌ର କନଫିଗରେଶନ୍‍ ଦେଖିବାକୁ ଏବଂ ପେୟାର୍‍ କରାଯାଇଥିବା ଡିଭାଇସ୍‌ ସହିତ ସଂଯୋଗ ସ୍ୱୀକାର କରିବା ପାଇଁ ଆପ୍‌କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"ପସନ୍ଦର NFC ପେମେଣ୍ଟ ସେବା ସୂଚନା"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"ପଞ୍ଜିକୃତ ଯନ୍ତ୍ର ଏବଂ ମାର୍ଗ ଲକ୍ଷସ୍ଥଳ ପରି ପସନ୍ଦର nfc ପେମେଣ୍ଟ ସେବା ସୂଚନା ପାଇବାକୁ ଆପ୍ ଅନୁମତି କରିଥାଏ।"</string>
<string name="permlab_nfc" msgid="1904455246837674977">"ନିଅର୍ ଫିଲ୍ଡ କମ୍ୟୁନିକେଶନ୍ ଉପରେ ନିୟନ୍ତ୍ରଣ ରଖନ୍ତୁ"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"ନିଅର୍‍ ଫିଲ୍ଡ କମ୍ୟୁନିକେସନ୍‍ନ (NFC) ଟାଗ୍‍, କାର୍ଡ ଓ ରିଡରଗୁଡ଼ିକ ସହ ଯୋଗାଯୋଗ କରିବା ପାଇଁ ଆପ୍‍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"ଆପଣଙ୍କ ସ୍କ୍ରୀନ୍‍ ଲକ୍‍ ଅକ୍ଷମ କରନ୍ତୁ"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"ଆକ୍ସେସିବିଲିଟୀ ଶର୍ଟକଟ୍‍ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ଅନ୍‍ କରାଯାଇଛି"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"ଆକ୍ସେସିବିଲିଟୀ ଶର୍ଟକଟ୍‍ <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>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"ଆପଣ ଆକ୍ସେସିବିଲିଟୀ ବଟନ୍ ଟାପ୍ କରିବା ସମୟରେ ଏକ ସେବା ବ୍ୟବହାର କରିବା ପାଇଁ ବାଛନ୍ତୁ:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"ଆକ୍ସେସିବିଲିଟୀ ଜେଶ୍ଚର୍ ବ୍ୟବହାର କରିବା ପାଇଁ ଏକ ସେବା ବାଛନ୍ତୁ (ଦୁଇଟି ଆଙ୍ଗୁଠିରେ ସ୍କ୍ରିନ୍‍ର ତଳୁ ଉପରକୁ ସ୍ୱାଇପ୍ କରନ୍ତୁ):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"ଆକ୍ସେସିବିଲିଟୀ ଜେଶ୍ଚର୍ ବ୍ୟବହାର କରିବା ପାଇଁ ଏକ ସେବା ବାଛନ୍ତୁ (ତିନିଟି ଆଙ୍ଗୁଠିରେ ସ୍କ୍ରିନ୍‍ର ତଳୁ ଉପରକୁ ସ୍ୱାଇପ୍ କରନ୍ତୁ):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"ସେବାଗୁଡ଼ିକ ମଧ୍ୟରେ ସ୍ୱିଚ୍ କରିବା ପାଇଁ ଆକ୍ସେସିବିଲିଟୀ ବଟନ୍ ସ୍ପର୍ଶ କରନ୍ତୁ ଓ ଧରି ରଖନ୍ତୁ।"</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"ସେବାଗୁଡ଼ିକ ମଧ୍ୟରେ ସ୍ୱିଚ୍ କରିବା ପାଇଁ ଦୁଇଟି ଆଙ୍ଗୁଠିରେ ଉପରକୁ ସ୍ୱାଇପ୍ କରନ୍ତୁ ଏବଂ ଧରି ରଖନ୍ତୁ।"</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"ସେବାଗୁଡ଼ିକ ମଧ୍ୟରେ ସ୍ୱିଚ୍ କରିବା ପାଇଁ ତିନିଟି ଆଙ୍ଗୁଠିରେ ଉପରକୁ ସ୍ୱାଇପ୍ କରନ୍ତୁ ଏବଂ ଧରି ରଖନ୍ତୁ।"</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>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> ସହ କନେକ୍ଟ କରାଗଲା"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"ଫାଇଲ୍‍ ଦେଖିବା ପାଇଁ ଟାପ୍‍ କରନ୍ତୁ"</string>
<string name="pin_target" msgid="8036028973110156895">"ପିନ୍‍"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"<xliff:g id="LABEL">%1$s</xliff:g>ରେ ପିନ୍ କରନ୍ତୁ"</string>
<string name="unpin_target" msgid="3963318576590204447">"ଅନପିନ୍ କରନ୍ତୁ"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"<xliff:g id="LABEL">%1$s</xliff:g>ରେ ଅନ୍‌ପିନ୍ କରନ୍ତୁ"</string>
<string name="app_info" msgid="6113278084877079851">"ଆପ୍‍ ସୂଚନା"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"ଡେମୋ ଆରମ୍ଭ କରାଯାଉଛି…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291"><b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"ରେ: <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> ଆଇଟମ୍‌ଗୁଡ଼ିକ ଅପ୍‌ଡେଟ୍ କରିବେ?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"ସେଭ୍‌ କରନ୍ତୁ"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"ନାଁ, ପଚାରିଥିବାରୁ ଧନ୍ୟବାଦ"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"ଏବେ ନୁହେଁ"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"କେବେ ବି ନୁହେଁ"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"ଅପ୍‍ଡେଟ୍‌ କରନ୍ତୁ"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"ଜାରି ରଖନ୍ତୁ"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"ପାସୱର୍ଡ୍"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"ଦୁଇଟି ସ୍କ୍ରିନ୍ ମଧ୍ୟରେ ଟୋଗଲ୍ କରନ୍ତୁ"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"ସ୍କ୍ରିନ୍ ଲକ୍ କରନ୍ତୁ"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"ସ୍କ୍ରି‍ନ୍‍ସଟ୍ ନିଅନ୍ତୁ"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"ପପ୍-ଅପ୍ ୱିଣ୍ଡୋରେ <xliff:g id="APP_NAME">%1$s</xliff:g> ଆପ୍"</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g>ର କ୍ୟାପ୍ସନ୍ ବାର୍।"</string>
</resources>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 7760db00b3ee..72e695efad80 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਪ੍ਰਸ਼ਾਸਕ ਐਪ ਜਾਂ ਤਾਂ ਗੁੰਮਸ਼ੁਦਾ ਹੈ ਜਾਂ ਖਰਾਬ ਹੈ। ਨਤੀਜੇ ਵਜੋਂ, ਤੁਹਾਡੀ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਅਤੇ ਸਬੰਧਿਤ ਡਾਟਾ ਮਿਟਾਇਆ ਗਿਆ ਹੈ। ਸਹਾਇਤਾ ਲਈ ਆਪਣੇ ਪ੍ਰਸ਼ਾਸਕ ਨਾਲ ਸੰਪਰਕ ਕਰੋ।"</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"ਤੁਹਾਡਾ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਹੁਣ ਇਸ ਡੀਵਾਈਸ \'ਤੇ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"ਕਈ ਵਾਰ ਗਲਤ ਪਾਸਵਰਡ ਦਾਖਲ ਕੀਤਾ ਗਿਆ"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"ਪ੍ਰਸ਼ਾਸਕ ਨੇ ਨਿੱਜੀ ਵਰਤੋਂ ਲਈ ਡੀਵਾਈਸ ਤਿਆਗਿਆ"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"ਡੀਵਾਈਸ ਪ੍ਰਬੰਧਨ ਅਧੀਨ ਹੈ"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"ਤੁਹਾਡਾ ਸੰਗਠਨ ਇਸ ਡੀਵਾਈਸ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰਦਾ ਹੈ ਅਤੇ ਨੈੱਟਵਰਕ ਟਰੈਫਿਕ ਦੀ ਨਿਗਰਾਨੀ ਕਰ ਸਕਦਾ ਹੈ। ਵੇਰਵਿਆਂ ਲਈ ਟੈਪ ਕਰੋ।"</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"ਤੁਹਾਡਾ ਡੀਵਾਈਸ ਮਿਟਾਇਆ ਜਾਏਗਾ"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"ਐਪ ਨੂੰ ਸਟਿੱਕੀ ਪ੍ਰਸਾਰਨ ਭੇਜਣ ਦਿੰਦੀ ਹੈ, ਜੋ ਪ੍ਰਸਾਰਨ ਦੇ ਖਤਮ ਹੋਣ ਤੋਂ ਬਾਅਦ ਵੀ ਰਹਿੰਦੇ ਹਨ। ਹੱਦੋਂ ਵੱਧ ਵਰਤੋਂ ਇਸ ਵੱਲੋਂ ਬਹੁਤ ਜ਼ਿਆਦਾ ਮੈਮੋਰੀ ਵਰਤੇ ਜਾਣ ਦਾ ਕਾਰਨ ਬਣਕੇ ਡੀਵਾਈਸ ਨੂੰ ਧੀਮਾ ਜਾਂ ਅਸਥਿਰ ਬਣਾ ਸਕਦੀ ਹੈ।"</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"ਐਪ ਨੂੰ ਸਟਿਕੀ ਪ੍ਰਸਾਰਨ ਭੇਜਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਜੋ ਪ੍ਰਸਾਰਨ ਦੇ ਖਤਮ ਹੋਣ ਤੋਂ ਬਾਅਦ ਰਹਿੰਦੇ ਹਨ। ਵਾਧੂ ਵਰਤੋਂ ਫ਼ੋਨ ਨੂੰ ਹੌਲੀ ਜਾਂ ਬਹੁਤ ਜ਼ਿਆਦਾ ਮੈਮਰੀ ਵਰਤ ਕੇ ਇਸਨੂੰ ਅਸਥਿਰ ਬਣਾ ਸਕਦੀ ਹੈ।"</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"ਆਪਣੇ ਸੰਪਰਕ ਪੜ੍ਹੋ"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ ਟੈਬਲੈੱਟ \'ਤੇ ਸਟੋਰ ਕੀਤੇ ਤੁਹਾਡੇ ਸੰਪਰਕਾਂ ਬਾਰੇ ਡਾਟਾ ਪੜ੍ਹਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਉਸ ਬਾਰੰਬਾਰਤਾ ਸਮੇਤ ਜਿਸ ਨਾਲ ਤੁਸੀਂ ਕਾਲ ਕੀਤੀ ਹੈ, ਈਮੇਲ ਕੀਤੀ ਹੈ ਜਾਂ ਖਾਸ ਵਿਅਕਤੀਆਂ ਨਾਲ ਹੋਰ ਤਰੀਕਿਆਂ ਨਾਲ ਸੰਚਾਰ ਕੀਤਾ ਹੈ। ਇਹ ਇਜਾਜ਼ਤ ਐਪਾਂ ਨੂੰ ਤੁਹਾਡਾ ਸੰਪਰਕ ਡਾਟਾ ਰੱਖਿਅਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ ਅਤੇ ਖਰਾਬ ਐਪਾਂ ਤੁਹਾਡੀ ਜਾਣਕਾਰੀ ਤੋਂ ਬਿਨਾਂ ਸੰਪਰਕ ਡਾਟਾ ਸਾਂਝਾ ਕਰ ਸਕਦੀਆਂ ਹਨ।"</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ Android TV ਡੀਵਾਈਸ \'ਤੇ ਸਟੋਰ ਕੀਤੇ ਤੁਹਾਡੇ ਸੰਪਰਕਾਂ ਬਾਰੇ ਡਾਟਾ ਪੜ੍ਹਨ ਦਿੰਦੀ ਹੈ, ਇਸ ਵਿੱਚ ਸ਼ਾਮਲ ਹੈ ਕਿ ਤੁਸੀਂ ਵਿਅਕਤੀ ਵਿਸ਼ੇਸ਼ਾਂ ਨਾਲ ਕਿਸ ਬਾਰੰਬਾਰਤਾ ਨਾਲ ਕਾਲ ਕੀਤੀ ਹੈ, ਈਮੇਲ ਕੀਤੀ ਹੈ ਜਾਂ ਹੋਰ ਤਰੀਕਿਆਂ ਨਾਲ ਸੰਚਾਰ ਕੀਤਾ। ਇਹ ਇਜਾਜ਼ਤ ਐਪਾਂ ਨੂੰ ਤੁਹਾਡਾ ਸੰਪਰਕ ਡਾਟਾ ਰੱਖਿਅਤ ਕਰਨ ਦਿੰਦੀ ਹੈ ਅਤੇ ਭੈੜੀਆਂ ਐਪਾਂ ਤੁਹਾਡੀ ਜਾਣਕਾਰੀ ਤੋਂ ਬਿਨਾਂ ਸੰਪਰਕ ਡਾਟਾ ਸਾਂਝਾ ਕਰ ਸਕਦੀਆਂ ਹਨ।"</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ ਫ਼ੋਨ \'ਤੇ ਸਟੋਰ ਕੀਤੇ ਤੁਹਾਡੇ ਸੰਪਰਕਾਂ ਬਾਰੇ ਡਾਟਾ ਪੜ੍ਹਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਉਸ ਬਾਰੰਬਾਰਤਾ ਸਮੇਤ ਜਿਸ ਨਾਲ ਤੁਸੀਂ ਕਾਲ ਕੀਤੀ ਹੈ, ਈਮੇਲ ਕੀਤੀ ਹੈ ਜਾਂ ਖਾਸ ਵਿਅਕਤੀਆਂ ਨਾਲ ਹੋਰ ਤਰੀਕਿਆਂ ਨਾਲ ਸੰਚਾਰ ਕੀਤਾ ਹੈ। ਇਹ ਇਜਾਜ਼ਤ ਐਪਾਂ ਨੂੰ ਤੁਹਾਡਾ ਸੰਪਰਕ ਡਾਟਾ ਰੱਖਿਅਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ ਅਤੇ ਖਰਾਬ ਐਪਾਂ ਤੁਹਾਡੀ ਜਾਣਕਾਰੀ ਤੋਂ ਬਿਨਾਂ ਸੰਪਰਕ ਡਾਟਾ ਸਾਂਝਾ ਕਰ ਸਕਦੀਆਂ ਹਨ।"</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ ਟੈਬਲੈੱਟ \'ਤੇ ਸਟੋਰ ਕੀਤੇ ਤੁਹਾਡੇ ਸੰਪਰਕਾਂ ਬਾਰੇ ਡਾਟਾ ਪੜ੍ਹਨ ਦਿੰਦੀ ਹੈ। ਐਪਾਂ ਕੋਲ ਤੁਹਾਡੇ ਟੈਬਲੈੱਟ ਦੇ ਉਹਨਾਂ ਖਾਤਿਆਂ ਤੱਕ ਵੀ ਪਹੁੰਚ ਹੋਵੇਗੀ ਜਿਨ੍ਹਾਂ ਨੇ ਸੰਪਰਕ ਬਣਾਏ ਹਨ। ਇਸ ਵਿੱਚ ਤੁਹਾਡੇ ਵੱਲੋਂ ਸਥਾਪਤ ਕੀਤੀਆਂ ਐਪਾਂ ਵੱਲੋਂ ਬਣਾਏ ਗਏ ਖਾਤੇ ਸ਼ਾਮਲ ਹੋ ਸਕਦੇ ਹਨ। ਇਹ ਇਜਾਜ਼ਤ ਐਪਾਂ ਨੂੰ ਤੁਹਾਡਾ ਸੰਪਰਕ ਡਾਟਾ ਰੱਖਿਅਤ ਕਰਨ ਦਿੰਦੀ ਹੈ ਅਤੇ ਨੁਕਸਾਨਦੇਹ ਐਪਾਂ ਤੁਹਾਡੀ ਜਾਣਕਾਰੀ ਤੋਂ ਬਿਨਾਂ ਸੰਪਰਕ ਡਾਟਾ ਸਾਂਝਾ ਕਰ ਸਕਦੀਆਂ ਹਨ।"</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ Android TV ਡੀਵਾਈਸ \'ਤੇ ਸਟੋਰ ਕੀਤੇ ਤੁਹਾਡੇ ਸੰਪਰਕਾਂ ਬਾਰੇ ਡਾਟਾ ਪੜ੍ਹਨ ਦਿੰਦੀ ਹੈ। ਐਪਾਂ ਕੋਲ ਤੁਹਾਡੇ Android TV ਡੀਵਾਈਸ ਦੇ ਉਹਨਾਂ ਖਾਤਿਆਂ ਤੱਕ ਵੀ ਪਹੁੰਚ ਹੋਵੇਗੀ ਜਿਨ੍ਹਾਂ ਨੇ ਸੰਪਰਕ ਬਣਾਏ ਹਨ। ਇਸ ਵਿੱਚ ਤੁਹਾਡੇ ਵੱਲੋਂ ਸਥਾਪਤ ਕੀਤੀਆਂ ਐਪਾਂ ਵੱਲੋਂ ਬਣਾਏ ਗਏ ਖਾਤੇ ਸ਼ਾਮਲ ਹੋ ਸਕਦੇ ਹਨ। ਇਹ ਇਜਾਜ਼ਤ ਐਪਾਂ ਨੂੰ ਤੁਹਾਡਾ ਸੰਪਰਕ ਡਾਟਾ ਰੱਖਿਅਤ ਕਰਨ ਦਿੰਦੀ ਹੈ ਅਤੇ ਨੁਕਸਾਨਦੇਹ ਐਪਾਂ ਤੁਹਾਡੀ ਜਾਣਕਾਰੀ ਤੋਂ ਬਿਨਾਂ ਸੰਪਰਕ ਡਾਟਾ ਸਾਂਝਾ ਕਰ ਸਕਦੀਆਂ ਹਨ।"</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ ਫ਼ੋਨ \'ਤੇ ਸਟੋਰ ਕੀਤੇ ਤੁਹਾਡੇ ਸੰਪਰਕਾਂ ਬਾਰੇ ਡਾਟਾ ਪੜ੍ਹਨ ਦਿੰਦੀ ਹੈ। ਐਪਾਂ ਕੋਲ ਤੁਹਾਡੇ ਫ਼ੋਨ ਦੇ ਉਹਨਾਂ ਖਾਤਿਆਂ ਤੱਕ ਵੀ ਪਹੁੰਚ ਹੋਵੇਗੀ ਜਿਨ੍ਹਾਂ ਨੇ ਸੰਪਰਕ ਬਣਾਏ ਹਨ। ਇਸ ਵਿੱਚ ਤੁਹਾਡੇ ਵੱਲੋਂ ਸਥਾਪਤ ਕੀਤੀਆਂ ਐਪਾਂ ਵੱਲੋਂ ਬਣਾਏ ਗਏ ਖਾਤੇ ਸ਼ਾਮਲ ਹੋ ਸਕਦੇ ਹਨ। ਇਹ ਇਜਾਜ਼ਤ ਐਪਾਂ ਨੂੰ ਤੁਹਾਡਾ ਸੰਪਰਕ ਡਾਟਾ ਰੱਖਿਅਤ ਕਰਨ ਦਿੰਦੀ ਹੈ ਅਤੇ ਨੁਕਸਾਨਦੇਹ ਐਪਾਂ ਤੁਹਾਡੀ ਜਾਣਕਾਰੀ ਤੋਂ ਬਿਨਾਂ ਸੰਪਰਕ ਡਾਟਾ ਸਾਂਝਾ ਕਰ ਸਕਦੀਆਂ ਹਨ।"</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"ਆਪਣੇ ਸੰਪਰਕ ਸੰਸ਼ੋਧਿਤ ਕਰੋ"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"ਐਪ ਨੂੰ ਤੁਹਾਡੀ ਟੈਬਲੈੱਟ ਤੇ ਸਟੋਰ ਕੀਤੇ ਤੁਹਾਡੇ ਸੰਪਰਕਾਂ ਬਾਰੇ ਡਾਟਾ ਪੜ੍ਹਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਉਸ ਬਾਰੰਬਾਰਤਾ ਸਮੇਤ ਜਿਸ ਨਾਲ ਤੁਸੀਂ ਕਾਲ ਕੀਤੀ ਹੈ, ਈਮੇਲ ਕੀਤੀ ਹੈ ਜਾਂ ਖ਼ਾਸ ਵਿਅਕਤੀਆਂ ਨਾਲ ਹੋਰ ਤਰੀਕਿਆਂ ਨਾਲ ਸੰਚਾਰ ਕੀਤਾ। ਇਹ ਇਜਾਜ਼ਤ ਐਪਾਂ ਨੂੰ ਸੰਪਰਕ ਡਾਟਾ ਮਿਟਾਉਣ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ।"</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ Android TV ਡੀਵਾਈਸ \'ਤੇ ਸਟੋਰ ਕੀਤੇ ਤੁਹਾਡੇ ਸੰਪਰਕਾਂ ਬਾਰੇ ਡਾਟਾ ਸੋਧਣ ਦਿੰਦੀ ਹੈ, ਇਸ ਵਿੱਚ ਉਹ ਬਾਰੰਬਾਰਤਾ ਵੀ ਸ਼ਾਮਲ ਹੈ ਜਿਸ ਨਾਲ ਤੁਸੀਂ ਵਿਸ਼ੇਸ਼ ਸੰਪਰਕਾਂ ਨੂੰ ਕਾਲ ਕੀਤੀ ਹੈ, ਈਮੇਲ ਕੀਤੀ ਹੈ ਜਾਂ ਹੋਰ ਤਰੀਕਿਆਂ ਨਾਲ ਸੰਚਾਰ ਕੀਤਾ ਹੈ। ਇਹ ਇਜਾਜ਼ਤ ਐਪਾਂ ਨੂੰ ਸੰਪਰਕ ਡਾਟਾ ਮਿਟਾਉਣ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ।"</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ ਫ਼ੋਨ ਤੇ ਸਟੋਰ ਕੀਤੇ ਤੁਹਾਡੇ ਸੰਪਰਕਾਂ ਬਾਰੇ ਡਾਟਾ ਪੜ੍ਹਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਉਸ ਬਾਰੰਬਾਰਤਾ ਸਮੇਤ ਜਿਸ ਨਾਲ ਤੁਸੀਂ ਕਾਲ ਕੀਤੀ ਹੈ, ਈਮੇਲ ਕੀਤੀ ਹੈ ਜਾਂ ਖ਼ਾਸ ਵਿਅਕਤੀਆਂ ਨਾਲ ਹੋਰ ਤਰੀਕਿਆਂ ਨਾਲ ਸੰਚਾਰ ਕੀਤਾ। ਇਹ ਇਜਾਜ਼ਤ ਐਪਾਂ ਨੂੰ ਤੁਹਾਡਾ ਸੰਪਰਕ ਡਾਟਾ ਮਿਟਾਉਣ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ।"</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ ਟੈਬਲੈੱਟ \'ਤੇ ਸਟੋਰ ਕੀਤੇ ਤੁਹਾਡੇ ਸੰਪਰਕਾਂ ਬਾਰੇ ਡਾਟਾ ਸੋਧਣ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ। ਇਹ ਇਜਾਜ਼ਤ ਐਪਾਂ ਨੂੰ ਸੰਪਰਕ ਡਾਟਾ ਮਿਟਾਉਣ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ।"</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ Android TV ਡੀਵਾਈਸ \'ਤੇ ਸਟੋਰ ਕੀਤੇ ਤੁਹਾਡੇ ਸੰਪਰਕਾਂ ਬਾਰੇ ਡਾਟਾ ਸੋਧਣ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ। ਇਹ ਇਜਾਜ਼ਤ ਐਪਾਂ ਨੂੰ ਸੰਪਰਕ ਡਾਟਾ ਮਿਟਾਉਣ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ।"</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ ਫ਼ੋਨ \'ਤੇ ਸਟੋਰ ਕੀਤੇ ਤੁਹਾਡੇ ਸੰਪਰਕਾਂ ਬਾਰੇ ਡਾਟਾ ਸੋਧਣ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ। ਇਹ ਇਜਾਜ਼ਤ ਐਪਾਂ ਨੂੰ ਸੰਪਰਕ ਡਾਟਾ ਮਿਟਾਉਣ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ।"</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"ਕਾਲ ਲੌਗ ਪੜ੍ਹੋ"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"ਇਹ ਐਪ ਤੁਹਾਡਾ ਕਾਲ ਇਤਿਹਾਸ ਪੜ੍ਹ ਸਕਦੀ ਹੈ।"</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"ਕਾਲ ਲੌਗ ਲਿਖੋ"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"ਵਾਧੂ ਟਿਕਾਣਾ ਪ੍ਰਦਾਤਾ ਕਮਾਂਡਾਂ ਤੱਕ ਪਹੁੰਚ"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"ਐਪ ਨੂੰ ਵਾਧੂ ਟਿਕਾਣਾ ਪ੍ਰਦਾਤਾ ਕਮਾਂਡਾਂ ਤੱਕ ਪਹੁੰਚ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਹ ਐਪ ਨੂੰ GPS ਜਾਂ ਹੋਰ ਟਿਕਾਣਾ ਸਰੋਤਾਂ ਦੇ ਓਪਰੇਸ਼ਨ ਵਿੱਚ ਵਿਘਨ ਪਾਉਣ ਦੀ ਆਗਿਆ ਦੇ ਸਕਦਾ ਹੈ।"</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"ਸਿਰਫ਼ ਫੋਰਗ੍ਰਾਊਂਡ ਵਿੱਚ ਸਟੀਕ ਟਿਕਾਣੇ ਤੱਕ ਪਹੁੰਚ ਕਰੋ"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"ਇਹ ਐਪ ਫੋਰਗ੍ਰਾਉਂਡ ਵਿੱਚ ਹੋਣ \'ਤੇ ਹੀ ਤੁਹਾਡਾ ਸਟੀਕ ਟਿਕਾਣਾ ਪਤਾ ਕਰ ਸਕਦੀ ਹੈ। ਐਪ ਵੱਲੋਂ ਟਿਕਾਣਾ ਸੇਵਾਵਾਂ ਦੀ ਵਰਤੋਂ ਕਰਨ ਲਈ ਇਹ ਸੇਵਾਵਾਂ ਤੁਹਾਡੇ ਫ਼ੋਨ \'ਤੇ ਉਪਲਬਧ ਹੋਣੀਆਂ ਅਤੇ ਚਾਲੂ ਕੀਤੀਆਂ ਹੋਣੀਆਂ ਲਾਜ਼ਮੀ ਹਨ। ਇਸ ਨਾਲ ਬੈਟਰੀ ਦੀ ਖਪਤ ਵਧ ਸਕਦੀ ਹੈ।"</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"ਸਿਰਫ਼ ਫੋਰਗ੍ਰਾਊਂਡ ਵਿੱਚ ਅਨੁਮਾਨਿਤ ਟਿਕਾਣੇ ਤੱਕ ਪਹੁੰਚ ਕਰੋ (ਨੈੱਟਵਰਕ-ਆਧਾਰਿਤ)"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"ਇਹ ਐਪ ਨੈੱਟਵਰਕ ਸਰੋਤਾਂ ਜਿਵੇਂ ਕਿ ਸੈੱਲ ਟਾਵਰਾਂ ਅਤੇ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕਾਂ \'ਤੇ ਆਧਾਰਿਤ ਤੁਹਾਡਾ ਟਿਕਾਣਾ ਪਤਾ ਕਰ ਸਕਦੀ ਹੈ, ਪਰ ਸਿਰਫ਼ ਐਪ ਦੇ ਫੋਰਗ੍ਰਾਊਂਡ ਹੋਣ \'ਤੇ ਹੀ। ਐਪ ਵੱਲੋਂ ਟਿਕਾਣਾ ਸੇਵਾਵਾਂ ਦੀ ਵਰਤੋਂ ਕੀਤੇ ਜਾਣ ਦੇ ਯੋਗ ਹੋਣ ਲਈ ਇਹ ਸੇਵਾਵਾਂ ਤੁਹਾਡੀ ਟੈਬਲੈੱਟ \'ਤੇ ਉਪਲਬਧ ਹੋਣੀਆਂ ਅਤੇ ਚਾਲੂ ਕੀਤੀਆਂ ਹੋਣੀਆਂ ਲਾਜ਼ਮੀ ਹਨ।"</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"ਇਹ ਐਪ ਨੈੱਟਵਰਕ ਸਰੋਤਾਂ ਜਿਵੇਂ ਕਿ ਸੈੱਲ ਟਾਵਰਾਂ ਅਤੇ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕਾਂ \'ਤੇ ਆਧਾਰਿਤ ਤੁਹਾਡਾ ਟਿਕਾਣਾ ਪਤਾ ਕਰ ਸਕਦੀ ਹੈ, ਪਰ ਸਿਰਫ਼ ਐਪ ਦੇ ਫੋਰਗ੍ਰਾਊਂਡ ਹੋਣ \'ਤੇ ਹੀ। ਐਪ ਵੱਲੋਂ ਟਿਕਾਣਾ ਸੇਵਾਵਾਂ ਦੀ ਵਰਤੋਂ ਕੀਤੇ ਜਾਣ ਦੇ ਯੋਗ ਹੋਣ ਲਈ ਇਹ ਸੇਵਾਵਾਂ ਤੁਹਾਡੇ Android TV ਟੀਵੀ ਡੀਵਾਈਸ \'ਤੇ ਉਪਲਬਧ ਹੋਣੀਆਂ ਅਤੇ ਚਾਲੂ ਕੀਤੀਆਂ ਹੋਣੀਆਂ ਲਾਜ਼ਮੀ ਹਨ।"</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"ਇਹ ਐਪ ਨੈੱਟਵਰਕ ਸਰੋਤਾਂ ਜਿਵੇਂ ਕਿ ਸੈੱਲ ਟਾਵਰਾਂ ਅਤੇ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕਾਂ \'ਤੇ ਆਧਾਰਿਤ ਤੁਹਾਡਾ ਟਿਕਾਣਾ ਪਤਾ ਕਰ ਸਕਦੀ ਹੈ, ਪਰ ਸਿਰਫ਼ ਐਪ ਦੇ ਫੋਰਗ੍ਰਾਊਂਡ ਹੋਣ \'ਤੇ ਹੀ। ਐਪ ਵੱਲੋਂ ਟਿਕਾਣਾ ਸੇਵਾਵਾਂ ਦੀ ਵਰਤੋਂ ਕੀਤੇ ਜਾਣ ਦੇ ਯੋਗ ਹੋਣ ਲਈ ਇਹ ਸੇਵਾਵਾਂ ਤੁਹਾਡੇ ਫ਼ੋਨ \'ਤੇ ਉਪਲਬਧ ਹੋਣੀਆਂ ਅਤੇ ਚਾਲੂ ਕੀਤੀਆਂ ਹੋਣੀਆਂ ਲਾਜ਼ਮੀ ਹਨ।"</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"ਇਹ ਐਪ ਸਿਰਫ਼ ਉਦੋਂ ਤੁਹਾਡਾ ਸਟੀਕ ਟਿਕਾਣਾ ਪਤਾ ਕਰ ਸਕਦੀ ਹੈ, ਜਦੋਂ ਇਹ ਸਕ੍ਰੀਨ \'ਤੇ ਹੋਵੇ। ਐਪ ਦੇ ਵਰਤਣ ਲਈ ਟਿਕਾਣਾ ਸੇਵਾਵਾਂ ਦਾ ਚਾਲੂ ਹੋਣਾ ਅਤੇ ਤੁਹਾਡੇ ਡੀਵਾਈਸ \'ਤੇ ਉਪਲਬਧ ਹੋਣਾ ਲਾਜ਼ਮੀ ਹੈ। ਇਸ ਨਾਲ ਬੈਟਰੀ ਦੀ ਖਪਤ ਵਧ ਸਕਦੀ ਹੈ।"</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"ਸਿਰਫ਼ ਸਕ੍ਰੀਨ \'ਤੇ ਅੰਦਾਜ਼ਨ ਟਿਕਾਣੇ ਤੱਕ ਪਹੁੰਚ ਕਰੋ"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"ਇਹ ਐਪ ਸਿਰਫ਼ ਉਦੋਂ ਤੁਹਾਡਾ ਅੰਦਾਜ਼ਨ ਟਿਕਾਣਾ ਪਤਾ ਕਰ ਸਕਦੀ ਹੈ, ਜਦੋਂ ਇਹ ਸਕ੍ਰੀਨ \'ਤੇ ਹੋਵੇ। ਐਪ ਦੇ ਵਰਤਣ ਲਈ ਟਿਕਾਣਾ ਸੇਵਾਵਾਂ ਦਾ ਚਾਲੂ ਹੋਣਾ ਅਤੇ ਤੁਹਾਡੇ ਡੀਵਾਈਸ \'ਤੇ ਉਪਲਬਧ ਹੋਣਾ ਲਾਜ਼ਮੀ ਹੈ।"</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਟਿਕਾਣੇ ਤੱਕ ਪਹੁੰਚ"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"ਐਪ ਨੂੰ ਵਧੀਕ ਤੌਰ \'ਤੇ ਅਨੁਮਾਨਿਤ ਜਾਂ ਸਟੀਕ ਟਿਕਾਣੇ ਤੱਕ ਪਹੁੰਚ ਦੇਣ \'ਤੇ ਇਹ ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਚੱਲਣ ਵੇਲੇ ਟਿਕਾਣੇ ਤੱਕ ਪਹੁੰਚ ਕਰ ਸਕਦੀ ਹੈ।"</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"ਸਕ੍ਰੀਨ \'ਤੇ ਟਿਕਾਣੇ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਤੋਂ ਇਲਾਵਾ, ਇਹ ਐਪ ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਚੱਲਣ ਵੇਲੇ ਟਿਕਾਣੇ ਤੱਕ ਪਹੁੰਚ ਕਰ ਸਕਦੀ ਹੈ।"</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"ਆਪਣੀਆਂ ਆਡੀਓ ਸੈਟਿੰਗਾਂ ਬਦਲੋ"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"ਐਪ ਨੂੰ ਗਲੋਬਲ ਆਡੀਓ ਸੈਟਿੰਗਾਂ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ ਜਿਵੇਂ ਅਵਾਜ਼ ਅਤੇ ਆਊਟਪੁਟ ਲਈ ਕਿਹੜਾ ਸਪੀਕਰ ਵਰਤਿਆ ਜਾਂਦਾ ਹੈ।"</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">" ਆਡੀਓ ਰਿਕਾਰਡ ਕਰਨ"</string>
@@ -494,6 +491,8 @@
<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_preferredPaymentInfo" msgid="5274423844767445054">"ਤਰਜੀਹੀ NFC ਭੁਗਤਾਨਸ਼ੁਦਾ ਸੇਵਾ ਜਾਣਕਾਰੀ"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"ਐਪ ਨੂੰ ਤਰਜੀਹੀ NFC ਭੁਗਤਾਨਸ਼ੁਦਾ ਸੇਵਾ ਜਾਣਕਾਰੀ ਪ੍ਰਾਪਤ ਕਰਨ ਦਿੰਦਾ ਹੈ ਜਿਵੇਂ ਕਿ ਰਜਿਸਟਰ ਕੀਤੇ ਸਾਧਨ ਅਤੇ ਮੰਜ਼ਿਲ ਰਸਤਾ।"</string>
<string name="permlab_nfc" msgid="1904455246837674977">"ਨਜ਼ਦੀਕੀ ਖੇਤਰ ਸੰਚਾਰ ਤੇ ਨਿਯੰਤਰਣ ਪਾਓ"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"ਐਪ ਨੂੰ ਨਜ਼ਦੀਕੀ ਖੇਤਰ ਸੰਚਾਰ (NFC) ਟੈਗਾਂ, ਕਾਰਡਾਂ ਅਤੇ ਰੀਡਰਾਂ ਨਾਲ ਸੰਚਾਰ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"ਆਪਣਾ ਸਕ੍ਰੀਨ ਲਾਕ ਅਸਮਰੱਥ ਬਣਾਓ"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"ਪਹੁੰਚਯੋਗਤਾ ਸ਼ਾਰਟਕੱਟ ਨੇ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ਨੂੰ ਚਾਲੂ ਕੀਤਾ"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"ਪਹੁੰਚਯੋਗਤਾ ਸ਼ਾਰਟਕੱਟ ਨੇ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ਨੂੰ ਬੰਦ ਕੀਤਾ"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ਦੀ ਵਰਤੋਂ ਕਰਨ ਲਈ ਦੋਵੇਂ ਅਵਾਜ਼ ਕੁੰਜੀਆਂ ਨੂੰ 3 ਸਕਿੰਟਾਂ ਲਈ ਦਬਾਈ ਰੱਖੋ"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"ਪਹੁੰਚਯੋਗਤਾ ਬਟਨ \'ਤੇ ਟੈਪ ਕਰਕੇ ਵਰਤਣ ਲਈ ਕੋਈ ਸੇਵਾ ਚੁਣੋ:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"ਪਹੁੰਚਯੋਗਤਾ ਸੰਕੇਤ ਨਾਲ ਵਰਤਣ ਲਈ ਕੋਈ ਸੇਵਾ ਚੁਣੋ (ਦੋ ਉਂਗਲਾਂ ਨਾਲ ਸਕ੍ਰੀਨ ਦੇ ਹੇਠਾਂ ਤੋਂ ਉੱਪਰ ਵੱਲ ਸਕ੍ਰੋਲ ਕਰੋ):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"ਪਹੁੰਚਯੋਗਤਾ ਸੰਕੇਤ ਨਾਲ ਵਰਤਣ ਲਈ ਕੋਈ ਸੇਵਾ ਚੁਣੋ (ਤਿੰਨ ਉਂਗਲਾਂ ਨਾਲ ਸਕ੍ਰੀਨ ਦੇ ਹੇਠਾਂ ਤੋਂ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"ਸੇਵਾਵਾਂ ਵਿਚਾਲੇ ਅਦਲਾ-ਬਦਲੀ ਕਰਨ ਲਈ, ਪਹੁੰਚਯੋਗਤਾ ਬਟਨ \'ਤੇ ਸਪਰਸ਼ ਕਰਕੇ ਰੱਖੋ।"</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"ਸੇਵਾਵਾਂ ਵਿਚਾਲੇ ਅਦਲਾ-ਬਦਲੀ ਕਰਨ ਲਈ, ਦੋ ਉਂਗਲਾਂ ਨਾਲ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰਕੇ ਦਬਾਈ ਰੱਖੋ।"</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"ਸੇਵਾਵਾਂ ਵਿਚਾਲੇ ਅਦਲਾ-ਬਦਲੀ ਕਰਨ ਲਈ, ਤਿੰਨ ਉਂਗਲਾਂ ਨਾਲ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰਕੇ ਦਬਾਈ ਰੱਖੋ।"</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>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਹੋਈ"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"ਫ਼ਾਈਲਾਂ ਦੇਖਣ ਲਈ ਟੈਪ ਕਰੋ"</string>
<string name="pin_target" msgid="8036028973110156895">"ਪਿੰਨ ਕਰੋ"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"<xliff:g id="LABEL">%1$s</xliff:g> ਨੂੰ ਪਿੰਨ ਕਰੋ"</string>
<string name="unpin_target" msgid="3963318576590204447">"ਅਨਪਿੰਨ ਕਰੋ"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"<xliff:g id="LABEL">%1$s</xliff:g> ਨੂੰ ਅਨਪਿੰਨ ਕਰੋ"</string>
<string name="app_info" msgid="6113278084877079851">"ਐਪ ਜਾਣਕਾਰੀ"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"ਡੈਮੋ ਚਾਲੂ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"ਕੀ ਤੁਸੀਂ "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" ਵਿੱਚ ਇਹਨਾਂ ਆਈਟਮਾਂ ਨੂੰ ਅੱਪਡੇਟ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ: <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>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"ਰੱਖਿਅਤ ਕਰੋ"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"ਨਹੀਂ ਧੰਨਵਾਦ"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"ਹੁਣੇ ਨਹੀਂ"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"ਕਦੇ ਵੀ ਨਹੀਂ"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"ਅੱਪਡੇਟ ਕਰੋ"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"ਜਾਰੀ ਰੱਖੋ"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"ਪਾਸਵਰਡ"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਨੂੰ ਟੌਗਲ ਕਰੋ"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"ਲਾਕ ਸਕ੍ਰੀਨ"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"ਸਕ੍ਰੀਨਸ਼ਾਟ"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"ਪੌਪ-ਅੱਪ ਵਿੰਡੋ ਵਿੱਚ <xliff:g id="APP_NAME">%1$s</xliff:g> ਐਪ।"</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਦੀ ਸੁਰਖੀ ਪੱਟੀ।"</string>
</resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 4ff7cc419694..4f6e74824992 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -192,8 +192,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Brakuje aplikacji administratora profilu do pracy lub jest ona uszkodzona. Dlatego Twój profil służbowy i związane z nim dane zostały usunięte. Skontaktuj się ze swoim administratorem, by uzyskać pomoc."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Twój profil służbowy nie jest już dostępny na tym urządzeniu"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Zbyt wiele prób podania hasła"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Administrator odstąpił urządzenie do użytku osobistego"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Urządzenie jest zarządzane"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Twoja organizacja zarządza tym urządzeniem i może monitorować ruch w sieci. Kliknij, by dowiedzieć się więcej."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Twoje urządzenie zostanie wyczyszczone"</string>
@@ -387,13 +386,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Pozwala aplikacji wysyłać trwałe transmisje, które są zachowywane po ich zakończeniu. Nadmierne korzystanie z tej funkcji może powodować wolne lub niestabilne działanie urządzenia z Androidem TV z powodu użycia zbyt dużej ilości pamięci."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Pozwala aplikacji na wysyłanie transmisji trwałych, które pozostają aktywne po zakończeniu połączenia. Nadmierne używanie może spowolnić lub zdestabilizować telefon przez wymuszenie zbyt dużego użycia pamięci."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"odczytywanie kontaktów"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Pozwala aplikacji na odczyt danych o kontaktach zapisanych na tablecie, w tym informacji o częstotliwości rozmawiania, przesyłania e-maili i komunikowania się w inny sposób z poszczególnymi osobami. Aplikacje z tym uprawnieniem mogą zapisywać dane kontaktów, a złośliwe aplikacje mogą je udostępniać bez Twojej wiedzy."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Pozwala aplikacji odczytywać dane o Twoich kontaktach zapisanych na urządzeniu z Androidem TV, wraz z informacjami o tym, jak często dzwonisz lub piszesz e-maile do określonych osób albo komunikujesz się z nimi na inne sposoby. Aplikacje z tym uprawnieniem mogą zapisywać dane kontaktów, a złośliwe aplikacje mogą je udostępniać bez Twojej wiedzy."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Pozwala aplikacji na odczyt danych o kontaktach zapisanych na telefonie, w tym informacji o częstotliwości rozmawiania, przesyłania e-maili i komunikowania się w inny sposób z poszczególnymi osobami. Aplikacje z tym uprawnieniem mogą zapisywać dane kontaktów, a złośliwe aplikacje mogą je udostępniać bez Twojej wiedzy."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Pozwala aplikacji odczytywać dane Twoich kontaktów zapisane na tablecie. Aplikacje będą również miały dostęp do kont na tablecie, na których utworzono kontakty. Może to obejmować konta utworzone przez zainstalowane aplikacje. Aplikacje z tymi uprawnieniami mogą zapisywać dane kontaktów, a złośliwe aplikacje mogą je udostępniać bez Twojej wiedzy."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Pozwala aplikacji odczytywać dane Twoich kontaktów zapisane na urządzeniu z Androidem TV. Aplikacje będą również miały dostęp do kont na urządzeniu z Androidem TV, na których utworzono kontakty. Może to obejmować konta utworzone przez zainstalowane aplikacje. Aplikacje z tymi uprawnieniami mogą zapisywać dane kontaktów, a złośliwe aplikacje mogą je udostępniać bez Twojej wiedzy."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Pozwala aplikacji odczytywać dane Twoich kontaktów zapisane na telefonie. Aplikacje będą również miały dostęp do kont na telefonie, na których utworzono kontakty. Może to obejmować konta utworzone przez zainstalowane aplikacje. Aplikacje z tymi uprawnieniami mogą zapisywać dane kontaktów, a złośliwe aplikacje mogą je udostępniać bez Twojej wiedzy."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"modyfikowanie kontaktów"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Pozwala aplikacji na modyfikowanie danych o kontaktach zapisanych na tablecie, w tym informacji o częstotliwości rozmawiania, przesyłania e-maili i komunikowania się w inny sposób z poszczególnymi kontaktami. Aplikacje z tym uprawnieniem mogą usuwać dane kontaktów."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Pozwala aplikacji modyfikować dane o Twoich kontaktach zapisane na urządzeniu z Androidem TV, wraz z informacjami o tym, jak często dzwonisz lub piszesz e-maile do określonych osób albo komunikujesz się z nimi na inne sposoby. Aplikacje z tym uprawnieniem mogą usuwać dane kontaktów."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Pozwala aplikacji na modyfikowanie danych o kontaktach zapisanych na telefonie, w tym informacji o częstotliwości rozmawiania, przesyłania e-maili i komunikowania się w inny sposób z poszczególnymi kontaktami. Aplikacje z tym uprawnieniem mogą usuwać dane kontaktów."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Pozwala aplikacji odczytywać dane Twoich kontaktów zapisane na tablecie. Aplikacje z tymi uprawnieniami mogą usuwać dane kontaktów."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Pozwala aplikacji odczytywać dane Twoich kontaktów zapisane na urządzeniu z Androidem TV. Aplikacje z tymi uprawnieniami mogą usuwać dane kontaktów."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Pozwala aplikacji odczytywać dane Twoich kontaktów zapisane na telefonie. Aplikacje z tymi uprawnieniami mogą usuwać dane kontaktów."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"czytanie rejestru połączeń"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Ta aplikacja może odczytywać historię połączeń."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"zapisywanie rejestru połączeń"</string>
@@ -413,13 +412,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"dostęp do dodatkowych poleceń dostawcy informacji o lokalizacji"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Pozwala aplikacji na dostęp do dodatkowych poleceń dostawcy informacji o lokalizacji. Aplikacje z tym uprawnieniem mogą wpływać na działanie GPS-a lub innych źródeł lokalizacji."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"dostęp do dokładnej lokalizacji tylko na pierwszym planie"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Ta aplikacja może określić Twoją dokładną lokalizację tylko wtedy, gdy działa na pierwszym planie. Te usługi lokalizacyjne muszą być włączone i dostępne na telefonie, by aplikacja mogła z nich korzystać. Może to zwiększyć zużycie baterii."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"dostęp do przybliżonej lokalizacji (na podstawie sieci) tylko na pierwszym planie"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Ta aplikacja może określać Twoją lokalizację na podstawie źródeł sieciowych takich jak stacje bazowe i sieci Wi-Fi, ale tylko wtedy, gdy działa na pierwszym planie. Wymienione usługi lokalizacyjne muszą być włączone i dostępne na tablecie, by aplikacja mogła z nich korzystać."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Ta aplikacja może określać Twoją lokalizację na podstawie źródeł sieciowych takich jak stacje bazowe i sieci Wi-Fi, ale tylko wtedy, gdy działa na pierwszym planie. Aby aplikacja mogła korzystać z tych usług lokalizacyjnych, muszą one być włączone i dostępne na urządzeniu z Androidem TV."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Ta aplikacja może określać Twoją lokalizację na podstawie źródeł sieciowych takich jak stacje bazowe i sieci Wi-Fi, ale tylko wtedy, gdy działa na pierwszym planie. Wymienione usługi lokalizacyjne muszą być włączone i dostępne na telefonie, by aplikacja mogła z nich korzystać."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Ta aplikacja może określić Twoją dokładną lokalizację tylko wtedy, gdy działa na pierwszym planie. Usługi lokalizacyjne muszą być włączone i dostępne na urządzeniu, by aplikacja mogła z nich korzystać. Może to zwiększyć zużycie baterii."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"dostęp do przybliżonej lokalizacji tylko na pierwszym planie"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Ta aplikacja może określić Twoją przybliżoną lokalizację tylko wtedy, gdy działa na pierwszym planie. Usługi lokalizacyjne muszą być włączone i dostępne na urządzeniu, by aplikacja mogła z nich korzystać."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"dostęp do lokalizacji w tle"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Jeśli te uprawnienia zostaną przyznane wraz z dostępem do dokładnej lub przybliżonej lokalizacji, aplikacja będzie mogła uzyskiwać dostęp do lokalizacji podczas działania w tle."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Ta aplikacja może korzystać z lokalizacji, gdy działa w tle, niezależnie od dostępu do lokalizacji na pierwszym planie."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"zmienianie ustawień audio"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Pozwala aplikacji na modyfikowanie globalnych ustawień dźwięku, takich jak głośność oraz urządzenie wyjściowe."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"nagrywanie dźwięku"</string>
@@ -500,6 +497,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Pozwala aplikacji na dostęp do konfiguracji Bluetooth na tablecie oraz na nawiązywanie i akceptowanie połączeń ze sparowanych urządzeń."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Pozwala aplikacji odczytywać konfigurację Bluetootha na urządzeniu z Androidem TV oraz nawiązywać i akceptować połączenia ze sparowanymi urządzeniami."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Pozwala aplikacji na dostęp do konfiguracji Bluetooth na telefonie oraz na nawiązywanie i akceptowanie połączeń ze sparowanych urządzeń."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Informacje o preferowanych usługach płatniczych NFC"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Pozwala aplikacji uzyskiwać informacje o preferowanych usługach płatniczych NFC, np. zarejestrowanych pomocach i miejscach docelowych tras."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"kontrolowanie łączności Near Field Communication"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Pozwala aplikacji na komunikowanie się z tagami, kartami i czytnikami NFC (Near Field Communication)."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"wyłączanie blokady ekranu"</string>
@@ -1662,12 +1661,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"Skrót ułatwień dostępu wyłączył usługę <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"Skrót ułatwień dostępu wyłączył usługę <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Naciśnij i przytrzymaj oba przyciski głośności przez trzy sekundy, by użyć usługi <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Wybierz usługę używaną po kliknięciu przycisku ułatwień dostępu:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Wybierz usługę używaną w przypadku gestu ułatwień dostępu (przesunięcie dwoma palcami z dołu ekranu w górę):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Wybierz usługę, której chcesz używać w połączeniu z gestami ułatwień dostępu (przesuń trzema palcami z dołu ekranu w górę):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Aby przełączać usługi, naciśnij i przytrzymaj przycisk ułatwień dostępu."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Aby przełączać usługi, przesuń dwoma palcami w górę i przytrzymaj."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Aby przełączyć usługi, przesuń trzema palcami w górę i przytrzymaj."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Powiększenie"</string>
<string name="user_switched" msgid="7249833311585228097">"Bieżący użytkownik: <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="1912993630661332336">"Przełączam na użytkownika <xliff:g id="NAME">%1$s</xliff:g>…"</string>
@@ -1926,7 +1919,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Połączono z: <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Dotknij, by wyświetlić pliki"</string>
<string name="pin_target" msgid="8036028973110156895">"Przypnij"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Przypnij: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Odepnij"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Odepnij: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"O aplikacji"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Uruchamiam tryb demo…"</string>
@@ -1971,6 +1966,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Zaktualizować w: "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" te elementy: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> i <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Zapisz"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Nie, dziękuję"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Nie teraz"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Nigdy"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Zaktualizuj"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Dalej"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"hasło"</string>
@@ -2068,5 +2065,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Przełącz podzielony ekran"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Ekran blokady"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Zrzut ekranu"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> w wyskakującym okienku."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Pasek napisów w aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 1750d2a92de3..f4c9e3436eb7 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"O app para administrador do perfil de trabalho não foi encontrado ou está corrompido. Consequentemente, seu perfil de trabalho e os dados relacionados foram excluídos. Entre em contato com seu administrador para receber assistência."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Seu perfil de trabalho não está mais disponível neste dispositivo"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Muitas tentativas de senha"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"O administrador renunciou ao dispositivo para uso pessoal"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"O dispositivo é gerenciado"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Sua organização gerencia este dispositivo e pode monitorar o tráfego de rede. Toque para ver detalhes."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Seu dispositivo será limpo"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Permite ao app enviar transmissões fixas, que permanecem após o fim da transmissão. O uso excessivo pode causar lentidão ou instabilidade no seu dispositivo Android TV, devido ao aumento do uso de memória."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Permite que o app envie transmissões fixas, que permanecem depois que a transmissão termina. O uso excessivo pode deixar o telefone lento ou instável, fazendo com que ele use muita memória."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"ler seus contatos"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Permite que o app leia dados dos contatos armazenados no tablet, incluindo a frequência com que você chamou, enviou e-mails ou se comunicou de qualquer outra forma com indivíduos específicos. Esta permissão autoriza o app a salvar seus dados de contato, e apps maliciosos podem compartilhar esses dados de contato sem seu conhecimento."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Permite que o app leia os dados sobre os contatos armazenados no seu dispositivo Android TV, incluindo a frequência de chamadas, e-mails e outras comunicações com pessoas específicas. Essa autorização permite que os apps salvem os dados dos seus contatos,. Tenha cuidado porque apps maliciosos podem compartilhar esses dados sem seu conhecimento."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Permite que o app leia dados dos contatos armazenados no telefone, incluindo a frequência com que você chamou, enviou e-mails ou se comunicou de qualquer outra forma com indivíduos específicos. Esta permissão autoriza o app a salvar seus dados de contato, e apps maliciosos podem compartilhar esses dados de contato sem seu conhecimento."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Permite que o app leia dados sobre seus contatos armazenados no tablet. Os apps também terão acesso às contas no tablet que criaram contatos. Isso pode incluir contas criadas pelos apps que você instalou. Essa permissão autoriza os apps a salvarem os dados dos seus contatos, e apps maliciosos podem compartilhar esses dados sem seu conhecimento."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Permite que o app leia dados sobre seus contatos armazenados no dispositivo Android TV. Os apps também terão acesso às contas no dispositivo Android TV que criaram contatos. Isso pode incluir contas criadas pelos apps que você instalou. Essa permissão autoriza os apps a salvarem os dados dos seus contatos, e apps maliciosos podem compartilhar esses dados sem seu conhecimento."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Permite que o app leia dados sobre seus contatos armazenados no smartphone. Os apps também terão acesso às contas no smartphone que criaram contatos. Isso pode incluir contas criadas pelos apps que você instalou. Essa permissão autoriza os apps a salvarem os dados dos seus contatos, e apps maliciosos podem compartilhar esses dados sem seu conhecimento."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"modificar seus contatos"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Permite que o app modifique os dados sobre os contatos armazenados no tablet, incluindo a frequência com que você fez chamadas, enviou e-mails ou se comunicou de outras formas com contatos específicos. Esta permissão autoriza o app a excluir dados de contatos."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Permite que o app modifique os dados dos contatos armazenados no seu dispositivo Android TV, incluindo a frequência de chamadas, e-mails e outras comunicações com contatos específicos. Essa permissão autoriza os apps a excluir dados dos contatos."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Permite que o app modifique os dados dos contatos armazenados no telefone, incluindo a frequência com que você fez chamadas, enviou e-mails ou se comunicou de outras formas com contatos específicos. Esta permissão autoriza o app a excluir dados de contatos."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Permite que o app modifique os dados sobre os contatos armazenados no tablet. Essa permissão autoriza os apps a excluírem dados de contato."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Permite que o app modifique os dados sobre os contatos armazenados no dispositivo Android TV. Essa permissão autoriza os apps a excluírem dados de contato."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Permite que o app modifique os dados sobre os contatos armazenados no smartphone. Essa permissão autoriza os apps a excluírem dados de contato."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"ler registro de chamadas"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Este app pode ler seu histórico de chamadas."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"salvar no registo de chamadas"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"acessar comandos extras do provedor de localização"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Permite que o app acesse comandos do provedor não relacionados à localização. Isso pode permitir que o app interfira no funcionamento do GPS ou de outras fontes de localização."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"acessar localização precisa apenas em primeiro plano"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Este app pode ver sua localização exata a qualquer momento apenas quando está em primeiro plano. Esses serviços de localização precisam estar ativados e disponíveis no seu smartphone para que o app possa usá-los. Isso pode aumentar o consumo de bateria."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"acessar localização aproximada (baseada em rede) apenas em primeiro plano"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Esse app pode acessar sua localização com base em fontes de rede, como torres de celular e redes Wi-Fi, mas apenas quando está em primeiro plano. Esses serviços de localização precisam estar ativados e disponíveis no seu tablet para que o app possa usá-los."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Esse app pode acessar sua localização com base em fontes de rede, como torres de celular e redes Wi-Fi, mas apenas quando está em primeiro plano. Esses serviços de localização precisam estar ativados e disponíveis no seu dispositivo Android TV para que o app possa usá-los."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Esse app pode acessar sua localização com base em fontes de rede, como torres de celular e redes Wi-Fi, mas apenas quando está em primeiro plano. Esses serviços de localização precisam estar ativados e disponíveis no seu smartphone para que o app possa usá-los."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Este app pode ver seu local exato apenas quando está em primeiro plano. Os \"Serviços de localização\" precisam estar ativados e disponíveis no seu dispositivo para que o app possa usá-los. Isso pode aumentar o consumo de bateria."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"acessar local aproximado apenas em primeiro plano"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Este app poderá acessar seu local aproximado somente quando estiver em primeiro plano. Os \"Serviços de localização\" precisam estar ativados e disponíveis no dispositivo para que o app possa usá-los."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"acessar a localização em segundo plano"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Se essa permissão for concedida, além do acesso à localização precisa ou aproximada, o app poderá acessar a localização durante a execução em segundo plano."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Esse app pode acessar o local em segundo plano, além do acesso em primeiro plano."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"alterar as suas configurações de áudio"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Permite que o app modifique configurações de áudio globais como volume e alto-falantes de saída."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"gravar áudio"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Permite que o app acesse a configuração do Bluetooth no tablet, além de fazer e aceitar conexões com dispositivos pareados."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Permite que o app acesse a configuração do Bluetooth no dispositivo Android TV, além de fazer e aceitar conexões com dispositivos pareados."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Permite que o app acesse a configuração do Bluetooth no telefone, além de fazer e aceitar conexões com dispositivos pareados."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Informações preferidas de serviço de pagamento por NFC"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Permite que o app acesse as informações preferidas de serviço de pagamento por NFC, como auxílios registrados ou destinos de trajetos."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"controlar a comunicação a curta distância"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Permite que o app se comunique com leitores, cartões e etiqueta NFC (comunicação a curta distância)."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"desativar o bloqueio de tela"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"O atalho de acessibilidade ativou o <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"O atalho de acessibilidade desativou o <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Toque nos dois botões de volume e os mantenha pressionados por três segundo para usar o <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Escolha um serviço a ser usado quando você toca no botão Acessibilidade:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Escolha um serviço para usar com o gesto de acessibilidade (deslizar de baixo para cima na tela com dois dedos):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Escolha um serviço para usar com o gesto de acessibilidade (deslizar de baixo para cima na tela com três dedos):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Para alternar entre serviços, toque no botão de acessibilidade e mantenha-o pressionado."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Para alternar entre serviços, deslize de baixo para cima na tela com dois dedos sem soltar."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Para alternar entre serviços, deslize de baixo para cima na tela com três dedos sem soltar."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Ampliação"</string>
<string name="user_switched" msgid="7249833311585228097">"Usuário atual <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="1912993630661332336">"Alternando para <xliff:g id="NAME">%1$s</xliff:g>…"</string>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Conectado a <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Toque para ver os arquivos"</string>
<string name="pin_target" msgid="8036028973110156895">"Fixar guia"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Fixar <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Liberar guia"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Liberar <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Informações do app"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Iniciando demonstração…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Atualizar estes itens em "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Salvar"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Não, obrigado"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Agora não"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Nunca"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Atualizar"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Continuar"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"senha"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Ativar tela dividida"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Bloquear tela"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Capturar tela"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"App <xliff:g id="APP_NAME">%1$s</xliff:g> na janela pop-up."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Barra de legendas do app <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 5c21c0dc0445..65913cec79ac 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"A aplicação de administração do perfil de trabalho está em falta ou danificada. Consequentemente, o seu perfil de trabalho e os dados relacionados foram eliminados. Contacte o gestor para obter assistência."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"O seu perfil de trabalho já não está disponível neste dispositivo"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Demasiadas tentativas de introdução da palavra-passe"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"O administrador anulou o dispositivo para utilização pessoal."</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"O dispositivo é gerido"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"A sua entidade gere este dispositivo e pode monitorizar o tráfego de rede. Toque para obter mais detalhes."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"O seu dispositivo será apagado"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Permite à aplicação enviar transmissões fixas que permanecem após o fim da transmissão. Uma utilização excessiva pode tornar o seu dispositivo Android TV lento ou instável, fazendo com que utilize demasiada memória."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Permite que a aplicação envie difusões fixas, que permanecem após o fim da difusão. Uma utilização excessiva pode tornar o telemóvel lento ou instável, fazendo com que utilize demasiada memória."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"ler os contactos"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Permite que a aplicação leia dados acerca de contactos guardados no tablet, incluindo a frequência com que telefonou, enviou emails ou comunicou através de outras formas com determinadas pessoas. Esta autorização permite que a aplicação guarde dados de contactos e as aplicações maliciosas podem partilhar dados de contactos sem o seu conhecimento."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Permite à aplicação ler dados acerca dos contactos armazenados no seu dispositivo Android TV, incluindo a frequência com que efetuou chamadas, enviou emails ou comunicou de outras formas com indivíduos específicos. Esta autorização permite às aplicações guardarem dados de contactos e as aplicações maliciosas podem partilhá-los sem o seu conhecimento."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Permite que a aplicação leia dados acerca de contactos guardados no telemóvel, incluindo a frequência com que telefonou, enviou emails ou comunicou através de outras formas com determinadas pessoas. Esta autorização permite que a aplicação guarde dados de contactos e as aplicações maliciosas podem partilhar dados de contactos sem o seu conhecimento."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Permite à aplicação ler dados acerca dos contactos armazenados no seu tablet. As aplicações também terão acesso às contas no tablet que criaram contactos. Pode incluir contas criadas pelas aplicações instaladas. Esta autorização permite às aplicações guardarem dados de contactos e as aplicações maliciosas podem partilhá-los sem o seu conhecimento."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Permite à aplicação ler dados acerca dos contactos armazenados no seu dispositivo Android TV. As aplicações terão acesso às contas no dispositivo Android TV que criaram contactos. Pode incluir contas criadas pelas aplicações instaladas. Esta autorização permite às aplicações guardarem dados de contactos e as aplicações maliciosas podem partilhá-los sem o seu conhecimento."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Permite à aplicação ler dados acerca dos contactos armazenados no seu telemóvel. As aplicações também terão acesso às contas no telemóvel que criaram contactos. Pode incluir contas criadas pelas aplicações instaladas. Esta autorização permite às aplicações guardarem dados de contactos e as aplicações maliciosas podem partilhá-los sem o seu conhecimento."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"modificar os contactos"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Permite que a aplicação modifique dados acerca dos contactos guardados no tablet, incluindo a frequência com que telefonou, enviou emails ou comunicou através de outras formas com determinadas pessoas. Esta autorização permite que as aplicações eliminem dados de contactos."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Permite à aplicação modificar dados acerca dos contactos armazenados no seu dispositivo Android TV, incluindo a frequência com que efetuou chamadas, enviou emails ou comunicou de outras formas com pessoas específicas. Esta autorização permite às aplicações eliminarem dados de contactos."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Permite que a aplicação modifique dados acerca dos contactos guardados no telemóvel, incluindo a frequência com que telefonou, enviou emails ou comunicou através de outras formas com determinadas pessoas. Esta autorização permite que as aplicações eliminem dados de contactos."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Permite que a aplicação modifique dados acerca dos contactos armazenados no tablet. Esta autorização permite que as aplicações eliminem dados de contactos."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Permite à aplicação modificar dados acerca dos contactos armazenados no seu dispositivo Android TV. Esta autorização permite que as aplicações eliminem dados de contactos."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Permite que a aplicação modifique dados acerca dos contactos guardados no telemóvel. Esta autorização permite que as aplicações eliminem dados de contactos."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"ler registo de chamadas"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Esta aplicação pode ler o seu histórico de chamadas."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"escrever registo de chamadas"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"aceder a comandos adicionais do fornecedor de localização"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Permite que a aplicação aceda a comandos adicionais do fornecedor de localização. Esta opção pode permitir que a aplicação interfira com o funcionamento do GPS ou de outras fontes de localização."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"apenas aceder à localização exata em primeiro plano"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Esta aplicação apenas pode obter a sua localização exata quando estiver em primeiro plano. É necessário que estes Serviços de localização estejam ativados e disponíveis no seu telemóvel para que a aplicação os possa utilizar. Esta ação pode aumentar o consumo da bateria."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"aceder à localização aproximada (baseada na rede) apenas em primeiro plano"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Esta aplicação pode obter a sua localização com base em fontes de rede, tais como torres de redes móveis e redes Wi-Fi, mas apenas quando estiver em primeiro plano. É necessário que estes Serviços de localização estejam ativados e disponíveis no seu tablet para que a aplicação os possa utilizar."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Esta aplicação pode obter a sua localização com base em fontes de rede, tais como torres de redes móveis e redes Wi-Fi, mas apenas quando estiver em primeiro plano. É necessário que estes Serviços de localização estejam ativados e disponíveis no seu dispositivo Android TV para que a aplicação os possa utilizar."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Esta aplicação pode obter a sua localização com base em fontes de rede, tais como torres de redes móveis e redes Wi-Fi, mas apenas quando estiver em primeiro plano. É necessário que estes Serviços de localização estejam ativados e disponíveis no seu telemóvel para que a aplicação os possa utilizar."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Esta aplicação apenas pode obter a sua localização exata quando estiver em primeiro plano. É necessário que os Serviços de localização estejam ativados e disponíveis no seu dispositivo para que a aplicação os possa utilizar. Esta ação pode aumentar o consumo da bateria."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"apenas aceder à localização aproximada em primeiro plano"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Esta aplicação apenas pode obter a sua localização aproximada quando estiver em primeiro plano. É necessário que os Serviços de localização estejam ativados e disponíveis para que a aplicação os possa utilizar."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"aceder à localização em segundo plano"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Se tal for concedido em conjunto com o acesso à localização aproximada ou exata, a aplicação pode aceder à localização mesmo estando em segundo plano."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Esta aplicação pode aceder à localização mesmo estando em segundo plano, além do acesso à localização em primeiro plano."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"alterar as suas definições de áudio"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Permite que a aplicação modifique definições de áudio globais, tais como o volume e qual o altifalante utilizado para a saída de som."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"gravar áudio"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Permite que a aplicação visualize a configuração do Bluetooth no tablet e que estabeleça e aceite ligações com dispositivos emparelhados."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Permite que a aplicação visualize a configuração do Bluetooth no seu dispositivo Android TV e que estabeleça e aceite ligações com dispositivos sincronizados."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Permite que a aplicação visualize a configuração do Bluetooth no telemóvel e que estabeleça e aceite ligações com dispositivos emparelhados."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Informações de serviços de pagamento com NFC preferenciais"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Permite que a aplicação obtenha informações de serviços de pagamento com NFC preferenciais, como apoios registados e destino da rota."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"controlo Near Field Communication"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Permite que a aplicação comunique com etiquetas, cartões e leitores Near Field Communication (NFC)."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"desativar o bloqueio do ecrã"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"O Atalho de acessibilidade ativou o serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"O Atalho de acessibilidade desativou o serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Prima sem soltar as teclas de volume durante três segundos para utilizar o serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Escolha o serviço a utilizar quando tocar no botão de acessibilidade:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Escolha o serviço a utilizar com o gesto de acessibilidade (deslize rapidamente com dois dedos para cima a partir da parte inferior do ecrã):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Escolha o serviço a utilizar com o gesto de acessibilidade (deslize rapidamente com três dedos para cima a partir da parte inferior do ecrã):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Para alternar entre serviços, toque sem soltar no botão de acessibilidade."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Para alternar entre serviços, deslize rapidamente com dois dedos para cima sem soltar."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Para alternar entre serviços, deslize rapidamente com três dedos para cima sem soltar."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Ampliação"</string>
<string name="user_switched" msgid="7249833311585228097">"<xliff:g id="NAME">%1$s</xliff:g> do utilizador atual."</string>
<string name="user_switching_message" msgid="1912993630661332336">"A mudar para <xliff:g id="NAME">%1$s</xliff:g>…"</string>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Ligado a <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Tocar para ver ficheiros"</string>
<string name="pin_target" msgid="8036028973110156895">"Fixar"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Fixar <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Soltar"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Soltar <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Info. da aplicação"</string>
<string name="negative_duration" msgid="1938335096972945232">"-<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"A iniciar a demonstração…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Pretende atualizar estes itens em "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Guardar"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Não, obrigado"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Agora não"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Nunca"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Atualizar"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Continuar"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"palavra-passe"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Ativar/desativar o ecrã dividido"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Ecrã de bloqueio"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Captura de ecrã"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"Aplicação <xliff:g id="APP_NAME">%1$s</xliff:g> numa janela de pop-up."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Barra de legendas da aplicação <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 1750d2a92de3..f4c9e3436eb7 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"O app para administrador do perfil de trabalho não foi encontrado ou está corrompido. Consequentemente, seu perfil de trabalho e os dados relacionados foram excluídos. Entre em contato com seu administrador para receber assistência."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Seu perfil de trabalho não está mais disponível neste dispositivo"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Muitas tentativas de senha"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"O administrador renunciou ao dispositivo para uso pessoal"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"O dispositivo é gerenciado"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Sua organização gerencia este dispositivo e pode monitorar o tráfego de rede. Toque para ver detalhes."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Seu dispositivo será limpo"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Permite ao app enviar transmissões fixas, que permanecem após o fim da transmissão. O uso excessivo pode causar lentidão ou instabilidade no seu dispositivo Android TV, devido ao aumento do uso de memória."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Permite que o app envie transmissões fixas, que permanecem depois que a transmissão termina. O uso excessivo pode deixar o telefone lento ou instável, fazendo com que ele use muita memória."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"ler seus contatos"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Permite que o app leia dados dos contatos armazenados no tablet, incluindo a frequência com que você chamou, enviou e-mails ou se comunicou de qualquer outra forma com indivíduos específicos. Esta permissão autoriza o app a salvar seus dados de contato, e apps maliciosos podem compartilhar esses dados de contato sem seu conhecimento."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Permite que o app leia os dados sobre os contatos armazenados no seu dispositivo Android TV, incluindo a frequência de chamadas, e-mails e outras comunicações com pessoas específicas. Essa autorização permite que os apps salvem os dados dos seus contatos,. Tenha cuidado porque apps maliciosos podem compartilhar esses dados sem seu conhecimento."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Permite que o app leia dados dos contatos armazenados no telefone, incluindo a frequência com que você chamou, enviou e-mails ou se comunicou de qualquer outra forma com indivíduos específicos. Esta permissão autoriza o app a salvar seus dados de contato, e apps maliciosos podem compartilhar esses dados de contato sem seu conhecimento."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Permite que o app leia dados sobre seus contatos armazenados no tablet. Os apps também terão acesso às contas no tablet que criaram contatos. Isso pode incluir contas criadas pelos apps que você instalou. Essa permissão autoriza os apps a salvarem os dados dos seus contatos, e apps maliciosos podem compartilhar esses dados sem seu conhecimento."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Permite que o app leia dados sobre seus contatos armazenados no dispositivo Android TV. Os apps também terão acesso às contas no dispositivo Android TV que criaram contatos. Isso pode incluir contas criadas pelos apps que você instalou. Essa permissão autoriza os apps a salvarem os dados dos seus contatos, e apps maliciosos podem compartilhar esses dados sem seu conhecimento."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Permite que o app leia dados sobre seus contatos armazenados no smartphone. Os apps também terão acesso às contas no smartphone que criaram contatos. Isso pode incluir contas criadas pelos apps que você instalou. Essa permissão autoriza os apps a salvarem os dados dos seus contatos, e apps maliciosos podem compartilhar esses dados sem seu conhecimento."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"modificar seus contatos"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Permite que o app modifique os dados sobre os contatos armazenados no tablet, incluindo a frequência com que você fez chamadas, enviou e-mails ou se comunicou de outras formas com contatos específicos. Esta permissão autoriza o app a excluir dados de contatos."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Permite que o app modifique os dados dos contatos armazenados no seu dispositivo Android TV, incluindo a frequência de chamadas, e-mails e outras comunicações com contatos específicos. Essa permissão autoriza os apps a excluir dados dos contatos."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Permite que o app modifique os dados dos contatos armazenados no telefone, incluindo a frequência com que você fez chamadas, enviou e-mails ou se comunicou de outras formas com contatos específicos. Esta permissão autoriza o app a excluir dados de contatos."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Permite que o app modifique os dados sobre os contatos armazenados no tablet. Essa permissão autoriza os apps a excluírem dados de contato."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Permite que o app modifique os dados sobre os contatos armazenados no dispositivo Android TV. Essa permissão autoriza os apps a excluírem dados de contato."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Permite que o app modifique os dados sobre os contatos armazenados no smartphone. Essa permissão autoriza os apps a excluírem dados de contato."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"ler registro de chamadas"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Este app pode ler seu histórico de chamadas."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"salvar no registo de chamadas"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"acessar comandos extras do provedor de localização"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Permite que o app acesse comandos do provedor não relacionados à localização. Isso pode permitir que o app interfira no funcionamento do GPS ou de outras fontes de localização."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"acessar localização precisa apenas em primeiro plano"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Este app pode ver sua localização exata a qualquer momento apenas quando está em primeiro plano. Esses serviços de localização precisam estar ativados e disponíveis no seu smartphone para que o app possa usá-los. Isso pode aumentar o consumo de bateria."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"acessar localização aproximada (baseada em rede) apenas em primeiro plano"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Esse app pode acessar sua localização com base em fontes de rede, como torres de celular e redes Wi-Fi, mas apenas quando está em primeiro plano. Esses serviços de localização precisam estar ativados e disponíveis no seu tablet para que o app possa usá-los."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Esse app pode acessar sua localização com base em fontes de rede, como torres de celular e redes Wi-Fi, mas apenas quando está em primeiro plano. Esses serviços de localização precisam estar ativados e disponíveis no seu dispositivo Android TV para que o app possa usá-los."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Esse app pode acessar sua localização com base em fontes de rede, como torres de celular e redes Wi-Fi, mas apenas quando está em primeiro plano. Esses serviços de localização precisam estar ativados e disponíveis no seu smartphone para que o app possa usá-los."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Este app pode ver seu local exato apenas quando está em primeiro plano. Os \"Serviços de localização\" precisam estar ativados e disponíveis no seu dispositivo para que o app possa usá-los. Isso pode aumentar o consumo de bateria."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"acessar local aproximado apenas em primeiro plano"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Este app poderá acessar seu local aproximado somente quando estiver em primeiro plano. Os \"Serviços de localização\" precisam estar ativados e disponíveis no dispositivo para que o app possa usá-los."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"acessar a localização em segundo plano"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Se essa permissão for concedida, além do acesso à localização precisa ou aproximada, o app poderá acessar a localização durante a execução em segundo plano."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Esse app pode acessar o local em segundo plano, além do acesso em primeiro plano."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"alterar as suas configurações de áudio"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Permite que o app modifique configurações de áudio globais como volume e alto-falantes de saída."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"gravar áudio"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Permite que o app acesse a configuração do Bluetooth no tablet, além de fazer e aceitar conexões com dispositivos pareados."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Permite que o app acesse a configuração do Bluetooth no dispositivo Android TV, além de fazer e aceitar conexões com dispositivos pareados."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Permite que o app acesse a configuração do Bluetooth no telefone, além de fazer e aceitar conexões com dispositivos pareados."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Informações preferidas de serviço de pagamento por NFC"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Permite que o app acesse as informações preferidas de serviço de pagamento por NFC, como auxílios registrados ou destinos de trajetos."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"controlar a comunicação a curta distância"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Permite que o app se comunique com leitores, cartões e etiqueta NFC (comunicação a curta distância)."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"desativar o bloqueio de tela"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"O atalho de acessibilidade ativou o <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"O atalho de acessibilidade desativou o <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Toque nos dois botões de volume e os mantenha pressionados por três segundo para usar o <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Escolha um serviço a ser usado quando você toca no botão Acessibilidade:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Escolha um serviço para usar com o gesto de acessibilidade (deslizar de baixo para cima na tela com dois dedos):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Escolha um serviço para usar com o gesto de acessibilidade (deslizar de baixo para cima na tela com três dedos):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Para alternar entre serviços, toque no botão de acessibilidade e mantenha-o pressionado."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Para alternar entre serviços, deslize de baixo para cima na tela com dois dedos sem soltar."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Para alternar entre serviços, deslize de baixo para cima na tela com três dedos sem soltar."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Ampliação"</string>
<string name="user_switched" msgid="7249833311585228097">"Usuário atual <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="1912993630661332336">"Alternando para <xliff:g id="NAME">%1$s</xliff:g>…"</string>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Conectado a <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Toque para ver os arquivos"</string>
<string name="pin_target" msgid="8036028973110156895">"Fixar guia"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Fixar <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Liberar guia"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Liberar <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Informações do app"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Iniciando demonstração…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Atualizar estes itens em "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Salvar"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Não, obrigado"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Agora não"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Nunca"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Atualizar"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Continuar"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"senha"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Ativar tela dividida"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Bloquear tela"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Capturar tela"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"App <xliff:g id="APP_NAME">%1$s</xliff:g> na janela pop-up."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Barra de legendas do app <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 397525a3faf3..5b50ef733a5f 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -190,8 +190,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Aplicația de administrare a profilului de serviciu lipsește sau este deteriorată. Prin urmare, profilul de serviciu și datele asociate au fost șterse. Pentru asistență, contactați administratorul."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Profilul de serviciu nu mai este disponibil pe acest dispozitiv"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Prea multe încercări de introducere a parolei"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Administratorul a retras dispozitivul pentru uz personal"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Dispozitivul este gestionat"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Organizația dvs. gestionează acest dispozitiv și poate monitoriza traficul în rețea. Atingeți pentru mai multe detalii."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Datele de pe dispozitiv vor fi șterse"</string>
@@ -384,13 +383,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Permite aplicației să trimită mesaje difuzate persistente, care se păstrează după terminarea difuzării mesajului. Utilizarea excesivă a acestei funcții poate să încetinească sau să destabilizeze dispozitivul Android TV, determinându-l să utilizeze prea multă memorie."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Permite aplicației să trimită mesaje difuzate persistente, care se păstrează după terminarea difuzării mesajului. Utilizarea excesivă a acestei funcții poate să încetinească sau să destabilizeze telefonul, determinându-l să utilizeze prea multă memorie."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"citește agenda"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Permite aplicației să citească datele despre persoanele din agenda stocată pe tabletă, inclusiv frecvența cu care ați apelat, ați trimis e-mailuri sau ați comunicat în alte moduri cu anumite persoane. Cu această permisiune aplicația salvează datele dvs. de contact, iar aplicațiile rău intenționate pot distribui datele de contact fără știrea dvs."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Permite aplicației să citească datele despre persoanele de contact salvate pe dispozitivul Android TV, inclusiv frecvența cu care ați apelat, ați trimis e-mailuri sau ați comunicat în alte moduri cu anumite persoane. Cu această permisiune, aplicațiile pot salva datele de contact, iar aplicațiile rău-intenționate pot permite accesul la datele de contact fără cunoștința dvs."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Permite aplicației să citească datele despre persoanele din agenda stocată pe telefon, inclusiv frecvența cu care ați apelat, ați trimis e-mailuri sau ați comunicat în alte moduri cu anumite persoane. Cu această permisiune aplicația salvează datele dvs. de contact, iar aplicațiile rău intenționate pot distribui datele de contact fără știrea dvs."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Permite aplicației să citească datele despre persoanele din agenda stocată pe tabletă. Aplicațiile vor avea și acces la conturile de pe tabletă care au creat agenda. Aici pot fi incluse conturile create de aplicațiile pe care le-ați instalat. Cu această permisiune, aplicațiile pot salva datele de contact, iar aplicațiile rău-intenționate pot permite accesul la datele de contact fără cunoștința dvs."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Permite aplicației să citească datele despre persoanele de contact din agenda stocată pe dispozitivul Android TV. Aplicațiile vor avea și acces la conturile de pe dispozitivul Android TV care au creat agenda. Aici pot fi incluse conturile create de aplicațiile pe care le-ați instalat. Cu această permisiune, aplicațiile pot salva datele de contact, iar aplicațiile rău-intenționate pot permite accesul la datele de contact fără cunoștința dvs."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Permite aplicației să citească datele despre persoanele de contact salvate pe telefon. Aplicațiile vor avea și acces la conturile de pe telefon care au creat agenda. Aici pot fi incluse conturile create de aplicațiile pe care le-ați instalat. Cu această permisiune, aplicațiile pot salva datele de contact, iar aplicațiile rău-intenționate pot permite accesul la datele de contact fără cunoștința dvs."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"modifică agenda"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Permite aplicației să modifice datele despre persoanele din agenda stocată pe tabletă, inclusiv frecvența cu care ați apelat, ați trimis e-mailuri sau ați comunicat în alte moduri cu anumite persoane din agendă. Cu această permisiune aplicația poate șterge datele de contact."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Permite aplicației să modifice datele despre persoanele de contact salvate pe dispozitivul Android TV, inclusiv frecvența cu care ați apelat, ați trimis e-mailuri sau ați comunicat în alte moduri cu anumite persoane de contact. Cu această permisiune, aplicația poate șterge datele de contact."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Permite aplicației să modifice datele despre persoanele din agenda stocată pe telefon, inclusiv frecvența cu care ați apelat, ați trimis e-mailuri sau ați comunicat în alte moduri cu anumite persoane din agendă. Cu această permisiune aplicația poate șterge datele de contact."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Permite aplicației să modifice datele despre persoanele din agenda stocată pe tabletă. Cu această permisiune, aplicația poate șterge datele de contact."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Permite aplicației să modifice datele despre persoanele din agenda stocată pe dispozitivul Android TV. Cu această permisiune, aplicația poate șterge datele de contact."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Permite aplicației să modifice datele despre persoanele din agenda stocată pe telefon. Cu această permisiune, aplicația poate șterge datele de contact."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"citește jurnalul de apeluri"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Această aplicație poate citi istoricul apelurilor."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"scrie jurnalul de apeluri"</string>
@@ -410,13 +409,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"accesare comenzi suplimentare ale furnizorului locației"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Permite aplicației să acceseze comenzi suplimentare pentru furnizorul locației. Aplicația ar putea să utilizeze această permisiune pentru a influența operațiile GPS sau ale altor surse de locații."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"să acceseze locația exactă în prim-plan"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Aplicația vă poate obține locația exactă numai când rulează în prim-plan. Serviciile de localizare trebuie să fie activate și disponibile pe telefon pentru ca aplicația să le poată folosi. Acest lucru poate accelera descărcarea bateriei."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"să acceseze locația aproximativă (bazată pe rețea) doar în prim-plan"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Aplicația vă poate determina locația folosind sursele din rețea, cum ar fi turnurile de telefonie mobilă și rețelele Wi-Fi, însă numai când rulează în prim-plan. Aceste servicii de localizare trebuie să fie activate și disponibile pe tabletă pentru ca aplicația să le poată folosi."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Aplicația vă poate determina locația folosind sursele din rețea, cum ar fi turnurile de telefonie mobilă și rețelele Wi-Fi, însă numai când rulează în prim-plan. Aceste servicii de localizare trebuie să fie activate și disponibile pe dispozitivul Android TV pentru ca aplicația să le poată folosi."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Aplicația vă poate determina locația folosind sursele din rețea, cum ar fi turnurile de telefonie mobilă și rețelele Wi-Fi, însă numai când rulează în prim-plan. Aceste servicii de localizare trebuie să fie activate și disponibile pe telefon pentru ca aplicația să le poată folosi."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Aplicația vă poate obține locația exactă numai când rulează în prim-plan. Serviciile de localizare trebuie să fie activate și disponibile pe dispozitiv pentru ca aplicația să le poată folosi. Acest lucru poate accelera descărcarea bateriei."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"să acceseze locația aproximativă numai în prim-plan."</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Aplicația vă poate determina locația aproximativă numai când rulează în prim-plan. Serviciile de localizare trebuie să fie activate și disponibile pe dispozitiv pentru ca aplicația să le poată folosi."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"accesați locația în fundal"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Dacă se acordă în plus față de accesul la locație aproximativă sau exactă, aplicația poate accesa locația în timp ce rulează în fundal."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Această aplicație poate accesa locația cât timp rulează în fundal, pe lângă accesul la locație din prim-plan."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"modificare setări audio"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Permite aplicației să modifice setările audio globale, cum ar fi volumul și difuzorul care este utilizat pentru ieșire."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"înregistreze sunet"</string>
@@ -497,6 +494,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Permite aplicației să vadă configurația tabletei Bluetooth, să efectueze și să accepte conexiuni cu dispozitive împerecheate."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Permite aplicației să vadă configurația conexiunii prin Bluetooth a dispozitivului Android TV, să efectueze și să accepte conexiuni cu dispozitive împerecheate."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Permite aplicației să vadă configurația telefonului Bluetooth, să efectueze și să accepte conexiuni cu dispozitive împerecheate."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Informații despre serviciul de plăți NFC preferat"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Permite aplicației să obțină informații despre serviciul de plăți NFC preferat, de exemplu, identificatorii de aplicație înregistrați și destinația traseului."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"controlare schimb de date prin Near Field Communication"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Permite aplicației să comunice cu etichetele, cardurile și cititoarele NFC (Near Field Communication)."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"dezactivează blocarea ecranului"</string>
@@ -1640,12 +1639,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"Comanda rapidă de accesibilitate a activat <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"Comanda rapidă de accesibilitate a dezactivat <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Apăsați ambele butoane de volum timp de trei secunde pentru a folosi <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Alegeți un serviciu pe care să îl folosiți când atingeți butonul de accesibilitate:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Alegeți un serviciu pe care să îl folosiți cu gestul de accesibilitate (glisați în sus cu două degete din partea de jos a ecranului):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Alegeți un serviciu pe care să îl folosiți cu gestul de accesibilitate (glisați în sus cu trei degete din partea de jos a ecranului):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Pentru a comuta între servicii, atingeți lung butonul de accesibilitate."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Pentru a schimba între servicii, glisați în sus cu două degete și țineți lung."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Pentru a schimba între servicii, glisați în sus cu trei degete și țineți lung."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Mărire"</string>
<string name="user_switched" msgid="7249833311585228097">"Utilizator curent: <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="1912993630661332336">"Se comută la <xliff:g id="NAME">%1$s</xliff:g>…"</string>
@@ -1894,7 +1887,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Conectat la <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Atingeți pentru a vedea fișierele"</string>
<string name="pin_target" msgid="8036028973110156895">"Fixați"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Fixați <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Anulați fixarea"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Anulați fixarea pentru <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Informații despre aplicație"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Se pornește demonstrația…"</string>
@@ -1938,6 +1933,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Actualizați aceste articole în "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> și <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Salvați"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Nu, mulțumesc"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Nu acum"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Niciodată"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Actualizați"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Continuați"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"parolă"</string>
@@ -2034,5 +2031,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Activați ecranul împărțit"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Ecran de blocare"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Captură de ecran"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"Aplicația <xliff:g id="APP_NAME">%1$s</xliff:g> în fereastră pop-up."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Bară cu legenda pentru <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index a7abbffdbe2d..9e8e13af4eed 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -192,8 +192,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Приложение для администрирования рабочего профиля отсутствует или повреждено. Из-за этого рабочий профиль и связанные с ним данные были удалены. Если у вас возникли вопросы, обратитесь к администратору."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Ваш рабочий профиль больше не доступен на этом устройстве"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Слишком много попыток ввести пароль."</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Администратор освободил устройство для личного использования"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Это управляемое устройство"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Ваша организация управляет этим устройством и может отслеживать сетевой трафик. Подробнее…"</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Все данные с устройства будут удалены"</string>
@@ -387,13 +386,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Приложение сможет делать бессрочные рассылки, которые не удаляются после отправки. Злоупотребление ими может замедлить работу устройства Android TV или сделать ее нестабильной из-за чрезмерной загрузки памяти."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Приложение сможет делать несрочные рассылки, которые не удаляются после их отправки. Злоупотребление этими рассылками может замедлить работу телефона или сделать ее нестабильной из-за чрезмерного использования памяти."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"Просмотр контактов"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Приложение сможет просматривать и сохранять все данные о контактах на устройстве, включая то, как часто вы звоните, отправляете письма и другими способами связываетесь с определенными людьми. Вредоносные программы смогут передавать данные о контактах без уведомления."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Приложение получит доступ к контактам, сохраненным на устройстве Android TV, а также к данным о частоте звонков, отправки сообщений электронной почты и других сеансов связи с определенными людьми. Приложения смогут сохранять данные о контактах. Вредоносные программы смогут публиковать их без вашего ведома."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Приложение сможет просматривать и сохранять все данные о контактах на устройстве, включая то, как часто вы звоните, отправляете письма и другими способами связываетесь с определенными людьми. Вредоносные программы смогут передавать данные о контактах без уведомления."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Приложение сможет считывать данные о контактах, сохраненных на вашем планшете. Кроме того, у приложения будет доступ к аккаунтам на планшете, в которых есть контакты. В их число могут входить аккаунты, созданные приложениями, которые вы установили. Получив возможность сохранять данные контактов, вредоносные программы смогут передавать их без вашего ведома."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Приложение сможет считывать данные о контактах, сохраненных на вашем устройстве Android TV. Кроме того, у приложения будет доступ к аккаунтам на устройстве Android TV, в которых есть контакты. В их число могут входить аккаунты, созданные приложениями, которые вы установили. Получив возможность сохранять данные контактов, вредоносные программы смогут передавать их без вашего ведома."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Приложение сможет считывать данные о контактах, сохраненных на вашем телефоне. Кроме того, у приложения будет доступ к аккаунтам на телефоне, в которых есть контакты. В их число могут входить аккаунты, созданные приложениями, которые вы установили. Получив возможность сохранять данные контактов, вредоносные программы смогут передавать их без вашего ведома."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"Изменение контактов"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Приложение сможет изменять сведения о контактах на вашем планшетном ПК, включая то, как часто вы звоните, отправляете письма и другими способами связываетесь с определенными людьми. С этим разрешением приложения смогут удалять данные о контактах."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Приложение сможет изменять сведения о контактах на вашем устройстве Android TV, включая то, как часто вы звоните, отправляете письма и другими способами связываетесь с определенными людьми. С этим разрешением приложения смогут удалять данные о контактах."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Приложение сможет изменять сведения о контактах на вашем телефоне, включая то, как часто вы звоните, отправляете письма и другими способами связываетесь с определенными людьми. С этим разрешением приложения смогут удалять данные о контактах."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Приложение сможет изменять сведения о контактах, сохраненных на вашем планшете. Это разрешение позволяет приложениям удалять данные о контактах."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Приложение сможет изменять сведения о контактах, сохраненных на вашем устройстве Android TV. Это разрешение позволяет приложениям удалять данные о контактах."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Приложение сможет изменять сведения о контактах, сохраненных на вашем телефоне. Это разрешение позволяет приложениям удалять данные о контактах."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"Просмотр журнала вызовов"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Приложение может считывать данные журнала звонков."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"Изменение журнала вызовов"</string>
@@ -413,13 +412,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"Доступ к дополнительным командам управления источниками геоданных"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Доступ к дополнительным командам управления источниками геоданных и вмешательство в работу системы GPS или других источников геоданных."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"Доступ к точному местоположению только в фоновом режиме"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Приложение может получать сведения о вашем точном местоположении только в фоновом режиме. Для этого необходимо включить соответствующие параметры на телефоне и разрешить использовать геоданные. Может увеличиться расход заряда батареи."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"Доступ к примерному местоположению (по координатам сети) только в фоновом режиме"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Приложение может получать сведения о вашем местоположении от источников сетей, таких как вышки сотовой связи и точки доступа Wi-Fi, но только в фоновом режиме. Для этого необходимо включить соответствующие параметры на планшете и разрешить использовать геоданные."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Приложение может получать сведения о вашем местоположении от сетевых источников, таких как вышки сотовой связи и точки доступа Wi-Fi, но только в активном режиме. Для этого необходимо включить на устройстве Android TV соответствующие сервисы геолокации и разрешить приложению использовать их."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Приложение может получать сведения о вашем местоположении от источников сетей, таких как вышки сотовой связи и точки доступа Wi-Fi, но только в фоновом режиме. Для этого необходимо включить соответствующие параметры на телефоне и разрешить использовать геоданные."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Приложение сможет получать сведения о вашем точном местоположении только в активном режиме. Для этого нужно включить геолокацию на устройстве и разрешить приложению использовать геоданные. Расход заряда батареи может увеличиться."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"Доступ к приблизительному местоположению только в активном режиме"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Приложение сможет получать сведения о вашем приблизительном местоположении только в активном режиме. Для этого нужно включить геолокацию на устройстве и разрешить приложению использовать геоданные."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"доступ к геоданным в фоновом режиме"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Если помимо доступа к данным о точном или приблизительном местоположении вы предоставите это разрешение, приложение сможет получать доступ к геоданным в фоновом режиме."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Приложение сможет получать сведения о вашем местоположении как в фоновом, так и в активном режиме."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"Изменение настроек аудио"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Приложение сможет изменять системные настройки звука, например уровень громкости и активный динамик."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"Запись аудио"</string>
@@ -500,6 +497,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Приложение сможет просматривать конфигурацию Bluetooth на планшетном ПК, а также запрашивать и подтверждать соединение с другими устройствами."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Приложение сможет просматривать конфигурацию Bluetooth на устройстве Android TV, а также запрашивать и подтверждать соединение с другими устройствами."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Приложение сможет просматривать конфигурацию Bluetooth на телефоне, а также запрашивать и подтверждать соединение с другими устройствами."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Сведения о предпочтительном платежном сервисе NFC"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Приложение сможет получать сведения о предпочтительном платежном сервисе NFC (например, зарегистрированные идентификаторы AID и конечный пункт маршрута)."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"Управление NFC-модулем"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Приложение сможет обмениваться данными с NFC-метками, картами и устройствами считывания, используя NFC."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"Отключение функции блокировки экрана"</string>
@@ -1662,12 +1661,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"Сервис <xliff:g id="SERVICE_NAME">%1$s</xliff:g> включен"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"Сервис <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>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Выберите сервис, который будет запускаться при нажатии кнопки специальных возможностей:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Выберите сервис, который будет запускаться жестом (провести по экрану снизу вверх двумя пальцами):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Выберите сервис, который будет запускаться жестом (провести по экрану снизу вверх тремя пальцами):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Для переключения между сервисами нажмите и удерживайте кнопку специальных возможностей."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Для переключения между сервисами проведите по экрану снизу вверх двумя пальцами и задержите их."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Для переключения между сервисами проведите по экрану снизу вверх тремя пальцами и задержите их."</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>
@@ -1926,7 +1919,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Подключено к <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Нажмите, чтобы просмотреть файлы"</string>
<string name="pin_target" msgid="8036028973110156895">"Закрепить"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Закрепить приложение \"<xliff:g id="LABEL">%1$s</xliff:g>\""</string>
<string name="unpin_target" msgid="3963318576590204447">"Открепить"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Открепить приложение \"<xliff:g id="LABEL">%1$s</xliff:g>\""</string>
<string name="app_info" msgid="6113278084877079851">"О приложении"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Запуск деморежима…"</string>
@@ -1971,6 +1966,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Обновить данные (<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_save_yes" msgid="8035743017382012850">"Сохранить"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Нет, спасибо"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Не сейчас"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Никогда"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Обновить"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Продолжить"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"Пароль"</string>
@@ -2068,5 +2065,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Включить или выключить разделение экрана"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Заблокированный экран"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Скриншот"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" в всплывающем окне."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Строка субтитров в приложении \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"."</string>
</resources>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 7d3f80d1331b..a28e0362fb75 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"කාර්යාල පැතිකඩ පාලක යෙදුම නොමැති හෝ දූෂණය වී ඇත. ප්‍රතිඵලයක් ලෙස ඔබගේ කාර්යාල පැතිකඩ සහ අදාළ දත්ත මකා දමා ඇත. සහය සඳහා ඔබගේ පරිපාලකයා සම්බන්ධ කර ගන්න."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"ඔබේ කාර්යාල පැතිකඩ මෙම උපාංගය මත තවදුරටත් ලබා ගැනීමට නොහැකිය"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"මුරපද උත්සාහ කිරීම් ඉතා වැඩි ගණනකි"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"පරිපාලක පුද්ගලික භාවිතය සඳහා උපාංගය අත්හැර දමන ලදී"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"උපාංගය කළමනාකරණය කෙරේ"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"ඔබගේ ආයතනය මෙම උපාංගය කළමනාකරණය කරන අතර එය ජාල තදබදය නිරීක්ෂණය කළ හැක. විස්තර සඳහා තට්ටු කරන්න."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"ඔබගේ උපාංගය මකා දැමෙනු ඇත"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"යෙදුමට විකාශයෙන් පසුවද ඉතිරි වන, ඇලවෙන විකාශ යැවීමට ඉඩ දෙයි. වැඩියෙන් භාවිතය වැඩිපුර මතකය භාවිත කිරීම මගින් ඔබේ Android TV උපාංගය මන්දගාමී හෝ අස්ථායී බවට පත් කළ හැකිය."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"ප්‍රචාරණයට පසුවද පවතින, ප්‍රචාරණයන් යැවීමට යෙදුමට අවසර දෙන්න. වැඩිපුර මතකය භාවිතය හේතු කොට, අධික භාවිතය මඟින් දුරකථනය පමා කිරීම හෝ අස්ථිර කළ හැක."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"ඔබගේ සම්බන්ධතා කියවීම"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"සඳහන් පුද්ගලයන් හට ඔබ ඇමතුම් ගත්, ඊ-තැපැල්, හෝ අනෙකුත් ආකාර වලින් සන්නිවේදනය කරගත් සංඛ්‍යතද ඇතුළුව, ඔබගේ ටැබ්ලටයේ ගබඩාවී ඇති සම්බන්ධතා පිළිබඳ දත්ත කියවීමට යෙදුමට අවසර දෙන්න. මෙම අවසරය මඟින් යෙදුම්වලට ඔබගේ සම්බන්ධතා පිළිබඳ දත්ත සුරැකීමට ඉඩ ලබා දෙන අතර, අනිෂ්ට යෙදුම් විසින් ඔබ නොදැනුවත්වම සම්බන්ධතා දත්ත බෙදා ගැනීමට ඉඩ ඇත."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"ඔබ නිශ්චිත පුද්ගලයන් ඇමතූ, ඉ-තැපැල් කළ හෝ වෙනත් ආකාරයකින් සන්නිවේදනය කළ වාර ගණනද ඇතුළුව, ඔබගේ Android TV උපාංගයේ ගබඩා කර ඇති ඔබගේ සම්බන්ධතා පිළිබඳ දත්ත කියවීමට යෙදුමට ඉඩ දෙයි. මෙම අවසරය යෙදුම්වලට ඔබගේ සම්බන්ධතා දත්ත සුරැකීමට ඉඩ දෙන අතර, අනිෂ්ට යෙදුම් ඔබගේ දැනුමෙන් තොරව සම්බන්ධතා දත්ත බෙදා ගත හැකිය."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"නියමිත පුද්ගලයන් සමග ඔබ ඇමතු, ඊ-තැපැල් කළ හෝ වෙනත් ආකාරයකින් සන්නිවේදනය කළ සංඛ්‍යාතය ඇතුලත් ඔබගේ දුරකථනයේ ආචයනය කරන ලද ඔබගේ සම්බන්ධතා ගැන දත්ත කියවීමට යෙදුමට අවසර දෙන්න. ඔබගේ සම්බන්ධතා දත්ත උපස්ථ කිරීමට මෙම අවසරය යෙදුමට අවසර දෙන අතර ඔබගේ දැනුමකින් තොරව අනිෂ්ට යෙදුම් සම්බන්ධතා දත්ත බෙදාගැනීම කළ හැක."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"ඔබගේ ටැබ්ලට් පරිගණකයේ ගබඩා කර ඇති ඔබගේ සම්බන්ධතා පිළිබඳ දත්ත කියවීමට යෙදුමට ඉඩ දෙයි. යෙදුම්වලට සම්බන්ධතා තැනූ ඔබගේ ටැබ්ලට් පරිගණකයේ ගිණුම්වලට ප්‍රවේශය ද ලැබෙනු ඇත. මෙයට ඔබ ස්ථාපනය කර ඇති යෙදුම් මගින් තැනූ ගිණුම් ඇතුළත් විය හැකිය. මෙම අවසරය යෙදුම්වලට ඔබගේ සම්බන්ධතා දත්ත සුරැකීමට ඉඩ දෙන අතර, අනිෂ්ට යෙදුම් ඔබගේ දැනුමෙන් තොරව සම්බන්ධතා දත්ත බෙදා ගත හැකිය."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"ඔබගේ Android TV උපාංගයේ ගබඩා කර ඇති ඔබගේ සම්බන්ධතා පිළිබඳ දත්ත කියවීමට යෙදුමට ඉඩ දෙයි. යෙදුම්වලට සම්බන්ධතා තැනූ ඔබගේ Android TV උපාංගයේ ගිණුම්වලට ප්‍රවේශය ද ලැබෙනු ඇත. මෙයට ඔබ ස්ථාපනය කර ඇති යෙදුම් මගින් තැනූ ගිණුම් ඇතුළත් විය හැකිය. මෙම අවසරය යෙදුම්වලට ඔබගේ සම්බන්ධතා දත්ත සුරැකීමට ඉඩ දෙන අතර, අනිෂ්ට යෙදුම් ඔබගේ දැනුමෙන් තොරව සම්බන්ධතා දත්ත බෙදා ගත හැකිය."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"ඔබගේ දුරකථනයේ ගබඩා කර ඇති ඔබගේ සම්බන්ධතා පිළිබඳ දත්ත කියවීමට යෙදුමට ඉඩ දෙයි. යෙදුම්වලට සම්බන්ධතා තැනූ ඔබගේ දුරකථනයේ ගිණුම්වලට ප්‍රවේශය ද ලැබෙනු ඇත. මෙයට ඔබ ස්ථාපනය කර ඇති යෙදුම් මගින් තැනූ ගිණුම් ඇතුළත් විය හැකිය. මෙම අවසරය යෙදුම්වලට ඔබගේ සම්බන්ධතා දත්ත සුරැකීමට ඉඩ දෙන අතර, අනිෂ්ට යෙදුම් ඔබගේ දැනුමෙන් තොරව සම්බන්ධතා දත්ත බෙදා ගත හැකිය."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"ඔබගේ සම්බන්ධතා වෙනස් කිරීම"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"නියමිත පුද්ගලයන්ට ඔබ ඇමතූ, ඊ-තැපැල් කළ හෝ ඇමතුම් කළ සංඛ්‍යාත ඇතුලත් ඔබගේ ටැබ්ලටයේ ආචයනය කරන ලද සම්බන්ධතා (ලිපින) දත්ත වෙනස් කිරීමට යෙදුමට අවසර දෙන්න. මෙම අවසරයෙන් යෙදුමට සම්බන්ධතා දත්ත මැකීමට අවසර දෙයි."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"ඔබ නිශ්චිත සම්බන්ධතා ඇමතූ, ඉ-තැපැල් කළ හෝ වෙනත් ආකාරයකින් සන්නිවේදනය කළ වාර ගණනද ඇතුළුව, ඔබගේ Android TV උපාංගයේ ගබඩා කර ඇති ඔබගේ සම්බන්ධතා පිළිබඳ දත්ත වෙනස් කිරීමට යෙදුමට ඉඩ දෙයි. මෙම අවසරය යෙදුම්වලට සම්බන්ධතා දත්ත මැකීමට ඉඩ දෙයි."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"සඳහන් පුද්ගලයන්ට ඔබ ඇමතූ, ඊ-තැපැල් කළ හෝ ඇමතුම් කළ සංඛ්‍යාන ඇතුලත් ඔබගේ දුරකථනයේ ආචයනය කරන ලද සම්බන්ධතා (ලිපින) දත්ත වෙනස් කිරීමට යෙදුමට අවසර දෙන්න. මෙම අවසරයෙන් යෙදුමට සම්බන්ධතා දත්ත මැකීමට අවසර දෙයි."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"ඔබගේ ටැබ්ලට් පරිගණකයේ ගබඩා කර ඇති ඔබගේ සම්බන්ධතා පිළිබඳ දත්ත වෙනස් කිරීමට යෙදුමට ඉඩ දෙයි. මෙම අවසරය යෙදුම්වලට සම්බන්ධතා දත්ත මැකීමට ඉඩ දෙයි."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"ඔබගේ Android TV උපාංගයේ ගබඩා කර ඇති ඔබගේ සම්බන්ධතා පිළිබඳ දත්ත වෙනස් කිරීමට යෙදුමට ඉඩ දෙයි. මෙම අවසරය යෙදුම්වලට සම්බන්ධතා දත්ත මැකීමට ඉඩ දෙයි."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"ඔබගේ දුරකථනයේ ගබඩා කර ඇති ඔබගේ සම්බන්ධතා පිළිබඳ දත්ත වෙනස් කිරීමට යෙදුමට ඉඩ දෙයි. මෙම අවසරය යෙදුම්වලට සම්බන්ධතා දත්ත මැකීමට ඉඩ දෙයි."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"ඇමතුම් ලොගය කියවන්න"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"මෙම යෙදුමට ඔබේ ඇමතුම් ඉතිහාසය කියවීමට හැකිය."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"ඇමතුම් ලොගය ලිවීම"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"අමතර ස්ථාන සැපයුම්කරු විධාන වෙත ප්‍රවේශ වීම"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"ස්ථානය සපයන අමතර අණ වලට ප්‍රවේශය කිරීමට යෙදුමට අවසර දෙන්න. GPS ක්‍රියාවන් හෝ වෙනත් ස්ථාන මූලාශ්‍ර සමඟ මැදිහත් වීමට මෙයින් යෙදුමට ඉඩ ලැබේ."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"පෙරබිම තුළ පමණක් නිශ්චිත ස්ථානය වෙත පිවිසෙන්න"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"මෙම යෙදුම පෙරබිම තුළ ඇති විට පමණක් එයට ඔබේ නිශ්චිත ස්ථානය ලබා ගත හැකිය. යෙදුමට ඒවා භාවිත කිරීමට හැකි වීමට මෙම ස්ථාන සේවා ක්‍රියාත්මක කර සහ ඔබේ දුරකථනය මත ලබා ගත හැකිව තිබිය යුතුය. මෙය බැටරි පරිභෝජනය වැඩි කළ හැකිය."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"ඉදිරියේ ඇති ආසන්න ස්ථානය (ජාලය පදනම්වූ) පමණක් ප්‍ර වේශ වන්න"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"මෙම යෙදුමට ජංගම දුරකථන කුළුණු සහ Wi-Fi ජාල වැනි ජාල මූලාශ්‍ර පදනම්ව ඔබගේ ස්ථානය ලබා ගත හැකි නමුත් යෙදුම ඉදිරියේ ඇති විට පමණී. යෙදුමට ඒවා භාවිත කිරීමට හැකි වීමට මෙම ස්ථාන සේවා ක්‍රියාත්මක කර ඔබේ ටැබ්ලටය මත ලබා ගත හැකිව තිබිය යුතුය."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"මෙම යෙදුමට ජංගම දුරකථන කුළුණු සහ Wi-Fi ජාල වැනි ජාල මූලාශ්‍ර පදනම්ව ඔබගේ ස්ථානය ලබා ගත හැකි නමුත් යෙදුම ඉදිරියේ ඇති විට පමණී. යෙදුමට ඒවා භාවිත කිරීමට හැකි වීමට මෙම ස්ථාන සේවා ක්‍රියාත්මක කර ඔබේ ඔබගේ Android TV උපාංගය මත ලබා ගත හැකිව තිබිය යුතුය."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"මෙම යෙදුමට ජංගම දුරකථන කුළුණු සහ Wi-Fi ජාල වැනි ජාල මූලාශ්‍ර පදනම්ව ඔබගේ ස්ථානය ලබා ගත හැකි නමුත් යෙදුම ඉදිරියේ ඇති විට පමණී. යෙදුමට ඒවා භාවිත කිරීමට හැකි වීමට මෙම ස්ථාන සේවා ක්‍රියාත්මක කර ඔබේ දුරකථනය මත ලබා ගත හැකිව තිබිය යුතුය."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"මෙම යෙදුම පෙරබිම තුළ ඇති විට පමණක් එයට ඔබගේ නිශ්චිත ස්ථානය ලබා ගත හැකිය. යෙදුමට ඒවා භාවිත කිරීමට හැකියාව ලැබීමට ස්ථාන සේවා ක්‍රියාත්මක කර ඔබගේ දුරකථනයේ ලබා ගත හැකි විය යුතුය. මෙය බැටරි පරිභෝජනය වැඩි කළ හැකිය."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"පෙරබිම තුළ පමණක් ආසන්න ස්ථානයට ප්‍රවේශය"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"මෙම යෙදුම පෙරබිම තුළ ඇති විට පමණක් එයට ඔබගේ ආසන්න ස්ථානය ලබා ගත හැකිය. යෙදුමට ඒවා භාවිත කිරීමට හැකියාව ලැබීමට ස්ථාන සේවා ක්‍රියාත්මක කර ඔබගේ උපාංගයේ ලබා ගත හැකි විය යුතුය."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"පසුබිමේ ස්ථානය ප්‍රවේශ කිරීම"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"මෙය ආසන්න වශයෙන් හෝ නිශ්චිත ස්ථානයක ප්‍රවේශය ලබා දෙන්නේ නම් පසුබිම් ධාවන අතරතුරදී යෙදුමට ස්ථානය වෙත ප්‍රවේශය විය හැක."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"පෙරබිම ස්ථාන ප්‍රවේශයට අමතරව පසුබිමේ ධාවනය වන අතරතුර මෙම යෙදුමට ස්ථානය වෙත ප්‍රවේශ විය හැකිය."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"ඔබගේ ශ්‍රව්‍ය සැකසීම් වෙනස් කරන්න"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"ශබ්දය ආදී ගෝලීය ශබ්ද සැකසීම් වෙනස් කිරීමට සහ ප්‍රතිදානය සඳහා භාවිත කරන්නේ කුමන නාදකය දැයි තේරීමට යෙදුමට අවසර දෙන්න."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"ශබ්ද පටිගත කරන්න"</string>
@@ -494,6 +491,8 @@
<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_preferredPaymentInfo" msgid="5274423844767445054">"කැමති NFC ගෙවීම් සේවා තොරතුරු"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"ලියාපදිංචි කළ ආධාර සහ ගමන් මාර්ග ගමනාන්ත වැනි කැමති nfc ගෙවීම් සේවා තොරතුරු ලබා ගැනීමට යෙදුමට ඉඩ දෙයි."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"ආසන්න ක්ෂේත්‍ර සන්නිවේදනය පාලනය කරන්න"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"ආසන්න ක්ෂේත්‍ර සන්නිවේදන (NFC) ටැග්, පත්, සහ කියවන්නන් සමඟ සන්නිවේදනය කිරීමට යෙදුමට අවසර දෙන්න."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"ඔබගේ තිරයේ අගුල අබල කරන්න"</string>
@@ -1620,12 +1619,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"ප්‍රවේශ්‍යතා කෙටි මග <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ක්‍රියාත්මක කරන ලදී"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"ප්‍රවේශ්‍යතා කෙටි මග <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>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"ඔබ ප්‍රවේශ්‍යතා බොත්තම තට්ටු කරන විට භාවිතයට සේවාවක් තෝරා ගන්න:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"ප්‍රවේශ්‍යතා ඉංගිතය සමඟ භාවිතයට සේවාවක් තෝරා ගන්න (ඇඟිලි දෙකක් සමඟින් තිරයේ පහළින් උඩට ස්වයිප් කරන්න):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"ප්‍රවේශ්‍යතා ඉංගිතය සමඟ භාවිතයට සේවාවක් තෝරා ගන්න (ඇඟිලි තුනක් සමඟින් තිරයේ පහළින් උඩට ස්වයිප් කරන්න):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"සේවා අතර මාරු වීමට, ප්‍රවේශ්‍යතා බොත්තම ස්පර්ශ කර අල්ලා සිටින්න."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"සේවා අතර මාරු වීමට, ඇඟිලි දෙකක් සමඟින් උඩට ස්වයිප් කර අල්ලා සිටින්න."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"සේවා අතර මාරු වීමට, ඇඟිලි තුනක් සමඟින් උඩට ස්වයිප් කර අල්ලා සිටින්න."</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>
@@ -1864,7 +1857,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> වෙත සම්බන්ධ විය"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"ගොනු බැලීමට තට්ටු කරන්න"</string>
<string name="pin_target" msgid="8036028973110156895">"අමුණන්න"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"<xliff:g id="LABEL">%1$s</xliff:g> අමුණන්න"</string>
<string name="unpin_target" msgid="3963318576590204447">"ගලවන්න"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"<xliff:g id="LABEL">%1$s</xliff:g> ඇමුණුම ඉවත් කරන්න"</string>
<string name="app_info" msgid="6113278084877079851">"යෙදුම් තොරතුරු"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"ආදර්ශනය ආරම්භ කරමින්..."</string>
@@ -1907,6 +1902,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291"><b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" තුළ යාවත්කාලීන කරන්නද?: <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> ?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"සුරකින්න"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"එපා ස්තූතියි"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"දැන් නොවේ"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"කිසිදා නැත"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"යාවත්කාලීන කරන්න"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"ඉදිරියට යන්න"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"මුරපදය"</string>
@@ -2002,5 +1999,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"බෙදුම් තිරය ටොගල කරන්න"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"අගුලු තිරය"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"තිර රුව"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"උත්පතන කවුළුව තුළ <xliff:g id="APP_NAME">%1$s</xliff:g> යෙදුම."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> හි සිරස්තල තීරුව."</string>
</resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 3a81468c2d72..6bf54b0ddc89 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -192,8 +192,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Aplikácia na správu pracovného profilu buď chýba, alebo je poškodená. Z toho dôvodu bol odstránený pracovný profil aj k nemu priradené dáta. Ak potrebujete pomoc, kontaktujte svojho správcu."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Váš pracovný profil už v tomto zariadení nie je k dispozícii"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Príliš veľa pokusov o zadanie hesla"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Správca uvoľnil toto zariadenie na osobné používanie"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Zariadenie je spravované"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Vaša organizácia spravuje toto zariadenie a môže sledovať sieťovú premávku. Klepnutím zobrazíte podrobnosti."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Vaše zariadenie bude vymazané"</string>
@@ -387,13 +386,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Umožňuje aplikácii odosielať trvalé vysielania, ktoré pretrvávajú aj po skončení vysielania. Nadmerné používanie môže zariadenie Android TV spomaliť alebo spôsobiť jeho nestabilitu, pretože bude používať príliš veľa pamäte."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Umožňuje aplikácii odosielať trvalé vysielania, ktoré pretrvávajú aj po skončení vysielania. Nadmerné používanie môže telefón spomaliť alebo spôsobiť jeho nestabilitu, pretože bude používať príliš veľa pamäte."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"čítať kontakty"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Umožňuje aplikácii čítať údaje o kontaktoch uložených v tablete vrátane informácií o frekvencii vašich telefonátov, odoslaných e-mailov alebo iných foriem komunikácie s konkrétnymi osobami. Toto povolenie umožňuje aplikáciám ukladať údaje o kontaktoch. Škodlivé aplikácie môžu zdieľať údaje o kontaktoch bez vášho vedomia."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Umožňuje aplikácii čítať údaje o kontaktoch, ktoré máte uložené v zariadení Android TV, vrátane informácií o frekvencii vašich volaní, odoslaných e‑mailov alebo iných foriem komunikácie s konkrétnymi osobami. Toto povolenie umožňuje aplikáciám ukladať údaje kontaktov. Škodlivé aplikácie môžu zdieľať údaje kontaktov bez vášho vedomia."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Umožňuje aplikácii čítať údaje o kontaktoch uložených v telefóne vrátane informácií o frekvencii vašich telefonátov, odoslaných e-mailov alebo iných foriem komunikácie s konkrétnymi osobami. Toto povolenie umožňuje aplikáciám ukladať údaje o kontaktoch. Škodlivé aplikácie môžu zdieľať údaje o kontaktoch bez vášho vedomia."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Umožňuje aplikácii čítať údaje o kontaktoch uložených v tablete. Aplikácie budú mať tiež prístup k účtom v tablete, ktoré vytvorili kontakty. Môže ísť o účty vytvorené aplikáciami, ktoré ste nainštalovali. Toto povolenie umožňuje aplikáciám ukladať údaje o kontaktoch. Škodlivé aplikácie môžu zdieľať údaje o kontaktoch bez vášho vedomia."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Umožňuje aplikácii čítať údaje o kontaktoch uložených v zariadení Android TV. Aplikácie budú mať tiež prístup k účtom v zariadení Android TV, ktoré vytvorili kontakty. Môže ísť o účty vytvorené aplikáciami, ktoré ste nainštalovali. Toto povolenie umožňuje aplikáciám ukladať údaje o kontaktoch. Škodlivé aplikácie môžu zdieľať údaje o kontaktoch bez vášho vedomia."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Umožňuje aplikácii čítať údaje o kontaktoch uložených v telefóne. Aplikácie budú mať tiež prístup k účtom v telefóne, ktoré vytvorili kontakty. Môže ísť o účty vytvorené aplikáciami, ktoré ste nainštalovali. Toto povolenie umožňuje aplikáciám ukladať údaje o kontaktoch. Škodlivé aplikácie môžu zdieľať údaje o kontaktoch bez vášho vedomia."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"upraviť kontakty"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Umožňuje aplikácii upraviť údaje o kontaktoch uložených v tablete vrátane informácií o frekvencii vašich telefonátov, odoslaných e-mailov alebo iných foriem komunikácie s konkrétnymi osobami. Toto povolenie umožňuje aplikáciám odstraňovať údaje o kontaktoch."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Umožňuje aplikácii upravovať údaje o kontaktoch, ktoré máte uložené v zariadení Android TV, vrátane informácií o frekvencii vašich volaní, odoslaných e‑mailov alebo iných foriem komunikácie s konkrétnymi kontaktmi. Toto povolenie umožňuje aplikáciám odstraňovať údaje kontaktov."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Umožňuje aplikácii upraviť údaje o kontaktoch uložených v telefóne vrátane informácií o frekvencii vašich telefonátov, odoslaných e-mailov alebo iných foriem komunikácie s konkrétnymi osobami. Toto povolenie umožňuje aplikáciám odstraňovať údaje o kontaktoch."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Umožňuje aplikácii upraviť údaje o kontaktoch uložených v tablete. Toto povolenie umožňuje aplikáciám odstraňovať údaje o kontaktoch."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Umožňuje aplikácii upraviť údaje o kontaktoch uložených v zariadení Android TV. Toto povolenie umožňuje aplikáciám odstraňovať údaje o kontaktoch."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Umožňuje aplikácii upraviť údaje o kontaktoch uložených v telefóne. Toto povolenie umožňuje aplikáciám odstraňovať údaje o kontaktoch."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"čítať denník hovorov"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Táto aplikácia môže čítať históriu vašich hovorov."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"zapisovať do denníka hovorov"</string>
@@ -413,13 +412,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"prístup k ďalším príkazom poskytovateľa polohy"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Umožňuje aplikácii pristupovať k ďalším príkazom poskytovateľa informácií o polohe. Aplikácii to môže umožniť zasahovať do činnosti systému GPS alebo iných zdrojov informácií o polohe."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"prístup k presnej polohe iba v popredí"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Táto aplikácia dokáže získať vašu presnú polohu iba vtedy, keď je spustená v popredí. Na to, aby mohla používať služby určovania polohy, musia byť tieto služby zapnuté a k dispozícii v telefóne. Môže to zvýšiť spotebu batérie."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"prístup k približnej polohe (pomocou siete) iba v popredí"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Táto aplikácia môže získať údaje o vašej polohe na základe sieťových zdrojov, ako sú mobilné veže a siete Wi‑Fi, keď je spustená v popredí. Na to, aby aplikácia mohla používať služby určovania polohy, musia byť tieto služby zapnuté a k dispozícii v tablete."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Táto aplikácia môže získať údaje o vašej polohe na základe sieťových zdrojov, ako sú vysielače mobilnej siete a siete Wi‑Fi, keď je spustená v popredí. Tieto služby musia byť zapnuté a k dispozícii v zariadení Android TV, aby aplikácia mohla používať služby určovania polohy."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Táto aplikácia môže získať údaje o vašej polohe na základe sieťových zdrojov, ako sú mobilné veže a siete Wi‑Fi, ale iba keď je spustená v popredí. Na to, aby aplikácia mohla používať služby určovania polohy, musia byť tieto služby zapnuté a k dispozícii v telefóne."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Táto aplikácia dokáže získať vašu presnú polohu iba vtedy, keď je spustená v popredí. Služby určovania polohy musia byť zapnuté a k dispozícii v zariadení, aby ich mohla aplikácia používať. Môže to zvýšiť spotrebu batérie."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"prístup k približnej polohe iba v popredí"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Táto aplikácia dokáže získať vašu približnú polohu iba vtedy, keď je spustená v popredí. Služby určovania polohy musia byť zapnuté a k dispozícii v zariadení, aby ich mohla aplikácia používať."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"prístup k polohe na pozadí"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Ak okrem prístupu k približnej alebo presnej polohe udelíte aj toto povolenie, aplikácia bude môcť používať polohu, keď bude spustená na pozadí."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Táto aplikácia môže používať polohu nielen vtedy, keď je spustená v popredí, ale aj na pozadí."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"meniť nastavenia zvuku"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Umožňuje aplikácii upraviť globálne nastavenia zvuku, ako je hlasitosť, alebo určiť, z ktorého reproduktora bude zvuk vychádzať."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"nahrávať zvuk"</string>
@@ -500,6 +497,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Umožňuje aplikácii zobraziť informácie o konfigurácii Bluetooth na tablete. Taktiež jej umožňuje nadväzovať a akceptovať spojenia so spárovanými zariadeniami."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Umožňuje aplikácii zobraziť konfiguráciu rozhrania Bluetooth v zariadení Android TV, ako aj nadväzovať a prijímať pripojenia so spárovanými zariadeniami."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Umožňuje aplikácii zobraziť informácie o konfigurácii Bluetooth na telefóne. Taktiež jej umožňuje nadväzovať a akceptovať spojenia so spárovanými zariadeniami."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Preferované informácie platenej služby NFC"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Umožňuje aplikácii získavať preferované informácie platenej služby NFC, napríklad o registrovanej pomoci a trasách k cieľu."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"ovládať technológiu NFC"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Umožňuje aplikácii komunikovať so značkami, kartami a čítačkami s podporou technológie NFC."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"deaktivácia zámky obrazovky"</string>
@@ -1662,12 +1661,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"Skratka dostupnosti zapla službu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"Skratka dostupnosti vypla službu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</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>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Vyberte službu, ktorú chcete používať po klepnutí na tlačidlo dostupnosti:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Vyberte službu, ktorú chcete používať s daným gestom dostupnosti (potiahnutím dvoma prstami z dolnej časti obrazovky smerom nahor):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Vyberte službu aktivovanú daným gestom dostupnosti (potiahnutie troma prstami z dolnej časti obrazovky nahor):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Služby prepnete pridržaním tlačidla dostupnosti."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Služby prepnete potiahnutím dvoma prstami smerom nahor a pridržaním."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Služby prepnete potiahnutím troma prstami nahor a pridržaním."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Priblíženie"</string>
<string name="user_switched" msgid="7249833311585228097">"Aktuálny používateľ je <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="1912993630661332336">"Prepína sa na účet <xliff:g id="NAME">%1$s</xliff:g>…"</string>
@@ -1926,7 +1919,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Pripojené k zariadeniu <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Klepnutím zobrazíte súbory"</string>
<string name="pin_target" msgid="8036028973110156895">"Pripnúť"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Pripnúť <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Uvoľniť"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Odopnúť <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Info o aplikácii"</string>
<string name="negative_duration" msgid="1938335096972945232">"-<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Spúšťa sa ukážka…"</string>
@@ -1971,6 +1966,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Chcete tieto položky aktualizovať v službe "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> a <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Uložiť"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Nie, vďaka"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Teraz nie"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Nikdy"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Aktualizovať"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Pokračovať"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"heslo"</string>
@@ -2068,5 +2065,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Prepnúť rozdelenú obrazovku"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Uzamknúť obrazovku"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Snímka obrazovky"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"Aplikácia <xliff:g id="APP_NAME">%1$s</xliff:g> vo vyskakovacom okne."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Popis aplikácie <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index c28384c74236..be173dd878e5 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -192,8 +192,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Skrbniška aplikacija delovnega profila manjka ali pa je poškodovana, zaradi česar je bil delovni profil s povezanimi podatki izbrisan. Za pomoč se obrnite na skrbnika."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Vaš delovni profil ni več na voljo v tej napravi"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Preveč poskusov vnosa gesla"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Skrbnik je napravo prepustil osebni uporabi"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Naprava je upravljana"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Vaša organizacija upravlja to napravo in lahko nadzira omrežni promet. Dotaknite se za podrobnosti."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Podatki v napravi bodo izbrisani"</string>
@@ -387,13 +386,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Aplikaciji dovoljuje pošiljanje fiksnih oddaj, ki ostanejo po koncu oddajanja. Zaradi prekomerne uporabe je delovanje naprave Android TV lahko počasno ali nestabilno, ker porabi preveč pomnilnika."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Aplikaciji omogoča hitro pošiljanje fiksnih oddaj, ki ostanejo po koncu oddajanja. Zaradi prekomerne uporabe je delovanje telefona lahko počasno ali nestabilno, ker porabi preveč pomnilnika."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"branje stikov"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Aplikaciji omogoča branje podatkov o stikih v tabličnem računalniku, vključno s pogostostjo klicev, pošiljanja e-poštnih sporočil in druge komunikacije s posamezniki. S tem dovoljenjem lahko aplikacije shranjujejo podatke o stikih in zlonamerne aplikacije lahko te podatke razkrijejo brez vaše vednosti."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Aplikaciji dovoljuje branje podatkov o stikih, shranjenih v napravi Android TV, vključno s pogostostjo klicev, pošiljanja e-poštnih sporočil in druge komunikacije s posamezniki. S tem dovoljenjem lahko aplikacije shranjujejo podatke o stikih in zlonamerne aplikacije lahko te podatke razkrijejo brez vaše vednosti."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Aplikaciji omogoča branje podatkov o stikih v telefonu, vključno s pogostostjo klicev, pošiljanja e-poštnih sporočil in druge komunikacije s posamezniki. S tem dovoljenjem lahko aplikacije shranjujejo podatke o stikih in zlonamerne aplikacije lahko te podatke razkrijejo brez vaše vednosti."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Aplikaciji dovoljuje branje podatkov o stikih, shranjenih v tabličnem računalniku. Aplikacije bodo imele dostop tudi do računov v tabličnem računalniku, ki so ustvarili stike. To lahko vključuje račune, ki so jih ustvarile nameščene aplikacije. S tem dovoljenjem lahko aplikacije shranjujejo podatke o stikih in zlonamerne aplikacije lahko te podatke razkrijejo brez vaše vednosti."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Aplikaciji dovoljuje branje podatkov o stikih, shranjenih v napravi Android TV. Aplikacije bodo imele dostop tudi do računov v napravi Android TV, ki so ustvarili stike. To lahko vključuje račune, ki so jih ustvarile nameščene aplikacije. S tem dovoljenjem lahko aplikacije shranjujejo podatke o stikih in zlonamerne aplikacije lahko te podatke razkrijejo brez vaše vednosti."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Aplikaciji dovoljuje branje podatkov o stikih, shranjenih v telefonu. Aplikacije bodo imele dostop tudi do računov v telefonu, ki so ustvarili stike. To lahko vključuje račune, ki so jih ustvarile nameščene aplikacije. S tem dovoljenjem lahko aplikacije shranjujejo podatke o stikih in zlonamerne aplikacije lahko te podatke razkrijejo brez vaše vednosti."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"spreminjanje stikov"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Aplikaciji omogoča spreminjanje podatkov o stikih v tabličnem računalniku, vključno s pogostostjo klicev, pošiljanja e-poštnih sporočil in druge komunikacije z določenimi stiki. S tem dovoljenjem lahko aplikacije brišejo podatke o stikih."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Aplikaciji dovoljuje spreminjanje podatkov o stikih, shranjenih v napravi Android TV, vključno s pogostostjo klicev, pošiljanja e-poštnih sporočil in druge komunikacije z določenimi stiki. S tem dovoljenjem lahko aplikacije brišejo podatke o stikih."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Aplikaciji omogoča spreminjanje podatkov o stikih v telefonu, vključno s pogostostjo klicev, pošiljanja e-poštnih sporočil in druge komunikacije z določenimi stiki. S tem dovoljenjem lahko aplikacije brišejo podatke o stikih."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Aplikaciji dovoljuje spreminjanje podatkov o stikih, shranjenih v tabličnem računalniku. S tem dovoljenjem lahko aplikacije brišejo podatke o stikih."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Aplikaciji dovoljuje spreminjanje podatkov o stikih, shranjenih v napravi Android TV. S tem dovoljenjem lahko aplikacije brišejo podatke o stikih."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Aplikaciji dovoljuje spreminjanje podatkov o stikih, shranjenih v telefonu. S tem dovoljenjem lahko aplikacije brišejo podatke o stikih."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"branje dnevnika klicev"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Ta aplikacija lahko prebere zgodovino klicev."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"pisanje v dnevnik klicev"</string>
@@ -413,13 +412,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"dostopanje do ukazov ponudnika dodatnih lokacij"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Aplikaciji omogoča dostop do dodatnih ukazov ponudnika lokacij. S tem lahko aplikacija moti delovanje sistema GPS ali drugih virov lokacije."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"dostop do točne lokacije samo, ko deluje v ospredju"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Ta aplikacija lahko pridobi vašo točno lokacijo samo, ko deluje v ospredju. Če želite aplikaciji omogočiti uporabo teh lokacijskih storitev, morajo biti te vklopljene in na voljo v telefonu. Poraba energije akumulatorja bo morda večja."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"dostop do približne lokacije (na podlagi omrežja) samo med delovanjem v ospredju"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Ta aplikacija lahko pridobi vašo lokacijo na podlagi omrežnih virov, kot so bazne postaje in omrežja Wi-Fi, vendar samo, ko deluje v ospredju. Če želite aplikaciji omogočiti uporabo teh lokacijskih storitev, morajo biti te vklopljene in na voljo v tabličnem računalniku."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Ta aplikacija lahko pridobi vašo lokacijo na podlagi omrežnih virov, kot so bazne postaje in omrežja Wi-Fi, vendar samo, ko deluje v ospredju. Če želite aplikaciji omogočiti uporabo teh lokacijskih storitev, morajo biti te vklopljene in na voljo v napravi Android TV."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Ta aplikacija lahko pridobi vašo lokacijo na podlagi omrežnih virov, kot so bazne postaje in omrežja Wi-Fi, vendar samo, ko deluje v ospredju. Če želite aplikaciji omogočiti uporabo teh lokacijskih storitev, morajo biti te vklopljene in na voljo v telefonu."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Ta aplikacija lahko pridobi vašo točno lokacijo samo, ko deluje v ospredju. Če želite aplikaciji omogočiti uporabo lokacijskih storitev, morajo biti te vklopljene in na voljo v napravi. Poraba energije baterije bo morda večja."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"dostop do približne lokacije samo, ko deluje v ospredju"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Ta aplikacija lahko pridobi vašo približno lokacijo samo, ko deluje v ospredju. Če želite aplikaciji omogočiti uporabo lokacijskih storitev, morajo biti te vklopljene in na voljo v napravi."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"dostop do lokacije med izvajanjem v ozadju"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Če to dovolite poleg dostopa do približne ali natančne lokacije, lahko aplikacija dostopa do lokacije, medtem ko se izvaja v ozadju."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Ta aplikacija lahko dostopa do lokacije, ko deluje v ospredju ali ozadju."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"spreminjanje nastavitev zvoka"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Aplikaciji omogoča spreminjanje splošnih zvočnih nastavitev, na primer glasnost in kateri zvočnik se uporablja."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"snemanje zvoka"</string>
@@ -500,6 +497,10 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Aplikaciji omogoča ogled konfiguracije Bluetootha tabličnega računalnika ter vzpostavljanje in sprejemanje povezave s seznanjenimi napravami."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Aplikaciji dovoljuje ogled konfiguracije vmesnika Bluetooth v napravi Android TV ter ustvarjanje in sprejemanje povezav s seznanjenimi napravami."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Aplikaciji omogoča ogled konfiguracije Bluetootha telefona ter ustvarjanje in sprejemanje povezave s seznanjenimi napravami."</string>
+ <!-- no translation found for permlab_preferredPaymentInfo (5274423844767445054) -->
+ <skip />
+ <!-- no translation found for permdesc_preferredPaymentInfo (8583552469807294967) -->
+ <skip />
<string name="permlab_nfc" msgid="1904455246837674977">"nadzor nad komunikacijo s tehnologijo bližnjega polja"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Podpira komunikacijo med računalnikom in oznakami, karticami in bralniki komunikacije s tehnologijo bližnjega polja."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"onemogočanje zaklepanja zaslona"</string>
@@ -1926,7 +1927,11 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Vzpostavljena povezava z napravo <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Dotaknite se, če si želite ogledati datoteke"</string>
<string name="pin_target" msgid="8036028973110156895">"Pripenjanje"</string>
+ <!-- no translation found for pin_specific_target (7824671240625957415) -->
+ <skip />
<string name="unpin_target" msgid="3963318576590204447">"Odpenjanje"</string>
+ <!-- no translation found for unpin_specific_target (3859828252160908146) -->
+ <skip />
<string name="app_info" msgid="6113278084877079851">"Podatki o aplikacijah"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Začenjanje predstavitve …"</string>
@@ -1971,6 +1976,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Želite posodobiti te elemente v aplikaciji "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> in <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Shrani"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Ne, hvala"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Ne zdaj"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Nikoli"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Posodobi"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Naprej"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"geslo"</string>
@@ -2068,5 +2075,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Preklop razdeljenega zaslona"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Zaklenjen zaslon"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Posnetek zaslona"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> v pojavnem oknu."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Vrstica s podnapisi aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 39f73779a4ef..f38d354b6ae8 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Aplikacioni i administratorit të profilit të punës mungon ose është dëmtuar. Si rezultat i kësaj, profili yt i punës dhe të dhënat përkatëse janë fshirë. Kontakto me administratorin për ndihmë."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Profili yt i punës nuk është më i disponueshëm në këtë pajisje"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Shumë përpjekje për fjalëkalimin"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Administratori e refuzoi pajisjen për përdorim personal"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Pajisja është e menaxhuar"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Organizata jote e menaxhon këtë pajisje dhe mund të monitorojë trafikun e rrjetit. Trokit për detaje."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Pajisja do të spastrohet"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Lejon aplikacionin të dërgojë transmetime ngjitëse të cilat mbeten pas përfundimit të transmetimit. Përdorimi i tepërt mund ta bëjë pajisjen tënde Android TV të ngadaltë ose të paqëndrueshme, duke e detyruar atë të përdorë më shumë memorie."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Lejon aplikacionin të dërgojë transmetime ngjitëse që qëndrojnë derisa të përfundojë transmetimi. Përdorimi i tepruar mund ta bëjë telefonin të ngadaltë ose të paqëndrueshëm duke e detyruar atë të përdorë shumë kujtesë."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"lexo kontaktet e tua"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Lejon aplikacionin të lexojë të dhëna rreth kontakteve të ruajtura në tabletin tënd, përfshirë shpeshtësinë me të cilën ke telefonuar, ke dërguar mail-a ose komunikuar në mënyra të tjera me individë të caktuar. Kjo leje u mundëson aplikacioneve të ruajnë të dhënat e tua të kontakteve, ndaj aplikacionet keqdashëse mund të ndajnë të dhëna të kontakteve pa dijeninë tënde."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Lejon aplikacionin të lexojë të dhënat rreth kontakteve të tua të ruajtura në pajisjen tënde Android TV, përfshi shpeshtësinë me të cilën ke telefonuar, ke dërguar email-e apo komunikuar në rrugë të tjera me kontakte të veçanta. Ky autorizim i lejon aplikacionet të ruajnë të dhënat e tua të kontakteve, dhe aplikacionet keqdashëse mund të ndajnë të dhëna të kontakteve pa dijeninë tënde."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Lejon aplikacionin të lexojë të dhëna rreth kontakteve të ruajtura në telefonin tënd, përfshirë shpeshtësinë me të cilën ke telefonuar, ke dërguar mail-a ose komunikuar në mënyra të tjera me individë të caktuar. Kjo leje u mundëson aplikacioneve të ruajnë të dhënat e tua të kontakteve, ndaj aplikacionet keqdashëse mund të ndajnë të dhëna të kontakteve pa dijeninë tënde."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Lejon aplikacionin të lexojë të dhëna për kontaktet e ruajtura në tabletin tënd. Aplikacionet do të kenë po ashtu qasje te llogaritë në tabletin tënd, të cilat i kanë krijuar kontaktet. Kjo mund të përfshijë llogaritë e krijuara nga aplikacionet që ke instaluar. Kjo leje lejon që aplikacionet të ruajnë të dhënat e tua të kontakteve dhe aplikacionet keqdashëse mund të ndajnë të dhëna të kontakteve pa dijeninë tënde."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Lejon aplikacionin të lexojë të dhëna për kontaktet e ruajtura në pajisjen tënde Android TV. Aplikacionet do të kenë po ashtu qasje te llogaritë në pajisjen tënde të Android TV, të cilat i kanë krijuar kontaktet. Kjo mund të përfshijë llogaritë e krijuara nga aplikacionet që ke instaluar. Kjo leje lejon që aplikacionet të ruajnë të dhënat e tua të kontakteve dhe aplikacionet keqdashëse mund të ndajnë të dhëna të kontakteve pa dijeninë tënde."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Lejon aplikacionin të lexojë të dhëna për kontaktet e ruajtura në telefonin tënd. Aplikacionet do të kenë po ashtu qasje te llogaritë në telefonin tënd, të cilat i kanë krijuar kontaktet. Kjo mund të përfshijë llogaritë e krijuara nga aplikacionet që ke instaluar. Kjo leje lejon që aplikacionet të ruajnë të dhënat e tua të kontakteve dhe aplikacionet keqdashëse mund të ndajnë të dhëna të kontakteve pa dijeninë tënde."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"modifiko kontaktet"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Lejon aplikacionin të modifikojë të dhënat rreth kontakteve të tua të ruajtura në tabletin tënd, përfshi shpeshtësinë me të cilën ke telefonuar, ke dërguar mail-a apo ke komunikuar në rrugë të tjera me kontakte të veçanta. Kjo leje u mundëson aplikacioneve të fshijnë të dhënat e kontaktit."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Lejon aplikacionin të modifikojë të dhënat rreth kontakteve të tua të ruajtura në pajisjen tënde Android TV, përfshi shpeshtësinë me të cilën ke telefonuar, ke dërguar email-e apo komunikuar në rrugë të tjera me kontakte specifike. Ky autorizim i lejon aplikacionet të fshijnë të dhënat e kontaktit."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Lejon aplikacionin të modifikojë të dhënat e kontakteve të tua të ruajtura në telefon, përfshirë shpeshtësinë me të cilën ke telefonuar, ke dërguar mail-a apo ke komunikuar në rrugë të tjera me kontakte të veçanta. Kjo leje iu mundëson aplikacioneve të fshijnë të dhënat e kontakteve."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Lejon aplikacionin të modifikojë të dhënat rreth kontakteve të tua të ruajtura në tabletin tënd. Kjo leje lejon që aplikacionet të fshijnë të dhënat e kontakteve."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Lejon aplikacionin të modifikojë të dhënat rreth kontakteve të tua të ruajtura në pajisjen tënde Android TV. Kjo leje lejon që aplikacionet të fshijnë të dhënat e kontakteve."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Lejon aplikacionin të modifikojë të dhënat rreth kontakteve të tua të ruajtura në telefonin tënd. Kjo leje lejon që aplikacionet të fshijnë të dhënat e kontakteve."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"lexo ditarin e telefonatave"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Ky aplikacion mund të lexojë të gjithë historikun e telefonatave."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"shkruaj ditarin e telefonatave"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"qasje në komandat shtesë të ofruesit të vendndodhjes"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Lejon aplikacionin të ketë qasje në komandat shtesë të ofruesit për vendndodhjen. Kjo mund ta lejojë aplikacionin të ndërhyjë në operacionin e GPS-së apo të burimeve të tjera për vendndodhjen."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"qasu në vendndodhjen e saktë vetëm në plan të parë"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Ky aplikacion mund të marrë vendndodhjen tënde të saktë në çdo kohë kur është në plan të parë. Këto shërbime të vendndodhjes duhet të jenë të aktivizuara dhe në dispozicion në telefonin tënd që aplikacioni të mund t\'i përdorë. Kjo gjë mund të rritë konsumin e baterisë."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"qasu te vendndodhja e përafërt (bazuar te rrjeti) vetëm në plan të parë"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Ky aplikacion mund të marrë vendndodhjen tënde bazuar në burimet e rrjetit si antenat e operatorëve celulare dhe rrjetet Wi-Fi, por vetëm kur aplikacioni është në plan të parë. Këto shërbime të vendndodhjes duhet të jenë të aktivizuara dhe të ofrohen në tabletin tënd që aplikacioni të mund t\'i përdorë."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Ky aplikacion mund të marrë vendndodhjen tënde bazuar në burimet e rrjetit si antenat e operatorëve celulare dhe rrjetet Wi-Fi, por vetëm kur aplikacioni është në plan të parë. Këto shërbime të vendndodhjes duhet të jenë të aktivizuara dhe të ofrohen në pajisjen tënde Android TV që aplikacioni të mund t\'i përdorë."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Ky aplikacion mund të marrë vendndodhjen tënde bazuar në burimet e rrjetit si antenat e operatorëve celulare dhe rrjetet Wi-Fi, por vetëm kur aplikacioni është në plan të parë. Këto shërbime të vendndodhjes duhet të jenë të aktivizuara dhe të ofrohen në telefonin tënd që aplikacioni të mund t\'i përdorë."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Ky aplikacion mund të marrë vendndodhjen tënde të saktë vetëm kur është në plan të parë. Shërbimet e vendndodhjes duhet të jenë të aktivizuara dhe në dispozicion në pajisjen tënde që aplikacioni të mund t\'i përdorë. Kjo gjë mund të rrisë konsumin e baterisë."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"qasu në vendndodhjen e përafërt vetëm në plan të parë"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Ky aplikacion mund të marrë vendndodhjen tënde të përafërt vetëm kur është në plan të parë. Shërbimet e vendndodhjes duhet të jenë të aktivizuara dhe të ofrohen në pajisjen tënde që aplikacioni të mund t\'i përdorë."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"qasje te vendndodhja në sfond"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Nëse kjo jepet përveç qasjes te vendndodhja e përafërt ose të saktë, aplikacioni mund të qaset te vendndodhja ndërkohë që ekzekutohet në sfond."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Ky aplikacion mund të ketë qasje te vendndodhja ndërkohë që funksionon në sfond, përveç qasjes në plan të parë te vendndodhja."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"ndrysho cilësimet e audios"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Lejon aplikacionin të modifikojë cilësimet globale të audios siç është volumi dhe se cili altoparlant përdoret për daljen."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"regjistro audio"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Lejon aplikacionin të shikojë konfigurimin e \"bluetooth-it\" në tablet, të kryejë dhe të pranojë lidhje me pajisjet e çiftuara."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Lejon aplikacionin të shikojë konfigurimin e Bluetooth-it në pajisjen tënde Android TV dhe të kryejë dhe të pranojë lidhje me pajisjet e çiftuara."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Lejon aplikacionin të shohë konfigurimin e \"bluetooth-it\" në telefon dhe të kryejë e pranojë lidhje me pajisjet e çiftuara."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Informacionet për shërbimin e preferuar të pagesës me NFC"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Lejon aplikacionin të marrë informacione për shërbimin e preferuar të pagesës me NFC si p.sh. ndihmat e regjistruara dhe destinacionin e itinerarit."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"kontrollo \"Komunikimin e fushës në afërsi\" NFC"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Lejon aplikacionin të komunikojë me etiketimet e \"Komunikimit të fushës së afërt (NFC)\", kartat dhe lexuesit."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"çaktivizo kyçjen e ekranit"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"Shkurtorja e qasshmërisë e aktivizoi <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"Shkurtorja e qasshmërisë e çaktivizoi <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Shtyp dhe mbaj shtypur të dy butonat e volumit për tre sekonda për të përdorur <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Zgjidh një shërbim për ta përdorur kur troket butonin e qasshmërisë:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Zgjidh një shërbim për ta përdorur me gjestin e qasshmërisë (rrëshqit shpejt lart nga fundi i ekranit me dy gishta):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Zgjidh një shërbim për ta përdorur me gjestin e qasshmërisë (rrëshqit shpejt lart nga fundi i ekranit me tre gishta):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Për të kaluar mes shërbimeve, prek dhe mbaj të shtypur butonin e qasshmërisë."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Për të kaluar mes pajisjeve, rrëshqit shpejt lart me dy gishta dhe mbaje prekur."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Për të kaluar mes pajisjeve, rrëshqit shpejt lart me tre gishta dhe mbaje prekur."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Zmadhimi"</string>
<string name="user_switched" msgid="7249833311585228097">"Emri i përdoruesit aktual: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="user_switching_message" msgid="1912993630661332336">"Po kalon në <xliff:g id="NAME">%1$s</xliff:g>…"</string>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"U lidh me <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Trokit për të parë skedarët"</string>
<string name="pin_target" msgid="8036028973110156895">"Gozhdo"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Gozhdoje <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Zhgozhdo"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Zhgozhdoje <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Informacioni mbi aplikacionin"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Po nis demonstrimin..."</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Të përditësohen këta artikuj në "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> dhe <xliff:g id="TYPE_2">%3$s</xliff:g> ?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Ruaj"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Jo, faleminderit"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Jo tani"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Asnjëherë"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Përditëso"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Vazhdo"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"fjalëkalimi"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Kalo tek ekrani i ndarë"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Ekrani i kyçjes"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Pamja e ekranit"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"Aplikacioni <xliff:g id="APP_NAME">%1$s</xliff:g> në dritaren kërcyese."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Shiriti i nëntitullit të <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index e93c852dfccc..c3881cbf62fc 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -190,8 +190,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Апликација за администраторе на профилу за Work недостаје или је оштећена. Због тога су профил за Work и повезани подаци избрисани. Обратите се администратору за помоћ."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Профил за Work више није доступан на овом уређају"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Превише покушаја уноса лозинке"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Администратор је уступио уређај за личну употребу"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Уређајем се управља"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Организација управља овим уређајем и може да надгледа мрежни саобраћај. Додирните за детаље."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Уређај ће бити обрисан"</string>
@@ -384,13 +383,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Дозвољава апликацији да шаље лепљива емитовања која остају по завршетку емитовања. Прекомерна употреба може да успори или дестабилизује Android TV уређај тако што ће га приморати да троши превише меморије."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Дозвољава апликацији да шаље пријемчива емитовања, која остају по завршетку емитовања. Прекомерна употреба може да успори или дестабилизује телефон тако што ће га приморати да троши превише меморије."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"читање контаката"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Дозвољава апликацији да чита податке о контактима ускладиштене на таблету, укључујући податке о томе колико често зовете одређене особе, шаљете им поруке е-поште или на други начин комуницирате са њима. Ова дозвола омогућава апликацијама да чувају податке о контактима, а злонамерне апликације могу да деле податке о контактима без вашег знања."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Дозвољава апликацији да чита податке о контактима које чувате на Android TV уређају, укључујући учесталост позива, слања имејлова или других начина комуникације са одређеним појединцима. Ова дозвола омогућава апликацијама да чувају податке о контактима и злонамерне апликације могу да деле податке о контактима без вашег знања."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Дозвољава апликацији да чита податке о контактима ускладиштене на телефону, укључујући податке о томе колико често зовете одређене особе, шаљете им поруке е-поште или на други начин комуницирате са њима. Ова дозвола омогућава апликацијама да чувају податке о контактима, а злонамерне апликације могу да деле податке о контактима без вашег знања."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Дозвољава апликацији да чита податке о контактима које чувате на таблету. Апликације ће имати приступ и налозима на вашем таблету на којима су направљени контакти. Ту могу да спадају налози које су отвориле апликације које сте инсталирали. Ова дозвола омогућава апликацијама да чувају податке о контактима и злонамерне апликације могу да деле податке о контактима без вашег знања."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Дозвољава апликацији да чита податке о контактима које чувате на Android TV уређају. Апликације ће имати приступ и налозима на вашем Android TV уређају на којима су направљени контакти. Ту могу да спадају налози које су отвориле апликације које сте инсталирали. Ова дозвола омогућава апликацијама да чувају податке о контактима и злонамерне апликације могу да деле податке о контактима без вашег знања."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Дозвољава апликацији да чита податке о контактима које чувате на телефону. Апликације ће имати приступ и налозима на вашем телефону на којима су направљени контакти. Ту могу да спадају налози које су отвориле апликације које сте инсталирали. Ова дозвола омогућава апликацијама да чувају податке о контактима и злонамерне апликације могу да деле податке о контактима без вашег знања."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"измена контаката"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Дозвољава апликацији да мења податке о контактима ускладиштене на таблету, укључујући податке о томе колико често зовете одређене контакте, шаљете им поруке е-поште или на други начин комуницирате са њима. Ова дозвола омогућава апликацијама да бришу податке о контактима."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Дозвољава апликацији да мења податке о контактима које чувате на Android TV уређају, укључујући учесталост позива, слања имејлова или других начина комуникације са одређеним контактима. Ова дозвола омогућава апликацијама да бришу податке о контактима."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Дозвољава апликацији да мења податке о контактима ускладиштене на телефону, укључујући податке о томе колико често зовете одређене контакте, шаљете им поруке е-поште или на други начин комуницирате са њима. Ова дозвола омогућава апликацијама да бришу податке о контактима."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Дозвољава апликацији да мења податке о контактима које чувате на таблету. Ова дозвола омогућава апликацијама да бришу податке о контактима."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Дозвољава апликацији да мења податке о контактима које чувате на Android TV уређају. Ова дозвола омогућава апликацијама да бришу податке о контактима."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Дозвољава апликацији да мења податке о контактима које чувате на телефону. Ова дозвола омогућава апликацијама да бришу податке о контактима."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"читање евиденције позива"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Ова апликација може да чита историју позива."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"писање евиденције позива"</string>
@@ -410,13 +409,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"приступ додатним командама добављача локације"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Омогућава апликацији да приступа додатним командама даваоца услуга локације. То може да омогући апликацији да утиче на рад GPS-а или других извора локације."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"приступ прецизној локацији само у првом плану"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Ова апликација може да одреди вашу тачну локацију само када ради у првом плану. Ове услуге локације морају да буду укључене и доступне на телефону да би апликација могла да их користи. То може да повећа потрошњу батерије."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"приступ приближној локацији (утврђеној преко мреже) само у првом плану"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Ова апликација може да приступи вашој локацији помоћу извора мреже, као што су мобилни предајници и Wi-Fi мреже, али само када апликација ради у првом плану. Ове услуге локације морају да буду укључене и доступне на таблету да би апликација могла да их користи"</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Ова апликација може да приступи вашој локацији помоћу извора мреже, као што су мобилни предајници и Wi-Fi мреже, али само када апликација ради у првом плану. Ове услуге локације морају да буду укључене и доступне на Android TV уређају да би апликација могла да их користи."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Ова апликација може да приступи вашој локацији помоћу извора мреже, као што су мобилни предајници и Wi-Fi мреже, али само када апликација ради у првом плану. Ове услуге локације морају да буду укључене и доступне на телефону да би апликација могла да их користи."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Ова апликација може да одреди вашу тачну локацију само када ради у првом плану. Услуге локације морају да буду укључене и доступне на уређају да би апликација могла да их користи. То може да повећа потрошњу батерије."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"приступ приближној локацији само у првом плану"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Ова апликација може да одреди вашу приближну локацију само када ради у првом плану. Услуге локације морају да буду укључене и доступне на уређају да би апликација могла да их користи."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"приступ локацији у позадини"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Ако се поред приближног или прецизног приступа локација одобри и овај, апликација може да приступа локацији док је покренута у позадини."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Ова апликација може да приступа локацији док ради у позадини, као и када ради у првом плану."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"промена аудио подешавања"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Дозвољава апликацији да мења глобална аудио подешавања као што су јачина звука и избор звучника који се користи као излаз."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"снимање аудио записа"</string>
@@ -497,6 +494,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Дозвољава апликацији да прегледа конфигурацију Bluetooth-а на таблету, као и да успоставља и прихвата везе са упареним уређајима."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Дозвољава апликацији да прегледа конфигурацију Bluetooth-а на Android TV уређају и да успоставља и прихвата везе са упареним уређајима."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Дозвољава апликацији да прегледа конфигурацију Bluetooth-а на телефону, као и да успоставља и прихвата везе са упареним уређајима."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Информације о жељеној NFC услузи за плаћање"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Дозвољава апликацији да преузима информације о жељеној NFC услузи за плаћање, попут регистрованих идентификатора апликација и одредишта преусмеравања."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"контрола комуникације у ужем пољу (Near Field Communication)"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Дозвољава апликацији да комуницира са ознакама, картицама и читачима комуникације кратког домета (NFC)."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"онемогућавање закључавања екрана"</string>
@@ -1640,12 +1639,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"Пречица за приступачност је укључила услугу <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"Пречица за приступачност је искључила услугу <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>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Одаберите услугу која ће се користити када додирнете дугме за приступачност:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Одаберите функцију која ће се користити помоћу покрета за приступачност (помоћу два прста превуците нагоре од дна екрана):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Одаберите услугу која ће се користити помоћу покрета за приступачност (помоћу три прста превуците нагоре од дна екрана):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Да бисте прелазили са једне услуге на другу, додирните и задржите дугме за приступачност."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Да бисте прелазили са једне услуге на другу, превуците нагоре помоћу два прста и задржите."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Да бисте прелазили са једне услуге на другу, превуците нагоре помоћу три прста и задржите."</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>
@@ -1894,7 +1887,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Повезано је са производом <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Додирните за преглед датотека"</string>
<string name="pin_target" msgid="8036028973110156895">"Закачи"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Закачи апликацију <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Откачи"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Откачи апликацију <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Информације о апликацији"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Покрећемо демонстрацију..."</string>
@@ -1938,6 +1933,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Желите ли да ажурирате ове ставке у услузи "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <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>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Сачувај"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Не, хвала"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Не сада"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Никада"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Ажурирај"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Настави"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"лозинка"</string>
@@ -2034,5 +2031,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Укључите/искључите подељени екран"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Закључани екран"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Снимак екрана"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"Апликација <xliff:g id="APP_NAME">%1$s</xliff:g> у искачућем прозору."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Трака са насловима апликације <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index cf0e0bbea662..feef35b0949b 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Administratörsappen för jobbprofilen saknas eller är skadad. Det innebär att jobbprofilen och all relaterad data har raderats. Kontakta administratören om du vill ha hjälp."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Jobbprofilen är inte längre tillgänglig på enheten"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"För många försök med lösenord"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Administratören tillåter inte längre privat bruk av enheten"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Enheten hanteras"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Organisationen hanterar den här enheten och kan övervaka nätverkstrafiken. Tryck om du vill veta mer."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Enheten kommer att rensas"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Tillåter att appen skickar sticky-sändningar som finns kvar när sändningen är slut. Vid intensiv användning kan Android TV-enheten bli långsam eller instabil eftersom för mycket minne används."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Tillåter att appen skickar sticky broadcast, som finns kvar när sändningen är slut. Vid intensiv användning kan mobilen bli långsam eller instabil eftersom minnet överbelastas."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"läsa dina kontakter"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Tillåter att appen läser kontaktuppgifter som sparats på surfplattan, inklusive information om hur ofta du har ringt, skickat e-post till eller på andra sätt kommunicerat med specifika personer. Med den här behörigheten tillåts appen att spara kontaktuppgifter. Skadliga appar kan dela uppgifterna med andra utan din vetskap."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Tillåter att appen läser kontaktuppgifter som sparats på Android TV-enheten, inklusive information om hur ofta du har ringt, skickat e-post till eller på andra sätt kommunicerat med enskilda personer. Med den här behörigheten tillåts appen att spara kontaktuppgifter. Skadliga appar kan dela uppgifterna med andra utan din vetskap."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Tillåter att appen läser kontaktuppgifter som sparats på mobilen, inklusive information om hur ofta du har ringt, skickat e-post till eller på andra sätt kommunicerat med specifika personer. Med den här behörigheten tillåts appen att spara kontaktuppgifter. Skadliga appar kan dela uppgifterna med andra utan din vetskap."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Tillåter att appen läser kontaktuppgifter som sparats på surfplattan. Appar har även åtkomst till de konton på surfplattan som har skapade kontakter. Detta kan inkludera konton som har skapats av appar som du har installerat. Med den här behörigheten tillåts appen att spara kontaktuppgifter. Skadliga appar kan dela uppgifterna med andra utan din vetskap."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Tillåter att appen läser kontaktuppgifter som sparats på Android TV-enheten. Appar har även åtkomst till de konton på Android TV-enheten som har skapade kontakter. Detta kan inkludera konton som har skapats av appar som du har installerat. Med den här behörigheten tillåts appen att spara kontaktuppgifter. Skadliga appar kan dela uppgifterna med andra utan din vetskap."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Tillåter att appen läser kontaktuppgifter som sparats på telefonen. Appar har även åtkomst till de konton på telefonen som har skapade kontakter. Detta kan inkludera konton som har skapats av appar som du har installerat. Med den här behörigheten tillåts appen att spara kontaktuppgifter. Skadliga appar kan dela uppgifterna med andra utan din vetskap."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"ändra kontakterna"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Tillåter att appen ändrar kontaktuppgifter som sparats på surfplattan, inklusive information om hur ofta du har ringt, skickat e-post till eller på andra sätt kommunicerat med specifika personer. Med den här behörigheten tillåts appar att ta bort kontaktuppgifter."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Tillåter att appen ändrar kontaktuppgifter som sparats på Android TV-enheten, inklusive information om hur ofta du har ringt, skickat e-post till eller på andra sätt kommunicerat med enskilda kontakter. Med den här behörigheten tillåts appar att ta bort kontaktuppgifter."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Tillåter att appen ändrar kontaktuppgifter som sparats på mobilen, inklusive information om hur ofta du har ringt, skickat e-post till eller på andra sätt kommunicerat med specifika personer. Med den här behörigheten tillåts appar att ta bort kontaktuppgifter."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Tillåter att appen ändrar kontaktuppgifter som sparats på surfplattan. Med den här behörigheten får appar även radera kontaktuppgifter."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Tillåter att appen ändrar kontaktuppgifter som sparats på Android TV-enheten. Med den här behörigheten får appar även radera kontaktuppgifter."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Tillåter att appen ändrar kontaktuppgifter som sparats på telefonen. Med den här behörigheten får appar även radera kontaktuppgifter."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"läs samtalslogg"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Appen kan läsa din samtalshistorik."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"skriv samtalslogg"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"få åtkomst till extra kommandon för platsleverantör"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Tillåter att appen får åtkomst till extra kommandon för platsleverantör. Detta kan innebära att appen tillåts störa funktionen för GPS eller andra platskällor."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"endast åtkomst till exakt plats i förgrunden"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Den här appen kan endast få information om din exakta plats när den körs i förgrunden. Platstjänsterna måste ha aktiverats och finnas på mobilen om appen ska kunna använda dem. Detta kan leda till ökad batteriförbrukning."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"endast åtkomst till beräknad plats (nätverksbaserad) i förgrunden"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Appen kan endast få information om din plats från källor i nätverket, som mobilmaster och Wi-Fi-nätverk, när den körs i förgrunden. Platstjänsterna måste ha aktiverats och finnas på surfplattan om appen ska kunna använda dem."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Appen kan få information om din plats från olika nätverkskällor, som mobilmaster och Wi-Fi-nätverk, men endast när den körs i förgrunden. Platstjänsterna måste ha aktiverats och finnas på Android TV-enheten om appen ska kunna använda dem."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Appen kan endast få information om din plats från källor i nätverket, som mobilmaster och Wi-Fi-nätverk, när den körs i förgrunden. Platstjänsterna måste ha aktiverats och finnas på mobilen om appen ska kunna använda dem."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Den här appen kan endast få information om din exakta plats när den körs i förgrunden. Platstjänsterna måste ha aktiverats och vara tillgängliga på enheten om appen ska kunna använda dem. Detta kan leda till ökad batteriförbrukning."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"endast åtkomst till ungefärlig plats i förgrunden"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Den här appen kan endast få information om din ungefärliga plats när den körs i förgrunden. Platstjänsterna måste ha aktiverats och vara tillgängliga på enheten om appen ska kunna använda dem."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"få åtkomst till platsinformation i bakgrunden"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Om denna behörighet ges utöver ungefärlig eller exakt platsåtkomst får appen åtkomst till platsinformation när den körs i bakgrunden."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Appen får åtkomst till platsinformation när appen körs i bakgrunden, förutom att den har åtkomst när den körs i förgrunden."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"ändra dina ljudinställningar"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Tillåter att appen ändrar globala ljudinställningar som volym och vilken högtalarutgång som används."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"spela in ljud"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Tillåter att appen kommer åt pekdatorns Bluetooth-konfiguration och upprättar och godkänner anslutningar till parkopplade enheter."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Tillåter att appen läser Android TV-enhetens Bluetooth-konfiguration och upprättar och godkänner anslutningar till parkopplade enheter."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Tillåter att appen kommer åt mobilens Bluetooth-konfiguration och upprättar och godkänner anslutningar till parkopplade enheter."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Information kopplad till standardtjänsten för NFC-betalning"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Tillåter att appen hämtar information kopplad till standardtjänsten för NFC-betalning, till exempel registrerade hjälpmedel och ruttdestinationer."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"kontrollera närfältskommunikationen"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Tillåter att appen kommunicerar med etiketter, kort och läsare för närfältskommunikation (NFC)."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"inaktivera skärmlåset"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> aktiverades av Aktivera tillgänglighet snabbt"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> inaktiverades av Aktivera tillgänglighet snabbt"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Tryck och håll båda volymknapparna i tre sekunder för att använda <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Välj en tjänst som ska användas när du trycker på tillgänglighetsknappen:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Välj en tjänst som ska användas med tillgänglighetsrörelsen (svepa uppåt med två fingrar från skärmens nederkant):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Välj en tjänst som ska användas med tillgänglighetsrörelsen (svepa uppåt med tre fingrar från skärmens nederkant):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Byt mellan tjänster genom att trycka länge på tillgänglighetsknappen."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Byt mellan tjänster genom att svepa uppåt med två fingrar och hålla kvar dem."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Byt mellan tjänster genom att svepa uppåt med tre fingrar och hålla kvar dem."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Förstoring"</string>
<string name="user_switched" msgid="7249833311585228097">"Nuvarande användare: <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="1912993630661332336">"Byter till <xliff:g id="NAME">%1$s</xliff:g> …"</string>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Ansluten till <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Filerna visas om du trycker här"</string>
<string name="pin_target" msgid="8036028973110156895">"Fäst"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Fäst <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Lossa"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Lossa <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Info om appen"</string>
<string name="negative_duration" msgid="1938335096972945232">"-<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Demo startas …"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Vill du uppdatera dessa objekt i "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> och <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Spara"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Nej tack"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Inte nu"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Aldrig"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Uppdatera"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Fortsätt"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"lösenordet"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Aktivera och inaktivera delad skärm"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Låsskärm"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Skärmdump"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"<xliff:g id="APP_NAME">%1$s</xliff:g>-app i popup-fönster."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Textningsfält för <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index f8cd19ce5517..094e324efdc1 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Programu ya msimamizi wa wasifu wa kazini imepotea au ina hitilafu. Kwa sababu hiyo, wasifu wako wa kazini na data husika imefutwa. Wasiliana na msimamizi wako kwa usaidizi."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Wasifu wako wa kazini haupatikani tena kwenye kifaa hiki"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Umejaribu kuweka nenosiri mara nyingi mno"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Msimamizi aliacha kutumia kifaa kwa matumizi ya binafsi"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Kifaa kinadhibitiwa"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Shirika lako linadhibiti kifaa hiki na huenda likafuatilia shughuli kwenye mtandao. Gusa ili upate maelezo zaidi."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Data iliyomo kwenye kifaa chako itafutwa"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Huruhusu programu itume matangazo yanayonata, ambayo hubaki baada ya matangazo kuisha. Huenda matumizi zaidi yakapunguza kasi ya kifaa chako cha Android TV au kukifanya kisiwe thabiti kwa kukifanya kitumie hifadhi kubwa zaidi."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Inaruhusu programu kutuma matangazo nata, ambayo hubakia baada ya matangazo kuisha. Matumizi zaidi yanaweza kufanya simu kufanya kazi polepole au kuifanya isiwe thabiti kwa kuisababisha itumie kumbukumbu kubwa zaidi."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"kusoma anwani zako"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Inaruhusu programu kusoma data kuhusu anwani zako zilizohifadhiwa kwenye kompyuta kibao yako, ikiwa ni pamoja na mara ngapi umepiga simu, kutuma barua pepe au kuwasiliana kwa njia zingine na watu fulani. Idhini hii inaruhusu programu kuhifadhi data yako ya anwani, na programu hasidi zinaweza kushiriki data ya anwani bila ya kujua kwako."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Huruhusu programu isome data kuhusu anwani zako zilizohifadhiwa kwenye kifaa chako cha Android TV, ikiwa ni pamoja na mara ambazo umepiga simu, umetuma barua pepe au umewasiliana kwa njia zingine na watu mahususi. Idhini hii huruhusu programu kuhifadhi data yako ya anwani na huenda programu hasidi zikashiriki data ya anwani bila idhini yako."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Inaruhusu programu kusoma data kuhusu anwani zako zilizohifadhiwa kwenye simu yako, ikiwa ni pamoja na mara ngapi umepiga simu, kutuma barua pepe au kuwasiliana kwa njia zingine na watu fulani. Idhini hii inaruhusu programu kuhifadhi data yako ya anwani, na programu hasidi zinaweza kushiriki data ya anwani bila ya kujua kwako."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Huruhusu programu kusoma data kuhusu anwani zako zilizohifadhiwa kwenye kompyuta yako kibao. Programu pia zitafikia akaunti zilizo kwenye kompyuta yako kibao zilizounda anwani. Hii inaweza kujumuisha akaunti zilizoundwa na programu ambazo umesakinisha. Idhini hii huruhusu programu kuhifadhi data yako ya anwani na programu hasidi zinaweza kushiriki data ya anwani bila wewe kujua."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Huruhusu programu kusoma data kuhusu anwani zako zilizohifadhiwa kwenye kifaa chako cha Android TV. Programu pia zitafikia akaunti zilizo kwenye kifaa chako cha Android TV zilizounda anwani. Hii inaweza kujumuisha akaunti zilizoundwa na programu ambazo umesakinisha. Idhini hii huruhusu programu kuhifadhi data yako ya anwani na programu hasidi zinaweza kushiriki data ya anwani bila wewe kujua."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Huruhusu programu kusoma data kuhusu anwani zako zilizohifadhiwa kwenye simu yako. Programu pia zitafikia akaunti zilizo kwenye simu yako zilizounda anwani. Hii inaweza kujumuisha akaunti zilizoundwa na programu ambazo umesakinisha. Idhini hii huruhusu programu kuhifadhi data yako ya anwani na programu hasidi zinaweza kushiriki data ya anwani bila wewe kujua."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"kurekebisha anwani zako"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Huruhusu programu kurekebisha data kuhusu anwani ulizohifadhi kwenye kompyuta kibao yako, ikiwa ni pamoja na mara ambazo umepiga simu, kutuma barua pepe au kuwasiliana kwa njia nyingine na anwani maalum. Idhini hii inaruhusu programu kufuta data ya anwani."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Huruhusu programu ibadilishe data kuhusu anwani zako zilizohifadhiwa kwenye kifaa chako cha Android TV, ikiwa ni pamoja na mara ambazo umepiga simu, umetuma barua pepe au kuwasiliana kwa njia nyingine na anwani mahususi. Idhini hii huruhusu programu ifute data ya anwani."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Huruhusu programu kurekebisha data kuhusu anwani ulizohifadhi kwenye simu yako, ikiwa ni pamoja na mara ambazo umepiga simu, kutuma barua pepe au kuwasiliana kwa njia nyingine na anwani maalum. Idhini hii inaruhusu programu kufuta data ya anwani."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Huruhusu programu kubadilisha data kuhusu anwani zako zilizohifadhiwa kwenye kompyuta yako kibao. Idhini hii huruhusu programu kufuta data ya anwani."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Huruhusu programu kubadilisha data kuhusu anwani zako zilizohifadhiwa kwenye kifaa chako cha Android TV. Idhini hii huruhusu programu kufuta data ya anwani."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Huruhusu programu kurekebisha data kuhusu anwani zako zilizohifadhiwa kwenye simu yako. Idhini hii huruhusu programu kufuta data ya anwani."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"kusoma rekodi ya simu"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Programu hii inaweza kusoma rekodi yako ya simu zilizopigwa."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"kuandika rekodi ya simu"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"fikia amri za ziada za mtoa huduma ya mahali"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Ruhusu programu kufikia amri za ziada za mtoa huduma za mahali. Hii huenda ikaruhusu programu ikatize matumizi ya GPS au vyanzo vingine vya eneo."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"kufikia mahali mahususi ikiwa tu programu imefunguliwa kwenye skrini"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Programu hii inaweza kupata mahali halisi ikiwa tu umeifungua kwenye skrini. Ni lazima uwashe huduma hizi za mahali na zipatikane kwenye simu yako ili programu iweze kuzitumia. Hatua hii inaweza kuongeza utumiaji wa betri."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"fikia eneo linalokadiriwa (kulingana na mtandao) wakati tu programu inatumika kwenye skrini"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Programu hii inaweza kupata eneo lako kulingana na vyanzo vya mtandao kama vile minara ya simu na mitandao ya Wi-Fi, lakini hili hufanyika tu wakati programu inatumika kwenye skrini. Ni lazima uwashe huduma hizi za mahali na zipatikane kwenye simu kibao yako ili programu iweze kuzitumia."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Programu hii inaweza kupata maelezo ya mahali ulipo kulingana na vyanzo vya mtandao kama vile minara ya simu na mitandao ya Wi-Fi, lakini hili hufanyika tu wakati programu inatumika. Ni lazima huduma hizi za mahali ziwashwe na kupatikana kwenye kifaa chako cha Android TV ili programu iweze kuzitumia."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Programu hii inaweza kupata eneo lako kulingana na vyanzo vya mtandao kama vile minara ya simu na mitandao ya Wi-Fi, lakini hili hufanyika tu wakati programu inatumika kwenye skrini. Ni lazima uwashe huduma hizi za mahali na zipatikane kwenye simu yako ili programu iweze kuzitumia."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Programu hii inaweza kupata mahali halisi ikiwa tu umeifungua kwenye skrini. Ni lazima uwashe huduma za mahali na zipatikane kwenye kifaa chako ili programu iweze kuzitumia. Hatua hii inaweza kuongeza matumizi ya betri."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"kufikia mahali palipokadiriwa ikiwa tu programu imefunguliwa kwenye skrini"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Programu hii inaweza kukadiria mahali ulipo ikiwa tu umeifungua kwenye skrini. Ni lazima huduma za mahali ziwashwe na zipatikane kwenye kifaa chako ili programu iweze kuzitumia."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"ifikie mahali inapotumika chinichini"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Kama ruhusa hii itatolewa, mbali na idhini ya kufikia mahali panapokadiriwa au mahali mahususi, programu inaweza kufikia mahali wakati inatumika chinichini."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Programu hii inaweza kufikia maelezo ya mahali inapotumika chinichini, pamoja na ufikiaji wa mahali wakati umeifungua kwenye skrini."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"badilisha mipangilio yako ya sauti"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Inaruhusu programu kurekebisha mipangilio ya sauti kila mahali kama vile sauti na ni kipaza sauti kipi ambacho kinatumika kwa kutoa."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"kurekodi sauti"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Huruhusu programu kuona usanidi wa Bluetooth kwenye kompyuta kibao, na kutuma na kukubali miunganisho kwa vifaa vilivyooanishwa."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Huruhusu programu iangalie mipangilio iliyowekwa ya Bluetooth kwenye kifaa chako cha Android TV na kufanya na kukubali miunganisho na vifaa vilivyooanishwa."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Huruhusu programu kuona usanidi wa Bluetooth kwenye simu, na kutuma na kukubali miunganisho kwa vifaa vilivyooanishwa."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Maelezo ya Huduma Inayopendelewa ya Malipo ya NFC"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Huruhusu programu kupata maelezo ya huduma inayopendelewa ya malipo ya nfc kama vile huduma zilizosajiliwa na njia."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"kudhibiti Mawasiliano ya Vifaa Vilivyokaribu (NFC)"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Inaruhusu programu kuwasiliana na lebo, kadi na wasomaji wa Near Field Communication (NFC)."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"zima kufuli la skrini yako"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"Njia ya mkato ya ufikivu imewasha <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"Njia ya mkato ya ufikivu imezima <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Bonyeza na ushikilie vitufe vyote viwili vya sauti kwa sekunde tatu ili utumie <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Chagua huduma ya kutumia unapogusa kitufe cha ufikivu:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Chagua huduma ya kutumia pamoja na ishara ya ufikivu (telezesha vidole viwili kutoka chini kwenda juu kwenye skrini):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Chagua huduma ya kutumia pamoja na ishara ya ufikivu (telezesha kutoka chini kwenda juu kwenye skrini kwa vidole vitatu):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Ili ubadilishe kati ya huduma, gusa na ushikilie kitufe cha ufikivu."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Ili ubadilishe kati ya huduma, telezesha vidole viwili juu na ushikilie."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Ili ubadilishe kati ya huduma, telezesha vidole vitatu juu na ushikilie."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Ukuzaji"</string>
<string name="user_switched" msgid="7249833311585228097">"Mtumiaji wa sasa <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="1912993630661332336">"Inabadili kwenda <xliff:g id="NAME">%1$s</xliff:g>…"</string>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Imeunganishwa na <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Gusa ili uangalie faili"</string>
<string name="pin_target" msgid="8036028973110156895">"Bandika"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Bandika <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Bandua"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Bandua <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Maelezo ya programu"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Inaanzisha onyesho..."</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Ungependa kusasisha vipengee hivi katika "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> na <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Hifadhi"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Hapana, asante"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Si sasa"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Kamwe"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Sasisha"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Endelea"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"nenosiri"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Geuza Skrini Iliyogawanywa"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Skrini Iliyofungwa"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Picha ya skrini"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"Programu ya <xliff:g id="APP_NAME">%1$s</xliff:g> katika dirisha Ibukizi."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Upau wa manukuu wa <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index ac284d35607f..08b32b95040f 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"பணிக் கணக்கு நிர்வாகி ஆப்ஸ் இல்லை அல்லது அது சிதைந்துள்ளது. இதன் விளைவாக, உங்கள் பணிக் கணக்குமும் அதனுடன் தொடர்புடைய தரவும் நீக்கப்பட்டன. உதவிக்கு, நிர்வாகியைத் தொடர்புகொள்ளவும்."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"இந்தச் சாதனத்தில் இனி பணிக் கணக்கு கிடைக்காது"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"கடவுச்சொல்லை அதிக முறை தவறாக முயற்சித்துவிட்டீர்கள்"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"நிர்வாகியால் தனிப்பட்ட உபயோகத்திற்காக ஒதுக்கப்பட்ட சாதனம்"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"சாதனம் நிர்வகிக்கப்படுகிறது"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"உங்கள் நிறுவனம் இந்தச் சாதனத்தை நிர்வகிக்கும், அத்துடன் அது நெட்வொர்க் ட்ராஃபிக்கைக் கண்காணிக்கலாம். விவரங்களுக்கு, தட்டவும்."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"சாதனத் தரவு அழிக்கப்படும்"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"வலைபரப்பு முடிந்த பின்னரும் தங்கிவிடும் ஸ்டிக்கி வலைபரப்புகளை அனுப்ப ஆப்ஸை அனுமதிக்கும். அளவுக்கதிகமான உபயோகம் Android TVயின் வேகத்தைக் குறைக்கவோ நிலையற்றதாகவோ ஆக்கக்கூடும். இதனால் அதிகமான நினைவகம் பயன்படுத்தப்படும்."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"அலைபரப்பு முடிந்த பின்னும் இருக்கும், தொடர்ந்து அணுகத்தக்க அலைபரப்பை அனுப்பப் ஆப்ஸை அனுமதிக்கிறது. அதிகமாகப் பயன்படுத்தினால், மொபைலானது நினைவகத்தை மிக அதிகமாகப் பயன்படுத்துவதால் வேகம் குறைந்ததாகவும், நிலையற்றதாகவும் ஆகலாம்."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"உங்கள் தொடர்புகளைப் படித்தல்"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"குறிப்பிட்டவர்களுடன் நீங்கள் அழைத்த, மின்னஞ்சல் அனுப்பிய அல்லது வேறு வழியில் தொடர்புகொண்டதின் எண்ணிக்கை உட்பட, உங்கள் டேப்லெட்டில் சேமிக்கப்பட்ட உங்கள் தொடர்புகள் குறித்த தரவைப் படிக்க ஆப்ஸை அனுமதிக்கிறது. இந்த அனுமதி, உங்கள் தொடர்பு தரவைச் சேமிக்க ஆப்ஸை அனுமதிக்கிறது, மேலும் தீங்கிழைக்கும் ஆப்ஸ் உங்களுக்குத் தெரியாமல் தொடர்பு தரவைப் பகிரலாம்."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"உங்கள் Android TVயில் சேமித்துள்ள தொடர்புகள் பற்றிய தரவைத் தெரிந்துகொள்ள ஆப்ஸை அனுமதிக்கும். குறிப்பிட்ட தனிநபரை எத்தனை முறை அழைத்தீர்கள், பிறவழிகளில் தொடர்புகொண்டீர்கள் அல்லது அவருக்கு எத்தனை முறை மின்னஞ்சல் அனுப்பினீர்கள் என்பதும் இதில் அடங்கும். இது உங்கள் தொடர்புத் தரவைச் சேமிக்க ஆப்ஸை அனுமதிக்கும், அத்துடன் தீங்குவிளைவிக்கும் ஆப்ஸ் உங்களுக்குத் தெரியாமல் தொடர்புத் தரவைப் பகிரக்கூடும்."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"குறிப்பிட்டவர்களுடன் நீங்கள் அழைத்த, மின்னஞ்சல் அனுப்பிய அல்லது வேறு வழியில் தொடர்புகொண்ட எண்ணிக்கை உட்பட, உங்கள் மொபைலில் சேமிக்கப்பட்ட உங்கள் தொடர்புகள் குறித்த தரவைப் படிக்க ஆப்ஸை அனுமதிக்கிறது. இந்த அனுமதி, உங்கள் தொடர்பு தரவைச் சேமிக்க ஆப்ஸை அனுமதிக்கிறது, மேலும் தீங்கிழைக்கும் ஆப்ஸ் உங்களுக்குத் தெரியாமல் தொடர்பு தரவைப் பகிரலாம்."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"உங்கள் டேப்லெட்டில் சேமித்துள்ள தொடர்புகள் பற்றிய தரவை அணுக ஆப்ஸை அனுமதிக்கும். உங்கள் டேப்லெட்டில் உள்ள தொடர்புகளை உருவாக்கிய கணக்குகளுக்கான அணுகலும் ஆப்ஸிற்கு இருக்கும். நீங்கள் நிறுவிய ஆப்ஸ் மூலம் உருவாக்கப்பட்ட அனைத்துக் கணக்குகளும் இதில் உள்ளடங்கக்கூடும். இந்த அனுமதி உங்கள் தொடர்புத் தரவைச் சேமிக்க ஆப்ஸை அனுமதிக்கிறது, மேலும் தீங்கிழைக்கும் ஆப்ஸ் உங்களுக்குத் தெரியாமல் தொடர்பு தரவைப் பகிரக்கூடும்."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"உங்கள் Android TVயில் சேமித்துள்ள தொடர்புகள் பற்றிய தரவை அணுக ஆப்ஸை அனுமதிக்கும். உங்கள் Android TVயில் உள்ள தொடர்புகளை உருவாக்கிய கணக்குகளுக்கான அணுகலும் ஆப்ஸிற்கு இருக்கும். நீங்கள் நிறுவிய ஆப்ஸ் மூலம் உருவாக்கப்பட்ட அனைத்துக் கணக்குகளும் இதில் உள்ளடங்கக்கூடும். இந்த அனுமதி உங்கள் தொடர்புத் தரவைச் சேமிக்க ஆப்ஸை அனுமதிக்கிறது, மேலும் தீங்கிழைக்கும் ஆப்ஸ் உங்களுக்குத் தெரியாமல் தொடர்பு தரவைப் பகிரக்கூடும்."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"உங்கள் மொபைலில் சேமித்துள்ள தொடர்புகள் பற்றிய தரவை அணுக ஆப்ஸை அனுமதிக்கும். உங்கள் மொபைலில் உள்ள தொடர்புகளை உருவாக்கிய கணக்குகளுக்கான அணுகலும் ஆப்ஸிற்கு இருக்கும். நீங்கள் நிறுவிய ஆப்ஸ் மூலம் உருவாக்கப்பட்ட அனைத்துக் கணக்குகளும் இதில் உள்ளடங்கக்கூடும். இந்த அனுமதி உங்கள் தொடர்புத் தரவைச் சேமிக்க ஆப்ஸை அனுமதிக்கிறது, மேலும் தீங்கிழைக்கும் ஆப்ஸ் உங்களுக்குத் தெரியாமல் தொடர்பு தரவைப் பகிரக்கூடும்."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"உங்கள் தொடர்புகளை மாற்றுதல்"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"குறிப்பிட்ட தொடர்புகளுடன் நீங்கள் அழைத்த, மின்னஞ்சல் அனுப்பிய அல்லது வேறு வழியில் தொடர்புகொண்டதின் எண்ணிக்கை உள்பட, உங்கள் டேப்லெட்டில் சேமிக்கப்பட்ட உங்கள் தொடர்புகள் குறித்த தரவைத் திருத்த ஆப்ஸை அனுமதிக்கிறது. இந்த அனுமதியானது தொடர்புத் தரவை நீக்க ஆப்ஸை அனுமதிக்கிறது."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"உங்கள் Android TVயில் சேமித்துள்ள தொடர்புகள் பற்றிய தரவை மாற்ற ஆப்ஸை அனுமதிக்கும். குறிப்பிட்ட தொடர்பை எத்தனை முறை அழைத்தீர்கள், பிறவழிகளில் தொடர்புகொண்டீர்கள் அல்லது அவருக்கு எத்தனை முறை மின்னஞ்சல் அனுப்பினீர்கள் என்பதும் இதில் அடங்கும். தொடர்புத் தரவை நீக்க ஆப்ஸை இது அனுமதிக்கும்."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"குறிப்பிட்ட தொடர்புகளுடன் நீங்கள் அழைத்த, மின்னஞ்சல் அனுப்பிய அல்லது வேறு வழியில் தொடர்புகொண்டதின் எண்ணிக்கை உள்பட, உங்கள் மொபைலில் சேமிக்கப்பட்ட உங்கள் தொடர்புகள் குறித்த தரவைத் திருத்த ஆப்ஸை அனுமதிக்கிறது. இந்த அனுமதியானது தொடர்புத் தரவை நீக்க ஆப்ஸை அனுமதிக்கிறது."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"உங்கள் டேப்லெட்டில் சேமித்துள்ள தொடர்புகள் பற்றிய தரவை மாற்ற ஆப்ஸை அனுமதிக்கும். இது தொடர்புத் தரவை நீக்கவும் ஆப்ஸை அனுமதிக்கும்."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"உங்கள் Android TVயில் சேமித்துள்ள தொடர்புகள் பற்றிய தரவை மாற்ற ஆப்ஸை அனுமதிக்கும். இது தொடர்புத் தரவை நீக்கவும் ஆப்ஸை அனுமதிக்கும்."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"உங்கள் மொபைலில் சேமித்துள்ள தொடர்புகள் பற்றிய தரவை மாற்ற ஆப்ஸை அனுமதிக்கும். இது தொடர்புத் தரவை நீக்கவும் ஆப்ஸை அனுமதிக்கும்."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"அழைப்புப் பதிவைப் படித்தல்"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"இந்த ஆப்ஸ் உங்கள் அழைப்பு வரலாற்றைப் படிக்கலாம்."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"அழைப்புப் பதிவை எழுதுதல்"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"கூடுதல் இட வழங்குநரின் கட்டளைகளின் அணுகல்"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"கூடுதல் இட வழங்குநர் கட்டளைகளை அணுகப் ஆப்ஸை அனுமதிக்கிறது. இது, GPS அல்லது பிற இருப்பிட மூலங்களின் செயல்பாட்டை இடைமறிக்க ஆப்ஸை அனுமதிக்கலாம்."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"முன்புலத்தில் இயங்கும்போது மட்டும் துல்லியமான இருப்பிடத்தைக் கண்டறிதல்"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"இந்த ஆப்ஸ் முன்புலத்தில் இயங்கும்போது மட்டுமே நீங்கள் இருக்கும் இடத்தைத் துல்லியமாகக் கண்டறியும். உங்கள் மொபைலில், இருப்பிடச் சேவைகளை ஆப்ஸ் பயன்படுத்துவதற்கு வசதியாக, அவை ஆன் செய்யப்பட்டிருக்க வேண்டும். இதனால் பேட்டரி அதிகம் பயன்படுத்தப்படலாம்."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"முன்புலத்தில் இயங்கும்போது மட்டும் தோராயமான இருப்பிடத்தைக் கண்டறிதல் (நெட்வொர்க் அடிப்படையில்)"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"ஆப்ஸ் முன்புலத்தில் இயங்கும்போது மட்டுமே மொபைல் டவர்கள், வைஃபை நெட்வொர்க்குகள் போன்ற நெட்வொர்க் மூலங்கள் மூலம் ஆப்ஸால் உங்கள் இருப்பிடத்தைப் பெற முடியும். உங்கள் டேப்லெட்டில் \'இருப்பிடச் சேவைகளை\' ஆப்ஸ் பயன்படுத்துவதற்கு வசதியாக அவை ஆன் செய்யப்பட்டிருக்க வேண்டும்."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"மொபைல் டவர்கள், வைஃபை நெட்வொர்க்குகள் போன்ற நெட்வொர்க் ஆதாரங்களின் உதவியுடன் ஆப்ஸால் உங்கள் இருப்பிடத்தைப் பெற முடியும். அதற்கு ஆப்ஸ் முன்புலத்தில் இயங்க வேண்டும். இதனை ஆப்ஸ் பயன்படுத்துவதற்கேற்ப உங்கள் Android TVயில் இந்த இருப்பிடச் சேவைகள் இயக்கப்பட்டு கிடைக்கும்படி இருக்க வேண்டும்."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"ஆப்ஸ் முன்புலத்தில் இயங்கும்போது மட்டுமே மொபைல் டவர்கள், வைஃபை நெட்வொர்க்குகள் போன்ற நெட்வொர்க் மூலங்கள் மூலம் ஆப்ஸால் உங்கள் இருப்பிடத்தைப் பெற முடியும். உங்கள் மொபைலில் \'இருப்பிடச் சேவைகளை\' ஆப்ஸ் பயன்படுத்துவதற்கு வசதியாக அவை ஆன் செய்யப்பட்டிருக்க வேண்டும்."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"இந்த ஆப்ஸ் முன்புலத்தில் இயங்கும்போது மட்டுமே நீங்கள் இருக்கும் இடத்தைத் துல்லியமாகக் கண்டறியும். உங்கள் சாதனத்தில், இருப்பிடச் சேவைகளை ஆப்ஸ் பயன்படுத்துவதற்கு வசதியாக, அவை ஆன் செய்யப்பட்டிருக்க வேண்டும். இதனால் பேட்டரி அதிகம் பயன்படுத்தப்படக்கூடும்."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"முன்புலத்தில் இயங்கும்போது மட்டும் தோராயமான இருப்பிடத்தைக் கண்டறிதல்"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"முன்புலத்தில் இருக்கும்போது மட்டுமே இந்த ஆப்ஸால் தோராயமான இடத்தைக் கண்டறிய முடியும். இருப்பிட சேவைகள் ஆன் செய்யப்பட்டு சாதனத்தில் இருக்க வேண்டும், அப்போதுதான் அவற்றை ஆப்ஸால் பயன்படுத்த முடியும்."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"பின்புலத்தில் இருப்பிடத்தை அணுகுதல்"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"தோராயமான அல்லது துல்லியமான \'இருப்பிட அணுகலுடன்\' சேர்ந்து இதற்கும் அனுமதி வழங்கப்பட்டால், ஆப்ஸ் பின்புலத்தில் இயங்கினாலும் இருப்பிடத்தை அணுக இயலும்."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"முன்புல இருப்பிட அணுகலுடன் பின்புலத்தில் இயங்கும்போதும் இந்த ஆப்ஸால் இருப்பிடத்தை அணுக முடியும்."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"எனது ஆடியோ அமைப்புகளை மாற்றுதல்"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"ஒலியளவு மற்றும் வெளியீட்டிற்கு ஸ்பீக்கர்கள் பயன்படுத்தப்படுவது போன்ற ஒட்டுமொத்த ஆடியோ அமைப்புகளைக் கட்டுப்படுத்தப் ஆப்ஸை அனுமதிக்கிறது."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"ஆடியோவைப் பதிவுசெய்தல்"</string>
@@ -494,6 +491,8 @@
<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_preferredPaymentInfo" msgid="5274423844767445054">"விருப்பமான NFC பேமெண்ட் சேவை தொடர்பான தகவல்கள்"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"பதிவுசெய்யப்பட்ட கருவிகள், சேருமிடத்திற்கான வழி போன்ற விருப்பமான NFC பேமெண்ட் சேவை தொடர்பான தகவல்களைப் பெற ஆப்ஸை அனுமதிக்கிறது."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"குறுகிய இடைவெளி தகவல்பரிமாற்றத்தைக் கட்டுப்படுத்துதல்"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"குறுகிய இடைவெளி தகவல்பரிமாற்றம் (NFC), குறிகள், கார்டுகள் மற்றும் ரீடர்கள் ஆகியவற்றுடன் தொடர்புகொள்ள, ஆப்ஸை அனுமதிக்கிறது."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"உங்கள் திரைப் பூட்டை முடக்குதல்"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"அணுகல்தன்மை ஷார்ட்கட்டானது <xliff:g id="SERVICE_NAME">%1$s</xliff:g>ஐ இயக்கியது"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"அணுகல்தன்மை ஷார்ட்கட்டானது <xliff:g id="SERVICE_NAME">%1$s</xliff:g>ஐ முடக்கியது"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>ஐப் பயன்படுத்த 3 விநாடிகளுக்கு இரண்டு ஒலியளவு பட்டன்களையும் அழுத்திப் பிடிக்கவும்"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"அணுகல்தன்மை பட்டனுக்கான சேவையைத் தேர்வுசெய்யவும்:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"அணுகல்தன்மை சைகைக்கான சேவையைத் தேர்வுசெய்யவும் (இரண்டு விரல்களால் திரையின் கீழிருந்து மேல் நோக்கி ஸ்வைப் செய்யவும்):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"அணுகல்தன்மை சைகைக்கான சேவையைத் தேர்வுசெய்யவும் (மூன்று விரல்களால் திரையின் கீழிருந்து மேல் நோக்கி ஸ்வைப் செய்யவும்):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"சேவைகளுக்கு இடையே மாற அணுகல்தன்மை பட்டனைத் தொட்டுப் பிடிக்கவும்."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"சேவைகளுக்கு இடையே மாற இரண்டு விரல்களால் மேல்நோக்கி ஸ்வைப் செய்து பிடிக்கவும்."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"சேவைகளுக்கு இடையே மாற மூன்று விரல்களால் மேல்நோக்கி ஸ்வைப் செய்து பிடிக்கவும்."</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>
@@ -1862,7 +1855,11 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> உடன் இணைக்கப்பட்டது"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"கோப்புகளைப் பார்க்க, தட்டவும்"</string>
<string name="pin_target" msgid="8036028973110156895">"பின் செய்"</string>
+ <!-- no translation found for pin_specific_target (7824671240625957415) -->
+ <skip />
<string name="unpin_target" msgid="3963318576590204447">"பின்னை அகற்று"</string>
+ <!-- no translation found for unpin_specific_target (3859828252160908146) -->
+ <skip />
<string name="app_info" msgid="6113278084877079851">"ஆப்ஸ் தகவல்"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"டெமோவைத் தொடங்குகிறது…"</string>
@@ -1905,6 +1902,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291"><b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" இல் <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>ஐ மாற்றவா?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"சேமி"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"வேண்டாம்"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"இப்போது வேண்டாம்"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"ஒருபோதும் வேண்டாம்"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"புதுப்பி"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"தொடர்க"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"கடவுச்சொல்"</string>
@@ -2000,5 +1999,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"திரைப் பிரிப்பை நிலைமாற்று"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"பூட்டுத் திரை"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"ஸ்கிரீன்ஷாட்"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸில் உள்ள பாப் அப் சாளரம்."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸின் தலைப்புப் பட்டி."</string>
</resources>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index 6641c413d36b..e1b88acf665f 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"కార్యాలయ ప్రొఫైల్ నిర్వాహక యాప్ లేదు లేదా పాడైంది. తత్ఫలితంగా, మీ కార్యాలయ ప్రొఫైల్ మరియు సంబంధిత డేటా తొలగించబడ్డాయి. సహాయం కోసం మీ నిర్వాహకులను సంప్రదించండి."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"ఈ పరికరంలో మీ కార్యాలయ ప్రొఫైల్ ఇప్పుడు అందుబాటులో లేదు"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"చాలా ఎక్కువ పాస్‌వర్డ్ ప్రయత్నాలు చేసారు"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"వ్యక్తిగత వినియోగం కోసం నిర్వాహకులు పరికరాన్ని తీసి వేశారు"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"పరికరం నిర్వహించబడింది"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"మీ సంస్థ ఈ పరికరాన్ని నిర్వహిస్తుంది మరియు నెట్‌వర్క్ ట్రాఫిక్‌ని పర్యవేక్షించవచ్చు. వివరాల కోసం నొక్కండి."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"మీ పరికరంలోని డేటా తొలగించబడుతుంది"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"ప్రసారం ముగిసిన తర్వాత భద్రపరచబడే ప్రసారాలను పంపడానికి యాప్‌ని అనుమతిస్తుంది. ఎక్కువగా వినియోగిస్తే అధిక పరిమాణంలో మెమరీని ఉపయోగించడం వలన టీవీ నెమ్మదిగా పని చేయవచ్చు లేదా అస్థిరంగా మారవచ్చు."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"ప్రసారం ముగిసిన తర్వాత భద్రపరచబడే ప్రసారాలను పంపడానికి యాప్‌ను అనుమతిస్తుంది. అత్యధిక వినియోగం వలన ఫోన్ నెమ్మదిగా పని చేయవచ్చు లేదా అధిక పరిమాణంలో మెమరీని ఉపయోగించడం వలన అస్థిరంగా మారవచ్చు."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"మీ పరిచయాలను చదవడం"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"మీరు నిర్దిష్ట వ్యక్తులకు కాల్ చేసిన, ఇమెయిల్ చేసిన లేదా ఇతర మార్గాల్లో కమ్యూనికేట్ చేసిన తరచుదనంతో సహా మీ టాబ్లెట్‌లో నిల్వ చేయబడిన మీ పరిచయాల గురించి డేటాను చదవడానికి యాప్‌ను అనుమతిస్తుంది. ఈ అనుమతి మీ పరిచయ డేటాను సేవ్ చేయడానికి యాప్‌లను అనుమతిస్తుంది మరియు హానికరమైన యాప్‌లు మీకు తెలియకుండానే పరిచయ డేటాను షేర్ చేయవచ్చు."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"మీరు నిర్దిష్ట వ్యక్తులకు కాల్ చేసిన, ఇమెయిల్ చేసిన లేదా ఇతర మార్గాల్లో కమ్యూనికేట్ చేసిన ఫ్రీక్వెన్సీతో సహా మీ Android TV పరికరంలో నిల్వ చేసిన మీ పరిచయాలకు సంబంధించిన డేటాను చదవడానికి యాప్‌ని అనుమతిస్తుంది. ఈ అనుమతి మీ పరిచయ డేటాను సేవ్ చేయడానికి యాప్‌లను అనుమతిస్తుంది మరియు హానికరమైన యాప్‌లు మీకు తెలియకుండానే పరిచయ డేటాను షేర్ చేయవచ్చు."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"మీరు నిర్దిష్ట వ్యక్తులకు కాల్ చేసిన, ఇమెయిల్ చేసిన లేదా ఇతర మార్గాల్లో కమ్యూనికేట్ చేసిన తరచుదనంతో సహా మీ ఫోన్‌లో నిల్వ చేయబడిన మీ పరిచయాల గురించి డేటాను చదవడానికి యాప్‌ను అనుమతిస్తుంది. ఈ అనుమతి మీ పరిచయ డేటాను సేవ్ చేయడానికి యాప్‌లను అనుమతిస్తుంది మరియు హానికరమైన యాప్‌లు మీకు తెలియకుండానే పరిచయ డేటాను షేర్ చేయవచ్చు."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"టాబ్లెట్‌లో నిల్వ చేసిన మీ కాంటాక్ట్‌లకు సంబంధించిన డేటాను చదవడానికి యాప్‌ను అనుమతిస్తుంది. కాంటాక్ట్‌లను సృష్టించిన మీ టాబ్లెట్‌లోని ఖాతాలకు కూడా యాప్‌లకు యాక్సెస్ ఉంటుంది. ఇందులో మీరు ఇన్‌స్టాల్ చేసిన యాప్‌ల ద్వారా సృష్టించబడిన ఖాతాలు ఉండవచ్చు. ఈ అనుమతి, మీ కాంటాక్ట్ డేటాను సేవ్ చేయడానికి యాప్‌లను అనుమతిస్తుంది, హానికరమైన యాప్‌లు మీకు తెలియకుండానే కాంటాక్ట్ డేటాను షేర్ చేయవచ్చు."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"మీ Android TV పరికరంలో నిల్వ చేసిన కాంటాక్ట్‌లకు సంబంధించిన డేటాను చదవడానికి యాప్‌ను అనుమతిస్తుంది. కాంటాక్ట్‌లను సృష్టించిన మీ Android TV పరికరంలోని ఖాతాలకు కూడా యాప్‌లకు యాక్సెస్ ఉంటుంది. ఇందులో మీరు ఇన్‌స్టాల్ చేసిన యాప్‌ల ద్వారా సృష్టించబడిన ఖాతాలు ఉండవచ్చు. ఈ అనుమతి, మీ కాంటాక్ట్ డేటాను సేవ్ చేయడానికి యాప్‌లను అనుమతిస్తుంది, హానికరమైన యాప్‌లు మీకు తెలియకుండానే కాంటాక్ట్ డేటాను షేర్ చేయవచ్చు."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"ఫోన్‌లో నిల్వ చేసిన మీ కాంటాక్ట్‌లకు సంబంధించిన డేటాను చదవడానికి యాప్‌ను అనుమతిస్తుంది. కాంటాక్ట్‌లను సృష్టించిన మీ ఫోన్‌లోని ఖాతాలను కూడా యాప్‌లు యాక్సెస్ చేయగలవు. ఇందులో మీరు ఇన్‌స్టాల్ చేసిన యాప్‌ల ద్వారా సృష్టించబడిన ఖాతాలు ఉండవచ్చు. ఈ అనుమతి, మీ కాంటాక్ట్ డేటాను సేవ్ చేయడానికి యాప్‌లను అనుమతిస్తుంది, హానికరమైన యాప్‌లు మీకు తెలియకుండానే కాంటాక్ట్ డేటాను షేర్ చేయవచ్చు."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"మీ పరిచయాలను సవరించడం"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"మీరు నిర్దిష్ట పరిచయాలకు కాల్ చేసిన, ఇమెయిల్ చేసిన లేదా ఇతర మార్గాల్లో కమ్యూనికేట్ చేసిన తరచుదనంతో సహా మీ టాబ్లెట్‌లో నిల్వ చేయబడిన మీ పరిచయాల గురించి డేటాను సవరించడానికి యాప్‌ను అనుమతిస్తుంది. ఈ అనుమతి పరిచయ డేటాను తొలగించడానికి యాప్‌లను అనుమతిస్తుంది."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"మీరు నిర్దిష్ట పరిచయాలకు కాల్ చేసిన, ఇమెయిల్ చేసిన లేదా ఇతర మార్గాల్లో కమ్యూనికేట్ చేసిన ఫ్రీక్వెన్సీతో సహా మీ Android TV పరికరంలో నిల్వ చేసిన మీ పరిచయాలకు సంబంధించిన డేటాను సవరించడానికి యాప్‌ని అనుమతిస్తుంది. ఈ అనుమతి పరిచయ డేటాను తొలగించడానికి యాప్‌లను అనుమతిస్తుంది."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"మీరు నిర్దిష్ట పరిచయాలకు కాల్ చేసిన, ఇమెయిల్ చేసిన లేదా ఇతర మార్గాల్లో కమ్యూనికేట్ చేసిన తరచుదనంతో సహా మీ ఫోన్‌లో నిల్వ చేయబడిన మీ పరిచయాల గురించి డేటాను సవరించడానికి యాప్‌ను అనుమతిస్తుంది. ఈ అనుమతి పరిచయ డేటాను తొలగించడానికి యాప్‌లను అనుమతిస్తుంది."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"మీ టాబ్లెట్‌లో నిల్వ చేసి ఉన్న కాంటాక్ట్‌లకు సంబంధించిన డేటాను సవరించడానికి యాప్‌ను అనుమతిస్తుంది. ఈ అనుమతి, కాంటాక్ట్ డేటాను తొలగించడానికి యాప్‌లను అనుమతిస్తుంది."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"మీ Android TV పరికరంలో నిల్వ చేసి ఉన్న కాంటాక్ట్‌లకు సంబంధించిన డేటాను సవరించడానికి యాప్‌ను అనుమతిస్తుంది. ఈ అనుమతి, కాంటాక్ట్ డేటాను తొలగించడానికి యాప్‌లను అనుమతిస్తుంది."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"మీ ఫోన్‌లో నిల్వ చేసి ఉన్న కాంటాక్ట్‌లకు సంబంధించిన డేటాను సవరించడానికి యాప్‌ను అనుమతిస్తుంది. ఈ అనుమతి, కాంటాక్ట్ డేటాను తొలగించడానికి యాప్‌లను అనుమతిస్తుంది."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"కాల్ లాగ్‌ను చదవడం"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"ఈ యాప్‌ మీ కాల్ చరిత్రను చదవగలదు."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"కాల్ లాగ్‌ను వ్రాయడం"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"అదనపు స్థాన ప్రదాత ఆదేశాలను యాక్సెస్ చేయడం"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"అదనపు స్థాన ప్రదాత ఆదేశాలను యాక్సెస్ చేయడానికి యాప్‌ను అనుమతిస్తుంది. ఇది GPS లేదా ఇతర స్థాన మూలాల నిర్వహణలో యాప్‌ ప్రమేయం ఉండేలా అనుమతించవచ్చు."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"స్క్రీన్‌పై ఉన్నప్పుడు మాత్రమే ఖచ్చితమైన స్థానాన్ని యాక్సెస్ చేయండి"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"ఈ యాప్ స్క్రీన్‌పై ఉన్నప్పుడు మాత్రమే అది మీ ఖచ్చితమైన స్థానాన్ని తెలుసుకోగలదు. యాప్‌ ఉపయోగించడానికి మీ ఫోన్‌లో ఈ స్థాన సేవలను తప్పనిసరిగా ఆన్ చేయాలి మరియు అందుబాటులో ఉండాలి. ఇది బ్యాటరీ వినియోగాన్ని పెంచవచ్చు."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"స్క్రీన్‌పై ఉన్నప్పుడు మాత్రమే సమీప స్థానాన్ని (నెట్‌వర్క్-ఆధారిత) యాక్సెస్ చేయండి"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"ఈ యాప్‌ సెల్ టవర్‌లు మరియు Wi-Fi నెట్‌వర్క్‌ల వంటి నెట్‌వర్క్ మూలాధారాల ఆధారంగా మీ స్థానాన్ని తెలుసుకోగలదు, కానీ యాప్ తెరపై ఉన్నప్పుడు మాత్రమే. యాప్‌ ఉపయోగించడానికి మీ టాబ్లెట్‌లో ఈ స్థాన సేవలను తప్పనిసరిగా ఆన్ చేయాలి మరియు అందుబాటులో ఉండాలి."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"ఈ యాప్‌ సెల్ టవర్‌లు మరియు Wi-Fi నెట్‌వర్క్‌ల వంటి నెట్‌వర్క్ మూలాధారాల ఆధారంగా మీ స్థానాన్ని తెలుసుకోగలదు, కానీ యాప్ తెరపై ఉన్నప్పుడు మాత్రమే. యాప్‌ ఉపయోగించడానికి మీ Android TV పరికరంలో ఈ స్థాన సేవలను తప్పనిసరిగా ఆన్ చేయాలి మరియు అవి అందుబాటులో ఉండాలి."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"ఈ యాప్‌ సెల్ టవర్‌లు మరియు Wi-Fi నెట్‌వర్క్‌ల వంటి నెట్‌వర్క్ మూలాధారాల ఆధారంగా మీ స్థానాన్ని తెలుసుకోగలదు, కానీ యాప్ తెరపై ఉన్నప్పుడు మాత్రమే. యాప్‌ ఉపయోగించడానికి మీ ఫోన్‌లో ఈ స్థాన సేవలను తప్పనిసరిగా ఆన్ చేయాలి మరియు అందుబాటులో ఉండాలి."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"ఈ యాప్ స్క్రీన్‌పై ఉన్నప్పుడు మాత్రమే మీ ఖచ్చితమైన లొకేషన్‌ను తెలుసుకోగలదు. మీ పరికరంలో లొకేషన్ సర్వీస్‌లు అందుబాటులో ఉండి, అవి తప్పనిసరిగా ఆన్ చేసి ఉంటేనే, యాప్ వాటిని ఉపయోగించగలదు. దీని వలన బ్యాటరీ వినియోగం పెరగవచ్చు."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"స్క్రీన్‌పై ఉన్నప్పుడు మాత్రమే సుమారు లొకేషన్‌ను యాక్సెస్ చేయండి"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"ఈ యాప్ స్క్రీన్‌పై ఉన్నప్పుడు మాత్రమే మీ సుమారు లొకేషన్‌ను తెలుసుకోగలదు. మీ పరికరంలో లొకేషన్ సర్వీస్‌లు అందుబాటులో ఉండి, అవి తప్పనిసరిగా ఆన్ చేసి ఉంటేనే, యాప్ వాటిని ఉపయోగించగలదు."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"నేపథ్యంలో స్థానాన్ని యాక్సెస్ చేయి"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"సుమారుగా లేదా ఖచ్చితమైన స్థాన యాక్సెస్‌తో పాటు అదనందా ఇది మంజూరు చేయబడితే, యాప్ నేపథ్యంలో నడుస్తున్నప్పుడు స్థానాన్ని యాక్సెస్ చేయగలదు."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"స్క్రీన్‌పై ఉన్నప్పుడు లొకేషన్‌ను యాక్సెస్ చేయడంతో పాటు ఈ యాప్ బ్యాక్‌గ్రౌండ్‌లో నడుస్తున్నప్పుడు కూడా లొకేషన్‌ను యాక్సెస్ చేయగలదు."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"మీ ఆడియో సెట్టింగ్‌లను మార్చడం"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"వాల్యూమ్ మరియు అవుట్‌పుట్ కోసం ఉపయోగించాల్సిన స్పీకర్ వంటి సార్వజనీన ఆడియో సెట్టింగ్‌లను సవరించడానికి యాప్‌ను అనుమతిస్తుంది."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"ఆడియోను రికార్డ్ చేయడం"</string>
@@ -494,6 +491,8 @@
<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_preferredPaymentInfo" msgid="5274423844767445054">"ప్రాధాన్యత ఇవ్వబడిన NFC చెల్లింపు సేవల సమాచారం"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"ప్రాధాన్యత ఇవ్వబడిన NFC చెల్లింపు సేవల సమాచారాన్ని, అంటే రిజిస్టర్ చేయబడిన సహాయక సాధనాలు, మార్గం, గమ్యస్థానం వంటి వాటిని పొందేందుకు యాప్‌ను అనుమతిస్తుంది."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"సమీప క్షేత్ర కమ్యూనికేషన్‌ను నియంత్రించడం"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"సమీప ఫీల్డ్ కమ్యూనికేషన్ (NFC) ట్యాగ్‌లు, కార్డులు మరియు రీడర్‌లతో కమ్యూనికేట్ చేయడానికి యాప్‌ను అనుమతిస్తుంది."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"మీ స్క్రీన్ లాక్‌ను నిలిపివేయడం"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"యాక్సెస్ సామర్థ్య షార్ట్‌కట్ ద్వారా <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ఆన్ చేయబడింది"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"యాక్సెస్ సామర్థ్య షార్ట్‌కట్ ద్వారా <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ఆఫ్ చేయబడింది"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>ని ఉపయోగించడానికి వాల్యూమ్ కీలు రెండింటినీ 3 సెకన్లు నొక్కి ఉంచండి"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"యాక్సెసిబిలిటీ బటన్‌ను మీరు నొక్కినప్పుడు ఉపయోగించాల్సిన ఒక ఫీచర్‌ను ఎంచుకోండి:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"యాక్సెసిబిలిటీ సంజ్ఞతో ఉపయోగించడానికి ఒక సేవను ఎంచుకోండి (రెండు వేళ్లతో స్క్రీన్‌ను కింద నుండి పైకి స్వైప్ చేయండి):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"యాక్సెసిబిలిటీ సంజ్ఞతో ఉపయోగించడానికి ఒక సేవను ఎంచుకోండి (మూడు చేతి వేళ్లతో స్క్రీన్‌ను కింద నుండి పైకి స్వైప్ చేయండి):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"సేవల మధ్య మారడానికి, యాక్సెసిబిలిటీ బటన్‌ను నొక్కి &amp; పట్టుకోండి."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"సేవల మధ్య మారడానికి, రెండు చేతి వేళ్ళతో పైకి స్వైప్ చేసి పట్టుకోండి."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"సేవల మధ్య మారడానికి, మూడు చేతి వేళ్ళతో పైకి స్వైప్ చేసి పట్టుకోండి."</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>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g>కి కనెక్ట్ చేయబడింది"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"ఫైల్‌లను వీక్షించడానికి నొక్కండి"</string>
<string name="pin_target" msgid="8036028973110156895">"పిన్ చేయి"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"<xliff:g id="LABEL">%1$s</xliff:g>ను పిన్ చేయండి"</string>
<string name="unpin_target" msgid="3963318576590204447">"అన్‌‌పిన్‌ ‌చేయి"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"<xliff:g id="LABEL">%1$s</xliff:g>ను అన్‌పిన్ చేయి"</string>
<string name="app_info" msgid="6113278084877079851">"యాప్ సమాచారం"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"డెమోను ప్రారంభిస్తోంది..."</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"ఈ అంశాలను "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"లో అప్‌డేట్ చేయాలా: <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> ?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"సేవ్ చేయి"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"వద్దు, ధన్యవాదాలు"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"ఇప్పుడు కాదు"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"ఎప్పుడూ వద్దు"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"అప్‌డేట్ చేయి"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"కొనసాగించు"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"పాస్‌వర్డ్"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"స్క్రీన్ విభజనను టోగుల్ చేయి"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"స్క్రీన్‌ను లాక్ చేయి"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"స్క్రీన్‌షాట్"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"పాప్-అప్ విండోలో <xliff:g id="APP_NAME">%1$s</xliff:g> యాప్ ఉంది."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> క్యాప్షన్ బార్."</string>
</resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index bc4b79ebc5b1..bd02a73d07bf 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"แอปผู้ดูแลระบบโปรไฟล์งานไม่มีอยู่หรือเสียหาย ระบบจึงทำการลบโปรไฟล์งานและข้อมูลที่เกี่ยวข้องของคุณออก โปรดติดต่อผู้ดูแลระบบเพื่อรับความช่วยเหลือ"</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"โปรไฟล์งานของคุณไม่สามารถใช้ในอุปกรณ์นี้อีกต่อไป"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"ลองป้อนรหัสผ่านหลายครั้งเกินไป"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"ผู้ดูแลระบบปล่อยอุปกรณ์ให้คุณใช้งานส่วนตัว"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"อุปกรณ์มีการจัดการ"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"องค์กรของคุณจัดการอุปกรณ์นี้และอาจตรวจสอบการจราจรของข้อมูลในเครือข่าย แตะเพื่อดูรายละเอียด"</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"ระบบจะลบข้อมูลในอุปกรณ์ของคุณ"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"อนุญาตให้แอปส่งการแพร่ภาพแบบติดหนึบ ซึ่งจะยังคงอยู่หลังจากการแพร่ภาพจบไปแล้ว การใช้งานมากเกินไปอาจทำให้อุปกรณ์ Android TV ทำงานช้าลงหรือไม่เสถียรเนื่องจากมีการใช้หน่วยความจำมากเกิน"</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"อนุญาตให้แอปพลิเคชันส่งการกระจายข้อมูลที่ติดหนึบ ซึ่งจะยังคงอยู่หลังจากการกระจายข้อมูลจบไปแล้ว การใช้งานมากเกินไปอาจทำให้โทรศัพท์ทำงานช้าลงหรือไม่เสถียรโดยการใช้หน่วยความจำมากเกินไป"</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"อ่านผู้ติดต่อของคุณ"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"อนุญาตให้แอปพลิเคชันอ่านข้อมูลผู้ติดต่อที่จัดเก็บไว้ในแท็บเล็ต ซึ่งรวมถึงความถี่ในการโทร ส่งอีเมล หรือการติดต่อด้วยวิธีอื่นๆ กับบุคคลใดบุคคลหนึ่ง การอนุญาตนี้ทำให้แอปพลิเคชันสามารถบันทึกข้อมูลผู้ติดต่อของคุณ และแอปพลิเคชันที่เป็นอันตรายอาจแชร์ข้อมูลผู้ติดต่อโดยไม่แจ้งให้คุณทราบ"</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"อนุญาตให้แอปอ่านข้อมูลเกี่ยวกับรายชื่อติดต่อที่จัดเก็บไว้ในอุปกรณ์ Android TV รวมถึงความถี่ที่คุณโทรหา ส่งอีเมล หรือสื่อสารในรูปแบบอื่นกับรายชื่อติดต่อแต่ละคน สิทธิ์นี้ทำให้แอปบันทึกข้อมูลรายชื่อติดต่อได้และแอปที่เป็นอันตรายอาจแชร์ข้อมูลรายชื่อติดต่อโดยไม่แจ้งให้คุณทราบ"</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"อนุญาตให้แอปพลิเคชันอ่านข้อมูลผู้ติดต่อที่จัดเก็บไว้ในโทรศัพท์ ซึ่งรวมถึงความถี่ในการโทร ส่งอีเมล หรือการติดต่อด้วยวิธีอื่นๆ กับบุคคลใดบุคคลหนึ่ง การอนุญาตนี้ทำให้แอปพลิเคชันสามารถบันทึกข้อมูลผู้ติดต่อของคุณ และแอปพลิเคชันที่เป็นอันตรายอาจแชร์ข้อมูลผู้ติดต่อโดยไม่แจ้งให้คุณทราบ"</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"อนุญาตให้แอปอ่านข้อมูลเกี่ยวกับรายชื่อติดต่อที่จัดเก็บไว้ในแท็บเล็ต แอปจะมีสิทธิ์เข้าถึงบัญชีในแท็บเล็ตที่มีการสร้างรายชื่อติดต่อด้วย โดยอาจรวมถึงบัญชีซึ่งแอปที่คุณได้ติดตั้งไว้สร้างขึ้น สิทธิ์นี้ทำให้แอปบันทึกข้อมูลรายชื่อติดต่อได้และแอปที่เป็นอันตรายอาจแชร์ข้อมูลรายชื่อติดต่อโดยไม่แจ้งให้คุณทราบ"</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"อนุญาตให้แอปอ่านข้อมูลเกี่ยวกับรายชื่อติดต่อที่จัดเก็บไว้ในอุปกรณ์ Android TV แอปจะมีสิทธิ์เข้าถึงบัญชีในอุปกรณ์ Android TV ที่มีการสร้างรายชื่อติดต่อด้วย โดยอาจรวมถึงบัญชีซึ่งแอปที่คุณได้ติดตั้งไว้สร้างขึ้น สิทธิ์นี้ทำให้แอปบันทึกข้อมูลรายชื่อติดต่อได้และแอปที่เป็นอันตรายอาจแชร์ข้อมูลรายชื่อติดต่อโดยไม่แจ้งให้คุณทราบ"</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"อนุญาตให้แอปอ่านข้อมูลเกี่ยวกับรายชื่อติดต่อที่จัดเก็บไว้ในโทรศัพท์ แอปจะมีสิทธิ์เข้าถึงบัญชีในโทรศัพท์ที่มีการสร้างรายชื่อติดต่อด้วย โดยอาจรวมถึงบัญชีซึ่งแอปที่คุณได้ติดตั้งไว้สร้างขึ้น สิทธิ์นี้ทำให้แอปบันทึกข้อมูลรายชื่อติดต่อได้และแอปที่เป็นอันตรายอาจแชร์ข้อมูลรายชื่อติดต่อโดยไม่แจ้งให้คุณทราบ"</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"แก้ไขผู้ติดต่อของคุณ"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"อนุญาตให้แอปพลิเคชันเปลี่ยนแปลงข้อมูลผู้ติดต่อที่จัดเก็บไว้ในแท็บเล็ต ซึ่งรวมถึงความถี่ในการโทร ส่งอีเมล หรือการติดต่อด้วยวิธีอื่นๆ กับบุคคลใดบุคคลหนึ่ง การอนุญาตนี้ทำให้แอปพลิเคชันสามารถลบข้อมูลผู้ติดต่อได้"</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"อนุญาตให้แอปแก้ไขข้อมูลเกี่ยวกับรายชื่อติดต่อที่จัดเก็บไว้ในอุปกรณ์ Android TV รวมถึงความถี่ที่คุณโทรหา ส่งอีเมล หรือสื่อสารในรูปแบบอื่นกับรายชื่อติดต่อแต่ละคน สิทธิ์นี้ทำให้แอปลบข้อมูลรายชื่อติดต่อได้"</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"อนุญาตให้แอปพลิเคชันเปลี่ยนแปลงข้อมูลผู้ติดต่อที่จัดเก็บไว้ในโทรศัพท์ ซึ่งรวมถึงความถี่ในการโทร ส่งอีเมล หรือการติดต่อด้วยวิธีอื่นๆ กับบุคคลใดบุคคลหนึ่ง การอนุญาตนี้ทำให้แอปพลิเคชันสามารถลบข้อมูลผู้ติดต่อได้"</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"อนุญาตให้แอปแก้ไขข้อมูลเกี่ยวกับรายชื่อติดต่อที่จัดเก็บไว้ในแท็บเล็ต สิทธิ์นี้ทำให้แอปลบข้อมูลรายชื่อติดต่อได้"</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"อนุญาตให้แอปแก้ไขข้อมูลเกี่ยวกับรายชื่อติดต่อที่จัดเก็บไว้ในอุปกรณ์ Android TV สิทธิ์นี้ทำให้แอปลบข้อมูลรายชื่อติดต่อได้"</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"อนุญาตให้แอปแก้ไขข้อมูลเกี่ยวกับรายชื่อติดต่อที่จัดเก็บไว้ในโทรศัพท์ สิทธิ์นี้ทำให้แอปลบข้อมูลรายชื่อติดต่อได้"</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"อ่านประวัติการโทร"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"แอปนี้สามารถอ่านประวัติการโทรของคุณได้"</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"เขียนประวัติการโทร"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"เข้าถึงคำสั่งของโปรแกรมแจ้งตำแหน่งพิเศษ"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"อนุญาตให้แอปเข้าถึงคำสั่งของผู้ให้บริการตำแหน่งเพิ่มเติม ซึ่งอาจทำให้แอปสามารถแทรกแซงการทำงานของ GPS หรือต้นทางของตำแหน่งอื่นๆ ได้"</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"เข้าถึงตำแหน่งที่แม่นยำเมื่ออยู่เบื้องหน้าเท่านั้น"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"แอปนี้รับตำแหน่งที่แม่นยำของคุณได้เมื่อทำงานอยู่เบื้องหน้าเท่านั้น แอปจะใช้บริการตำแหน่งเหล่านี้ได้ต่อเมื่อคุณเปิดบริการและบริการพร้อมใช้งานในโทรศัพท์ของคุณ ซึ่งอาจทำให้มีการใช้แบตเตอรี่มากขึ้น"</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"เข้าถึงตำแหน่งโดยประมาณ (อิงตามเครือข่าย) เมื่อทำงานอยู่เบื้องหน้าเท่านั้น"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"แอปนี้รับตำแหน่งของคุณโดยอิงตามแหล่งที่มาของเครือข่าย เช่น เสาส่งสัญญาณมือถือและเครือข่าย Wi-Fi เมื่อทำงานอยู่เบื้องหน้าเท่านั้น แอปจะใช้บริการตำแหน่งเหล่านี้ได้ต่อเมื่อคุณเปิดบริการและบริการพร้อมใช้งานในแท็บเล็ตของคุณ"</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"แอปนี้รับตำแหน่งของคุณได้โดยอิงตามแหล่งที่มาของเครือข่าย เช่น เสาส่งสัญญาณมือถือและเครือข่าย Wi-Fi เมื่อแอปทำงานอยู่เบื้องหน้าเท่านั้น แอปจะใช้บริการตำแหน่งเหล่านี้ได้ต่อเมื่อคุณเปิดใช้งานและบริการพร้อมใช้งานในอุปกรณ์ Android TV ของคุณ"</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"แอปนี้รับตำแหน่งของคุณโดยอิงตามแหล่งที่มาของเครือข่าย เช่น เสาส่งสัญญาณมือถือและเครือข่าย Wi-Fi เมื่อทำงานอยู่เบื้องหน้าเท่านั้น แอปจะใช้บริการตำแหน่งเหล่านี้ได้ต่อเมื่อคุณเปิดบริการและบริการพร้อมใช้งานในโทรศัพท์ของคุณ"</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"แอปนี้เข้าถึงตำแหน่งที่แม่นยำของคุณได้เมื่อทำงานอยู่เบื้องหน้าเท่านั้น แอปจะใช้บริการตำแหน่งได้ต่อเมื่อคุณเปิดบริการและบริการพร้อมใช้งานในอุปกรณ์ของคุณ ซึ่งอาจทำให้มีการใช้แบตเตอรี่มากขึ้น"</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"เข้าถึงตำแหน่งโดยประมาณเมื่ออยู่เบื้องหน้าเท่านั้น"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"แอปนี้เข้าถึงตำแหน่งโดยประมาณของคุณได้เมื่อทำงานอยู่เบื้องหน้าเท่านั้น แอปจะใช้บริการตำแหน่งได้ต่อเมื่อคุณเปิดบริการและบริการพร้อมใช้งานในอุปกรณ์ของคุณ"</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"เข้าถึงตำแหน่งในเบื้องหลัง"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"หากได้รับสิทธิ์นี้เพิ่มจากการเข้าถึงตำแหน่งโดยประมาณหรือตำแหน่งที่แม่นยำ แอปจะมีสิทธิ์เข้าถึงตำแหน่งระหว่างที่ทำงานในเบื้องหลังได้"</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"แอปนี้เข้าถึงตำแหน่งในขณะที่ทำงานอยู่เบื้องหลังได้ด้วย นอกเหนือจากการเข้าถึงตำแหน่งเมื่อทำงานอยู่เบื้องหน้า"</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"เปลี่ยนการตั้งค่าเสียงของคุณ"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"อนุญาตให้แอปพลิเคชันปรับเปลี่ยนการตั้งค่าเสียงทั้งหมดได้ เช่น ระดับเสียงและลำโพงที่จะใช้งาน"</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"บันทึกเสียง"</string>
@@ -494,6 +491,8 @@
<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_preferredPaymentInfo" msgid="5274423844767445054">"ข้อมูลบริการชำระเงิน NFC ที่ต้องการ"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"อนุญาตให้แอปรับข้อมูลบริการชำระเงิน NFC ที่ต้องการ เช่น รหัสแอป (AID) ที่ลงทะเบียนและปลายทางของเส้นทาง"</string>
<string name="permlab_nfc" msgid="1904455246837674977">"ควบคุม Near Field Communication"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"อนุญาตให้แอปพลิเคชันสื่อสารกับแท็ก Near Field Communication (NFC) การ์ด และโปรแกรมอ่าน"</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"ปิดใช้งานการล็อกหน้าจอของคุณ"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"ทางลัดการเข้าถึงเปิด <xliff:g id="SERVICE_NAME">%1$s</xliff:g> แล้ว"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"ทางลัดการเข้าถึงปิด <xliff:g id="SERVICE_NAME">%1$s</xliff:g> แล้ว"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"กดปุ่มปรับระดับเสียงทั้ง 2 ปุ่มค้างไว้ 3 วินาทีเพื่อใช้ <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"เลือกบริการที่จะใช้เมื่อคุณแตะปุ่มการช่วยเหลือพิเศษ:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"เลือกบริการที่จะใช้กับท่าทางสัมผัสการช่วยเหลือพิเศษ (ใช้ 2 นิ้วเลื่อนขึ้นจากด้านล่างของหน้าจอ):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"เลือกบริการที่จะใช้กับท่าทางสัมผัสการช่วยเหลือพิเศษ (ใช้ 3 นิ้วเลื่อนขึ้นจากด้านล่างของหน้าจอ):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"หากต้องการสลับระหว่างบริการ ให้แตะปุ่มการช่วยเหลือพิเศษค้างไว้"</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"หากต้องการสลับระหว่างบริการ ให้ใช้ 2 นิ้วเลื่อนขึ้นค้างไว้"</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"หากต้องการสลับระหว่างบริการ ให้ใช้ 3 นิ้วเลื่อนขึ้นค้างไว้"</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>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"เชื่อมต่อ <xliff:g id="PRODUCT_NAME">%1$s</xliff:g> แล้ว"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"แตะเพื่อดูไฟล์"</string>
<string name="pin_target" msgid="8036028973110156895">"ปักหมุด"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"ตรึง <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"เลิกปักหมุด"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"เลิกตรึง <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"ข้อมูลแอป"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"กำลังเริ่มการสาธิต…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"อัปเดตข้อมูล<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_save_yes" msgid="8035743017382012850">"บันทึก"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"ไม่เป็นไร"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"ไว้ทีหลัง"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"ไม่เลย"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"อัปเดต"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"ทำต่อ"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"รหัสผ่าน"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"เปิด/ปิดการแบ่งหน้าจอ"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"หน้าจอล็อก"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"ภาพหน้าจอ"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"แอป <xliff:g id="APP_NAME">%1$s</xliff:g> ในหน้าต่างป๊อปอัป"</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"แถบคำบรรยาย <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index b24e95a80dbf..c6fb52db4748 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Nawawala o nasira ang admin app ng profile sa trabaho. Dahil dito, na-delete ang profile mo sa trabaho at nauugnay na data. Makipag-ugnayan sa iyong admin para sa tulong."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Hindi na available sa device na ito ang iyong profile sa trabaho"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Masyadong maraming pagsubok sa password"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Inalis ng admin ang device para sa personal na paggamit"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Pinamamahalaan ang device"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Pinamamahalaan ng iyong organisasyon ang device na ito, at maaari nitong subaybayan ang trapiko sa network. I-tap para sa mga detalye."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Buburahin ang iyong device"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Nagbibigay-daan sa app na magpadala ng mga sticky broadcast, na nananatili pagkatapos ng broadcast. Posibleng bumagal o maging hindi stable ang iyong Android TV device dahil sa sobra-sobrang paggamit sa pamamagitan ng pagtulak dito na gumamit ng masyadong maraming memory."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Pinapayagan ang app na magpadala ng mga sticky na pag-broadcast, na nananatili pagkatapos ng pag-broadcast. Maaaring pabagalin o gawing hindi matatag ng labis na paggamit ang telepono sa pamamagitan ng pagdulot dito na gumamit ng masyadong maraming memory."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"basahin ang iyong mga contact"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Pinapayagan ang app na magbasa ng data tungkol sa mga contact na naka-imbak sa iyong tablet, kabilang ang dalas kung kailan ka tumawag, nag-email, o nakipag-ugnayan sa iba pang mga paraan sa mga tukoy na indibidwal. Pinapayagan ng pahintulot na ito ang apps na i-save ang data ng iyong contact, at maaaring magbahagi ang nakakahamak na apps ng data ng contact nang hindi mo nalalaman."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Nagbibigay-daan sa app na basahin ang data tungkol sa iyong mga contact na naka-store sa Android TV device mo, kasama ang dalas ng iyong pagtawag, pag-email, o pakikipag-ugnayan sa iba pang paraan sa mga partikular na indibidwal. Nagbibigay-daan sa mga app ang pahintulot na ito na i-save ang iyong data ng contact at posibleng magbahagi ng data ng contact ang mga nakakapinsalang app nang hindi mo nalalaman."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Pinapayagan ang app na magbasa ng data tungkol sa mga contact na naka-imbak sa iyong telepono, kabilang ang dalas kung kailan ka tumawag, nag-email, o nakipag-ugnayan sa iba pang mga paraan sa mga tukoy na indibidwal. Pinapayagan ng pahintulot na ito ang apps na i-save ang data ng iyong contact, at maaaring magbahagi ang nakakahamak na apps ng data ng contact nang hindi mo nalalaman."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Nagbibigay-daan sa app na magbasa ng data tungkol sa iyong mga contact na naka-store sa tablet mo. Magkakaroon din ang mga app ng access sa mga account sa iyong tablet na gumawa ng mga contact. Puwedeng kasama rito ang mga account na ginawa ng mga na-install mong app. Nagbibigay-daan ang pahintulot na ito sa mga app na i-save ang iyong data ng contact, at puwedeng magbahagi ng data ng contact ang mga nakakahamak na app nang hindi mo alam."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Nagbibigay-daan sa app na magbasa ng data tungkol sa iyong mga contact na naka-store sa Android TV device mo. Magkakaroon din ang mga app ng access sa mga account sa iyong Android TV device na gumawa ng mga contact. Puwedeng kasama rito ang mga account na ginawa ng mga na-install mong app. Nagbibigay-daan ang pahintulot na ito sa mga app na i-save ang iyong data ng contact, at puwedeng magbahagi ng data ng contact ang mga nakakahamak na app nang hindi mo alam."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Nagbibigay-daan sa app na magbasa ng data tungkol sa iyong mga contact na naka-store sa telepono mo. Magkakaroon din ang mga app ng access sa mga account sa iyong telepono na gumawa ng mga contact. Puwedeng kasama rito ang mga account na ginawa ng mga na-install mong app. Nagbibigay-daan ang pahintulot na ito sa mga app na i-save ang iyong data ng contact, at puwedeng magbahagi ng data ng contact ang mga nakakahamak na app nang hindi mo alam."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"baguhin ang iyong mga contact"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Pinapayagan ang app na baguhin ang data tungkol sa iyong mga contact na naka-imbak sa iyong tablet, kabilang ang dalas kung kailan ka tumawag, nag-email, o nakipag-ugnayan sa iba pang mga paraan sa mga tukoy na contact. Pinapayagan ng pahintulot na ito ang apps na magtanggal ng data ng contact."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Nagbibigay-daan sa app na baguhin ang data tungkol sa iyong mga contact na naka-store sa iyong Android TV device, kasama ang dalas ng iyong pagtawag, pag-email, o pakikipag-ugnayan sa iba pang paraan sa mga partikular na contact. Nagbibigay-daan ang pahintulot na ito sa mga app na mag-delete ng data ng contact."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Pinapayagan ang app na baguhin ang data tungkol sa iyong mga contact na naka-imbak sa iyong telepono, kabilang ang dalas kung kailan ka tumawag, nag-email, o nakipag-ugnayan sa iba pang mga paraan sa mga tukoy na contact. Pinapayagan ng pahintulot na ito ang apps na magtanggal ng data ng contact."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Nagbibigay-daan sa app na baguhin ang data tungkol sa iyong mga contact na naka-store sa tablet mo. Nagbibigay-daan ang pahintulot na ito sa mga app na mag-delete ng data ng contact."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Nagbibigay-daan sa app na baguhin ang data tungkol sa iyong mga contact na naka-store sa Android TV device mo. Nagbibigay-daan ang pahintulot na ito sa mga app na mag-delete ng data ng contact."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Nagbibigay-daan sa app na baguhin ang data tungkol sa iyong mga contact na naka-store sa telepono mo. Nagbibigay-daan ang pahintulot na ito sa mga app na mag-delete ng data ng contact."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"basahin ang log ng tawag"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Mababasa ng app na ito ang iyong history ng tawag."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"isulat ang log ng tawag"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"i-access ang mga dagdag na command ng provider ng lokasyon"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Nagbibigay-daan sa app na mag-access ng mga karagdagang command ng provider ng lokasyon. Maaari nitong bigyang-daan ang app na gambalain ang pagpapatakbo ng GPS o ng iba pang mga pinagmulan ng lokasyon."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"i-access lang ang tumpak na lokasyon sa foreground"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Makukuha lang ng app na ito ang iyong eksaktong lokasyon kapag nasa foreground ito. Ang mga serbisyo ng lokasyon na ito ay dapat naka-on at available sa iyong telepono para magamit ng app ang mga ito. Maaaring lumakas ang pagkonsumo ng baterya dahil dito."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"i-access lang ang tinatantiyang lokasyon (batay sa network) sa foreground"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Makukuha ng app na ito ang iyong lokasyon batay sa mga source ng network gaya ng mga cell tower at Wi-Fi network ngunit magagawa lang ito kapag nasa foreground ang app. Ang mga serbisyo ng lokasyon na ito ay dapat naka-on at available sa iyong tablet para magamit ng app ang mga ito."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Makukuha ng app na ito ang iyong lokasyon batay sa mga source ng network gaya ng mga cell site at Wi-Fi network, pero magagawa lang ito kapag nasa foreground ang app. Naka-on at available dapat ang mga serbisyo ng lokasyon na ito sa iyong Android TV device para magamit ng app ang mga ito."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Makukuha ng app na ito ang iyong lokasyon batay sa mga source ng network gaya ng mga cell tower at Wi-Fi network, ngunit magagawa lang ito kapag nasa foreground ang app. Ang mga serbisyo ng lokasyon na ito ay dapat naka-on at available sa iyong telepono para magamit ng app ang mga ito."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Makukuha lang ng app na ito ang iyong eksaktong lokasyon kapag nasa foreground ito. Naka-on at available dapat ang mga serbisyo ng lokasyon sa iyong device para magamit ng app ang mga ito. Posibleng lumakas ang pagkonsumo ng baterya dahil dito."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"i-access lang ang tinatantyang lokasyon sa foreground"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Makukuha lang ng app na ito ang iyong tinatantyang lokasyon kapag nasa foreground ito. Naka-on at available dapat ang mga serbisyo ng lokasyon sa iyong device para magamit ng app ang mga ito."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"i-access ang lokasyon sa background"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Kung papahintulutan ito bukod pa sa pag-access sa tinataya o tumpak na lokasyon, maaaring i-access ng app ang lokasyon habang tumatakbo sa background."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Puwedeng i-access ng app na ito ang lokasyon habang tumatakbo sa background, bilang karagdagan sa access sa lokasyon sa foreground."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"baguhin ang mga setting ng iyong audio"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Pinapayagan ang app na baguhin ang mga pandaigdigang setting ng audio gaya ng volume at kung aling speaker ang ginagamit para sa output."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"mag-record ng audio"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Pinapayagan ang app na tingnan ang configuration ng Bluetooth sa tablet, at na gumawa at tumanggap ng mga koneksyong may mga nakapares na device."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Nagbibigay-daan sa app na tingnan ang configuration ng Bluetooth sa iyong Android TV device, and at gumawa at tumanggap ng mga koneksyon sa mga nakapares na device."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Pinapayagan ang app na tingnan ang configuration ng Bluetooth sa telepono, at na gumawa at tumanggap ng mga koneksyong may mga nakapares na device."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Impormasyon sa Gustong NFC na Serbisyo sa Pagbabayad"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Pinapayagan ang app na makakuha ng impormasyon sa gustong nfc na serbisyo sa pagbabayad tulad ng mga nakarehistrong application ID at destinasyon ng ruta."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"kontrolin ang Near Field Communication"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Pinapayagan ang app na makipag-ugnay sa Near Field Communication (NFC) na mga tag, card, at reader."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"i-disable ang iyong screen lock"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"Na-on ng Shortcut sa Accessibility ang <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"Na-off ng Shortcut sa Accessibility ang <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Pindutin nang matagal ang parehong volume key sa loob ng tatlong segundo para magamit ang <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Pumili ng serbisyong gagamitin kapag na-tap mo ang button ng pagiging accessible:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Pumili ng serbisyong gagamitin sa galaw ng pagiging accessible (pag-swipe pataas mula sa ibaba ng screen gamit ang dalawang daliri):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Pumili ng serbisyong gagamitin sa galaw ng pagiging accessible (pag-swipe pataas mula sa ibaba ng screen gamit ang tatlong daliri):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Para magpalipat-lipat sa mga serbisyo, pindutin nang matagal ang button ng pagiging accessible."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Para magpalipat-lipat sa mga serbisyo, mag-swipe pataas gamit ang dalawang daliri at i-hold."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Para magpalipat-lipat sa mga serbisyo, mag-swipe pataas gamit ang tatlong daliri at i-hold."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Pag-magnify"</string>
<string name="user_switched" msgid="7249833311585228097">"Kasalukuyang user <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="1912993630661332336">"Lumilipat kay <xliff:g id="NAME">%1$s</xliff:g>…"</string>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Nakakonekta sa <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"I-tap upang makita ang mga file"</string>
<string name="pin_target" msgid="8036028973110156895">"I-pin"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"I-pin ang <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"I-unpin"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"I-unpin ang <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Impormasyon ng app"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Sinisimulan ang demo…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"I-update ang mga item na ito sa "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, at <xliff:g id="TYPE_2">%3$s</xliff:g> ?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"I-save"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Hindi, salamat na lang"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Hindi ngayon"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Hindi Kailanman"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"I-update"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Magpatuloy"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"password"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"I-toggle ang Split Screen"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Lock Screen"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Screenshot"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"<xliff:g id="APP_NAME">%1$s</xliff:g> app sa Pop-up na window."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Caption bar ng <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 326ace96f68d..25d0674f32ce 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"İş profili yönetici uygulaması eksik ya da bozuk. Bunun sonucunda iş profiliniz ve ilgili veriler silindi. Yardım almak için yöneticiniz ile iletişim kurun."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"İş profiliniz arık bu cihazda kullanılamıyor"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Çok fazla şifre denemesi yapıldı"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Yönetici, cihazı kişisel kullanım için serbest bıraktı"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Cihaz yönetiliyor"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Kuruluşunuz bu cihazı yönetmekte olup ağ trafiğini izleyebilir. Ayrıntılar için dokunun."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Cihazınız silinecek"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Uygulamaya, yayın bittikten sonra da kalan sabit yayınlar gönderme izni verir. Aşırı kullanılması çok fazla bellek harcanmasına neden olarak Android TV cihazınızı yavaşlatabilir veya dengesiz hale getirebilir."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Uygulamaya, yayın bittikten sonra da kalan sabit yayınlar gönderme izni verir. Aşırı kullanılması çok fazla bellek harcanmasına neden olarak telefonunu yavaşlatabilir veya dengesiz hale getirebilir."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"kişilerinizi okuma"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Uygulamaya tabletinizde depolanan kişilerinizle ilgili verileri okuma izni verir. Bu verilere belirli kişilerle ne sıklıkta çağrı, e-posta veya diğer yöntemlerle iletişim kurduğunuz bilgisi dahildir. Bu izin, uygulamanın kişi verilerinizi kaydetmesine olanak sağlar ve kötü amaçlı uygulamalar kişi verilerini haberiniz olmadan paylaşabilir."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Uygulamaya Android TV cihazınızda depolanan kişilerinizle ilgili verileri okuma izni verir. Bu verilere belirli kişilerle ne sıklıkta çağrı, e-posta veya diğer yöntemlerle iletişim kurduğunuz bilgisi dahildir. Bu izin, uygulamanın kişi verilerinizi kaydetmesine olanak sağlar ve kötü amaçlı uygulamalar kişi verilerini sizden habersiz paylaşabilir."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Uygulamaya telefonunuzda depolanan kişilerinizle ilgili verileri okuma izni verir. Bu verilere belirli kişilerle ne sıklıkta çağrı, e-posta veya diğer yöntemlerle iletişim kurduğunuz bilgisi dahildir. Bu izin, uygulamanın kişi verilerinizi kaydetmesine olanak sağlar ve kötü amaçlı uygulamalar kişi verilerini sizden habersiz paylaşabilir."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Uygulamaya tabletinizde kayıtlı kişileriniz ile ilgili verileri okuma izni verir. Uygulamalar ayrıca tabletinizde kişi oluşturan hesaplara da erişebilir. Bu, yüklediğiniz uygulamalar tarafından oluşturulan hesapları içerebilir. Bu izin, uygulamanın kişi verilerinizi kaydetmesine olanak sağlar ve kötü amaçlı uygulamalar kişi verilerini sizden habersiz paylaşabilir."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Uygulamaya Android TV cihazınızda depolanan kişilerinizle ilgili verileri okuma izni verir. Uygulamalar ayrıca Android TV cihazınızda kişi oluşturan hesaplara da erişebilir. Bu, yüklediğiniz uygulamalar tarafından oluşturulan hesapları içerebilir. Bu izin, uygulamanın kişi verilerinizi kaydetmesine olanak sağlar ve kötü amaçlı uygulamalar kişi verilerini sizden habersiz paylaşabilir."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Uygulamaya telefonunuzda depolanan kişilerinizle ilgili verileri okuma izni verir. Uygulamalar ayrıca telefonunuzda kişi oluşturan hesaplara da erişebilir. Bu, yüklediğiniz uygulamalar tarafından oluşturulan hesapları içerebilir. Bu izin, uygulamanın kişi verilerinizi kaydetmesine olanak sağlar ve kötü amaçlı uygulamalar kişi verilerini sizden habersiz paylaşabilir."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"kişilerinizi değiştirme"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Uygulamaya tabletinizde depolanan kişilerinizle ilgili verileri değiştirme izni verir. Bu verilere belirli kişilerle ne sıklıkta çağrı, e-posta veya diğer yöntemlerle iletişim kurduğunuz bilgisi dahildir. Bu izin, uygulamanın kişi verilerinizi silmesine olanak sağlar."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Uygulamaya Android TV cihazınızda depolanan kişilerinizle ilgili verileri değiştirme izni verir. Bu verilere belirli kişilerle ne sıklıkta çağrı, e-posta veya diğer yöntemlerle iletişim kurduğunuz bilgisi dahildir. Bu izin, uygulamanın kişi verilerinizi silmesine olanak sağlar."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Uygulamaya telefonunuzda depolanan kişilerinizle ilgili verileri değiştirme izni verir. Bu verilere belirli kişilerle ne sıklıkta çağrı, e-posta veya diğer yöntemlerle iletişim kurduğunuz bilgisi dahildir. Bu izin, uygulamanın kişi verilerinizi silmesine olanak sağlar."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Uygulamaya tabletinizde kayıtlı kişileriniz ile ilgili verileri değiştirme izni verir. Bu izin, uygulamanın kişi verilerinizi silmesine olanak sağlar."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Uygulamaya Android TV cihazınızda kayıtlı kişileriniz ile ilgili verileri değiştirme izni verir. Bu izin, uygulamanın kişi verilerinizi silmesine olanak sağlar."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Uygulamaya telefonunuzda kayıtlı kişileriniz ile ilgili verileri değiştirme izni verir. Bu izin, uygulamanın kişi verilerinizi silmesine olanak sağlar."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"çağrı günlüğünü oku"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Bu uygulama, çağrı geçmişinizi okuyabilir."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"çağrı günlüğüne yaz"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"ek konum sağlayıcı komutlarına eriş"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Uygulamanın, ekstra konum sağlayıcı komutlarına erişmesine izin verir. Bu izin, uygulamanın GPS veya diğer konum kaynaklarının çalışmasını kesmesine olanak sağlayabilir."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"yalnızca ön planda kesin konuma erişme"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Bu uygulama yalnızca ön plandayken kesin konumunuzu alabilir. Uygulamanın bu hizmetleri kullanabilmesi için telefonunuzda bu konum hizmetleri açık ve kullanılabilir olmalıdır. Bu, pil tüketimini artırabilir."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"yalnızca ön planda yaklaşık konuma (ağa dayalı) erişme"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Bu uygulama baz istasyonları ve kablosuz ağlar gibi ağ kaynaklarını dikkate alarak konumunuzu bulabilir, ancak bunu yalnızca ön plandayken yapabilir. Uygulamanın bu hizmetleri kullanabilmesi için tabletinizde bu konum hizmetleri açık ve kullanılabilir olmalıdır."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Bu uygulama baz istasyonları ve kablosuz ağlar gibi ağ kaynaklarını dikkate alarak konumunuzu bulabilir, ancak bunu yalnızca ön plandayken yapabilir. Uygulamanın bu hizmetleri kullanabilmesi için Android TV cihazınızda bu konum hizmetleri açık ve kullanılabilir olmalıdır."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Bu uygulama baz istasyonları ve kablosuz ağlar gibi ağ kaynaklarını dikkate alarak konumunuzu bulabilir, ancak bunu yalnızca ön plandayken yapabilir. Uygulamanın bu hizmetleri kullanabilmesi için telefonunuzda bu konum hizmetleri açık ve kullanılabilir olmalıdır."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Bu uygulama yalnızca ön plandayken kesin konumunuzu alabilir. Uygulamanın bu hizmetleri kullanabilmesi için telefonunuzda bu konum hizmetleri açık ve kullanılabilir olmalıdır. Bu, pil tüketimini artırabilir."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"yalnızca ön planda yaklaşık konuma erişme"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Bu uygulama, yalnızca ön planda çalışırken yaklaşık konum bilginizi alabilir. Uygulamanın kullanabilmesi için konum hizmetlerinin açılması ve cihazınızda kullanılabilir olması gerekir."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"konum bilgisine arka planda eriş"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Bu izin, yaklaşık veya tam konum erişimine ek olarak verilirse uygulama, konum bilgisine arka planda çalışırken erişebilir."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Bu uygulama ön plan konum erişimine ek olarak konum bilgisine arka planda çalışırken erişebilir."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"ses ayarlarınızı değiştirin"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Uygulamaya ses düzeyi ve ses çıkışı için kullanılan hoparlör gibi genel ses ayarlarını değiştirme izni verir."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"ses kaydet"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Uygulamaya, tabletteki Bluetooth yapılandırmasını görüntüleme, eşlenmiş cihazlarla bağlantı yapma ve bu tür bağlantıları kabul etme izni verir."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Uygulamaya, Android TV cihazınızdaki Bluetooth yapılandırmasını görüntüleme, eşleştirilmiş cihazlarla bağlantı yapma ve bu tür bağlantıları kabul etme izni verir."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Uygulamaya, telefondaki Bluetooth yapılandırmasını görüntüleme, eşlenmiş cihazlarla bağlantı yapma ve bu tür bağlantıları kabul etme izni verir."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Tercih Edilen NFC Ödeme Hizmeti Bilgileri"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Uygulamaya, kayıtlı yardımlar ve rota hedefi gibi tercih edilen NFC ödeme hizmeti bilgilerini alma izni verir."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"Yakın Alan İletişimini denetle"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Uygulamaya, Near Field Communication (NFC) etiketleri, kartlar ve okuyucular ile iletişim kurma izni verir."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"ekran kilidimi devre dışı bırak"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"Erişilebilirlik Kısayolu <xliff:g id="SERVICE_NAME">%1$s</xliff:g> hizmetini açtı"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"Erişilebilirlik Kısayolu <xliff:g id="SERVICE_NAME">%1$s</xliff:g> hizmetini kapattı"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> hizmetini kullanmak için her iki ses tuşunu basılı tutun"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Erişilebilirlik düğmesine dokunduğunuzda kullanmak üzere bir hizmet seçin:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Erişilebilirlik hareketiyle (iki parmakla ekranın altından yukarı kaydırma) kullanılacak bir hizmet seçin:"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Erişilebilirlik hareketiyle (üç parmakla ekranın altından yukarı kaydırma) kullanılacak bir hizmet seçin:"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Hizmetler arasında geçiş yapmak erişilebilirlik düğmesine dokunup basılı tutun."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Hizmetler arasında geçiş yapmak için iki parmakla yukarı kaydırıp basılı tutun."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Hizmetler arasında geçiş yapmak için üç parmakla yukarı kaydırıp basılı tutun."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Büyütme"</string>
<string name="user_switched" msgid="7249833311585228097">"Geçerli kullanıcı: <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="1912993630661332336">"<xliff:g id="NAME">%1$s</xliff:g> adlı kullanıcıya geçiliyor…"</string>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> cihazına bağlandı"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Dosyaları görüntülemek için dokunun"</string>
<string name="pin_target" msgid="8036028973110156895">"Sabitle"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"<xliff:g id="LABEL">%1$s</xliff:g> uygulamasını sabitle"</string>
<string name="unpin_target" msgid="3963318576590204447">"Sabitlemeyi kaldır"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"<xliff:g id="LABEL">%1$s</xliff:g> uygulamasının sabitlemesini kaldır"</string>
<string name="app_info" msgid="6113278084877079851">"Uygulama bilgileri"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Demo başlatılıyor…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Şu öğeler "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" hizmetinde güncellensin mi: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ve <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Kaydet"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Hayır, teşekkürler"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Şimdi değil"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Hiçbir zaman"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Güncelle"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Devam"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"şifre"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Bölünmüş Ekranı aç/kapat"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Kilit Ekranı"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Ekran görüntüsü"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"Pop-up pencerede <xliff:g id="APP_NAME">%1$s</xliff:g> uygulaması."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> uygulamasının başlık çubuğu."</string>
</resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 8007f9e1d46a..ca0146b7ca79 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -192,8 +192,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Додаток адміністратора в робочому профілі відсутній або пошкоджений. У результаті ваш робочий профіль і пов’язані з ним дані видалено. Зверніться до свого адміністратора по допомогу."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Робочий профіль більше не доступний на цьому пристрої"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Забагато спроб ввести пароль"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Адміністратор не дозволив використовувати пристрій для особистих потреб"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Пристрій контролюється"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Адміністратор вашої організації контролює цей пристрій і відстежує мережевий трафік. Торкніться, щоб дізнатися більше."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"З вашого пристрою буде стерто всі дані"</string>
@@ -236,7 +235,7 @@
<string name="global_action_bug_report" msgid="5127867163044170003">"Звіт про помилки"</string>
<string name="global_action_logout" msgid="6093581310002476511">"Завершити сеанс"</string>
<string name="global_action_screenshot" msgid="2610053466156478564">"Знімок екрана"</string>
- <string name="bugreport_title" msgid="8549990811777373050">"Повідомлення про помилку"</string>
+ <string name="bugreport_title" msgid="8549990811777373050">"Звіт про помилку"</string>
<string name="bugreport_message" msgid="5212529146119624326">"Інформація про поточний стан вашого пристрою буде зібрана й надіслана електронною поштою. Підготовка звіту триватиме певний час."</string>
<string name="bugreport_option_interactive_title" msgid="7968287837902871289">"Інтерактивний звіт"</string>
<string name="bugreport_option_interactive_summary" msgid="8493795476325339542">"Підходить для більшості випадків. Можна відстежувати, як створюється звіт, вводити більше деталей про проблему та робити знімки екрана. Можуть опускатися деякі розділи, які рідко використовуються, але довго створюються."</string>
@@ -387,13 +386,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Дозволяє додатку надсилати закріплені широкомовні повідомлення, які залишаються після їх відтворення. Надмірне використання може сповільнювати роботу пристрою Android TV або порушувати її стабільність, спричиняючи завелике використання пам\'яті."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Дозволяє програмі надсилати закріплені широкомовні повідомлення, які залишаються після відтворення широкомовного повідомлення. Надмірне використання може сповільнювати роботу телефону або порушувати її стабільність, спричиняючи завелике використання пам’яті."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"читати контакти"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Дозволяє програмі читати дані про контакти, які зберігаються у вашому планшетному ПК, зокрема частоту здійснення викликів, надсилання електронних листів або інших способів спілкування з окремими особами. Такий дозвіл дає програмам змогу зберігати ваші контактні дані. Шкідливі програми можуть надсилати контактні дані без вашого відома."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Дозволяє додатку зчитувати дані про контакти, які зберігаються на вашому пристрої Android TV, зокрема частоту здійснення викликів, надсилання електронних листів або спілкування з певними особами іншими способами. Додатки з цим дозволом можуть зберігати контактні дані. Шкідливі додатки можуть надсилати контактні дані без вашого відома."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Дозволяє програмі читати дані про контакти, які зберігаються у вашому телефоні, зокрема частоту здійснення викликів, надсилання електронних листів або інших способів спілкування з окремими особами. Такий дозвіл дає програмам змогу змогу зберігати ваші контактні дані. Шкідливі програми можуть надсилати контактні дані без вашого відома."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Дозволяє додатку переглядати дані про контакти, які зберігаються на вашому планшеті. Додатки також отримають доступ до облікових записів на вашому планшеті (зокрема до створених іншими встановленими додатками), у яких було створено контакти. Додатки з цим дозволом можуть зберігати ваші контактні дані. Шкідливі додатки можуть надсилати контактні дані без вашого відома."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Дозволяє додатку переглядати дані про контакти, які зберігаються на вашому пристрої Android TV. Додатки також отримають доступ до облікових записів на вашому пристрої Android TV (зокрема до створених іншими встановленими додатками), у яких було створено контакти. Додатки з цим дозволом можуть зберігати ваші контактні дані. Шкідливі додатки можуть надсилати контактні дані без вашого відома."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Дозволяє додатку переглядати дані про контакти, які зберігаються на вашому телефоні. Додатки також отримають доступ до облікових записів на вашому телефоні (зокрема до створених іншими встановленими додатками), у яких було створено контакти. Додатки з цим дозволом можуть зберігати ваші контактні дані. Шкідливі додатки можуть надсилати контактні дані без вашого відома."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"змінювати контакти"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Дозволяє програмі змінювати дані про контакти, які зберігаються у вашому планшетному ПК, зокрема частоту здійснення дзвінків, надсилання електронних листів або інших способів спілкування з окремими особами. Такий дозвіл дає програмам змогу видаляти контактні дані."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Дозволяє додатку змінювати дані про контакти, які зберігаються на вашому пристрої Android TV, зокрема частоту здійснення викликів, надсилання електронних листів або спілкування з певними особами іншими способами. Додатки з цим дозволом можуть видаляти контактні дані."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Дозволяє програмі змінювати дані про контакти, які зберігаються у вашому телефоні, зокрема частоту здійснення дзвінків, надсилання електронних листів або інших способів спілкування з окремими особами. Такий дозвіл дає програмам змогу видаляти контактні дані."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Дозволяє додатку змінювати дані про контакти, які зберігаються на вашому планшеті, а також видаляти їх."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Дозволяє додатку змінювати дані про контакти, які зберігаються на вашому пристрої Android TV, а також видаляти їх."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Дозволяє додатку змінювати дані про контакти, які зберігаються на вашому телефоні, а також видаляти їх."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"читати журнал викликів"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Цей додаток може переглядати історію викликів."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"записувати в журнал викликів"</string>
@@ -413,13 +412,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"отр. дост. до додат. команд пров. місцезн."</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Додаток отримуватиме доступ до додаткових команд постачальника геоданих. Можливе втручання додатка в роботу GPS чи інших джерел геоданих."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"отримувати доступ до даних про точне місцезнаходження лише в активному режимі"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Цей додаток може отримувати дані про ваше точне місцезнаходження лише в активному режимі. Щоб додаток користувався службами локації, вони мають бути наявні й увімкнені на вашому телефоні. Через це може швидше розряджатись акумулятор."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"отримувати доступ до даних про приблизне місцезнаходження (на основі мережі) лише в активному режимі"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Цей додаток може отримувати дані про ваше місцезнаходження на основі джерел мережі, як-от антен мобільного зв’язку та мереж Wi-Fi, лише в активному режимі. Щоб додаток міг користуватися цими службами локації, вони мають бути доступними й увімкненими на вашому планшеті."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Додаток може отримувати дані про ваше місцезнаходження на основі джерел мережі, як-от антен мобільного зв’язку та мереж Wi-Fi, лише в активному режимі. Щоб додаток міг користуватися цими службами локації, вони мають бути доступними й увімкненими на вашому пристрої Android TV."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Цей додаток може отримувати дані про ваше місцезнаходження на основі джерел мережі, як-от антен мобільного зв’язку та мереж Wi-Fi, лише в активному режимі. Щоб додаток міг користуватися цими службами локації, вони мають бути доступними й увімкненими на вашому телефоні."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Цей додаток може отримувати дані про ваше точне місцезнаходження лише в активному режимі. Щоб додаток міг використовувати Служби локації, вони мають бути доступні й увімкнені на вашому пристрої. Це може пришвидшити розряджання акумулятора."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"отримувати доступ до даних про приблизне місцезнаходження лише в активному режимі"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Цей додаток може отримувати дані про ваше приблизне місцезнаходження лише в активному режимі. Щоб додаток міг використовувати Служби локації, вони мають бути доступні й увімкнені на вашому пристрої."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"доступ до геоданих у фоновому режимі"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Якщо ви надасте цей дозвіл і доступ до приблизного або точного місцезнаходження, додаток зможе отримувати геодані у фоновому режимі."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Цей додаток може отримувати дані про місцезнаходження, коли його запущено не лише в активному, а й у фоновому режимі."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"змінювати налаштув-ня звуку"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Дозволяє програмі змінювати загальні налаштування звуку, як-от гучність і динамік, який використовується для виводу сигналу."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"запис-ти аудіо"</string>
@@ -500,6 +497,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Дозволяє програмі переглядати конфігурацію Bluetooth на планшетному ПК, а також створювати та приймати з’єднання зі спареними пристроями."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Дозволяє додатку зчитувати конфігурацію Bluetooth на вашому пристрої Android TV, а також створювати та приймати з\'єднання зі спареними пристроями."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Дозволяє програмі переглядати конфігурацію Bluetooth на телефоні, а також створювати та приймати з’єднання зі спареними пристроями."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Використання інформації з платіжного NFC-сервісу"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Дозволяє додатку отримувати доступ до інформації потрібного платіжного NFC-сервісу (наприклад, пов\'язаних ідентифікаторів чи даних про маршрутизацію трансакцій)."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"контрол. Near Field Communication"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Дозволяє програмі обмінюватися даними з тегами, картками та читачами екрана Near Field Communication (NFC)."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"вимикати блокування екрана"</string>
@@ -906,7 +905,7 @@
<string name="factorytest_no_action" msgid="339252838115675515">"Не було знайдено жодного пакета, який надає дію FACTORY_TEST."</string>
<string name="factorytest_reboot" msgid="2050147445567257365">"Перезав."</string>
<string name="js_dialog_title" msgid="7464775045615023241">"На сторінці за адресою \"<xliff:g id="TITLE">%s</xliff:g>\" написано:"</string>
- <string name="js_dialog_title_default" msgid="3769524569903332476">"Javascript"</string>
+ <string name="js_dialog_title_default" msgid="3769524569903332476">"JavaScript"</string>
<string name="js_dialog_before_unload_title" msgid="7012587995876771246">"Підтвердити перехід"</string>
<string name="js_dialog_before_unload_positive_button" msgid="4274257182303565509">"Полишити цю сторінку"</string>
<string name="js_dialog_before_unload_negative_button" msgid="3873765747622415310">"Залишитися на цій сторінці"</string>
@@ -1356,7 +1355,7 @@
<string name="usb_contaminant_detected_message" msgid="7346100585390795743">"USB-порт автоматично вимкнено. Торкніться, щоб дізнатися більше."</string>
<string name="usb_contaminant_not_detected_title" msgid="2651167729563264053">"Можна використовувати USB-порт"</string>
<string name="usb_contaminant_not_detected_message" msgid="892863190942660462">"Телефон уже не виявляє рідини або сміття."</string>
- <string name="taking_remote_bugreport_notification_title" msgid="1582531382166919850">"Створюється повідомлення про помилку…"</string>
+ <string name="taking_remote_bugreport_notification_title" msgid="1582531382166919850">"Створення звіту про помилку…"</string>
<string name="share_remote_bugreport_notification_title" msgid="6708897723753334999">"Надіслати звіт про помилку?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="3077385149217638550">"Надсилається звіт про помилку…"</string>
<string name="share_remote_bugreport_notification_message_finished" msgid="7325635795739260135">"Ваш адміністратор просить надіслати повідомлення про помилку, щоб вирішити проблему з пристроєм. Він може отримати доступ до ваших додатків і даних."</string>
@@ -1662,12 +1661,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"Сервіс <xliff:g id="SERVICE_NAME">%1$s</xliff:g> увімкнено"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"Сервіс <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>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Виберіть сервіс для кнопки спеціальних можливостей:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Виберіть сервіс для жесту спеціальних можливостей (проведення двома пальцями знизу вгору):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Виберіть сервіс для жесту спеціальних можливостей (проведення трьома пальцями знизу вгору):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Щоб переключитися між сервісами, натисніть і утримуйте кнопку спеціальних можливостей."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Щоб переключитися між сервісами, проведіть двома пальцями вгору й утримуйте екран."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Щоб переключитися між сервісами, проведіть трьома пальцями вгору й утримуйте екран."</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>
@@ -1926,7 +1919,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Під’єднано до пристрою <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Торкніться, щоб переглянути файли"</string>
<string name="pin_target" msgid="8036028973110156895">"Закріпити"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Закріпити додаток <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Відкріпити"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Відкріпити додаток <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Про додатки"</string>
<string name="negative_duration" msgid="1938335096972945232">"-<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Запуск демонстрації…"</string>
@@ -1971,6 +1966,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Оновити в сервісі "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" такі дані: <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>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Зберегти"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Ні, дякую"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Не зараз"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Ніколи"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Оновити"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Продовжити"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"пароль"</string>
@@ -2068,5 +2065,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Розділити екран"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Заблокувати екран"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Знімок екрана"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> у спливаючому вікні."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Смуга із субтитрами для додатка <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 312aed7dec0f..1d79c6ea6652 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"دفتری پروفائل کی منتظم ایپ یا تو غائب ہے یا خراب ہے۔ اس کی وجہ سے، آپ کا دفتری پروفائل اور متعلقہ ڈیٹا حذف کر دیے گئے ہیں۔ مدد کیلئے اپنے منتظم سے رابطہ کریں۔"</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"آپ کا دفتری پروفائل اس آلہ پر مزید دستیاب نہیں ہے"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"پاس ورڈ کی بہت ساری کوششیں"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"منتظم نے ذاتی استعمال کے لیے آلہ کو دستبردار کیا ہے"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"آلہ زیر انتظام ہے"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"آپ کی تنظیم اس آلے کا نظم کرتی ہے اور وہ نیٹ ورک ٹریفک کی نگرانی کر سکتی ہے۔ تفاصیل کیلئے تھپتھپائیں۔"</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"آپ کا آلہ صاف کر دیا جائے گا"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"‏ایپ کو چپکنے والا براڈکاسٹس بھیجنے کی اجازت دیتا ہے، جو براڈکاسٹ ختم ہونے کے بعد بھی باقی رہتے ہیں۔ حد سے زیادہ استعمال میموری کے کافی زیادہ استعمال کی وجہ سے آپ کے Android TV کو سُست یا غیر مستحکم بنا سکتا ہے۔"</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"ایپ کو اسٹیکی براڈکاسٹس بھیجنے کی اجازت دیتا ہے، جو براڈکاسٹ ختم ہونے کے بعد بھی باقی رہتے ہیں۔ حد سے زیادہ استعمال فون کو سست یا غیر مستحکم بنا سکتا ہے جس کی وجہ سے یہ میموری کا کافی زیادہ استعمال کر سکتا ہے۔"</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"اپنے رابطوں کو پڑھیں"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"ایپ کو آپ کے ٹیبلٹ پر اسٹور کردہ آپ کے رابطوں، بشمول مخصوص افراد کو دوسرے طریقوں سے جس تعدد سے آپ نے کال، ای میل کیا ہے یا ان کے ساتھ مواصلت کی ہے اس کے بارے میں ڈیٹا کو پڑھنے کی اجازت دیتا ہے۔ یہ اجازت ایپس کو آپ کے رابطے کا ڈیٹا محفوظ کرنے کی اجازت دیتی ہے اور نقصان دہ ایپس آپ کے علم کے بغیر رابطے کے ڈیٹا کا اشتراک کرسکتی ہیں۔"</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"‏ایپ کو آپ کے Android TV آلہ پر اسٹور کردہ آپ کے رابطے، بشمول مخصوص افراد کو دوسرے طریقوں سے جس تعدد سے آپ نے کال، ای میل کیا ہے یا ان کے ساتھ مواصلت کی ہے ان کے بارے میں ڈیٹا پڑھنے کی اجازت دیتا ہے۔ یہ اجازت ایپس کو آپ کے رابطے کا ڈیٹا محفوظ کرنے کی اجازت دیتی ہے اور نقصان دہ ایپس آپ کی جانکاری کے بغیر رابطے کے ڈیٹا کا اشتراک کر سکتی ہے۔"</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"ایپ کو آپ کے فون پر اسٹور کردہ آپ کے رابطوں، بشمول مخصوص افراد کو دوسرے طریقوں سے جس تعدد سے آپ نے کال، ای میل کیا ہے یا ان کے ساتھ مواصلت کی ہے اس کے بارے میں ڈیٹا کو پڑھنے کی اجازت دیتا ہے۔ یہ اجازت ایپس کو آپ کے رابطے کا ڈیٹا محفوظ کرنے کی اجازت دیتی ہے اور نقصان دہ ایپس آپ کے علم کے بغیر رابطے کے ڈیٹا کا اشتراک کرسکتی ہیں۔"</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"ایپ کو آپ کے ٹیبلیٹ پر اسٹور کردہ آپ کے رابطوں کے بارے میں ڈیٹا کو پڑھنے کی اجازت دیتی ہے۔ ایپس کو آپ کے ٹیبلیٹ پر ان اکاؤنٹس تک رسائی حاصل ہو گی جنہوں نے رابطے تخلیق کیے ہیں۔ اس میں آپ کی انسٹال کردہ ایپس کے ذریعے تخلیق کردہ اکاؤنٹس بھی شامل ہو سکتے ہیں۔ یہ اجازت ایپس کو آپ کے رابطے کا ڈیٹا محفوظ کرنے کی اجازت دیتی ہے اور نقصان دہ ایپس آپ کی جانکاری کے بغیر رابطے کے ڈیٹا کا اشتراک کر سکتی ہیں۔"</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"‏ایپ کو آپ کے Android TV آلہ پر اسٹور کردہ آپ کے رابطوں کے بارے میں ڈیٹا کو پڑھنے کی اجازت دیتی ہے۔ ایپس کو آپ کے Android TV آلات پر ان اکاؤنٹس تک رسائی حاصل ہو گی جنہوں نے رابطے تخلیق کیے ہیں۔ اس میں آپ کی انسٹال کردہ ایپس کے ذریعے تخلیق کردہ اکاؤنٹس بھی شامل ہو سکتے ہیں۔ یہ اجازت ایپس کو آپ کے رابطے کا ڈیٹا محفوظ کرنے کی اجازت دیتی ہے اور نقصان دہ ایپس آپ کی جانکاری کے بغیر رابطے کے ڈیٹا کا اشتراک کر سکتی ہیں۔"</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"ایپ کو آپ کے فون پر اسٹور کردہ آپ کے رابطوں کے بارے میں ڈیٹا پڑھنے کی اجازت دیتی ہے۔ ایپس کو آپ کے فون پر ان اکاؤنٹس تک رسائی حاصل ہو گی جنہوں نے رابطے تخلیق کیے ہیں۔ اس میں آپ کی انسٹال کردہ ایپس کے ذریعے تخلیق کردہ اکاؤنٹس بھی شامل ہو سکتے ہیں۔ یہ اجازت ایپس کو آپ کے رابطے کا ڈیٹا محفوظ کرنے کی اجازت دیتی ہے اور نقصان دہ ایپس آپ کی جانکاری کے بغیر رابطے کے ڈیٹا کا اشتراک کر سکتی ہیں۔"</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"اپنے رابطوں میں ترمیم کریں"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"ایپ کو آپ کے ٹیبلٹ پر اسٹور کردہ آپ کے رابطوں، بشمول مخصوص رابطوں کو جس تعدد سے آپ نے کال، ای میل کیا ہے یا دوسرے طریقوں سے ان کے ساتھ مواصلت کی ہے اس کے بارے میں ڈیٹا میں ترمیم کی اجازت دیتا ہے۔ یہ اجازت ایپس کو رابطے کا ڈیٹا حذف کرنے کی اجازت دیتی ہے۔"</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"‏ایپ کو آپ کے Android TV آلات پر اسٹور کردہ آپ کے رابطوں، بشمول مخصوص رابطوں کو جس تعدد سے آپ نے کال، ای میل کیا ہے یا دوسرے طریقوں سے ان کے ساتھ مواصلت کی ہے ان کے بارے میں ڈیٹا میں ترمیم کی اجازت دیتا ہے۔ یہ اجازت ایپس کو رابطے کا ڈیٹا حذف کرنے کی اجازت دیتی ہے۔"</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"ایپ کو آپ کے فون پر اسٹور کردہ آپ کے رابطوں، بشمول مخصوص رابطوں کو جس تعدد سے آپ نے کال، ای میل کیا ہے یا دوسرے طریقوں سے ان کے ساتھ مواصلت کی ہے اس کے بارے میں ڈیٹا میں ترمیم کی اجازت دیتا ہے۔ یہ اجازت ایپس کو رابطے کا ڈیٹا حذف کرنے کی اجازت دیتی ہے۔"</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"ایپ کو آپ کے ٹیبلیٹ پر اسٹور کردہ آپ کے رابطوں کے بارے میں ڈیٹا کو ترمیم کرنے کی اجازت دیتی ہے۔ یہ اجازت ایپس کو رابطے کا ڈیٹا حذف کرنے کی اجازت دیتی ہے۔"</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"‏ایپ کو آپ کے Android TV آلہ پر اسٹور کردہ آپ کے رابطوں کے بارے میں ڈیٹا کو ترمیم کرنے کی اجازت دیتی ہے۔ یہ اجازت ایپس کو رابطے کا ڈیٹا حذف کرنے کی اجازت دیتی ہے۔"</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"ایپ کو آپ کے فون پر اسٹور کردہ آپ کے رابطوں کے بارے میں ڈیٹا کو ترمیم کرنے کی اجازت دیتی ہے۔ یہ اجازت ایپس کو رابطے کا ڈیٹا حذف کرنے کی اجازت دیتی ہے۔"</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"کال لاگ پڑھیں"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"یہ ایپ آپ کی کال کی سرگزشت پڑھ سکتی ہے۔"</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"کال لاگ لکھیں"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"اضافی مقام فراہم کنندہ کی کمانڈز تک رسائی حاصل کریں"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"‏ایپ کو اضافی مقام فراہم کنندہ کی کمانڈز تک رسائی حاصل کرنے کی اجازت دیتی ہے۔ یہ ایپ کو GPS یا دوسرے مقام کے مآخذ کے عمل کے ساتھ مداخلت کرنے کی اجازت دے سکتی ہے۔"</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"صرف پیش منظر میں درست مقام تک رسائی حاصل کریں"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"یہ ایپ جب پس منظر میں ہوتی ہے تبھی یہ آپ کا صحیح مقام حاصل کر سکتی ہے۔ ایپ کو ان مقام کی سروسز کو استعمال کر سکنے کیلئے ان کا آن ہونا اور آپ کے فون پر دستیاب ہونا ضروری ہے۔"</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"صرف پیش منظر میں (نیٹ ورک پر مبنی) تخمینی مقام تک رسائی حاصل کریں"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"‏نیٹ ورک ماخذات جیسے کہ سیل ٹاورز اور Wi-Fi نیٹ ورکس کی بنیاد پر یہ ایپ آپ کا مقام حاصل کر سکتی ہے لیکن صرف اس وقت جب ایپ پیش منظر میں ہو۔ ایپ کو ان مقام کی سروسز کو استعمال کرنے کے لیے ان کا آن ہونا اور آپ کے ٹیبلیٹ پر دستیاب ہونا ضروری ہے۔"</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"‏نیٹ ورک ماخذات جیسے کہ سیل ٹاورز اور Wi-Fi نیٹ ورکس کی بنیاد پر یہ ایپ آپ کا مقام حاصل کر سکتی ہے لیکن صرف اس وقت جب ایپ پیش منظر میں ہو۔ ایپ کو ان مقام کی سروسز کو استعمال کرنے کے لیے ان کا آن ہونا اور آپ کے Android TV آلہ پر دستیاب ہونا ضروری ہے۔"</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"‏نیٹ ورک ماخذات جیسے کہ سیل ٹاورز اور Wi-Fi نیٹ ورکس کی بنیاد پر یہ ایپ آپ کا مقام حاصل کر سکتی ہے لیکن صرف اس وقت جب ایپ پیش منظر میں ہو۔ ایپ کو ان مقام کی سروسز کو استعمال کرنے کے لیے ان کا آن ہونا اور آپ کے فون پر دستیاب ہونا ضروری ہے۔"</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"یہ ایپ جب پس منظر میں ہوتی ہے تبھی یہ آپ کا صحیح مقام حاصل کر سکتی ہے۔ ایپ کو مقام کی سروسز کو استعمال کرنے کیلئے اِن کا آپ کے آلہ پر دستیاب ہونا اور آن ہونا ضروری ہے۔ اس سے بیٹری کی کھپت میں اضافہ ہو سکتا ہے۔"</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"صرف پیش منظر میں تخمینی مقام تک رسائی"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"یہ ایپ جب پس منظر میں ہوتی ہے تبھی یہ آپ کا تخمینی مقام حاصل کر سکتی ہے۔ ایپ کو مقام کی سروسز کو استعمال کرنے کیلئے ان کا آپ کے آلہ پر دستیاب ہونا اور آن ہونا ضروری ہے۔"</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"پس منظر میں مقام کی رسائی حاصل کریں"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"اگر اضافی طور پر اسے تخمینی یا درست مقام تک رسائی کی منظوری دی جاتی ہے تو پس منظر میں چلنے کے دوران ایپ اس مقام تک رسائی حاصل کر سکتی ہے۔"</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"یہ ایپ پیش منظر کے مقام تک رسائی کے ساتھ ساتھ، پس منظر میں چلتے ہوئے مقام تک رسائی حاصل کر سکتی ہے۔"</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"اپنے آڈیو کی ترتیبات کو تبدیل کریں"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"ایپ کو مجموعی آڈیو ترتیبات جیسے والیوم اور آؤٹ پٹ کیلئے جو اسپیکر استعمال ہوتا ہے اس میں ترمیم کرنے کی اجازت دیتا ہے۔"</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"آڈیو ریکارڈ کریں"</string>
@@ -494,6 +491,8 @@
<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_preferredPaymentInfo" msgid="5274423844767445054">"‏ترجیح شدہ NFC ادائیگی کی سروس کی معلومات"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"‏ایپ کو رجسٹرشدہ ایڈز اور روٹ ڈسٹنیشن جیسی ترجیح شدہ nfc ادائیگی سروس کی معلومات حاصل کرنے کی اجازت دیتا ہے۔"</string>
<string name="permlab_nfc" msgid="1904455246837674977">"‏Near Field کمیونیکیشن کنٹرول کریں"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"‏ایپ کو Near Field Communication (NFC)‎ ٹیگز، کارڈز اور ریڈرز کے ساتھ مواصلت کرنے کی اجازت دیٹا ہے۔"</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"اپنے اسکرین لاک کو غیر فعال کریں"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"ایکسیسبیلٹی شارٹ کٹ نے <xliff:g id="SERVICE_NAME">%1$s</xliff:g> کو آن کر دیا"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"ایکسیسبیلٹی شارٹ کٹ نے <xliff:g id="SERVICE_NAME">%1$s</xliff:g> کو آف کر دیا"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> کا استعمال کرنے کے لیے 3 سیکنڈ تک والیوم کی دونوں کلیدوں کو چھوئیں اور دبائے رکھیں"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"ایکسیسبیلٹی بٹن پر تھپتھپانے وقت استعمال کرنے کیلئے ایک سروس چنیں:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"ایکسیسبیلٹی اشارہ کے ساتھ استعمال کرنے کے لیے ایک سروس چنیں (دو انگلیوں سے اسکرین کے نیچے سے اوپر کی طرف سوائپ کریں):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"ایکسیسبیلٹی اشارہ کے ساتھ استعمال کرنے کے لیے ایک سروس چنیں (تین انگلیوں سے اسکرین کے نیچے سے اوپر کی طرف سوائپ کریں):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"سروسز کے مابین سوئچ کرنے کے لیے، ایکسیسبیلٹی بٹن کو ٹچ کرکے ہولڈ کریں۔"</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"سروسز کے مابین سوئچ کرنے کے لیے، دو انگلیوں سے اوپر سوائپ کرکے ہولڈ کریں۔"</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"سروسز کے مابین سوئچ کرنے کے لیے، تین انگلیوں سے اوپر سوائپ کرکے ہولڈ کریں۔"</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>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> سے منسلک"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"فائلوں کو دیکھنے کیلئے تھپتھپائیں"</string>
<string name="pin_target" msgid="8036028973110156895">"پن کریں"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"<xliff:g id="LABEL">%1$s</xliff:g> کو پن کریں"</string>
<string name="unpin_target" msgid="3963318576590204447">"پن ہٹائیں"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"<xliff:g id="LABEL">%1$s</xliff:g> سے پن ہٹائیں"</string>
<string name="app_info" msgid="6113278084877079851">"ایپ کی معلومات"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"ڈیمو شروع ہو رہا ہے…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"ان آئٹمز کو "<b>"<xliff:g id="LABEL">%4$s</xliff:g> "</b>" میں اپ ڈیٹ کریں: <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> ؟"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"محفوظ کریں"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"نہیں، شکریہ"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"ابھی نہیں"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"کبھی نہیں"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"اپ ڈیٹ کریں"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"جاری رکھیں"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"پاس ورڈ"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"اسپلٹ اسکرین ٹوگل کریں"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"مقفل اسکرین"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"اسکرین شاٹ"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"پوپ-اپ ونڈو میں <xliff:g id="APP_NAME">%1$s</xliff:g> ایپ۔"</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> کی کیپشن بار۔"</string>
</resources>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index c7987d1b3410..744f54dba133 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Ishchi profilning administrator ilovasi yo‘q yoki buzilgan. Shuning uchun, ishchi profilingiz va unga aloqador ma’lumotlar o‘chirib tashlandi. Yordam olish uchun administratoringizga murojaat qiling."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Bu qurilmada endi ishchi profilingiz mavjud emas"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Parol ko‘p marta xato kiritildi"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Administrator shaxsiy foydalanishga qoldirilgan qurilmani rad etdi"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Bu – boshqariladigan qurilma"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Tashkilotingiz bu qurilmani boshqaradi va tarmoq trafigini nazorat qilishi mumkin. Tafsilotlar uchun bosing."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Qurilmangizdagi ma’lumotlar o‘chirib tashlanadi"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Ilova yuborilganidan keyin oʻchib ketmaydigan muddatsiz tarqatma xabarlarni yuborishi mumkin. Ulardan notoʻgʻri maqsadda foydalanish qurilmaning ishlashini sekinlatishi yoki xotiraga haddan ziyod yuklanish tushishi oqibatida qurilma ishdan chiqishi mumkin."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Ilova yuborilganidan keyin o‘chib ketmaydigan muddatsiz tarqatma xabarlarni yuborishi mumkin. Ulardan noto‘g‘ri maqsadda foydalanish qurilmaning ishlashini sekinlatishi yoki xotiraga haddan ziyod yuklanish tushishi oqibatida qurilma ishdan chiqishi mumkin."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"kontaktlaringizni ko‘rish"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Ilovaga planshetingizda saqlangan kontaktlar ma’lumotlarini, shuningdek, ba‘zi shaxslarga qilgan qo‘ng‘iroqlar muntazamligi, ularga yozgan e-pochta xabarlari yoki boshqa xabar almashish yo‘llari orqali xabarlashganingiz haqidagi ma’lumotlarni o‘qishga ruxsat beradi. Ushbu ruxsat ilovalarga aloqa ma’lumotlaringizni saqlash uchun ruxsat beradi va zararli ilovalar sizga bildirmasdan kontaktlar ma’lumotlaringizni boshqalarga ulashishi mumkin."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Ilovaga Android TV qurilmangizdagi kontaktlar haqidagi axborotni, jumladan, muayyan shaxslar bilan chaqiruv, email orqali xabarlashish yoki muloqot qilish takroriyligi haqidagi axborotni oʻqish huquqini beradi. Bu ruxsat ilovalarga kontaktlaringizga oid axborotni saqlash huquqini berib, zararli ilovalar uning yordamida kontakt maʼlumotlarini sizdan beruxsat boshqalarga ulashishi mumkin."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Ilovaga telefoningizda saqlangan kontaktlar ma’lumotlarini, shuningdek, ba‘zi shaxslarga qilgan qo‘ng‘iroqlar muntazamligi, ularga yozgan e-pochta xabarlari yoki boshqa xabar almashish yo‘llari orqali xabarlashganingiz haqidagi ma’lumotlarni o‘qishga ruxsat beradi. Ushbu ruxsat ilovalarga kontaktlar ma’lumotlaringizni saqlash uchun ruxsat beradi va zararli ilovalar sizga bildirmasdan aloqa ma’lumotlaringizni boshqalarga ulashishi mumkin."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Bu planshetga telefoningizdagi kontaktlarga oid axborotni oʻqish huquqini beradi. Ilovalar ham planshetdagi kontaktlarni yaratgan hisoblaringizga ruxsat oladi Jumladan, oʻrnatilgan ilovalar ochgan hisoblarga ham ruxsat beriladi. Bu ruxsat ilovalarga kontaktlaringizga oid axborotni saqlash huquqini berib, zararli ilovalar uning yordamida kontakt maʼlumotlarini sizdan beruxsat boshqalarga ulashishi mumkin."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Bu ilovaga Android TV qurilmangizdagi kontaktlarga oid axborotni oʻqish huquqini beradi. Ilovalar ham Android TV qurilmasidagi kontaktlarni yaratgan hisoblaringizga ruxsat oladi Jumladan, oʻrnatilgan ilovalar ochgan hisoblarga ham ruxsat beriladi. Bu ruxsat ilovalarga kontaktlaringizga oid axborotni saqlash huquqini berib, zararli ilovalar uning yordamida kontakt maʼlumotlarini sizdan beruxsat boshqalarga ulashishi mumkin."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Bu ilovaga telefoningizdagi kontaktlarga oid axborotni oʻqish huquqini beradi. Ilovalar ham telefondagi kontaktlarni yaratgan hisoblaringizga ruxsat oladi Jumladan, oʻrnatilgan ilovalar ochgan hisoblarga ham ruxsat beriladi. Bu ruxsat ilovalarga kontaktlaringizga oid axborotni saqlash huquqini berib, zararli ilovalar uning yordamida kontakt maʼlumotlarini sizdan beruxsat boshqalarga ulashishi mumkin."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"kontaktlaringizni tahrirlash"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Ilovaga planshetingizda saqlangan kontaktlar ma’lumotlarini, shuningdek, ba‘zi shaxslarga qilgan qo‘ng‘iroqlar muntazamligi, ularga yozgan e-pochta xabarlari yoki boshqa xabar almashish yo‘llari orqali xabarlashganingiz haqidagi ma’lumotlarni o‘zgartirishga ruxsat beradi. Ushbu ruxsat ilovalarga kontaktlar ma’lumotlarini o‘chirishga ruxsat beradi."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Ilovaga Android TV qurilmangizda saqlangan kontaktlar haqidagi axborotni, jumladan, muayyan kontakt bilan chaqiruv, email yoki boshqa usullar orqali muloqot qilish takroriyligini tahrirlash huquqini beradi. Bu ruxsat orqali ilovalar kontaktlar haqidagi axborotni oʻchirib tashlashi mumkin."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Ilovaga telefoningizda saqlangan kontaktlar ma’lumotlarini, shuningdek, ba‘zi shaxslarga qilgan qo‘ng‘iroqlar muntazamligi, ularga yozgan e-pochta xabarlari yoki boshqa xabar almashish yo‘llari orqali xabarlashganingiz haqidagi ma’lumotlarni o‘zgartirishga ruxsat beradi. Ushbu ruxsat ilovalarga kontaktlar ma’lumotlarini o‘chirishga ruxsat beradi."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Bu ilovaga planshetingizdagi kontaktlarga oid axborotni oʻzgartirish huquqini beradi. Bu ruxsat ilovalarga kontaktlarga oid axborotni oʻchirish imkonini ham beradi."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Bu ilovaga Android TV qurilmangizdagi kontaktlarga oid axborotni oʻzgartirish huquqini beradi. Bu ruxsat ilovalarga kontaktlarga oid axborotni oʻchirish imkonini ham beradi."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Bu ilovaga telefoningizdagi kontaktlarga oid axborotni oʻzgartirish huquqini beradi. Bu ruxsat ilovalarga kontaktlarga oid axborotni oʻchirish imkonini ham beradi."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"qo‘ng‘iroq jurnallarini o‘qish"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Bu ilova chaqiruvlar tarixini o‘qiy oladi."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"qo‘ng‘iroq jurnaliga yozish"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"qo‘shimcha manzillarga kirish buyruqlari"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Ilovaga qo‘shimcha joylashuv xizmati buyruqlaridan foydalanishga ruxsat beradi. Uning yordamida ilova GPS yoki boshqa joylashuv ma’lumoti manbalarining ishlashiga xalaqit qilishi mumkin."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"aniq joylashuv axborotini olishga faqat old fonda ruxsat"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Bu ilova faqat fon rejimida aniq joylashuv axborotingizdan foydalanishi mumkin. Ilova ushbu joylashuv xizmatlaridan foydalana olishi uchun ular telefoningizda yoniq turishi va ishlashi kerak. Bunda batareya sarfi oshishi mumkin."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"faqat faol rejimda taxminiy joylashuv axborotiga (tarmoq asosida) ruxsat"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Bu ilova faqat faol rejimda ekanida Wi-Fi va uyali tarmoq antennalari kabi tarmoq manbalari asosida joylashuvingiz axborotini olishi mumkin. Ilova ushbu joylashuv xizmatlaridan foydalana olishi uchun ular planshetingizda yoniq bo‘lishi va ishlashi kerak."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Bu ilova faqat faol rejimda ekanida Wi-Fi va uyali tarmoq antennalari kabi tarmoq manbalari asosida joylashuvingiz axborotini olishi mumkin. Ilova ushbu joylashuv xizmatlaridan foydalana olishi uchun ular Android TV qurilmangizda yoniq boʻlishi va ishlashi kerak."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Bu ilova faqat faol rejimda ekanida Wi-Fi va uyali tarmoq antennalari kabi tarmoq manbalari asosida joylashuvingiz axborotini olishi mumkin. Ilova ushbu joylashuv xizmatlaridan foydalana olishi uchun ular telefoningizda yoniq bo‘lishi va ishlashi kerak."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Bu ilova faqat fon rejimida aniq joylashuv axborotingizdan foydalanishi mumkin. Ilova joylashuv xizmatlaridan foydalana olishi uchun ular qurilmangizda yoniq turishi va ishlashi kerak. Bunda batareya sarfi oshishi mumkin."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"taxminiy joylashuv axborotini olishga faqat old fonda ruxsat"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Bu ilova faqat fon rejimida taxminiy joylashuv axborotingizdan foydalanishi mumkin. Ilova joylashuv xizmatlaridan foydalana olishi uchun ular avtomobilingizda yoniq boʻlishi va ishlashi kerak."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"fonda joylashuv axborotidan foydalanish"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Agar taxminiy yoki aniq joylashuv axborotiga qo‘shimcha tarzda ruxsat berilgan bo‘lsa, ilova ishlayotganda joylashuv axborotidan fonda foydalana oladi."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Bu ilova joylashuv axborotidan orqa fonda ham, old fonda ham foydalanishi mumkin."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"audio sozlamalaringizni o‘zgartirish"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Ilovalarga tovush va ovoz chiqarish uchun foydalaniladigan karnay kabi global audio sozlamalarini o‘zgartirish uchun ruxsat beradi."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"ovoz yozib olish"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Ilovaga planshetdagi Bluetooth‘ning sozlamasini ko‘rishga va bog‘langan qurilmalarga ulanish va ulardan ulanish so‘rovlarini qabul qulishga imkon beradi."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Ilovaga Android TV qurilmangizdagi Bluetooth sozlamasini koʻrishga va bogʻlangan qurilmalarga ulanish va ulardan ulanish talablarni qabul qilishga imkon beradi."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Ilovaga telefondagi Bluetooth‘ning sozlamasini ko‘rishga va bog‘langan qurilmalarga ulanish va ulardan ulanish so‘rovlarini qabul qulishga imkon beradi."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Asosiy NFC toʻlov xizmati haqidagi axborot"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Bu ilovaga asosiy NFC toʻlov xizmati haqidagi axborotni olish imkonini beradi (masalan, qayd qilingan AID identifikatorlari va marshrutning yakuniy manzili)."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"NFC modulini boshqarish"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Ilova qisqa masofali aloqa (NFC) texnologiyasi yordamida NFC yorliqlari, kartalar va o‘qish moslamalari bilan ma’lumot almashishi mumkin."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"ekran qulfini o‘chirib qo‘yish"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> xizmati yoqildi"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> xizmati o‘chirib qo‘yildi"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> xizmatidan foydalanish uchun ikkala ovoz balandligi tugmalarini uzoq bosib turing"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Maxsus imkoniyatlar tugmasi bosilganda ishga tushadigan xizmatni tanlang:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Maxsus imkoniyatlar ishorasi bilan ishga tushadigan xizmatni tanlang (2 barmoq bilan ekranning pastidan tepaga surib tortilganda):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Maxsus imkoniyatlar ishorasi bilan ishga tushadigan xizmatni tanlang (3 barmoq bilan ekranning pastidan tepaga surib tortilganda):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Xizmatlar orasida almashish uchun maxsus imkoniyatlar tugmasini bosib turing."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Xizmatlarni almashtirish uchun 2 barmoq bilan tepaga suring va bosib turing."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Xizmatlarni almashtirish uchun 3 barmoq bilan tepaga suring va bosib turing."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Kattalashtirish"</string>
<string name="user_switched" msgid="7249833311585228097">"Joriy foydalanuvchi <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="1912993630661332336">"Quyidagi foydalanuvchiga o‘tilmoqda: <xliff:g id="NAME">%1$s</xliff:g>…"</string>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> qurilmasiga ulandi"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Fayllarni ko‘rish uchun bosing"</string>
<string name="pin_target" msgid="8036028973110156895">"Qadash"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Mahkamlash: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Olib tashlash"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Olib tashlash: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Ilova haqida"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Demo boshlanmoqda…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291"><b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" xizmatidagi <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> va <xliff:g id="TYPE_2">%3$s</xliff:g> yangilansinmi?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Saqlash"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Kerak emas"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Keyinroq"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Hech qachon"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Yangilash"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Davom etish"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"parol"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Ekranni ikkiga ajratish tugmasi"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Ekran qulfi"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Skrinshot"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"<xliff:g id="APP_NAME">%1$s</xliff:g> ilovasi qalqib chiquvchi oynada."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> taglavhalar paneli."</string>
</resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 13c75f681a20..7e4e2644fb7f 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Ứng dụng quản trị hồ sơ công việc bị thiếu hoặc hỏng. Do vậy, hồ sơ công việc của bạn và dữ liệu liên quan đã bị xóa. Hãy liên hệ với quản trị viên của bạn để được trợ giúp."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Hồ sơ công việc của bạn không có sẵn trên thiết bị này nữa"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Quá nhiều lần nhập mật khẩu"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Quản trị viên đã từ bỏ quyền sở hữu thiết bị để cho phép dùng vào mục đích cá nhân"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Thiết bị được quản lý"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Tổ chức của bạn sẽ quản lý thiết bị này và có thể theo dõi lưu lượng truy cập mạng. Nhấn để biết chi tiết."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Thiết bị của bạn sẽ bị xóa"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Cho phép ứng dụng gửi nội dung truyền phát hấp dẫn người xem. Nội dung này sẽ vẫn còn sau khi quá trình truyền phát kết thúc. Việc sử dụng quá mức có thể làm cho thiết bị Android TV bị chậm hoặc không ổn định do việc sử dụng quá mức khiến thiết bị sử dụng quá nhiều bộ nhớ."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Cho phép ứng dụng gửi nội dung truyền phát hấp dẫn người xem. Nội dung này sẽ vẫn còn sau khi quá trình truyền phát kết thúc. Việc sử dụng quá mức có thể làm cho điện thoại bị chậm hoặc không ổn định do khiến điện thoại sử dụng quá nhiều bộ nhớ."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"đọc danh sách liên hệ của bạn"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Cho phép ứng dụng đọc dữ liệu về các liên hệ được lưu trữ trên máy tính bảng của bạn, bao gồm tần suất bạn đã gọi điện, gửi email hoặc liên lạc theo các cách khác với những người cụ thể. Quyền này cho phép ứng dụng lưu dữ liệu liên lạc của bạn và các ứng dụng độc hại có thể chia sẻ dữ liệu liên lạc mà bạn không biết."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Cho phép ứng dụng đọc dữ liệu về người liên hệ mà bạn lưu trên thiết bị Android TV, bao gồm cả tần suất bạn gọi điện, gửi email hoặc liên lạc theo cách khác với những cá nhân cụ thể. Quyền này cho phép ứng dụng lưu dữ liệu về người liên hệ của bạn, và các ứng dụng độc hại có thể chia sẻ dữ liệu về người liên hệ mà bạn không biết."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Cho phép ứng dụng đọc dữ liệu về các liên hệ được lưu trữ trên điện thoại của bạn, bao gồm tần suất bạn đã gọi điện, gửi email hoặc liên lạc theo các cách khác với những người cụ thể. Quyền này cho phép ứng dụng lưu dữ liệu liên lạc của bạn và các ứng dụng độc hại có thể chia sẻ dữ liệu liên lạc mà bạn không biết."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Cho phép ứng dụng đọc dữ liệu về người liên hệ mà bạn lưu trữ trên máy tính bảng của mình. Ứng dụng cũng sẽ có quyền truy cập vào các tài khoản đã tạo người liên hệ trên máy tính bảng của bạn. Đây có thể là các tài khoản do ứng dụng (bạn đã cài đặt) tạo. Quyền này cho phép ứng dụng lưu dữ liệu về người liên hệ của bạn và các ứng dụng độc hại có thể lén lút chia sẻ dữ liệu này."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Cho phép ứng dụng đọc dữ liệu về người liên hệ mà bạn lưu trữ trên thiết bị Android TV của mình. Ứng dụng cũng sẽ có quyền truy cập vào các tài khoản đã tạo người liên hệ trên thiết bị Android TV của bạn. Đây có thể là các tài khoản do ứng dụng (bạn đã cài đặt) tạo. Quyền này cho phép ứng dụng lưu dữ liệu về người liên hệ của bạn và các ứng dụng độc hại có thể lén lút chia sẻ dữ liệu này."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Cho phép ứng dụng đọc dữ liệu về người liên hệ mà bạn lưu trữ trên điện thoại. Ứng dụng cũng sẽ có quyền truy cập vào các tài khoản đã tạo người liên hệ trên điện thoại của bạn. Đây có thể là các tài khoản do ứng dụng (bạn đã cài đặt) tạo. Quyền này cho phép ứng dụng lưu dữ liệu về người liên hệ của bạn và các ứng dụng độc hại có thể lén lút chia sẻ dữ liệu này."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"sửa đổi danh sách liên hệ của bạn"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Cho phép ứng dụng sửa đổi dữ liệu về các địa chỉ liên hệ được lưu trữ trên máy tính bảng của bạn, bao gồm tần suất mà bạn đã gọi, gửi email hoặc liên lạc theo các cách khác với những địa chỉ liên hệ cụ thể. Quyền này cho phép ứng dụng xóa dữ liệu liên lạc."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Cho phép ứng dụng sửa đổi dữ liệu về người liên hệ mà bạn lưu trên thiết bị Android TV, bao gồm cả tần suất bạn gọi điện, gửi email hoặc liên lạc theo cách khác với những người liên hệ cụ thể. Quyền này cho phép ứng dụng xóa dữ liệu về người liên hệ."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Cho phép ứng dụng sửa đổi dữ liệu về các địa chỉ liên hệ được lưu trữ trên điện thoại của bạn, bao gồm tần suất mà bạn đã gọi, gửi email hoặc liên lạc theo các cách khác với những địa chỉ liên hệ cụ thể. Quyền này cho phép ứng dụng xóa dữ liệu liên lạc."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Cho phép ứng dụng sửa đổi dữ liệu về người liên hệ mà bạn lưu trữ trên máy tính bảng của mình. Quyền này cho phép ứng dụng xóa dữ liệu về người liên hệ."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Cho phép ứng dụng sửa đổi dữ liệu về người liên hệ mà bạn lưu trữ trên thiết bị Android TV. Quyền này cho phép ứng dụng xóa dữ liệu về người liên hệ."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Cho phép ứng dụng sửa đổi dữ liệu về người liên hệ mà bạn lưu trữ trên điện thoại của mình. Quyền này cho phép ứng dụng xóa dữ liệu về người liên hệ."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"đọc nhật ký cuộc gọi"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Ứng dụng này có thể đọc nhật ký cuộc gọi của bạn."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"ghi nhật ký cuộc gọi"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"truy cập vào các lệnh của nhà cung cấp vị trí bổ sung"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Cho phép ứng dụng truy cập vào các lệnh của nhà cung cấp vị trí bổ sung. Điều này có thể cho phép ứng dụng can thiệp vào hoạt động của Hệ thống định vị toàn cầu (GPS) hoặc các nguồn vị trí khác."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"chỉ truy cập vị trí chính xác trong nền trước"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Bất cứ khi nào chạy trong nền trước, ứng dụng này có thể nhận thông tin vị trí chính xác của bạn. Để ứng dụng có thể sử các dụng dịch vụ vị trí, điện thoại của bạn phải có các dịch vụ này và dịch vụ ở trạng thái bật. Hoạt động này có thể tăng mức tiêu thụ pin."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"chỉ truy cập vị trí gần đúng (dựa trên mạng) trong nền trước"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Bất cứ khi nào chạy trong nền trước, ứng dụng này có thể nhận thông tin vị trí dựa trên nguồn mạng, chẳng hạn như trạm phát sóng di động và mạng Wi-Fi. Để ứng dụng có thể dùng các dịch vụ vị trí, máy tính bảng của bạn phải có các dịch vụ này ở trạng thái bật."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Chỉ khi ở nền trước, ứng dụng này mới có thể nhận thông tin vị trí của bạn dựa trên các nguồn mạng, chẳng hạn như trạm phát sóng di động và mạng Wi-Fi. Bạn phải bật và sử dụng được các dịch vụ vị trí này trên thiết bị Android TV thì ứng dụng mới có thể dùng các dịch vụ đó."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Bất cứ khi nào chạy trong nền trước, ứng dụng này có thể nhận thông tin vị trí dựa trên nguồn mạng, chẳng hạn như trạm phát sóng di động và mạng Wi-Fi. Để ứng dụng có thể dùng các dịch vụ vị trí, điện thoại của bạn phải có các dịch vụ này ở trạng thái bật."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Ứng dụng này chỉ có thể nhận thông tin vị trí chính xác của bạn khi mở trên màn hình. Để ứng dụng có thể sử các dụng dịch vụ vị trí, thiết bị của bạn phải có các dịch vụ này và dịch vụ ở trạng thái bật. Hoạt động này có thể tăng mức tiêu thụ pin."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"chỉ truy cập thông tin vị trí gần đúng khi ứng dụng mở trên màn hình"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Ứng dụng này chỉ có thể nhận được thông tin vị trí gần đúng của bạn khi mở trên màn hình. Để ứng dụng có thể dùng các dịch vụ vị trí này, thiết bị của bạn phải có các dịch vụ này và dịch vụ ở trạng thái bật."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"truy cập vào vị trí trong nền"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Nếu bạn cấp cho ứng dụng quyền truy cập bổ sung vào vị trị gần đúng hoặc chính xác, thì ứng dụng có thể truy cập vào vị trí đó khi chạy trong nền."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Ngoài quyền truy cập vào thông tin vị trí khi mở trên màn hình, ứng dụng này còn có thể truy cập vào thông tin vị trí khi đang chạy trong nền."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"thay đổi cài đặt âm thanh của bạn"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Cho phép ứng dụng sửa đổi cài đặt âm thanh chung chẳng hạn như âm lượng và loa nào được sử dụng cho thiết bị ra."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"ghi âm"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Cho phép ứng dụng xem cấu hình của Bluetooth trên máy tính bảng và tạo và chấp nhận các kết nối với các thiết bị được ghép nối."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Cho phép ứng dụng xem cấu hình của Bluetooth trên thiết bị Android TV, đồng thời tạo và chấp nhận các kết nối với thiết bị được ghép nối."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Cho phép ứng dụng xem cấu hình của Bluetooth trên điện thoại, tạo và chấp nhận các kết nối với các thiết bị được ghép nối."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Thông tin về dịch vụ thanh toán qua công nghệ giao tiếp tầm gần (NFC) được ưu tiên"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Cho phép ứng dụng nhận thông tin về dịch vụ thanh toán qua công nghệ giao tiếp tầm gần mà bạn ưu tiên, chẳng hạn như các hình thức hỗ trợ đã đăng ký và điểm đến trong hành trình."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"kiểm soát Liên lạc trường gần"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Cho phép ứng dụng giao tiếp với thẻ Giao tiếp trường gần (NFC), thẻ và trình đọc."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"vô hiệu hóa khóa màn hình của bạn"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"Đã bật phím tắt trợ năng <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"Đã tắt phím tắt trợ năng <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Nhấn và giữ đồng thời cả hai phím âm lượng trong 3 giây để sử dụng <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Chọn dịch vụ sẽ sử dụng khi bạn nhấn vào nút hỗ trợ tiếp cận:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Chọn dịch vụ sẽ sử dụng với cử chỉ hỗ trợ tiếp cận này (vuốt lên từ cuối màn hình bằng 2 ngón tay):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Chọn dịch vụ sẽ sử dụng với cử chỉ hỗ trợ tiếp cận này (vuốt lên từ cuối màn hình bằng 3 ngón tay):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Để chuyển đổi giữa các dịch vụ, hãy chạm và giữ nút hỗ trợ tiếp cận."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Để chuyển đổi giữa các dịch vụ, hãy vuốt lên và giữ bằng 2 ngón tay."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Để chuyển đổi giữa các dịch vụ, hãy vuốt lên và giữ bằng 3 ngón tay."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Phóng to"</string>
<string name="user_switched" msgid="7249833311585228097">"Người dùng hiện tại <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="1912993630661332336">"Đang chuyển sang <xliff:g id="NAME">%1$s</xliff:g>…"</string>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Đã kết nối với <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Nhấn để xem tệp"</string>
<string name="pin_target" msgid="8036028973110156895">"Ghim"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Ghim <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Bỏ ghim"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Bỏ ghim <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Thông tin ứng dụng"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Đang bắt đầu bản trình diễn..."</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Cập nhật các mục này: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> và <xliff:g id="TYPE_2">%3$s</xliff:g> trong "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Lưu"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Không, cảm ơn"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Để sau"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Không bao giờ"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Cập nhật"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Tiếp tục"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"mật khẩu"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Bật/tắt chế độ chia đôi màn hình"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Khóa màn hình"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Chụp ảnh màn hình"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"Ứng dụng <xliff:g id="APP_NAME">%1$s</xliff:g> trong Cửa sổ bật lên."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Thanh phụ đề của <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 1df2a40c53ef..6abfda60a89c 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"工作资料管理应用缺失或损坏,因此系统已删除您的工作资料及相关数据。如需帮助,请与您的管理员联系。"</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"您的工作资料已不在此设备上"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"密码尝试次数过多"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"管理员已将该设备开放给个人使用"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"设备为受管理设备"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"贵单位会管理该设备,且可能会监控网络流量。点按即可了解详情。"</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"系统将清空您的设备"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"允许应用发送置顶广播,这类广播在广播结束后仍会继续存在。过度使用这项功能可能会导致 Android TV 设备使用过多内存,从而降低其运行速度或稳定性。"</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"允许该应用发送持久广播消息,此类消息在广播结束后仍会保留。过度使用可能会导致手机使用过多内存,从而降低其速度或稳定性。"</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"读取联系人"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"允许该应用读取您平板电脑上存储的联系人的相关数据,包括您通过打电话、发送电子邮件或以其他方式与特定个人通信的频率。此权限可让应用保存您的联系人数据,而恶意应用可能会在您不知情的情况下分享联系人数据。"</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"允许应用读取您的 Android TV 设备上存储的联系人相关数据,包括您与特定用户通话、发送电子邮件或通过其他方式进行通信的频率。此权限可让应用保存您的联系人数据,而恶意应用可能会在您不知情的情况下分享联系人数据。"</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"允许该应用读取您手机上存储的联系人的相关数据,包括您通过打电话、发送电子邮件或以其他方式与特定个人通信的频率。此权限可让应用保存您的联系人数据,而恶意应用可能会在您不知情的情况下分享联系人数据。"</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"允许该应用读取您的平板电脑上存储的联系人相关数据。应用还将有权访问您的平板电脑上已创建联系人的帐号,其中可能包括您已安装的应用所创建的帐号。此权限允许应用保存您的联系人数据,而恶意应用可能会在您不知情的情况下分享联系人数据。"</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"允许该应用读取您的 Android TV 设备上存储的联系人相关数据。应用还将有权访问您的 Android TV 设备上已创建联系人的帐号,其中可能包括您已安装的应用所创建的帐号。此权限允许应用保存您的联系人数据,而恶意应用可能会在您不知情的情况下分享联系人数据。"</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"允许该应用读取您手机上存储的联系人相关数据。应用还将有权访问您的手机上已创建联系人的帐号,其中可能包括您已安装的应用所创建的帐号。此权限允许应用保存您的联系人数据,而恶意应用可能会在您不知情的情况下分享联系人数据。"</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"修改您的通讯录"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"允许该应用修改您平板电脑上存储的联系人的相关数据,包括您通过打电话、发送电子邮件或以其他方式与特定联系人通信的频率。此权限可让应用删除联系人数据。"</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"允许应用修改您 Android TV 设备上存储的联系人相关数据,包括您与特定联系人通话、发送电子邮件或通过其他方式进行通信的频率。此权限可让应用删除联系人数据。"</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"允许该应用修改您手机上存储的联系人的相关数据,包括您通过打电话、发送电子邮件或以其他方式与特定联系人通信的频率。此权限可让应用删除联系人数据。"</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"允许该应用修改您平板电脑上存储的联系人相关数据。此权限允许应用删除联系人数据。"</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"允许该应用修改您的 Android TV 设备上存储的联系人相关数据。此权限允许应用删除联系人数据。"</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"允许该应用修改您手机上存储的联系人相关数据。此权限允许应用删除联系人数据。"</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"读取通话记录"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"此应用可读取您的通话记录。"</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"新建/修改/删除通话记录"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"获取额外的位置信息提供程序命令"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"允许该应用使用其他的位置信息提供程序命令。此权限使该应用可以干扰GPS或其他位置信息源的运作。"</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"只能在前台获取精确的位置信息"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"此应用只有在前台运行时才能获取您的精确位置信息。您的手机必须支持并开启这些位置信息服务,此应用才能使用这些服务。这可能会增加耗电量。"</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"只能在前台获取大概位置(基于网络)"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"此应用只能在前台根据网络来源(例如手机信号塔和 WLAN 网络)获取您的位置信息。您的平板电脑必须支持并开启这些位置信息服务,此应用才能使用这些服务。"</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"只要这个应用在前台运行,就可以根据网络来源(例如手机信号塔和 WLAN 网络)获取您的位置信息。您的 Android TV 设备必须支持并开启这些位置信息服务,此应用才能使用这些服务。"</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"此应用只能在前台根据网络来源(例如手机信号塔和 WLAN 网络)获取您的位置信息。您的手机必须支持并开启这些位置信息服务,此应用才能使用这些服务。"</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"此应用只有在前台运行时才能获取您的精确位置信息。您的设备必须支持并开启位置信息服务,此应用才能使用这些服务。这可能会增加耗电量。"</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"只有在前台运行时才能获取大致位置信息"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"此应用只有在前台运行时才能获取您的大致位置信息。您的设备必须支持并开启位置信息服务,此应用才能使用这些服务。"</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"在后台使用位置信息"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"如果另外授予大致位置信息或精确位置信息访问权限,该应用便可在后台运行时使用位置信息。"</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"此应用不仅在前台运行时可以获取位置信息,在后台运行时也能获取位置信息。"</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"更改您的音频设置"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"允许该应用修改全局音频设置,例如音量和用于输出的扬声器。"</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"录音"</string>
@@ -494,6 +491,8 @@
<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_preferredPaymentInfo" msgid="5274423844767445054">"首选 NFC 付款服务信息"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"允许应用获取首选 NFC 付款服务信息,例如注册的应用标识符和路线目的地。"</string>
<string name="permlab_nfc" msgid="1904455246837674977">"控制近距离通信"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"允许应用与近距离无线通信(NFC)标签、卡和读取器通信。"</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"停用屏幕锁定"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"无障碍快捷方式已开启<xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"无障碍快捷方式已关闭<xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"同时按住两个音量键 3 秒钟即可使用 <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"选择按“无障碍”按钮后要使用的服务:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"选择要搭配无障碍手势(用两指从屏幕底部向上滑动)使用的服务:"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"选择要搭配无障碍手势(用三指从屏幕底部向上滑动)使用的服务:"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"要在多项服务之间切换,请轻触并按住“无障碍”按钮。"</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"要在多项服务之间切换,请用两指向上滑动并按住。"</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"要在多项服务之间切换,请用三指向上滑动并按住。"</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>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"已连接到<xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"点按即可查看文件"</string>
<string name="pin_target" msgid="8036028973110156895">"固定"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"将<xliff:g id="LABEL">%1$s</xliff:g>置顶"</string>
<string name="unpin_target" msgid="3963318576590204447">"取消固定"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"取消置顶<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"应用信息"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"正在启动演示模式…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"要在"<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"中更新<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>这些内容吗?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"保存"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"不用了"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"以后再说"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"永不"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"更新"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"继续"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"密码"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"开启/关闭分屏"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"锁定屏幕"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"屏幕截图"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"以弹出式窗口形式打开的<xliff:g id="APP_NAME">%1$s</xliff:g>应用。"</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g>的标题栏。"</string>
</resources>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index d4d1f7c0d2b3..d01e8e787f47 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"工作設定檔管理員應用程式已遺失或損毀。因此,您的工作設定檔和相關資料已刪除。請聯絡您的管理員以取得協助。"</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"您的工作設定檔無法再在此裝置上使用"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"密碼輸入錯誤的次數過多"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"管理員已開放裝置供個人使用"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"裝置已受管理"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"您的機構會管理此裝置,並可能會監控網絡流量。輕按即可瞭解詳情。"</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"您的裝置將被清除"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"允許應用程式傳送置頂廣播,並在廣播結束後仍然繼續。過度使用會佔用大量記憶體,可能會令 Android TV 減慢運行速度或無法穩定運行。"</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"允許應用程式傳送在廣播結束後仍繼續存在的記憶廣播。過度使用可能會促使手機過度使用記憶體,因而拖慢運行速度或造成不穩定。"</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"讀取您的通訊錄"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"允許應用程式讀取平板電腦上儲存的聯絡人資料,包括您與個別聯絡人通話、電郵或以其他通訊方式聯絡的頻率。這項權限允許應用程式儲存您的聯絡人資料,而惡意應用程式也可能在您不知情下擅自共用聯絡人資料。"</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"允許應用程式讀取儲存在 Android TV 裝置上的聯絡人資料,包括您與特定聯絡人通話、傳送電郵或以其他通訊方式聯絡的頻率。這項權限允許應用程式儲存您的聯絡人資料,而惡意應用程式也可能在您不知情時擅自共用聯絡資料。"</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"允許應用程式讀取手機上儲存的聯絡人資料,包括您與個別聯絡人通話、電郵或以其他通訊方式聯絡的頻率。這項權限允許應用程式儲存您的聯絡人資料,而惡意應用程式也可能在您不知情下擅自共用聯絡人資料。"</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"允許應用程式讀取儲存在平板電腦上的聯絡人資料。應用程式亦可存取平板電腦上已建立聯絡人的帳戶,其中可能包括已安裝應用程式所建立的帳戶。這項權限允許應用程式儲存您的聯絡人資料,而惡意應用程式也可能在您不知情時擅自共用聯絡資料。"</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"允許應用程式讀取儲存在 Android TV 裝置上的聯絡人資料。應用程式亦可存取 Android TV 裝置上已建立聯絡人的帳戶,其中可能包括已安裝應用程式所建立的帳戶。這項權限允許應用程式儲存您的聯絡人資料,而惡意應用程式也可能在您不知情時擅自共用聯絡資料。"</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"允許應用程式讀取儲存在手機上的聯絡人資料。應用程式亦可存取手機上已建立聯絡人的帳戶,其中可能包括已安裝應用程式所建立的帳戶。這項權限允許應用程式儲存您的聯絡人資料,而惡意應用程式也可能在您不知情時擅自共用聯絡資料。"</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"修改您的通訊錄"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"允許應用程式修改平板電腦上儲存的聯絡人資料,包括您與個別聯絡人通話、電郵或以其他通訊方式聯絡的頻率。這項權限允許應用程式刪除聯絡人資料。"</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"允許應用程式修改儲存在 Android TV 裝置上的聯絡人資料,包括您與特定聯絡人通話、傳送電郵或以其他通訊方式聯絡的頻率。這項權限允許應用程式刪除聯絡資料。"</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"允許應用程式修改手機上儲存的聯絡人資料,包括您與個別聯絡人通話、電郵或以其他通訊方式聯絡的頻率。這項權限允許應用程式刪除聯絡人資料。"</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"允許應用程式修改儲存在平板電腦上的聯絡人資料。這項權限允許應用程式刪除聯絡人資料。"</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"允許應用程式修改儲存在 Android TV 裝置上的聯絡人資料。這項權限允許應用程式刪除聯絡人資料。"</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"允許應用程式修改儲存在手機上的聯絡人資料。這項權限允許應用程式刪除聯絡人資料。"</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"讀取通話記錄"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"此應用程式可以讀取您的通話記錄。"</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"寫入通話記錄"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"接收額外的位置提供者指令"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"允許應用程式存取額外的位置提供者指令。這項設定可能會使應用程式干擾 GPS 或其他位置來源的運作。"</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"只在前景存取精確位置"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"此應用程式只可在前台運行時獲取您的確實位置資訊。您的手機必須支援並啟用這些定位服務,應用程式方可使用這項功能,但這樣做可能會增加耗電量。"</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"只可在前景存取大概位置 (根據網絡定位)"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"此應用程式只能在前景中根據網絡來源 (例如手機訊號發射塔和 Wi-Fi 網絡) 獲取您的位置資訊。您必須在平板電腦上開啟這些定位服務,才能讓此應用程式使用位置資訊。"</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"此應用程式只能在前景中根據網絡來源 (例如手機訊號發射塔和 Wi-Fi 網絡) 獲取您的位置資訊。您必須在適用的 Android TV 裝置上開啟這些定位服務,才能讓此應用程式使用位置資訊。"</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"此應用程式只能在前景中根據網絡來源 (例如手機訊號發射塔和 Wi-Fi 網絡) 獲取您的位置資訊。您必須在手機上開啟這些定位服務,才能讓此應用程式使用位置資訊。"</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"此應用程式只可在前景執行時獲取您的確實位置資訊。您的裝置必須支援並已啟用定位服務,應用程式才能使用此功能。不過,這樣做可能會增加耗電量。"</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"只在前景存取大概位置"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"此應用程式只可在前景執行時獲取您的大概位置資訊。您的裝置必須支援並已啟用定位服務,應用程式才能使用此功能。"</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"在背景存取位置資訊"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"如果您另外授予概略位置或精確位置的存取權,這個應用程式在背景運行時將可存取位置資訊。"</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"此應用程式除了可在前景存取位置資訊外,亦可在背景中存取位置。"</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"更改音效設定"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"允許應用程式修改全域音頻設定,例如音量和用於輸出的喇叭。"</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"錄製音效"</string>
@@ -494,6 +491,8 @@
<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_preferredPaymentInfo" msgid="5274423844767445054">"首選 NFC 付款服務資訊"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"允許應用程式取得首選 NFC 付款服務的資訊 (如已註冊的付款輔助和最終付款對象)。"</string>
<string name="permlab_nfc" msgid="1904455246837674977">"控制近距離無線通訊"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"允許應用程式使用近距離無線通訊 (NFC) 標記、卡片及讀取程式進行通訊。"</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"停用螢幕上鎖"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"無障礙功能快速鍵已啟用 <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"無障礙功能快速鍵已停用 <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"㩒住兩個音量鍵 3 秒就可以用 <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"請選擇輕按無障礙功能按鈕時使用的服務:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"請選擇透過無障礙手勢 (使用兩隻手指從螢幕底部向上滑動) 使用的服務:"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"請選擇透過無障礙手勢 (使用三隻手指從螢幕底部向上滑動) 使用的服務:"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"如要在服務之間切換,請按住無障礙功能按鈕。"</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"如要在服務之間切換,請使用兩隻手指向上滑動並按住。"</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"如要在服務之間切換,請使用三隻手指向上滑動並按住。"</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>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"已連線至 <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"輕按即可查看檔案"</string>
<string name="pin_target" msgid="8036028973110156895">"固定"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"將<xliff:g id="LABEL">%1$s</xliff:g>置頂"</string>
<string name="unpin_target" msgid="3963318576590204447">"取消固定"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"取消將<xliff:g id="LABEL">%1$s</xliff:g>置頂"</string>
<string name="app_info" msgid="6113278084877079851">"應用程式資料"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"正在開始示範…"</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"要在 "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" 中更新<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>嗎?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"儲存"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"不用了,謝謝"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"暫時不要"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"永不"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"更新"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"繼續"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"密碼"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"切換分割螢幕"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"將畫面上鎖"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"螢幕截圖"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」應用程式在彈出式視窗中顯示。"</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」的說明列。"</string>
</resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 9997b68198d1..15aaec1e1f27 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"工作資料夾管理員應用程式遺失或已毀損,因此系統刪除了你的工作資料夾和相關資料。如需協助,請與你的管理員聯絡。"</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"你的工作資料夾已不在這個裝置上"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"密碼輸入錯誤的次數過多"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"管理員將這部裝置開放給個人使用"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"裝置受到管理"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"貴機構會管理這個裝置,且可能監控網路流量。輕觸即可瞭解詳情。"</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"你的裝置資料將遭到清除"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"允許應用程式傳送記憶廣播,這類廣播在廣播動作結束後仍繼續存在。請注意,過度使用這項功能可能會使得 Android TV 裝置占用過多記憶體,導致系統的執行速度變慢或穩定性降低。"</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"允許應用程式傳送記憶廣播,這類廣播在廣播動作結束後仍繼續存在。請注意,過度使用此功能可能導致手機使用過多的記憶體,導致手機的執行速度變慢或不穩定。"</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"讀取你的聯絡人"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"允許應用程式讀取平板電腦上儲存的聯絡人資料,包括你與特定聯絡人通話、傳送電子郵件或使用其他通訊方式的互動頻率。這項權限可讓應用程式儲存你的聯絡人資料,惡意應用程式也可能私自共用聯絡人資料。"</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"允許應用程式讀取 Android TV 裝置上儲存的聯絡人資料,包括你與特定使用者通話、傳送電子郵件或使用其他通訊方式的頻率。這項權限可讓應用程式儲存你的聯絡人資料,惡意應用程式也可能在你不知情的情況下洩露你的聯絡人資料。"</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"允許應用程式讀取手機上儲存的聯絡人資料,包括你與特定聯絡人通話、傳送電子郵件或使用其他通訊方式的互動頻率。這項權限可讓應用程式儲存你的聯絡人資料,惡意應用程式也可能私自共用聯絡人資料。"</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"允許應用程式讀取平板電腦上儲存的聯絡人資料。如果你已在平板電腦上的帳戶建立聯絡人,應用程式也將可以存取這些帳戶,當中可能包括你安裝的應用程式所建立的帳戶。這項權限可讓應用程式儲存你的聯絡人資料,惡意應用程式也可能在你不知情的情況下洩露你的聯絡人資料。"</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"允許應用程式讀取 Android TV 裝置上儲存的聯絡人資料。如果你已在 Android TV 裝置上的帳戶建立聯絡人,應用程式也將可以存取這些帳戶,當中可能包括你安裝的應用程式所建立的帳戶。這項權限可讓應用程式儲存你的聯絡人資料,惡意應用程式也可能在你不知情的情況下洩露你的聯絡人資料。"</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"允許應用程式讀取手機上儲存的聯絡人資料。如果你已在手機上的帳戶建立聯絡人,應用程式也將可以存取這些帳戶,當中可能包括你安裝的應用程式所建立的帳戶。這項權限可讓應用程式儲存你的聯絡人資料,惡意應用程式也可能在你不知情的情況下洩露你的聯絡人資料。"</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"修改你的聯絡人"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"允許應用程式讀取平板電腦上儲存的聯絡人資料,包括你與特定聯絡人通話、傳送電子郵件或使用其他通訊方式的互動頻率。這項權限可讓應用程式刪除聯絡人資料。"</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"允許應用程式修改 Android TV 裝置上儲存的聯絡人資料,包括你與特定聯絡人通話、傳送電子郵件或使用其他通訊方式的頻率。這項權限可讓應用程式刪除聯絡人資料。"</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"允許應用程式讀取手機上儲存的聯絡人資料,包括你與特定聯絡人通話、傳送電子郵件或使用其他通訊方式的互動頻率。這項權限可讓應用程式刪除聯絡人資料。"</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"允許應用程式修改平板電腦上儲存的聯絡人資料。這項權限可讓應用程式刪除聯絡人資料。"</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"允許應用程式修改 Android TV 裝置上儲存的聯絡人資料。這項權限可讓應用程式刪除聯絡人資料。"</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"允許應用程式修改手機上儲存的聯絡人資料。這項權限可讓應用程式刪除聯絡人資料。"</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"讀取通話記錄"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"這個應用程式可讀取通話記錄。"</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"寫入通話記錄"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"接收額外的位置提供者指令"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"允許應用程式存取額外位置資訊提供者指令。這項設定可能會造成應用程式干擾 GPS 或其他位置資訊來源的運作。"</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"僅可在前景中取得精確位置"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"這個應用程式只能在前景中取得你的確切位置。你必須在手機上開啟這些定位服務,才能讓這個應用程式取得確切位置。請注意,這麼做可能會增加耗電量。"</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"只有在前景執行時才能根據網路取得概略位置"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"只要這個應用程式在前景執行,就可以根據網路來源 (例如基地台和 Wi-Fi 網路) 取得你的位置資訊。如要讓這個應用程式使用定位服務,你必須在平板電腦上開啟這些服務。"</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"只要這個應用程式在前景執行,就可以根據網路來源 (例如基地台和 Wi-Fi 網路) 取得你的位置資訊。如要讓這個應用程式使用定位服務,你必須在 Android TV 裝置上開啟這些服務。"</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"只要這個應用程式在前景執行,就可以根據網路來源 (例如基地台和 Wi-Fi 網路) 取得你的位置資訊。如要讓這個應用程式使用定位服務,你必須在手機上開啟這些服務。"</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"這個應用程式只能在前景執行時取得你的確切位置。你必須在裝置上開啟定位服務,這個應用程式才能取得定位資訊。請注意,這麼做可能會增加耗電量。"</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"僅可在前景中取得概略位置"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"這個應用程式只能在前景執行時取得你的概略位置。你必須在裝置上開啟定位服務,這個應用程式才能取得定位資訊。"</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"在背景存取位置資訊"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"除了概略位置或精確位置的存取權外,若您另外授予這項存取權,這個應用程式就能在背景執行時存取位置資訊。"</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"這個應用程式在前景和背景執行時,皆可取得位置資訊。"</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"變更音訊設定"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"允許應用程式修改全域音訊設定,例如音量和用來輸出的喇叭。"</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"錄製音訊"</string>
@@ -494,6 +491,8 @@
<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_preferredPaymentInfo" msgid="5274423844767445054">"首選 NFC 付費服務資訊"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"允許應用程式取得首選 NFC 付費服務資訊,例如已註冊的輔助工具和路線目的地。"</string>
<string name="permlab_nfc" msgid="1904455246837674977">"控制近距離無線通訊"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"允許應用程式與近距離無線通訊 (NFC) 電子感應標籤、卡片及感應器進行通訊。"</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"停用螢幕鎖定"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"無障礙捷徑啟用了「<xliff:g id="SERVICE_NAME">%1$s</xliff:g>」"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"無障礙捷徑停用了「<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>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"選擇輕觸無障礙按鈕後要使用的服務:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"選擇要搭配無障礙手勢 (用兩指從螢幕底部向上滑動) 使用的服務:"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"選擇要搭配無障礙手勢 (用三指從螢幕底部向上滑動) 使用的服務:"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"如要切換不同的服務,請輕觸並按住無障礙按鈕。"</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"如要切換不同的服務,請用兩指向上滑動並按住。"</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"如要切換不同的服務,請用三指向上滑動並按住。"</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>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"已連線至 <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"輕觸即可查看檔案"</string>
<string name="pin_target" msgid="8036028973110156895">"固定"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"將「<xliff:g id="LABEL">%1$s</xliff:g>」固定"</string>
<string name="unpin_target" msgid="3963318576590204447">"取消固定"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"將「<xliff:g id="LABEL">%1$s</xliff:g>」取消固定"</string>
<string name="app_info" msgid="6113278084877079851">"應用程式資訊"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"正在啟動示範模式..."</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"要更新 "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" 中的<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>嗎?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"儲存"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"不用了,謝謝"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"暫時不要"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"永遠不要"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"更新"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"繼續"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"密碼"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"切換分割畫面模式"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"螢幕鎖定"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"擷取螢幕畫面"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」應用程式顯示在彈出式視窗中。"</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」的說明文字列。"</string>
</resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 5838a93890cf..ddaf38cd40c6 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -188,8 +188,7 @@
<string name="work_profile_deleted_details" msgid="3773706828364418016">"Uhlelo lokusebenza lokulawula lephrofayela yomsebenzi kungenzeka alukho noma lonakele. Njengomphumela, iphrofayela yakho yomsebenzi nedatha ehlobene isusiwe. Xhumana nomlawuli wakho ukuze uthole usizo."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Iphrofayela yakho yomsebenzi ayisatholakali kule divayisi"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Imizamo yamaphasiwedi eminingi kakhulu"</string>
- <!-- no translation found for device_ownership_relinquished (4080886992183195724) -->
- <skip />
+ <string name="device_ownership_relinquished" msgid="4080886992183195724">"Umphathi udedela idivayisi ngokusetshenziswa komuntu siqu"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Idivayisi iphethwe"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Inhlangano yakho iphethe le divayisi futhi kungenzeka ingaqaphi ithrafikhi yenethiwekhi. Thephela imininingwane."</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Idivayisi yakho izosulwa"</string>
@@ -381,13 +380,13 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Ivumela uhlelo lokusebenza ukuthi lithumele ukusakaza okunamathelayo, okusalayo ngemuva kokuphela kokusakaza. Ukusetshenziswa ngokweqile kungenza idivayisi yakho ye-Android TV ihambe kancane noma ingazinzi ngokuyenza ukuthi isebenzise imemori eningi kakhulu."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Ivumela uhlelo lokusebenza ukuthumela ukusakaza okunamathelayo, okusalayo emva kokuba ukusakazwa sekuphelile. Ukusebenzisa kakhulu kuhle kwenze ifoni ukuthi ingasheshi noma ingahlali kahle ngokuyibangela ukusebenzisa imemori eningi."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"funda oxhumana nabo"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="3792628955305119168">"Ivumela uhlelo lokusebenza ukufunda idatha mayelana noxhumana nabo abalondolozwe kuthebhulethi yakho, kufaka phakathi nobuningi obushayele, wathumela i-imeyili, noma oxhumene nabo ngezinye izindlela nomuntu oyedwa. Le mvume ivumela izinhlelo zokusebenza ukulondoloza idatha yoxhumana nabo, izinhlelo zokusebenza ezingalungile zingaba idatha yokuxhumana ngaphandle kolwazi lakho."</string>
- <string name="permdesc_readContacts" product="tv" msgid="2387823103274997441">"Ivumela uhlelo lokusebenza ukuthi lifunde idatha mayelana noxhumana nabo abangqinwe kudivayisi ye-Android TV, okufaka imvamisa oshaye ngayo, wathumela ama-imeyili, noma waxhumana ngezinye izindlela nabantu abathile. Le mvume ivumela izinhlelo zokusebenza ukuthi zilondoloze idatha yoxhumana nabo, futhi izinhlelo zokusebenza ezinobungozi zingabelana ngedatha yokuxhumana ngaphandle kolwazi lakho."</string>
- <string name="permdesc_readContacts" product="default" msgid="6938416250821270191">"Ivumela uhlelo lokusebenza ukufunda idatha mayelana noxhumana nabo abalondolozwe efonini yakho, kufaka phakathi nobuningi obushayele, wathumela i-imeyili, noma oxhumene nabo ngezinye izindlela nomuntu oyedwa. Le mvume ivumela izinhlelo zokusebenza ukulondoloza idatha yoxhumana nabo, izinhlelo zokusebenza ezingalungile zingaba idatha yokuxhumana ngaphandle kolwazi lakho."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Ivumela uhlelo lokusebenza ukufunda idatha mayelana noxhumana nabo abalondolozwe kuthebhulethi yakho. Izinhlelo zokusebenza zizophinda zibe nokufinyelela kuma-akhawunti akuthebulethi yakho adale oxhumana nabo. Lokhu kungafaka ama-akhawunti adalwe izinhlelo zokusebenza ozifakile. Le mvume ivumela izinhlelo zokusebenza ukuthi zilondoloze idatha yoxhumana nabo, kanye nezinhlelo zokusebenza ezinobungozi zingabelana ngedatha yoxhumana nabo ngaphandle kolwazi lwakho."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Ivumela uhlelo lokusebenza ukufunda idatha mayelana noxhumana nabo abalondolozwe kudivayisi yakho ye-Android TV. Izinhlelo zokusebenza zizophinda zibe nokufinyelela kuma-akhawunti kudivayisi yakho ye-Android TV adale oxhumana nabo. Lokhu kungafaka ama-akhawunti adalwe izinhlelo zokusebenza ozifakile. Le mvume ivumela izinhlelo zokusebenza ukuthi zilondoloze idatha yoxhumana nabo, kanye nezinhlelo zokusebenza ezinobungozi zingabelana ngedatha yoxhumana nabo ngaphandle kolwazi lwakho."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Ivumela uhlelo lokusebenza ukufunda idatha mayelana noxhumana nabo abalondolozwe efonini yakho. Izinhlelo zokusebenza zizophinda zibe nokufinyelela kuma-akhawunti akufoni yakho adale oxhumana nabo. Lokhu kungafaka ama-akhawunti adalwe izinhlelo zokusebenza ozifakile. Le mvume ivumela izinhlelo zokusebenza ukuthi zilondoloze idatha yoxhumana nabo, kanye nezinhlelo zokusebenza ezinobungozi zingabelana ngedatha yoxhumana nabo ngaphandle kolwazi lwakho."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"shintsha oxhumana nabo"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="4460252002098005534">"Ivumela uhlelo lokusebenza ukushintsha idatha mayelana noxhumana nabo abalondolozwe kuthebhulethi yakho, kufaka phakathi ubuningi bokushayela, ukuthumela i-imeyili, noma oxhumene nabo ngezinye izindlela. Le mvume ivumela izinhlelo zokusebenza ukususa idatha yoxhumana nabo."</string>
- <string name="permdesc_writeContacts" product="tv" msgid="3870937407268625273">"Ivumela uhlelo lokusebenza ukuguqula idatha emayelana noxhumana nabo abagcinwe kudivayisi yakho ye-Android TV yakho, okufaka imvamisa oshaye ngayo, wathumela ama-imeyili, noma waxhumana ngezinye izindlela noxhumana nabo abathile. Le mvume ivumela izinhlelo zokusebenza ukususa idatha yoxhumana nabo."</string>
- <string name="permdesc_writeContacts" product="default" msgid="4152877294201215490">"Ivumela uhlelo lokusebenza ukushintsha idatha mayelana noxhumana nabo abalondolozwe efonini yakho, kufaka phakathi ubuningi bokushayela, ukuthumela i-imeyili, noma oxhumene nabo ngezinye izindlela. Le mvume ivumela izinhlelo zokusebenza ukususa idatha yoxhumana nabo."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Ivumela uhlelo lokusebenza ukushintsha idatha mayelana noxhumana nabo abalondolozwe kuthebhulethi yakho. Le mvume ivumela izinhlelo zokusebenza ukususa idatha yoxhumana nabo."</string>
+ <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Ivumela uhlelo lokusebenza ukushintsha idatha mayelana noxhumana nabo abalondolozwe kudivayisi yakho ye-Android. Le mvume ivumela izinhlelo zokusebenza ukususa idatha yoxhumana nabo."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Ivumela uhlelo lokusebenza ukushintsha idatha mayelana noxhumana nabo abalondolozwe efonini yakho. Le mvume ivumela izinhlelo zokusebenza ukususa idatha yoxhumana nabo."</string>
<string name="permlab_readCallLog" msgid="1739990210293505948">"funda irekhodi lamakholi"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"Lolu hlelo lokusebenza lungafunda umlando wakho wekholi."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"bhala irekhodi lamakholi"</string>
@@ -407,13 +406,11 @@
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"finyelela kweminye imiyalo yokunikeza indawo"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Ivumela uhlelo lokusebenza ukufinyelela imiyalo eyengeziwe yabahlinzeki bendawo. Lokhu kungase kuvumele uhlelo lokusebenza ukuthi liphazamisane nomsebenzi we-GPS noma eminye imithombo yendawo."</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"finyelela indawo eqondile kuphela phambili"</string>
- <string name="permdesc_accessFineLocation" msgid="3056141052532120237">"Lolu hlelo lokusebenza lungakutholela indawo eqondile kuphela uma liphambili. Lawa masevisi endawo kufanele avulwe futhi atholakale efonini yakho ukuze uhlelo lokusebenza lukwazi ukuwasebenzisa. Lokhu kungakhulisa ukusebenza kwebhethri."</string>
- <string name="permlab_accessCoarseLocation" msgid="8215351553392299056">"finyelela indawo eseduze (esuselwa kunethiwekhi) kuphela ngaphambili"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="7479449026750078899">"Lolu hlelo lokusebenza lungathola indawo yakho kusukela kumithombo yenethiwekhi efana nezinqaba zeselula namanethiwekhi e-Wi-Fi, kodwa kuphela uma uhlelo lokusebenza lungaphambili. Lawa masevisi endawo kumele avulwe futhi atholakale kuthebulethi yakho ukuze uhlelo lokusebenza lukwazi ukuwasebenzisa."</string>
- <string name="permdesc_accessCoarseLocation" product="tv" msgid="6994518594789550469">"Lolu hlelo lokusebenza lungathola indawo yakho kusukela kumithombo yenethiwekhi efana nezinqaba zeselula namanethiwekhi e-Wi-Fi, kodwa kuphela uma uhlelo lokusebenza lungaphambili. Lawa masevisi endawo kumele avulwe futhi atholakale kudivayisi yakho ye-Android TV ukuze uhlelo lokusebenza lukwazi ukuwasebenzisa."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8962998102400124341">"Lolu hlelo lokusebenza lungathola indawo yakho kusukela kumithombo yenethiwekhi efana nezinqaba zeselula kanye namanethiwekhi e-Wi-Fi, kodwa kuphela uma uhlelo lokusebenza lungaphambili. Lawa masevisi endawo kumele avulwe futhi atholakale kufoni yakho ukuze uhlelo lokusebenza lukwazi ukuwasebenzisa."</string>
+ <string name="permdesc_accessFineLocation" msgid="9221079523494157324">"Lolu hlelo lokusebenza lungakutholela indawo eqondile kuphela uma liphambili. Amasevisi endawo kufanele avulwe futhi atholakale kudivayisi yakho ukuze uhlelo lokusebenza lukwazi ukuwasebenzisa. Lokhu kungakhulisa ukusebenza kwebhethri."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"finyelela indawo enembile kuphela engaphambili"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="4826281078353537786">"Lolu hlelo lokusebenza lungakutholela indawo enembile kuphela uma ingaphambili. Amasevisi endawo kumele avulwe futhi atholakale kudivayisi yakho ukuze uhlelo lokusebenza lukwazi ukuwasebenzisa."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"finyelela kundawo ngemuva"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="6904788108073882096">"Uma lokhu kunikezwa ngokungeziwe ekufinyeleleni okulinganiselwe noma okunembile kwendawo uhlelo lokusebenza lungafinyelela kundawo ngenkathi lusebenza ngemuva."</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Lolu hlelo lokusebenza lungafinyelela indawo ngenkathi isebenza ngasemuva, ngokungeziwe ekufinyeleleni kwendawo yangaphambili."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"shintsha izilungiselelo zakho zomsindo"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Ivumela uhlelo lokusebenza ukushintsha izilungiselelo zomsindo we-global njengevolomu nokuthi isiphi isipika esisetshenziselwa okukhiphayo."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"qopha umsindo"</string>
@@ -494,6 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Ivumela uhlelo lokusebenza ukubuka ukucushwa kwe-Bluetooth kuthebhulethi, nokwenza futhi nokwamukela uxhumo namadivayisi amatanisiwe."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Ivumela uhlelo lokusebenza ukubuka ukucushwa kwe-Bluetooth kudivayisi ye-Android TV, nokwenza futhi nokwamukela uxhumo namadivayisi abhangqiwe."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Ivumela uhlelo lokusebenza ukubuka ukucushwa kwe-Bluetooth efonini, ukwenza futhi nokwamukela uxhumo namadivayisi amatanisiwe."</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Ulwazi Lwesevisi Yenkokhelo Ye-NFC Okhethwayo"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Ivuemela uhlelo lokusebenza ukuthola ulwazi lesevisi yenkokhelo ye-nfc njengezinsiza zokubhalisa nezindawo zomzila."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"lawula Uxhumano Lwenkambu Eseduze"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Ivuela uhlelo lokusebenza ukuthi ixhumane ne-Near Field Communication (NFC) amathegi, amakhadi kanye nezinhlelo zokufunda."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"khubaza ukukhiya kwakho iskrini"</string>
@@ -1618,12 +1617,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"Isinqamuleli sokufinyelela sivule i-<xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"Isinqamuleli sokufinyelela sivale i-<xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Cindezela uphinde ubambe bobabili okhiye bevolumu ngamasekhondi amathathu ukuze usebenzise i-<xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Khetha isevisi ozoyisebenzisa uma uthepha inkinobho yokufinyeleleka:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Khetha isevisi ezosetshenziswa ngokuthinta kokufinyeleleka (swayiphela phezulu kusukela ngaphansi kwesikrini ngeminwe emibili):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Khetha isevisi ozoyisebenzisa ngokuthinta kokufinyeleleka (swayiphela phezulu kusukela ngaphansi kwesikrini ngeminwe emithathu):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Ukuze ushintshe phakathi kwamasevisi, thinta uphinde ubambe inkinobho yokufinyeleleka."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Ukuze ushintshe phakathi kwamasevisi, swayiphela phezulu ngeminwe emibili uphinde ubambe."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Ukuze ushintshe phakathi kwamasevisi, swayiphela phezulu ngeminwe emithathu uphinde ubambe."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Ukukhuliswa"</string>
<string name="user_switched" msgid="7249833311585228097">"Umsebenzisi wamanje <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="1912993630661332336">"Ishintshela ku-<xliff:g id="NAME">%1$s</xliff:g>…"</string>
@@ -1862,7 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Kuxhumekile ku-<xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Thepha ukuze ubuke onke amafayela"</string>
<string name="pin_target" msgid="8036028973110156895">"Phina"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"Iphinikhodi engu-<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Susa ukuphina"</string>
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Susa ukuphina ku-<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Ulwazi lohlelo lokusebenza"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Iqalisa i-demo..."</string>
@@ -1905,6 +1900,8 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"Buyekeza lezi zinto ku-"<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, ne-<xliff:g id="TYPE_2">%3$s</xliff:g> ?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Londoloza"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Cha ngiyabonga"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"Hhayi manje"</string>
+ <string name="autofill_save_never" msgid="6821841919831402526">"Akusoze"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"Buyekeza"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"Qhubeka"</string>
<string name="autofill_save_type_password" msgid="5624528786144539944">"iphasiwedi"</string>
@@ -2000,5 +1997,5 @@
<string name="accessibility_system_action_toggle_split_screen_label" msgid="6626177163849387748">"Guqula ukuhlukanisa isikrini"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Khiya isikrini"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Isithombe-skrini"</string>
- <string name="accessibility_freeform_caption" msgid="7873194416838321119">"<xliff:g id="APP_NAME">%1$s</xliff:g> uhlelo lokusebenza kuwindi le-Pop-up."</string>
+ <string name="accessibility_freeform_caption" msgid="8377519323496290122">"Ibha yamazwibela we-<xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
</resources>
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 166cde0d7005..85f7d617352e 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -298,6 +298,9 @@
<!-- Additional flag from base permission type: this permission can be automatically
granted to the system telephony apps -->
<flag name="telephony" value="0x400000" />
+ <!-- Additional flag from base permission type: this permission can be automatically
+ granted to the system companion device manager service -->
+ <flag name="companion" value="0x800000" />
</attr>
<!-- Flags indicating more context for a permission group. -->
@@ -1753,6 +1756,12 @@
The default value is {@code false}. -->
<attr name="forceQueryable" format="boolean" />
+
+ <!-- If {@code true} indicates that this application is capable of presenting a unified
+ interface representing multiple profiles.
+
+ The default value is {@code false}. -->
+ <attr name="crossProfile" format="boolean" />
</declare-styleable>
<!-- The <code>permission</code> tag declares a security permission that can be
used to control access from other packages to specific components or
@@ -2494,6 +2503,30 @@
<enum name="hdr" value="2" />
</attr>
<attr name="forceQueryable" format="boolean" />
+ <!-- Indicates whether the activity wants the connected display to do minimal
+ post processing on the produced image or video frames. This will only be
+ requested if this activity's main window is visible on the screen.
+
+ <p> This setting should be used when low latency has a higher priority than
+ image enhancement processing (e.g. for games or video conferencing).
+
+ <p> If the Display sink is connected via HDMI, the device will begin to
+ send infoframes with Auto Low Latency Mode enabled and Game Content Type.
+ This will switch the connected display to a minimal image processing mode
+ (if available), which reduces latency, improving the user experience for
+ gaming or video conferencing applications. For more information,
+ see HDMI 2.1 specification.
+
+ <p> If the Display sink has an internal connection or uses some other
+ protocol than HDMI, effects may be similar but implementation-defined.
+
+ <p> The ability to switch to a mode with minimal post proessing may be
+ disabled by a user setting in the system settings menu. In that case,
+ this field is ignored and the display will remain in its current
+ mode.
+
+ <p> See {@link android.content.pm.ActivityInfo #preferMinimalPostProcessing} -->
+ <attr name="preferMinimalPostProcessing" format="boolean"/>
</declare-styleable>
<!-- The <code>activity-alias</code> tag declares a new
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 03f8ebd96884..9073a02e72d3 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2357,15 +2357,22 @@
<!-- Whether to only install system packages on a user if they're whitelisted for that user
type. These are flags and can be freely combined.
- 0 (0b000) - disable whitelist (install all system packages; no logging)
- 1 (0b001) - enforce (only install system packages if they are whitelisted)
- 2 (0b010) - log (log when a non-whitelisted package is run)
- 4 (0b100) - treat any package not mentioned in the whitelist file as implicitly whitelisted
- 8 (0b1000) - ignore OTAs (don't install system packages during OTAs)
+ 0 - disable whitelist (install all system packages; no logging)
+ 1 - enforce (only install system packages if they are whitelisted)
+ 2 - log (log when a non-whitelisted package is run)
+ 4 - any package not mentioned in the whitelist file is implicitly whitelisted on all users
+ 8 - same as 4, but just for the SYSTEM user
+ 16 - ignore OTAs (don't install system packages during OTAs)
+ Common scenarios:
+ - to enable feature (fully enforced) for a complete whitelist: 1
+ - to enable feature for an incomplete whitelist (so use implicit whitelist mode): 5
+ - to enable feature but implicitly whitelist for SYSTEM user to ease local development: 9
+ - to disable feature completely if it had never been enabled: 16
+ - to henceforth disable feature and try to undo its previous effects: 0
Note: This list must be kept current with PACKAGE_WHITELIST_MODE_PROP in
frameworks/base/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java -->
- <integer name="config_userTypePackageWhitelistMode">13</integer> <!-- 0b1101 -->
- <!-- TODO(b/143200798): Change to value 5, i.e. 0b0101, when b/143200798 is resolved. -->
+ <integer name="config_userTypePackageWhitelistMode">29</integer> <!-- 1+4+8+16 -->
+ <!-- TODO(b/143200798): Change to value 13, i.e. 1+4+8, when b/143200798 is resolved. -->
<!-- Whether UI for multi user should be shown -->
<bool name="config_enableMultiUserUI">false</bool>
@@ -3553,18 +3560,26 @@
set to empty string), a default textclassifier will be loaded in the calling app's process.
See android.view.textclassifier.TextClassificationManager.
-->
+ <!-- TODO(b/144896755) remove the config -->
<string name="config_defaultTextClassifierPackage" translatable="false"></string>
- <!-- A list of the default system textclassifier service package name. Only one of the packages
- will be activated and the fist package is the default system textclassifier service. OS
- only tries to bind the first trusted service and the others can be selected via device
- config. These services must be trusted, as they can be activated without explicit consent
- of the user. Example: "com.android.textclassifier"
+ <!-- A list of supported system textClassifier service package names. Only one of the packages
+ will be activated. The first package in the list is the default system textClassifier
+ service. OS only tries to bind and grant permissions to the first trusted service and the
+ others can be selected via device config. These services must be trusted, as they can be
+ activated without explicit consent of the user. Example: "com.android.textclassifier"
-->
<string-array name="config_defaultTextClassifierPackages" translatable="false">
<item>android.ext.services</item>
</string-array>
+ <!-- The package name for the system companion device manager service.
+ This service must be trusted, as it can be activated without explicit consent of the user.
+ Example: "com.android.companiondevicemanager"
+ See android.companion.CompanionDeviceManager.
+ -->
+ <string name="config_companionDeviceManagerPackage" translatable="false"></string>
+
<!-- The package name for the default wellbeing app.
This package must be trusted, as it has the permissions to control other applications
on the device.
@@ -4246,6 +4261,10 @@
<!-- Add packages here -->
</string-array>
+ <!-- Whether or not wcg (wide color gamut) should be enabled on this device,
+ we only enabled it while the device has ability of mixed color spaces composition -->
+ <bool name="config_enableWcgMode">false</bool>
+
<!-- When true, enables the whitelisted app to handle bug reports from power menu short press. -->
<bool name="config_bugReportHandlerEnabled">false</bool>
@@ -4265,4 +4284,7 @@
value is left empty. When this is non-empty then config_rawContactsLocalAccountName
should also be non-empty.-->
<string name="config_rawContactsLocalAccountType" translatable="false"></string>
+
+ <!-- Whether or not to use assistant stream volume separately from music volume -->
+ <bool name="config_useAssistantVolume">false</bool>
</resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 9791241a52af..bf7558c8597a 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -760,6 +760,7 @@
<dimen name="chooser_edge_margin_normal">24dp</dimen>
<dimen name="chooser_preview_image_font_size">20sp</dimen>
<dimen name="chooser_preview_image_border">1dp</dimen>
+ <dimen name="chooser_preview_image_max_dimen">200dp</dimen>
<dimen name="chooser_preview_width">-1px</dimen>
<dimen name="chooser_target_width">90dp</dimen>
<dimen name="chooser_header_scroll_elevation">4dp</dimen>
@@ -772,4 +773,8 @@
<dimen name="resolver_small_margin">18dp</dimen>
<dimen name="resolver_edge_margin">24dp</dimen>
<dimen name="resolver_elevation">1dp</dimen>
+
+ <!-- Assistant handles -->
+ <dimen name="assist_handle_shadow_radius">2dp</dimen>
+
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 78c4efec5b72..0b6351860a02 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3007,8 +3007,6 @@
</public-group>
<public-group type="drawable" first-id="0x010800b5">
- <!-- @hide @SystemApi -->
- <public name="stat_notify_wifi_in_range" />
</public-group>
<public-group type="style" first-id="0x010302e5">
@@ -3019,11 +3017,11 @@
</public-group>
<public-group type="string" first-id="0x01040025">
- <!-- @hide @SystemApi -->
+ <!-- @hide -->
<public name="notification_channel_network_status" />
- <!-- @hide @SystemApi -->
+ <!-- @hide -->
<public name="notification_channel_network_alerts" />
- <!-- @hide @SystemApi -->
+ <!-- @hide -->
<public name="notification_channel_network_available" />
<!-- @hide @SystemApi -->
<public name="config_defaultCallRedirection" />
@@ -3051,6 +3049,10 @@
<public name="accessibilitySystemActionLockScreen" />
<public name="accessibilitySystemActionTakeScreenshot" />
</public-group>
+
+ <public-group type="attr" first-id="0x0101060c">
+ <public name="preferMinimalPostProcessing"/>
+ </public-group>
<!-- ===============================================================
DO NOT ADD UN-GROUPED ITEMS HERE
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index ab10738327b3..ed744ba9e50e 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1345,6 +1345,12 @@
connections with paired devices.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_preferredPaymentInfo">Preferred NFC Payment Service Information</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_preferredPaymentInfo">Allows the app to get preferred nfc payment service information like
+ registered aids and route destination.</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_nfc">control Near Field Communication</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_nfc">Allows the app to communicate
@@ -4377,20 +4383,6 @@
<string name="accessibility_shortcut_spoken_feedback">Press and hold both volume keys for three seconds to use
<xliff:g id="service_name" example="TalkBack">%1$s</xliff:g></string>
- <!-- Text appearing in a prompt at the top of UI allowing the user to select a target service or feature to be assigned to the Accessibility button in the navigation bar. -->
- <string name="accessibility_button_prompt_text">Choose a service to use when you tap the accessibility button:</string>
- <!-- Text appearing in a prompt at the top of UI allowing the user to select a target service or feature to be assigned to the Accessibility button when gesture navigation is enabled [CHAR LIMIT=none] -->
- <string name="accessibility_gesture_prompt_text">Choose a service to use with the accessibility gesture (swipe up from the bottom of the screen with two fingers):</string>
- <!-- Text appearing in a prompt at the top of UI allowing the user to select a target service or feature to be assigned to the Accessibility button when gesture navigation and TalkBack is enabled [CHAR LIMIT=none] -->
- <string name="accessibility_gesture_3finger_prompt_text">Choose a service to use with the accessibility gesture (swipe up from the bottom of the screen with three fingers):</string>
-
- <!-- Text describing how to display UI allowing a user to select a target service or feature to be assigned to the Accessibility button in the navigation bar. -->
- <string name="accessibility_button_instructional_text">To switch between services, touch &amp; hold the accessibility button.</string>
- <!-- Text describing how to display UI allowing a user to select a target service or feature to be assigned to the Accessibility button when gesture navigation is enabled. [CHAR LIMIT=none] -->
- <string name="accessibility_gesture_instructional_text">To switch between services, swipe up with two fingers and hold.</string>
- <!-- Text describing how to display UI allowing a user to select a target service or feature to be assigned to the Accessibility button when gesture navigation and TalkBack is enabled. [CHAR LIMIT=none] -->
- <string name="accessibility_gesture_3finger_instructional_text">To switch between services, swipe up with three fingers and hold.</string>
-
<!-- Text used to describe system navigation features, shown within a UI allowing a user to assign system magnification features to the Accessibility button in the navigation bar. -->
<string name="accessibility_magnification_chooser_text">Magnification</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index a8d30c120377..a00296c86a40 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -468,6 +468,7 @@
<java-symbol type="string" name="config_deviceSpecificAudioService" />
<java-symbol type="integer" name="config_num_physical_slots" />
<java-symbol type="array" name="config_integrityRuleProviderPackages" />
+ <java-symbol type="bool" name="config_useAssistantVolume" />
<java-symbol type="color" name="tab_indicator_text_v4" />
@@ -1341,6 +1342,7 @@
<java-symbol type="drawable" name="picture_emergency" />
<java-symbol type="drawable" name="platlogo" />
<java-symbol type="drawable" name="stat_notify_sync_error" />
+ <java-symbol type="drawable" name="stat_notify_wifi_in_range" />
<java-symbol type="drawable" name="ic_wifi_signal_0" />
<java-symbol type="drawable" name="ic_wifi_signal_1" />
<java-symbol type="drawable" name="ic_wifi_signal_2" />
@@ -2720,6 +2722,7 @@
<java-symbol type="layout" name="chooser_grid_preview_file" />
<java-symbol type="id" name="chooser_row_text_option" />
<java-symbol type="dimen" name="chooser_row_text_option_translate" />
+ <java-symbol type="dimen" name="chooser_preview_image_max_dimen"/>
<java-symbol type="integer" name="config_maxShortcutTargetsPerApp" />
<java-symbol type="layout" name="resolve_grid_item" />
<java-symbol type="id" name="day_picker_view_pager" />
@@ -3201,20 +3204,11 @@
<java-symbol type="string" name="accessibility_shortcut_spoken_feedback" />
<!-- Accessibility Button -->
- <java-symbol type="layout" name="accessibility_button_chooser" />
<java-symbol type="layout" name="accessibility_button_chooser_item" />
- <java-symbol type="id" name="accessibility_button_chooser_grid" />
- <java-symbol type="id" name="accessibility_button_prompt" />
- <java-symbol type="id" name="accessibility_button_prompt_prologue" />
<java-symbol type="id" name="accessibility_button_target_icon" />
<java-symbol type="id" name="accessibility_button_target_label" />
<java-symbol type="string" name="accessibility_magnification_chooser_text" />
- <java-symbol type="string" name="accessibility_gesture_prompt_text" />
- <java-symbol type="string" name="accessibility_gesture_3finger_prompt_text" />
- <java-symbol type="string" name="accessibility_gesture_instructional_text" />
- <java-symbol type="string" name="accessibility_gesture_3finger_instructional_text" />
-
<java-symbol type="drawable" name="ic_accessibility_magnification" />
<!-- com.android.internal.widget.RecyclerView -->
@@ -3787,7 +3781,15 @@
<java-symbol type="string" name="accessibility_freeform_caption" />
+ <!-- For Wide Color Gamut -->
+ <java-symbol type="bool" name="config_enableWcgMode" />
+
<!-- For contacts provider. -->
<java-symbol type="string" name="config_rawContactsLocalAccountName" />
<java-symbol type="string" name="config_rawContactsLocalAccountType" />
+
+ <!-- Assistant handles -->
+ <java-symbol type="dimen" name="assist_handle_shadow_radius" />
+
+
</resources>
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index c7e54f3fcd1b..1aea98a93afe 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -1399,6 +1399,7 @@
</activity>
<activity android:name="android.app.activity.ActivityThreadTest$TestActivity"
+ android:supportsPictureInPicture="true"
android:exported="true">
</activity>
diff --git a/core/tests/coretests/src/android/app/PullAtomMetadataTest.java b/core/tests/coretests/src/android/app/PullAtomMetadataTest.java
new file mode 100644
index 000000000000..2e3f8928d9c2
--- /dev/null
+++ b/core/tests/coretests/src/android/app/PullAtomMetadataTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.StatsManager.PullAtomMetadata;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public final class PullAtomMetadataTest {
+
+ @Test
+ public void testEmpty() {
+ PullAtomMetadata metadata = PullAtomMetadata.newBuilder().build();
+ assertThat(metadata.getTimeoutNs()).isEqualTo(StatsManager.DEFAULT_TIMEOUT_NS);
+ assertThat(metadata.getCoolDownNs()).isEqualTo(StatsManager.DEFAULT_COOL_DOWN_NS);
+ assertThat(metadata.getAdditiveFields()).isNull();
+ }
+
+ @Test
+ public void testSetTimeoutNs() {
+ long timeoutNs = 500_000_000L;
+ PullAtomMetadata metadata =
+ PullAtomMetadata.newBuilder().setTimeoutNs(timeoutNs).build();
+ assertThat(metadata.getTimeoutNs()).isEqualTo(timeoutNs);
+ assertThat(metadata.getCoolDownNs()).isEqualTo(StatsManager.DEFAULT_COOL_DOWN_NS);
+ assertThat(metadata.getAdditiveFields()).isNull();
+ }
+
+ @Test
+ public void testSetCoolDownNs() {
+ long coolDownNs = 10_000_000_000L;
+ PullAtomMetadata metadata =
+ PullAtomMetadata.newBuilder().setCoolDownNs(coolDownNs).build();
+ assertThat(metadata.getTimeoutNs()).isEqualTo(StatsManager.DEFAULT_TIMEOUT_NS);
+ assertThat(metadata.getCoolDownNs()).isEqualTo(coolDownNs);
+ assertThat(metadata.getAdditiveFields()).isNull();
+ }
+
+ @Test
+ public void testSetAdditiveFields() {
+ int[] fields = {2, 4, 6};
+ PullAtomMetadata metadata =
+ PullAtomMetadata.newBuilder().setAdditiveFields(fields).build();
+ assertThat(metadata.getTimeoutNs()).isEqualTo(StatsManager.DEFAULT_TIMEOUT_NS);
+ assertThat(metadata.getCoolDownNs()).isEqualTo(StatsManager.DEFAULT_COOL_DOWN_NS);
+ assertThat(metadata.getAdditiveFields()).isEqualTo(fields);
+ }
+
+ @Test
+ public void testSetAllElements() {
+ long timeoutNs = 300L;
+ long coolDownNs = 9572L;
+ int[] fields = {3, 2};
+ PullAtomMetadata metadata = PullAtomMetadata.newBuilder()
+ .setTimeoutNs(timeoutNs)
+ .setCoolDownNs(coolDownNs)
+ .setAdditiveFields(fields)
+ .build();
+ assertThat(metadata.getTimeoutNs()).isEqualTo(timeoutNs);
+ assertThat(metadata.getCoolDownNs()).isEqualTo(coolDownNs);
+ assertThat(metadata.getAdditiveFields()).isEqualTo(fields);
+ }
+}
diff --git a/core/tests/coretests/src/android/app/activity/ActivityManagerTest.java b/core/tests/coretests/src/android/app/activity/ActivityManagerTest.java
index bbd442d53f76..6c5d5485664e 100644
--- a/core/tests/coretests/src/android/app/activity/ActivityManagerTest.java
+++ b/core/tests/coretests/src/android/app/activity/ActivityManagerTest.java
@@ -16,7 +16,11 @@
package android.app.activity;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
+
import android.app.ActivityManager;
+import android.app.ActivityManager.TaskDescription;
import android.content.Context;
import android.content.pm.ConfigurationInfo;
import android.content.res.Configuration;
@@ -110,7 +114,123 @@ public class ActivityManagerTest extends AndroidTestCase {
assertNotNull(config.reqInputFeatures & ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD);
}
}
-
+
+ @SmallTest
+ public void testTaskDescriptionCopyFrom() {
+ TaskDescription td1 = new TaskDescription(
+ "test label", // label
+ null, // bitmap
+ 21, // iconRes
+ "dummy file", // iconFilename
+ 0x111111, // colorPrimary
+ 0x222222, // colorBackground
+ 0x333333, // statusBarColor
+ 0x444444, // navigationBarColor
+ true, // ensureStatusBarContrastWhenTransparent
+ true, // ensureNavigationBarContrastWhenTransparent
+ RESIZE_MODE_RESIZEABLE, // resizeMode
+ 10, // minWidth
+ 20 // minHeight
+ );
+
+ TaskDescription td2 = new TaskDescription();
+ // Must overwrite all the fields
+ td2.copyFrom(td1);
+
+ assertEquals(td1.getLabel(), td2.getLabel());
+ assertEquals(td1.getInMemoryIcon(), td2.getInMemoryIcon());
+ assertEquals(td1.getIconFilename(), td2.getIconFilename());
+ assertEquals(td1.getIconResource(), td2.getIconResource());
+ assertEquals(td1.getPrimaryColor(), td2.getPrimaryColor());
+ assertEquals(td1.getBackgroundColor(), td2.getBackgroundColor());
+ assertEquals(td1.getStatusBarColor(), td2.getStatusBarColor());
+ assertEquals(td1.getNavigationBarColor(), td2.getNavigationBarColor());
+ assertEquals(td1.getEnsureStatusBarContrastWhenTransparent(),
+ td2.getEnsureStatusBarContrastWhenTransparent());
+ assertEquals(td1.getEnsureNavigationBarContrastWhenTransparent(),
+ td2.getEnsureNavigationBarContrastWhenTransparent());
+ assertEquals(td1.getResizeMode(), td2.getResizeMode());
+ assertEquals(td1.getMinWidth(), td2.getMinWidth());
+ assertEquals(td1.getMinHeight(), td2.getMinHeight());
+ }
+
+ @SmallTest
+ public void testTaskDescriptionCopyFromPreserveHiddenFields() {
+ TaskDescription td1 = new TaskDescription(
+ "test label", // label
+ null, // bitmap
+ 21, // iconRes
+ "dummy file", // iconFilename
+ 0x111111, // colorPrimary
+ 0x222222, // colorBackground
+ 0x333333, // statusBarColor
+ 0x444444, // navigationBarColor
+ false, // ensureStatusBarContrastWhenTransparent
+ false, // ensureNavigationBarContrastWhenTransparent
+ RESIZE_MODE_UNRESIZEABLE, // resizeMode
+ 10, // minWidth
+ 20 // minHeight
+ );
+
+ TaskDescription td2 = new TaskDescription(
+ "test label2", // label
+ null, // bitmap
+ 212, // iconRes
+ "dummy file2", // iconFilename
+ 0x1111112, // colorPrimary
+ 0x2222222, // colorBackground
+ 0x3333332, // statusBarColor
+ 0x4444442, // navigationBarColor
+ true, // ensureStatusBarContrastWhenTransparent
+ true, // ensureNavigationBarContrastWhenTransparent
+ RESIZE_MODE_RESIZEABLE, // resizeMode
+ 102, // minWidth
+ 202 // minHeight
+ );
+
+ // Must overwrite all public and hidden fields, since other has all fields set.
+ td2.copyFromPreserveHiddenFields(td1);
+
+ assertEquals(td1.getLabel(), td2.getLabel());
+ assertEquals(td1.getInMemoryIcon(), td2.getInMemoryIcon());
+ assertEquals(td1.getIconFilename(), td2.getIconFilename());
+ assertEquals(td1.getIconResource(), td2.getIconResource());
+ assertEquals(td1.getPrimaryColor(), td2.getPrimaryColor());
+ assertEquals(td1.getBackgroundColor(), td2.getBackgroundColor());
+ assertEquals(td1.getStatusBarColor(), td2.getStatusBarColor());
+ assertEquals(td1.getNavigationBarColor(), td2.getNavigationBarColor());
+ assertEquals(td1.getEnsureStatusBarContrastWhenTransparent(),
+ td2.getEnsureStatusBarContrastWhenTransparent());
+ assertEquals(td1.getEnsureNavigationBarContrastWhenTransparent(),
+ td2.getEnsureNavigationBarContrastWhenTransparent());
+ assertEquals(td1.getResizeMode(), td2.getResizeMode());
+ assertEquals(td1.getMinWidth(), td2.getMinWidth());
+ assertEquals(td1.getMinHeight(), td2.getMinHeight());
+
+ TaskDescription td3 = new TaskDescription();
+ // Must overwrite only public fields, and preserve hidden fields.
+ td2.copyFromPreserveHiddenFields(td3);
+
+ // Overwritten fields
+ assertEquals(td3.getLabel(), td2.getLabel());
+ assertEquals(td3.getInMemoryIcon(), td2.getInMemoryIcon());
+ assertEquals(td3.getIconFilename(), td2.getIconFilename());
+ assertEquals(td3.getIconResource(), td2.getIconResource());
+ assertEquals(td3.getPrimaryColor(), td2.getPrimaryColor());
+ assertEquals(td3.getEnsureStatusBarContrastWhenTransparent(),
+ td2.getEnsureStatusBarContrastWhenTransparent());
+ assertEquals(td3.getEnsureNavigationBarContrastWhenTransparent(),
+ td2.getEnsureNavigationBarContrastWhenTransparent());
+
+ // Preserved fields
+ assertEquals(td1.getBackgroundColor(), td2.getBackgroundColor());
+ assertEquals(td1.getStatusBarColor(), td2.getStatusBarColor());
+ assertEquals(td1.getNavigationBarColor(), td2.getNavigationBarColor());
+ assertEquals(td1.getResizeMode(), td2.getResizeMode());
+ assertEquals(td1.getMinWidth(), td2.getMinWidth());
+ assertEquals(td1.getMinHeight(), td2.getMinHeight());
+ }
+
// If any entries in appear in the list, sanity check them against all running applications
private void checkErrorListSanity(List<ActivityManager.ProcessErrorStateInfo> errList) {
if (errList == null) return;
diff --git a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
index c50cbe3773ab..beaaa373b1a0 100644
--- a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
+++ b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
@@ -25,10 +25,12 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.testng.Assert.assertFalse;
import android.app.Activity;
import android.app.ActivityThread;
import android.app.IApplicationThread;
+import android.app.PictureInPictureParams;
import android.app.servertransaction.ActivityConfigurationChangeItem;
import android.app.servertransaction.ActivityRelaunchItem;
import android.app.servertransaction.ClientTransaction;
@@ -332,6 +334,50 @@ public class ActivityThreadTest {
assertThat(activity.isResumed()).isTrue();
}
+ @Test
+ public void testHandlePictureInPictureRequested_overriddenToEnter() {
+ final Intent startIntent = new Intent();
+ startIntent.putExtra(TestActivity.PIP_REQUESTED_OVERRIDE_ENTER, true);
+ final TestActivity activity = mActivityTestRule.launchActivity(startIntent);
+ final ActivityThread activityThread = activity.getActivityThread();
+
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+ activityThread.handlePictureInPictureRequested(activity.getActivityToken());
+ });
+
+ assertTrue(activity.pipRequested());
+ assertTrue(activity.enteredPip());
+ }
+
+ @Test
+ public void testHandlePictureInPictureRequested_overriddenToSkip() {
+ final Intent startIntent = new Intent();
+ startIntent.putExtra(TestActivity.PIP_REQUESTED_OVERRIDE_SKIP, true);
+ final TestActivity activity = mActivityTestRule.launchActivity(startIntent);
+ final ActivityThread activityThread = activity.getActivityThread();
+
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+ activityThread.handlePictureInPictureRequested(activity.getActivityToken());
+ });
+
+ assertTrue(activity.pipRequested());
+ assertTrue(activity.enterPipSkipped());
+ }
+
+ @Test
+ public void testHandlePictureInPictureRequested_notOverridden() {
+ final TestActivity activity = mActivityTestRule.launchActivity(new Intent());
+ final ActivityThread activityThread = activity.getActivityThread();
+
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+ activityThread.handlePictureInPictureRequested(activity.getActivityToken());
+ });
+
+ assertTrue(activity.pipRequested());
+ assertFalse(activity.enteredPip());
+ assertFalse(activity.enterPipSkipped());
+ }
+
/**
* Calls {@link ActivityThread#handleActivityConfigurationChanged(IBinder, Configuration, int)}
* to try to push activity configuration to the activity for the given sequence number.
@@ -428,9 +474,16 @@ public class ActivityThreadTest {
// Test activity
public static class TestActivity extends Activity {
+ static final String PIP_REQUESTED_OVERRIDE_ENTER = "pip_requested_override_enter";
+ static final String PIP_REQUESTED_OVERRIDE_SKIP = "pip_requested_override_skip";
+
int mNumOfConfigChanges;
final Configuration mConfig = new Configuration();
+ private boolean mPipRequested;
+ private boolean mPipEntered;
+ private boolean mPipEnterSkipped;
+
/**
* A latch used to notify tests that we're about to wait for configuration latch. This
* is used to notify test code that preExecute phase for activity configuration change
@@ -460,5 +513,29 @@ public class ActivityThreadTest {
}
}
}
+
+ @Override
+ public void onPictureInPictureRequested() {
+ mPipRequested = true;
+ if (getIntent().getBooleanExtra(PIP_REQUESTED_OVERRIDE_ENTER, false)) {
+ enterPictureInPictureMode(new PictureInPictureParams.Builder().build());
+ mPipEntered = true;
+ } else if (getIntent().getBooleanExtra(PIP_REQUESTED_OVERRIDE_SKIP, false)) {
+ mPipEnterSkipped = true;
+ }
+ super.onPictureInPictureRequested();
+ }
+
+ boolean pipRequested() {
+ return mPipRequested;
+ }
+
+ boolean enteredPip() {
+ return mPipEntered;
+ }
+
+ boolean enterPipSkipped() {
+ return mPipEnterSkipped;
+ }
}
}
diff --git a/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java b/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java
index 85aa1184c501..895b22c7037c 100644
--- a/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java
+++ b/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java
@@ -115,10 +115,26 @@ public class BrightnessConfigurationTest {
}
@Test
+ public void testLuxMultipliersMustBePositive() {
+ BrightnessConfiguration.Builder config = new BrightnessConfiguration.Builder(
+ LUX_LEVELS, NITS_LEVELS);
+ assertThrows(IllegalArgumentException.class, () -> {
+ config.setShortTermModelUpperLuxMultiplier(-1f);
+ });
+
+ assertThrows(IllegalArgumentException.class, () -> {
+ config.setShortTermModelLowerLuxMultiplier(-1f);
+ });
+ }
+
+ @Test
public void testParceledConfigIsEquivalent() {
BrightnessConfiguration.Builder builder =
new BrightnessConfiguration.Builder(LUX_LEVELS, NITS_LEVELS);
builder.setShouldCollectColorSamples(true);
+ builder.setShortTermModelTimeout(1234L);
+ builder.setShortTermModelLowerLuxMultiplier(0.9f);
+ builder.setShortTermModelUpperLuxMultiplier(0.2f);
builder.addCorrectionByCategory(3,
BrightnessCorrection.createScaleAndTranslateLog(1.0f, 2.0f));
builder.addCorrectionByPackageName("a.package.name",
@@ -137,6 +153,9 @@ public class BrightnessConfigurationTest {
BrightnessConfiguration.Builder builder =
new BrightnessConfiguration.Builder(LUX_LEVELS, NITS_LEVELS);
builder.setShouldCollectColorSamples(true);
+ builder.setShortTermModelTimeout(123L);
+ builder.setShortTermModelLowerLuxMultiplier(0.4f);
+ builder.setShortTermModelUpperLuxMultiplier(0.8f);
builder.addCorrectionByCategory(3,
BrightnessCorrection.createScaleAndTranslateLog(1.0f, 2.0f));
builder.addCorrectionByPackageName("a.package.name",
@@ -208,13 +227,28 @@ public class BrightnessConfigurationTest {
BrightnessCorrection.createScaleAndTranslateLog(1.0f, 2.0f));
builder.addCorrectionByPackageName("a.package.name",
BrightnessCorrection.createScaleAndTranslateLog(1.0f, 2.0f));
+ BrightnessConfiguration correctionsDiffer = builder.build();
+ assertNotEquals(baseConfig, correctionsDiffer);
+
+ builder = new BrightnessConfiguration.Builder(LUX_LEVELS, NITS_LEVELS);
+ builder.setShouldCollectColorSamples(true);
BrightnessConfiguration colorCollectionDiffers = builder.build();
assertNotEquals(baseConfig, colorCollectionDiffers);
builder = new BrightnessConfiguration.Builder(LUX_LEVELS, NITS_LEVELS);
- builder.setShouldCollectColorSamples(true);
- BrightnessConfiguration correctionsDiffer = builder.build();
- assertNotEquals(baseConfig, correctionsDiffer);
+ builder.setShortTermModelTimeout(300L);
+ BrightnessConfiguration timeoutDiffers = builder.build();
+ assertNotEquals(baseConfig, timeoutDiffers);
+
+ builder = new BrightnessConfiguration.Builder(LUX_LEVELS, NITS_LEVELS);
+ builder.setShortTermModelLowerLuxMultiplier(0.7f);
+ BrightnessConfiguration lowerLuxDiffers = builder.build();
+ assertNotEquals(baseConfig, lowerLuxDiffers);
+
+ builder = new BrightnessConfiguration.Builder(LUX_LEVELS, NITS_LEVELS);
+ builder.setShortTermModelUpperLuxMultiplier(0.6f);
+ BrightnessConfiguration upperLuxDiffers = builder.build();
+ assertNotEquals(baseConfig, upperLuxDiffers);
}
private static void assertArrayEquals(float[] expected, float[] actual, String name) {
diff --git a/core/tests/coretests/src/android/os/PowerManagerTest.java b/core/tests/coretests/src/android/os/PowerManagerTest.java
index 576ac73bc183..5cb7852f7acc 100644
--- a/core/tests/coretests/src/android/os/PowerManagerTest.java
+++ b/core/tests/coretests/src/android/os/PowerManagerTest.java
@@ -239,4 +239,17 @@ public class PowerManagerTest extends AndroidTestCase {
verify(mListener2, timeout(CALLBACK_TIMEOUT_MILLI_SEC)
.times(1)).onThermalStatusChanged(status);
}
+
+ @Test
+ public void testUserspaceRebootNotSupported_throwsUnsupportedOperationException() {
+ // Can't use assumption framework with AndroidTestCase :(
+ if (mPm.isRebootingUserspaceSupported()) {
+ return;
+ }
+ try {
+ mPm.reboot(PowerManager.REBOOT_USERSPACE);
+ fail("UnsupportedOperationException not thrown");
+ } catch (UnsupportedOperationException expected) {
+ }
+ }
}
diff --git a/core/tests/coretests/src/android/service/controls/ControlActionTest.java b/core/tests/coretests/src/android/service/controls/ControlActionTest.java
index ef4912fe1f74..d0264da206d9 100644
--- a/core/tests/coretests/src/android/service/controls/ControlActionTest.java
+++ b/core/tests/coretests/src/android/service/controls/ControlActionTest.java
@@ -22,6 +22,12 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import android.os.Parcel;
+import android.service.controls.actions.BooleanAction;
+import android.service.controls.actions.CommandAction;
+import android.service.controls.actions.ControlAction;
+import android.service.controls.actions.FloatAction;
+import android.service.controls.actions.ModeAction;
+import android.service.controls.actions.MultiFloatAction;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -55,6 +61,36 @@ public class ControlActionTest {
assertTrue(fromParcel instanceof FloatAction);
}
+ @Test
+ public void testUnparcelingCorrectClass_multiFloat() {
+ ControlAction toParcel = new MultiFloatAction(TEST_ID, new float[] {0f, 1f});
+
+ ControlAction fromParcel = parcelAndUnparcel(toParcel);
+
+ assertEquals(ControlAction.TYPE_MULTI_FLOAT, fromParcel.getActionType());
+ assertTrue(fromParcel instanceof MultiFloatAction);
+ }
+
+ @Test
+ public void testUnparcelingCorrectClass_mode() {
+ ControlAction toParcel = new ModeAction(TEST_ID, 1);
+
+ ControlAction fromParcel = parcelAndUnparcel(toParcel);
+
+ assertEquals(ControlAction.TYPE_MODE, fromParcel.getActionType());
+ assertTrue(fromParcel instanceof ModeAction);
+ }
+
+ @Test
+ public void testUnparcelingCorrectClass_command() {
+ ControlAction toParcel = new CommandAction(TEST_ID);
+
+ ControlAction fromParcel = parcelAndUnparcel(toParcel);
+
+ assertEquals(ControlAction.TYPE_COMMAND, fromParcel.getActionType());
+ assertTrue(fromParcel instanceof CommandAction);
+ }
+
private ControlAction parcelAndUnparcel(ControlAction toParcel) {
Parcel parcel = Parcel.obtain();
diff --git a/core/tests/coretests/src/android/service/controls/ControlTemplateTest.java b/core/tests/coretests/src/android/service/controls/ControlTemplateTest.java
index 4fa4e1d7b733..2756891c7c36 100644
--- a/core/tests/coretests/src/android/service/controls/ControlTemplateTest.java
+++ b/core/tests/coretests/src/android/service/controls/ControlTemplateTest.java
@@ -24,6 +24,16 @@ import static org.junit.Assert.assertNotNull;
import android.annotation.DrawableRes;
import android.graphics.drawable.Icon;
import android.os.Parcel;
+import android.service.controls.templates.ControlButton;
+import android.service.controls.templates.ControlTemplate;
+import android.service.controls.templates.CoordinatedRangeTemplate;
+import android.service.controls.templates.DiscreteToggleTemplate;
+import android.service.controls.templates.RangeTemplate;
+import android.service.controls.templates.StatelessTemplate;
+import android.service.controls.templates.TemperatureControlTemplate;
+import android.service.controls.templates.ThumbnailTemplate;
+import android.service.controls.templates.ToggleRangeTemplate;
+import android.service.controls.templates.ToggleTemplate;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -35,8 +45,6 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
-import java.security.InvalidParameterException;
-
@SmallTest
@RunWith(AndroidJUnit4.class)
public class ControlTemplateTest {
@@ -44,7 +52,7 @@ public class ControlTemplateTest {
private static final String PACKAGE_NAME = "com.android.frameworks.coretests";
private static final @DrawableRes int TEST_ICON_ID = R.drawable.box;
private static final String TEST_ID = "TEST_ID";
- private static final CharSequence TEST_CONTENT_DESCRIPTION = "TEST_CONTENT_DESCRIPTION";
+ private static final CharSequence TEST_ACTION_DESCRIPTION = "TEST_ACTION_DESCRIPTION";
private Icon mIcon;
private ControlButton mControlButton;
@@ -52,12 +60,13 @@ public class ControlTemplateTest {
public void setUp() {
MockitoAnnotations.initMocks(this);
mIcon = Icon.createWithResource(PACKAGE_NAME, TEST_ICON_ID);
- mControlButton = new ControlButton(true, mIcon, TEST_CONTENT_DESCRIPTION);
+ mControlButton = new ControlButton(true, TEST_ACTION_DESCRIPTION);
}
@Test
public void testUnparcelingCorrectClass_none() {
- ControlTemplate toParcel = ControlTemplate.NO_TEMPLATE;
+ ControlTemplate
+ toParcel = ControlTemplate.NO_TEMPLATE;
ControlTemplate fromParcel = parcelAndUnparcel(toParcel);
@@ -66,7 +75,8 @@ public class ControlTemplateTest {
@Test
public void testUnparcelingCorrectClass_toggle() {
- ControlTemplate toParcel = new ToggleTemplate(TEST_ID, mControlButton);
+ ControlTemplate
+ toParcel = new android.service.controls.templates.ToggleTemplate(TEST_ID, mControlButton);
ControlTemplate fromParcel = parcelAndUnparcel(toParcel);
@@ -76,7 +86,8 @@ public class ControlTemplateTest {
@Test
public void testUnparcelingCorrectClass_range() {
- ControlTemplate toParcel = new RangeTemplate(TEST_ID, 0, 2, 1, 1, "%f");
+ ControlTemplate
+ toParcel = new RangeTemplate(TEST_ID, 0, 2, 1, 1, "%f");
ControlTemplate fromParcel = parcelAndUnparcel(toParcel);
@@ -84,29 +95,30 @@ public class ControlTemplateTest {
assertTrue(fromParcel instanceof RangeTemplate);
}
- @Test(expected = InvalidParameterException.class)
+ @Test(expected = IllegalArgumentException.class)
public void testRangeParameters_minMax() {
- RangeTemplate range = new RangeTemplate(TEST_ID, 2, 0, 1, 1, "%f");
+ new RangeTemplate(TEST_ID, 2, 0, 1, 1, "%f");
}
- @Test(expected = InvalidParameterException.class)
+ @Test(expected = IllegalArgumentException.class)
public void testRangeParameters_minCurrent() {
- RangeTemplate range = new RangeTemplate(TEST_ID, 0, 2, -1, 1, "%f");
+ new RangeTemplate(TEST_ID, 0, 2, -1, 1, "%f");
}
- @Test(expected = InvalidParameterException.class)
+ @Test(expected = IllegalArgumentException.class)
public void testRangeParameters_maxCurrent() {
- RangeTemplate range = new RangeTemplate(TEST_ID, 0, 2, 3, 1, "%f");
+ new RangeTemplate(TEST_ID, 0, 2, 3, 1, "%f");
}
- @Test(expected = InvalidParameterException.class)
+ @Test(expected = IllegalArgumentException.class)
public void testRangeParameters_negativeStep() {
- RangeTemplate range = new RangeTemplate(TEST_ID, 0, 2, 1, -1, "%f");
+ new RangeTemplate(TEST_ID, 0, 2, 1, -1, "%f");
}
@Test
public void testUnparcelingCorrectClass_thumbnail() {
- ControlTemplate toParcel = new ThumbnailTemplate(TEST_ID, mIcon, TEST_CONTENT_DESCRIPTION);
+ ControlTemplate
+ toParcel = new ThumbnailTemplate(TEST_ID, mIcon, TEST_ACTION_DESCRIPTION);
ControlTemplate fromParcel = parcelAndUnparcel(toParcel);
@@ -125,7 +137,115 @@ public class ControlTemplateTest {
assertTrue(fromParcel instanceof DiscreteToggleTemplate);
}
- private ControlTemplate parcelAndUnparcel(ControlTemplate toParcel) {
+ @Test
+ public void testUnparcelingCorrectClass_coordRange() {
+ ControlTemplate toParcel =
+ new CoordinatedRangeTemplate(TEST_ID,0.1f, 0, 1, 0.5f, 1, 2, 1.5f, 0.1f, "%f");
+ ControlTemplate fromParcel = parcelAndUnparcel(toParcel);
+ assertEquals(ControlTemplate.TYPE_COORD_RANGE, fromParcel.getTemplateType());
+ assertTrue(fromParcel instanceof CoordinatedRangeTemplate);
+ }
+
+ @Test
+ public void testCoordRangeParameters_negativeMinGap() {
+ CoordinatedRangeTemplate template =
+ new CoordinatedRangeTemplate(TEST_ID,-0.1f, 0, 1, 0.5f, 1, 2, 1.5f, 0.1f, "%f");
+ assertEquals(0, template.getMinGap(), 0);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCoordRangeParameters_differentStep() {
+ RangeTemplate rangeLow = new RangeTemplate(TEST_ID, 0, 1, 0.5f, 0.1f, "%f");
+ RangeTemplate rangeHigh = new RangeTemplate(TEST_ID, 0, 1, 0.75f, 0.2f, "%f");
+ new CoordinatedRangeTemplate(TEST_ID, 0.1f, rangeLow, rangeHigh);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCoordRangeParameters_differentFormat() {
+ RangeTemplate rangeLow = new RangeTemplate(TEST_ID, 0, 1, 0.5f, 0.1f, "%f");
+ RangeTemplate rangeHigh = new RangeTemplate(TEST_ID, 0, 1, 0.75f, 0.1f, "%.1f");
+ new CoordinatedRangeTemplate(TEST_ID, 0.1f, rangeLow, rangeHigh);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCoordRangeParameters_LargeMinGap() {
+ RangeTemplate rangeLow = new RangeTemplate(TEST_ID, 0, 1, 0.5f, 0.1f, "%f");
+ RangeTemplate rangeHigh = new RangeTemplate(TEST_ID, 0, 1, 0.75f, 0.1f, "%f");
+ new CoordinatedRangeTemplate(TEST_ID, 0.5f, rangeLow, rangeHigh);
+ }
+
+ @Test
+ public void testUnparcelingCorrectClass_toggleRange() {
+ ControlTemplate toParcel =
+ new ToggleRangeTemplate(TEST_ID, mControlButton,
+ new RangeTemplate(TEST_ID, 0, 2, 1, 1, "%f"));
+
+ ControlTemplate fromParcel = parcelAndUnparcel(toParcel);
+
+ assertEquals(ControlTemplate.TYPE_TOGGLE_RANGE, fromParcel.getTemplateType());
+ assertTrue(fromParcel instanceof ToggleRangeTemplate);
+ }
+
+ @Test
+ public void testUnparcelingCorrectClass_stateless() {
+ ControlTemplate toParcel = new StatelessTemplate(TEST_ID);
+
+ ControlTemplate fromParcel = parcelAndUnparcel(toParcel);
+
+ assertEquals(ControlTemplate.TYPE_STATELESS, fromParcel.getTemplateType());
+ assertTrue(fromParcel instanceof StatelessTemplate);
+ }
+
+ @Test
+ public void testUnparcelingCorrectClass_thermostat() {
+ ControlTemplate toParcel = new TemperatureControlTemplate(TEST_ID,
+ new ToggleTemplate("", mControlButton),
+ TemperatureControlTemplate.MODE_OFF,
+ TemperatureControlTemplate.MODE_OFF,
+ TemperatureControlTemplate.FLAG_MODE_OFF);
+
+ ControlTemplate fromParcel = parcelAndUnparcel(toParcel);
+
+ assertEquals(ControlTemplate.TYPE_TEMPERATURE, fromParcel.getTemplateType());
+ assertTrue(fromParcel instanceof TemperatureControlTemplate);
+ }
+
+ @Test
+ public void testThermostatParams_wrongMode() {
+ TemperatureControlTemplate thermostat = new TemperatureControlTemplate(TEST_ID, ControlTemplate.NO_TEMPLATE, -1,
+ TemperatureControlTemplate.MODE_OFF, TemperatureControlTemplate.FLAG_MODE_OFF);
+ assertEquals(TemperatureControlTemplate.MODE_UNKNOWN, thermostat.getCurrentMode());
+
+ thermostat = new TemperatureControlTemplate(TEST_ID, ControlTemplate.NO_TEMPLATE, 100,
+ TemperatureControlTemplate.MODE_OFF, TemperatureControlTemplate.FLAG_MODE_OFF);
+ assertEquals(TemperatureControlTemplate.MODE_UNKNOWN, thermostat.getCurrentMode());
+ }
+
+ @Test
+ public void testThermostatParams_wrongActiveMode() {
+ TemperatureControlTemplate thermostat = new TemperatureControlTemplate(TEST_ID, ControlTemplate.NO_TEMPLATE,
+ TemperatureControlTemplate.MODE_OFF,-1, TemperatureControlTemplate.FLAG_MODE_OFF);
+ assertEquals(TemperatureControlTemplate.MODE_UNKNOWN, thermostat.getCurrentActiveMode());
+
+ thermostat = new TemperatureControlTemplate(TEST_ID, ControlTemplate.NO_TEMPLATE,
+ TemperatureControlTemplate.MODE_OFF,100, TemperatureControlTemplate.FLAG_MODE_OFF);
+ assertEquals(TemperatureControlTemplate.MODE_UNKNOWN, thermostat.getCurrentActiveMode());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testThermostatParams_wrongFlags_currentMode() {
+ new TemperatureControlTemplate(TEST_ID, ControlTemplate.NO_TEMPLATE, TemperatureControlTemplate.MODE_HEAT,
+ TemperatureControlTemplate.MODE_OFF, TemperatureControlTemplate.FLAG_MODE_OFF);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testThermostatParams_wrongFlags_currentActiveMode() {
+ new TemperatureControlTemplate(TEST_ID, ControlTemplate.NO_TEMPLATE, TemperatureControlTemplate.MODE_HEAT,
+ TemperatureControlTemplate.MODE_OFF, TemperatureControlTemplate.FLAG_MODE_HEAT);
+ }
+
+ private ControlTemplate parcelAndUnparcel(
+ ControlTemplate toParcel) {
Parcel parcel = Parcel.obtain();
assertNotNull(parcel);
diff --git a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
index 68d95cd38497..179929f2aae0 100644
--- a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
+++ b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
@@ -76,7 +76,6 @@ public class InsetsAnimationControlImplTest {
@Mock Transaction mMockTransaction;
@Mock InsetsController mMockController;
@Mock WindowInsetsAnimationControlListener mMockListener;
- @Mock SyncRtSurfaceTransactionApplier mMockTransactionApplier;
@BeforeClass
public static void setupOnce() {
@@ -111,12 +110,12 @@ public class InsetsAnimationControlImplTest {
navConsumer.setControl(new InsetsSourceControl(ITYPE_NAVIGATION_BAR, mNavLeash,
new Point(400, 0)));
- SparseArray<InsetsSourceConsumer> consumers = new SparseArray<>();
- consumers.put(ITYPE_STATUS_BAR, topConsumer);
- consumers.put(ITYPE_NAVIGATION_BAR, navConsumer);
- mController = new InsetsAnimationControlImpl(consumers,
+ SparseArray<InsetsSourceControl> controls = new SparseArray<>();
+ controls.put(ITYPE_STATUS_BAR, topConsumer.getControl());
+ controls.put(ITYPE_NAVIGATION_BAR, navConsumer.getControl());
+ mController = new InsetsAnimationControlImpl(controls,
new Rect(0, 0, 500, 500), mInsetsState, mMockListener, systemBars(),
- () -> mMockTransactionApplier, mMockController, 10 /* durationMs */,
+ mMockController, 10 /* durationMs */,
false /* fade */);
}
@@ -137,7 +136,7 @@ public class InsetsAnimationControlImplTest {
assertEquals(1f, mController.getCurrentAlpha(), 1f - mController.getCurrentAlpha());
ArgumentCaptor<SurfaceParams> captor = ArgumentCaptor.forClass(SurfaceParams.class);
- verify(mMockTransactionApplier).scheduleApply(captor.capture());
+ verify(mMockController).applySurfaceParams(captor.capture());
List<SurfaceParams> params = captor.getAllValues();
assertEquals(2, params.size());
SurfaceParams first = params.get(0);
diff --git a/core/tests/coretests/src/android/view/textclassifier/ActionsSuggestionsHelperTest.java b/core/tests/coretests/src/android/view/textclassifier/ActionsSuggestionsHelperTest.java
index 80bce264c11b..ec7e83f1f243 100644
--- a/core/tests/coretests/src/android/view/textclassifier/ActionsSuggestionsHelperTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/ActionsSuggestionsHelperTest.java
@@ -238,6 +238,7 @@ public class ActionsSuggestionsHelperTest {
assertThat(conversationActions).isEmpty();
}
+ @Test
public void createLabeledIntentResult_null() {
ActionsSuggestionsModel.ActionSuggestion nativeSuggestion =
new ActionsSuggestionsModel.ActionSuggestion(
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextLinksTest.java b/core/tests/coretests/src/android/view/textclassifier/TextLinksTest.java
index b9cc8f4ba4a0..ec5813fd4123 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextLinksTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextLinksTest.java
@@ -29,6 +29,9 @@ import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.time.Instant;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -77,6 +80,7 @@ public class TextLinksTest {
final TextLinks result = TextLinks.CREATOR.createFromParcel(parcel);
final List<TextLinks.TextLink> resultList = new ArrayList<>(result.getLinks());
+ assertEquals(fullText, result.getText());
assertEquals(2, resultList.size());
assertEquals(0, resultList.get(0).getStart());
assertEquals(4, resultList.get(0).getEnd());
@@ -103,10 +107,13 @@ public class TextLinksTest {
Arrays.asList(TextClassifier.HINT_TEXT_IS_EDITABLE),
Arrays.asList("a", "b", "c"),
Arrays.asList("b"));
+ final ZonedDateTime referenceTime = ZonedDateTime.ofInstant(Instant.ofEpochMilli(1000L),
+ ZoneId.of("UTC"));
final TextLinks.Request reference = new TextLinks.Request.Builder("text")
.setDefaultLocales(new LocaleList(Locale.US, Locale.GERMANY))
.setEntityConfig(entityConfig)
.setExtras(BUNDLE)
+ .setReferenceTime(referenceTime)
.build();
reference.setCallingPackageName(packageName);
@@ -124,5 +131,6 @@ public class TextLinksTest {
result.getEntityConfig().resolveEntityListModifications(Collections.emptyList()));
assertEquals(BUNDLE_VALUE, result.getExtras().getString(BUNDLE_KEY));
assertEquals(packageName, result.getCallingPackageName());
+ assertEquals(referenceTime, result.getReferenceTime());
}
}
diff --git a/core/tests/coretests/src/android/widget/EditorCursorDragTest.java b/core/tests/coretests/src/android/widget/EditorCursorDragTest.java
new file mode 100644
index 000000000000..b4f2c91f27b7
--- /dev/null
+++ b/core/tests/coretests/src/android/widget/EditorCursorDragTest.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget;
+
+import static android.widget.espresso.TextViewActions.dragOnText;
+import static android.widget.espresso.TextViewAssertions.hasInsertionPointerAtIndex;
+
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.action.ViewActions.replaceText;
+import static androidx.test.espresso.matcher.ViewMatchers.withId;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.frameworks.coretests.R;
+
+import com.google.common.base.Strings;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class EditorCursorDragTest {
+ @Rule
+ public ActivityTestRule<TextViewActivity> mActivityRule = new ActivityTestRule<>(
+ TextViewActivity.class);
+
+ private boolean mOriginalFlagValue;
+ private Instrumentation mInstrumentation;
+ private Activity mActivity;
+
+ @Before
+ public void before() throws Throwable {
+ mInstrumentation = InstrumentationRegistry.getInstrumentation();
+ mActivity = mActivityRule.getActivity();
+ mOriginalFlagValue = Editor.FLAG_ENABLE_CURSOR_DRAG;
+ Editor.FLAG_ENABLE_CURSOR_DRAG = true;
+ }
+ @After
+ public void after() throws Throwable {
+ Editor.FLAG_ENABLE_CURSOR_DRAG = mOriginalFlagValue;
+ }
+
+ @Test
+ public void testCursorDrag_horizontal_whenTextViewContentsFitOnScreen() throws Throwable {
+ String text = "Hello world!";
+ onView(withId(R.id.textview)).perform(replaceText(text));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(0));
+
+ // Drag left to right. The cursor should end up at the position where the finger is lifted.
+ onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("llo"), text.indexOf("!")));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(11));
+
+ // Drag right to left. The cursor should end up at the position where the finger is lifted.
+ onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("!"), text.indexOf("llo")));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(2));
+ }
+
+ @Test
+ public void testCursorDrag_horizontal_whenTextViewContentsLargerThanScreen() throws Throwable {
+ String text = "Hello world!"
+ + Strings.repeat("\n", 500) + "012345middle"
+ + Strings.repeat("\n", 10) + "012345last";
+ onView(withId(R.id.textview)).perform(replaceText(text));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(0));
+
+ // Drag left to right. The cursor should end up at the position where the finger is lifted.
+ onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("llo"), text.indexOf("!")));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(11));
+
+ // Drag right to left. The cursor should end up at the position where the finger is lifted.
+ onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("!"), text.indexOf("llo")));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(2));
+ }
+
+ @Test
+ public void testCursorDrag_diagonal_whenTextViewContentsLargerThanScreen() throws Throwable {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 1; i <= 9; i++) {
+ sb.append("line").append(i).append("\n");
+ }
+ sb.append(Strings.repeat("0123456789\n\n", 500)).append("Last line");
+ String text = sb.toString();
+ onView(withId(R.id.textview)).perform(replaceText(text));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(0));
+
+ // Drag along a diagonal path.
+ onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("line1"), text.indexOf("2")));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("2")));
+
+ // Drag along a steeper diagonal path.
+ onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("line1"), text.indexOf("9")));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("9")));
+
+ // Drag along an almost vertical path.
+ // TODO(b/145833335): Consider whether this should scroll instead of dragging the cursor.
+ onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("ne1"), text.indexOf("9")));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("9")));
+
+ // Drag along a vertical path from line 1 to line 9.
+ // TODO(b/145833335): Consider whether this should scroll instead of dragging the cursor.
+ onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("e1"), text.indexOf("e9")));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("e9")));
+
+ // Drag along a vertical path from line 9 to line 1.
+ // TODO(b/145833335): Consider whether this should scroll instead of dragging the cursor.
+ onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("e9"), text.indexOf("e1")));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("e1")));
+ }
+
+ @Test
+ public void testCursorDrag_vertical_whenTextViewContentsFitOnScreen() throws Throwable {
+ String text = "012first\n\n" + Strings.repeat("012345\n\n", 10) + "012last";
+ onView(withId(R.id.textview)).perform(replaceText(text));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(0));
+
+ // Drag down. Since neither the TextView nor its container require scrolling, the cursor
+ // drag should execute and the cursor should end up at the position where the finger is
+ // lifted.
+ onView(withId(R.id.textview)).perform(
+ dragOnText(text.indexOf("first"), text.indexOf("last")));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.length() - 4));
+
+ // Drag up. Since neither the TextView nor its container require scrolling, the cursor
+ // drag should execute and the cursor should end up at the position where the finger is
+ // lifted.
+ onView(withId(R.id.textview)).perform(
+ dragOnText(text.indexOf("last"), text.indexOf("first")));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(3));
+ }
+
+ @Test
+ public void testCursorDrag_vertical_whenTextViewContentsLargerThanScreen() throws Throwable {
+ String text = "012345first\n\n"
+ + Strings.repeat("0123456789\n\n", 10) + "012345middle"
+ + Strings.repeat("0123456789\n\n", 500) + "012345last";
+ onView(withId(R.id.textview)).perform(replaceText(text));
+ int initialCursorPosition = 0;
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(initialCursorPosition));
+
+ // Drag up.
+ // TODO(b/145833335): Consider whether this should scroll instead of dragging the cursor.
+ onView(withId(R.id.textview)).perform(
+ dragOnText(text.indexOf("middle"), text.indexOf("first")));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("first")));
+
+ // Drag down.
+ // TODO(b/145833335): Consider whether this should scroll instead of dragging the cursor.
+ onView(withId(R.id.textview)).perform(
+ dragOnText(text.indexOf("first"), text.indexOf("middle")));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("middle")));
+ }
+}
diff --git a/core/tests/coretests/src/android/widget/EditorTouchStateTest.java b/core/tests/coretests/src/android/widget/EditorTouchStateTest.java
index 6d50e3aa3b8f..6adb1b8fa0d6 100644
--- a/core/tests/coretests/src/android/widget/EditorTouchStateTest.java
+++ b/core/tests/coretests/src/android/widget/EditorTouchStateTest.java
@@ -16,6 +16,9 @@
package android.widget;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
@@ -50,19 +53,19 @@ public class EditorTouchStateTest {
long event1Time = 1000;
MotionEvent event1 = downEvent(event1Time, event1Time, 20f, 30f);
mTouchState.update(event1, mConfig);
- assertSingleTap(mTouchState, 20f, 30f, 0, 0);
+ assertSingleTap(mTouchState, 20f, 30f, 0, 0, false);
// Simulate an ACTION_UP event.
long event2Time = 1001;
MotionEvent event2 = upEvent(event1Time, event2Time, 20f, 30f);
mTouchState.update(event2, mConfig);
- assertSingleTap(mTouchState, 20f, 30f, 20f, 30f);
+ assertSingleTap(mTouchState, 20f, 30f, 20f, 30f, false);
// Generate an ACTION_DOWN event whose time is after the double-tap timeout.
long event3Time = event2Time + ViewConfiguration.getDoubleTapTimeout() + 1;
MotionEvent event3 = downEvent(event3Time, event3Time, 22f, 33f);
mTouchState.update(event3, mConfig);
- assertSingleTap(mTouchState, 22f, 33f, 20f, 30f);
+ assertSingleTap(mTouchState, 22f, 33f, 20f, 30f, false);
}
@Test
@@ -71,19 +74,19 @@ public class EditorTouchStateTest {
long event1Time = 1000;
MotionEvent event1 = downEvent(event1Time, event1Time, 20f, 30f);
mTouchState.update(event1, mConfig);
- assertSingleTap(mTouchState, 20f, 30f, 0, 0);
+ assertSingleTap(mTouchState, 20f, 30f, 0, 0, false);
// Simulate an ACTION_UP event.
long event2Time = 1001;
MotionEvent event2 = upEvent(event1Time, event2Time, 20f, 30f);
mTouchState.update(event2, mConfig);
- assertSingleTap(mTouchState, 20f, 30f, 20f, 30f);
+ assertSingleTap(mTouchState, 20f, 30f, 20f, 30f, false);
// Generate an ACTION_DOWN event whose time is within the double-tap timeout.
long event3Time = 1002;
MotionEvent event3 = downEvent(event3Time, event3Time, 22f, 33f);
mTouchState.update(event3, mConfig);
- assertTap(mTouchState, 22f, 33f, 20f, 30f,
+ assertMultiTap(mTouchState, 22f, 33f, 20f, 30f,
MultiTapStatus.DOUBLE_TAP, true);
}
@@ -93,26 +96,26 @@ public class EditorTouchStateTest {
long event1Time = 1000;
MotionEvent event1 = downEvent(event1Time, event1Time, 20f, 30f);
mTouchState.update(event1, mConfig);
- assertSingleTap(mTouchState, 20f, 30f, 0, 0);
+ assertSingleTap(mTouchState, 20f, 30f, 0, 0, false);
// Simulate an ACTION_UP event.
long event2Time = 1001;
MotionEvent event2 = upEvent(event1Time, event2Time, 20f, 30f);
mTouchState.update(event2, mConfig);
- assertSingleTap(mTouchState, 20f, 30f, 20f, 30f);
+ assertSingleTap(mTouchState, 20f, 30f, 20f, 30f, false);
// Generate an ACTION_DOWN event whose time is within the double-tap timeout.
long event3Time = 1002;
MotionEvent event3 = downEvent(event3Time, event3Time, 200f, 300f);
mTouchState.update(event3, mConfig);
- assertTap(mTouchState, 200f, 300f, 20f, 30f,
+ assertMultiTap(mTouchState, 200f, 300f, 20f, 30f,
MultiTapStatus.DOUBLE_TAP, false);
// Simulate an ACTION_UP event.
long event4Time = 1003;
MotionEvent event4 = upEvent(event3Time, event4Time, 200f, 300f);
mTouchState.update(event4, mConfig);
- assertTap(mTouchState, 200f, 300f, 200f, 300f,
+ assertMultiTap(mTouchState, 200f, 300f, 200f, 300f,
MultiTapStatus.DOUBLE_TAP, false);
}
@@ -123,21 +126,21 @@ public class EditorTouchStateTest {
MotionEvent event1 = downEvent(event1Time, event1Time, 20f, 30f);
event1.setSource(InputDevice.SOURCE_MOUSE);
mTouchState.update(event1, mConfig);
- assertSingleTap(mTouchState, 20f, 30f, 0, 0);
+ assertSingleTap(mTouchState, 20f, 30f, 0, 0, false);
// Simulate an ACTION_UP event.
long event2Time = 1001;
MotionEvent event2 = upEvent(event1Time, event2Time, 20f, 30f);
event2.setSource(InputDevice.SOURCE_MOUSE);
mTouchState.update(event2, mConfig);
- assertSingleTap(mTouchState, 20f, 30f, 20f, 30f);
+ assertSingleTap(mTouchState, 20f, 30f, 20f, 30f, false);
// Generate a second ACTION_DOWN event whose time is within the double-tap timeout.
long event3Time = 1002;
MotionEvent event3 = downEvent(event3Time, event3Time, 21f, 31f);
event3.setSource(InputDevice.SOURCE_MOUSE);
mTouchState.update(event3, mConfig);
- assertTap(mTouchState, 21f, 31f, 20f, 30f,
+ assertMultiTap(mTouchState, 21f, 31f, 20f, 30f,
MultiTapStatus.DOUBLE_TAP, true);
// Simulate an ACTION_UP event.
@@ -145,7 +148,7 @@ public class EditorTouchStateTest {
MotionEvent event4 = upEvent(event3Time, event4Time, 21f, 31f);
event4.setSource(InputDevice.SOURCE_MOUSE);
mTouchState.update(event4, mConfig);
- assertTap(mTouchState, 21f, 31f, 21f, 31f,
+ assertMultiTap(mTouchState, 21f, 31f, 21f, 31f,
MultiTapStatus.DOUBLE_TAP, true);
// Generate a third ACTION_DOWN event whose time is within the double-tap timeout.
@@ -153,7 +156,7 @@ public class EditorTouchStateTest {
MotionEvent event5 = downEvent(event5Time, event5Time, 22f, 32f);
event5.setSource(InputDevice.SOURCE_MOUSE);
mTouchState.update(event5, mConfig);
- assertTap(mTouchState, 22f, 32f, 21f, 31f,
+ assertMultiTap(mTouchState, 22f, 32f, 21f, 31f,
MultiTapStatus.TRIPLE_CLICK, true);
}
@@ -163,34 +166,71 @@ public class EditorTouchStateTest {
long event1Time = 1000;
MotionEvent event1 = downEvent(event1Time, event1Time, 20f, 30f);
mTouchState.update(event1, mConfig);
- assertSingleTap(mTouchState, 20f, 30f, 0, 0);
+ assertSingleTap(mTouchState, 20f, 30f, 0, 0, false);
// Simulate an ACTION_UP event.
long event2Time = 1001;
MotionEvent event2 = upEvent(event1Time, event2Time, 20f, 30f);
mTouchState.update(event2, mConfig);
- assertSingleTap(mTouchState, 20f, 30f, 20f, 30f);
+ assertSingleTap(mTouchState, 20f, 30f, 20f, 30f, false);
// Generate a second ACTION_DOWN event whose time is within the double-tap timeout.
long event3Time = 1002;
MotionEvent event3 = downEvent(event3Time, event3Time, 21f, 31f);
mTouchState.update(event3, mConfig);
- assertTap(mTouchState, 21f, 31f, 20f, 30f,
+ assertMultiTap(mTouchState, 21f, 31f, 20f, 30f,
MultiTapStatus.DOUBLE_TAP, true);
// Simulate an ACTION_UP event.
long event4Time = 1003;
MotionEvent event4 = upEvent(event3Time, event4Time, 21f, 31f);
mTouchState.update(event4, mConfig);
- assertTap(mTouchState, 21f, 31f, 21f, 31f,
+ assertMultiTap(mTouchState, 21f, 31f, 21f, 31f,
MultiTapStatus.DOUBLE_TAP, true);
// Generate a third ACTION_DOWN event whose time is within the double-tap timeout.
long event5Time = 1004;
MotionEvent event5 = downEvent(event5Time, event5Time, 22f, 32f);
mTouchState.update(event5, mConfig);
- assertTap(mTouchState, 22f, 32f, 21f, 31f,
- MultiTapStatus.FIRST_TAP, false);
+ assertSingleTap(mTouchState, 22f, 32f, 21f, 31f, false);
+ }
+
+ @Test
+ public void testUpdate_drag() throws Exception {
+ // Simulate an ACTION_DOWN event.
+ long event1Time = 1000;
+ MotionEvent event1 = downEvent(event1Time, event1Time, 20f, 30f);
+ mTouchState.update(event1, mConfig);
+ assertSingleTap(mTouchState, 20f, 30f, 0, 0, false);
+
+ // Simulate an ACTION_MOVE event whose location is not far enough to start a drag.
+ long event2Time = 1001;
+ MotionEvent event2 = moveEvent(event1Time, event2Time, 21f, 30f);
+ mTouchState.update(event2, mConfig);
+ assertSingleTap(mTouchState, 20f, 30f, 0, 0, false);
+
+ // Simulate another ACTION_MOVE event whose location is far enough to start a drag.
+ int touchSlop = mConfig.getScaledTouchSlop();
+ float newX = event1.getX() + touchSlop + 1;
+ float newY = event1.getY();
+ long event3Time = 1002;
+ MotionEvent event3 = moveEvent(event3Time, event3Time, newX, newY);
+ mTouchState.update(event3, mConfig);
+ assertSingleTap(mTouchState, 20f, 30f, 0, 0, true);
+
+ // Simulate an ACTION_UP event.
+ long event4Time = 1003;
+ MotionEvent event4 = upEvent(event3Time, event4Time, 200f, 300f);
+ mTouchState.update(event4, mConfig);
+ assertSingleTap(mTouchState, 20f, 30f, 200f, 300f, false);
+ }
+
+ @Test
+ public void testIsDistanceWithin() throws Exception {
+ assertTrue(EditorTouchState.isDistanceWithin(0, 0, 0, 0, 8));
+ assertTrue(EditorTouchState.isDistanceWithin(3, 9, 5, 11, 8));
+ assertTrue(EditorTouchState.isDistanceWithin(5, 11, 3, 9, 8));
+ assertFalse(EditorTouchState.isDistanceWithin(5, 10, 5, 20, 8));
}
private static MotionEvent downEvent(long downTime, long eventTime, float x, float y) {
@@ -201,8 +241,12 @@ public class EditorTouchStateTest {
return MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, x, y, 0);
}
+ private static MotionEvent moveEvent(long downTime, long eventTime, float x, float y) {
+ return MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, x, y, 0);
+ }
+
private static void assertSingleTap(EditorTouchState touchState, float lastDownX,
- float lastDownY, float lastUpX, float lastUpY) {
+ float lastDownY, float lastUpX, float lastUpY, boolean isMovedEnoughForDrag) {
assertThat(touchState.getLastDownX(), is(lastDownX));
assertThat(touchState.getLastDownY(), is(lastDownY));
assertThat(touchState.getLastUpX(), is(lastUpX));
@@ -211,9 +255,10 @@ public class EditorTouchStateTest {
assertThat(touchState.isTripleClick(), is(false));
assertThat(touchState.isMultiTap(), is(false));
assertThat(touchState.isMultiTapInSameArea(), is(false));
+ assertThat(touchState.isMovedEnoughForDrag(), is(isMovedEnoughForDrag));
}
- private static void assertTap(EditorTouchState touchState,
+ private static void assertMultiTap(EditorTouchState touchState,
float lastDownX, float lastDownY, float lastUpX, float lastUpY,
@MultiTapStatus int multiTapStatus, boolean isMultiTapInSameArea) {
assertThat(touchState.getLastDownX(), is(lastDownX));
@@ -225,5 +270,6 @@ public class EditorTouchStateTest {
assertThat(touchState.isMultiTap(), is(multiTapStatus == MultiTapStatus.DOUBLE_TAP
|| multiTapStatus == MultiTapStatus.TRIPLE_CLICK));
assertThat(touchState.isMultiTapInSameArea(), is(isMultiTapInSameArea));
+ assertThat(touchState.isMovedEnoughForDrag(), is(false));
}
}
diff --git a/core/tests/coretests/src/android/widget/espresso/TextViewActions.java b/core/tests/coretests/src/android/widget/espresso/TextViewActions.java
index 83ce67bd96ad..4808a0b0656a 100644
--- a/core/tests/coretests/src/android/widget/espresso/TextViewActions.java
+++ b/core/tests/coretests/src/android/widget/espresso/TextViewActions.java
@@ -358,6 +358,27 @@ public final class TextViewActions {
}
/**
+ * Returns an action that drags on text from startIndex to endIndex on the TextView.<br>
+ * <br>
+ * View constraints:
+ * <ul>
+ * <li>must be a TextView displayed on screen
+ * <ul>
+ *
+ * @param startIndex The index of the TextView's text to start a drag from
+ * @param endIndex The index of the TextView's text to end the drag at
+ */
+ public static ViewAction dragOnText(int startIndex, int endIndex) {
+ return actionWithAssertions(
+ new DragAction(
+ DragAction.Drag.TAP,
+ new TextCoordinates(startIndex),
+ new TextCoordinates(endIndex),
+ Press.FINGER,
+ TextView.class));
+ }
+
+ /**
* A provider of the x, y coordinates of the handle dragging point.
*/
private static final class CurrentHandleCoordinates implements CoordinatesProvider {
diff --git a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
index 364e4ea6e3ec..9863e389cb5e 100644
--- a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
+++ b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
@@ -25,10 +25,12 @@ import static android.app.servertransaction.ActivityLifecycleItem.ON_STOP;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.when;
import android.app.Activity;
@@ -36,6 +38,7 @@ import android.app.ActivityTaskManager;
import android.app.ActivityThread;
import android.app.ActivityThread.ActivityClientRecord;
import android.app.IActivityTaskManager;
+import android.app.LoadedApk;
import android.app.servertransaction.PendingTransactionActions;
import android.content.ComponentName;
import android.content.Intent;
@@ -346,6 +349,14 @@ public class ActivityThreadClientTest {
info.applicationInfo.packageName = info.packageName;
info.applicationInfo.uid = UserHandle.myUserId();
+ // mock the function for preventing NPE in emulator environment. The purpose of the
+ // test is for activity client state changes, we don't focus on the updating for the
+ // ApplicationInfo.
+ LoadedApk packageInfo = mThread.peekPackageInfo(info.packageName,
+ true /* includeCode */);
+ spyOn(packageInfo);
+ doNothing().when(packageInfo).updateApplicationInfo(any(), any());
+
return new ActivityClientRecord(new Binder(), Intent.makeMainActivity(component),
0 /* ident */, info, new Configuration(),
CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null /* referrer */,
diff --git a/core/tests/overlaytests/device/res/layout/layout.xml b/core/tests/overlaytests/device/res/layout/layout.xml
new file mode 100644
index 000000000000..e12c715a2a32
--- /dev/null
+++ b/core/tests/overlaytests/device/res/layout/layout.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout android:id="@id/view_1"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <com.android.overlaytest.view.TestTextView
+ android:id="@id/view_2"
+ android:layout_width="match_parent"
+ android:layout_height="100dp"
+ app:customAttribute="none"/>
+
+ <com.android.overlaytest.view.TestTextView
+ android:id="@id/view_3"
+ android:layout_width="match_parent"
+ android:layout_height="100dp"
+ app:customAttribute="none" />
+ </LinearLayout>
+</LinearLayout> \ No newline at end of file
diff --git a/core/tests/overlaytests/device/res/values/config.xml b/core/tests/overlaytests/device/res/values/config.xml
index c692a2625199..e918268fa073 100644
--- a/core/tests/overlaytests/device/res/values/config.xml
+++ b/core/tests/overlaytests/device/res/values/config.xml
@@ -56,4 +56,16 @@
<item>17</item>
<item>19</item>
</integer-array>
+
+ <attr name="customAttribute" />
+ <id name="view_1" />
+ <id name="view_2" />
+ <id name="view_3" />
+
+ <!-- Stabilize the ids of attributes and ids used in test layouts so that they differ from the
+ overlay resource ids -->
+ <public type="attr" name="customAttribute" id="0x7f200000"/>
+ <public type="id" name="view_1" id="0x7f210000"/>
+ <public type="id" name="view_2" id="0x7f210001"/>
+ <public type="id" name="view_3" id="0x7f210002"/>
</resources>
diff --git a/core/tests/overlaytests/device/src/com/android/overlaytest/OverlayBaseTest.java b/core/tests/overlaytests/device/src/com/android/overlaytest/OverlayBaseTest.java
index fdb6bbb4550b..636f4c8b59ca 100644
--- a/core/tests/overlaytests/device/src/com/android/overlaytest/OverlayBaseTest.java
+++ b/core/tests/overlaytests/device/src/com/android/overlaytest/OverlayBaseTest.java
@@ -18,20 +18,26 @@ package com.android.overlaytest;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import android.content.Context;
import android.content.res.AssetManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.os.LocaleList;
import android.util.AttributeSet;
+import android.util.TypedValue;
import android.util.Xml;
+import android.view.LayoutInflater;
+import android.view.View;
import androidx.test.InstrumentationRegistry;
import com.android.internal.util.ArrayUtils;
+import com.android.overlaytest.view.TestTextView;
import org.junit.Before;
import org.junit.Ignore;
@@ -45,6 +51,7 @@ import java.util.Locale;
@Ignore
public abstract class OverlayBaseTest {
+ private Context mContext;
private Resources mResources;
private final int mMode;
static final int MODE_NO_OVERLAY = 0;
@@ -61,7 +68,8 @@ public abstract class OverlayBaseTest {
@Before
public void setUp() {
- mResources = InstrumentationRegistry.getContext().getResources();
+ mContext = InstrumentationRegistry.getContext();
+ mResources = mContext.getResources();
}
private int calculateRawResourceChecksum(int resId) throws Throwable {
@@ -321,6 +329,50 @@ public abstract class OverlayBaseTest {
assertEquals("com.android.overlaytest", contents);
}
+ @Test
+ public void testRewrite() throws Throwable {
+ final TypedValue result = new TypedValue();
+ mResources.getValue(R.string.str, result, true);
+ assertEquals(result.resourceId & 0xff000000, 0x7f000000);
+ }
+
+ @Test
+ public void testOverlayLayout() throws Throwable {
+ final LayoutInflater inflater = LayoutInflater.from(mContext);
+ final View layout = inflater.inflate(R.layout.layout, null);
+ assertNotNull(layout.findViewById(R.id.view_1));
+
+ final TestTextView view2 = layout.findViewById(R.id.view_2);
+ assertNotNull(view2);
+ switch (mMode) {
+ case MODE_NO_OVERLAY:
+ assertEquals("none", view2.getCustomAttributeValue());
+ break;
+ case MODE_SINGLE_OVERLAY:
+ assertEquals("single", view2.getCustomAttributeValue());
+ break;
+ case MODE_MULTIPLE_OVERLAYS:
+ assertEquals("multiple", view2.getCustomAttributeValue());
+ break;
+ default:
+ fail("Unknown mode " + mMode);
+ }
+
+ final TestTextView view3 = layout.findViewById(R.id.view_3);
+ assertNotNull(view3);
+ switch (mMode) {
+ case MODE_NO_OVERLAY:
+ assertEquals("none", view3.getCustomAttributeValue());
+ break;
+ case MODE_SINGLE_OVERLAY:
+ case MODE_MULTIPLE_OVERLAYS:
+ assertEquals("overlaid", view3.getCustomAttributeValue());
+ break;
+ default:
+ fail("Unknown mode " + mMode);
+ }
+ }
+
/*
* testMatrix* tests
*
diff --git a/core/tests/overlaytests/device/src/com/android/overlaytest/view/TestTextView.java b/core/tests/overlaytests/device/src/com/android/overlaytest/view/TestTextView.java
new file mode 100644
index 000000000000..2245e2b8121b
--- /dev/null
+++ b/core/tests/overlaytests/device/src/com/android/overlaytest/view/TestTextView.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.overlaytest.view;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.widget.TextView;
+
+public class TestTextView extends TextView {
+
+ private final String mCustomAttributeValue;
+
+ public TestTextView(Context context, AttributeSet attrs) {
+ this(context, attrs, com.android.internal.R.attr.textViewStyle, 0);
+ }
+
+ public TestTextView(Context context, AttributeSet attrs,
+ int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+
+ int[] testResources = new int[]{com.android.overlaytest.R.attr.customAttribute};
+ final Resources.Theme theme = context.getTheme();
+ TypedArray typedArray = theme.obtainStyledAttributes(attrs, testResources, defStyleAttr,
+ defStyleRes);
+ mCustomAttributeValue = typedArray.getString(0);
+ }
+
+ public String getCustomAttributeValue() {
+ return mCustomAttributeValue;
+ }
+}
diff --git a/core/tests/overlaytests/device/test-apps/AppOverlayOne/AndroidManifest.xml b/core/tests/overlaytests/device/test-apps/AppOverlayOne/AndroidManifest.xml
index 7d2840886683..873ca3c9b821 100644
--- a/core/tests/overlaytests/device/test-apps/AppOverlayOne/AndroidManifest.xml
+++ b/core/tests/overlaytests/device/test-apps/AppOverlayOne/AndroidManifest.xml
@@ -19,5 +19,6 @@
android:versionCode="1"
android:versionName="1.0">
<application android:hasCode="false" />
- <overlay android:targetPackage="com.android.overlaytest" />
+ <overlay android:targetPackage="com.android.overlaytest"
+ android:resourcesMap="@xml/overlays"/>
</manifest>
diff --git a/core/tests/overlaytests/device/test-apps/AppOverlayOne/res/layout/layout.xml b/core/tests/overlaytests/device/test-apps/AppOverlayOne/res/layout/layout.xml
new file mode 100644
index 000000000000..7b636054c936
--- /dev/null
+++ b/core/tests/overlaytests/device/test-apps/AppOverlayOne/res/layout/layout.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout android:id="@+id/view_1"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <com.android.overlaytest.view.TestTextView
+ android:id="@+id/view_2"
+ android:layout_width="match_parent"
+ android:layout_height="100dp"
+ app:customAttribute="@string/str" />
+
+ <com.android.overlaytest.view.TestTextView
+ android:id="@+id/view_3"
+ android:layout_width="match_parent"
+ android:layout_height="100dp"
+ app:customAttribute="overlaid" />
+ </LinearLayout>
+</LinearLayout> \ No newline at end of file
diff --git a/core/tests/overlaytests/device/test-apps/AppOverlayOne/res/values/config.xml b/core/tests/overlaytests/device/test-apps/AppOverlayOne/res/values/config.xml
index 972137a3d1bf..74c496386f2f 100644
--- a/core/tests/overlaytests/device/test-apps/AppOverlayOne/res/values/config.xml
+++ b/core/tests/overlaytests/device/test-apps/AppOverlayOne/res/values/config.xml
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="str">single</string>
- <string name="str2">single</string>
<integer name="matrix_101000">300</integer>
<integer name="matrix_101001">300</integer>
<integer name="matrix_101010">300</integer>
@@ -18,7 +17,6 @@
<integer name="matrix_111101">300</integer>
<integer name="matrix_111110">300</integer>
<integer name="matrix_111111">300</integer>
- <bool name="usually_false">true</bool>
<integer-array name="fibonacci">
<item>21</item>
<item>13</item>
@@ -29,7 +27,10 @@
<item>1</item>
<item>1</item>
</integer-array>
+
<!-- The following integer does not exist in the original package. Idmap
generation should therefore ignore it. -->
<integer name="integer_not_in_original_package">0</integer>
+
+ <attr name="customAttribute" />
</resources>
diff --git a/core/tests/overlaytests/device/test-apps/AppOverlayOne/res/xml/overlays.xml b/core/tests/overlaytests/device/test-apps/AppOverlayOne/res/xml/overlays.xml
new file mode 100644
index 000000000000..38e5fa18300c
--- /dev/null
+++ b/core/tests/overlaytests/device/test-apps/AppOverlayOne/res/xml/overlays.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<overlay>
+ <item target="drawable/drawable" value="@drawable/drawable"/>
+ <item target="layout/layout" value="@layout/layout"/>
+ <item target="raw/lorem_ipsum" value="@raw/lorem_ipsum"/>
+ <item target="xml/integer" value="@xml/integer"/>
+ <item target="string/str" value="@string/str"/>
+ <item target="string/str2" value="single"/>
+
+ <item target="integer/matrix_100100" value="@integer/matrix_100100"/>
+ <item target="integer/matrix_100101" value="@integer/matrix_100101"/>
+ <item target="integer/matrix_100110" value="@integer/matrix_100110"/>
+ <item target="integer/matrix_100110" value="@integer/matrix_100110"/>
+ <item target="integer/matrix_100111" value="@integer/matrix_100111"/>
+ <item target="integer/matrix_101000" value="@integer/matrix_101000"/>
+ <item target="integer/matrix_101001" value="@integer/matrix_101001"/>
+ <item target="integer/matrix_101010" value="@integer/matrix_101010"/>
+ <item target="integer/matrix_101011" value="@integer/matrix_101011"/>
+ <item target="integer/matrix_101100" value="@integer/matrix_101100"/>
+ <item target="integer/matrix_101101" value="@integer/matrix_101101"/>
+ <item target="integer/matrix_101110" value="@integer/matrix_101110"/>
+ <item target="integer/matrix_101111" value="@integer/matrix_101111"/>
+ <item target="integer/matrix_110100" value="@integer/matrix_110100"/>
+ <item target="integer/matrix_110101" value="@integer/matrix_110101"/>
+ <item target="integer/matrix_110110" value="@integer/matrix_110110"/>
+ <item target="integer/matrix_110111" value="@integer/matrix_110111"/>
+ <item target="integer/matrix_111000" value="@integer/matrix_111000"/>
+ <item target="integer/matrix_111001" value="@integer/matrix_111001"/>
+ <item target="integer/matrix_111010" value="@integer/matrix_111010"/>
+ <item target="integer/matrix_111011" value="@integer/matrix_111011"/>
+ <item target="integer/matrix_111100" value="@integer/matrix_111100"/>
+ <item target="integer/matrix_111101" value="@integer/matrix_111101"/>
+ <item target="integer/matrix_111110" value="@integer/matrix_111110"/>
+ <item target="integer/matrix_111111" value="@integer/matrix_111111"/>
+
+ <item target="bool/usually_false" value="true"/>
+
+ <item target="array/fibonacci" value="@array/fibonacci"/>
+
+ <item target="attr/customAttribute" value="@attr/customAttribute"/>
+ <item target="id/view_1" value="@id/view_1"/>
+ <item target="id/view_2" value="@id/view_2"/>
+ <item target="id/view_3" value="@id/view_3"/>
+</overlay>
+
+
diff --git a/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java b/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java
index 9f70538191c2..67783bff9299 100644
--- a/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java
+++ b/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java
@@ -94,7 +94,7 @@ public class SystemPropertiesTest extends TestCase {
}
@SmallTest
- private static void testHandle() throws Exception {
+ public void testHandle() throws Exception {
String value;
SystemProperties.Handle handle = SystemProperties.find("doesnotexist_2341431");
assertNull(handle);
diff --git a/data/etc/Android.bp b/data/etc/Android.bp
index 183c04e62712..1d3a3997d857 100644
--- a/data/etc/Android.bp
+++ b/data/etc/Android.bp
@@ -28,6 +28,13 @@ prebuilt_etc {
}
prebuilt_etc {
+ name: "preinstalled-packages-platform-overlays.xml",
+ product_specific: true,
+ sub_dir: "sysconfig",
+ src: "preinstalled-packages-platform-overlays.xml",
+}
+
+prebuilt_etc {
name: "hiddenapi-package-whitelist.xml",
sub_dir: "sysconfig",
src: "hiddenapi-package-whitelist.xml",
@@ -128,7 +135,7 @@ prebuilt_etc {
prebuilt_etc {
name: "privapp_whitelist_com.android.systemui",
- product_specific: true,
+ system_ext_specific: true,
sub_dir: "permissions",
src: "com.android.systemui.xml",
filename_from_src: true,
diff --git a/data/etc/CleanSpec.mk b/data/etc/CleanSpec.mk
index b76eb1575b86..783a7edadeb7 100644
--- a/data/etc/CleanSpec.mk
+++ b/data/etc/CleanSpec.mk
@@ -53,6 +53,8 @@ $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/product/etc/permissions/com.
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/product/etc/permissions/com.android.settings.xml)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/product/etc/permissions/com.android.launcher3.xml)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/product/etc/permissions/com.android.launcher3.xml)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/product/etc/permissions/com.android.systemui.xml)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/product/etc/permissions/com.android.systemui.xml)
# ******************************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
# ******************************************************************
diff --git a/data/etc/car/Android.bp b/data/etc/car/Android.bp
index c44565129610..26a40d3dea8c 100644
--- a/data/etc/car/Android.bp
+++ b/data/etc/car/Android.bp
@@ -126,7 +126,7 @@ prebuilt_etc {
sub_dir: "permissions",
src: "com.android.car.developeroptions.xml",
filename_from_src: true,
- product_specific: true,
+ system_ext_specific: true,
}
prebuilt_etc {
diff --git a/data/etc/car/CleanSpec.mk b/data/etc/car/CleanSpec.mk
new file mode 100644
index 000000000000..18f7d343676b
--- /dev/null
+++ b/data/etc/car/CleanSpec.mk
@@ -0,0 +1,50 @@
+# Copyright (C) 2019 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# If you don't need to do a full clean build but would like to touch
+# a file or delete some intermediate files, add a clean step to the end
+# of the list. These steps will only be run once, if they haven't been
+# run before.
+#
+# E.g.:
+# $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
+# $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
+#
+# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
+# files that are missing or have been moved.
+#
+# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
+# Use $(OUT_DIR) to refer to the "out" directory.
+#
+# If you need to re-do something that's already mentioned, just copy
+# the command and add it to the bottom of the list. E.g., if a change
+# that you made last week required touching a file and a change you
+# made today requires touching the same file, just copy the old
+# touch step and add it to the end of the list.
+#
+# *****************************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THE BANNER
+# *****************************************************************
+
+# For example:
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
+#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
+#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/product/etc/permissions/com.android.car.developeroptions.xml)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/product/etc/permissions/com.android.car.developeroptions.xml)
+# ******************************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
+# ******************************************************************
diff --git a/data/etc/hiddenapi-package-whitelist.xml b/data/etc/hiddenapi-package-whitelist.xml
index 07a5617009d5..39973715a47d 100644
--- a/data/etc/hiddenapi-package-whitelist.xml
+++ b/data/etc/hiddenapi-package-whitelist.xml
@@ -65,4 +65,7 @@ Do NOT include any apps that are updatable via Play Store!
<hidden-api-whitelisted-app package="com.android.terminal" />
<hidden-api-whitelisted-app package="com.android.wallpaper" />
<hidden-api-whitelisted-app package="jp.co.omronsoft.openwnn" />
+ <!-- STOPSHIP: Remove this when fixing all @hide usage for tethering.-->
+ <hidden-api-whitelisted-app package="com.android.networkstack.tethering" />
+ <hidden-api-whitelisted-app package="com.android.networkstack" />
</config>
diff --git a/data/etc/preinstalled-packages-platform-overlays.xml b/data/etc/preinstalled-packages-platform-overlays.xml
new file mode 100644
index 000000000000..1724715b557b
--- /dev/null
+++ b/data/etc/preinstalled-packages-platform-overlays.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!-- System packages to preinstall on all devices with frameworks-base-overlays, per user type.
+ Documentation at frameworks/base/data/etc/preinstalled-packages-platform.xml
+-->
+<config>
+ <install-in-user-type package="com.android.internal.display.cutout.emulation.corner">
+ <install-in user-type="FULL" />
+ </install-in-user-type>
+ <install-in-user-type package="com.android.internal.display.cutout.emulation.double">
+ <install-in user-type="FULL" />
+ </install-in-user-type>
+ <install-in-user-type package="com.android.internal.display.cutout.emulation.tall">
+ <install-in user-type="FULL" />
+ </install-in-user-type>
+ <install-in-user-type package="com.android.internal.systemui.navbar.gestural">
+ <install-in user-type="FULL" />
+ </install-in-user-type>
+ <install-in-user-type package="com.android.internal.systemui.navbar.gestural_extra_wide_back">
+ <install-in user-type="FULL" />
+ </install-in-user-type>
+ <install-in-user-type package="com.android.internal.systemui.navbar.gestural_narrow_back">
+ <install-in user-type="FULL" />
+ </install-in-user-type>
+ <install-in-user-type package="com.android.internal.systemui.navbar.gestural_wide_back">
+ <install-in user-type="FULL" />
+ </install-in-user-type>
+ <install-in-user-type package="com.android.internal.systemui.navbar.threebutton">
+ <install-in user-type="FULL" />
+ </install-in-user-type>
+ <install-in-user-type package="com.android.internal.systemui.navbar.twobutton">
+ <install-in user-type="FULL" />
+ </install-in-user-type>
+</config>
diff --git a/data/etc/preinstalled-packages-platform.xml b/data/etc/preinstalled-packages-platform.xml
index 604b4072ca98..efab27f96efa 100644
--- a/data/etc/preinstalled-packages-platform.xml
+++ b/data/etc/preinstalled-packages-platform.xml
@@ -106,4 +106,7 @@ to pre-existing users, but cannot uninstall system packages from pre-existing us
<install-in user-type="FULL" />
<install-in user-type="PROFILE" />
</install-in-user-type>
+ <install-in-user-type package="com.android.wallpaperbackup">
+ <install-in user-type="FULL" />
+ </install-in-user-type>
</config>
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 624fc50030a0..f1941fcd2598 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -240,7 +240,7 @@ applications that come with the platform
<permission name="android.permission.WRITE_SECURE_SETTINGS"/>
</privapp-permissions>
- <privapp-permissions package="com.android.tethering">
+ <privapp-permissions package="com.android.networkstack.tethering">
<permission name="android.permission.MANAGE_USB"/>
<permission name="android.permission.MODIFY_PHONE_STATE"/>
<permission name="android.permission.READ_NETWORK_USAGE_HISTORY"/>
@@ -266,6 +266,8 @@ applications that come with the platform
</privapp-permissions>
<privapp-permissions package="com.android.shell">
+ <!-- Needed for test only -->
+ <permission name="android.permission.MODIFY_DAY_NIGHT_MODE"/>
<permission name="android.permission.ACCESS_LOWPAN_STATE"/>
<permission name="android.permission.BACKUP"/>
<permission name="android.permission.BATTERY_STATS"/>
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index 30604768e6d0..1e98e3afa97c 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -385,6 +385,12 @@
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "-1263316010": {
+ "message": "Computed rotation=%s (%d) for display id=%d based on lastOrientation=%s (%d) and oldRotation=%s (%d)",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_ORIENTATION",
+ "at": "com\/android\/server\/wm\/DisplayRotation.java"
+ },
"-1259022216": {
"message": "SURFACE HIDE ( %s ): %s",
"level": "INFO",
@@ -463,6 +469,12 @@
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "-1108775960": {
+ "message": "%s is requesting orientation %d (%s)",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_ORIENTATION",
+ "at": "com\/android\/server\/wm\/WindowContainer.java"
+ },
"-1103716954": {
"message": "Not removing %s due to exit animation",
"level": "VERBOSE",
@@ -631,6 +643,12 @@
"group": "WM_DEBUG_FOCUS_LIGHT",
"at": "com\/android\/server\/wm\/ActivityRecord.java"
},
+ "-766059044": {
+ "message": "Display id=%d selected orientation %s (%d), got rotation %s (%d)",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_ORIENTATION",
+ "at": "com\/android\/server\/wm\/DisplayRotation.java"
+ },
"-760801764": {
"message": "onAnimationCancelled",
"level": "DEBUG",
@@ -1267,12 +1285,6 @@
"group": "WM_DEBUG_RECENTS_ANIMATIONS",
"at": "com\/android\/server\/wm\/RecentsAnimation.java"
},
- "481370485": {
- "message": "Computed rotation=%d for display id=%d based on lastOrientation=%d and oldRotation=%d",
- "level": "VERBOSE",
- "group": "WM_DEBUG_ORIENTATION",
- "at": "com\/android\/server\/wm\/DisplayRotation.java"
- },
"490877640": {
"message": "onStackOrderChanged(): stack=%s",
"level": "DEBUG",
@@ -1729,6 +1741,12 @@
"group": "WM_DEBUG_APP_TRANSITIONS_ANIM",
"at": "com\/android\/server\/wm\/AppTransition.java"
},
+ "1460759282": {
+ "message": "getAnimationTarget in=%s, out=%s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_APP_TRANSITIONS_ANIM",
+ "at": "com\/android\/server\/wm\/AppTransitionController.java"
+ },
"1469292670": {
"message": "Changing focus from %s to %s displayId=%d Callers=%s",
"level": "VERBOSE",
@@ -1795,12 +1813,6 @@
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
- "1573332272": {
- "message": "Display id=%d selected orientation %d, got rotation %d",
- "level": "VERBOSE",
- "group": "WM_DEBUG_ORIENTATION",
- "at": "com\/android\/server\/wm\/DisplayRotation.java"
- },
"1577579529": {
"message": "win=%s destroySurfaces: appStopped=%b win.mWindowRemovalAllowed=%b win.mRemoveOnExit=%b",
"level": "ERROR",
diff --git a/graphics/java/android/graphics/HardwareRenderer.java b/graphics/java/android/graphics/HardwareRenderer.java
index 3f3ad578e8d7..3b864139cf71 100644
--- a/graphics/java/android/graphics/HardwareRenderer.java
+++ b/graphics/java/android/graphics/HardwareRenderer.java
@@ -28,7 +28,6 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;
import android.util.TimeUtils;
-import android.view.FrameMetricsObserver;
import android.view.IGraphicsStats;
import android.view.IGraphicsStatsCallback;
import android.view.NativeVectorDrawableAnimator;
@@ -38,8 +37,6 @@ import android.view.SurfaceHolder;
import android.view.TextureLayer;
import android.view.animation.AnimationUtils;
-import com.android.internal.util.VirtualRefBasePtr;
-
import java.io.File;
import java.io.FileDescriptor;
import java.lang.annotation.Retention;
@@ -598,9 +595,8 @@ public class HardwareRenderer {
*
* @hide
*/
- public void addFrameMetricsObserver(FrameMetricsObserver observer) {
- long nativeObserver = nAddFrameMetricsObserver(mNativeProxy, observer);
- observer.mNative = new VirtualRefBasePtr(nativeObserver);
+ public void addObserver(HardwareRendererObserver observer) {
+ nAddObserver(mNativeProxy, observer.getNativeInstance());
}
/**
@@ -608,9 +604,8 @@ public class HardwareRenderer {
*
* @hide
*/
- public void removeFrameMetricsObserver(FrameMetricsObserver observer) {
- nRemoveFrameMetricsObserver(mNativeProxy, observer.mNative.get());
- observer.mNative = null;
+ public void removeObserver(HardwareRendererObserver observer) {
+ nRemoveObserver(mNativeProxy, observer.getNativeInstance());
}
/**
@@ -1170,10 +1165,9 @@ public class HardwareRenderer {
private static native void nSetFrameCompleteCallback(long nativeProxy,
FrameCompleteCallback callback);
- private static native long nAddFrameMetricsObserver(long nativeProxy,
- FrameMetricsObserver observer);
+ private static native void nAddObserver(long nativeProxy, long nativeObserver);
- private static native void nRemoveFrameMetricsObserver(long nativeProxy, long nativeObserver);
+ private static native void nRemoveObserver(long nativeProxy, long nativeObserver);
private static native int nCopySurfaceInto(Surface surface,
int srcLeft, int srcTop, int srcRight, int srcBottom, long bitmapHandle);
diff --git a/graphics/java/android/graphics/HardwareRendererObserver.java b/graphics/java/android/graphics/HardwareRendererObserver.java
new file mode 100644
index 000000000000..da9d03c639f7
--- /dev/null
+++ b/graphics/java/android/graphics/HardwareRendererObserver.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics;
+
+import android.annotation.NonNull;
+import android.os.Handler;
+
+import com.android.internal.util.VirtualRefBasePtr;
+
+/**
+ * Provides streaming access to frame stats information from HardwareRenderer to apps.
+ *
+ * @hide
+ */
+public class HardwareRendererObserver {
+ private final long[] mFrameMetrics;
+ private final Handler mHandler;
+ private final OnFrameMetricsAvailableListener mListener;
+ private VirtualRefBasePtr mNativePtr;
+
+ /**
+ * Interface for clients that want frame timing information for each frame rendered.
+ * @hide
+ */
+ public interface OnFrameMetricsAvailableListener {
+ /**
+ * Called when information is available for the previously rendered frame.
+ *
+ * Reports can be dropped if this callback takes too long to execute, as the report producer
+ * cannot wait for the consumer to complete.
+ *
+ * It is highly recommended that clients copy the metrics array within this method
+ * and defer additional computation or storage to another thread to avoid unnecessarily
+ * dropping reports.
+ *
+ * @param dropCountSinceLastInvocation the number of reports dropped since the last time
+ * this callback was invoked.
+ */
+ void onFrameMetricsAvailable(int dropCountSinceLastInvocation);
+ }
+
+ /**
+ * Creates a FrameMetricsObserver
+ *
+ * @param frameMetrics the available metrics. This array is reused on every call to the listener
+ * and thus <strong>this reference should only be used within the scope of the listener callback
+ * as data is not guaranteed to be valid outside the scope of that method</strong>.
+ * @param handler the Handler to use when invoking callbacks
+ */
+ public HardwareRendererObserver(@NonNull OnFrameMetricsAvailableListener listener,
+ @NonNull long[] frameMetrics, @NonNull Handler handler) {
+ if (handler == null || handler.getLooper() == null) {
+ throw new NullPointerException("handler and its looper cannot be null");
+ }
+
+ if (handler.getLooper().getQueue() == null) {
+ throw new IllegalStateException("invalid looper, null message queue\n");
+ }
+
+ mFrameMetrics = frameMetrics;
+ mHandler = handler;
+ mListener = listener;
+ mNativePtr = new VirtualRefBasePtr(nCreateObserver());
+ }
+
+ /*package*/ long getNativeInstance() {
+ return mNativePtr.get();
+ }
+
+ // Called by native on the provided Handler
+ @SuppressWarnings("unused")
+ private void notifyDataAvailable() {
+ mHandler.post(() -> {
+ boolean hasMoreData = true;
+ while (hasMoreData) {
+ // a drop count of -1 is a sentinel that no more buffers are available
+ int dropCount = nGetNextBuffer(mNativePtr.get(), mFrameMetrics);
+ if (dropCount >= 0) {
+ mListener.onFrameMetricsAvailable(dropCount);
+ } else {
+ hasMoreData = false;
+ }
+ }
+ });
+ }
+
+ private native long nCreateObserver();
+ private static native int nGetNextBuffer(long nativePtr, long[] data);
+}
diff --git a/graphics/java/android/graphics/drawable/ColorDrawable.java b/graphics/java/android/graphics/drawable/ColorDrawable.java
index f5fa8c546bed..e93e7dfbe22c 100644
--- a/graphics/java/android/graphics/drawable/ColorDrawable.java
+++ b/graphics/java/android/graphics/drawable/ColorDrawable.java
@@ -20,7 +20,7 @@ import android.annotation.ColorInt;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo.Config;
import android.content.res.ColorStateList;
import android.content.res.Resources;
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 08409869c626..e70529b6cd1a 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -22,7 +22,7 @@ import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo.Config;
import android.content.res.ColorStateList;
import android.content.res.Resources;
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index 090d915a2f67..51b299c9ee5e 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -17,7 +17,7 @@
package android.graphics.drawable;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo.Config;
import android.content.res.ColorStateList;
import android.content.res.Resources;
diff --git a/graphics/java/android/graphics/drawable/DrawableInflater.java b/graphics/java/android/graphics/drawable/DrawableInflater.java
index bad3791a9c24..3408b64e7536 100644
--- a/graphics/java/android/graphics/drawable/DrawableInflater.java
+++ b/graphics/java/android/graphics/drawable/DrawableInflater.java
@@ -16,19 +16,19 @@
package android.graphics.drawable;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
import android.annotation.DrawableRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.Resources.Theme;
import android.util.AttributeSet;
import android.view.InflateException;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.util.HashMap;
diff --git a/graphics/java/android/graphics/drawable/DrawableWrapper.java b/graphics/java/android/graphics/drawable/DrawableWrapper.java
index 6c90c4c6c8a4..e197e7123fed 100644
--- a/graphics/java/android/graphics/drawable/DrawableWrapper.java
+++ b/graphics/java/android/graphics/drawable/DrawableWrapper.java
@@ -18,7 +18,7 @@ package android.graphics.drawable;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo.Config;
import android.content.res.ColorStateList;
import android.content.res.Resources;
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index c6586ecfceb9..3881955d2632 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -22,7 +22,7 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Px;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo.Config;
import android.content.res.ColorStateList;
import android.content.res.Resources;
diff --git a/graphics/java/android/graphics/drawable/Icon.java b/graphics/java/android/graphics/drawable/Icon.java
index c2e3c6419400..cc7182c3fd1c 100644
--- a/graphics/java/android/graphics/drawable/Icon.java
+++ b/graphics/java/android/graphics/drawable/Icon.java
@@ -21,7 +21,7 @@ import android.annotation.DrawableRes;
import android.annotation.IdRes;
import android.annotation.IntDef;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.ApplicationInfo;
diff --git a/graphics/java/android/graphics/drawable/InsetDrawable.java b/graphics/java/android/graphics/drawable/InsetDrawable.java
index bc8a4cbd7e9d..005a4d175fd5 100644
--- a/graphics/java/android/graphics/drawable/InsetDrawable.java
+++ b/graphics/java/android/graphics/drawable/InsetDrawable.java
@@ -18,7 +18,7 @@ package android.graphics.drawable;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.Resources;
import android.content.res.Resources.Theme;
import android.content.res.TypedArray;
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 760d554888ee..fb4146f04bc9 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -18,7 +18,7 @@ package android.graphics.drawable;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo.Config;
import android.content.res.ColorStateList;
import android.content.res.Resources;
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index 8561d95ddd88..99d27ba4c469 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -18,7 +18,7 @@ package android.graphics.drawable;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo.Config;
import android.content.res.ColorStateList;
import android.content.res.Resources;
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index 1540cc22e295..e5e4d4527fca 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -18,7 +18,7 @@ package android.graphics.drawable;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo.Config;
import android.content.res.ColorStateList;
import android.content.res.Resources;
diff --git a/graphics/java/android/graphics/drawable/RotateDrawable.java b/graphics/java/android/graphics/drawable/RotateDrawable.java
index db5f082bd853..43766b636adb 100644
--- a/graphics/java/android/graphics/drawable/RotateDrawable.java
+++ b/graphics/java/android/graphics/drawable/RotateDrawable.java
@@ -16,22 +16,22 @@
package android.graphics.drawable;
-import com.android.internal.R;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
-import android.graphics.Canvas;
-import android.graphics.Rect;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.Resources;
-import android.content.res.TypedArray;
import android.content.res.Resources.Theme;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.util.AttributeSet;
import android.util.MathUtils;
import android.util.TypedValue;
-import android.util.AttributeSet;
+
+import com.android.internal.R;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
diff --git a/graphics/java/android/graphics/drawable/ScaleDrawable.java b/graphics/java/android/graphics/drawable/ScaleDrawable.java
index 91ed061e511d..af7eed4b3897 100644
--- a/graphics/java/android/graphics/drawable/ScaleDrawable.java
+++ b/graphics/java/android/graphics/drawable/ScaleDrawable.java
@@ -16,14 +16,9 @@
package android.graphics.drawable;
-import com.android.internal.R;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.Resources;
import android.content.res.Resources.Theme;
import android.content.res.TypedArray;
@@ -34,6 +29,11 @@ import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
+import com.android.internal.R;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
import java.io.IOException;
/**
diff --git a/graphics/java/android/graphics/drawable/StateListDrawable.java b/graphics/java/android/graphics/drawable/StateListDrawable.java
index f67188c22609..2920acbe514c 100644
--- a/graphics/java/android/graphics/drawable/StateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/StateListDrawable.java
@@ -18,7 +18,7 @@ package android.graphics.drawable;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.Resources;
import android.content.res.Resources.Theme;
import android.content.res.TypedArray;
diff --git a/graphics/java/android/graphics/drawable/TransitionDrawable.java b/graphics/java/android/graphics/drawable/TransitionDrawable.java
index 276f3662189b..401e05ffc139 100644
--- a/graphics/java/android/graphics/drawable/TransitionDrawable.java
+++ b/graphics/java/android/graphics/drawable/TransitionDrawable.java
@@ -16,7 +16,7 @@
package android.graphics.drawable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo.Config;
import android.content.res.Resources;
import android.graphics.Canvas;
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index aa19b2a0e94c..e6fa866df3ab 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -16,7 +16,7 @@ package android.graphics.drawable;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo.Config;
import android.content.res.ColorStateList;
import android.content.res.ComplexColor;
diff --git a/graphics/java/android/graphics/fonts/FontVariationAxis.java b/graphics/java/android/graphics/fonts/FontVariationAxis.java
index bcee559d8291..4e6580ea5f53 100644
--- a/graphics/java/android/graphics/fonts/FontVariationAxis.java
+++ b/graphics/java/android/graphics/fonts/FontVariationAxis.java
@@ -18,7 +18,7 @@ package android.graphics.fonts;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.text.TextUtils;
diff --git a/graphics/java/android/graphics/pdf/PdfRenderer.java b/graphics/java/android/graphics/pdf/PdfRenderer.java
index bd1a49205fd5..54710e58687c 100644
--- a/graphics/java/android/graphics/pdf/PdfRenderer.java
+++ b/graphics/java/android/graphics/pdf/PdfRenderer.java
@@ -19,7 +19,7 @@ package android.graphics.pdf;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Matrix;
@@ -29,7 +29,9 @@ import android.os.ParcelFileDescriptor;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
+
import com.android.internal.util.Preconditions;
+
import dalvik.system.CloseGuard;
import libcore.io.IoUtils;
diff --git a/keystore/java/android/security/Credentials.java b/keystore/java/android/security/Credentials.java
index 048dee604a37..f53a7dc922f0 100644
--- a/keystore/java/android/security/Credentials.java
+++ b/keystore/java/android/security/Credentials.java
@@ -16,7 +16,7 @@
package android.security;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import com.android.org.bouncycastle.util.io.pem.PemObject;
import com.android.org.bouncycastle.util.io.pem.PemReader;
diff --git a/keystore/java/android/security/GateKeeper.java b/keystore/java/android/security/GateKeeper.java
index a50ff7984341..af188a95c929 100644
--- a/keystore/java/android/security/GateKeeper.java
+++ b/keystore/java/android/security/GateKeeper.java
@@ -16,7 +16,7 @@
package android.security;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.RemoteException;
import android.os.ServiceManager;
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index d9ed5f32cfc3..dc57f55bb4af 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -16,10 +16,10 @@
package android.security;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
import android.app.Application;
import android.app.KeyguardManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.face.FaceManager;
@@ -31,7 +31,6 @@ import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
-import android.security.KeyStoreException;
import android.security.keymaster.ExportResult;
import android.security.keymaster.KeyCharacteristics;
import android.security.keymaster.KeymasterArguments;
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java b/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java
index d03329445b18..71e6559c53c6 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java
@@ -18,7 +18,7 @@ package android.security.keystore;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.security.KeyStore;
import android.security.keymaster.ExportResult;
import android.security.keymaster.KeyCharacteristics;
diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
index 6df3b8c7661e..52ff9e0449ca 100644
--- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java
+++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
@@ -21,8 +21,8 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.KeyguardManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricPrompt;
import android.security.GateKeeper;
diff --git a/libs/androidfw/Idmap.cpp b/libs/androidfw/Idmap.cpp
index 773353d32d51..0b2fd9ec982d 100644
--- a/libs/androidfw/Idmap.cpp
+++ b/libs/androidfw/Idmap.cpp
@@ -43,6 +43,10 @@ static bool compare_overlay_entries(const Idmap_overlay_entry& e1, const uint32_
return dtohl(e1.overlay_id) < overlay_id;
}
+size_t Idmap_header::Size() const {
+ return sizeof(Idmap_header) + sizeof(uint8_t) * dtohl(debug_info_size);
+}
+
OverlayStringPool::OverlayStringPool(const LoadedIdmap* loaded_idmap)
: data_header_(loaded_idmap->data_header_),
idmap_string_pool_(loaded_idmap->string_pool_.get()) { };
@@ -53,7 +57,7 @@ OverlayStringPool::~OverlayStringPool() {
const char16_t* OverlayStringPool::stringAt(size_t idx, size_t* outLen) const {
const size_t offset = dtohl(data_header_->string_pool_index_offset);
- if (idmap_string_pool_ != nullptr && idx >= size() && idx >= offset) {
+ if (idmap_string_pool_ != nullptr && idx >= ResStringPool::size() && idx >= offset) {
return idmap_string_pool_->stringAt(idx - offset, outLen);
}
@@ -62,13 +66,17 @@ const char16_t* OverlayStringPool::stringAt(size_t idx, size_t* outLen) const {
const char* OverlayStringPool::string8At(size_t idx, size_t* outLen) const {
const size_t offset = dtohl(data_header_->string_pool_index_offset);
- if (idmap_string_pool_ != nullptr && idx >= size() && idx >= offset) {
+ if (idmap_string_pool_ != nullptr && idx >= ResStringPool::size() && idx >= offset) {
return idmap_string_pool_->string8At(idx - offset, outLen);
}
return ResStringPool::string8At(idx, outLen);
}
+size_t OverlayStringPool::size() const {
+ return ResStringPool::size() + (idmap_string_pool_ != nullptr ? idmap_string_pool_->size() : 0U);
+}
+
OverlayDynamicRefTable::OverlayDynamicRefTable(const Idmap_data_header* data_header,
const Idmap_overlay_entry* entries,
uint8_t target_assigned_package_id)
@@ -211,8 +219,8 @@ std::unique_ptr<const LoadedIdmap> LoadedIdmap::Load(const StringPiece& idmap_da
}
auto header = reinterpret_cast<const Idmap_header*>(idmap_data.data());
- const uint8_t* data_ptr = reinterpret_cast<const uint8_t*>(idmap_data.data()) + sizeof(*header);
- size_t data_size = idmap_data.size() - sizeof(*header);
+ const uint8_t* data_ptr = reinterpret_cast<const uint8_t*>(idmap_data.data()) + header->Size();
+ size_t data_size = idmap_data.size() - header->Size();
// Currently idmap2 can only generate one data block.
auto data_header = reinterpret_cast<const Idmap_data_header*>(data_ptr);
diff --git a/libs/androidfw/LocaleDataTables.cpp b/libs/androidfw/LocaleDataTables.cpp
index c462eb7f2401..e748bd886ebc 100644
--- a/libs/androidfw/LocaleDataTables.cpp
+++ b/libs/androidfw/LocaleDataTables.cpp
@@ -118,6 +118,7 @@ const std::unordered_map<uint32_t, uint8_t> LIKELY_SCRIPTS({
{0x80600000u, 44u}, // ada -> Latn
{0x90600000u, 44u}, // ade -> Latn
{0xA4600000u, 44u}, // adj -> Latn
+ {0xBC600000u, 88u}, // adp -> Tibt
{0xE0600000u, 16u}, // ady -> Cyrl
{0xE4600000u, 44u}, // adz -> Latn
{0x61650000u, 4u}, // ae -> Avst
@@ -145,6 +146,7 @@ const std::unordered_map<uint32_t, uint8_t> LIKELY_SCRIPTS({
{0xB5800000u, 44u}, // amn -> Latn
{0xB9800000u, 44u}, // amo -> Latn
{0xBD800000u, 44u}, // amp -> Latn
+ {0x616E0000u, 44u}, // an -> Latn
{0x89A00000u, 44u}, // anc -> Latn
{0xA9A00000u, 44u}, // ank -> Latn
{0xB5A00000u, 44u}, // ann -> Latn
@@ -165,6 +167,7 @@ const std::unordered_map<uint32_t, uint8_t> LIKELY_SCRIPTS({
{0xB6200000u, 44u}, // arn -> Latn
{0xBA200000u, 44u}, // aro -> Latn
{0xC2200000u, 1u}, // arq -> Arab
+ {0xCA200000u, 1u}, // ars -> Arab
{0xE2200000u, 1u}, // ary -> Arab
{0xE6200000u, 1u}, // arz -> Arab
{0x61730000u, 7u}, // as -> Beng
@@ -236,7 +239,6 @@ const std::unordered_map<uint32_t, uint8_t> LIKELY_SCRIPTS({
{0x84E10000u, 17u}, // bhb -> Deva
{0x98E10000u, 44u}, // bhg -> Latn
{0xA0E10000u, 17u}, // bhi -> Deva
- {0xA8E10000u, 44u}, // bhk -> Latn
{0xACE10000u, 44u}, // bhl -> Latn
{0xB8E10000u, 17u}, // bho -> Deva
{0xE0E10000u, 44u}, // bhy -> Latn
@@ -332,6 +334,7 @@ const std::unordered_map<uint32_t, uint8_t> LIKELY_SCRIPTS({
{0xB8E20000u, 44u}, // cho -> Latn
{0xBCE20000u, 44u}, // chp -> Latn
{0xC4E20000u, 13u}, // chr -> Cher
+ {0x89020000u, 44u}, // cic -> Latn
{0x81220000u, 1u}, // cja -> Arab
{0xB1220000u, 12u}, // cjm -> Cham
{0xD5220000u, 44u}, // cjv -> Latn
@@ -387,6 +390,7 @@ const std::unordered_map<uint32_t, uint8_t> LIKELY_SCRIPTS({
{0xA1C30000u, 1u}, // doi -> Arab
{0xBDC30000u, 44u}, // dop -> Latn
{0xD9C30000u, 44u}, // dow -> Latn
+ {0x9E230000u, 54u}, // drh -> Mong
{0xA2230000u, 44u}, // dri -> Latn
{0xCA230000u, 19u}, // drs -> Ethi
{0x86430000u, 44u}, // dsb -> Latn
@@ -737,6 +741,7 @@ const std::unordered_map<uint32_t, uint8_t> LIKELY_SCRIPTS({
{0x866A0000u, 19u}, // ktb -> Ethi
{0xB26A0000u, 44u}, // ktm -> Latn
{0xBA6A0000u, 44u}, // kto -> Latn
+ {0xC66A0000u, 44u}, // ktr -> Latn
{0x6B750000u, 44u}, // ku -> Latn
{0x6B754952u, 1u}, // ku-IR -> Arab
{0x6B754C42u, 1u}, // ku-LB -> Arab
@@ -755,8 +760,10 @@ const std::unordered_map<uint32_t, uint8_t> LIKELY_SCRIPTS({
{0x6B770000u, 44u}, // kw -> Latn
{0xA6CA0000u, 44u}, // kwj -> Latn
{0xBACA0000u, 44u}, // kwo -> Latn
+ {0xC2CA0000u, 44u}, // kwq -> Latn
{0x82EA0000u, 44u}, // kxa -> Latn
{0x8AEA0000u, 19u}, // kxc -> Ethi
+ {0x92EA0000u, 44u}, // kxe -> Latn
{0xB2EA0000u, 87u}, // kxm -> Thai
{0xBEEA0000u, 1u}, // kxp -> Arab
{0xDAEA0000u, 44u}, // kxw -> Latn
@@ -766,7 +773,9 @@ const std::unordered_map<uint32_t, uint8_t> LIKELY_SCRIPTS({
{0x6B795452u, 44u}, // ky-TR -> Latn
{0x930A0000u, 44u}, // kye -> Latn
{0xDF0A0000u, 44u}, // kyx -> Latn
+ {0xA72A0000u, 44u}, // kzj -> Latn
{0xC72A0000u, 44u}, // kzr -> Latn
+ {0xCF2A0000u, 44u}, // kzt -> Latn
{0x6C610000u, 44u}, // la -> Latn
{0x840B0000u, 46u}, // lab -> Lina
{0x8C0B0000u, 30u}, // lad -> Hebr
@@ -899,6 +908,7 @@ const std::unordered_map<uint32_t, uint8_t> LIKELY_SCRIPTS({
{0x95AC0000u, 44u}, // mnf -> Latn
{0xA1AC0000u, 7u}, // mni -> Beng
{0xD9AC0000u, 56u}, // mnw -> Mymr
+ {0x6D6F0000u, 44u}, // mo -> Latn
{0x81CC0000u, 44u}, // moa -> Latn
{0x91CC0000u, 44u}, // moe -> Latn
{0x9DCC0000u, 44u}, // moh -> Latn
@@ -1069,6 +1079,7 @@ const std::unordered_map<uint32_t, uint8_t> LIKELY_SCRIPTS({
{0xB5AF0000u, 44u}, // pnn -> Latn
{0xCDAF0000u, 24u}, // pnt -> Grek
{0xB5CF0000u, 44u}, // pon -> Latn
+ {0x81EF0000u, 17u}, // ppa -> Deva
{0xB9EF0000u, 44u}, // ppo -> Latn
{0x822F0000u, 38u}, // pra -> Khar
{0x8E2F0000u, 1u}, // prd -> Arab
@@ -1241,6 +1252,7 @@ const std::unordered_map<uint32_t, uint8_t> LIKELY_SCRIPTS({
{0x8C730000u, 79u}, // tdd -> Tale
{0x98730000u, 17u}, // tdg -> Deva
{0x9C730000u, 17u}, // tdh -> Deva
+ {0xD0730000u, 44u}, // tdu -> Latn
{0x74650000u, 84u}, // te -> Telu
{0x8C930000u, 44u}, // ted -> Latn
{0xB0930000u, 44u}, // tem -> Latn
@@ -1326,6 +1338,7 @@ const std::unordered_map<uint32_t, uint8_t> LIKELY_SCRIPTS({
{0xC5B40000u, 7u}, // unr -> Beng
{0xC5B44E50u, 17u}, // unr-NP -> Deva
{0xDDB40000u, 7u}, // unx -> Beng
+ {0xA9D40000u, 44u}, // uok -> Latn
{0x75720000u, 1u}, // ur -> Arab
{0xA2340000u, 44u}, // uri -> Latn
{0xCE340000u, 44u}, // urt -> Latn
@@ -1479,6 +1492,7 @@ std::unordered_set<uint64_t> REPRESENTATIVE_LOCALES({
0x904049444C61746ELLU, // ace_Latn_ID
0x9C4055474C61746ELLU, // ach_Latn_UG
0x806047484C61746ELLU, // ada_Latn_GH
+ 0xBC60425454696274LLU, // adp_Tibt_BT
0xE06052554379726CLLU, // ady_Cyrl_RU
0x6165495241767374LLU, // ae_Avst_IR
0x8480544E41726162LLU, // aeb_Arab_TN
@@ -1491,6 +1505,7 @@ std::unordered_set<uint64_t> REPRESENTATIVE_LOCALES({
0xCD6052554379726CLLU, // alt_Cyrl_RU
0x616D455445746869LLU, // am_Ethi_ET
0xB9804E474C61746ELLU, // amo_Latn_NG
+ 0x616E45534C61746ELLU, // an_Latn_ES
0xE5C049444C61746ELLU, // aoz_Latn_ID
0x8DE0544741726162LLU, // apd_Arab_TG
0x6172454741726162LLU, // ar_Arab_EG
@@ -1500,6 +1515,7 @@ std::unordered_set<uint64_t> REPRESENTATIVE_LOCALES({
0xB620434C4C61746ELLU, // arn_Latn_CL
0xBA20424F4C61746ELLU, // aro_Latn_BO
0xC220445A41726162LLU, // arq_Arab_DZ
+ 0xCA20534141726162LLU, // ars_Arab_SA
0xE2204D4141726162LLU, // ary_Arab_MA
0xE620454741726162LLU, // arz_Arab_EG
0x6173494E42656E67LLU, // as_Beng_IN
@@ -1537,7 +1553,6 @@ std::unordered_set<uint64_t> REPRESENTATIVE_LOCALES({
0xDCC154524772656BLLU, // bgx_Grek_TR
0x84E1494E44657661LLU, // bhb_Deva_IN
0xA0E1494E44657661LLU, // bhi_Deva_IN
- 0xA8E150484C61746ELLU, // bhk_Latn_PH
0xB8E1494E44657661LLU, // bho_Deva_IN
0x626956554C61746ELLU, // bi_Latn_VU
0xA90150484C61746ELLU, // bik_Latn_PH
@@ -1584,6 +1599,7 @@ std::unordered_set<uint64_t> REPRESENTATIVE_LOCALES({
0xB8E255534C61746ELLU, // cho_Latn_US
0xBCE243414C61746ELLU, // chp_Latn_CA
0xC4E2555343686572LLU, // chr_Cher_US
+ 0x890255534C61746ELLU, // cic_Latn_US
0x81224B4841726162LLU, // cja_Arab_KH
0xB122564E4368616DLLU, // cjm_Cham_VN
0x8542495141726162LLU, // ckb_Arab_IQ
@@ -1617,6 +1633,7 @@ std::unordered_set<uint64_t> REPRESENTATIVE_LOCALES({
0x91234E454C61746ELLU, // dje_Latn_NE
0xA5A343494C61746ELLU, // dnj_Latn_CI
0xA1C3494E41726162LLU, // doi_Arab_IN
+ 0x9E23434E4D6F6E67LLU, // drh_Mong_CN
0x864344454C61746ELLU, // dsb_Latn_DE
0xB2634D4C4C61746ELLU, // dtm_Latn_ML
0xBE634D594C61746ELLU, // dtp_Latn_MY
@@ -1809,6 +1826,7 @@ std::unordered_set<uint64_t> REPRESENTATIVE_LOCALES({
0x864A545A4C61746ELLU, // ksb_Latn_TZ
0x964A434D4C61746ELLU, // ksf_Latn_CM
0x9E4A44454C61746ELLU, // ksh_Latn_DE
+ 0xC66A4D594C61746ELLU, // ktr_Latn_MY
0x6B75495141726162LLU, // ku_Arab_IQ
0x6B7554524C61746ELLU, // ku_Latn_TR
0xB28A52554379726CLLU, // kum_Cyrl_RU
@@ -1821,6 +1839,8 @@ std::unordered_set<uint64_t> REPRESENTATIVE_LOCALES({
0x6B79434E41726162LLU, // ky_Arab_CN
0x6B794B474379726CLLU, // ky_Cyrl_KG
0x6B7954524C61746ELLU, // ky_Latn_TR
+ 0xA72A4D594C61746ELLU, // kzj_Latn_MY
+ 0xCF2A4D594C61746ELLU, // kzt_Latn_MY
0x6C6156414C61746ELLU, // la_Latn_VA
0x840B47524C696E61LLU, // lab_Lina_GR
0x8C0B494C48656272LLU, // lad_Hebr_IL
@@ -1893,6 +1913,7 @@ std::unordered_set<uint64_t> REPRESENTATIVE_LOCALES({
0x6D6E434E4D6F6E67LLU, // mn_Mong_CN
0xA1AC494E42656E67LLU, // mni_Beng_IN
0xD9AC4D4D4D796D72LLU, // mnw_Mymr_MM
+ 0x6D6F524F4C61746ELLU, // mo_Latn_RO
0x91CC43414C61746ELLU, // moe_Latn_CA
0x9DCC43414C61746ELLU, // moh_Latn_CA
0xC9CC42464C61746ELLU, // mos_Latn_BF
@@ -1981,6 +2002,7 @@ std::unordered_set<uint64_t> REPRESENTATIVE_LOCALES({
0xC98F49544C61746ELLU, // pms_Latn_IT
0xCDAF47524772656BLLU, // pnt_Grek_GR
0xB5CF464D4C61746ELLU, // pon_Latn_FM
+ 0x81EF494E44657661LLU, // ppa_Deva_IN
0x822F504B4B686172LLU, // pra_Khar_PK
0x8E2F495241726162LLU, // prd_Arab_IR
0x7073414641726162LLU, // ps_Arab_AF
@@ -2094,6 +2116,7 @@ std::unordered_set<uint64_t> REPRESENTATIVE_LOCALES({
0x8C73434E54616C65LLU, // tdd_Tale_CN
0x98734E5044657661LLU, // tdg_Deva_NP
0x9C734E5044657661LLU, // tdh_Deva_NP
+ 0xD0734D594C61746ELLU, // tdu_Latn_MY
0x7465494E54656C75LLU, // te_Telu_IN
0xB093534C4C61746ELLU, // tem_Latn_SL
0xB89355474C61746ELLU, // teo_Latn_UG
diff --git a/libs/androidfw/OWNERS b/libs/androidfw/OWNERS
index 87b14673ea2c..8cffd6a3e548 100644
--- a/libs/androidfw/OWNERS
+++ b/libs/androidfw/OWNERS
@@ -3,3 +3,4 @@ toddke@google.com
rtmitchell@google.com
per-file CursorWindow.cpp=omakoto@google.com
+per-file LocaleDataTables.cpp=vichang@google.com,tobiast@google.com,nikitai@google.com
diff --git a/libs/androidfw/include/androidfw/Idmap.h b/libs/androidfw/include/androidfw/Idmap.h
index ab4c9c204842..ccb57f373473 100644
--- a/libs/androidfw/include/androidfw/Idmap.h
+++ b/libs/androidfw/include/androidfw/Idmap.h
@@ -40,8 +40,9 @@ class IdmapResMap;
class OverlayStringPool : public ResStringPool {
public:
virtual ~OverlayStringPool();
- virtual const char16_t* stringAt(size_t idx, size_t* outLen) const;
- virtual const char* string8At(size_t idx, size_t* outLen) const;
+ const char16_t* stringAt(size_t idx, size_t* outLen) const override;
+ const char* string8At(size_t idx, size_t* outLen) const override;
+ size_t size() const override;
explicit OverlayStringPool(const LoadedIdmap* loaded_idmap);
private:
@@ -53,8 +54,8 @@ class OverlayStringPool : public ResStringPool {
// resources to the resource id of corresponding target resources.
class OverlayDynamicRefTable : public DynamicRefTable {
public:
- virtual ~OverlayDynamicRefTable() = default;
- virtual status_t lookupResourceId(uint32_t* resId) const;
+ ~OverlayDynamicRefTable() override = default;
+ status_t lookupResourceId(uint32_t* resId) const override;
private:
explicit OverlayDynamicRefTable(const Idmap_data_header* data_header,
diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h
index b20e6579fda7..35cebd425dc7 100644
--- a/libs/androidfw/include/androidfw/ResourceTypes.h
+++ b/libs/androidfw/include/androidfw/ResourceTypes.h
@@ -39,7 +39,7 @@
namespace android {
constexpr const static uint32_t kIdmapMagic = 0x504D4449u;
-constexpr const static uint32_t kIdmapCurrentVersion = 0x00000002u;
+constexpr const static uint32_t kIdmapCurrentVersion = 0x00000003u;
/**
* In C++11, char16_t is defined as *at least* 16 bits. We do a lot of
@@ -520,7 +520,7 @@ public:
ssize_t indexOfString(const char16_t* str, size_t strLen) const;
- size_t size() const;
+ virtual size_t size() const;
size_t styleCount() const;
size_t bytes() const;
const void* data() const;
@@ -1724,6 +1724,11 @@ struct Idmap_header {
uint8_t target_path[256];
uint8_t overlay_path[256];
+
+ uint32_t debug_info_size;
+ uint8_t debug_info[0];
+
+ size_t Size() const;
};
struct Idmap_data_header {
diff --git a/libs/androidfw/tests/data/overlay/overlay.apk b/libs/androidfw/tests/data/overlay/overlay.apk
index c594b8e67f28..62e98662e68d 100644
--- a/libs/androidfw/tests/data/overlay/overlay.apk
+++ b/libs/androidfw/tests/data/overlay/overlay.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/overlay/overlay.idmap b/libs/androidfw/tests/data/overlay/overlay.idmap
index 27cf792ff7e2..3759ed650033 100644
--- a/libs/androidfw/tests/data/overlay/overlay.idmap
+++ b/libs/androidfw/tests/data/overlay/overlay.idmap
Binary files differ
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index eb469a810358..c1fed269de5b 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -22,7 +22,6 @@
#include <log/log.h>
#include <private/gui/SyncFeatures.h>
#include <sync/sync.h>
-#include <system/window.h>
#include <utils/Trace.h>
#include <string>
diff --git a/libs/hwui/renderthread/VulkanSurface.cpp b/libs/hwui/renderthread/VulkanSurface.cpp
index bbffb359aebe..a7ea21d8c4de 100644
--- a/libs/hwui/renderthread/VulkanSurface.cpp
+++ b/libs/hwui/renderthread/VulkanSurface.cpp
@@ -29,12 +29,12 @@ namespace renderthread {
static int InvertTransform(int transform) {
switch (transform) {
- case NATIVE_WINDOW_TRANSFORM_ROT_90:
- return NATIVE_WINDOW_TRANSFORM_ROT_270;
- case NATIVE_WINDOW_TRANSFORM_ROT_180:
- return NATIVE_WINDOW_TRANSFORM_ROT_180;
- case NATIVE_WINDOW_TRANSFORM_ROT_270:
- return NATIVE_WINDOW_TRANSFORM_ROT_90;
+ case ANATIVEWINDOW_TRANSFORM_ROTATE_90:
+ return ANATIVEWINDOW_TRANSFORM_ROTATE_270;
+ case ANATIVEWINDOW_TRANSFORM_ROTATE_180:
+ return ANATIVEWINDOW_TRANSFORM_ROTATE_180;
+ case ANATIVEWINDOW_TRANSFORM_ROTATE_270:
+ return ANATIVEWINDOW_TRANSFORM_ROTATE_90;
default:
return 0;
}
@@ -47,11 +47,11 @@ static SkMatrix GetPreTransformMatrix(SkISize windowSize, int transform) {
switch (transform) {
case 0:
return SkMatrix::I();
- case NATIVE_WINDOW_TRANSFORM_ROT_90:
+ case ANATIVEWINDOW_TRANSFORM_ROTATE_90:
return SkMatrix::MakeAll(0, -1, height, 1, 0, 0, 0, 0, 1);
- case NATIVE_WINDOW_TRANSFORM_ROT_180:
+ case ANATIVEWINDOW_TRANSFORM_ROTATE_180:
return SkMatrix::MakeAll(-1, 0, width, 0, -1, height, 0, 0, 1);
- case NATIVE_WINDOW_TRANSFORM_ROT_270:
+ case ANATIVEWINDOW_TRANSFORM_ROTATE_270:
return SkMatrix::MakeAll(0, 1, 0, -1, 0, width, 0, 0, 1);
default:
LOG_ALWAYS_FATAL("Unsupported Window Transform (%d)", transform);
@@ -168,7 +168,7 @@ bool VulkanSurface::InitializeWindowInfoStruct(ANativeWindow* window, ColorMode
outWindowInfo->transform = query_value;
outWindowInfo->actualSize = outWindowInfo->size;
- if (outWindowInfo->transform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
+ if (outWindowInfo->transform & ANATIVEWINDOW_TRANSFORM_ROTATE_90) {
outWindowInfo->actualSize.set(outWindowInfo->size.height(), outWindowInfo->size.width());
}
diff --git a/location/java/android/location/Country.java b/location/java/android/location/Country.java
index f3c2a1684cda..8c40338e80fc 100644
--- a/location/java/android/location/Country.java
+++ b/location/java/android/location/Country.java
@@ -16,7 +16,7 @@
package android.location;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemClock;
diff --git a/location/java/android/location/CountryDetector.java b/location/java/android/location/CountryDetector.java
index ae139499eeb2..e344b820ca2a 100644
--- a/location/java/android/location/CountryDetector.java
+++ b/location/java/android/location/CountryDetector.java
@@ -16,10 +16,8 @@
package android.location;
-import java.util.HashMap;
-
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Build;
import android.os.Handler;
@@ -27,6 +25,8 @@ import android.os.Looper;
import android.os.RemoteException;
import android.util.Log;
+import java.util.HashMap;
+
/**
* This class provides access to the system country detector service. This
* service allows applications to obtain the country that the user is in.
diff --git a/location/java/android/location/CountryListener.java b/location/java/android/location/CountryListener.java
index 70a83c5acdd9..eb67205f4de9 100644
--- a/location/java/android/location/CountryListener.java
+++ b/location/java/android/location/CountryListener.java
@@ -16,7 +16,7 @@
package android.location;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* The listener for receiving the notification when the country is detected or
diff --git a/location/java/android/location/GeocoderParams.java b/location/java/android/location/GeocoderParams.java
index 45d92ee7cc34..1c6e9b6e1836 100644
--- a/location/java/android/location/GeocoderParams.java
+++ b/location/java/android/location/GeocoderParams.java
@@ -16,7 +16,7 @@
package android.location;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/location/java/android/location/Geofence.java b/location/java/android/location/Geofence.java
index 9570b26452e4..af57bfd30984 100644
--- a/location/java/android/location/Geofence.java
+++ b/location/java/android/location/Geofence.java
@@ -16,7 +16,7 @@
package android.location;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/location/java/android/location/Location.java b/location/java/android/location/Location.java
index db48ee7f2cf9..7a12cee899d8 100644
--- a/location/java/android/location/Location.java
+++ b/location/java/android/location/Location.java
@@ -19,7 +19,7 @@ package android.location;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcel;
diff --git a/location/java/android/location/LocationListener.java b/location/java/android/location/LocationListener.java
index aa9dddc03515..8df08345c79b 100644
--- a/location/java/android/location/LocationListener.java
+++ b/location/java/android/location/LocationListener.java
@@ -16,6 +16,7 @@
package android.location;
+import android.annotation.NonNull;
import android.os.Bundle;
/**
@@ -37,36 +38,32 @@ public interface LocationListener {
/**
* Called when the location has changed.
*
- * <p> There are no restrictions on the use of the supplied Location object.
- *
- * @param location The new location, as a Location object.
+ * @param location the updated location
*/
- void onLocationChanged(Location location);
+ void onLocationChanged(@NonNull Location location);
/**
- * This callback will never be invoked and providers can be considers as always in the
- * {@link LocationProvider#AVAILABLE} state.
+ * This callback will never be invoked on Android Q and above, and providers can be considered
+ * as always in the {@link LocationProvider#AVAILABLE} state.
*
- * @deprecated This callback will never be invoked.
+ * @deprecated This callback will never be invoked on Android Q and above.
*/
@Deprecated
- void onStatusChanged(String provider, int status, Bundle extras);
+ default void onStatusChanged(String provider, int status, Bundle extras) {}
/**
* Called when the provider is enabled by the user.
*
- * @param provider the name of the location provider associated with this
- * update.
+ * @param provider the name of the location provider that has become enabled
*/
- void onProviderEnabled(String provider);
+ default void onProviderEnabled(@NonNull String provider) {}
/**
* Called when the provider is disabled by the user. If requestLocationUpdates
* is called on an already disabled provider, this method is called
* immediately.
*
- * @param provider the name of the location provider associated with this
- * update.
+ * @param provider the name of the location provider that has become disabled
*/
- void onProviderDisabled(String provider);
+ default void onProviderDisabled(@NonNull String provider) {}
}
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index aa1484f21862..687535c3304b 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -31,9 +31,9 @@ import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.AlarmManager;
import android.app.PendingIntent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Binder;
diff --git a/location/java/android/location/LocationRequest.java b/location/java/android/location/LocationRequest.java
index ca8f2ac82e94..f3e4d81285bd 100644
--- a/location/java/android/location/LocationRequest.java
+++ b/location/java/android/location/LocationRequest.java
@@ -22,7 +22,7 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
index f9b2fe057995..9846436b3ac8 100644
--- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
+++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
@@ -19,6 +19,7 @@ package com.android.internal.location;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -37,8 +38,6 @@ import com.android.internal.R;
import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.telephony.GsmAlphabet;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
import java.io.UnsupportedEncodingException;
import java.util.concurrent.TimeUnit;
@@ -126,7 +125,7 @@ public class GpsNetInitiatedHandler {
public static class GpsNiNotification
{
- @android.annotation.UnsupportedAppUsage
+ @android.compat.annotation.UnsupportedAppUsage
public GpsNiNotification() {
}
public int notificationId;
diff --git a/location/java/com/android/internal/location/ProviderRequest.java b/location/java/com/android/internal/location/ProviderRequest.java
index 155f788cb33e..c23f49976799 100644
--- a/location/java/com/android/internal/location/ProviderRequest.java
+++ b/location/java/com/android/internal/location/ProviderRequest.java
@@ -16,7 +16,7 @@
package com.android.internal.location;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.location.LocationRequest;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/media/Android.bp b/media/Android.bp
index 75ccb227e5c5..a1365179c53a 100644
--- a/media/Android.bp
+++ b/media/Android.bp
@@ -26,7 +26,8 @@ java_library {
installable: true,
- // Make sure that the implementaion only relies on SDK or system APIs.
+ // TODO: build against stable API surface. Use core_platform for now to avoid
+ // link-check failure with exoplayer building against "current".
sdk_version: "core_platform",
libs: [
// The order matters. android_system_* library should come later.
@@ -101,6 +102,7 @@ java_library {
name: "framework_media_annotation",
srcs: [":framework-media-annotation-srcs"],
installable: false,
+ sdk_version: "core_current",
}
aidl_interface {
diff --git a/media/java/android/media/AmrInputStream.java b/media/java/android/media/AmrInputStream.java
index 5088798a2910..3cb224dd58cd 100644
--- a/media/java/android/media/AmrInputStream.java
+++ b/media/java/android/media/AmrInputStream.java
@@ -16,14 +16,14 @@
package android.media;
-import java.io.InputStream;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.media.MediaCodec.BufferInfo;
import android.util.Log;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+
/**
* DO NOT USE
diff --git a/media/java/android/media/AsyncPlayer.java b/media/java/android/media/AsyncPlayer.java
index 8ac26553bab4..c3dc118fec7e 100644
--- a/media/java/android/media/AsyncPlayer.java
+++ b/media/java/android/media/AsyncPlayer.java
@@ -17,9 +17,8 @@
package android.media;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
-import android.media.PlayerBase;
import android.net.Uri;
import android.os.PowerManager;
import android.os.SystemClock;
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index 8de3e0a63815..ece53353c871 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -20,7 +20,7 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.media.audiopolicy.AudioProductStrategy;
import android.os.Build;
import android.os.Bundle;
diff --git a/media/java/android/media/AudioDevicePort.java b/media/java/android/media/AudioDevicePort.java
index 62b18cbafcb1..51909db11a09 100644
--- a/media/java/android/media/AudioDevicePort.java
+++ b/media/java/android/media/AudioDevicePort.java
@@ -16,8 +16,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
-import android.media.AudioSystem;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* The AudioDevicePort is a specialized type of AudioPort
diff --git a/media/java/android/media/AudioDevicePortConfig.java b/media/java/android/media/AudioDevicePortConfig.java
index 0c647ea85c60..51b8037b82f8 100644
--- a/media/java/android/media/AudioDevicePortConfig.java
+++ b/media/java/android/media/AudioDevicePortConfig.java
@@ -16,7 +16,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* An AudioDevicePortConfig describes a possible configuration of an output or input device
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index f0787e93dc8b..7ff15df2d65e 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -20,7 +20,7 @@ import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
@@ -281,6 +281,8 @@ public final class AudioFormat implements Parcelable {
* metadata (object audio) over HDMI (e.g. Dolby Atmos content).
**/
public static final int ENCODING_DOLBY_MAT = 19;
+ /** Audio data format: OPUS compressed. */
+ public static final int ENCODING_OPUS = 20;
/** @hide */
public static String toLogFriendlyEncoding(int enc) {
@@ -323,6 +325,8 @@ public final class AudioFormat implements Parcelable {
return "ENCODING_E_AC3_JOC";
case ENCODING_DOLBY_MAT:
return "ENCODING_DOLBY_MAT";
+ case ENCODING_OPUS:
+ return "ENCODING_OPUS";
default :
return "invalid encoding " + enc;
}
@@ -548,6 +552,7 @@ public final class AudioFormat implements Parcelable {
case ENCODING_AC4:
case ENCODING_E_AC3_JOC:
case ENCODING_DOLBY_MAT:
+ case ENCODING_OPUS:
return true;
default:
return false;
@@ -576,6 +581,7 @@ public final class AudioFormat implements Parcelable {
case ENCODING_AC4:
case ENCODING_E_AC3_JOC:
case ENCODING_DOLBY_MAT:
+ case ENCODING_OPUS:
return true;
default:
return false;
@@ -607,6 +613,7 @@ public final class AudioFormat implements Parcelable {
case ENCODING_AC4:
case ENCODING_E_AC3_JOC:
case ENCODING_DOLBY_MAT:
+ case ENCODING_OPUS:
return false;
case ENCODING_INVALID:
default:
@@ -638,6 +645,7 @@ public final class AudioFormat implements Parcelable {
case ENCODING_AC4:
case ENCODING_E_AC3_JOC:
case ENCODING_DOLBY_MAT:
+ case ENCODING_OPUS:
return false;
case ENCODING_INVALID:
default:
@@ -917,6 +925,7 @@ public final class AudioFormat implements Parcelable {
case ENCODING_AC4:
case ENCODING_E_AC3_JOC:
case ENCODING_DOLBY_MAT:
+ case ENCODING_OPUS:
mEncoding = encoding;
break;
case ENCODING_INVALID:
@@ -1136,7 +1145,8 @@ public final class AudioFormat implements Parcelable {
ENCODING_AAC_XHE,
ENCODING_AC4,
ENCODING_E_AC3_JOC,
- ENCODING_DOLBY_MAT }
+ ENCODING_DOLBY_MAT,
+ ENCODING_OPUS }
)
@Retention(RetentionPolicy.SOURCE)
public @interface Encoding {}
diff --git a/media/java/android/media/AudioGain.java b/media/java/android/media/AudioGain.java
index dd129a26ee59..cae1b59d46a7 100644
--- a/media/java/android/media/AudioGain.java
+++ b/media/java/android/media/AudioGain.java
@@ -16,7 +16,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* The AudioGain describes a gain controller. Gain controllers are exposed by
diff --git a/media/java/android/media/AudioGainConfig.java b/media/java/android/media/AudioGainConfig.java
index f5ebef85d302..dfefa8621ef8 100644
--- a/media/java/android/media/AudioGainConfig.java
+++ b/media/java/android/media/AudioGainConfig.java
@@ -16,7 +16,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* The AudioGainConfig is used by APIs setting or getting values on a given gain
diff --git a/media/java/android/media/AudioHandle.java b/media/java/android/media/AudioHandle.java
index 24f81f918af2..8fc834f8d0a9 100644
--- a/media/java/android/media/AudioHandle.java
+++ b/media/java/android/media/AudioHandle.java
@@ -16,7 +16,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* The AudioHandle is used by the audio framework implementation to
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index fac276cfb5d1..e410882718d1 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -28,12 +28,12 @@ import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.bluetooth.BluetoothCodecConfig;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -374,6 +374,10 @@ public class AudioManager {
public static final int STREAM_TTS = AudioSystem.STREAM_TTS;
/** Used to identify the volume of audio streams for accessibility prompts */
public static final int STREAM_ACCESSIBILITY = AudioSystem.STREAM_ACCESSIBILITY;
+ /** @hide Used to identify the volume of audio streams for virtual assistant */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
+ public static final int STREAM_ASSISTANT = AudioSystem.STREAM_ASSISTANT;
/** Number of audio streams */
/**
@@ -3641,7 +3645,8 @@ public class AudioManager {
* the callback. If <code>null</code>, the {@link Handler} associated with the main
* {@link Looper} will be used.
*/
- public void registerAudioPlaybackCallback(@NonNull AudioPlaybackCallback cb, Handler handler)
+ public void registerAudioPlaybackCallback(@NonNull AudioPlaybackCallback cb,
+ @Nullable Handler handler)
{
if (cb == null) {
throw new IllegalArgumentException("Illegal null AudioPlaybackCallback argument");
@@ -3830,7 +3835,8 @@ public class AudioManager {
* the callback. If <code>null</code>, the {@link Handler} associated with the main
* {@link Looper} will be used.
*/
- public void registerAudioRecordingCallback(@NonNull AudioRecordingCallback cb, Handler handler)
+ public void registerAudioRecordingCallback(@NonNull AudioRecordingCallback cb,
+ @Nullable Handler handler)
{
if (cb == null) {
throw new IllegalArgumentException("Illegal null AudioRecordingCallback argument");
@@ -5168,7 +5174,7 @@ public class AudioManager {
* {@link Looper} will be used.
*/
public void registerAudioDeviceCallback(AudioDeviceCallback callback,
- android.os.Handler handler) {
+ @Nullable Handler handler) {
synchronized (mDeviceCallbacks) {
if (callback != null && !mDeviceCallbacks.containsKey(callback)) {
if (mDeviceCallbacks.size() == 0) {
diff --git a/media/java/android/media/AudioMixPort.java b/media/java/android/media/AudioMixPort.java
index c4a5c4d86a41..33d603f0b9da 100644
--- a/media/java/android/media/AudioMixPort.java
+++ b/media/java/android/media/AudioMixPort.java
@@ -16,7 +16,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* The AudioMixPort is a specialized type of AudioPort
diff --git a/media/java/android/media/AudioMixPortConfig.java b/media/java/android/media/AudioMixPortConfig.java
index 315e46b725ad..9d8120624a45 100644
--- a/media/java/android/media/AudioMixPortConfig.java
+++ b/media/java/android/media/AudioMixPortConfig.java
@@ -16,7 +16,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* An AudioMixPortConfig describes a possible configuration of an output or input mixer.
diff --git a/media/java/android/media/AudioPatch.java b/media/java/android/media/AudioPatch.java
index d1f800694f50..e5107d4e3309 100644
--- a/media/java/android/media/AudioPatch.java
+++ b/media/java/android/media/AudioPatch.java
@@ -16,7 +16,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
diff --git a/media/java/android/media/AudioPlaybackConfiguration.java b/media/java/android/media/AudioPlaybackConfiguration.java
index ab80b3af9fc8..515e9d0d4c5c 100644
--- a/media/java/android/media/AudioPlaybackConfiguration.java
+++ b/media/java/android/media/AudioPlaybackConfiguration.java
@@ -400,6 +400,7 @@ public final class AudioPlaybackConfiguration implements Parcelable {
* configurations
* @return true if active
*/
+ @SystemApi
public boolean isActive() {
switch (mPlayerState) {
case PLAYER_STATE_STARTED:
@@ -420,18 +421,7 @@ public final class AudioPlaybackConfiguration implements Parcelable {
* @param pw
*/
public void dump(PrintWriter pw) {
- pw.println(" " + toLogFriendlyString(this));
- }
-
- /**
- * @hide
- */
- public static String toLogFriendlyString(AudioPlaybackConfiguration apc) {
- return new String("ID:" + apc.mPlayerIId
- + " -- type:" + toLogFriendlyPlayerType(apc.mPlayerType)
- + " -- u/pid:" + apc.mClientUid +"/" + apc.mClientPid
- + " -- state:" + toLogFriendlyPlayerState(apc.mPlayerState)
- + " -- attr:" + apc.mPlayerAttr);
+ pw.println(" " + this);
}
public static final @android.annotation.NonNull Parcelable.Creator<AudioPlaybackConfiguration> CREATOR
@@ -498,6 +488,15 @@ public final class AudioPlaybackConfiguration implements Parcelable {
&& (mClientPid == that.mClientPid));
}
+ @Override
+ public String toString() {
+ return "AudioPlaybackConfiguration piid:" + mPlayerIId
+ + " type:" + toLogFriendlyPlayerType(mPlayerType)
+ + " u/pid:" + mClientUid + "/" + mClientPid
+ + " state:" + toLogFriendlyPlayerState(mPlayerState)
+ + " attr:" + mPlayerAttr;
+ }
+
//=====================================================================
// Inner class for corresponding IPlayer and its death monitoring
static final class IPlayerShell implements IBinder.DeathRecipient {
diff --git a/media/java/android/media/AudioPort.java b/media/java/android/media/AudioPort.java
index 83eb240be743..7c3ca24e1c9a 100644
--- a/media/java/android/media/AudioPort.java
+++ b/media/java/android/media/AudioPort.java
@@ -16,7 +16,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* An audio port is a node of the audio framework or hardware that can be connected to or
diff --git a/media/java/android/media/AudioPortConfig.java b/media/java/android/media/AudioPortConfig.java
index ac19bb167905..16fb5b80eb3e 100644
--- a/media/java/android/media/AudioPortConfig.java
+++ b/media/java/android/media/AudioPortConfig.java
@@ -16,7 +16,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* An AudioPortConfig contains a possible configuration of an audio port chosen
diff --git a/media/java/android/media/AudioPortEventHandler.java b/media/java/android/media/AudioPortEventHandler.java
index 6d9d6265f5e7..14249cbe8945 100644
--- a/media/java/android/media/AudioPortEventHandler.java
+++ b/media/java/android/media/AudioPortEventHandler.java
@@ -16,7 +16,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index 95afb090fcca..fd3523de4d0f 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -23,8 +23,8 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
+import android.compat.annotation.UnsupportedAppUsage;
import android.media.MediaRecorder.Source;
import android.media.audiopolicy.AudioMix;
import android.media.audiopolicy.AudioPolicy;
diff --git a/media/java/android/media/AudioRecordingConfiguration.java b/media/java/android/media/AudioRecordingConfiguration.java
index a98789bab4f8..f3613d3665ca 100644
--- a/media/java/android/media/AudioRecordingConfiguration.java
+++ b/media/java/android/media/AudioRecordingConfiguration.java
@@ -20,7 +20,7 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.media.audiofx.AudioEffect;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 33ec46abc457..e584addb35fc 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -19,8 +19,8 @@ package android.media;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.bluetooth.BluetoothCodecConfig;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.PackageManager;
import android.media.audiofx.AudioEffect;
@@ -80,6 +80,8 @@ public class AudioSystem
public static final int STREAM_TTS = 9;
/** Used to identify the volume of audio streams for accessibility prompts */
public static final int STREAM_ACCESSIBILITY = 10;
+ /** Used to identify the volume of audio streams for virtual assistant */
+ public static final int STREAM_ASSISTANT = 11;
/**
* @deprecated Use {@link #numStreamTypes() instead}
*/
@@ -92,7 +94,7 @@ public class AudioSystem
private static native int native_get_FCC_8();
// Expose only the getter method publicly so we can change it in the future
- private static final int NUM_STREAM_TYPES = 11;
+ private static final int NUM_STREAM_TYPES = 12;
@UnsupportedAppUsage
public static final int getNumStreamTypes() { return NUM_STREAM_TYPES; }
@@ -107,7 +109,8 @@ public class AudioSystem
"STREAM_SYSTEM_ENFORCED",
"STREAM_DTMF",
"STREAM_TTS",
- "STREAM_ACCESSIBILITY"
+ "STREAM_ACCESSIBILITY",
+ "STREAM_ASSISTANT"
};
/*
@@ -1277,6 +1280,7 @@ public class AudioSystem
5, // STREAM_DTMF
5, // STREAM_TTS
5, // STREAM_ACCESSIBILITY
+ 5, // STREAM_ASSISTANT
};
public static String streamToString(int stream) {
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 7cd09de41346..0ced68ef8695 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -23,7 +23,7 @@ import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Binder;
import android.os.Handler;
import android.os.HandlerThread;
diff --git a/media/java/android/media/CamcorderProfile.java b/media/java/android/media/CamcorderProfile.java
index 963b1d1504e2..e4bab7466a70 100644
--- a/media/java/android/media/CamcorderProfile.java
+++ b/media/java/android/media/CamcorderProfile.java
@@ -16,7 +16,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.os.Build;
diff --git a/media/java/android/media/DecoderCapabilities.java b/media/java/android/media/DecoderCapabilities.java
index df5e918ba8d5..ebfc63bd9bcd 100644
--- a/media/java/android/media/DecoderCapabilities.java
+++ b/media/java/android/media/DecoderCapabilities.java
@@ -16,9 +16,10 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
-import java.util.List;
+import android.compat.annotation.UnsupportedAppUsage;
+
import java.util.ArrayList;
+import java.util.List;
/**
* {@hide}
diff --git a/media/java/android/media/EncoderCapabilities.java b/media/java/android/media/EncoderCapabilities.java
index c09c5fae1213..67ce0f7cc0b9 100644
--- a/media/java/android/media/EncoderCapabilities.java
+++ b/media/java/android/media/EncoderCapabilities.java
@@ -16,9 +16,10 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
-import java.util.List;
+import android.compat.annotation.UnsupportedAppUsage;
+
import java.util.ArrayList;
+import java.util.List;
/**
* The EncoderCapabilities class is used to retrieve the
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index ce4aac9bdb7f..767b67b7e885 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -20,7 +20,7 @@ import android.annotation.CurrentTimeMillisLong;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
diff --git a/media/java/android/media/IMediaRoute2Provider.aidl b/media/java/android/media/IMediaRoute2Provider.aidl
index d8fd1ff22c89..02a381669893 100644
--- a/media/java/android/media/IMediaRoute2Provider.aidl
+++ b/media/java/android/media/IMediaRoute2Provider.aidl
@@ -24,8 +24,14 @@ import android.media.IMediaRoute2ProviderClient;
*/
oneway interface IMediaRoute2Provider {
void setClient(IMediaRoute2ProviderClient client);
- void requestSelectRoute(String packageName, String id, int seq);
- void unselectRoute(String packageName, String id);
+ void requestCreateSession(String packageName, String routeId,
+ String controlCategory, long requestId);
+ void releaseSession(int sessionId);
+
+ void selectRoute(int sessionId, String routeId);
+ void deselectRoute(int sessionId, String routeId);
+ void transferToRoute(int sessionId, String routeId);
+
void notifyControlRequestSent(String id, in Intent request);
void requestSetVolume(String id, int volume);
void requestUpdateVolume(String id, int delta);
diff --git a/media/java/android/media/IMediaRoute2ProviderClient.aidl b/media/java/android/media/IMediaRoute2ProviderClient.aidl
index f4fb7f450fb8..bcb2336dbf78 100644
--- a/media/java/android/media/IMediaRoute2ProviderClient.aidl
+++ b/media/java/android/media/IMediaRoute2ProviderClient.aidl
@@ -18,12 +18,15 @@ package android.media;
import android.media.MediaRoute2ProviderInfo;
import android.media.MediaRoute2Info;
+import android.media.RouteSessionInfo;
import android.os.Bundle;
/**
* @hide
*/
oneway interface IMediaRoute2ProviderClient {
- void updateProviderInfo(in MediaRoute2ProviderInfo info);
- void notifyRouteSelected(String packageName, String routeId, in Bundle controlHints, int seq);
+ void updateState(in MediaRoute2ProviderInfo providerInfo,
+ in List<RouteSessionInfo> sessionInfos);
+ void notifySessionCreated(in @nullable RouteSessionInfo sessionInfo, long requestId);
+ void notifySessionInfoChanged(in RouteSessionInfo sessionInfo);
}
diff --git a/media/java/android/media/IMediaRouter2Client.aidl b/media/java/android/media/IMediaRouter2Client.aidl
index b04af7d1d28d..18a6428f570e 100644
--- a/media/java/android/media/IMediaRouter2Client.aidl
+++ b/media/java/android/media/IMediaRouter2Client.aidl
@@ -17,6 +17,7 @@
package android.media;
import android.media.MediaRoute2Info;
+import android.media.RouteSessionInfo;
import android.os.Bundle;
/**
@@ -27,5 +28,6 @@ oneway interface IMediaRouter2Client {
void notifyRoutesAdded(in List<MediaRoute2Info> routes);
void notifyRoutesRemoved(in List<MediaRoute2Info> routes);
void notifyRoutesChanged(in List<MediaRoute2Info> routes);
- void notifyRouteSelected(in MediaRoute2Info route, int reason, in Bundle controlHints);
+ void notifySessionCreated(in @nullable RouteSessionInfo sessionInfo, int requestId);
+ void notifySessionInfoChanged(in RouteSessionInfo sessionInfo);
}
diff --git a/media/java/android/media/IMediaRouterService.aidl b/media/java/android/media/IMediaRouterService.aidl
index d803f04839b1..4b7d802dbe9e 100644
--- a/media/java/android/media/IMediaRouterService.aidl
+++ b/media/java/android/media/IMediaRouterService.aidl
@@ -22,6 +22,7 @@ import android.media.IMediaRouter2Manager;
import android.media.IMediaRouterClient;
import android.media.MediaRoute2Info;
import android.media.MediaRouterClientState;
+import android.media.RouteSessionInfo;
/**
* {@hide}
@@ -48,29 +49,24 @@ interface IMediaRouterService {
void sendControlRequest(IMediaRouter2Client client, in MediaRoute2Info route, in Intent request);
void requestSetVolume2(IMediaRouter2Client client, in MediaRoute2Info route, int volume);
void requestUpdateVolume2(IMediaRouter2Client client, in MediaRoute2Info route, int direction);
- /**
- * Changes the selected route of the client.
- *
- * @param client the client that changes it's selected route
- * @param route the route to be selected
- */
- void requestSelectRoute2(IMediaRouter2Client client, in @nullable MediaRoute2Info route);
+
+ void requestCreateSession(IMediaRouter2Client client, in MediaRoute2Info route,
+ String controlCategory, int requestId);
void setControlCategories(IMediaRouter2Client client, in List<String> categories);
+ void selectRoute(IMediaRouter2Client client, String sessionId, in MediaRoute2Info route);
+ void deselectRoute(IMediaRouter2Client client, String sessionId, in MediaRoute2Info route);
+ void transferToRoute(IMediaRouter2Client client, String sessionId, in MediaRoute2Info route);
void registerManager(IMediaRouter2Manager manager, String packageName);
void unregisterManager(IMediaRouter2Manager manager);
- /**
- * Changes the selected route of an application.
- *
- * @param manager the manager that calls the method
- * @param packageName the package name of the client that will change the selected route
- * @param route the route to be selected
- */
- void selectClientRoute2(IMediaRouter2Manager manager, String packageName,
- in @nullable MediaRoute2Info route);
+
+ void requestCreateClientSession(IMediaRouter2Manager manager, String packageName,
+ in @nullable MediaRoute2Info route, int requestId);
void requestSetVolume2Manager(IMediaRouter2Manager manager,
in MediaRoute2Info route, int volume);
void requestUpdateVolume2Manager(IMediaRouter2Manager manager,
in MediaRoute2Info route, int direction);
+
+ List<RouteSessionInfo> getActiveSessions(IMediaRouter2Manager manager);
}
diff --git a/media/java/android/media/Image.java b/media/java/android/media/Image.java
index 7ba122baeca1..79b861136b64 100644
--- a/media/java/android/media/Image.java
+++ b/media/java/android/media/Image.java
@@ -16,14 +16,13 @@
package android.media;
-import java.nio.ByteBuffer;
-import java.lang.AutoCloseable;
-
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Rect;
import android.hardware.HardwareBuffer;
+import java.nio.ByteBuffer;
+
/**
* <p>A single complete image buffer to use with a media source such as a
* {@link MediaCodec} or a
diff --git a/media/java/android/media/JetPlayer.java b/media/java/android/media/JetPlayer.java
index e85b3ff99104..84ee09b35b81 100644
--- a/media/java/android/media/JetPlayer.java
+++ b/media/java/android/media/JetPlayer.java
@@ -17,7 +17,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.AssetFileDescriptor;
import android.os.Handler;
import android.os.Looper;
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index d16a216a4cc9..f780d40d349b 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -19,7 +19,7 @@ package android.media;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.ImageFormat;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
@@ -362,7 +362,8 @@ import java.util.concurrent.locks.ReentrantLock;
</tr>
<tr>
<td>FLAC</td>
- <td>mandatory metadata block (called the STREAMINFO block),<br>
+ <td>"fLaC", the FLAC stream marker in ASCII,<br>
+ followed by the STREAMINFO block (the mandatory metadata block),<br>
optionally followed by any number of other metadata blocks</td>
<td class=NA>Not Used</td>
<td class=NA>Not Used</td>
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 91d644b5db74..cbc9683b9cc1 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -23,7 +23,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.SystemProperties;
import android.util.Log;
diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index 6523e30c13cc..13bd85634fda 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -21,17 +21,17 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringDef;
-import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.Looper;
-import android.os.Message;
import android.os.Parcel;
import android.os.PersistableBundle;
import android.util.Log;
+
import dalvik.system.CloseGuard;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
diff --git a/media/java/android/media/MediaFile.java b/media/java/android/media/MediaFile.java
index c4eb0310f292..9908e042c6a4 100644
--- a/media/java/android/media/MediaFile.java
+++ b/media/java/android/media/MediaFile.java
@@ -20,7 +20,7 @@ import static android.content.ContentResolver.MIME_TYPE_DEFAULT;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.mtp.MtpConstants;
import libcore.content.type.MimeMap;
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index dead066dcdd0..79b3886338b1 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -19,7 +19,7 @@ package android.media;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
diff --git a/media/java/android/media/MediaHTTPConnection.java b/media/java/android/media/MediaHTTPConnection.java
index 8ee929e77899..a17ff825e21b 100644
--- a/media/java/android/media/MediaHTTPConnection.java
+++ b/media/java/android/media/MediaHTTPConnection.java
@@ -18,13 +18,14 @@ package android.media;
import static android.media.MediaPlayer.MEDIA_ERROR_UNSUPPORTED;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.NetworkUtils;
import android.os.IBinder;
import android.os.StrictMode;
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
+
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
diff --git a/media/java/android/media/MediaHTTPService.java b/media/java/android/media/MediaHTTPService.java
index 97a0df799101..3008067daefb 100644
--- a/media/java/android/media/MediaHTTPService.java
+++ b/media/java/android/media/MediaHTTPService.java
@@ -17,7 +17,7 @@
package android.media;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.IBinder;
import android.util.Log;
diff --git a/media/java/android/media/MediaInserter.java b/media/java/android/media/MediaInserter.java
index 0749f58e460d..ca7a01cb990d 100644
--- a/media/java/android/media/MediaInserter.java
+++ b/media/java/android/media/MediaInserter.java
@@ -16,7 +16,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentProviderClient;
import android.content.ContentValues;
import android.net.Uri;
diff --git a/media/java/android/media/MediaMetadata.java b/media/java/android/media/MediaMetadata.java
index 8512dbe8d224..a23191f36efc 100644
--- a/media/java/android/media/MediaMetadata.java
+++ b/media/java/android/media/MediaMetadata.java
@@ -17,7 +17,7 @@ package android.media;
import android.annotation.NonNull;
import android.annotation.StringDef;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java
index 5d2bdd756840..7fca03cdfd57 100644
--- a/media/java/android/media/MediaMetadataRetriever.java
+++ b/media/java/android/media/MediaMetadataRetriever.java
@@ -19,7 +19,7 @@ package android.media;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
diff --git a/media/java/android/media/MediaMuxer.java b/media/java/android/media/MediaMuxer.java
index 0fb392bfc0fe..58c73b568553 100644
--- a/media/java/android/media/MediaMuxer.java
+++ b/media/java/android/media/MediaMuxer.java
@@ -18,8 +18,7 @@ package android.media;
import android.annotation.IntDef;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
-import android.media.MediaCodec;
+import android.compat.annotation.UnsupportedAppUsage;
import android.media.MediaCodec.BufferInfo;
import dalvik.system.CloseGuard;
@@ -677,10 +676,9 @@ final public class MediaMuxer {
throw new IllegalArgumentException("bufferInfo must not be null");
}
if (bufferInfo.size < 0 || bufferInfo.offset < 0
- || (bufferInfo.offset + bufferInfo.size) > byteBuf.capacity()
- || bufferInfo.presentationTimeUs < 0) {
+ || (bufferInfo.offset + bufferInfo.size) > byteBuf.capacity()) {
throw new IllegalArgumentException("bufferInfo must specify a" +
- " valid buffer offset, size and presentation time");
+ " valid buffer offset and size");
}
if (mNativeObject == 0) {
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 7d107ddbe978..71c97534c216 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -19,8 +19,8 @@ package android.media;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index abb820645ae7..4198d7917932 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -23,8 +23,8 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
+import android.compat.annotation.UnsupportedAppUsage;
import android.hardware.Camera;
import android.os.Build;
import android.os.Handler;
diff --git a/media/java/android/media/MediaRoute2Info.java b/media/java/android/media/MediaRoute2Info.java
index 445420f130d0..506d6165bbfa 100644
--- a/media/java/android/media/MediaRoute2Info.java
+++ b/media/java/android/media/MediaRoute2Info.java
@@ -16,13 +16,17 @@
package android.media;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.net.Uri;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@@ -46,6 +50,34 @@ public final class MediaRoute2Info implements Parcelable {
}
};
+ /** @hide */
+ @IntDef({CONNECTION_STATE_DISCONNECTED, CONNECTION_STATE_CONNECTING,
+ CONNECTION_STATE_CONNECTED})
+ @Retention(RetentionPolicy.SOURCE)
+ private @interface ConnectionState {}
+
+ /**
+ * The default connection state indicating the route is disconnected.
+ *
+ * @see #getConnectionState
+ */
+ public static final int CONNECTION_STATE_DISCONNECTED = 0;
+
+ /**
+ * A connection state indicating the route is in the process of connecting and is not yet
+ * ready for use.
+ *
+ * @see #getConnectionState
+ */
+ public static final int CONNECTION_STATE_CONNECTING = 1;
+
+ /**
+ * A connection state indicating the route is connected.
+ *
+ * @see #getConnectionState
+ */
+ public static final int CONNECTION_STATE_CONNECTED = 2;
+
/**
* Playback information indicating the playback volume is fixed, i&#46;e&#46; it cannot be
* controlled from this object. An example of fixed playback volume is a remote player,
@@ -61,6 +93,46 @@ public final class MediaRoute2Info implements Parcelable {
*/
public static final int PLAYBACK_VOLUME_VARIABLE = 1;
+ /** @hide */
+ @IntDef({
+ DEVICE_TYPE_UNKNOWN, DEVICE_TYPE_TV,
+ DEVICE_TYPE_SPEAKER, DEVICE_TYPE_BLUETOOTH})
+ @Retention(RetentionPolicy.SOURCE)
+ private @interface DeviceType {}
+
+ /**
+ * The default receiver device type of the route indicating the type is unknown.
+ *
+ * @see #getDeviceType
+ * @hide
+ */
+ public static final int DEVICE_TYPE_UNKNOWN = 0;
+
+ /**
+ * A receiver device type of the route indicating the presentation of the media is happening
+ * on a TV.
+ *
+ * @see #getDeviceType
+ */
+ public static final int DEVICE_TYPE_TV = 1;
+
+ /**
+ * A receiver device type of the route indicating the presentation of the media is happening
+ * on a speaker.
+ *
+ * @see #getDeviceType
+ */
+ public static final int DEVICE_TYPE_SPEAKER = 2;
+
+ /**
+ * A receiver device type of the route indicating the presentation of the media is happening
+ * on a bluetooth device such as a bluetooth speaker.
+ *
+ * @see #getDeviceType
+ * @hide
+ */
+ public static final int DEVICE_TYPE_BLUETOOTH = 3;
+
@NonNull
final String mId;
@Nullable
@@ -70,12 +142,17 @@ public final class MediaRoute2Info implements Parcelable {
@Nullable
final CharSequence mDescription;
@Nullable
+ final @ConnectionState int mConnectionState;
+ @Nullable
+ final Uri mIconUri;
+ @Nullable
final String mClientPackageName;
@NonNull
final List<String> mSupportedCategories;
final int mVolume;
final int mVolumeMax;
final int mVolumeHandling;
+ final @DeviceType int mDeviceType;
@Nullable
final Bundle mExtras;
@@ -86,11 +163,14 @@ public final class MediaRoute2Info implements Parcelable {
mProviderId = builder.mProviderId;
mName = builder.mName;
mDescription = builder.mDescription;
+ mConnectionState = builder.mConnectionState;
+ mIconUri = builder.mIconUri;
mClientPackageName = builder.mClientPackageName;
mSupportedCategories = builder.mSupportedCategories;
mVolume = builder.mVolume;
mVolumeMax = builder.mVolumeMax;
mVolumeHandling = builder.mVolumeHandling;
+ mDeviceType = builder.mDeviceType;
mExtras = builder.mExtras;
mUniqueId = createUniqueId();
}
@@ -100,11 +180,14 @@ public final class MediaRoute2Info implements Parcelable {
mProviderId = in.readString();
mName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
mDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+ mConnectionState = in.readInt();
+ mIconUri = in.readParcelable(null);
mClientPackageName = in.readString();
mSupportedCategories = in.createStringArrayList();
mVolume = in.readInt();
mVolumeMax = in.readInt();
mVolumeHandling = in.readInt();
+ mDeviceType = in.readInt();
mExtras = in.readBundle();
mUniqueId = createUniqueId();
}
@@ -112,11 +195,15 @@ public final class MediaRoute2Info implements Parcelable {
private String createUniqueId() {
String uniqueId = null;
if (mProviderId != null) {
- uniqueId = mProviderId + ":" + mId;
+ uniqueId = toUniqueId(mProviderId, mId);
}
return uniqueId;
}
+ static String toUniqueId(String providerId, String routeId) {
+ return providerId + ":" + routeId;
+ }
+
/**
* Returns true if the route info has all of the required field.
* A route info only obtained from {@link com.android.server.media.MediaRouterService}
@@ -145,18 +232,22 @@ public final class MediaRoute2Info implements Parcelable {
&& Objects.equals(mProviderId, other.mProviderId)
&& Objects.equals(mName, other.mName)
&& Objects.equals(mDescription, other.mDescription)
+ && (mConnectionState == other.mConnectionState)
+ && Objects.equals(mIconUri, other.mIconUri)
&& Objects.equals(mClientPackageName, other.mClientPackageName)
&& Objects.equals(mSupportedCategories, other.mSupportedCategories)
&& (mVolume == other.mVolume)
&& (mVolumeMax == other.mVolumeMax)
&& (mVolumeHandling == other.mVolumeHandling)
+ && (mDeviceType == other.mDeviceType)
//TODO: This will be evaluated as false in most cases. Try not to.
&& Objects.equals(mExtras, other.mExtras);
}
@Override
public int hashCode() {
- return Objects.hash(mId, mName, mDescription, mSupportedCategories);
+ return Objects.hash(mId, mName, mDescription, mConnectionState, mIconUri,
+ mSupportedCategories, mVolume, mVolumeMax, mVolumeHandling, mDeviceType);
}
/**
@@ -204,6 +295,29 @@ public final class MediaRoute2Info implements Parcelable {
}
/**
+ * Gets the connection state of the route.
+ *
+ * @return The connection state of this route: {@link #CONNECTION_STATE_DISCONNECTED},
+ * {@link #CONNECTION_STATE_CONNECTING}, or {@link #CONNECTION_STATE_CONNECTED}.
+ */
+ @ConnectionState
+ public int getConnectionState() {
+ return mConnectionState;
+ }
+
+ /**
+ * Gets the URI of the icon representing this route.
+ * <p>
+ * This icon will be used in picker UIs if available.
+ *
+ * @return The URI of the icon representing this route, or null if none.
+ */
+ @Nullable
+ public Uri getIconUri() {
+ return mIconUri;
+ }
+
+ /**
* Gets the package name of the client that uses the route.
* Returns null if no clients use this.
* @hide
@@ -221,6 +335,18 @@ public final class MediaRoute2Info implements Parcelable {
return mSupportedCategories;
}
+ //TODO: once device types are confirmed, reflect those into the comment.
+ /**
+ * Gets the type of the receiver device associated with this route.
+ *
+ * @return The type of the receiver device associated with this route:
+ * {@link #DEVICE_TYPE_TV} or {@link #DEVICE_TYPE_SPEAKER}.
+ */
+ @DeviceType
+ public int getDeviceType() {
+ return mDeviceType;
+ }
+
/**
* Gets the current volume of the route. This may be invalid if the route is not selected.
*/
@@ -249,20 +375,34 @@ public final class MediaRoute2Info implements Parcelable {
return mExtras;
}
+ /**
+ * Returns if the route supports the specified control category
+ *
+ * @param controlCategory control category to consider
+ * @return true if the route supports at the category
+ */
+ public boolean supportsControlCategory(@NonNull String controlCategory) {
+ Objects.requireNonNull(controlCategory, "control category must not be null");
+ for (String supportedCategory : getSupportedCategories()) {
+ if (TextUtils.equals(controlCategory, supportedCategory)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
//TODO: Move this if we re-define control category / selector things.
/**
- * Returns true if the route supports at least one of the specified control categories
+ * Returns if the route supports at least one of the specified control categories
*
* @param controlCategories the list of control categories to consider
* @return true if the route supports at least one category
*/
- public boolean supportsControlCategory(@NonNull Collection<String> controlCategories) {
+ public boolean supportsControlCategories(@NonNull Collection<String> controlCategories) {
Objects.requireNonNull(controlCategories, "control categories must not be null");
for (String controlCategory : controlCategories) {
- for (String supportedCategory : getSupportedCategories()) {
- if (TextUtils.equals(controlCategory, supportedCategory)) {
- return true;
- }
+ if (supportsControlCategory(controlCategory)) {
+ return true;
}
}
return false;
@@ -279,11 +419,14 @@ public final class MediaRoute2Info implements Parcelable {
dest.writeString(mProviderId);
TextUtils.writeToParcel(mName, dest, flags);
TextUtils.writeToParcel(mDescription, dest, flags);
+ dest.writeInt(mConnectionState);
+ dest.writeParcelable(mIconUri, flags);
dest.writeString(mClientPackageName);
dest.writeStringList(mSupportedCategories);
dest.writeInt(mVolume);
dest.writeInt(mVolumeMax);
dest.writeInt(mVolumeHandling);
+ dest.writeInt(mDeviceType);
dest.writeBundle(mExtras);
}
@@ -294,9 +437,12 @@ public final class MediaRoute2Info implements Parcelable {
.append("id=").append(getId())
.append(", name=").append(getName())
.append(", description=").append(getDescription())
+ .append(", connectionState=").append(getConnectionState())
+ .append(", iconUri=").append(getIconUri())
.append(", volume=").append(getVolume())
.append(", volumeMax=").append(getVolumeMax())
.append(", volumeHandling=").append(getVolumeHandling())
+ .append(", deviceType=").append(getDeviceType())
.append(", providerId=").append(getProviderId())
.append(" }");
return result.toString();
@@ -310,11 +456,16 @@ public final class MediaRoute2Info implements Parcelable {
String mProviderId;
CharSequence mName;
CharSequence mDescription;
+ @ConnectionState
+ int mConnectionState;
+ Uri mIconUri;
String mClientPackageName;
List<String> mSupportedCategories;
int mVolume;
int mVolumeMax;
int mVolumeHandling = PLAYBACK_VOLUME_FIXED;
+ @DeviceType
+ int mDeviceType = DEVICE_TYPE_UNKNOWN;
Bundle mExtras;
public Builder(@NonNull String id, @NonNull CharSequence name) {
@@ -334,11 +485,14 @@ public final class MediaRoute2Info implements Parcelable {
}
setName(routeInfo.mName);
mDescription = routeInfo.mDescription;
+ mConnectionState = routeInfo.mConnectionState;
+ mIconUri = routeInfo.mIconUri;
setClientPackageName(routeInfo.mClientPackageName);
setSupportedCategories(routeInfo.mSupportedCategories);
setVolume(routeInfo.mVolume);
setVolumeMax(routeInfo.mVolumeMax);
setVolumeHandling(routeInfo.mVolumeHandling);
+ setDeviceType(routeInfo.mDeviceType);
if (routeInfo.mExtras != null) {
mExtras = new Bundle(routeInfo.mExtras);
}
@@ -389,6 +543,39 @@ public final class MediaRoute2Info implements Parcelable {
}
/**
+ * Sets the route's connection state.
+ *
+ * {@link #CONNECTION_STATE_DISCONNECTED},
+ * {@link #CONNECTION_STATE_CONNECTING}, or
+ * {@link #CONNECTION_STATE_CONNECTED}.
+ */
+ @NonNull
+ public Builder setConnectionState(@ConnectionState int connectionState) {
+ mConnectionState = connectionState;
+ return this;
+ }
+
+ /**
+ * Sets the URI of the icon representing this route.
+ * <p>
+ * This icon will be used in picker UIs if available.
+ * </p><p>
+ * The URI must be one of the following formats:
+ * <ul>
+ * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li>
+ * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE})
+ * </li>
+ * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li>
+ * </ul>
+ * </p>
+ */
+ @NonNull
+ public Builder setIconUri(@Nullable Uri iconUri) {
+ mIconUri = iconUri;
+ return this;
+ }
+
+ /**
* Sets the package name of the app using the route.
*/
@NonNull
@@ -456,6 +643,16 @@ public final class MediaRoute2Info implements Parcelable {
mVolumeHandling = volumeHandling;
return this;
}
+
+ /**
+ * Sets the route's device type.
+ */
+ @NonNull
+ public Builder setDeviceType(@DeviceType int deviceType) {
+ mDeviceType = deviceType;
+ return this;
+ }
+
/**
* Sets a bundle of extras for the route.
*/
diff --git a/media/java/android/media/MediaRoute2ProviderInfo.java b/media/java/android/media/MediaRoute2ProviderInfo.java
index 4f203dea49f5..7078d4a0b568 100644
--- a/media/java/android/media/MediaRoute2ProviderInfo.java
+++ b/media/java/android/media/MediaRoute2ProviderInfo.java
@@ -46,14 +46,13 @@ public final class MediaRoute2ProviderInfo implements Parcelable {
};
@Nullable
- private final String mUniqueId;
+ final String mUniqueId;
@NonNull
- private final ArrayMap<String, MediaRoute2Info> mRoutes;
+ final ArrayMap<String, MediaRoute2Info> mRoutes;
MediaRoute2ProviderInfo(@NonNull Builder builder) {
- if (builder == null) {
- throw new NullPointerException("Builder must not be null.");
- }
+ Objects.requireNonNull(builder, "builder must not be null.");
+
mUniqueId = builder.mUniqueId;
mRoutes = builder.mRoutes;
}
@@ -143,6 +142,7 @@ public final class MediaRoute2ProviderInfo implements Parcelable {
public Builder(@NonNull MediaRoute2ProviderInfo descriptor) {
Objects.requireNonNull(descriptor, "descriptor must not be null");
+ mUniqueId = descriptor.mUniqueId;
mRoutes = new ArrayMap<>(descriptor.mRoutes);
}
diff --git a/media/java/android/media/MediaRoute2ProviderService.java b/media/java/android/media/MediaRoute2ProviderService.java
index 1b6183e361c8..99bd1dcde3bb 100644
--- a/media/java/android/media/MediaRoute2ProviderService.java
+++ b/media/java/android/media/MediaRoute2ProviderService.java
@@ -22,14 +22,22 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Service;
import android.content.Intent;
+import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
+import android.os.Process;
import android.os.RemoteException;
+import android.util.ArrayMap;
import android.util.Log;
+import com.android.internal.annotations.GuardedBy;
+
+import java.util.ArrayList;
+import java.util.List;
import java.util.Objects;
+import java.util.concurrent.atomic.AtomicBoolean;
/**
* @hide
@@ -40,10 +48,15 @@ public abstract class MediaRoute2ProviderService extends Service {
public static final String SERVICE_INTERFACE = "android.media.MediaRoute2ProviderService";
private final Handler mHandler;
+ private final Object mSessionLock = new Object();
+ private final AtomicBoolean mStatePublishScheduled = new AtomicBoolean(false);
private ProviderStub mStub;
private IMediaRoute2ProviderClient mClient;
private MediaRoute2ProviderInfo mProviderInfo;
+ @GuardedBy("mSessionLock")
+ private ArrayMap<Integer, RouteSessionInfo> mSessionInfo = new ArrayMap<>();
+
public MediaRoute2ProviderService() {
mHandler = new Handler(Looper.getMainLooper());
}
@@ -61,28 +74,6 @@ public abstract class MediaRoute2ProviderService extends Service {
}
/**
- * Called when selectRoute is called on a route of the provider.
- * Once the route is ready to be used , call {@link #notifyRouteSelected(SelectToken, Bundle)}
- * to notify that.
- *
- * @param packageName the package name of the application that selected the route
- * @param routeId the id of the route being selected
- * @param token token that contains select info
- *
- * @see #notifyRouteSelected
- */
- public abstract void onSelectRoute(@NonNull String packageName, @NonNull String routeId,
- @NonNull SelectToken token);
-
- /**
- * Called when unselectRoute is called on a route of the provider.
- *
- * @param packageName the package name of the application that has selected the route.
- * @param routeId the id of the route being unselected
- */
- public abstract void onUnselectRoute(@NonNull String packageName, @NonNull String routeId);
-
- /**
* Called when sendControlRequest is called on a route of the provider
*
* @param routeId the id of the target route
@@ -93,6 +84,7 @@ public abstract class MediaRoute2ProviderService extends Service {
/**
* Called when requestSetVolume is called on a route of the provider
+ *
* @param routeId the id of the route
* @param volume the target volume
*/
@@ -100,114 +92,340 @@ public abstract class MediaRoute2ProviderService extends Service {
/**
* Called when requestUpdateVolume is called on a route of the provider
+ *
* @param routeId id of the route
* @param delta the delta to add to the current volume
*/
public abstract void onUpdateVolume(@NonNull String routeId, int delta);
/**
- * Updates provider info and publishes routes
+ * Gets information of the session with the given id.
+ *
+ * @param sessionId id of the session
+ * @return information of the session with the given id.
+ * null if the session is destroyed or id is not valid.
*/
- public final void setProviderInfo(MediaRoute2ProviderInfo info) {
- mProviderInfo = info;
- publishState();
+ @Nullable
+ public final RouteSessionInfo getSessionInfo(int sessionId) {
+ synchronized (mSessionLock) {
+ return mSessionInfo.get(sessionId);
+ }
}
/**
- * Notifies the client of that the selected route is ready for use. If the selected route can be
- * controlled, pass a {@link Bundle} that contains how to control it.
+ * Gets the list of {@link RouteSessionInfo session info} that the provider service maintains.
+ */
+ @NonNull
+ public final List<RouteSessionInfo> getAllSessionInfo() {
+ synchronized (mSessionLock) {
+ return new ArrayList<>(mSessionInfo.values());
+ }
+ }
+
+ /**
+ * Updates the information of a session.
+ * If the session is destroyed or not created before, it will be ignored.
+ * A session will be destroyed if it has no selected route.
+ * Call {@link #updateProviderInfo(MediaRoute2ProviderInfo)} to notify clients of
+ * session info changes.
+ *
+ * @param sessionInfo new session information
+ * @see #notifySessionCreated(RouteSessionInfo, long)
+ */
+ public final void updateSessionInfo(@NonNull RouteSessionInfo sessionInfo) {
+ Objects.requireNonNull(sessionInfo, "sessionInfo must not be null");
+ int sessionId = sessionInfo.getSessionId();
+ if (sessionInfo.getSelectedRoutes().isEmpty()) {
+ releaseSession(sessionId);
+ return;
+ }
+
+ synchronized (mSessionLock) {
+ if (mSessionInfo.containsKey(sessionId)) {
+ mSessionInfo.put(sessionId, sessionInfo);
+ schedulePublishState();
+ } else {
+ Log.w(TAG, "Ignoring unknown session info.");
+ return;
+ }
+ }
+ }
+
+ /**
+ * Notifies the session is changed.
*
- * @param token token passed in {@link #onSelectRoute}
- * @param controlHints a {@link Bundle} that contains how to control the given route.
- * Pass {@code null} if the route is not available.
+ * TODO: This method is temporary, only created for tests. Remove when the alternative is ready.
+ * @hide
*/
- public final void notifyRouteSelected(@NonNull SelectToken token,
- @Nullable Bundle controlHints) {
- Objects.requireNonNull(token, "token must not be null");
+ public final void notifySessionInfoChanged(@NonNull RouteSessionInfo sessionInfo) {
+ Objects.requireNonNull(sessionInfo, "sessionInfo must not be null");
+
+ int sessionId = sessionInfo.getSessionId();
+ synchronized (mSessionLock) {
+ if (mSessionInfo.containsKey(sessionId)) {
+ mSessionInfo.put(sessionId, sessionInfo);
+ } else {
+ Log.w(TAG, "Ignoring unknown session info.");
+ return;
+ }
+ }
if (mClient == null) {
return;
}
try {
- mClient.notifyRouteSelected(token.mPackageName, token.mRouteId,
- controlHints, token.mSeq);
+ mClient.notifySessionInfoChanged(sessionInfo);
} catch (RemoteException ex) {
- Log.w(TAG, "Failed to notify route selected");
+ Log.w(TAG, "Failed to notify session info changed.");
}
}
- void setClient(IMediaRoute2ProviderClient client) {
- mClient = client;
- publishState();
- }
+ /**
+ * Notifies clients of that the session is created and ready for use. If the session can be
+ * controlled, pass a {@link Bundle} that contains how to control it.
+ *
+ * @param sessionInfo information of the new session.
+ * The {@link RouteSessionInfo#getSessionId() id} of the session must be
+ * unique. Pass {@code null} to reject the request or inform clients that
+ * session creation is failed.
+ * @param requestId id of the previous request to create this session
+ */
+ // TODO: fail reason?
+ // TODO: Maybe better to create notifySessionCreationFailed?
+ public final void notifySessionCreated(@Nullable RouteSessionInfo sessionInfo, long requestId) {
+ if (sessionInfo != null) {
+ int sessionId = sessionInfo.getSessionId();
+ synchronized (mSessionLock) {
+ if (mSessionInfo.containsKey(sessionId)) {
+ Log.w(TAG, "Ignoring duplicate session id.");
+ return;
+ }
+ mSessionInfo.put(sessionInfo.getSessionId(), sessionInfo);
+ }
+ schedulePublishState();
+ }
- void publishState() {
if (mClient == null) {
return;
}
try {
- mClient.updateProviderInfo(mProviderInfo);
+ mClient.notifySessionCreated(sessionInfo, requestId);
} catch (RemoteException ex) {
- Log.w(TAG, "Failed to send onProviderInfoUpdated");
+ Log.w(TAG, "Failed to notify session created.");
+ }
+ }
+
+ /**
+ * Releases a session with the given id.
+ * {@link #onDestroySession} is called if the session is released.
+ *
+ * @param sessionId id of the session to be released
+ * @see #onDestroySession(int, RouteSessionInfo)
+ */
+ public final void releaseSession(int sessionId) {
+ //TODO: notify media router service of release.
+ RouteSessionInfo sessionInfo;
+ synchronized (mSessionLock) {
+ sessionInfo = mSessionInfo.remove(sessionId);
+ }
+ if (sessionInfo != null) {
+ mHandler.sendMessage(obtainMessage(
+ MediaRoute2ProviderService::onDestroySession, this, sessionId, sessionInfo));
+ schedulePublishState();
}
}
/**
- * Route selection information.
+ * Called when a session should be created.
+ * You should create and maintain your own session and notifies the client of
+ * session info. Call {@link #notifySessionCreated(RouteSessionInfo, long)}
+ * with the given {@code requestId} to notify the information of a new session.
+ * If you can't create the session or want to reject the request, pass {@code null}
+ * as session info in {@link #notifySessionCreated(RouteSessionInfo, long)}
+ * with the given {@code requestId}.
+ *
+ * @param packageName the package name of the application that selected the route
+ * @param routeId the id of the route initially being connected
+ * @param controlCategory the control category of the new session
+ * @param requestId the id of this session creation request
+ */
+ public abstract void onCreateSession(@NonNull String packageName, @NonNull String routeId,
+ @NonNull String controlCategory, long requestId);
+
+ /**
+ * Called when a session is about to be destroyed.
+ * You can clean up your session here. This can happen by the
+ * client or provider itself.
+ *
+ * @param sessionId id of the session being destroyed.
+ * @param lastSessionInfo information of the session being destroyed.
+ * @see #releaseSession(int)
+ */
+ public abstract void onDestroySession(int sessionId, @NonNull RouteSessionInfo lastSessionInfo);
+
+ //TODO: make a way to reject the request
+ /**
+ * Called when a client requests selecting a route for the session.
+ * After the route is selected, call {@link #updateSessionInfo(RouteSessionInfo)} to update
+ * session info and call {@link #updateProviderInfo(MediaRoute2ProviderInfo)} to notify
+ * clients of updated session info.
+ *
+ * @param sessionId id of the session
+ * @param routeId id of the route
+ * @see #updateSessionInfo(RouteSessionInfo)
+ */
+ public abstract void onSelectRoute(int sessionId, @NonNull String routeId);
+
+ //TODO: make a way to reject the request
+ /**
+ * Called when a client requests deselecting a route from the session.
+ * After the route is deselected, call {@link #updateSessionInfo(RouteSessionInfo)} to update
+ * session info and call {@link #updateProviderInfo(MediaRoute2ProviderInfo)} to notify
+ * clients of updated session info.
+ *
+ * @param sessionId id of the session
+ * @param routeId id of the route
+ */
+ public abstract void onDeselectRoute(int sessionId, @NonNull String routeId);
+
+ //TODO: make a way to reject the request
+ /**
+ * Called when a client requests transferring a session to a route.
+ * After the transfer is finished, call {@link #updateSessionInfo(RouteSessionInfo)} to update
+ * session info and call {@link #updateProviderInfo(MediaRoute2ProviderInfo)} to notify
+ * clients of updated session info.
*
- * @see #notifyRouteSelected
+ * @param sessionId id of the session
+ * @param routeId id of the route
*/
- public final class SelectToken {
- final String mPackageName;
- final String mRouteId;
- final int mSeq;
+ public abstract void onTransferToRoute(int sessionId, @NonNull String routeId);
+
+ /**
+ * Updates provider info and publishes routes and session info.
+ */
+ public final void updateProviderInfo(@NonNull MediaRoute2ProviderInfo providerInfo) {
+ mProviderInfo = Objects.requireNonNull(providerInfo, "providerInfo must not be null");
+ schedulePublishState();
+ }
+
+ void setClient(IMediaRoute2ProviderClient client) {
+ mClient = client;
+ schedulePublishState();
+ }
+
+ void schedulePublishState() {
+ if (mStatePublishScheduled.compareAndSet(false, true)) {
+ mHandler.post(this::publishState);
+ }
+ }
+
+ private void publishState() {
+ if (!mStatePublishScheduled.compareAndSet(true, false)) {
+ return;
+ }
- SelectToken(String packageName, String routeId, int seq) {
- mPackageName = packageName;
- mRouteId = routeId;
- mSeq = seq;
+ if (mClient == null) {
+ return;
+ }
+
+ List<RouteSessionInfo> sessionInfos;
+ synchronized (mSessionLock) {
+ sessionInfos = new ArrayList<>(mSessionInfo.values());
+ }
+ try {
+ mClient.updateState(mProviderInfo, sessionInfos);
+ } catch (RemoteException ex) {
+ Log.w(TAG, "Failed to send onProviderInfoUpdated");
}
}
final class ProviderStub extends IMediaRoute2Provider.Stub {
ProviderStub() { }
+ boolean checkCallerisSystem() {
+ return Binder.getCallingUid() == Process.SYSTEM_UID;
+ }
+
@Override
public void setClient(IMediaRoute2ProviderClient client) {
+ if (!checkCallerisSystem()) {
+ return;
+ }
mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::setClient,
MediaRoute2ProviderService.this, client));
}
@Override
- public void requestSelectRoute(String packageName, String id, int seq) {
+ public void requestCreateSession(String packageName, String routeId,
+ String controlCategory, long requestId) {
+ if (!checkCallerisSystem()) {
+ return;
+ }
+ mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onCreateSession,
+ MediaRoute2ProviderService.this, packageName, routeId, controlCategory,
+ requestId));
+ }
+ @Override
+ public void releaseSession(int sessionId) {
+ if (!checkCallerisSystem()) {
+ return;
+ }
+ mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::releaseSession,
+ MediaRoute2ProviderService.this, sessionId));
+ }
+
+ @Override
+ public void selectRoute(int sessionId, String routeId) {
+ if (!checkCallerisSystem()) {
+ return;
+ }
mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onSelectRoute,
- MediaRoute2ProviderService.this, packageName, id,
- new SelectToken(packageName, id, seq)));
+ MediaRoute2ProviderService.this, sessionId, routeId));
+ }
+ @Override
+ public void deselectRoute(int sessionId, String routeId) {
+ if (!checkCallerisSystem()) {
+ return;
+ }
+ mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onDeselectRoute,
+ MediaRoute2ProviderService.this, sessionId, routeId));
}
@Override
- public void unselectRoute(String packageName, String id) {
- mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onUnselectRoute,
- MediaRoute2ProviderService.this, packageName, id));
+ public void transferToRoute(int sessionId, String routeId) {
+ if (!checkCallerisSystem()) {
+ return;
+ }
+ mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onTransferToRoute,
+ MediaRoute2ProviderService.this, sessionId, routeId));
}
@Override
- public void notifyControlRequestSent(String id, Intent request) {
+ public void notifyControlRequestSent(String routeId, Intent request) {
+ if (!checkCallerisSystem()) {
+ return;
+ }
mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onControlRequest,
- MediaRoute2ProviderService.this, id, request));
+ MediaRoute2ProviderService.this, routeId, request));
}
@Override
- public void requestSetVolume(String id, int volume) {
+ public void requestSetVolume(String routeId, int volume) {
+ if (!checkCallerisSystem()) {
+ return;
+ }
mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onSetVolume,
- MediaRoute2ProviderService.this, id, volume));
+ MediaRoute2ProviderService.this, routeId, volume));
}
@Override
- public void requestUpdateVolume(String id, int delta) {
+ public void requestUpdateVolume(String routeId, int delta) {
+ if (!checkCallerisSystem()) {
+ return;
+ }
mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onUpdateVolume,
- MediaRoute2ProviderService.this, id, delta));
+ MediaRoute2ProviderService.this, routeId, delta));
}
}
}
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index d72231f40dcf..9837e1cc62b3 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -22,8 +22,8 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java
index 3e6f4c01873c..910003270845 100644
--- a/media/java/android/media/MediaRouter2.java
+++ b/media/java/android/media/MediaRouter2.java
@@ -23,6 +23,7 @@ import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
@@ -31,6 +32,7 @@ import android.os.Looper;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.text.TextUtils;
+import android.util.ArrayMap;
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
@@ -45,10 +47,14 @@ import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicInteger;
/**
* A new Media Router
* @hide
+ *
+ * TODO: Add method names at the beginning of log messages. (e.g. changeSessionInfoOnHandler)
+ * Not only MediaRouter2, but also to service / manager / provider.
*/
public class MediaRouter2 {
@@ -98,26 +104,34 @@ public class MediaRouter2 {
private final Context mContext;
private final IMediaRouterService mMediaRouterService;
- private final CopyOnWriteArrayList<CallbackRecord> mCallbackRecords =
+ private final CopyOnWriteArrayList<RouteCallbackRecord> mRouteCallbackRecords =
new CopyOnWriteArrayList<>();
- private final String mPackageName;
- private final Map<String, MediaRoute2Info> mRoutes = new HashMap<>();
+ private final CopyOnWriteArrayList<SessionCallbackRecord> mSessionCallbackRecords =
+ new CopyOnWriteArrayList<>();
+
+ private final CopyOnWriteArrayList<SessionCreationRequest> mSessionCreationRequests =
+ new CopyOnWriteArrayList<>();
- //TODO: Use a lock for this to cover the below use case
- // mRouter.setControlCategories(...);
- // routes = mRouter.getRoutes();
- // The current implementation returns empty list
- private volatile List<String> mControlCategories = Collections.emptyList();
+ private final String mPackageName;
+ @GuardedBy("sLock")
+ final Map<String, MediaRoute2Info> mRoutes = new HashMap<>();
- private MediaRoute2Info mSelectedRoute;
@GuardedBy("sLock")
- private MediaRoute2Info mSelectingRoute;
+ private List<String> mControlCategories = Collections.emptyList();
+
+ // TODO: Make MediaRouter2 is always connected to the MediaRouterService.
@GuardedBy("sLock")
private Client2 mClient;
+ private Map<String, RouteSessionController> mSessionControllers = new ArrayMap<>();
+
+ private AtomicInteger mSessionCreationRequestCnt = new AtomicInteger(1);
+
final Handler mHandler;
- volatile List<MediaRoute2Info> mFilteredRoutes = Collections.emptyList();
+ @GuardedBy("sLock")
+ private boolean mShouldUpdateRoutes;
+ private volatile List<MediaRoute2Info> mFilteredRoutes = Collections.emptyList();
/**
* Gets an instance of the media router associated with the context.
@@ -154,44 +168,46 @@ public class MediaRouter2 {
for (MediaRoute2Info route : currentSystemRoutes) {
mRoutes.put(route.getId(), route);
}
- // The first route is the currently selected system route.
- // For example, if there are two system routes (BT and device speaker),
- // BT will be the first route in the list.
- mSelectedRoute = currentSystemRoutes.get(0);
+ }
+
+ /**
+ * Returns whether any route in {@code routeList} has a same unique ID with given route.
+ *
+ * @hide
+ */
+ public static boolean checkRouteListContainsRouteId(@NonNull List<MediaRoute2Info> routeList,
+ @NonNull String uniqueRouteId) {
+ for (MediaRoute2Info info : routeList) {
+ if (TextUtils.equals(uniqueRouteId, info.getUniqueId())) {
+ return true;
+ }
+ }
+ return false;
}
/**
* Registers a callback to discover routes and to receive events when they change.
*/
- public void registerCallback(@NonNull @CallbackExecutor Executor executor,
- @NonNull Callback callback) {
- registerCallback(executor, callback, 0);
+ public void registerRouteCallback(@NonNull @CallbackExecutor Executor executor,
+ @NonNull RouteCallback routeCallback) {
+ registerRouteCallback(executor, routeCallback, 0);
}
/**
* Registers a callback to discover routes and to receive events when they change.
* <p>
- * If you register the same callback twice or more, the previous arguments will be overwritten
- * with the new arguments.
+ * If you register the same callback twice or more, it will be ignored.
* </p>
*/
- public void registerCallback(@NonNull @CallbackExecutor Executor executor,
- @NonNull Callback callback, int flags) {
+ public void registerRouteCallback(@NonNull @CallbackExecutor Executor executor,
+ @NonNull RouteCallback routeCallback, int flags) {
Objects.requireNonNull(executor, "executor must not be null");
- Objects.requireNonNull(callback, "callback must not be null");
+ Objects.requireNonNull(routeCallback, "callback must not be null");
- CallbackRecord record;
- // This is required to prevent adding the same callback twice.
- synchronized (mCallbackRecords) {
- final int index = findCallbackRecordIndexLocked(callback);
- if (index < 0) {
- record = new CallbackRecord(callback);
- mCallbackRecords.add(record);
- } else {
- record = mCallbackRecords.get(index);
- }
- record.mExecutor = executor;
- record.mFlags = flags;
+ RouteCallbackRecord record = new RouteCallbackRecord(executor, routeCallback, flags);
+ if (!mRouteCallbackRecords.addIfAbsent(record)) {
+ Log.w(TAG, "Ignoring the same callback");
+ return;
}
synchronized (sLock) {
@@ -206,8 +222,6 @@ public class MediaRouter2 {
}
}
}
- //TODO: Is it thread-safe?
- record.notifyRoutes();
//TODO: Update discovery request here.
}
@@ -216,29 +230,27 @@ public class MediaRouter2 {
* Unregisters the given callback. The callback will no longer receive events.
* If the callback has not been added or been removed already, it is ignored.
*
- * @param callback the callback to unregister
- * @see #registerCallback
+ * @param routeCallback the callback to unregister
+ * @see #registerRouteCallback
*/
- public void unregisterCallback(@NonNull Callback callback) {
- Objects.requireNonNull(callback, "callback must not be null");
+ public void unregisterRouteCallback(@NonNull RouteCallback routeCallback) {
+ Objects.requireNonNull(routeCallback, "callback must not be null");
- synchronized (mCallbackRecords) {
- final int index = findCallbackRecordIndexLocked(callback);
- if (index < 0) {
- Log.w(TAG, "Ignoring to remove unknown callback. " + callback);
- return;
- }
- mCallbackRecords.remove(index);
- synchronized (sLock) {
- if (mCallbackRecords.size() == 0 && mClient != null) {
- try {
- mMediaRouterService.unregisterClient2(mClient);
- } catch (RemoteException ex) {
- Log.e(TAG, "Unable to unregister media router.", ex);
- }
- //TODO: Clean up mRoutes. (onHandler?)
- mClient = null;
+ if (!mRouteCallbackRecords.remove(
+ new RouteCallbackRecord(null, routeCallback, 0))) {
+ Log.w(TAG, "Ignoring unknown callback");
+ return;
+ }
+
+ synchronized (sLock) {
+ if (mRouteCallbackRecords.size() == 0 && mClient != null) {
+ try {
+ mMediaRouterService.unregisterClient2(mClient);
+ } catch (RemoteException ex) {
+ Log.e(TAG, "Unable to unregister media router.", ex);
}
+ //TODO: Clean up mRoutes. (onHandler?)
+ mClient = null;
}
}
}
@@ -246,62 +258,131 @@ public class MediaRouter2 {
//TODO(b/139033746): Rename "Control Category" when it's finalized.
/**
* Sets the control categories of the application.
- * Routes that support at least one of the given control categories only exists and are handled
+ * Routes that support at least one of the given control categories are handled
* by the media router.
*/
public void setControlCategories(@NonNull Collection<String> controlCategories) {
Objects.requireNonNull(controlCategories, "control categories must not be null");
- // To ensure invoking callbacks correctly according to control categories
- mHandler.sendMessage(obtainMessage(MediaRouter2::setControlCategoriesOnHandler,
- MediaRouter2.this, new ArrayList<>(controlCategories)));
+ List<String> newControlCategories = new ArrayList<>(controlCategories);
+
+ synchronized (sLock) {
+ mShouldUpdateRoutes = true;
+
+ // invoke callbacks due to control categories change
+ handleControlCategoriesChangedLocked(newControlCategories);
+ if (mClient != null) {
+ try {
+ mMediaRouterService.setControlCategories(mClient, mControlCategories);
+ } catch (RemoteException ex) {
+ Log.e(TAG, "Unable to set control categories.", ex);
+ }
+ }
+ }
}
/**
* Gets the unmodifiable list of {@link MediaRoute2Info routes} currently
* known to the media router.
+ * Please note that the list can be changed before callbacks are invoked.
*
* @return the list of routes that support at least one of the control categories set by
* the application
*/
@NonNull
public List<MediaRoute2Info> getRoutes() {
+ synchronized (sLock) {
+ if (mShouldUpdateRoutes) {
+ mShouldUpdateRoutes = false;
+
+ List<MediaRoute2Info> filteredRoutes = new ArrayList<>();
+ for (MediaRoute2Info route : mRoutes.values()) {
+ if (route.supportsControlCategories(mControlCategories)) {
+ filteredRoutes.add(route);
+ }
+ }
+ mFilteredRoutes = Collections.unmodifiableList(filteredRoutes);
+ }
+ }
return mFilteredRoutes;
}
/**
- * Gets the currently selected route.
+ * Registers a callback to get updates on creations and changes of route sessions.
+ * If you register the same callback twice or more, it will be ignored.
+ *
+ * @param executor the executor to execute the callback on
+ * @param callback the callback to register
+ * @see #unregisterSessionCallback
+ */
+ @NonNull
+ public void registerSessionCallback(@CallbackExecutor Executor executor,
+ @NonNull SessionCallback callback) {
+ Objects.requireNonNull(executor, "executor must not be null");
+ Objects.requireNonNull(callback, "callback must not be null");
+
+ SessionCallbackRecord record = new SessionCallbackRecord(executor, callback);
+ if (!mSessionCallbackRecords.addIfAbsent(record)) {
+ Log.w(TAG, "Ignoring the same session callback");
+ return;
+ }
+ }
+
+ /**
+ * Unregisters the given callback. The callback will no longer receive events.
+ * If the callback has not been added or been removed already, it is ignored.
*
- * @return the selected route
+ * @param callback the callback to unregister
+ * @see #registerSessionCallback
*/
@NonNull
- public MediaRoute2Info getSelectedRoute() {
- return mSelectedRoute;
+ public void unregisterSessionCallback(@NonNull SessionCallback callback) {
+ Objects.requireNonNull(callback, "callback must not be null");
+
+ if (!mSessionCallbackRecords.remove(new SessionCallbackRecord(null, callback))) {
+ Log.w(TAG, "Ignoring unknown session callback");
+ return;
+ }
}
/**
- * Request to select the specified route. When the route is selected,
- * {@link Callback#onRouteSelected(MediaRoute2Info, int, Bundle)} will be called.
+ * Requests the media route provider service to create a session with the given route.
+ *
+ * @param route the route you want to create a session with.
+ * @param controlCategory the control category of the session. Should not be empty
*
- * @param route the route to select
+ * @see SessionCallback#onSessionCreated
+ * @see SessionCallback#onSessionCreationFailed
*/
- public void requestSelectRoute(@NonNull MediaRoute2Info route) {
+ @NonNull
+ public void requestCreateSession(@NonNull MediaRoute2Info route,
+ @NonNull String controlCategory) {
Objects.requireNonNull(route, "route must not be null");
+ if (TextUtils.isEmpty(controlCategory)) {
+ throw new IllegalArgumentException("controlCategory must not be empty");
+ }
+ // TODO: Check the given route exists
+ // TODO: Check the route supports the given controlCategory
+
+ final int requestId;
+ requestId = mSessionCreationRequestCnt.getAndIncrement();
+
+ SessionCreationRequest request = new SessionCreationRequest(
+ requestId, route, controlCategory);
+ mSessionCreationRequests.add(request);
Client2 client;
synchronized (sLock) {
- if (mSelectingRoute == route) {
- Log.w(TAG, "The route selection request is already sent.");
- return;
- }
- mSelectingRoute = route;
client = mClient;
}
if (client != null) {
try {
- mMediaRouterService.requestSelectRoute2(client, route);
+ mMediaRouterService.requestCreateSession(
+ client, route, controlCategory, requestId);
} catch (RemoteException ex) {
- Log.e(TAG, "Unable to request to select route.", ex);
+ Log.e(TAG, "Unable to request to create session.", ex);
+ mHandler.sendMessage(obtainMessage(MediaRouter2::createControllerOnHandler,
+ MediaRouter2.this, null, requestId));
}
}
}
@@ -379,43 +460,16 @@ public class MediaRouter2 {
}
}
- @GuardedBy("mCallbackRecords")
- private int findCallbackRecordIndexLocked(Callback callback) {
- final int count = mCallbackRecords.size();
- for (int i = 0; i < count; i++) {
- CallbackRecord callbackRecord = mCallbackRecords.get(i);
- if (callbackRecord.mCallback == callback) {
- return i;
- }
- }
- return -1;
- }
-
- private void setControlCategoriesOnHandler(List<String> newControlCategories) {
- List<String> prevControlCategories = mControlCategories;
+ private void handleControlCategoriesChangedLocked(List<String> newControlCategories) {
List<MediaRoute2Info> addedRoutes = new ArrayList<>();
List<MediaRoute2Info> removedRoutes = new ArrayList<>();
- List<MediaRoute2Info> filteredRoutes = new ArrayList<>();
+ List<String> prevControlCategories = mControlCategories;
mControlCategories = newControlCategories;
- Client2 client;
- synchronized (sLock) {
- client = mClient;
- }
- if (client != null) {
- try {
- mMediaRouterService.setControlCategories(client, mControlCategories);
- } catch (RemoteException ex) {
- Log.e(TAG, "Unable to set control categories.", ex);
- }
- }
for (MediaRoute2Info route : mRoutes.values()) {
- boolean preSupported = route.supportsControlCategory(prevControlCategories);
- boolean postSupported = route.supportsControlCategory(newControlCategories);
- if (postSupported) {
- filteredRoutes.add(route);
- }
+ boolean preSupported = route.supportsControlCategories(prevControlCategories);
+ boolean postSupported = route.supportsControlCategories(newControlCategories);
if (preSupported == postSupported) {
continue;
}
@@ -425,13 +479,14 @@ public class MediaRouter2 {
addedRoutes.add(route);
}
}
- mFilteredRoutes = Collections.unmodifiableList(filteredRoutes);
if (removedRoutes.size() > 0) {
- notifyRoutesRemoved(removedRoutes);
+ mHandler.sendMessage(obtainMessage(MediaRouter2::notifyRoutesRemoved,
+ MediaRouter2.this, removedRoutes));
}
if (addedRoutes.size() > 0) {
- notifyRoutesAdded(addedRoutes);
+ mHandler.sendMessage(obtainMessage(MediaRouter2::notifyRoutesAdded,
+ MediaRouter2.this, addedRoutes));
}
}
@@ -441,116 +496,196 @@ public class MediaRouter2 {
// 2) Call onRouteSelected(system_route, reason_fallback) if previously selected route
// does not exist anymore. => We may need 'boolean MediaRoute2Info#isSystemRoute()'.
List<MediaRoute2Info> addedRoutes = new ArrayList<>();
- for (MediaRoute2Info route : routes) {
- mRoutes.put(route.getUniqueId(), route);
- if (route.supportsControlCategory(mControlCategories)) {
- addedRoutes.add(route);
+ synchronized (sLock) {
+ for (MediaRoute2Info route : routes) {
+ mRoutes.put(route.getUniqueId(), route);
+ if (route.supportsControlCategories(mControlCategories)) {
+ addedRoutes.add(route);
+ }
}
+ mShouldUpdateRoutes = true;
}
if (addedRoutes.size() > 0) {
- refreshFilteredRoutes();
notifyRoutesAdded(addedRoutes);
}
}
void removeRoutesOnHandler(List<MediaRoute2Info> routes) {
List<MediaRoute2Info> removedRoutes = new ArrayList<>();
- for (MediaRoute2Info route : routes) {
- mRoutes.remove(route.getUniqueId());
- if (route.supportsControlCategory(mControlCategories)) {
- removedRoutes.add(route);
+ synchronized (sLock) {
+ for (MediaRoute2Info route : routes) {
+ mRoutes.remove(route.getUniqueId());
+ if (route.supportsControlCategories(mControlCategories)) {
+ removedRoutes.add(route);
+ }
}
+ mShouldUpdateRoutes = true;
}
if (removedRoutes.size() > 0) {
- refreshFilteredRoutes();
notifyRoutesRemoved(removedRoutes);
}
}
void changeRoutesOnHandler(List<MediaRoute2Info> routes) {
List<MediaRoute2Info> changedRoutes = new ArrayList<>();
- for (MediaRoute2Info route : routes) {
- mRoutes.put(route.getUniqueId(), route);
- if (route.supportsControlCategory(mControlCategories)) {
- changedRoutes.add(route);
+ synchronized (sLock) {
+ for (MediaRoute2Info route : routes) {
+ mRoutes.put(route.getUniqueId(), route);
+ if (route.supportsControlCategories(mControlCategories)) {
+ changedRoutes.add(route);
+ }
}
}
if (changedRoutes.size() > 0) {
- refreshFilteredRoutes();
notifyRoutesChanged(changedRoutes);
}
}
- void selectRouteOnHandler(MediaRoute2Info route, int reason, Bundle controlHints) {
- synchronized (sLock) {
- if (reason == SELECT_REASON_USER_SELECTED) {
- if (mSelectingRoute == null
- || !TextUtils.equals(mSelectingRoute.getUniqueId(), route.getUniqueId())) {
- Log.w(TAG, "Ignoring invalid or outdated notifyRouteSelected call. "
- + "selectingRoute=" + mSelectingRoute + " route=" + route);
- return;
- }
+ /**
+ * Creates a controller and calls the {@link SessionCallback#onSessionCreated}.
+ * If session creation has failed, then it calls
+ * {@link SessionCallback#onSessionCreationFailed}.
+ * <p>
+ * Pass {@code null} to sessionInfo for the failure case.
+ */
+ void createControllerOnHandler(@Nullable RouteSessionInfo sessionInfo, int requestId) {
+ SessionCreationRequest matchingRequest = null;
+ for (SessionCreationRequest request : mSessionCreationRequests) {
+ if (request.mRequestId == requestId) {
+ matchingRequest = request;
+ break;
}
- mSelectingRoute = null;
}
- if (reason == SELECT_REASON_SYSTEM_SELECTED) {
- reason = SELECT_REASON_USER_SELECTED;
+
+ if (matchingRequest != null) {
+ mSessionCreationRequests.remove(matchingRequest);
+
+ MediaRoute2Info requestedRoute = matchingRequest.mRoute;
+ String requestedControlCategory = matchingRequest.mControlCategory;
+
+ if (sessionInfo == null) {
+ // TODO: We may need to distinguish between failure and rejection.
+ // One way can be introducing 'reason'.
+ notifySessionCreationFailed(requestedRoute, requestedControlCategory);
+ return;
+ } else if (!TextUtils.equals(requestedControlCategory,
+ sessionInfo.getControlCategory())) {
+ Log.w(TAG, "The session has different control category from what we requested. "
+ + "(requested=" + requestedControlCategory
+ + ", actual=" + sessionInfo.getControlCategory()
+ + ")");
+ notifySessionCreationFailed(requestedRoute, requestedControlCategory);
+ return;
+ } else if (!sessionInfo.getSelectedRoutes().contains(requestedRoute.getId())) {
+ Log.w(TAG, "The session does not contain the requested route. "
+ + "(requestedRouteId=" + requestedRoute.getId()
+ + ", actualRoutes=" + sessionInfo.getSelectedRoutes()
+ + ")");
+ notifySessionCreationFailed(requestedRoute, requestedControlCategory);
+ return;
+ } else if (!TextUtils.equals(requestedRoute.getProviderId(),
+ sessionInfo.getProviderId())) {
+ Log.w(TAG, "The session's provider ID does not match the requested route's. "
+ + "(requested route's providerId=" + requestedRoute.getProviderId()
+ + ", actual providerId=" + sessionInfo.getProviderId()
+ + ")");
+ notifySessionCreationFailed(requestedRoute, requestedControlCategory);
+ return;
+ }
+ }
+
+ if (sessionInfo != null) {
+ RouteSessionController controller = new RouteSessionController(sessionInfo);
+ mSessionControllers.put(controller.getUniqueSessionId(), controller);
+ notifySessionCreated(controller);
}
- mSelectedRoute = route;
- notifyRouteSelected(route, reason, controlHints);
}
- private void refreshFilteredRoutes() {
- List<MediaRoute2Info> filteredRoutes = new ArrayList<>();
+ void changeSessionInfoOnHandler(RouteSessionInfo sessionInfo) {
+ if (sessionInfo == null) {
+ Log.w(TAG, "changeSessionInfoOnHandler: Ignoring null sessionInfo.");
+ return;
+ }
- for (MediaRoute2Info route : mRoutes.values()) {
- if (route.supportsControlCategory(mControlCategories)) {
- filteredRoutes.add(route);
- }
+ RouteSessionController matchingController = mSessionControllers.get(
+ sessionInfo.getUniqueSessionId());
+
+ if (matchingController == null) {
+ Log.w(TAG, "changeSessionInfoOnHandler: Matching controller not found. uniqueSessionId="
+ + sessionInfo.getUniqueSessionId());
+ return;
}
- mFilteredRoutes = Collections.unmodifiableList(filteredRoutes);
+
+ RouteSessionInfo oldInfo = matchingController.getRouteSessionInfo();
+ if (!TextUtils.equals(oldInfo.getProviderId(), sessionInfo.getProviderId())) {
+ Log.w(TAG, "changeSessionInfoOnHandler: Provider IDs are not matched. old="
+ + oldInfo.getProviderId() + ", new=" + sessionInfo.getProviderId());
+ return;
+ }
+
+ matchingController.setRouteSessionInfo(sessionInfo);
+ notifySessionInfoChanged(matchingController, oldInfo, sessionInfo);
}
private void notifyRoutesAdded(List<MediaRoute2Info> routes) {
- for (CallbackRecord record: mCallbackRecords) {
+ for (RouteCallbackRecord record: mRouteCallbackRecords) {
record.mExecutor.execute(
- () -> record.mCallback.onRoutesAdded(routes));
+ () -> record.mRouteCallback.onRoutesAdded(routes));
}
}
private void notifyRoutesRemoved(List<MediaRoute2Info> routes) {
- for (CallbackRecord record: mCallbackRecords) {
+ for (RouteCallbackRecord record: mRouteCallbackRecords) {
record.mExecutor.execute(
- () -> record.mCallback.onRoutesRemoved(routes));
+ () -> record.mRouteCallback.onRoutesRemoved(routes));
}
}
private void notifyRoutesChanged(List<MediaRoute2Info> routes) {
- for (CallbackRecord record: mCallbackRecords) {
+ for (RouteCallbackRecord record: mRouteCallbackRecords) {
record.mExecutor.execute(
- () -> record.mCallback.onRoutesChanged(routes));
+ () -> record.mRouteCallback.onRoutesChanged(routes));
}
}
- private void notifyRouteSelected(MediaRoute2Info route, int reason, Bundle controlHints) {
- for (CallbackRecord record: mCallbackRecords) {
+ private void notifySessionCreated(RouteSessionController controller) {
+ for (SessionCallbackRecord record: mSessionCallbackRecords) {
record.mExecutor.execute(
- () -> record.mCallback.onRouteSelected(route, reason, controlHints));
+ () -> record.mSessionCallback.onSessionCreated(controller));
+ }
+ }
+
+ private void notifySessionCreationFailed(MediaRoute2Info route, String controlCategory) {
+ for (SessionCallbackRecord record: mSessionCallbackRecords) {
+ record.mExecutor.execute(
+ () -> record.mSessionCallback.onSessionCreationFailed(route, controlCategory));
+ }
+ }
+
+ private void notifySessionInfoChanged(RouteSessionController controller,
+ RouteSessionInfo oldInfo, RouteSessionInfo newInfo) {
+ for (SessionCallbackRecord record: mSessionCallbackRecords) {
+ record.mExecutor.execute(
+ () -> record.mSessionCallback.onSessionInfoChanged(
+ controller, oldInfo, newInfo));
}
}
/**
- * Interface for receiving events about media routing changes.
+ * Callback for receiving events about media route discovery.
*/
- public static class Callback {
+ public static class RouteCallback {
/**
- * Called when routes are added.
+ * Called when routes are added. Whenever you registers a callback, this will
+ * be invoked with known routes.
+ *
* @param routes the list of routes that have been added. It's never empty.
*/
public void onRoutesAdded(@NonNull List<MediaRoute2Info> routes) {}
/**
* Called when routes are removed.
+ *
* @param routes the list of routes that have been removed. It's never empty.
*/
public void onRoutesRemoved(@NonNull List<MediaRoute2Info> routes) {}
@@ -566,37 +701,408 @@ public class MediaRouter2 {
* @param routes the list of routes that have been changed. It's never empty.
*/
public void onRoutesChanged(@NonNull List<MediaRoute2Info> routes) {}
+ }
+
+ /**
+ * Callback for receiving a result of session creation and session updates.
+ */
+ public static class SessionCallback {
+ /**
+ * Called when the route session is created by the route provider.
+ *
+ * @param controller the controller to control the created session
+ */
+ public void onSessionCreated(@NonNull RouteSessionController controller) {}
+
+ /**
+ * Called when the session creation request failed.
+ *
+ * @param requestedRoute the route info which was used for the request
+ * @param requestedControlCategory the control category which was used for the request
+ */
+ public void onSessionCreationFailed(@NonNull MediaRoute2Info requestedRoute,
+ @NonNull String requestedControlCategory) {}
+
+ /**
+ * Called when the session info has changed.
+ *
+ * @param oldInfo the session info before the session changed.
+ * @prarm newInfo the changed session info
+ *
+ * TODO: (Discussion) Do we really need newInfo? The controller has the newInfo.
+ * However. there can be timing issue if there is no newInfo.
+ */
+ public void onSessionInfoChanged(@NonNull RouteSessionController controller,
+ @NonNull RouteSessionInfo oldInfo,
+ @NonNull RouteSessionInfo newInfo) {}
+
+ /**
+ * Called when the session is released. Session can be released by the controller using
+ * {@link RouteSessionController#release(boolean)}, or by the
+ * {@link MediaRoute2ProviderService} itself. One can do clean-ups here.
+ *
+ * TODO: When Provider#notifySessionDestroyed is introduced, add @see for the method.
+ */
+ public void onSessionReleased(@NonNull RouteSessionController controller, int reason,
+ boolean shouldStop) {}
+ }
+
+ /**
+ * A class to control media route session in media route provider.
+ * For example, selecting/deselcting/transferring routes to session can be done through this
+ * class. Instances are created by {@link MediaRouter2}.
+ *
+ * TODO: Need to add toString()
+ */
+ public final class RouteSessionController {
+ private final Object mLock = new Object();
+
+ @GuardedBy("mLock")
+ private RouteSessionInfo mSessionInfo;
+
+ @GuardedBy("mLock")
+ private volatile boolean mIsReleased;
+
+ RouteSessionController(@NonNull RouteSessionInfo sessionInfo) {
+ mSessionInfo = sessionInfo;
+ }
+
+ /**
+ * @return the ID of the session
+ */
+ public int getSessionId() {
+ synchronized (mLock) {
+ return mSessionInfo.getSessionId();
+ }
+ }
+
+ /**
+ * @return the unique ID of the session
+ * @hide
+ */
+ @NonNull
+ public String getUniqueSessionId() {
+ synchronized (mLock) {
+ return mSessionInfo.getUniqueSessionId();
+ }
+ }
+
+ /**
+ * @return the category of routes that the session includes.
+ */
+ @NonNull
+ public String getControlCategory() {
+ synchronized (mLock) {
+ return mSessionInfo.getControlCategory();
+ }
+ }
+
+ /**
+ * @return the control hints used to control route session if available.
+ */
+ @Nullable
+ public Bundle getControlHints() {
+ synchronized (mLock) {
+ return mSessionInfo.getControlHints();
+ }
+ }
+
+ /**
+ * @return the unmodifiable list of currently selected routes
+ */
+ @NonNull
+ public List<MediaRoute2Info> getSelectedRoutes() {
+ synchronized (mLock) {
+ return getRoutesWithIdsLocked(mSessionInfo.getSelectedRoutes());
+ }
+ }
+
+ /**
+ * @return the unmodifiable list of selectable routes for the session.
+ */
+ @NonNull
+ public List<MediaRoute2Info> getSelectableRoutes() {
+ synchronized (mLock) {
+ return getRoutesWithIdsLocked(mSessionInfo.getSelectableRoutes());
+ }
+ }
+
+ /**
+ * @return the unmodifiable list of deselectable routes for the session.
+ */
+ @NonNull
+ public List<MediaRoute2Info> getDeselectableRoutes() {
+ synchronized (mLock) {
+ return getRoutesWithIdsLocked(mSessionInfo.getDeselectableRoutes());
+ }
+ }
+
+ /**
+ * @return the unmodifiable list of transferrable routes for the session.
+ */
+ @NonNull
+ public List<MediaRoute2Info> getTransferrableRoutes() {
+ synchronized (mLock) {
+ return getRoutesWithIdsLocked(mSessionInfo.getTransferrableRoutes());
+ }
+ }
+
+ /**
+ * Returns true if the session is released, false otherwise.
+ * If it is released, then all other getters from this instance may return invalid values.
+ * Also, any operations to this instance will be ignored once released.
+ *
+ * @see #release
+ * @see SessionCallback#onSessionReleased
+ */
+ public boolean isReleased() {
+ synchronized (mLock) {
+ return mIsReleased;
+ }
+ }
+
+ /**
+ * Selects a route for the remote session. The given route must satisfy all of the
+ * following conditions:
+ * <ul>
+ * <li>ID should not be included in {@link #getSelectedRoutes()}</li>
+ * <li>ID should be included in {@link #getSelectableRoutes()}</li>
+ * </ul>
+ * If the route doesn't meet any of above conditions, it will be ignored.
+ *
+ * @see #getSelectedRoutes()
+ * @see #getSelectableRoutes()
+ * @see SessionCallback#onSessionInfoChanged
+ */
+ public void selectRoute(@NonNull MediaRoute2Info route) {
+ Objects.requireNonNull(route, "route must not be null");
+
+ List<MediaRoute2Info> selectedRoutes = getSelectedRoutes();
+ if (checkRouteListContainsRouteId(selectedRoutes, route.getUniqueId())) {
+ Log.w(TAG, "Ignoring selecting a route that is already selected. route=" + route);
+ return;
+ }
+
+ List<MediaRoute2Info> selectableRoutes = getSelectableRoutes();
+ if (!checkRouteListContainsRouteId(selectableRoutes, route.getUniqueId())) {
+ Log.w(TAG, "Ignoring selecting a non-selectable route=" + route);
+ return;
+ }
+
+ Client2 client;
+ synchronized (sLock) {
+ client = mClient;
+ }
+ if (client != null) {
+ try {
+ mMediaRouterService.selectRoute(mClient, getUniqueSessionId(), route);
+ } catch (RemoteException ex) {
+ Log.e(TAG, "Unable to select route for session.", ex);
+ }
+ }
+ }
/**
- * Called when a route is selected. Exactly one route can be selected at a time.
- * @param route the selected route.
- * @param reason the reason why the route is selected.
- * @param controlHints An optional bundle of provider-specific arguments which may be
- * used to control the selected route. Can be empty.
- * @see #SELECT_REASON_UNKNOWN
- * @see #SELECT_REASON_USER_SELECTED
- * @see #SELECT_REASON_FALLBACK
- * @see #getSelectedRoute()
+ * Deselects a route from the remote session. The given route must satisfy all of the
+ * following conditions:
+ * <ul>
+ * <li>ID should be included in {@link #getSelectedRoutes()}</li>
+ * <li>ID should be included in {@link #getDeselectableRoutes()}</li>
+ * </ul>
+ * If the route doesn't meet any of above conditions, it will be ignored.
+ *
+ * @see #getSelectedRoutes()
+ * @see #getDeselectableRoutes()
+ * @see SessionCallback#onSessionInfoChanged
*/
- public void onRouteSelected(@NonNull MediaRoute2Info route, @SelectReason int reason,
- @NonNull Bundle controlHints) {}
+ public void deselectRoute(@NonNull MediaRoute2Info route) {
+ Objects.requireNonNull(route, "route must not be null");
+
+ List<MediaRoute2Info> selectedRoutes = getSelectedRoutes();
+ if (!checkRouteListContainsRouteId(selectedRoutes, route.getUniqueId())) {
+ Log.w(TAG, "Ignoring deselecting a route that is not selected. route=" + route);
+ return;
+ }
+
+ List<MediaRoute2Info> deselectableRoutes = getDeselectableRoutes();
+ if (!checkRouteListContainsRouteId(deselectableRoutes, route.getUniqueId())) {
+ Log.w(TAG, "Ignoring deselecting a non-deselectable route=" + route);
+ return;
+ }
+
+ Client2 client;
+ synchronized (sLock) {
+ client = mClient;
+ }
+ if (client != null) {
+ try {
+ mMediaRouterService.deselectRoute(mClient, getUniqueSessionId(), route);
+ } catch (RemoteException ex) {
+ Log.e(TAG, "Unable to remove route from session.", ex);
+ }
+ }
+ }
+
+ /**
+ * Transfers to a given route for the remote session. The given route must satisfy
+ * all of the following conditions:
+ * <ul>
+ * <li>ID should not be included in {@link #getSelectedRoutes()}</li>
+ * <li>ID should be included in {@link #getTransferrableRoutes()}</li>
+ * </ul>
+ * If the route doesn't meet any of above conditions, it will be ignored.
+ *
+ * @see #getSelectedRoutes()
+ * @see #getTransferrableRoutes()
+ * @see SessionCallback#onSessionInfoChanged
+ */
+ public void transferToRoute(@NonNull MediaRoute2Info route) {
+ Objects.requireNonNull(route, "route must not be null");
+
+ List<MediaRoute2Info> selectedRoutes = getSelectedRoutes();
+ if (checkRouteListContainsRouteId(selectedRoutes, route.getUniqueId())) {
+ Log.w(TAG, "Ignoring transferring to a route that is already added. route="
+ + route);
+ return;
+ }
+
+ List<MediaRoute2Info> transferrableRoutes = getTransferrableRoutes();
+ if (!checkRouteListContainsRouteId(transferrableRoutes, route.getUniqueId())) {
+ Log.w(TAG, "Ignoring transferring to a non-transferrable route=" + route);
+ return;
+ }
+
+ Client2 client;
+ synchronized (sLock) {
+ client = mClient;
+ }
+ if (client != null) {
+ try {
+ mMediaRouterService.transferToRoute(mClient, getUniqueSessionId(), route);
+ } catch (RemoteException ex) {
+ Log.e(TAG, "Unable to transfer to route for session.", ex);
+ }
+ }
+ }
+
+ /**
+ * Release this session.
+ * Any operation on this session after calling this method will be ignored.
+ *
+ * @param stopMedia Should the media that is playing on the device be stopped after this
+ * session is released.
+ * @see SessionCallback#onSessionReleased
+ */
+ public void release(boolean stopMedia) {
+ synchronized (mLock) {
+ if (mIsReleased) {
+ return;
+ }
+ mIsReleased = true;
+ }
+ // TODO: Use stopMedia variable when the actual connection logic is implemented.
+ }
+
+ /**
+ * @hide
+ */
+ @NonNull
+ public RouteSessionInfo getRouteSessionInfo() {
+ synchronized (mLock) {
+ return mSessionInfo;
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public void setRouteSessionInfo(@NonNull RouteSessionInfo info) {
+ synchronized (mLock) {
+ mSessionInfo = info;
+ }
+ }
+
+ private List<MediaRoute2Info> getRoutesWithIdsLocked(List<String> routeIds) {
+ List<MediaRoute2Info> routes = new ArrayList<>();
+ synchronized (mLock) {
+ for (String routeId : routeIds) {
+ MediaRoute2Info route = mRoutes.get(
+ MediaRoute2Info.toUniqueId(mSessionInfo.mProviderId, routeId));
+ if (route != null) {
+ routes.add(route);
+ }
+ }
+ }
+ return Collections.unmodifiableList(routes);
+ }
}
- final class CallbackRecord {
- public final Callback mCallback;
- public Executor mExecutor;
- public int mFlags;
+ final class RouteCallbackRecord {
+ public final Executor mExecutor;
+ public final RouteCallback mRouteCallback;
+ public final int mFlags;
- CallbackRecord(@NonNull Callback callback) {
- mCallback = callback;
+ RouteCallbackRecord(@Nullable Executor executor, @NonNull RouteCallback routeCallback,
+ int flags) {
+ mRouteCallback = routeCallback;
+ mExecutor = executor;
+ mFlags = flags;
}
- void notifyRoutes() {
- final List<MediaRoute2Info> routes = mFilteredRoutes;
- // notify only when bound to media router service.
- if (routes.size() > 0) {
- mExecutor.execute(() -> mCallback.onRoutesAdded(routes));
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof RouteCallbackRecord)) {
+ return false;
}
+ return mRouteCallback == ((RouteCallbackRecord) obj).mRouteCallback;
+ }
+
+ @Override
+ public int hashCode() {
+ return mRouteCallback.hashCode();
+ }
+ }
+
+ final class SessionCallbackRecord {
+ public final Executor mExecutor;
+ public final SessionCallback mSessionCallback;
+
+ SessionCallbackRecord(@NonNull Executor executor,
+ @NonNull SessionCallback sessionCallback) {
+ mSessionCallback = sessionCallback;
+ mExecutor = executor;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof SessionCallbackRecord)) {
+ return false;
+ }
+ return mSessionCallback == ((SessionCallbackRecord) obj).mSessionCallback;
+ }
+
+ @Override
+ public int hashCode() {
+ return mSessionCallback.hashCode();
+ }
+ }
+
+ final class SessionCreationRequest {
+ public final MediaRoute2Info mRoute;
+ public final String mControlCategory;
+ public final int mRequestId;
+
+ SessionCreationRequest(int requestId, @NonNull MediaRoute2Info route,
+ @NonNull String controlCategory) {
+ mRoute = route;
+ mControlCategory = controlCategory;
+ mRequestId = requestId;
}
}
@@ -623,10 +1129,15 @@ public class MediaRouter2 {
}
@Override
- public void notifyRouteSelected(MediaRoute2Info route, int reason,
- Bundle controlHints) {
- mHandler.sendMessage(obtainMessage(MediaRouter2::selectRouteOnHandler,
- MediaRouter2.this, route, reason, controlHints));
+ public void notifySessionCreated(@Nullable RouteSessionInfo sessionInfo, int requestId) {
+ mHandler.sendMessage(obtainMessage(MediaRouter2::createControllerOnHandler,
+ MediaRouter2.this, sessionInfo, requestId));
+ }
+
+ @Override
+ public void notifySessionInfoChanged(@Nullable RouteSessionInfo sessionInfo) {
+ mHandler.sendMessage(obtainMessage(MediaRouter2::changeSessionInfoOnHandler,
+ MediaRouter2.this, sessionInfo));
}
}
}
diff --git a/media/java/android/media/MediaRouter2Manager.java b/media/java/android/media/MediaRouter2Manager.java
index d56dd11fb8f2..2e68e42e714f 100644
--- a/media/java/android/media/MediaRouter2Manager.java
+++ b/media/java/android/media/MediaRouter2Manager.java
@@ -25,6 +25,7 @@ import android.content.Context;
import android.os.Handler;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.text.TextUtils;
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
@@ -39,6 +40,7 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicInteger;
/**
* @hide
@@ -57,7 +59,7 @@ public class MediaRouter2Manager {
private Client mClient;
private final IMediaRouterService mMediaRouterService;
final Handler mHandler;
- final List<CallbackRecord> mCallbackRecords = new CopyOnWriteArrayList<>();
+ final CopyOnWriteArrayList<CallbackRecord> mCallbackRecords = new CopyOnWriteArrayList<>();
private final Object mRoutesLock = new Object();
@GuardedBy("mRoutesLock")
@@ -65,6 +67,8 @@ public class MediaRouter2Manager {
@NonNull
final ConcurrentMap<String, List<String>> mControlCategoryMap = new ConcurrentHashMap<>();
+ private AtomicInteger mNextRequestId = new AtomicInteger(1);
+
/**
* Gets an instance of media router manager that controls media route of other applications.
*
@@ -99,14 +103,10 @@ public class MediaRouter2Manager {
Objects.requireNonNull(executor, "executor must not be null");
Objects.requireNonNull(callback, "callback must not be null");
- CallbackRecord callbackRecord;
- synchronized (mCallbackRecords) {
- if (findCallbackRecordIndexLocked(callback) >= 0) {
- Log.w(TAG, "Ignoring to add the same callback twice.");
- return;
- }
- callbackRecord = new CallbackRecord(executor, callback);
- mCallbackRecords.add(callbackRecord);
+ CallbackRecord callbackRecord = new CallbackRecord(executor, callback);
+ if (!mCallbackRecords.addIfAbsent(callbackRecord)) {
+ Log.w(TAG, "Ignoring to add the same callback twice.");
+ return;
}
synchronized (sLock) {
@@ -118,8 +118,6 @@ public class MediaRouter2Manager {
} catch (RemoteException ex) {
Log.e(TAG, "Unable to register media router manager.", ex);
}
- } else {
- callbackRecord.notifyRoutes();
}
}
}
@@ -132,36 +130,23 @@ public class MediaRouter2Manager {
public void unregisterCallback(@NonNull Callback callback) {
Objects.requireNonNull(callback, "callback must not be null");
- synchronized (mCallbackRecords) {
- final int index = findCallbackRecordIndexLocked(callback);
- if (index < 0) {
- Log.w(TAG, "Ignore removing unknown callback. " + callback);
- return;
- }
- mCallbackRecords.remove(index);
- synchronized (sLock) {
- if (mCallbackRecords.size() == 0 && mClient != null) {
- try {
- mMediaRouterService.unregisterManager(mClient);
- } catch (RemoteException ex) {
- Log.e(TAG, "Unable to unregister media router manager", ex);
- }
- //TODO: clear mRoutes?
- mClient = null;
- }
- }
+ if (!mCallbackRecords.remove(new CallbackRecord(null, callback))) {
+ Log.w(TAG, "Ignore removing unknown callback. " + callback);
+ return;
}
- }
- @GuardedBy("mCallbackRecords")
- private int findCallbackRecordIndexLocked(Callback callback) {
- final int count = mCallbackRecords.size();
- for (int i = 0; i < count; i++) {
- if (mCallbackRecords.get(i).mCallback == callback) {
- return i;
+ synchronized (sLock) {
+ if (mCallbackRecords.size() == 0 && mClient != null) {
+ try {
+ mMediaRouterService.unregisterManager(mClient);
+ } catch (RemoteException ex) {
+ Log.e(TAG, "Unable to unregister media router manager", ex);
+ }
+ //TODO: clear mRoutes?
+ mClient = null;
+ mControlCategoryMap.clear();
}
}
- return -1;
}
//TODO: Use cache not to create array. For now, it's unclear when to purge the cache.
@@ -182,51 +167,77 @@ public class MediaRouter2Manager {
List<MediaRoute2Info> routes = new ArrayList<>();
synchronized (mRoutesLock) {
for (MediaRoute2Info route : mRoutes.values()) {
- if (route.supportsControlCategory(controlCategories)) {
+ if (route.supportsControlCategories(controlCategories)) {
routes.add(route);
}
}
}
- //TODO: Should we cache this?
return routes;
}
- /**
- * Selects media route for the specified package name.
- *
- * @param packageName the package name of the application that should change it's media route
- * @param route the route to be selected
- */
- public void selectRoute(@NonNull String packageName, @NonNull MediaRoute2Info route) {
- Objects.requireNonNull(packageName, "packageName must not be null");
- Objects.requireNonNull(route, "route must not be null");
-
+ @NonNull
+ public List<RouteSessionInfo> getActiveSessions() {
Client client;
synchronized (sLock) {
client = mClient;
}
if (client != null) {
try {
- mMediaRouterService.selectClientRoute2(client, packageName, route);
+ return mMediaRouterService.getActiveSessions(client);
} catch (RemoteException ex) {
- Log.e(TAG, "Unable to select media route", ex);
+ Log.e(TAG, "Unable to get sessions. Service probably died.", ex);
+ }
+ }
+ return Collections.emptyList();
+ }
+
+ /**
+ * Gets the list of routes that are actively used by {@link MediaRouter2}.
+ */
+ @NonNull
+ public List<MediaRoute2Info> getActiveRoutes() {
+ List<MediaRoute2Info> routes = new ArrayList<>();
+ synchronized (mRoutesLock) {
+ for (MediaRoute2Info route : mRoutes.values()) {
+ if (!TextUtils.isEmpty(route.getClientPackageName())) {
+ routes.add(route);
+ }
}
}
+ return routes;
}
/**
- * Unselects media route for the specified package name.
+ * Gets the list of discovered routes
+ */
+ @NonNull
+ public List<MediaRoute2Info> getAllRoutes() {
+ List<MediaRoute2Info> routes = new ArrayList<>();
+ synchronized (mRoutesLock) {
+ routes.addAll(mRoutes.values());
+ }
+ return routes;
+ }
+
+ /**
+ * Selects media route for the specified package name.
*
- * @param packageName the package name of the application that should stop routing
+ * @param packageName the package name of the application that should change it's media route
+ * @param route the route to be selected.
*/
- public void unselectRoute(@NonNull String packageName) {
+ public void selectRoute(@NonNull String packageName, @NonNull MediaRoute2Info route) {
+ Objects.requireNonNull(packageName, "packageName must not be null");
+ Objects.requireNonNull(route, "route must not be null");
+
Client client;
synchronized (sLock) {
client = mClient;
}
if (client != null) {
try {
- mMediaRouterService.selectClientRoute2(client, packageName, null);
+ int requestId = mNextRequestId.getAndIncrement();
+ mMediaRouterService.requestCreateClientSession(
+ client, packageName, route, requestId);
} catch (RemoteException ex) {
Log.e(TAG, "Unable to select media route", ex);
}
@@ -342,10 +353,14 @@ public class MediaRouter2Manager {
}
void updateControlCategories(String packageName, List<String> categories) {
- mControlCategoryMap.put(packageName, categories);
+ List<String> prevCategories = mControlCategoryMap.put(packageName, categories);
+ if ((prevCategories == null && categories.size() == 0)
+ || Objects.equals(categories, prevCategories)) {
+ return;
+ }
for (CallbackRecord record : mCallbackRecords) {
record.mExecutor.execute(
- () -> record.mCallback.onControlCategoriesChanged(packageName));
+ () -> record.mCallback.onControlCategoriesChanged(packageName, categories));
}
}
@@ -386,8 +401,10 @@ public class MediaRouter2Manager {
* Called when the control categories of an app is changed.
*
* @param packageName the package name of the application
+ * @param controlCategories the list of control categories set by an application.
*/
- public void onControlCategoriesChanged(@NonNull String packageName) {}
+ public void onControlCategoriesChanged(@NonNull String packageName,
+ @NonNull List<String> controlCategories) {}
}
final class CallbackRecord {
@@ -399,14 +416,20 @@ public class MediaRouter2Manager {
mCallback = callback;
}
- void notifyRoutes() {
- List<MediaRoute2Info> routes;
- synchronized (mRoutesLock) {
- routes = new ArrayList<>(mRoutes.values());
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
}
- if (routes.size() > 0) {
- mExecutor.execute(() -> mCallback.onRoutesAdded(routes));
+ if (!(obj instanceof CallbackRecord)) {
+ return false;
}
+ return mCallback == ((CallbackRecord) obj).mCallback;
+ }
+
+ @Override
+ public int hashCode() {
+ return mCallback.hashCode();
}
}
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index ca96c9ab5670..aae2606bcf5e 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -16,7 +16,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentValues;
import android.content.Context;
import android.net.Uri;
diff --git a/media/java/android/media/Metadata.java b/media/java/android/media/Metadata.java
index 792a2ba678fd..ef17073654a6 100644
--- a/media/java/android/media/Metadata.java
+++ b/media/java/android/media/Metadata.java
@@ -16,7 +16,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.util.Log;
import android.util.MathUtils;
diff --git a/media/java/android/media/MicrophoneInfo.java b/media/java/android/media/MicrophoneInfo.java
index f805975d53b0..876628fefff4 100644
--- a/media/java/android/media/MicrophoneInfo.java
+++ b/media/java/android/media/MicrophoneInfo.java
@@ -18,7 +18,7 @@ package android.media;
import android.annotation.IntDef;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.Pair;
import java.lang.annotation.Retention;
diff --git a/media/java/android/media/PlaybackParams.java b/media/java/android/media/PlaybackParams.java
index b4325b6ea53d..f24f831d0333 100644
--- a/media/java/android/media/PlaybackParams.java
+++ b/media/java/android/media/PlaybackParams.java
@@ -18,7 +18,7 @@ package android.media;
import android.annotation.IntDef;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/media/java/android/media/RemoteControlClient.java b/media/java/android/media/RemoteControlClient.java
index 325420b06122..c5fd3c30236d 100644
--- a/media/java/android/media/RemoteControlClient.java
+++ b/media/java/android/media/RemoteControlClient.java
@@ -16,8 +16,8 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
import android.app.PendingIntent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Intent;
import android.graphics.Bitmap;
diff --git a/media/java/android/media/RemoteController.java b/media/java/android/media/RemoteController.java
index f70963a982e4..9e48f1e05391 100644
--- a/media/java/android/media/RemoteController.java
+++ b/media/java/android/media/RemoteController.java
@@ -16,8 +16,8 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.graphics.Bitmap;
diff --git a/media/java/android/media/RemoteDisplay.java b/media/java/android/media/RemoteDisplay.java
index 2be206f2f462..e529af9da935 100644
--- a/media/java/android/media/RemoteDisplay.java
+++ b/media/java/android/media/RemoteDisplay.java
@@ -16,12 +16,12 @@
package android.media;
-import dalvik.system.CloseGuard;
-
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Handler;
import android.view.Surface;
+import dalvik.system.CloseGuard;
+
/**
* Listens for Wifi remote display connections managed by the media server.
*
diff --git a/media/java/android/media/RemoteDisplayState.java b/media/java/android/media/RemoteDisplayState.java
index 2f4ace0c8fdd..fed361a960e6 100644
--- a/media/java/android/media/RemoteDisplayState.java
+++ b/media/java/android/media/RemoteDisplayState.java
@@ -16,7 +16,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
diff --git a/media/java/android/media/Ringtone.java b/media/java/android/media/Ringtone.java
index eb680c8377f4..d35bc4176cb3 100644
--- a/media/java/android/media/Ringtone.java
+++ b/media/java/android/media/Ringtone.java
@@ -17,7 +17,7 @@
package android.media;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index a1e159174f95..d058243a6fcb 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -23,9 +23,9 @@ import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.WorkerThread;
import android.app.Activity;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentUris;
diff --git a/media/java/android/media/RouteSessionController.java b/media/java/android/media/RouteSessionController.java
deleted file mode 100644
index 5ff721837573..000000000000
--- a/media/java/android/media/RouteSessionController.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import android.annotation.NonNull;
-
-import com.android.internal.annotations.GuardedBy;
-
-import java.util.List;
-import java.util.Objects;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.Executor;
-
-/**
- * A class to control media route session in media route provider.
- * For example, adding/removing/transferring routes to session can be done through this class.
- * Instances are created by {@link MediaRouter2}.
- *
- * TODO: When session is introduced, change Javadoc of all methods/classes by using [@link Session].
- *
- * @hide
- */
-public class RouteSessionController {
- private final int mSessionId;
- private final String mCategory;
- private final Object mLock = new Object();
-
- @GuardedBy("mLock")
- private final CopyOnWriteArrayList<CallbackRecord> mCallbackRecords =
- new CopyOnWriteArrayList<>();
-
- private volatile boolean mIsReleased;
-
- /**
- * @param sessionId the ID of the session.
- * @param category The category of media routes that the session includes.
- */
- RouteSessionController(int sessionId, @NonNull String category) {
- mSessionId = sessionId;
- mCategory = category;
- }
-
- /**
- * @return the ID of this controller
- */
- public int getSessionId() {
- return mSessionId;
- }
-
- /**
- * @return the category of routes that the session includes.
- */
- @NonNull
- public String getCategory() {
- return mCategory;
- }
-
- /**
- * @return the list of currently connected routes
- */
- @NonNull
- public List<MediaRoute2Info> getRoutes() {
- // TODO: Implement this when SessionInfo is introduced.
- return null;
- }
-
- /**
- * Returns true if the session is released, false otherwise.
- * If it is released, then all other getters from this instance may return invalid values.
- * Also, any operations to this instance will be ignored once released.
- *
- * @see #release
- * @see Callback#onReleased
- */
- public boolean isReleased() {
- return mIsReleased;
- }
-
- /**
- * Add routes to the remote session.
- *
- * @see #getRoutes()
- * @see Callback#onSessionInfoChanged
- */
- public void addRoutes(List<MediaRoute2Info> routes) {
- // TODO: Implement this when the actual connection logic is implemented.
- }
-
- /**
- * Remove routes from this session. Media may be stopped on those devices.
- * Route removal requests that are not currently in {@link #getRoutes()} will be ignored.
- *
- * @see #getRoutes()
- * @see Callback#onSessionInfoChanged
- */
- public void removeRoutes(List<MediaRoute2Info> routes) {
- // TODO: Implement this when the actual connection logic is implemented.
- }
-
- /**
- * Registers a {@link Callback} for monitoring route changes.
- * If the same callback is registered previously, previous executor will be overwritten with the
- * new one.
- */
- public void registerCallback(Executor executor, Callback callback) {
- if (mIsReleased) {
- return;
- }
- Objects.requireNonNull(executor, "executor must not be null");
- Objects.requireNonNull(callback, "callback must not be null");
-
- synchronized (mLock) {
- CallbackRecord recordWithSameCallback = null;
- for (CallbackRecord record : mCallbackRecords) {
- if (callback == record.mCallback) {
- recordWithSameCallback = record;
- break;
- }
- }
-
- if (recordWithSameCallback != null) {
- recordWithSameCallback.mExecutor = executor;
- } else {
- mCallbackRecords.add(new CallbackRecord(executor, callback));
- }
- }
- }
-
- /**
- * Unregisters a previously registered {@link Callback}.
- */
- public void unregisterCallback(Callback callback) {
- Objects.requireNonNull(callback, "callback must not be null");
-
- synchronized (mLock) {
- CallbackRecord recordToRemove = null;
- for (CallbackRecord record : mCallbackRecords) {
- if (callback == record.mCallback) {
- recordToRemove = record;
- break;
- }
- }
-
- if (recordToRemove != null) {
- mCallbackRecords.remove(recordToRemove);
- }
- }
- }
-
- /**
- * Release this session.
- * Any operation on this session after calling this method will be ignored.
- *
- * @param stopMedia Should the device where the media is played
- * be stopped after this session is released.
- */
- public void release(boolean stopMedia) {
- mIsReleased = true;
- mCallbackRecords.clear();
- // TODO: Use stopMedia variable when the actual connection logic is implemented.
- }
-
- /**
- * Callback class for getting updates on routes and session release.
- */
- public static class Callback {
-
- /**
- * Called when the session info has changed.
- * TODO: When SessionInfo is introduced, uncomment below argument.
- */
- void onSessionInfoChanged(/* SessionInfo info */) {}
-
- /**
- * Called when the session is released. Session can be released by the controller using
- * {@link #release(boolean)}, or by the {@link MediaRoute2ProviderService} itself.
- * One can do clean-ups here.
- *
- * TODO: When SessionInfo is introduced, change the javadoc of releasing session on
- * provider side.
- */
- void onReleased(int reason, boolean shouldStop) {}
- }
-
- private class CallbackRecord {
- public final Callback mCallback;
- public Executor mExecutor;
-
- CallbackRecord(@NonNull Executor executor, @NonNull Callback callback) {
- mExecutor = executor;
- mCallback = callback;
- }
- }
-}
diff --git a/media/java/android/media/RouteSessionInfo.aidl b/media/java/android/media/RouteSessionInfo.aidl
new file mode 100644
index 000000000000..fb5d836da98e
--- /dev/null
+++ b/media/java/android/media/RouteSessionInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+parcelable RouteSessionInfo;
diff --git a/media/java/android/media/RouteSessionInfo.java b/media/java/android/media/RouteSessionInfo.java
new file mode 100644
index 000000000000..b9cf15edb101
--- /dev/null
+++ b/media/java/android/media/RouteSessionInfo.java
@@ -0,0 +1,426 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Describes a route session that is made when a media route is selected.
+ * @hide
+ */
+public class RouteSessionInfo implements Parcelable {
+ @NonNull
+ public static final Creator<RouteSessionInfo> CREATOR =
+ new Creator<RouteSessionInfo>() {
+ @Override
+ public RouteSessionInfo createFromParcel(Parcel in) {
+ return new RouteSessionInfo(in);
+ }
+ @Override
+ public RouteSessionInfo[] newArray(int size) {
+ return new RouteSessionInfo[size];
+ }
+ };
+
+ final int mSessionId;
+ final String mPackageName;
+ final String mControlCategory;
+ @Nullable
+ final String mProviderId;
+ final List<String> mSelectedRoutes;
+ final List<String> mSelectableRoutes;
+ final List<String> mDeselectableRoutes;
+ final List<String> mTransferrableRoutes;
+ @Nullable
+ final Bundle mControlHints;
+
+ RouteSessionInfo(@NonNull Builder builder) {
+ Objects.requireNonNull(builder, "builder must not be null.");
+
+ mSessionId = builder.mSessionId;
+ mPackageName = builder.mPackageName;
+ mControlCategory = builder.mControlCategory;
+ mProviderId = builder.mProviderId;
+
+ mSelectedRoutes = Collections.unmodifiableList(builder.mSelectedRoutes);
+ mSelectableRoutes = Collections.unmodifiableList(builder.mSelectableRoutes);
+ mDeselectableRoutes = Collections.unmodifiableList(builder.mDeselectableRoutes);
+ mTransferrableRoutes = Collections.unmodifiableList(builder.mTransferrableRoutes);
+
+ mControlHints = builder.mControlHints;
+ }
+
+ RouteSessionInfo(@NonNull Parcel src) {
+ Objects.requireNonNull(src, "src must not be null.");
+
+ mSessionId = src.readInt();
+ mPackageName = ensureString(src.readString());
+ mControlCategory = ensureString(src.readString());
+ mProviderId = src.readString();
+
+ mSelectedRoutes = ensureList(src.createStringArrayList());
+ mSelectableRoutes = ensureList(src.createStringArrayList());
+ mDeselectableRoutes = ensureList(src.createStringArrayList());
+ mTransferrableRoutes = ensureList(src.createStringArrayList());
+
+ mControlHints = src.readBundle();
+ }
+
+ private static String ensureString(String str) {
+ if (str != null) {
+ return str;
+ }
+ return "";
+ }
+
+ private static <T> List<T> ensureList(List<? extends T> list) {
+ if (list != null) {
+ return Collections.unmodifiableList(list);
+ }
+ return Collections.emptyList();
+ }
+
+ /**
+ * Gets non-unique session id (int) from unique session id (string).
+ */
+ public static int getSessionId(@NonNull String uniqueSessionId, @NonNull String providerId) {
+ return Integer.parseInt(uniqueSessionId.substring(providerId.length() + 1));
+ }
+
+ /**
+ * Returns whether the session info is valid or not
+ */
+ public boolean isValid() {
+ return !TextUtils.isEmpty(mPackageName)
+ && !TextUtils.isEmpty(mControlCategory)
+ && mSelectedRoutes.size() > 0;
+ }
+
+ /**
+ * Gets the id of the session
+ */
+ @NonNull
+ public int getSessionId() {
+ return mSessionId;
+ }
+
+ /**
+ * Gets the client package name of the session
+ */
+ @NonNull
+ public String getPackageName() {
+ return mPackageName;
+ }
+
+ /**
+ * Gets the control category of the session.
+ * Routes that don't support the category can't be added to the session.
+ */
+ @NonNull
+ public String getControlCategory() {
+ return mControlCategory;
+ }
+
+ /**
+ * Gets the provider id of the session.
+ * @hide
+ */
+ @Nullable
+ public String getProviderId() {
+ return mProviderId;
+ }
+
+ /**
+ * Gets the unique id of the session.
+ * @hide
+ */
+ @NonNull
+ public String getUniqueSessionId() {
+ StringBuilder sessionIdBuilder = new StringBuilder()
+ .append(mProviderId)
+ .append("/")
+ .append(mSessionId);
+ return sessionIdBuilder.toString();
+ }
+
+ /**
+ * Gets the list of ids of selected routes for the session. It shouldn't be empty.
+ */
+ @NonNull
+ public List<String> getSelectedRoutes() {
+ return mSelectedRoutes;
+ }
+
+ /**
+ * Gets the list of ids of selectable routes for the session.
+ */
+ @NonNull
+ public List<String> getSelectableRoutes() {
+ return mSelectableRoutes;
+ }
+
+ /**
+ * Gets the list of ids of deselectable routes for the session.
+ */
+ @NonNull
+ public List<String> getDeselectableRoutes() {
+ return mDeselectableRoutes;
+ }
+
+ /**
+ * Gets the list of ids of transferrable routes for the session.
+ */
+ @NonNull
+ public List<String> getTransferrableRoutes() {
+ return mTransferrableRoutes;
+ }
+
+ /**
+ * Gets the control hints
+ */
+ @Nullable
+ public Bundle getControlHints() {
+ return mControlHints;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mSessionId);
+ dest.writeString(mPackageName);
+ dest.writeString(mControlCategory);
+ dest.writeString(mProviderId);
+ dest.writeStringList(mSelectedRoutes);
+ dest.writeStringList(mSelectableRoutes);
+ dest.writeStringList(mDeselectableRoutes);
+ dest.writeStringList(mTransferrableRoutes);
+ dest.writeBundle(mControlHints);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder result = new StringBuilder()
+ .append("RouteSessionInfo{ ")
+ .append("sessionId=").append(mSessionId)
+ .append(", controlCategory=").append(mControlCategory)
+ .append(", selectedRoutes={")
+ .append(String.join(",", mSelectedRoutes))
+ .append("}")
+ .append(", selectableRoutes={")
+ .append(String.join(",", mSelectableRoutes))
+ .append("}")
+ .append(", deselectableRoutes={")
+ .append(String.join(",", mDeselectableRoutes))
+ .append("}")
+ .append(", transferrableRoutes={")
+ .append(String.join(",", mTransferrableRoutes))
+ .append("}")
+ .append(" }");
+ return result.toString();
+ }
+
+ /**
+ * Builder class for {@link RouteSessionInfo}.
+ */
+ public static final class Builder {
+ final String mPackageName;
+ final int mSessionId;
+ final String mControlCategory;
+ String mProviderId;
+ final List<String> mSelectedRoutes;
+ final List<String> mSelectableRoutes;
+ final List<String> mDeselectableRoutes;
+ final List<String> mTransferrableRoutes;
+ Bundle mControlHints;
+
+ public Builder(int sessionId, @NonNull String packageName,
+ @NonNull String controlCategory) {
+ mSessionId = sessionId;
+ mPackageName = Objects.requireNonNull(packageName, "packageName must not be null");
+ mControlCategory = Objects.requireNonNull(controlCategory,
+ "controlCategory must not be null");
+
+ mSelectedRoutes = new ArrayList<>();
+ mSelectableRoutes = new ArrayList<>();
+ mDeselectableRoutes = new ArrayList<>();
+ mTransferrableRoutes = new ArrayList<>();
+ }
+
+ public Builder(RouteSessionInfo sessionInfo) {
+ mSessionId = sessionInfo.mSessionId;
+ mPackageName = sessionInfo.mPackageName;
+ mControlCategory = sessionInfo.mControlCategory;
+ mProviderId = sessionInfo.mProviderId;
+
+ mSelectedRoutes = new ArrayList<>(sessionInfo.mSelectedRoutes);
+ mSelectableRoutes = new ArrayList<>(sessionInfo.mSelectableRoutes);
+ mDeselectableRoutes = new ArrayList<>(sessionInfo.mDeselectableRoutes);
+ mTransferrableRoutes = new ArrayList<>(sessionInfo.mTransferrableRoutes);
+
+ mControlHints = sessionInfo.mControlHints;
+ }
+
+ /**
+ * Sets the provider id of the session.
+ */
+ @NonNull
+ public Builder setProviderId(String providerId) {
+ mProviderId = providerId;
+ return this;
+ }
+
+ /**
+ * Clears the selected routes.
+ */
+ @NonNull
+ public Builder clearSelectedRoutes() {
+ mSelectedRoutes.clear();
+ return this;
+ }
+
+ /**
+ * Adds a route to the selected routes.
+ */
+ @NonNull
+ public Builder addSelectedRoute(@NonNull String routeId) {
+ mSelectedRoutes.add(Objects.requireNonNull(routeId, "routeId must not be null"));
+ return this;
+ }
+
+ /**
+ * Removes a route from the selected routes.
+ */
+ @NonNull
+ public Builder removeSelectedRoute(@NonNull String routeId) {
+ mSelectedRoutes.remove(Objects.requireNonNull(routeId, "routeId must not be null"));
+ return this;
+ }
+
+ /**
+ * Clears the selectable routes.
+ */
+ @NonNull
+ public Builder clearSelectableRoutes() {
+ mSelectableRoutes.clear();
+ return this;
+ }
+
+ /**
+ * Adds a route to the selectable routes.
+ */
+ @NonNull
+ public Builder addSelectableRoute(@NonNull String routeId) {
+ mSelectableRoutes.add(Objects.requireNonNull(routeId, "routeId must not be null"));
+ return this;
+ }
+
+ /**
+ * Removes a route from the selectable routes.
+ */
+ @NonNull
+ public Builder removeSelectableRoute(@NonNull String routeId) {
+ mSelectableRoutes.remove(Objects.requireNonNull(routeId, "routeId must not be null"));
+ return this;
+ }
+
+ /**
+ * Clears the deselectable routes.
+ */
+ @NonNull
+ public Builder clearDeselectableRoutes() {
+ mDeselectableRoutes.clear();
+ return this;
+ }
+
+ /**
+ * Adds a route to the deselectable routes.
+ */
+ @NonNull
+ public Builder addDeselectableRoute(@NonNull String routeId) {
+ mDeselectableRoutes.add(Objects.requireNonNull(routeId, "routeId must not be null"));
+ return this;
+ }
+
+ /**
+ * Removes a route from the deselectable routes.
+ */
+ @NonNull
+ public Builder removeDeselectableRoute(@NonNull String routeId) {
+ mDeselectableRoutes.remove(Objects.requireNonNull(routeId, "routeId must not be null"));
+ return this;
+ }
+
+ /**
+ * Clears the transferrable routes.
+ */
+ @NonNull
+ public Builder clearTransferrableRoutes() {
+ mTransferrableRoutes.clear();
+ return this;
+ }
+
+ /**
+ * Adds a route to the transferrable routes.
+ */
+ @NonNull
+ public Builder addTransferrableRoute(@NonNull String routeId) {
+ mTransferrableRoutes.add(Objects.requireNonNull(routeId, "routeId must not be null"));
+ return this;
+ }
+
+ /**
+ * Removes a route from the transferrable routes.
+ */
+ @NonNull
+ public Builder removeTransferrableRoute(@NonNull String routeId) {
+ mTransferrableRoutes.remove(
+ Objects.requireNonNull(routeId, "routeId must not be null"));
+ return this;
+ }
+
+ /**
+ * Sets control hints.
+ */
+ @NonNull
+ public Builder setControlHints(@Nullable Bundle controlHints) {
+ mControlHints = controlHints;
+ return this;
+ }
+
+ /**
+ * Builds a route session info.
+ */
+ @NonNull
+ public RouteSessionInfo build() {
+ return new RouteSessionInfo(this);
+ }
+ }
+}
diff --git a/media/java/android/media/SubtitleController.java b/media/java/android/media/SubtitleController.java
index 1a241af7345d..48657a6c810f 100644
--- a/media/java/android/media/SubtitleController.java
+++ b/media/java/android/media/SubtitleController.java
@@ -16,10 +16,7 @@
package android.media;
-import java.util.Locale;
-import java.util.Vector;
-
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.media.MediaPlayer.TrackInfo;
import android.media.SubtitleTrack.RenderingWidget;
@@ -28,6 +25,9 @@ import android.os.Looper;
import android.os.Message;
import android.view.accessibility.CaptioningManager;
+import java.util.Locale;
+import java.util.Vector;
+
/**
* The subtitle controller provides the architecture to display subtitles for a
* media source. It allows specifying which tracks to display, on which anchor
diff --git a/media/java/android/media/SubtitleTrack.java b/media/java/android/media/SubtitleTrack.java
index 0705d97a9edf..10669f466fe5 100644
--- a/media/java/android/media/SubtitleTrack.java
+++ b/media/java/android/media/SubtitleTrack.java
@@ -16,7 +16,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Canvas;
import android.media.MediaPlayer.TrackInfo;
import android.os.Handler;
diff --git a/media/java/android/media/ThumbnailUtils.java b/media/java/android/media/ThumbnailUtils.java
index 6705b0cb79f0..1f7b5ad51d9c 100644
--- a/media/java/android/media/ThumbnailUtils.java
+++ b/media/java/android/media/ThumbnailUtils.java
@@ -24,7 +24,7 @@ import static android.os.Environment.MEDIA_UNKNOWN;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
diff --git a/media/java/android/media/TimedText.java b/media/java/android/media/TimedText.java
index d8cdf9c12e09..120642a8e7cb 100644
--- a/media/java/android/media/TimedText.java
+++ b/media/java/android/media/TimedText.java
@@ -16,14 +16,15 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Rect;
import android.os.Parcel;
import android.util.Log;
+
+import java.util.ArrayList;
import java.util.HashMap;
-import java.util.Set;
import java.util.List;
-import java.util.ArrayList;
+import java.util.Set;
/**
* Class to hold the timed text's metadata, including:
diff --git a/media/java/android/media/ToneGenerator.java b/media/java/android/media/ToneGenerator.java
index c6d5ba3f9953..cc114a9092e1 100644
--- a/media/java/android/media/ToneGenerator.java
+++ b/media/java/android/media/ToneGenerator.java
@@ -16,7 +16,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
diff --git a/media/java/android/media/TtmlRenderer.java b/media/java/android/media/TtmlRenderer.java
index 34154ce93a8c..e5782642f4eb 100644
--- a/media/java/android/media/TtmlRenderer.java
+++ b/media/java/android/media/TtmlRenderer.java
@@ -16,7 +16,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.text.TextUtils;
import android.util.AttributeSet;
@@ -27,6 +27,10 @@ import android.view.accessibility.CaptioningManager;
import android.widget.LinearLayout;
import android.widget.TextView;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParserFactory;
+
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
@@ -37,10 +41,6 @@ import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlPullParserFactory;
-
/** @hide */
public class TtmlRenderer extends SubtitleController.Renderer {
private final Context mContext;
diff --git a/media/java/android/media/VolumeShaper.java b/media/java/android/media/VolumeShaper.java
index 663d564af23e..99dfe1e8e32f 100644
--- a/media/java/android/media/VolumeShaper.java
+++ b/media/java/android/media/VolumeShaper.java
@@ -19,13 +19,12 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.lang.AutoCloseable;
import java.lang.ref.WeakReference;
import java.util.Arrays;
import java.util.Objects;
diff --git a/media/java/android/media/WebVttRenderer.java b/media/java/android/media/WebVttRenderer.java
index 36458d7e1746..bc1429499e70 100644
--- a/media/java/android/media/WebVttRenderer.java
+++ b/media/java/android/media/WebVttRenderer.java
@@ -16,7 +16,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.text.Layout.Alignment;
import android.text.SpannableStringBuilder;
diff --git a/media/java/android/media/audiofx/AudioEffect.java b/media/java/android/media/audiofx/AudioEffect.java
index 5b4bbce91784..4a40c627ecb0 100644
--- a/media/java/android/media/audiofx/AudioEffect.java
+++ b/media/java/android/media/audiofx/AudioEffect.java
@@ -19,8 +19,8 @@ package android.media.audiofx;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
diff --git a/media/java/android/media/audiofx/Visualizer.java b/media/java/android/media/audiofx/Visualizer.java
index 89a509f64a1b..392e8fe7543f 100644
--- a/media/java/android/media/audiofx/Visualizer.java
+++ b/media/java/android/media/audiofx/Visualizer.java
@@ -16,8 +16,8 @@
package android.media.audiofx;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
diff --git a/media/java/android/media/audiopolicy/AudioMix.java b/media/java/android/media/audiopolicy/AudioMix.java
index a82c78fad271..dd9877a9c706 100644
--- a/media/java/android/media/audiopolicy/AudioMix.java
+++ b/media/java/android/media/audiopolicy/AudioMix.java
@@ -20,7 +20,7 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.media.AudioDeviceInfo;
import android.media.AudioFormat;
import android.media.AudioSystem;
diff --git a/media/java/android/media/audiopolicy/AudioMixingRule.java b/media/java/android/media/audiopolicy/AudioMixingRule.java
index c4afd95be9ac..8c204d222cd4 100644
--- a/media/java/android/media/audiopolicy/AudioMixingRule.java
+++ b/media/java/android/media/audiopolicy/AudioMixingRule.java
@@ -19,7 +19,7 @@ package android.media.audiopolicy;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.media.AudioAttributes;
import android.os.Parcel;
import android.util.Log;
diff --git a/media/java/android/media/session/ISessionCallback.aidl b/media/java/android/media/session/ISessionCallback.aidl
index a294088dd751..30db8f0c81c2 100644
--- a/media/java/android/media/session/ISessionCallback.aidl
+++ b/media/java/android/media/session/ISessionCallback.aidl
@@ -17,7 +17,6 @@ package android.media.session;
import android.content.Intent;
import android.media.Rating;
-import android.media.session.ISessionControllerCallback;
import android.net.Uri;
import android.os.Bundle;
import android.os.ResultReceiver;
@@ -26,48 +25,36 @@ import android.os.ResultReceiver;
* @hide
*/
oneway interface ISessionCallback {
- void onCommand(String packageName, int pid, int uid, ISessionControllerCallback caller,
- String command, in Bundle args, in ResultReceiver cb);
+ void onCommand(String packageName, int pid, int uid, String command, in Bundle args,
+ in ResultReceiver cb);
void onMediaButton(String packageName, int pid, int uid, in Intent mediaButtonIntent,
int sequenceNumber, in ResultReceiver cb);
void onMediaButtonFromController(String packageName, int pid, int uid,
- ISessionControllerCallback caller, in Intent mediaButtonIntent);
+ in Intent mediaButtonIntent);
// These callbacks are for the TransportControls
- void onPrepare(String packageName, int pid, int uid, ISessionControllerCallback caller);
- void onPrepareFromMediaId(String packageName, int pid, int uid,
- ISessionControllerCallback caller, String mediaId, in Bundle extras);
- void onPrepareFromSearch(String packageName, int pid, int uid,
- ISessionControllerCallback caller, String query, in Bundle extras);
- void onPrepareFromUri(String packageName, int pid, int uid,
- ISessionControllerCallback caller, in Uri uri, in Bundle extras);
- void onPlay(String packageName, int pid, int uid, ISessionControllerCallback caller);
- void onPlayFromMediaId(String packageName, int pid, int uid,
- ISessionControllerCallback caller, String mediaId, in Bundle extras);
- void onPlayFromSearch(String packageName, int pid, int uid,
- ISessionControllerCallback caller, String query, in Bundle extras);
- void onPlayFromUri(String packageName, int pid, int uid, ISessionControllerCallback caller,
- in Uri uri, in Bundle extras);
- void onSkipToTrack(String packageName, int pid, int uid, ISessionControllerCallback caller,
- long id);
- void onPause(String packageName, int pid, int uid, ISessionControllerCallback caller);
- void onStop(String packageName, int pid, int uid, ISessionControllerCallback caller);
- void onNext(String packageName, int pid, int uid, ISessionControllerCallback caller);
- void onPrevious(String packageName, int pid, int uid, ISessionControllerCallback caller);
- void onFastForward(String packageName, int pid, int uid, ISessionControllerCallback caller);
- void onRewind(String packageName, int pid, int uid, ISessionControllerCallback caller);
- void onSeekTo(String packageName, int pid, int uid, ISessionControllerCallback caller,
- long pos);
- void onRate(String packageName, int pid, int uid, ISessionControllerCallback caller,
- in Rating rating);
- void onSetPlaybackSpeed(String packageName, int pid, int uid,
- ISessionControllerCallback caller, float speed);
- void onCustomAction(String packageName, int pid, int uid, ISessionControllerCallback caller,
- String action, in Bundle args);
+ void onPrepare(String packageName, int pid, int uid);
+ void onPrepareFromMediaId(String packageName, int pid, int uid, String mediaId,
+ in Bundle extras);
+ void onPrepareFromSearch(String packageName, int pid, int uid, String query, in Bundle extras);
+ void onPrepareFromUri(String packageName, int pid, int uid, in Uri uri, in Bundle extras);
+ void onPlay(String packageName, int pid, int uid);
+ void onPlayFromMediaId(String packageName, int pid, int uid, String mediaId, in Bundle extras);
+ void onPlayFromSearch(String packageName, int pid, int uid, String query, in Bundle extras);
+ void onPlayFromUri(String packageName, int pid, int uid, in Uri uri, in Bundle extras);
+ void onSkipToTrack(String packageName, int pid, int uid, long id);
+ void onPause(String packageName, int pid, int uid);
+ void onStop(String packageName, int pid, int uid);
+ void onNext(String packageName, int pid, int uid);
+ void onPrevious(String packageName, int pid, int uid);
+ void onFastForward(String packageName, int pid, int uid);
+ void onRewind(String packageName, int pid, int uid);
+ void onSeekTo(String packageName, int pid, int uid, long pos);
+ void onRate(String packageName, int pid, int uid, in Rating rating);
+ void onSetPlaybackSpeed(String packageName, int pid, int uid, float speed);
+ void onCustomAction(String packageName, int pid, int uid, String action, in Bundle args);
// These callbacks are for volume handling
- void onAdjustVolume(String packageName, int pid, int uid, ISessionControllerCallback caller,
- int direction);
- void onSetVolumeTo(String packageName, int pid, int uid,
- ISessionControllerCallback caller, int value);
+ void onAdjustVolume(String packageName, int pid, int uid, int direction);
+ void onSetVolumeTo(String packageName, int pid, int uid, int value);
}
diff --git a/media/java/android/media/session/ISessionController.aidl b/media/java/android/media/session/ISessionController.aidl
index e1039fd26940..183c7c38a76e 100644
--- a/media/java/android/media/session/ISessionController.aidl
+++ b/media/java/android/media/session/ISessionController.aidl
@@ -36,10 +36,8 @@ import java.util.List;
* @hide
*/
interface ISessionController {
- void sendCommand(String packageName, in ISessionControllerCallback caller,
- String command, in Bundle args, in ResultReceiver cb);
- boolean sendMediaButton(String packageName, in ISessionControllerCallback caller,
- in KeyEvent mediaButton);
+ void sendCommand(String packageName, String command, in Bundle args, in ResultReceiver cb);
+ boolean sendMediaButton(String packageName, in KeyEvent mediaButton);
void registerCallback(String packageName, in ISessionControllerCallback cb);
void unregisterCallback(in ISessionControllerCallback cb);
String getPackageName();
@@ -48,38 +46,29 @@ interface ISessionController {
PendingIntent getLaunchPendingIntent();
long getFlags();
MediaController.PlaybackInfo getVolumeAttributes();
- void adjustVolume(String packageName, String opPackageName,
- in ISessionControllerCallback caller, int direction, int flags);
- void setVolumeTo(String packageName, String opPackageName, in ISessionControllerCallback caller,
- int value, int flags);
+ void adjustVolume(String packageName, String opPackageName, int direction, int flags);
+ void setVolumeTo(String packageName, String opPackageName, int value, int flags);
// These commands are for the TransportControls
- void prepare(String packageName, in ISessionControllerCallback caller);
- void prepareFromMediaId(String packageName, in ISessionControllerCallback caller,
- String mediaId, in Bundle extras);
- void prepareFromSearch(String packageName, in ISessionControllerCallback caller,
- String string, in Bundle extras);
- void prepareFromUri(String packageName, in ISessionControllerCallback caller,
- in Uri uri, in Bundle extras);
- void play(String packageName, in ISessionControllerCallback caller);
- void playFromMediaId(String packageName, in ISessionControllerCallback caller,
- String mediaId, in Bundle extras);
- void playFromSearch(String packageName, in ISessionControllerCallback caller,
- String string, in Bundle extras);
- void playFromUri(String packageName, in ISessionControllerCallback caller,
- in Uri uri, in Bundle extras);
- void skipToQueueItem(String packageName, in ISessionControllerCallback caller, long id);
- void pause(String packageName, in ISessionControllerCallback caller);
- void stop(String packageName, in ISessionControllerCallback caller);
- void next(String packageName, in ISessionControllerCallback caller);
- void previous(String packageName, in ISessionControllerCallback caller);
- void fastForward(String packageName, in ISessionControllerCallback caller);
- void rewind(String packageName, in ISessionControllerCallback caller);
- void seekTo(String packageName, in ISessionControllerCallback caller, long pos);
- void rate(String packageName, in ISessionControllerCallback caller, in Rating rating);
- void setPlaybackSpeed(String packageName, in ISessionControllerCallback caller, float speed);
- void sendCustomAction(String packageName, in ISessionControllerCallback caller,
- String action, in Bundle args);
+ void prepare(String packageName);
+ void prepareFromMediaId(String packageName, String mediaId, in Bundle extras);
+ void prepareFromSearch(String packageName, String string, in Bundle extras);
+ void prepareFromUri(String packageName, in Uri uri, in Bundle extras);
+ void play(String packageName);
+ void playFromMediaId(String packageName, String mediaId, in Bundle extras);
+ void playFromSearch(String packageName, String string, in Bundle extras);
+ void playFromUri(String packageName, in Uri uri, in Bundle extras);
+ void skipToQueueItem(String packageName, long id);
+ void pause(String packageName);
+ void stop(String packageName);
+ void next(String packageName);
+ void previous(String packageName);
+ void fastForward(String packageName);
+ void rewind(String packageName);
+ void seekTo(String packageName, long pos);
+ void rate(String packageName, in Rating rating);
+ void setPlaybackSpeed(String packageName, float speed);
+ void sendCustomAction(String packageName, String action, in Bundle args);
MediaMetadata getMetadata();
PlaybackState getPlaybackState();
ParceledListSlice getQueue();
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index 1fc4f7d59ca5..1812d9ce0739 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -18,8 +18,8 @@ package android.media.session;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.app.PendingIntent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.ParceledListSlice;
import android.media.AudioAttributes;
@@ -131,7 +131,7 @@ public final class MediaController {
return false;
}
try {
- return mSessionBinder.sendMediaButton(mContext.getPackageName(), mCbStub, keyEvent);
+ return mSessionBinder.sendMediaButton(mContext.getPackageName(), keyEvent);
} catch (RemoteException e) {
// System is dead. =(
}
@@ -298,7 +298,7 @@ public final class MediaController {
// RemoteUserInfo, and OP package name is used for AudioService's internal
// AppOpsManager usages.
mSessionBinder.setVolumeTo(mContext.getPackageName(), mContext.getOpPackageName(),
- mCbStub, value, flags);
+ value, flags);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling setVolumeTo.", e);
}
@@ -323,7 +323,7 @@ public final class MediaController {
// RemoteUserInfo, and OP package name is used for AudioService's internal
// AppOpsManager usages.
mSessionBinder.adjustVolume(mContext.getPackageName(), mContext.getOpPackageName(),
- mCbStub, direction, flags);
+ direction, flags);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling adjustVolumeBy.", e);
}
@@ -389,7 +389,7 @@ public final class MediaController {
throw new IllegalArgumentException("command cannot be null or empty");
}
try {
- mSessionBinder.sendCommand(mContext.getPackageName(), mCbStub, command, args, cb);
+ mSessionBinder.sendCommand(mContext.getPackageName(), command, args, cb);
} catch (RemoteException e) {
Log.d(TAG, "Dead object in sendCommand.", e);
}
@@ -443,8 +443,8 @@ public final class MediaController {
* Get the session's tag for debugging purposes.
*
* @return The session's tag.
- * @hide
*/
+ @NonNull
public String getTag() {
if (mTag == null) {
try {
@@ -630,7 +630,7 @@ public final class MediaController {
*/
public void prepare() {
try {
- mSessionBinder.prepare(mContext.getPackageName(), mCbStub);
+ mSessionBinder.prepare(mContext.getPackageName());
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling prepare.", e);
}
@@ -654,8 +654,7 @@ public final class MediaController {
"You must specify a non-empty String for prepareFromMediaId.");
}
try {
- mSessionBinder.prepareFromMediaId(mContext.getPackageName(), mCbStub, mediaId,
- extras);
+ mSessionBinder.prepareFromMediaId(mContext.getPackageName(), mediaId, extras);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling prepare(" + mediaId + ").", e);
}
@@ -681,8 +680,7 @@ public final class MediaController {
query = "";
}
try {
- mSessionBinder.prepareFromSearch(mContext.getPackageName(), mCbStub, query,
- extras);
+ mSessionBinder.prepareFromSearch(mContext.getPackageName(), query, extras);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling prepare(" + query + ").", e);
}
@@ -706,7 +704,7 @@ public final class MediaController {
"You must specify a non-empty Uri for prepareFromUri.");
}
try {
- mSessionBinder.prepareFromUri(mContext.getPackageName(), mCbStub, uri, extras);
+ mSessionBinder.prepareFromUri(mContext.getPackageName(), uri, extras);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling prepare(" + uri + ").", e);
}
@@ -717,7 +715,7 @@ public final class MediaController {
*/
public void play() {
try {
- mSessionBinder.play(mContext.getPackageName(), mCbStub);
+ mSessionBinder.play(mContext.getPackageName());
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling play.", e);
}
@@ -736,8 +734,7 @@ public final class MediaController {
"You must specify a non-empty String for playFromMediaId.");
}
try {
- mSessionBinder.playFromMediaId(mContext.getPackageName(), mCbStub, mediaId,
- extras);
+ mSessionBinder.playFromMediaId(mContext.getPackageName(), mediaId, extras);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling play(" + mediaId + ").", e);
}
@@ -759,7 +756,7 @@ public final class MediaController {
query = "";
}
try {
- mSessionBinder.playFromSearch(mContext.getPackageName(), mCbStub, query, extras);
+ mSessionBinder.playFromSearch(mContext.getPackageName(), query, extras);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling play(" + query + ").", e);
}
@@ -778,7 +775,7 @@ public final class MediaController {
"You must specify a non-empty Uri for playFromUri.");
}
try {
- mSessionBinder.playFromUri(mContext.getPackageName(), mCbStub, uri, extras);
+ mSessionBinder.playFromUri(mContext.getPackageName(), uri, extras);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling play(" + uri + ").", e);
}
@@ -790,7 +787,7 @@ public final class MediaController {
*/
public void skipToQueueItem(long id) {
try {
- mSessionBinder.skipToQueueItem(mContext.getPackageName(), mCbStub, id);
+ mSessionBinder.skipToQueueItem(mContext.getPackageName(), id);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling skipToItem(" + id + ").", e);
}
@@ -802,7 +799,7 @@ public final class MediaController {
*/
public void pause() {
try {
- mSessionBinder.pause(mContext.getPackageName(), mCbStub);
+ mSessionBinder.pause(mContext.getPackageName());
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling pause.", e);
}
@@ -814,7 +811,7 @@ public final class MediaController {
*/
public void stop() {
try {
- mSessionBinder.stop(mContext.getPackageName(), mCbStub);
+ mSessionBinder.stop(mContext.getPackageName());
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling stop.", e);
}
@@ -827,7 +824,7 @@ public final class MediaController {
*/
public void seekTo(long pos) {
try {
- mSessionBinder.seekTo(mContext.getPackageName(), mCbStub, pos);
+ mSessionBinder.seekTo(mContext.getPackageName(), pos);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling seekTo.", e);
}
@@ -839,7 +836,7 @@ public final class MediaController {
*/
public void fastForward() {
try {
- mSessionBinder.fastForward(mContext.getPackageName(), mCbStub);
+ mSessionBinder.fastForward(mContext.getPackageName());
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling fastForward.", e);
}
@@ -850,7 +847,7 @@ public final class MediaController {
*/
public void skipToNext() {
try {
- mSessionBinder.next(mContext.getPackageName(), mCbStub);
+ mSessionBinder.next(mContext.getPackageName());
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling next.", e);
}
@@ -862,7 +859,7 @@ public final class MediaController {
*/
public void rewind() {
try {
- mSessionBinder.rewind(mContext.getPackageName(), mCbStub);
+ mSessionBinder.rewind(mContext.getPackageName());
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling rewind.", e);
}
@@ -873,7 +870,7 @@ public final class MediaController {
*/
public void skipToPrevious() {
try {
- mSessionBinder.previous(mContext.getPackageName(), mCbStub);
+ mSessionBinder.previous(mContext.getPackageName());
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling previous.", e);
}
@@ -888,7 +885,7 @@ public final class MediaController {
*/
public void setRating(Rating rating) {
try {
- mSessionBinder.rate(mContext.getPackageName(), mCbStub, rating);
+ mSessionBinder.rate(mContext.getPackageName(), rating);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling rate.", e);
}
@@ -906,7 +903,7 @@ public final class MediaController {
throw new IllegalArgumentException("speed must not be zero");
}
try {
- mSessionBinder.setPlaybackSpeed(mContext.getPackageName(), mCbStub, speed);
+ mSessionBinder.setPlaybackSpeed(mContext.getPackageName(), speed);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling setPlaybackSpeed.", e);
}
@@ -941,7 +938,7 @@ public final class MediaController {
throw new IllegalArgumentException("CustomAction cannot be null.");
}
try {
- mSessionBinder.sendCustomAction(mContext.getPackageName(), mCbStub, action, args);
+ mSessionBinder.sendCustomAction(mContext.getPackageName(), action, args);
} catch (RemoteException e) {
Log.d(TAG, "Dead object in sendCustomAction.", e);
}
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index e11715ff7299..3adee590c125 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -19,9 +19,9 @@ package android.media.session;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.app.Activity;
import android.app.PendingIntent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ParceledListSlice;
@@ -1159,8 +1159,8 @@ public final class MediaSession {
}
@Override
- public void onCommand(String packageName, int pid, int uid,
- ISessionControllerCallback caller, String command, Bundle args, ResultReceiver cb) {
+ public void onCommand(String packageName, int pid, int uid, String command, Bundle args,
+ ResultReceiver cb) {
MediaSession session = mMediaSession.get();
if (session != null) {
session.dispatchCommand(createRemoteUserInfo(packageName, pid, uid),
@@ -1186,7 +1186,7 @@ public final class MediaSession {
@Override
public void onMediaButtonFromController(String packageName, int pid, int uid,
- ISessionControllerCallback caller, Intent mediaButtonIntent) {
+ Intent mediaButtonIntent) {
MediaSession session = mMediaSession.get();
if (session != null) {
session.dispatchMediaButton(createRemoteUserInfo(packageName, pid, uid),
@@ -1195,8 +1195,7 @@ public final class MediaSession {
}
@Override
- public void onPrepare(String packageName, int pid, int uid,
- ISessionControllerCallback caller) {
+ public void onPrepare(String packageName, int pid, int uid) {
MediaSession session = mMediaSession.get();
if (session != null) {
session.dispatchPrepare(createRemoteUserInfo(packageName, pid, uid));
@@ -1204,8 +1203,7 @@ public final class MediaSession {
}
@Override
- public void onPrepareFromMediaId(String packageName, int pid, int uid,
- ISessionControllerCallback caller, String mediaId,
+ public void onPrepareFromMediaId(String packageName, int pid, int uid, String mediaId,
Bundle extras) {
MediaSession session = mMediaSession.get();
if (session != null) {
@@ -1215,8 +1213,7 @@ public final class MediaSession {
}
@Override
- public void onPrepareFromSearch(String packageName, int pid, int uid,
- ISessionControllerCallback caller, String query,
+ public void onPrepareFromSearch(String packageName, int pid, int uid, String query,
Bundle extras) {
MediaSession session = mMediaSession.get();
if (session != null) {
@@ -1226,8 +1223,7 @@ public final class MediaSession {
}
@Override
- public void onPrepareFromUri(String packageName, int pid, int uid,
- ISessionControllerCallback caller, Uri uri, Bundle extras) {
+ public void onPrepareFromUri(String packageName, int pid, int uid, Uri uri, Bundle extras) {
MediaSession session = mMediaSession.get();
if (session != null) {
session.dispatchPrepareFromUri(createRemoteUserInfo(packageName, pid, uid),
@@ -1236,8 +1232,7 @@ public final class MediaSession {
}
@Override
- public void onPlay(String packageName, int pid, int uid,
- ISessionControllerCallback caller) {
+ public void onPlay(String packageName, int pid, int uid) {
MediaSession session = mMediaSession.get();
if (session != null) {
session.dispatchPlay(createRemoteUserInfo(packageName, pid, uid));
@@ -1245,8 +1240,7 @@ public final class MediaSession {
}
@Override
- public void onPlayFromMediaId(String packageName, int pid, int uid,
- ISessionControllerCallback caller, String mediaId,
+ public void onPlayFromMediaId(String packageName, int pid, int uid, String mediaId,
Bundle extras) {
MediaSession session = mMediaSession.get();
if (session != null) {
@@ -1256,8 +1250,7 @@ public final class MediaSession {
}
@Override
- public void onPlayFromSearch(String packageName, int pid, int uid,
- ISessionControllerCallback caller, String query,
+ public void onPlayFromSearch(String packageName, int pid, int uid, String query,
Bundle extras) {
MediaSession session = mMediaSession.get();
if (session != null) {
@@ -1267,8 +1260,7 @@ public final class MediaSession {
}
@Override
- public void onPlayFromUri(String packageName, int pid, int uid,
- ISessionControllerCallback caller, Uri uri, Bundle extras) {
+ public void onPlayFromUri(String packageName, int pid, int uid, Uri uri, Bundle extras) {
MediaSession session = mMediaSession.get();
if (session != null) {
session.dispatchPlayFromUri(createRemoteUserInfo(packageName, pid, uid),
@@ -1277,8 +1269,7 @@ public final class MediaSession {
}
@Override
- public void onSkipToTrack(String packageName, int pid, int uid,
- ISessionControllerCallback caller, long id) {
+ public void onSkipToTrack(String packageName, int pid, int uid, long id) {
MediaSession session = mMediaSession.get();
if (session != null) {
session.dispatchSkipToItem(createRemoteUserInfo(packageName, pid, uid), id);
@@ -1286,8 +1277,7 @@ public final class MediaSession {
}
@Override
- public void onPause(String packageName, int pid, int uid,
- ISessionControllerCallback caller) {
+ public void onPause(String packageName, int pid, int uid) {
MediaSession session = mMediaSession.get();
if (session != null) {
session.dispatchPause(createRemoteUserInfo(packageName, pid, uid));
@@ -1295,8 +1285,7 @@ public final class MediaSession {
}
@Override
- public void onStop(String packageName, int pid, int uid,
- ISessionControllerCallback caller) {
+ public void onStop(String packageName, int pid, int uid) {
MediaSession session = mMediaSession.get();
if (session != null) {
session.dispatchStop(createRemoteUserInfo(packageName, pid, uid));
@@ -1304,8 +1293,7 @@ public final class MediaSession {
}
@Override
- public void onNext(String packageName, int pid, int uid,
- ISessionControllerCallback caller) {
+ public void onNext(String packageName, int pid, int uid) {
MediaSession session = mMediaSession.get();
if (session != null) {
session.dispatchNext(createRemoteUserInfo(packageName, pid, uid));
@@ -1313,8 +1301,7 @@ public final class MediaSession {
}
@Override
- public void onPrevious(String packageName, int pid, int uid,
- ISessionControllerCallback caller) {
+ public void onPrevious(String packageName, int pid, int uid) {
MediaSession session = mMediaSession.get();
if (session != null) {
session.dispatchPrevious(createRemoteUserInfo(packageName, pid, uid));
@@ -1322,8 +1309,7 @@ public final class MediaSession {
}
@Override
- public void onFastForward(String packageName, int pid, int uid,
- ISessionControllerCallback caller) {
+ public void onFastForward(String packageName, int pid, int uid) {
MediaSession session = mMediaSession.get();
if (session != null) {
session.dispatchFastForward(createRemoteUserInfo(packageName, pid, uid));
@@ -1331,8 +1317,7 @@ public final class MediaSession {
}
@Override
- public void onRewind(String packageName, int pid, int uid,
- ISessionControllerCallback caller) {
+ public void onRewind(String packageName, int pid, int uid) {
MediaSession session = mMediaSession.get();
if (session != null) {
session.dispatchRewind(createRemoteUserInfo(packageName, pid, uid));
@@ -1340,8 +1325,7 @@ public final class MediaSession {
}
@Override
- public void onSeekTo(String packageName, int pid, int uid,
- ISessionControllerCallback caller, long pos) {
+ public void onSeekTo(String packageName, int pid, int uid, long pos) {
MediaSession session = mMediaSession.get();
if (session != null) {
session.dispatchSeekTo(createRemoteUserInfo(packageName, pid, uid), pos);
@@ -1349,8 +1333,7 @@ public final class MediaSession {
}
@Override
- public void onRate(String packageName, int pid, int uid, ISessionControllerCallback caller,
- Rating rating) {
+ public void onRate(String packageName, int pid, int uid, Rating rating) {
MediaSession session = mMediaSession.get();
if (session != null) {
session.dispatchRate(createRemoteUserInfo(packageName, pid, uid), rating);
@@ -1358,8 +1341,7 @@ public final class MediaSession {
}
@Override
- public void onSetPlaybackSpeed(String packageName, int pid, int uid,
- ISessionControllerCallback caller, float speed) {
+ public void onSetPlaybackSpeed(String packageName, int pid, int uid, float speed) {
MediaSession session = mMediaSession.get();
if (session != null) {
session.dispatchSetPlaybackSpeed(
@@ -1368,8 +1350,8 @@ public final class MediaSession {
}
@Override
- public void onCustomAction(String packageName, int pid, int uid,
- ISessionControllerCallback caller, String action, Bundle args) {
+ public void onCustomAction(String packageName, int pid, int uid, String action,
+ Bundle args) {
MediaSession session = mMediaSession.get();
if (session != null) {
session.dispatchCustomAction(createRemoteUserInfo(packageName, pid, uid),
@@ -1378,8 +1360,7 @@ public final class MediaSession {
}
@Override
- public void onAdjustVolume(String packageName, int pid, int uid,
- ISessionControllerCallback caller, int direction) {
+ public void onAdjustVolume(String packageName, int pid, int uid, int direction) {
MediaSession session = mMediaSession.get();
if (session != null) {
session.dispatchAdjustVolume(createRemoteUserInfo(packageName, pid, uid),
@@ -1388,8 +1369,7 @@ public final class MediaSession {
}
@Override
- public void onSetVolumeTo(String packageName, int pid, int uid,
- ISessionControllerCallback caller, int value) {
+ public void onSetVolumeTo(String packageName, int pid, int uid, int value) {
MediaSession session = mMediaSession.get();
if (session != null) {
session.dispatchSetVolumeTo(createRemoteUserInfo(packageName, pid, uid),
diff --git a/media/java/android/media/session/MediaSessionLegacyHelper.java b/media/java/android/media/session/MediaSessionLegacyHelper.java
index 123c4f75d5b6..0d506f0eb52c 100644
--- a/media/java/android/media/session/MediaSessionLegacyHelper.java
+++ b/media/java/android/media/session/MediaSessionLegacyHelper.java
@@ -16,9 +16,9 @@
package android.media.session;
-import android.annotation.UnsupportedAppUsage;
import android.app.PendingIntent;
import android.app.PendingIntent.CanceledException;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -26,7 +26,6 @@ import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
-import android.media.AudioManager;
import android.media.MediaMetadata;
import android.media.MediaMetadataEditor;
import android.media.MediaMetadataRetriever;
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index a89dc5f1d2af..aff725734ee1 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -22,7 +22,7 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ParceledListSlice;
diff --git a/media/java/android/media/tv/tuner/FilterEvent.java b/media/java/android/media/tv/tuner/FilterEvent.java
new file mode 100644
index 000000000000..7c165cecd6de
--- /dev/null
+++ b/media/java/android/media/tv/tuner/FilterEvent.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.tv.tuner;
+
+import android.os.NativeHandle;
+
+/**
+ * Demux filter event.
+ *
+ * @hide
+ */
+public abstract class FilterEvent {
+
+ /**
+ * Section event.
+ */
+ public static class SectionEvent extends FilterEvent {
+ private int mTableId;
+ private int mVersion;
+ private int mSectionNum;
+ private int mDataLength;
+ }
+
+ /**
+ * Media event.
+ */
+ public static class MediaEvent extends FilterEvent {
+ private int mStreamId;
+ private boolean mIsPtsPresent;
+ private long mPts;
+ private int mDataLength;
+ private NativeHandle mHandle;
+ private boolean mIsSecureMemory;
+ private int mMpuSequenceNumber;
+ private boolean mIsPrivateData;
+ private AudioExtraMetaData mExtraMetaData;
+ }
+
+ /**
+ * PES event.
+ */
+ public static class PesEvent extends FilterEvent {
+ private int mStreamId;
+ private int mDataLength;
+ private int mMpuSequenceNumber;
+ }
+
+ /**
+ * TS record event.
+ */
+ public static class TsRecordEvent extends FilterEvent {
+ private int mTpid;
+ private int mIndexMask;
+ private long mByteNumber;
+ }
+
+ /**
+ * MMPT record event.
+ */
+ public static class MmtpRecordEvent extends FilterEvent {
+ private int mScHevcIndexMask;
+ private long mByteNumber;
+ }
+
+ /**
+ * Download event.
+ */
+ public static class DownloadEvent extends FilterEvent {
+ private int mItemId;
+ private int mMpuSequenceNumber;
+ private int mItemFragmentIndex;
+ private int mLastItemFragmentIndex;
+ private int mDataLength;
+ }
+
+ /**
+ * IP payload event.
+ */
+ public static class IpPayloadEvent extends FilterEvent {
+ private int mDataLength;
+ }
+
+ /**
+ * TEMI event.
+ */
+ public static class TemiEvent extends FilterEvent {
+ private long mPts;
+ private byte mDescrTag;
+ private byte[] mDescrData;
+ }
+
+ /**
+ * Extra Meta Data from AD (Audio Descriptor) according to
+ * ETSI TS 101 154 V2.1.1.
+ */
+ public static class AudioExtraMetaData {
+ private byte mAdFade;
+ private byte mAdPan;
+ private byte mVersionTextTag;
+ private byte mAdGainCenter;
+ private byte mAdGainFront;
+ private byte mAdGainSurround;
+ }
+}
diff --git a/media/java/android/media/tv/tuner/FilterSettings.java b/media/java/android/media/tv/tuner/FilterSettings.java
index d5f100341dc6..673b3d9d8bcc 100644
--- a/media/java/android/media/tv/tuner/FilterSettings.java
+++ b/media/java/android/media/tv/tuner/FilterSettings.java
@@ -17,8 +17,7 @@
package android.media.tv.tuner;
import android.annotation.Nullable;
-import android.hardware.tv.tuner.V1_0.Constants;
-import android.media.tv.tuner.TunerConstants.FilterSettingsType;
+import android.media.tv.tuner.TunerConstants.FilterType;
import java.util.List;
@@ -38,7 +37,8 @@ public abstract class FilterSettings {
/**
* Gets filter settings type
*/
- @FilterSettingsType public abstract int getType();
+ @FilterType
+ public abstract int getType();
// TODO: more builders and getters
@@ -55,7 +55,7 @@ public abstract class FilterSettings {
@Override
public int getType() {
- return TunerConstants.FILTER_SETTINGS_TS;
+ return TunerConstants.FILTER_TYPE_TS;
}
/**
@@ -109,7 +109,7 @@ public abstract class FilterSettings {
@Override
public int getType() {
- return TunerConstants.FILTER_SETTINGS_MMTP;
+ return TunerConstants.FILTER_TYPE_MMTP;
}
}
@@ -130,7 +130,7 @@ public abstract class FilterSettings {
@Override
public int getType() {
- return TunerConstants.FILTER_SETTINGS_IP;
+ return TunerConstants.FILTER_TYPE_IP;
}
}
@@ -149,7 +149,7 @@ public abstract class FilterSettings {
@Override
public int getType() {
- return TunerConstants.FILTER_SETTINGS_TLV;
+ return TunerConstants.FILTER_TYPE_TLV;
}
}
@@ -167,7 +167,7 @@ public abstract class FilterSettings {
@Override
public int getType() {
- return TunerConstants.FILTER_SETTINGS_ALP;
+ return TunerConstants.FILTER_TYPE_ALP;
}
}
@@ -197,24 +197,7 @@ public abstract class FilterSettings {
public static class SectionSettings extends Settings {
private SectionSettings(int mainType) {
- super(SectionSettings.findType(mainType));
- }
-
- private static int findType(int mainType) {
- switch (mainType) {
- case TunerConstants.FILTER_SETTINGS_TS:
- return Constants.DemuxTsFilterType.SECTION;
- case TunerConstants.FILTER_SETTINGS_MMTP:
- return Constants.DemuxMmtpFilterType.SECTION;
- case TunerConstants.FILTER_SETTINGS_IP:
- return Constants.DemuxIpFilterType.SECTION;
- case TunerConstants.FILTER_SETTINGS_TLV:
- return Constants.DemuxTlvFilterType.SECTION;
- case TunerConstants.FILTER_SETTINGS_ALP:
- return Constants.DemuxAlpFilterType.SECTION;
- }
- // UNDEFINED
- return 0;
+ super(TunerUtils.getFilterSubtype(mainType, TunerConstants.FILTER_SUBTYPE_SECTION));
}
}
@@ -251,22 +234,11 @@ public abstract class FilterSettings {
private boolean mIsRaw;
private PesSettings(int mainType, int streamId, boolean isRaw) {
- super(PesSettings.findType(mainType));
+ super(TunerUtils.getFilterSubtype(mainType, TunerConstants.FILTER_SUBTYPE_PES));
mStreamId = streamId;
mIsRaw = isRaw;
}
- private static int findType(int mainType) {
- switch (mainType) {
- case TunerConstants.FILTER_SETTINGS_TS:
- return Constants.DemuxTsFilterType.PES;
- case TunerConstants.FILTER_SETTINGS_MMTP:
- return Constants.DemuxMmtpFilterType.PES;
- }
- // UNDEFINED
- return 0;
- }
-
/**
* Creates a builder for PesSettings.
*/
@@ -319,22 +291,11 @@ public abstract class FilterSettings {
private boolean mIsPassthrough;
private AvSettings(int mainType, boolean isAudio) {
- super(AvSettings.findType(mainType, isAudio));
- }
-
- private static int findType(int mainType, boolean isAudio) {
- switch (mainType) {
- case TunerConstants.FILTER_SETTINGS_TS:
- return isAudio
- ? Constants.DemuxTsFilterType.AUDIO
- : Constants.DemuxTsFilterType.VIDEO;
- case TunerConstants.FILTER_SETTINGS_MMTP:
- return isAudio
- ? Constants.DemuxMmtpFilterType.AUDIO
- : Constants.DemuxMmtpFilterType.VIDEO;
- }
- // UNDEFINED
- return 0;
+ super(TunerUtils.getFilterSubtype(
+ mainType,
+ isAudio
+ ? TunerConstants.FILTER_SUBTYPE_AUDIO
+ : TunerConstants.FILTER_SUBTYPE_VIDEO));
}
}
@@ -345,15 +306,7 @@ public abstract class FilterSettings {
private int mDownloadId;
public DownloadSettings(int mainType) {
- super(DownloadSettings.findType(mainType));
- }
-
- private static int findType(int mainType) {
- if (mainType == TunerConstants.FILTER_SETTINGS_MMTP) {
- return Constants.DemuxMmtpFilterType.DOWNLOAD;
- }
- // UNDEFINED
- return 0;
+ super(TunerUtils.getFilterSubtype(mainType, TunerConstants.FILTER_SUBTYPE_DOWNLOAD));
}
}
@@ -365,18 +318,7 @@ public abstract class FilterSettings {
private int mIndexMask;
public RecordSettings(int mainType) {
- super(RecordSettings.findType(mainType));
- }
-
- private static int findType(int mainType) {
- switch (mainType) {
- case TunerConstants.FILTER_SETTINGS_TS:
- return Constants.DemuxTsFilterType.RECORD;
- case TunerConstants.FILTER_SETTINGS_MMTP:
- return Constants.DemuxMmtpFilterType.RECORD;
- }
- // UNDEFINED
- return 0;
+ super(TunerUtils.getFilterSubtype(mainType, TunerConstants.FILTER_SUBTYPE_RECORD));
}
}
diff --git a/media/java/android/media/tv/tuner/FrontendSettings.java b/media/java/android/media/tv/tuner/FrontendSettings.java
index 3782cc6c6ec3..531e21038bfc 100644
--- a/media/java/android/media/tv/tuner/FrontendSettings.java
+++ b/media/java/android/media/tv/tuner/FrontendSettings.java
@@ -16,15 +16,22 @@
package android.media.tv.tuner;
+import android.annotation.SystemApi;
import android.media.tv.tuner.TunerConstants.FrontendSettingsType;
import java.util.List;
/**
+ * Frontend settings for tune and scan operations.
* @hide
*/
+@SystemApi
public abstract class FrontendSettings {
- protected int mFrequency;
+ private final int mFrequency;
+
+ FrontendSettings(int frequency) {
+ mFrequency = frequency;
+ }
/**
* Returns the frontend type.
@@ -32,7 +39,12 @@ public abstract class FrontendSettings {
@FrontendSettingsType
public abstract int getType();
- public int getFrequency() {
+ /**
+ * Gets the frequency setting.
+ *
+ * @return the frequency in Hz.
+ */
+ public final int getFrequency() {
return mFrequency;
}
@@ -42,6 +54,7 @@ public abstract class FrontendSettings {
/**
* Frontend settings for analog.
+ * @hide
*/
public static class FrontendAnalogSettings extends FrontendSettings {
private int mAnalogType;
@@ -68,7 +81,7 @@ public abstract class FrontendSettings {
}
private FrontendAnalogSettings(int frequency, int analogType, int sifStandard) {
- mFrequency = frequency;
+ super(frequency);
mAnalogType = analogType;
mSifStandard = sifStandard;
}
@@ -118,10 +131,15 @@ public abstract class FrontendSettings {
/**
* Frontend settings for ATSC.
+ * @hide
*/
public static class FrontendAtscSettings extends FrontendSettings {
public int modulation;
+ FrontendAtscSettings(int frequency) {
+ super(frequency);
+ }
+
@Override
public int getType() {
return TunerConstants.FRONTEND_TYPE_ATSC;
@@ -130,12 +148,17 @@ public abstract class FrontendSettings {
/**
* Frontend settings for ATSC-3.
+ * @hide
*/
public static class FrontendAtsc3Settings extends FrontendSettings {
public int bandwidth;
public byte demodOutputFormat;
public List<FrontendAtsc3PlpSettings> plpSettings;
+ FrontendAtsc3Settings(int frequency) {
+ super(frequency);
+ }
+
@Override
public int getType() {
return TunerConstants.FRONTEND_TYPE_ATSC3;
@@ -144,6 +167,7 @@ public abstract class FrontendSettings {
/**
* Frontend settings for DVBS.
+ * @hide
*/
public static class FrontendDvbsSettings extends FrontendSettings {
public int modulation;
@@ -154,6 +178,10 @@ public abstract class FrontendSettings {
public int inputStreamId;
public byte standard;
+ FrontendDvbsSettings(int frequency) {
+ super(frequency);
+ }
+
@Override
public int getType() {
return TunerConstants.FRONTEND_TYPE_DVBS;
@@ -162,6 +190,7 @@ public abstract class FrontendSettings {
/**
* Frontend settings for DVBC.
+ * @hide
*/
public static class FrontendDvbcSettings extends FrontendSettings {
public int modulation;
@@ -171,6 +200,10 @@ public abstract class FrontendSettings {
public byte annex;
public int spectralInversion;
+ FrontendDvbcSettings(int frequency) {
+ super(frequency);
+ }
+
@Override
public int getType() {
return TunerConstants.FRONTEND_TYPE_DVBC;
@@ -179,6 +212,7 @@ public abstract class FrontendSettings {
/**
* Frontend settings for DVBT.
+ * @hide
*/
public static class FrontendDvbtSettings extends FrontendSettings {
public int transmissionMode;
@@ -195,6 +229,10 @@ public abstract class FrontendSettings {
public byte plpId;
public byte plpGroupId;
+ FrontendDvbtSettings(int frequency) {
+ super(frequency);
+ }
+
@Override
public int getType() {
return TunerConstants.FRONTEND_TYPE_DVBT;
@@ -203,6 +241,7 @@ public abstract class FrontendSettings {
/**
* Frontend settings for ISDBS.
+ * @hide
*/
public static class FrontendIsdbsSettings extends FrontendSettings {
public int streamId;
@@ -212,6 +251,10 @@ public abstract class FrontendSettings {
public int symbolRate;
public int rolloff;
+ FrontendIsdbsSettings(int frequency) {
+ super(frequency);
+ }
+
@Override
public int getType() {
return TunerConstants.FRONTEND_TYPE_ISDBS;
@@ -220,6 +263,7 @@ public abstract class FrontendSettings {
/**
* Frontend settings for ISDBS-3.
+ * @hide
*/
public static class FrontendIsdbs3Settings extends FrontendSettings {
public int streamId;
@@ -229,6 +273,10 @@ public abstract class FrontendSettings {
public int symbolRate;
public int rolloff;
+ FrontendIsdbs3Settings(int frequency) {
+ super(frequency);
+ }
+
@Override
public int getType() {
return TunerConstants.FRONTEND_TYPE_ISDBS3;
@@ -237,6 +285,7 @@ public abstract class FrontendSettings {
/**
* Frontend settings for ISDBT.
+ * @hide
*/
public static class FrontendIsdbtSettings extends FrontendSettings {
public int modulation;
@@ -245,6 +294,10 @@ public abstract class FrontendSettings {
public int guardInterval;
public int serviceAreaId;
+ FrontendIsdbtSettings(int frequency) {
+ super(frequency);
+ }
+
@Override
public int getType() {
return TunerConstants.FRONTEND_TYPE_ISDBT;
@@ -253,6 +306,7 @@ public abstract class FrontendSettings {
/**
* PLP settings for ATSC-3.
+ * @hide
*/
public static class FrontendAtsc3PlpSettings {
public byte plpId;
@@ -264,6 +318,7 @@ public abstract class FrontendSettings {
/**
* Code rate for DVBS.
+ * @hide
*/
public static class FrontendDvbsCodeRate {
public long fec;
diff --git a/media/java/android/media/tv/tuner/FrontendStatus.java b/media/java/android/media/tv/tuner/FrontendStatus.java
new file mode 100644
index 000000000000..f8b2d128d657
--- /dev/null
+++ b/media/java/android/media/tv/tuner/FrontendStatus.java
@@ -0,0 +1,258 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.tv.tuner;
+
+import android.media.tv.tuner.TunerConstants.FrontendDvbcSpectralInversion;
+import android.media.tv.tuner.TunerConstants.FrontendDvbtHierarchy;
+import android.media.tv.tuner.TunerConstants.FrontendInnerFec;
+import android.media.tv.tuner.TunerConstants.FrontendModulation;
+import android.media.tv.tuner.TunerConstants.FrontendStatusType;
+import android.media.tv.tuner.TunerConstants.LnbVoltage;
+
+/**
+ * Frontend status
+ *
+ * @hide
+ */
+public class FrontendStatus {
+
+ private final int mType;
+ private final Object mValue;
+
+ private FrontendStatus(int type, Object value) {
+ mType = type;
+ mValue = value;
+ }
+
+ /** Gets frontend status type. */
+ @FrontendStatusType
+ public int getStatusType() {
+ return mType;
+ }
+ /** Lock status for Demod in True/False. */
+ public boolean getIsDemodLocked() {
+ if (mType != TunerConstants.FRONTEND_STATUS_TYPE_DEMOD_LOCK) {
+ throw new IllegalStateException();
+ }
+ return (Boolean) mValue;
+ }
+ /** SNR value measured by 0.001 dB. */
+ public int getSnr() {
+ if (mType != TunerConstants.FRONTEND_STATUS_TYPE_SNR) {
+ throw new IllegalStateException();
+ }
+ return (int) mValue;
+ }
+ /** The number of error bit per 1 billion bits. */
+ public int getBer() {
+ if (mType != TunerConstants.FRONTEND_STATUS_TYPE_BER) {
+ throw new IllegalStateException();
+ }
+ return (int) mValue;
+ }
+ /** The number of error package per 1 billion packages. */
+ public int getPer() {
+ if (mType != TunerConstants.FRONTEND_STATUS_TYPE_PER) {
+ throw new IllegalStateException();
+ }
+ return (int) mValue;
+ }
+ /** The number of error bit per 1 billion bits before FEC. */
+ public int getPerBer() {
+ if (mType != TunerConstants.FRONTEND_STATUS_TYPE_PRE_BER) {
+ throw new IllegalStateException();
+ }
+ return (int) mValue;
+ }
+ /** Signal Quality in percent. */
+ public int getSignalQuality() {
+ if (mType != TunerConstants.FRONTEND_STATUS_TYPE_SIGNAL_QUALITY) {
+ throw new IllegalStateException();
+ }
+ return (int) mValue;
+ }
+ /** Signal Strength measured by 0.001 dBm. */
+ public int getSignalStrength() {
+ if (mType != TunerConstants.FRONTEND_STATUS_TYPE_SIGNAL_STRENGTH) {
+ throw new IllegalStateException();
+ }
+ return (int) mValue;
+ }
+ /** Symbols per second. */
+ public int getSymbolRate() {
+ if (mType != TunerConstants.FRONTEND_STATUS_TYPE_SYMBOL_RATE) {
+ throw new IllegalStateException();
+ }
+ return (int) mValue;
+ }
+ /**
+ * Inner Forward Error Correction type as specified in ETSI EN 300 468 V1.15.1
+ * and ETSI EN 302 307-2 V1.1.1.
+ */
+ @FrontendInnerFec
+ public long getFec() {
+ if (mType != TunerConstants.FRONTEND_STATUS_TYPE_FEC) {
+ throw new IllegalStateException();
+ }
+ return (long) mValue;
+ }
+ /** Modulation */
+ @FrontendModulation
+ public int getModulation() {
+ if (mType != TunerConstants.FRONTEND_STATUS_TYPE_MODULATION) {
+ throw new IllegalStateException();
+ }
+ return (int) mValue;
+ }
+ /** Spectral Inversion for DVBC. */
+ @FrontendDvbcSpectralInversion
+ public int getSpectralInversion() {
+ if (mType != TunerConstants.FRONTEND_STATUS_TYPE_SPECTRAL) {
+ throw new IllegalStateException();
+ }
+ return (int) mValue;
+ }
+ /** Power Voltage Type for LNB. */
+ @LnbVoltage
+ public int getLnbVoltage() {
+ if (mType != TunerConstants.FRONTEND_STATUS_TYPE_LNB_VOLTAGE) {
+ throw new IllegalStateException();
+ }
+ return (int) mValue;
+ }
+ /** PLP ID */
+ public byte getPlpId() {
+ if (mType != TunerConstants.FRONTEND_STATUS_TYPE_PLP_ID) {
+ throw new IllegalStateException();
+ }
+ return (byte) mValue;
+ }
+ /** Emergency Warning Broadcasting System */
+ public boolean getIsEwbs() {
+ if (mType != TunerConstants.FRONTEND_STATUS_TYPE_EWBS) {
+ throw new IllegalStateException();
+ }
+ return (Boolean) mValue;
+ }
+ /** AGC value is normalized from 0 to 255. */
+ public byte getAgc() {
+ if (mType != TunerConstants.FRONTEND_STATUS_TYPE_AGC) {
+ throw new IllegalStateException();
+ }
+ return (byte) mValue;
+ }
+ /** LNA(Low Noise Amplifier) is on or not. */
+ public boolean getLnaOn() {
+ if (mType != TunerConstants.FRONTEND_STATUS_TYPE_LNA) {
+ throw new IllegalStateException();
+ }
+ return (Boolean) mValue;
+ }
+ /** Error status by layer. */
+ public boolean[] getIsLayerError() {
+ if (mType != TunerConstants.FRONTEND_STATUS_TYPE_LAYER_ERROR) {
+ throw new IllegalStateException();
+ }
+ return (boolean[]) mValue;
+ }
+ /** CN value by VBER measured by 0.001 dB. */
+ public int getVberCn() {
+ if (mType != TunerConstants.FRONTEND_STATUS_TYPE_VBER_CN) {
+ throw new IllegalStateException();
+ }
+ return (int) mValue;
+ }
+ /** CN value by LBER measured by 0.001 dB. */
+ public int getLberCn() {
+ if (mType != TunerConstants.FRONTEND_STATUS_TYPE_LBER_CN) {
+ throw new IllegalStateException();
+ }
+ return (int) mValue;
+ }
+ /** CN value by XER measured by 0.001 dB. */
+ public int getXerCn() {
+ if (mType != TunerConstants.FRONTEND_STATUS_TYPE_XER_CN) {
+ throw new IllegalStateException();
+ }
+ return (int) mValue;
+ }
+ /** MER value measured by 0.001 dB. */
+ public int getMer() {
+ if (mType != TunerConstants.FRONTEND_STATUS_TYPE_MER) {
+ throw new IllegalStateException();
+ }
+ return (int) mValue;
+ }
+ /** Frequency difference in Hertz. */
+ public int getFreqOffset() {
+ if (mType != TunerConstants.FRONTEND_STATUS_TYPE_FREQ_OFFSET) {
+ throw new IllegalStateException();
+ }
+ return (int) mValue;
+ }
+ /** Hierarchy Type for DVBT. */
+ @FrontendDvbtHierarchy
+ public int getHierarchy() {
+ if (mType != TunerConstants.FRONTEND_STATUS_TYPE_HIERARCHY) {
+ throw new IllegalStateException();
+ }
+ return (int) mValue;
+ }
+ /** Lock status for RF. */
+ public boolean getIsRfLock() {
+ if (mType != TunerConstants.FRONTEND_STATUS_TYPE_RF_LOCK) {
+ throw new IllegalStateException();
+ }
+ return (Boolean) mValue;
+ }
+ /** A list of PLP status for tuned PLPs for ATSC3 frontend. */
+ public Atsc3PlpInfo[] getAtsc3PlpInfo() {
+ if (mType != TunerConstants.FRONTEND_STATUS_TYPE_ATSC3_PLP_INFO) {
+ throw new IllegalStateException();
+ }
+ return (Atsc3PlpInfo[]) mValue;
+ }
+
+ /** Status for each tuning PLPs. */
+ public static class Atsc3PlpInfo {
+ private final int mPlpId;
+ private final boolean mIsLock;
+ private final int mUec;
+
+ private Atsc3PlpInfo(int plpId, boolean isLock, int uec) {
+ mPlpId = plpId;
+ mIsLock = isLock;
+ mUec = uec;
+ }
+
+ /** Gets PLP IDs. */
+ public int getPlpId() {
+ return mPlpId;
+ }
+ /** Gets Demod Lock/Unlock status of this particular PLP. */
+ public boolean getIsLock() {
+ return mIsLock;
+ }
+ /**
+ * Gets Uncorrectable Error Counts (UEC) of this particular PLP since last tune
+ * operation.
+ */
+ public int getUec() {
+ return mUec;
+ }
+ }
+}
diff --git a/media/java/android/media/tv/tuner/ScanMessage.java b/media/java/android/media/tv/tuner/ScanMessage.java
new file mode 100644
index 000000000000..35f54f8447c0
--- /dev/null
+++ b/media/java/android/media/tv/tuner/ScanMessage.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.tv.tuner;
+
+import android.media.tv.tuner.TunerConstants.ScanMessageType;
+
+/**
+ * Message from frontend during scan operations.
+ *
+ * @hide
+ */
+public class ScanMessage {
+ private final int mType;
+ private final Object mValue;
+
+ private ScanMessage(int type, Object value) {
+ mType = type;
+ mValue = value;
+ }
+
+ /** Gets scan message type. */
+ @ScanMessageType
+ public int getMessageType() {
+ return mType;
+ }
+ /** Message indicates whether frontend is locked or not. */
+ public boolean getIsLocked() {
+ if (mType != TunerConstants.SCAN_MESSAGE_TYPE_LOCKED) {
+ throw new IllegalStateException();
+ }
+ return (Boolean) mValue;
+ }
+ /** Message indicates whether the scan has reached the end or not. */
+ public boolean getIsEnd() {
+ if (mType != TunerConstants.SCAN_MESSAGE_TYPE_END) {
+ throw new IllegalStateException();
+ }
+ return (Boolean) mValue;
+ }
+ /** Progress message in percent. */
+ public int getProgressPercent() {
+ if (mType != TunerConstants.SCAN_MESSAGE_TYPE_PROGRESS_PERCENT) {
+ throw new IllegalStateException();
+ }
+ return (Integer) mValue;
+ }
+ /** Gets frequency. */
+ public int getFrequency() {
+ if (mType != TunerConstants.SCAN_MESSAGE_TYPE_FREQUENCY) {
+ throw new IllegalStateException();
+ }
+ return (Integer) mValue;
+ }
+ /** Gets symbol rate. */
+ public int getSymbolRate() {
+ if (mType != TunerConstants.SCAN_MESSAGE_TYPE_SYMBOL_RATE) {
+ throw new IllegalStateException();
+ }
+ return (Integer) mValue;
+ }
+ /** Gets PLP IDs. */
+ public int[] getPlpIds() {
+ if (mType != TunerConstants.SCAN_MESSAGE_TYPE_PLP_IDS) {
+ throw new IllegalStateException();
+ }
+ return (int[]) mValue;
+ }
+ /** Gets group IDs. */
+ public int[] getGroupIds() {
+ if (mType != TunerConstants.SCAN_MESSAGE_TYPE_GROUP_IDS) {
+ throw new IllegalStateException();
+ }
+ return (int[]) mValue;
+ }
+ /** Gets Input stream IDs. */
+ public int[] getInputStreamIds() {
+ if (mType != TunerConstants.SCAN_MESSAGE_TYPE_INPUT_STREAM_IDS) {
+ throw new IllegalStateException();
+ }
+ return (int[]) mValue;
+ }
+ /** Gets the DVB-T or DVB-S standard. */
+ public int getStandard() {
+ if (mType != TunerConstants.SCAN_MESSAGE_TYPE_STANDARD) {
+ throw new IllegalStateException();
+ }
+ return (int) mValue;
+ }
+
+ /** Gets PLP information for ATSC3. */
+ public Atsc3PlpInfo[] getAtsc3PlpInfos() {
+ if (mType != TunerConstants.SCAN_MESSAGE_TYPE_ATSC3_PLP_INFO) {
+ throw new IllegalStateException();
+ }
+ return (Atsc3PlpInfo[]) mValue;
+ }
+
+ /** PLP information for ATSC3. */
+ public static class Atsc3PlpInfo {
+ private final int mPlpId;
+ private final boolean mLlsFlag;
+
+ private Atsc3PlpInfo(int plpId, boolean llsFlag) {
+ mPlpId = plpId;
+ mLlsFlag = llsFlag;
+ }
+
+ /** Gets PLP IDs. */
+ public int getPlpId() {
+ return mPlpId;
+ }
+ /** Gets LLS flag. */
+ public boolean getLlsFlag() {
+ return mLlsFlag;
+ }
+ }
+}
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index 4c93101bc0b5..b8ab7eea248e 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -18,7 +18,17 @@ package android.media.tv.tuner;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
+import android.content.Context;
import android.media.tv.tuner.TunerConstants.DemuxPidType;
+import android.media.tv.tuner.TunerConstants.FilterSubtype;
+import android.media.tv.tuner.TunerConstants.FilterType;
+import android.media.tv.tuner.TunerConstants.FrontendScanType;
+import android.media.tv.tuner.TunerConstants.LnbPosition;
+import android.media.tv.tuner.TunerConstants.LnbTone;
+import android.media.tv.tuner.TunerConstants.LnbVoltage;
+import android.media.tv.tuner.TunerConstants.Result;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -26,10 +36,15 @@ import android.os.Message;
import java.util.List;
/**
- * Tuner is used to interact with tuner devices.
+ * This class is used to interact with hardware tuners devices.
+ *
+ * <p> Each TvInputService Session should create one instance of this class.
+ *
+ * <p> This class controls the TIS interaction with Tuner HAL.
*
* @hide
*/
+@SystemApi
public final class Tuner implements AutoCloseable {
private static final String TAG = "MediaTvTuner";
private static final boolean DEBUG = false;
@@ -44,6 +59,8 @@ public final class Tuner implements AutoCloseable {
nativeInit();
}
+ private final Context mContext;
+
private List<Integer> mFrontendIds;
private Frontend mFrontend;
private EventHandler mHandler;
@@ -51,12 +68,19 @@ public final class Tuner implements AutoCloseable {
private List<Integer> mLnbIds;
private Lnb mLnb;
- public Tuner() {
+ /**
+ * Constructs a Tuner instance.
+ *
+ * @param context context of the caller.
+ */
+ public Tuner(@NonNull Context context) {
+ mContext = context;
nativeSetup();
}
private long mNativeContext; // used by native jMediaTuner
+ /** @hide */
@Override
public void close() {}
@@ -80,7 +104,12 @@ public final class Tuner implements AutoCloseable {
*/
private native Frontend nativeOpenFrontendById(int id);
private native int nativeTune(int type, FrontendSettings settings);
-
+ private native int nativeStopTune();
+ private native int nativeScan(int settingsType, FrontendSettings settings, int scanType);
+ private native int nativeStopScan();
+ private native int nativeSetLnb(int lnbId);
+ private native int nativeSetLna(boolean enable);
+ private native FrontendStatus[] nativeGetFrontendStatus(int[] statusTypes);
private native Filter nativeOpenFilter(int type, int subType, int bufferSize);
private native List<Integer> nativeGetLnbIds();
@@ -92,6 +121,8 @@ public final class Tuner implements AutoCloseable {
/**
* Frontend Callback.
+ *
+ * @hide
*/
public interface FrontendCallback {
@@ -99,23 +130,46 @@ public final class Tuner implements AutoCloseable {
* Invoked when there is a frontend event.
*/
void onEvent(int frontendEventType);
+
+ /**
+ * Invoked when there is a scan message.
+ * @param msg
+ */
+ void onScanMessage(ScanMessage msg);
}
/**
* LNB Callback.
+ *
+ * @hide
*/
public interface LnbCallback {
/**
* Invoked when there is a LNB event.
*/
void onEvent(int lnbEventType);
+
+ /**
+ * Invoked when there is a new DiSEqC message.
+ *
+ * @param diseqcMessage a byte array of data for DiSEqC (Digital Satellite
+ * Equipment Control) message which is specified by EUTELSAT Bus Functional
+ * Specification Version 4.2.
+ */
+ void onDiseqcMessage(byte[] diseqcMessage);
}
/**
* Frontend Callback.
+ *
+ * @hide
*/
public interface FilterCallback {
/**
+ * Invoked when there are filter events.
+ */
+ void onFilterEvent(FilterEvent[] events);
+ /**
* Invoked when filter status changed.
*/
void onFilterStatus(int status);
@@ -123,6 +177,8 @@ public final class Tuner implements AutoCloseable {
/**
* DVR Callback.
+ *
+ * @hide
*/
public interface DvrCallback {
/**
@@ -177,7 +233,7 @@ public final class Tuner implements AutoCloseable {
}
}
- protected class Frontend {
+ private class Frontend {
private int mId;
private FrontendCallback mCallback;
@@ -210,12 +266,91 @@ public final class Tuner implements AutoCloseable {
}
/**
- * Tunes the frontend to using the settings given.
+ * Tunes the frontend to the settings given.
+ *
+ * @return result status of tune operation.
+ * @throws SecurityException if the caller does not have appropriate permissions.
+ * TODO: add result constants or throw exceptions.
*/
+ @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
public int tune(@NonNull FrontendSettings settings) {
+ TunerUtils.checkTunerPermission(mContext);
return nativeTune(settings.getType(), settings);
}
+ /**
+ * Stops a previous tuning.
+ *
+ * If the method completes successfully the frontend is no longer tuned and no data
+ * will be sent to attached filters.
+ *
+ * @return result status of the operation.
+ * @hide
+ */
+ public int stopTune() {
+ return nativeStopTune();
+ }
+
+ /**
+ * Scan channels.
+ * @hide
+ */
+ public int scan(@NonNull FrontendSettings settings, @FrontendScanType int scanType) {
+ return nativeScan(settings.getType(), settings, scanType);
+ }
+
+ /**
+ * Stops a previous scanning.
+ *
+ * If the method completes successfully, the frontend stop previous scanning.
+ * @hide
+ */
+ public int stopScan() {
+ return nativeStopScan();
+ }
+
+ /**
+ * Sets Low-Noise Block downconverter (LNB) for satellite frontend.
+ *
+ * This assigns a hardware LNB resource to the satellite tuner. It can be
+ * called multiple times to update LNB assignment.
+ *
+ * @param lnb the LNB instance.
+ *
+ * @return result status of the operation.
+ * @hide
+ */
+ public int setLnb(@NonNull Lnb lnb) {
+ return nativeSetLnb(lnb.mId);
+ }
+
+ /**
+ * Enable or Disable Low Noise Amplifier (LNA).
+ *
+ * @param enable true to activate LNA module; false to deactivate LNA
+ *
+ * @return result status of the operation.
+ * @hide
+ */
+ public int setLna(boolean enable) {
+ return nativeSetLna(enable);
+ }
+
+ /**
+ * Gets the statuses of the frontend.
+ *
+ * This retrieve the statuses of the frontend for given status types.
+ *
+ * @param statusTypes an array of status type which the caller request.
+ *
+ * @return statuses an array of statuses which response the caller's
+ * request.
+ * @hide
+ */
+ public FrontendStatus[] getFrontendStatus(int[] statusTypes) {
+ return nativeGetFrontendStatus(statusTypes);
+ }
+
private List<Integer> getFrontendIds() {
mFrontendIds = nativeGetFrontendIds();
return mFrontendIds;
@@ -238,16 +373,20 @@ public final class Tuner implements AutoCloseable {
}
}
- protected class Filter {
+ /** @hide */
+ public class Filter {
private long mNativeContext;
private FilterCallback mCallback;
int mId;
private native int nativeConfigureFilter(int type, int subType, FilterSettings settings);
- private native boolean nativeStartFilter();
- private native boolean nativeStopFilter();
- private native boolean nativeFlushFilter();
+ private native int nativeGetId();
+ private native int nativeSetDataSource(Filter source);
+ private native int nativeStartFilter();
+ private native int nativeStopFilter();
+ private native int nativeFlushFilter();
private native int nativeRead(byte[] buffer, int offset, int size);
+ private native int nativeClose();
private Filter(int id) {
mId = id;
@@ -260,6 +399,12 @@ public final class Tuner implements AutoCloseable {
}
}
+ /**
+ * Configures the filter.
+ *
+ * @param settings the settings of the filter.
+ * @return result status of the operation.
+ */
public int configure(FilterSettings settings) {
int subType = -1;
if (settings.mSettings != null) {
@@ -268,15 +413,56 @@ public final class Tuner implements AutoCloseable {
return nativeConfigureFilter(settings.getType(), subType, settings);
}
- public boolean start() {
+ /**
+ * Gets the filter Id.
+ *
+ * @return the hardware resource Id for the filter.
+ */
+ public int getId() {
+ return nativeGetId();
+ }
+
+ /**
+ * Sets the filter's data source.
+ *
+ * A filter uses demux as data source by default. If the data was packetized
+ * by multiple protocols, multiple filters may need to work together to
+ * extract all protocols' header. Then a filter's data source can be output
+ * from another filter.
+ *
+ * @param source the filter instance which provides data input. Switch to
+ * use demux as data source if the filter instance is NULL.
+ * @return result status of the operation.
+ */
+ public int setDataSource(@Nullable Filter source) {
+ return nativeSetDataSource(source);
+ }
+
+ /**
+ * Starts the filter.
+ *
+ * @return result status of the operation.
+ */
+ public int start() {
return nativeStartFilter();
}
- public boolean stop() {
+
+ /**
+ * Stops the filter.
+ *
+ * @return result status of the operation.
+ */
+ public int stop() {
return nativeStopFilter();
}
- public boolean flush() {
+ /**
+ * Flushes the filter.
+ *
+ * @return result status of the operation.
+ */
+ public int flush() {
return nativeFlushFilter();
}
@@ -284,10 +470,21 @@ public final class Tuner implements AutoCloseable {
size = Math.min(size, buffer.length - offset);
return nativeRead(buffer, offset, size);
}
+
+ /**
+ * Release the Filter instance.
+ *
+ * @return result status of the operation.
+ */
+ public int close() {
+ return nativeClose();
+ }
}
- private Filter openFilter(int type, int subType, int bufferSize, FilterCallback cb) {
- Filter filter = nativeOpenFilter(type, subType, bufferSize);
+ private Filter openFilter(@FilterType int mainType, @FilterSubtype int subType, int bufferSize,
+ FilterCallback cb) {
+ Filter filter = nativeOpenFilter(
+ mainType, TunerUtils.getFilterSubtype(mainType, subType), bufferSize);
if (filter != null) {
filter.mCallback = cb;
if (mHandler == null) {
@@ -297,10 +494,17 @@ public final class Tuner implements AutoCloseable {
return filter;
}
- protected class Lnb {
+ /** @hide */
+ public class Lnb {
private int mId;
private LnbCallback mCallback;
+ private native int nativeSetVoltage(int voltage);
+ private native int nativeSetTone(int tone);
+ private native int nativeSetSatellitePosition(int position);
+ private native int nativeSendDiseqcMessage(byte[] message);
+ private native int nativeClose();
+
private Lnb(int id) {
mId = id;
}
@@ -314,6 +518,64 @@ public final class Tuner implements AutoCloseable {
mHandler = createEventHandler();
}
}
+
+ /**
+ * Sets the LNB's power voltage.
+ *
+ * @param voltage the power voltage the Lnb to use.
+ * @return result status of the operation.
+ */
+ @Result
+ public int setVoltage(@LnbVoltage int voltage) {
+ return nativeSetVoltage(voltage);
+ }
+
+ /**
+ * Sets the LNB's tone mode.
+ *
+ * @param tone the tone mode the Lnb to use.
+ * @return result status of the operation.
+ */
+ @Result
+ public int setTone(@LnbTone int tone) {
+ return nativeSetTone(tone);
+ }
+
+ /**
+ * Selects the LNB's position.
+ *
+ * @param position the position the Lnb to use.
+ * @return result status of the operation.
+ */
+ @Result
+ public int setSatellitePosition(@LnbPosition int position) {
+ return nativeSetSatellitePosition(position);
+ }
+
+ /**
+ * Sends DiSEqC (Digital Satellite Equipment Control) message.
+ *
+ * The response message from the device comes back through callback onDiseqcMessage.
+ *
+ * @param message a byte array of data for DiSEqC message which is specified by EUTELSAT Bus
+ * Functional Specification Version 4.2.
+ *
+ * @return result status of the operation.
+ */
+ @Result
+ public int sendDiseqcMessage(byte[] message) {
+ return nativeSendDiseqcMessage(message);
+ }
+
+ /**
+ * Releases the LNB instance
+ *
+ * @return result status of the operation.
+ */
+ @Result
+ public int close() {
+ return nativeClose();
+ }
}
private List<Integer> getLnbIds() {
@@ -338,61 +600,186 @@ public final class Tuner implements AutoCloseable {
}
}
- protected class Descrambler {
+ /**
+ * This class is used to interact with descramblers.
+ *
+ * <p> Descrambler is a hardware component used to descramble data.
+ *
+ * <p> This class controls the TIS interaction with Tuner HAL.
+ * TODO: make it static and extends Closable.
+ */
+ public class Descrambler {
private long mNativeContext;
- private native boolean nativeAddPid(int pidType, int pid, Filter filter);
- private native boolean nativeRemovePid(int pidType, int pid, Filter filter);
+ private native int nativeAddPid(int pidType, int pid, Filter filter);
+ private native int nativeRemovePid(int pidType, int pid, Filter filter);
+ private native int nativeSetKeyToken(byte[] keyToken);
+ private native int nativeClose();
private Descrambler() {}
- private boolean addPid(@DemuxPidType int pidType, int pid, Filter filter) {
+ /**
+ * Add packets' PID to the descrambler for descrambling.
+ *
+ * The descrambler will start descrambling packets with this PID. Multiple PIDs can be added
+ * into one descrambler instance because descambling can happen simultaneously on packets
+ * from different PIDs.
+ *
+ * If the Descrambler previously contained a filter for the PID, the old filter is replaced
+ * by the specified filter.
+ *
+ * @param pidType the type of the PID.
+ * @param pid the PID of packets to start to be descrambled.
+ * @param filter an optional filter instance to identify upper stream.
+ * @return result status of the operation.
+ *
+ * @hide
+ */
+ public int addPid(@DemuxPidType int pidType, int pid, @Nullable Filter filter) {
return nativeAddPid(pidType, pid, filter);
}
- private boolean removePid(@DemuxPidType int pidType, int pid, Filter filter) {
+ /**
+ * Remove packets' PID from the descrambler
+ *
+ * The descrambler will stop descrambling packets with this PID.
+ *
+ * @param pidType the type of the PID.
+ * @param pid the PID of packets to stop to be descrambled.
+ * @param filter an optional filter instance to identify upper stream.
+ * @return result status of the operation.
+ *
+ * @hide
+ */
+ public int removePid(@DemuxPidType int pidType, int pid, @Nullable Filter filter) {
return nativeRemovePid(pidType, pid, filter);
}
+ /**
+ * Set a key token to link descrambler to a key slot
+ *
+ * A descrambler instance can have only one key slot to link, but a key slot can hold a few
+ * keys for different purposes.
+ *
+ * @param keyToken the token to be used to link the key slot.
+ * @return result status of the operation.
+ *
+ * @hide
+ */
+ public int setKeyToken(byte[] keyToken) {
+ return nativeSetKeyToken(keyToken);
+ }
+
+ /**
+ * Release the descrambler instance.
+ *
+ * @return result status of the operation.
+ *
+ * @hide
+ */
+ public int close() {
+ return nativeClose();
+ }
+
}
- private Descrambler openDescrambler() {
- Descrambler descrambler = nativeOpenDescrambler();
- return descrambler;
+ /**
+ * Opens a Descrambler in tuner.
+ *
+ * @return a {@link Descrambler} object.
+ */
+ @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
+ @Nullable
+ public Descrambler openDescrambler() {
+ TunerUtils.checkTunerPermission(mContext);
+ return nativeOpenDescrambler();
}
// TODO: consider splitting Dvr to Playback and Recording
- protected class Dvr {
+ /** @hide */
+ public class Dvr {
private long mNativeContext;
private DvrCallback mCallback;
- private native boolean nativeAttachFilter(Filter filter);
- private native boolean nativeDetachFilter(Filter filter);
+ private native int nativeAttachFilter(Filter filter);
+ private native int nativeDetachFilter(Filter filter);
private native int nativeConfigureDvr(DvrSettings settings);
- private native boolean nativeStartDvr();
- private native boolean nativeStopDvr();
- private native boolean nativeFlushDvr();
+ private native int nativeStartDvr();
+ private native int nativeStopDvr();
+ private native int nativeFlushDvr();
+ private native int nativeClose();
private Dvr() {}
- public boolean attachFilter(Filter filter) {
+ /**
+ * Attaches a filter to DVR interface for recording.
+ *
+ * @param filter the filter to be attached.
+ * @return result status of the operation.
+ */
+ public int attachFilter(Filter filter) {
return nativeAttachFilter(filter);
}
- public boolean detachFilter(Filter filter) {
+
+ /**
+ * Detaches a filter from DVR interface.
+ *
+ * @param filter the filter to be detached.
+ * @return result status of the operation.
+ */
+ public int detachFilter(Filter filter) {
return nativeDetachFilter(filter);
}
+
+ /**
+ * Configures the DVR.
+ *
+ * @param settings the settings of the DVR interface.
+ * @return result status of the operation.
+ */
public int configure(DvrSettings settings) {
return nativeConfigureDvr(settings);
}
- public boolean start() {
+
+ /**
+ * Starts DVR.
+ *
+ * Starts consuming playback data or producing data for recording.
+ *
+ * @return result status of the operation.
+ */
+ public int start() {
return nativeStartDvr();
}
- public boolean stop() {
+
+ /**
+ * Stops DVR.
+ *
+ * Stops consuming playback data or producing data for recording.
+ *
+ * @return result status of the operation.
+ */
+ public int stop() {
return nativeStopDvr();
}
- public boolean flush() {
+
+ /**
+ * Flushed DVR data.
+ *
+ * @return result status of the operation.
+ */
+ public int flush() {
return nativeFlushDvr();
}
+
+ /**
+ * closes the DVR instance to release resources.
+ *
+ * @return result status of the operation.
+ */
+ public int close() {
+ return nativeClose();
+ }
}
private Dvr openDvr(int type, int bufferSize) {
diff --git a/media/java/android/media/tv/tuner/TunerConstants.java b/media/java/android/media/tv/tuner/TunerConstants.java
index 261b2deebac9..e611431febe9 100644
--- a/media/java/android/media/tv/tuner/TunerConstants.java
+++ b/media/java/android/media/tv/tuner/TunerConstants.java
@@ -17,6 +17,7 @@
package android.media.tv.tuner;
import android.annotation.IntDef;
+import android.annotation.LongDef;
import android.hardware.tv.tuner.V1_0.Constants;
import java.lang.annotation.Retention;
@@ -75,6 +76,7 @@ final class TunerConstants {
public static final int DEMUX_T_PID = 1;
public static final int DEMUX_MMPT_PID = 2;
+ @Retention(RetentionPolicy.SOURCE)
@IntDef({FRONTEND_SETTINGS_ANALOG, FRONTEND_SETTINGS_ATSC, FRONTEND_SETTINGS_ATSC3,
FRONTEND_SETTINGS_DVBS, FRONTEND_SETTINGS_DVBC, FRONTEND_SETTINGS_DVBT,
FRONTEND_SETTINGS_ISDBS, FRONTEND_SETTINGS_ISDBS3, FRONTEND_SETTINGS_ISDBT})
@@ -91,6 +93,474 @@ final class TunerConstants {
public static final int FRONTEND_SETTINGS_ISDBT = 9;
@Retention(RetentionPolicy.SOURCE)
+ @IntDef({FILTER_TYPE_TS, FILTER_TYPE_MMTP, FILTER_TYPE_IP, FILTER_TYPE_TLV, FILTER_TYPE_ALP})
+ public @interface FilterType {}
+
+ public static final int FILTER_TYPE_TS = Constants.DemuxFilterMainType.TS;
+ public static final int FILTER_TYPE_MMTP = Constants.DemuxFilterMainType.MMTP;
+ public static final int FILTER_TYPE_IP = Constants.DemuxFilterMainType.IP;
+ public static final int FILTER_TYPE_TLV = Constants.DemuxFilterMainType.TLV;
+ public static final int FILTER_TYPE_ALP = Constants.DemuxFilterMainType.ALP;
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({FILTER_SUBTYPE_UNDEFINED, FILTER_SUBTYPE_SECTION, FILTER_SUBTYPE_PES,
+ FILTER_SUBTYPE_AUDIO, FILTER_SUBTYPE_VIDEO, FILTER_SUBTYPE_DOWNLOAD,
+ FILTER_SUBTYPE_RECORD, FILTER_SUBTYPE_TS, FILTER_SUBTYPE_PCR, FILTER_SUBTYPE_TEMI,
+ FILTER_SUBTYPE_MMPT, FILTER_SUBTYPE_NTP, FILTER_SUBTYPE_IP_PAYLOAD, FILTER_SUBTYPE_IP,
+ FILTER_SUBTYPE_PAYLOAD_THROUGH, FILTER_SUBTYPE_TLV, FILTER_SUBTYPE_PTP, })
+ public @interface FilterSubtype {}
+
+ public static final int FILTER_SUBTYPE_UNDEFINED = 0;
+ public static final int FILTER_SUBTYPE_SECTION = 1;
+ public static final int FILTER_SUBTYPE_PES = 2;
+ public static final int FILTER_SUBTYPE_AUDIO = 3;
+ public static final int FILTER_SUBTYPE_VIDEO = 4;
+ public static final int FILTER_SUBTYPE_DOWNLOAD = 5;
+ public static final int FILTER_SUBTYPE_RECORD = 6;
+ public static final int FILTER_SUBTYPE_TS = 7;
+ public static final int FILTER_SUBTYPE_PCR = 8;
+ public static final int FILTER_SUBTYPE_TEMI = 9;
+ public static final int FILTER_SUBTYPE_MMPT = 10;
+ public static final int FILTER_SUBTYPE_NTP = 11;
+ public static final int FILTER_SUBTYPE_IP_PAYLOAD = 12;
+ public static final int FILTER_SUBTYPE_IP = 13;
+ public static final int FILTER_SUBTYPE_PAYLOAD_THROUGH = 14;
+ public static final int FILTER_SUBTYPE_TLV = 15;
+ public static final int FILTER_SUBTYPE_PTP = 16;
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({FRONTEND_SCAN_UNDEFINED, FRONTEND_SCAN_AUTO, FRONTEND_SCAN_BLIND})
+ public @interface FrontendScanType {}
+
+ public static final int FRONTEND_SCAN_UNDEFINED = Constants.FrontendScanType.SCAN_UNDEFINED;
+ public static final int FRONTEND_SCAN_AUTO = Constants.FrontendScanType.SCAN_AUTO;
+ public static final int FRONTEND_SCAN_BLIND = Constants.FrontendScanType.SCAN_BLIND;
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({SCAN_MESSAGE_TYPE_LOCKED, SCAN_MESSAGE_TYPE_END, SCAN_MESSAGE_TYPE_PROGRESS_PERCENT,
+ SCAN_MESSAGE_TYPE_FREQUENCY, SCAN_MESSAGE_TYPE_SYMBOL_RATE, SCAN_MESSAGE_TYPE_PLP_IDS,
+ SCAN_MESSAGE_TYPE_GROUP_IDS, SCAN_MESSAGE_TYPE_INPUT_STREAM_IDS,
+ SCAN_MESSAGE_TYPE_STANDARD, SCAN_MESSAGE_TYPE_ATSC3_PLP_INFO})
+ public @interface ScanMessageType {}
+
+ public static final int SCAN_MESSAGE_TYPE_LOCKED = Constants.FrontendScanMessageType.LOCKED;
+ public static final int SCAN_MESSAGE_TYPE_END = Constants.FrontendScanMessageType.END;
+ public static final int SCAN_MESSAGE_TYPE_PROGRESS_PERCENT =
+ Constants.FrontendScanMessageType.PROGRESS_PERCENT;
+ public static final int SCAN_MESSAGE_TYPE_FREQUENCY =
+ Constants.FrontendScanMessageType.FREQUENCY;
+ public static final int SCAN_MESSAGE_TYPE_SYMBOL_RATE =
+ Constants.FrontendScanMessageType.SYMBOL_RATE;
+ public static final int SCAN_MESSAGE_TYPE_PLP_IDS = Constants.FrontendScanMessageType.PLP_IDS;
+ public static final int SCAN_MESSAGE_TYPE_GROUP_IDS =
+ Constants.FrontendScanMessageType.GROUP_IDS;
+ public static final int SCAN_MESSAGE_TYPE_INPUT_STREAM_IDS =
+ Constants.FrontendScanMessageType.INPUT_STREAM_IDS;
+ public static final int SCAN_MESSAGE_TYPE_STANDARD =
+ Constants.FrontendScanMessageType.STANDARD;
+ public static final int SCAN_MESSAGE_TYPE_ATSC3_PLP_INFO =
+ Constants.FrontendScanMessageType.ATSC3_PLP_INFO;
+
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({FRONTEND_STATUS_TYPE_DEMOD_LOCK, FRONTEND_STATUS_TYPE_SNR, FRONTEND_STATUS_TYPE_BER,
+ FRONTEND_STATUS_TYPE_PER, FRONTEND_STATUS_TYPE_PRE_BER,
+ FRONTEND_STATUS_TYPE_SIGNAL_QUALITY, FRONTEND_STATUS_TYPE_SIGNAL_STRENGTH,
+ FRONTEND_STATUS_TYPE_SYMBOL_RATE, FRONTEND_STATUS_TYPE_FEC,
+ FRONTEND_STATUS_TYPE_MODULATION, FRONTEND_STATUS_TYPE_SPECTRAL,
+ FRONTEND_STATUS_TYPE_LNB_VOLTAGE, FRONTEND_STATUS_TYPE_PLP_ID,
+ FRONTEND_STATUS_TYPE_EWBS, FRONTEND_STATUS_TYPE_AGC, FRONTEND_STATUS_TYPE_LNA,
+ FRONTEND_STATUS_TYPE_LAYER_ERROR, FRONTEND_STATUS_TYPE_VBER_CN,
+ FRONTEND_STATUS_TYPE_LBER_CN, FRONTEND_STATUS_TYPE_XER_CN, FRONTEND_STATUS_TYPE_MER,
+ FRONTEND_STATUS_TYPE_FREQ_OFFSET, FRONTEND_STATUS_TYPE_HIERARCHY,
+ FRONTEND_STATUS_TYPE_RF_LOCK, FRONTEND_STATUS_TYPE_ATSC3_PLP_INFO})
+ public @interface FrontendStatusType {}
+
+ /**
+ * Lock status for Demod.
+ */
+ public static final int FRONTEND_STATUS_TYPE_DEMOD_LOCK =
+ Constants.FrontendStatusType.DEMOD_LOCK;
+ /**
+ * Signal to Noise Ratio.
+ */
+ public static final int FRONTEND_STATUS_TYPE_SNR = Constants.FrontendStatusType.SNR;
+ /**
+ * Bit Error Ratio.
+ */
+ public static final int FRONTEND_STATUS_TYPE_BER = Constants.FrontendStatusType.BER;
+ /**
+ * Packages Error Ratio.
+ */
+ public static final int FRONTEND_STATUS_TYPE_PER = Constants.FrontendStatusType.PER;
+ /**
+ * Bit Error Ratio before FEC.
+ */
+ public static final int FRONTEND_STATUS_TYPE_PRE_BER = Constants.FrontendStatusType.PRE_BER;
+ /**
+ * Signal Quality (0..100). Good data over total data in percent can be
+ * used as a way to present Signal Quality.
+ */
+ public static final int FRONTEND_STATUS_TYPE_SIGNAL_QUALITY =
+ Constants.FrontendStatusType.SIGNAL_QUALITY;
+ /**
+ * Signal Strength.
+ */
+ public static final int FRONTEND_STATUS_TYPE_SIGNAL_STRENGTH =
+ Constants.FrontendStatusType.SIGNAL_STRENGTH;
+ /**
+ * Symbol Rate.
+ */
+ public static final int FRONTEND_STATUS_TYPE_SYMBOL_RATE =
+ Constants.FrontendStatusType.SYMBOL_RATE;
+ /**
+ * Forward Error Correction Type.
+ */
+ public static final int FRONTEND_STATUS_TYPE_FEC = Constants.FrontendStatusType.FEC;
+ /**
+ * Modulation Type.
+ */
+ public static final int FRONTEND_STATUS_TYPE_MODULATION =
+ Constants.FrontendStatusType.MODULATION;
+ /**
+ * Spectral Inversion Type.
+ */
+ public static final int FRONTEND_STATUS_TYPE_SPECTRAL = Constants.FrontendStatusType.SPECTRAL;
+ /**
+ * LNB Voltage.
+ */
+ public static final int FRONTEND_STATUS_TYPE_LNB_VOLTAGE =
+ Constants.FrontendStatusType.LNB_VOLTAGE;
+ /**
+ * Physical Layer Pipe ID.
+ */
+ public static final int FRONTEND_STATUS_TYPE_PLP_ID = Constants.FrontendStatusType.PLP_ID;
+ /**
+ * Status for Emergency Warning Broadcasting System.
+ */
+ public static final int FRONTEND_STATUS_TYPE_EWBS = Constants.FrontendStatusType.EWBS;
+ /**
+ * Automatic Gain Control.
+ */
+ public static final int FRONTEND_STATUS_TYPE_AGC = Constants.FrontendStatusType.AGC;
+ /**
+ * Low Noise Amplifier.
+ */
+ public static final int FRONTEND_STATUS_TYPE_LNA = Constants.FrontendStatusType.LNA;
+ /**
+ * Error status by layer.
+ */
+ public static final int FRONTEND_STATUS_TYPE_LAYER_ERROR =
+ Constants.FrontendStatusType.LAYER_ERROR;
+ /**
+ * CN value by VBER.
+ */
+ public static final int FRONTEND_STATUS_TYPE_VBER_CN = Constants.FrontendStatusType.VBER_CN;
+ /**
+ * CN value by LBER.
+ */
+ public static final int FRONTEND_STATUS_TYPE_LBER_CN = Constants.FrontendStatusType.LBER_CN;
+ /**
+ * CN value by XER.
+ */
+ public static final int FRONTEND_STATUS_TYPE_XER_CN = Constants.FrontendStatusType.XER_CN;
+ /**
+ * Moduration Error Ratio.
+ */
+ public static final int FRONTEND_STATUS_TYPE_MER = Constants.FrontendStatusType.MER;
+ /**
+ * Difference between tuning frequency and actual locked frequency.
+ */
+ public static final int FRONTEND_STATUS_TYPE_FREQ_OFFSET =
+ Constants.FrontendStatusType.FREQ_OFFSET;
+ /**
+ * Hierarchy for DVBT.
+ */
+ public static final int FRONTEND_STATUS_TYPE_HIERARCHY = Constants.FrontendStatusType.HIERARCHY;
+ /**
+ * Lock status for RF.
+ */
+ public static final int FRONTEND_STATUS_TYPE_RF_LOCK = Constants.FrontendStatusType.RF_LOCK;
+ /**
+ * PLP information in a frequency band for ATSC3.0 frontend.
+ */
+ public static final int FRONTEND_STATUS_TYPE_ATSC3_PLP_INFO =
+ Constants.FrontendStatusType.ATSC3_PLP_INFO;
+
+
+ @Retention(RetentionPolicy.SOURCE)
+ @LongDef({FEC_UNDEFINED, FEC_AUTO, FEC_1_2, FEC_1_3, FEC_1_4, FEC_1_5, FEC_2_3, FEC_2_5,
+ FEC_2_9, FEC_3_4, FEC_3_5, FEC_4_5, FEC_4_15, FEC_5_6, FEC_5_9, FEC_6_7, FEC_7_8,
+ FEC_7_9, FEC_7_15, FEC_8_9, FEC_8_15, FEC_9_10, FEC_9_20, FEC_11_15, FEC_11_20,
+ FEC_11_45, FEC_13_18, FEC_13_45, FEC_14_45, FEC_23_36, FEC_25_36, FEC_26_45, FEC_28_45,
+ FEC_29_45, FEC_31_45, FEC_32_45, FEC_77_90})
+ public @interface FrontendInnerFec {}
+
+ /**
+ * FEC not defined
+ */
+ public static final long FEC_UNDEFINED = Constants.FrontendInnerFec.FEC_UNDEFINED;
+ /**
+ * hardware is able to detect and set FEC automatically
+ */
+ public static final long FEC_AUTO = Constants.FrontendInnerFec.AUTO;
+ /**
+ * 1/2 conv. code rate
+ */
+ public static final long FEC_1_2 = Constants.FrontendInnerFec.FEC_1_2;
+ /**
+ * 1/3 conv. code rate
+ */
+ public static final long FEC_1_3 = Constants.FrontendInnerFec.FEC_1_3;
+ /**
+ * 1/4 conv. code rate
+ */
+ public static final long FEC_1_4 = Constants.FrontendInnerFec.FEC_1_4;
+ /**
+ * 1/5 conv. code rate
+ */
+ public static final long FEC_1_5 = Constants.FrontendInnerFec.FEC_1_5;
+ /**
+ * 2/3 conv. code rate
+ */
+ public static final long FEC_2_3 = Constants.FrontendInnerFec.FEC_2_3;
+ /**
+ * 2/5 conv. code rate
+ */
+ public static final long FEC_2_5 = Constants.FrontendInnerFec.FEC_2_5;
+ /**
+ * 2/9 conv. code rate
+ */
+ public static final long FEC_2_9 = Constants.FrontendInnerFec.FEC_2_9;
+ /**
+ * 3/4 conv. code rate
+ */
+ public static final long FEC_3_4 = Constants.FrontendInnerFec.FEC_3_4;
+ /**
+ * 3/5 conv. code rate
+ */
+ public static final long FEC_3_5 = Constants.FrontendInnerFec.FEC_3_5;
+ /**
+ * 4/5 conv. code rate
+ */
+ public static final long FEC_4_5 = Constants.FrontendInnerFec.FEC_4_5;
+ /**
+ * 4/15 conv. code rate
+ */
+ public static final long FEC_4_15 = Constants.FrontendInnerFec.FEC_4_15;
+ /**
+ * 5/6 conv. code rate
+ */
+ public static final long FEC_5_6 = Constants.FrontendInnerFec.FEC_5_6;
+ /**
+ * 5/9 conv. code rate
+ */
+ public static final long FEC_5_9 = Constants.FrontendInnerFec.FEC_5_9;
+ /**
+ * 6/7 conv. code rate
+ */
+ public static final long FEC_6_7 = Constants.FrontendInnerFec.FEC_6_7;
+ /**
+ * 7/8 conv. code rate
+ */
+ public static final long FEC_7_8 = Constants.FrontendInnerFec.FEC_7_8;
+ /**
+ * 7/9 conv. code rate
+ */
+ public static final long FEC_7_9 = Constants.FrontendInnerFec.FEC_7_9;
+ /**
+ * 7/15 conv. code rate
+ */
+ public static final long FEC_7_15 = Constants.FrontendInnerFec.FEC_7_15;
+ /**
+ * 8/9 conv. code rate
+ */
+ public static final long FEC_8_9 = Constants.FrontendInnerFec.FEC_8_9;
+ /**
+ * 8/15 conv. code rate
+ */
+ public static final long FEC_8_15 = Constants.FrontendInnerFec.FEC_8_15;
+ /**
+ * 9/10 conv. code rate
+ */
+ public static final long FEC_9_10 = Constants.FrontendInnerFec.FEC_9_10;
+ /**
+ * 9/20 conv. code rate
+ */
+ public static final long FEC_9_20 = Constants.FrontendInnerFec.FEC_9_20;
+ /**
+ * 11/15 conv. code rate
+ */
+ public static final long FEC_11_15 = Constants.FrontendInnerFec.FEC_11_15;
+ /**
+ * 11/20 conv. code rate
+ */
+ public static final long FEC_11_20 = Constants.FrontendInnerFec.FEC_11_20;
+ /**
+ * 11/45 conv. code rate
+ */
+ public static final long FEC_11_45 = Constants.FrontendInnerFec.FEC_11_45;
+ /**
+ * 13/18 conv. code rate
+ */
+ public static final long FEC_13_18 = Constants.FrontendInnerFec.FEC_13_18;
+ /**
+ * 13/45 conv. code rate
+ */
+ public static final long FEC_13_45 = Constants.FrontendInnerFec.FEC_13_45;
+ /**
+ * 14/45 conv. code rate
+ */
+ public static final long FEC_14_45 = Constants.FrontendInnerFec.FEC_14_45;
+ /**
+ * 23/36 conv. code rate
+ */
+ public static final long FEC_23_36 = Constants.FrontendInnerFec.FEC_23_36;
+ /**
+ * 25/36 conv. code rate
+ */
+ public static final long FEC_25_36 = Constants.FrontendInnerFec.FEC_25_36;
+ /**
+ * 26/45 conv. code rate
+ */
+ public static final long FEC_26_45 = Constants.FrontendInnerFec.FEC_26_45;
+ /**
+ * 28/45 conv. code rate
+ */
+ public static final long FEC_28_45 = Constants.FrontendInnerFec.FEC_28_45;
+ /**
+ * 29/45 conv. code rate
+ */
+ public static final long FEC_29_45 = Constants.FrontendInnerFec.FEC_29_45;
+ /**
+ * 31/45 conv. code rate
+ */
+ public static final long FEC_31_45 = Constants.FrontendInnerFec.FEC_31_45;
+ /**
+ * 32/45 conv. code rate
+ */
+ public static final long FEC_32_45 = Constants.FrontendInnerFec.FEC_32_45;
+ /**
+ * 77/90 conv. code rate
+ */
+ public static final long FEC_77_90 = Constants.FrontendInnerFec.FEC_77_90;
+
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({DVBC_MODULATION_UNDEFINED, DVBC_MODULATION_AUTO, DVBC_MODULATION_MOD_16QAM,
+ DVBC_MODULATION_MOD_32QAM, DVBC_MODULATION_MOD_64QAM, DVBC_MODULATION_MOD_128QAM,
+ DVBC_MODULATION_MOD_256QAM, DVBS_MODULATION_UNDEFINED, DVBS_MODULATION_AUTO,
+ DVBS_MODULATION_MOD_QPSK, DVBS_MODULATION_MOD_8PSK, DVBS_MODULATION_MOD_16QAM,
+ DVBS_MODULATION_MOD_16PSK, DVBS_MODULATION_MOD_32PSK, DVBS_MODULATION_MOD_ACM,
+ DVBS_MODULATION_MOD_8APSK, DVBS_MODULATION_MOD_16APSK, DVBS_MODULATION_MOD_32APSK,
+ DVBS_MODULATION_MOD_64APSK, DVBS_MODULATION_MOD_128APSK, DVBS_MODULATION_MOD_256APSK,
+ DVBS_MODULATION_MOD_RESERVED, ISDBS_MODULATION_UNDEFINED, ISDBS_MODULATION_AUTO,
+ ISDBS_MODULATION_MOD_BPSK, ISDBS_MODULATION_MOD_QPSK, ISDBS_MODULATION_MOD_TC8PSK,
+ ISDBS3_MODULATION_UNDEFINED, ISDBS3_MODULATION_AUTO, ISDBS3_MODULATION_MOD_BPSK,
+ ISDBS3_MODULATION_MOD_QPSK, ISDBS3_MODULATION_MOD_8PSK, ISDBS3_MODULATION_MOD_16APSK,
+ ISDBS3_MODULATION_MOD_32APSK, ISDBT_MODULATION_UNDEFINED, ISDBT_MODULATION_AUTO,
+ ISDBT_MODULATION_MOD_DQPSK, ISDBT_MODULATION_MOD_QPSK, ISDBT_MODULATION_MOD_16QAM,
+ ISDBT_MODULATION_MOD_64QAM})
+ public @interface FrontendModulation {}
+
+ public static final int DVBC_MODULATION_UNDEFINED = Constants.FrontendDvbcModulation.UNDEFINED;
+ public static final int DVBC_MODULATION_AUTO = Constants.FrontendDvbcModulation.AUTO;
+ public static final int DVBC_MODULATION_MOD_16QAM = Constants.FrontendDvbcModulation.MOD_16QAM;
+ public static final int DVBC_MODULATION_MOD_32QAM = Constants.FrontendDvbcModulation.MOD_32QAM;
+ public static final int DVBC_MODULATION_MOD_64QAM = Constants.FrontendDvbcModulation.MOD_64QAM;
+ public static final int DVBC_MODULATION_MOD_128QAM =
+ Constants.FrontendDvbcModulation.MOD_128QAM;
+ public static final int DVBC_MODULATION_MOD_256QAM =
+ Constants.FrontendDvbcModulation.MOD_256QAM;
+ public static final int DVBS_MODULATION_UNDEFINED = Constants.FrontendDvbsModulation.UNDEFINED;
+ public static final int DVBS_MODULATION_AUTO = Constants.FrontendDvbsModulation.AUTO;
+ public static final int DVBS_MODULATION_MOD_QPSK = Constants.FrontendDvbsModulation.MOD_QPSK;
+ public static final int DVBS_MODULATION_MOD_8PSK = Constants.FrontendDvbsModulation.MOD_8PSK;
+ public static final int DVBS_MODULATION_MOD_16QAM = Constants.FrontendDvbsModulation.MOD_16QAM;
+ public static final int DVBS_MODULATION_MOD_16PSK = Constants.FrontendDvbsModulation.MOD_16PSK;
+ public static final int DVBS_MODULATION_MOD_32PSK = Constants.FrontendDvbsModulation.MOD_32PSK;
+ public static final int DVBS_MODULATION_MOD_ACM = Constants.FrontendDvbsModulation.MOD_ACM;
+ public static final int DVBS_MODULATION_MOD_8APSK = Constants.FrontendDvbsModulation.MOD_8APSK;
+ public static final int DVBS_MODULATION_MOD_16APSK =
+ Constants.FrontendDvbsModulation.MOD_16APSK;
+ public static final int DVBS_MODULATION_MOD_32APSK =
+ Constants.FrontendDvbsModulation.MOD_32APSK;
+ public static final int DVBS_MODULATION_MOD_64APSK =
+ Constants.FrontendDvbsModulation.MOD_64APSK;
+ public static final int DVBS_MODULATION_MOD_128APSK =
+ Constants.FrontendDvbsModulation.MOD_128APSK;
+ public static final int DVBS_MODULATION_MOD_256APSK =
+ Constants.FrontendDvbsModulation.MOD_256APSK;
+ public static final int DVBS_MODULATION_MOD_RESERVED =
+ Constants.FrontendDvbsModulation.MOD_RESERVED;
+ public static final int ISDBS_MODULATION_UNDEFINED =
+ Constants.FrontendIsdbsModulation.UNDEFINED;
+ public static final int ISDBS_MODULATION_AUTO = Constants.FrontendIsdbsModulation.AUTO;
+ public static final int ISDBS_MODULATION_MOD_BPSK = Constants.FrontendIsdbsModulation.MOD_BPSK;
+ public static final int ISDBS_MODULATION_MOD_QPSK = Constants.FrontendIsdbsModulation.MOD_QPSK;
+ public static final int ISDBS_MODULATION_MOD_TC8PSK =
+ Constants.FrontendIsdbsModulation.MOD_TC8PSK;
+ public static final int ISDBS3_MODULATION_UNDEFINED =
+ Constants.FrontendIsdbs3Modulation.UNDEFINED;
+ public static final int ISDBS3_MODULATION_AUTO = Constants.FrontendIsdbs3Modulation.AUTO;
+ public static final int ISDBS3_MODULATION_MOD_BPSK =
+ Constants.FrontendIsdbs3Modulation.MOD_BPSK;
+ public static final int ISDBS3_MODULATION_MOD_QPSK =
+ Constants.FrontendIsdbs3Modulation.MOD_QPSK;
+ public static final int ISDBS3_MODULATION_MOD_8PSK =
+ Constants.FrontendIsdbs3Modulation.MOD_8PSK;
+ public static final int ISDBS3_MODULATION_MOD_16APSK =
+ Constants.FrontendIsdbs3Modulation.MOD_16APSK;
+ public static final int ISDBS3_MODULATION_MOD_32APSK =
+ Constants.FrontendIsdbs3Modulation.MOD_32APSK;
+ public static final int ISDBT_MODULATION_UNDEFINED =
+ Constants.FrontendIsdbtModulation.UNDEFINED;
+ public static final int ISDBT_MODULATION_AUTO = Constants.FrontendIsdbtModulation.AUTO;
+ public static final int ISDBT_MODULATION_MOD_DQPSK =
+ Constants.FrontendIsdbtModulation.MOD_DQPSK;
+ public static final int ISDBT_MODULATION_MOD_QPSK = Constants.FrontendIsdbtModulation.MOD_QPSK;
+ public static final int ISDBT_MODULATION_MOD_16QAM =
+ Constants.FrontendIsdbtModulation.MOD_16QAM;
+ public static final int ISDBT_MODULATION_MOD_64QAM =
+ Constants.FrontendIsdbtModulation.MOD_64QAM;
+
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({SPECTRAL_INVERSION_UNDEFINED, SPECTRAL_INVERSION_NORMAL, SPECTRAL_INVERSION_INVERTED})
+ public @interface FrontendDvbcSpectralInversion {}
+
+ public static final int SPECTRAL_INVERSION_UNDEFINED =
+ Constants.FrontendDvbcSpectralInversion.UNDEFINED;
+ public static final int SPECTRAL_INVERSION_NORMAL =
+ Constants.FrontendDvbcSpectralInversion.NORMAL;
+ public static final int SPECTRAL_INVERSION_INVERTED =
+ Constants.FrontendDvbcSpectralInversion.INVERTED;
+
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({HIERARCHY_UNDEFINED, HIERARCHY_AUTO, HIERARCHY_NON_NATIVE, HIERARCHY_1_NATIVE,
+ HIERARCHY_2_NATIVE, HIERARCHY_4_NATIVE, HIERARCHY_NON_INDEPTH, HIERARCHY_1_INDEPTH,
+ HIERARCHY_2_INDEPTH, HIERARCHY_4_INDEPTH})
+ public @interface FrontendDvbtHierarchy {}
+
+ public static final int HIERARCHY_UNDEFINED = Constants.FrontendDvbtHierarchy.UNDEFINED;
+ public static final int HIERARCHY_AUTO = Constants.FrontendDvbtHierarchy.AUTO;
+ public static final int HIERARCHY_NON_NATIVE =
+ Constants.FrontendDvbtHierarchy.HIERARCHY_NON_NATIVE;
+ public static final int HIERARCHY_1_NATIVE = Constants.FrontendDvbtHierarchy.HIERARCHY_1_NATIVE;
+ public static final int HIERARCHY_2_NATIVE = Constants.FrontendDvbtHierarchy.HIERARCHY_2_NATIVE;
+ public static final int HIERARCHY_4_NATIVE = Constants.FrontendDvbtHierarchy.HIERARCHY_4_NATIVE;
+ public static final int HIERARCHY_NON_INDEPTH =
+ Constants.FrontendDvbtHierarchy.HIERARCHY_NON_INDEPTH;
+ public static final int HIERARCHY_1_INDEPTH =
+ Constants.FrontendDvbtHierarchy.HIERARCHY_1_INDEPTH;
+ public static final int HIERARCHY_2_INDEPTH =
+ Constants.FrontendDvbtHierarchy.HIERARCHY_2_INDEPTH;
+ public static final int HIERARCHY_4_INDEPTH =
+ Constants.FrontendDvbtHierarchy.HIERARCHY_4_INDEPTH;
+
+
+ @Retention(RetentionPolicy.SOURCE)
@IntDef({FILTER_SETTINGS_TS, FILTER_SETTINGS_MMTP, FILTER_SETTINGS_IP, FILTER_SETTINGS_TLV,
FILTER_SETTINGS_ALP})
public @interface FilterSettingsType {}
@@ -108,6 +578,51 @@ final class TunerConstants {
public static final int DVR_SETTINGS_RECORD = Constants.DvrType.RECORD;
public static final int DVR_SETTINGS_PLAYBACK = Constants.DvrType.PLAYBACK;
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({LNB_VOLTAGE_NONE, LNB_VOLTAGE_5V, LNB_VOLTAGE_11V, LNB_VOLTAGE_12V, LNB_VOLTAGE_13V,
+ LNB_VOLTAGE_14V, LNB_VOLTAGE_15V, LNB_VOLTAGE_18V, LNB_VOLTAGE_19V})
+ public @interface LnbVoltage {}
+
+ public static final int LNB_VOLTAGE_NONE = Constants.LnbVoltage.NONE;
+ public static final int LNB_VOLTAGE_5V = Constants.LnbVoltage.VOLTAGE_5V;
+ public static final int LNB_VOLTAGE_11V = Constants.LnbVoltage.VOLTAGE_11V;
+ public static final int LNB_VOLTAGE_12V = Constants.LnbVoltage.VOLTAGE_12V;
+ public static final int LNB_VOLTAGE_13V = Constants.LnbVoltage.VOLTAGE_13V;
+ public static final int LNB_VOLTAGE_14V = Constants.LnbVoltage.VOLTAGE_14V;
+ public static final int LNB_VOLTAGE_15V = Constants.LnbVoltage.VOLTAGE_15V;
+ public static final int LNB_VOLTAGE_18V = Constants.LnbVoltage.VOLTAGE_18V;
+ public static final int LNB_VOLTAGE_19V = Constants.LnbVoltage.VOLTAGE_19V;
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({LNB_TONE_NONE, LNB_TONE_CONTINUOUS})
+ public @interface LnbTone {}
+
+ public static final int LNB_TONE_NONE = Constants.LnbTone.NONE;
+ public static final int LNB_TONE_CONTINUOUS = Constants.LnbTone.CONTINUOUS;
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({LNB_POSITION_UNDEFINED, LNB_POSITION_A, LNB_POSITION_B})
+ public @interface LnbPosition {}
+
+ public static final int LNB_POSITION_UNDEFINED = Constants.LnbPosition.UNDEFINED;
+ public static final int LNB_POSITION_A = Constants.LnbPosition.POSITION_A;
+ public static final int LNB_POSITION_B = Constants.LnbPosition.POSITION_B;
+
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({RESULT_SUCCESS, RESULT_UNAVAILABLE, RESULT_NOT_INITIALIZED, RESULT_INVALID_STATE,
+ RESULT_INVALID_ARGUMENT, RESULT_OUT_OF_MEMORY, RESULT_UNKNOWN_ERROR})
+ public @interface Result {}
+
+ public static final int RESULT_SUCCESS = Constants.Result.SUCCESS;
+ public static final int RESULT_UNAVAILABLE = Constants.Result.UNAVAILABLE;
+ public static final int RESULT_NOT_INITIALIZED = Constants.Result.NOT_INITIALIZED;
+ public static final int RESULT_INVALID_STATE = Constants.Result.INVALID_STATE;
+ public static final int RESULT_INVALID_ARGUMENT = Constants.Result.INVALID_ARGUMENT;
+ public static final int RESULT_OUT_OF_MEMORY = Constants.Result.OUT_OF_MEMORY;
+ public static final int RESULT_UNKNOWN_ERROR = Constants.Result.UNKNOWN_ERROR;
+
private TunerConstants() {
}
}
diff --git a/media/java/android/media/tv/tuner/TunerUtils.java b/media/java/android/media/tv/tuner/TunerUtils.java
new file mode 100644
index 000000000000..b3bd78076b60
--- /dev/null
+++ b/media/java/android/media/tv/tuner/TunerUtils.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.tv.tuner;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.hardware.tv.tuner.V1_0.Constants;
+import android.media.tv.tuner.TunerConstants.FilterSubtype;
+import android.media.tv.tuner.TunerConstants.FilterType;
+
+/**
+ * Utility class for tuner framework.
+ *
+ * @hide
+ */
+public final class TunerUtils {
+ private static final String PERMISSION = android.Manifest.permission.ACCESS_TV_TUNER;
+
+ static void checkTunerPermission(Context context) {
+ if (context.checkCallingOrSelfPermission(PERMISSION)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Caller must have " + PERMISSION + " permission.");
+ }
+ }
+
+ static int getFilterSubtype(@FilterType int mainType, @FilterSubtype int subtype) {
+ if (mainType == TunerConstants.FILTER_TYPE_TS) {
+ switch (subtype) {
+ case TunerConstants.FILTER_SUBTYPE_UNDEFINED:
+ return Constants.DemuxTsFilterType.UNDEFINED;
+ case TunerConstants.FILTER_SUBTYPE_SECTION:
+ return Constants.DemuxTsFilterType.SECTION;
+ case TunerConstants.FILTER_SUBTYPE_PES:
+ return Constants.DemuxTsFilterType.PES;
+ case TunerConstants.FILTER_SUBTYPE_TS:
+ return Constants.DemuxTsFilterType.TS;
+ case TunerConstants.FILTER_SUBTYPE_AUDIO:
+ return Constants.DemuxTsFilterType.AUDIO;
+ case TunerConstants.FILTER_SUBTYPE_VIDEO:
+ return Constants.DemuxTsFilterType.VIDEO;
+ case TunerConstants.FILTER_SUBTYPE_PCR:
+ return Constants.DemuxTsFilterType.PCR;
+ case TunerConstants.FILTER_SUBTYPE_RECORD:
+ return Constants.DemuxTsFilterType.RECORD;
+ case TunerConstants.FILTER_SUBTYPE_TEMI:
+ return Constants.DemuxTsFilterType.TEMI;
+ default:
+ break;
+ }
+ } else if (mainType == TunerConstants.FILTER_TYPE_MMTP) {
+ switch (subtype) {
+ case TunerConstants.FILTER_SUBTYPE_UNDEFINED:
+ return Constants.DemuxMmtpFilterType.UNDEFINED;
+ case TunerConstants.FILTER_SUBTYPE_SECTION:
+ return Constants.DemuxMmtpFilterType.SECTION;
+ case TunerConstants.FILTER_SUBTYPE_PES:
+ return Constants.DemuxMmtpFilterType.PES;
+ case TunerConstants.FILTER_SUBTYPE_MMPT:
+ return Constants.DemuxMmtpFilterType.MMTP;
+ case TunerConstants.FILTER_SUBTYPE_AUDIO:
+ return Constants.DemuxMmtpFilterType.AUDIO;
+ case TunerConstants.FILTER_SUBTYPE_VIDEO:
+ return Constants.DemuxMmtpFilterType.VIDEO;
+ case TunerConstants.FILTER_SUBTYPE_RECORD:
+ return Constants.DemuxMmtpFilterType.RECORD;
+ case TunerConstants.FILTER_SUBTYPE_DOWNLOAD:
+ return Constants.DemuxMmtpFilterType.DOWNLOAD;
+ default:
+ break;
+ }
+
+ } else if (mainType == TunerConstants.FILTER_TYPE_IP) {
+ switch (subtype) {
+ case TunerConstants.FILTER_SUBTYPE_UNDEFINED:
+ return Constants.DemuxIpFilterType.UNDEFINED;
+ case TunerConstants.FILTER_SUBTYPE_SECTION:
+ return Constants.DemuxIpFilterType.SECTION;
+ case TunerConstants.FILTER_SUBTYPE_NTP:
+ return Constants.DemuxIpFilterType.NTP;
+ case TunerConstants.FILTER_SUBTYPE_IP_PAYLOAD:
+ return Constants.DemuxIpFilterType.IP_PAYLOAD;
+ case TunerConstants.FILTER_SUBTYPE_IP:
+ return Constants.DemuxIpFilterType.IP;
+ case TunerConstants.FILTER_SUBTYPE_PAYLOAD_THROUGH:
+ return Constants.DemuxIpFilterType.PAYLOAD_THROUGH;
+ default:
+ break;
+ }
+ } else if (mainType == TunerConstants.FILTER_TYPE_TLV) {
+ switch (subtype) {
+ case TunerConstants.FILTER_SUBTYPE_UNDEFINED:
+ return Constants.DemuxTlvFilterType.UNDEFINED;
+ case TunerConstants.FILTER_SUBTYPE_SECTION:
+ return Constants.DemuxTlvFilterType.SECTION;
+ case TunerConstants.FILTER_SUBTYPE_TLV:
+ return Constants.DemuxTlvFilterType.TLV;
+ case TunerConstants.FILTER_SUBTYPE_PAYLOAD_THROUGH:
+ return Constants.DemuxTlvFilterType.PAYLOAD_THROUGH;
+ default:
+ break;
+ }
+ } else if (mainType == TunerConstants.FILTER_TYPE_ALP) {
+ switch (subtype) {
+ case TunerConstants.FILTER_SUBTYPE_UNDEFINED:
+ return Constants.DemuxAlpFilterType.UNDEFINED;
+ case TunerConstants.FILTER_SUBTYPE_SECTION:
+ return Constants.DemuxAlpFilterType.SECTION;
+ case TunerConstants.FILTER_SUBTYPE_PTP:
+ return Constants.DemuxAlpFilterType.PTP;
+ case TunerConstants.FILTER_SUBTYPE_PAYLOAD_THROUGH:
+ return Constants.DemuxAlpFilterType.PAYLOAD_THROUGH;
+ default:
+ break;
+ }
+ }
+ throw new IllegalArgumentException(
+ "Invalid filter types. Main type=" + mainType + ", subtype=" + subtype);
+ }
+
+ private TunerUtils() {}
+}
diff --git a/media/jni/android_media_MediaExtractor.h b/media/jni/android_media_MediaExtractor.h
index baa779c24b09..f5ba92e38455 100644
--- a/media/jni/android_media_MediaExtractor.h
+++ b/media/jni/android_media_MediaExtractor.h
@@ -19,7 +19,7 @@
#include <media/stagefright/foundation/ABase.h>
#include <media/stagefright/foundation/AudioPresentationInfo.h>
-#include <media/MediaSource.h>
+#include <media/stagefright/MediaSource.h>
#include <media/DataSource.h>
#include <utils/Errors.h>
#include <utils/KeyedVector.h>
diff --git a/media/jni/android_media_MediaMetricsJNI.cpp b/media/jni/android_media_MediaMetricsJNI.cpp
index e17a6173ba4d..c064de299b19 100644
--- a/media/jni/android_media_MediaMetricsJNI.cpp
+++ b/media/jni/android_media_MediaMetricsJNI.cpp
@@ -18,8 +18,10 @@
#include <binder/Parcel.h>
#include <jni.h>
+#include <media/IMediaMetricsService.h>
#include <media/MediaMetricsItem.h>
#include <nativehelper/JNIHelp.h>
+#include <variant>
#include "android_media_MediaMetricsJNI.h"
#include "android_os_Parcel.h"
@@ -74,18 +76,30 @@ struct BundleHelper {
}
template<>
- void put(jstring keyName, const char * const& value) {
- env->CallVoidMethod(bundle, putStringID, keyName, env->NewStringUTF(value));
+ void put(jstring keyName, const std::string& value) {
+ env->CallVoidMethod(bundle, putStringID, keyName, env->NewStringUTF(value.c_str()));
}
template<>
- void put(jstring keyName, char * const& value) {
+ void put(jstring keyName, const std::pair<int64_t, int64_t>& value) {
+ ; // rate is currently ignored
+ }
+
+ template<>
+ void put(jstring keyName, const std::monostate& value) {
+ ; // none is currently ignored
+ }
+
+ // string char * helpers
+
+ template<>
+ void put(jstring keyName, const char * const& value) {
env->CallVoidMethod(bundle, putStringID, keyName, env->NewStringUTF(value));
}
template<>
- void put(jstring keyName, const std::pair<int64_t, int64_t>& value) {
- ; // rate is currently ignored
+ void put(jstring keyName, char * const& value) {
+ env->CallVoidMethod(bundle, putStringID, keyName, env->NewStringUTF(value));
}
// We allow both jstring and non-jstring variants.
@@ -107,15 +121,15 @@ jobject MediaMetricsJNI::writeMetricsToBundle(
return nullptr;
}
- bh.put("__key", item->getKey().c_str());
+ bh.put(mediametrics::BUNDLE_KEY, item->getKey().c_str());
if (item->getPid() != -1) {
- bh.put("__pid", (int32_t)item->getPid());
+ bh.put(mediametrics::BUNDLE_PID, (int32_t)item->getPid());
}
if (item->getTimestamp() > 0) {
- bh.put("__timestamp", (int64_t)item->getTimestamp());
+ bh.put(mediametrics::BUNDLE_TIMESTAMP, (int64_t)item->getTimestamp());
}
if (item->getUid() != -1) {
- bh.put("__uid", (int32_t)item->getUid());
+ bh.put(mediametrics::BUNDLE_UID, (int32_t)item->getUid());
}
for (const auto &prop : *item) {
const char *name = prop.getName();
@@ -137,14 +151,12 @@ static jint android_media_MediaMetrics_submit_bytebuffer(
return (jint)BAD_VALUE;
}
- // TODO: directly record item to MediaMetrics service.
- mediametrics::Item item;
- if (item.readFromByteString((char *)buffer, length) != NO_ERROR) {
- ALOGW("%s: cannot read from byte string", __func__);
- return (jint)BAD_VALUE;
+ sp<IMediaMetricsService> service = mediametrics::BaseItem::getService();
+ if (service == nullptr) {
+ ALOGW("Cannot retrieve mediametrics service");
+ return (jint)NO_INIT;
}
- item.selfrecord();
- return (jint)NO_ERROR;
+ return (jint)service->submitBuffer((char *)buffer, length);
}
// Helper function to convert a native PersistableBundle to a Java
diff --git a/media/jni/android_media_MediaMuxer.cpp b/media/jni/android_media_MediaMuxer.cpp
index f0aa4c3f1ab6..0c1e9a2ad7bd 100644
--- a/media/jni/android_media_MediaMuxer.cpp
+++ b/media/jni/android_media_MediaMuxer.cpp
@@ -26,11 +26,15 @@
#include <unistd.h>
#include <fcntl.h>
+#include <android/api-level.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MediaMuxer.h>
+extern "C" int android_get_application_target_sdk_version();
+
namespace android {
struct fields_t {
@@ -229,10 +233,31 @@ static void android_media_MediaMuxer_stop(JNIEnv *env, jclass /* clazz */,
status_t err = muxer->stop();
- if (err != OK) {
- jniThrowException(env, "java/lang/IllegalStateException",
- "Failed to stop the muxer");
- return;
+ if (android_get_application_target_sdk_version() >= __ANDROID_API_R__) {
+ switch (err) {
+ case OK:
+ break;
+ case ERROR_IO: {
+ jniThrowException(env, "java/lang/UncheckedIOException",
+ "Muxer stopped unexpectedly");
+ return;
+ }
+ case ERROR_MALFORMED: {
+ jniThrowException(env, "java/io/IOError",
+ "Failure of reading or writing operation");
+ return;
+ }
+ default: {
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "Failed to stop the muxer");
+ return;
+ }
+ }
+ } else {
+ if (err != OK) {
+ jniThrowException(env, "java/lang/IllegalStateException", "Failed to stop the muxer");
+ return;
+ }
}
}
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index 9304450dc271..da52696506b5 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -312,6 +312,15 @@ int JTuner::tune(const FrontendSettings& settings) {
return (int)result;
}
+int JTuner::scan(const FrontendSettings& settings, FrontendScanType scanType) {
+ if (mFe == NULL) {
+ ALOGE("frontend is not initialized");
+ return (int)Result::INVALID_STATE;
+ }
+ Result result = mFe->scan(settings, scanType);
+ return (int)result;
+}
+
bool JTuner::openDemux() {
if (mTuner == nullptr) {
return false;
@@ -600,6 +609,33 @@ static int android_media_tv_Tuner_tune(JNIEnv *env, jobject thiz, jint type, job
return tuner->tune(getFrontendSettings(env, type, settings));
}
+static int android_media_tv_Tuner_stop_tune(JNIEnv*, jobject) {
+ return 0;
+}
+
+static int android_media_tv_Tuner_scan(
+ JNIEnv *env, jobject thiz, jint settingsType, jobject settings, jint scanType) {
+ sp<JTuner> tuner = getTuner(env, thiz);
+ return tuner->scan(getFrontendSettings(
+ env, settingsType, settings), static_cast<FrontendScanType>(scanType));
+}
+
+static int android_media_tv_Tuner_stop_scan(JNIEnv*, jobject) {
+ return 0;
+}
+
+static int android_media_tv_Tuner_set_lnb(JNIEnv*, jobject, jint) {
+ return 0;
+}
+
+static int android_media_tv_Tuner_set_lna(JNIEnv*, jobject, jint, jboolean) {
+ return 0;
+}
+
+static jobjectArray android_media_tv_Tuner_get_frontend_status(JNIEnv, jobject, jintArray) {
+ return NULL;
+}
+
static jobject android_media_tv_Tuner_get_lnb_ids(JNIEnv *env, jobject thiz) {
sp<JTuner> tuner = getTuner(env, thiz);
return tuner->getLnbIds();
@@ -715,31 +751,42 @@ static int android_media_tv_Tuner_configure_filter(
return (int)res;
}
-static bool android_media_tv_Tuner_start_filter(JNIEnv *env, jobject filter) {
+static int android_media_tv_Tuner_get_filter_id(JNIEnv*, jobject) {
+ return 0;
+}
+
+static int android_media_tv_Tuner_set_filter_data_source(JNIEnv*, jobject, jobject) {
+ return 0;
+}
+
+static int android_media_tv_Tuner_start_filter(JNIEnv *env, jobject filter) {
sp<IFilter> filterSp = getFilter(env, filter)->getIFilter();
if (filterSp == NULL) {
ALOGD("Failed to start filter: filter not found");
return false;
}
- return filterSp->start() == Result::SUCCESS;
+ Result r = filterSp->start();
+ return (int) r;
}
-static bool android_media_tv_Tuner_stop_filter(JNIEnv *env, jobject filter) {
+static int android_media_tv_Tuner_stop_filter(JNIEnv *env, jobject filter) {
sp<IFilter> filterSp = getFilter(env, filter)->getIFilter();
if (filterSp == NULL) {
ALOGD("Failed to stop filter: filter not found");
return false;
}
- return filterSp->stop() == Result::SUCCESS;
+ Result r = filterSp->stop();
+ return (int) r;
}
-static bool android_media_tv_Tuner_flush_filter(JNIEnv *env, jobject filter) {
+static int android_media_tv_Tuner_flush_filter(JNIEnv *env, jobject filter) {
sp<IFilter> filterSp = getFilter(env, filter)->getIFilter();
if (filterSp == NULL) {
ALOGD("Failed to flush filter: filter not found");
return false;
}
- return filterSp->flush() == Result::SUCCESS;
+ Result r = filterSp->flush();
+ return (int) r;
}
static int android_media_tv_Tuner_read_filter_fmq(
@@ -752,12 +799,16 @@ static int android_media_tv_Tuner_read_filter_fmq(
return copyData(env, filterSp, buffer, offset, size);
}
+static int android_media_tv_Tuner_close_filter(JNIEnv*, jobject) {
+ return 0;
+}
+
static jobject android_media_tv_Tuner_open_descrambler(JNIEnv *env, jobject thiz) {
sp<JTuner> tuner = getTuner(env, thiz);
return tuner->openDescrambler();
}
-static bool android_media_tv_Tuner_add_pid(
+static int android_media_tv_Tuner_add_pid(
JNIEnv *env, jobject descrambler, jint pidType, jint pid, jobject filter) {
sp<IDescrambler> descramblerSp = getDescrambler(env, descrambler);
if (descramblerSp == NULL) {
@@ -765,10 +816,10 @@ static bool android_media_tv_Tuner_add_pid(
}
sp<IFilter> filterSp = getFilter(env, filter)->getIFilter();
Result result = descramblerSp->addPid(getDemuxPid((int)pidType, (int)pid), filterSp);
- return result == Result::SUCCESS;
+ return (int)result;
}
-static bool android_media_tv_Tuner_remove_pid(
+static int android_media_tv_Tuner_remove_pid(
JNIEnv *env, jobject descrambler, jint pidType, jint pid, jobject filter) {
sp<IDescrambler> descramblerSp = getDescrambler(env, descrambler);
if (descramblerSp == NULL) {
@@ -776,7 +827,15 @@ static bool android_media_tv_Tuner_remove_pid(
}
sp<IFilter> filterSp = getFilter(env, filter)->getIFilter();
Result result = descramblerSp->removePid(getDemuxPid((int)pidType, (int)pid), filterSp);
- return result == Result::SUCCESS;
+ return (int)result;
+}
+
+static int android_media_tv_Tuner_set_key_token(JNIEnv, jobject, jbyteArray) {
+ return 0;
+}
+
+static int android_media_tv_Tuner_close_descrambler(JNIEnv, jobject) {
+ return 0;
}
static jobject android_media_tv_Tuner_open_dvr(JNIEnv *env, jobject thiz, jint type, jint bufferSize) {
@@ -784,24 +843,24 @@ static jobject android_media_tv_Tuner_open_dvr(JNIEnv *env, jobject thiz, jint t
return tuner->openDvr(static_cast<DvrType>(type), bufferSize);
}
-static bool android_media_tv_Tuner_attach_filter(JNIEnv *env, jobject dvr, jobject filter) {
+static int android_media_tv_Tuner_attach_filter(JNIEnv *env, jobject dvr, jobject filter) {
sp<IDvr> dvrSp = getDvr(env, dvr)->getIDvr();
sp<IFilter> filterSp = getFilter(env, filter)->getIFilter();
if (dvrSp == NULL || filterSp == NULL) {
return false;
}
Result result = dvrSp->attachFilter(filterSp);
- return result == Result::SUCCESS;
+ return (int) result;
}
-static bool android_media_tv_Tuner_detach_filter(JNIEnv *env, jobject dvr, jobject filter) {
+static int android_media_tv_Tuner_detach_filter(JNIEnv *env, jobject dvr, jobject filter) {
sp<IDvr> dvrSp = getDvr(env, dvr)->getIDvr();
sp<IFilter> filterSp = getFilter(env, filter)->getIFilter();
if (dvrSp == NULL || filterSp == NULL) {
return false;
}
Result result = dvrSp->detachFilter(filterSp);
- return result == Result::SUCCESS;
+ return (int) result;
}
static int android_media_tv_Tuner_configure_dvr(JNIEnv *env, jobject dvr, jobject settings) {
@@ -814,31 +873,58 @@ static int android_media_tv_Tuner_configure_dvr(JNIEnv *env, jobject dvr, jobjec
return (int)result;
}
-static bool android_media_tv_Tuner_start_dvr(JNIEnv *env, jobject dvr) {
+static int android_media_tv_Tuner_start_dvr(JNIEnv *env, jobject dvr) {
sp<IDvr> dvrSp = getDvr(env, dvr)->getIDvr();
if (dvrSp == NULL) {
ALOGD("Failed to start dvr: dvr not found");
return false;
}
- return dvrSp->start() == Result::SUCCESS;
+ Result result = dvrSp->start();
+ return (int) result;
}
-static bool android_media_tv_Tuner_stop_dvr(JNIEnv *env, jobject dvr) {
+static int android_media_tv_Tuner_stop_dvr(JNIEnv *env, jobject dvr) {
sp<IDvr> dvrSp = getDvr(env, dvr)->getIDvr();
if (dvrSp == NULL) {
ALOGD("Failed to stop dvr: dvr not found");
return false;
}
- return dvrSp->stop() == Result::SUCCESS;
+ Result result = dvrSp->stop();
+ return (int) result;
}
-static bool android_media_tv_Tuner_flush_dvr(JNIEnv *env, jobject dvr) {
+static int android_media_tv_Tuner_flush_dvr(JNIEnv *env, jobject dvr) {
sp<IDvr> dvrSp = getDvr(env, dvr)->getIDvr();
if (dvrSp == NULL) {
ALOGD("Failed to flush dvr: dvr not found");
return false;
}
- return dvrSp->flush() == Result::SUCCESS;
+ Result result = dvrSp->flush();
+ return (int) result;
+}
+
+static int android_media_tv_Tuner_close_dvr(JNIEnv*, jobject) {
+ return 0;
+}
+
+static int android_media_tv_Tuner_lnb_set_voltage(JNIEnv*, jobject, jint) {
+ return 0;
+}
+
+static int android_media_tv_Tuner_lnb_set_tone(JNIEnv*, jobject, jint) {
+ return 0;
+}
+
+static int android_media_tv_Tuner_lnb_set_position(JNIEnv*, jobject, jint) {
+ return 0;
+}
+
+static int android_media_tv_Tuner_lnb_send_diseqc_msg(JNIEnv*, jobject, jbyteArray) {
+ return 0;
+}
+
+static int android_media_tv_Tuner_close_lnb(JNIEnv*, jobject) {
+ return 0;
}
static const JNINativeMethod gTunerMethods[] = {
@@ -850,6 +936,14 @@ static const JNINativeMethod gTunerMethods[] = {
(void *)android_media_tv_Tuner_open_frontend_by_id },
{ "nativeTune", "(ILandroid/media/tv/tuner/FrontendSettings;)I",
(void *)android_media_tv_Tuner_tune },
+ { "nativeStopTune", "()I", (void *)android_media_tv_Tuner_stop_tune },
+ { "nativeScan", "(ILandroid/media/tv/tuner/FrontendSettings;I)I",
+ (void *)android_media_tv_Tuner_scan },
+ { "nativeStopScan", "()I", (void *)android_media_tv_Tuner_stop_scan },
+ { "nativeSetLnb", "(I)I", (void *)android_media_tv_Tuner_set_lnb },
+ { "nativeSetLna", "(Z)I", (void *)android_media_tv_Tuner_set_lna },
+ { "nativeGetFrontendStatus", "([I)[Landroid/media/tv/tuner/FrontendStatus;",
+ (void *)android_media_tv_Tuner_get_frontend_status },
{ "nativeOpenFilter", "(III)Landroid/media/tv/tuner/Tuner$Filter;",
(void *)android_media_tv_Tuner_open_filter },
{ "nativeGetLnbIds", "()Ljava/util/List;",
@@ -865,29 +959,44 @@ static const JNINativeMethod gTunerMethods[] = {
static const JNINativeMethod gFilterMethods[] = {
{ "nativeConfigureFilter", "(IILandroid/media/tv/tuner/FilterSettings;)I",
(void *)android_media_tv_Tuner_configure_filter },
- { "nativeStartFilter", "()Z", (void *)android_media_tv_Tuner_start_filter },
- { "nativeStopFilter", "()Z", (void *)android_media_tv_Tuner_stop_filter },
- { "nativeFlushFilter", "()Z", (void *)android_media_tv_Tuner_flush_filter },
+ { "nativeGetId", "()I", (void *)android_media_tv_Tuner_get_filter_id },
+ { "nativeSetDataSource", "(Landroid/media/tv/tuner/Tuner$Filter;)I",
+ (void *)android_media_tv_Tuner_set_filter_data_source },
+ { "nativeStartFilter", "()I", (void *)android_media_tv_Tuner_start_filter },
+ { "nativeStopFilter", "()I", (void *)android_media_tv_Tuner_stop_filter },
+ { "nativeFlushFilter", "()I", (void *)android_media_tv_Tuner_flush_filter },
{ "nativeRead", "([BII)I", (void *)android_media_tv_Tuner_read_filter_fmq },
+ { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_filter },
};
static const JNINativeMethod gDescramblerMethods[] = {
- { "nativeAddPid", "(IILandroid/media/tv/tuner/Tuner$Filter;)Z",
+ { "nativeAddPid", "(IILandroid/media/tv/tuner/Tuner$Filter;)I",
(void *)android_media_tv_Tuner_add_pid },
- { "nativeRemovePid", "(IILandroid/media/tv/tuner/Tuner$Filter;)Z",
+ { "nativeRemovePid", "(IILandroid/media/tv/tuner/Tuner$Filter;)I",
(void *)android_media_tv_Tuner_remove_pid },
+ { "nativeSetKeyToken", "([B)I", (void *)android_media_tv_Tuner_set_key_token },
+ { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_descrambler },
};
static const JNINativeMethod gDvrMethods[] = {
- { "nativeAttachFilter", "(Landroid/media/tv/tuner/Tuner$Filter;)Z",
+ { "nativeAttachFilter", "(Landroid/media/tv/tuner/Tuner$Filter;)I",
(void *)android_media_tv_Tuner_attach_filter },
- { "nativeDetachFilter", "(Landroid/media/tv/tuner/Tuner$Filter;)Z",
+ { "nativeDetachFilter", "(Landroid/media/tv/tuner/Tuner$Filter;)I",
(void *)android_media_tv_Tuner_detach_filter },
{ "nativeConfigureDvr", "(Landroid/media/tv/tuner/DvrSettings;)I",
(void *)android_media_tv_Tuner_configure_dvr },
- { "nativeStartDvr", "()Z", (void *)android_media_tv_Tuner_start_dvr },
- { "nativeStopDvr", "()Z", (void *)android_media_tv_Tuner_stop_dvr },
- { "nativeFlushDvr", "()Z", (void *)android_media_tv_Tuner_flush_dvr },
+ { "nativeStartDvr", "()I", (void *)android_media_tv_Tuner_start_dvr },
+ { "nativeStopDvr", "()I", (void *)android_media_tv_Tuner_stop_dvr },
+ { "nativeFlushDvr", "()I", (void *)android_media_tv_Tuner_flush_dvr },
+ { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_dvr },
+};
+
+static const JNINativeMethod gLnbMethods[] = {
+ { "nativeSetVoltage", "(I)I", (void *)android_media_tv_Tuner_lnb_set_voltage },
+ { "nativeSetTone", "(I)I", (void *)android_media_tv_Tuner_lnb_set_tone },
+ { "nativeSetSatellitePosition", "(I)I", (void *)android_media_tv_Tuner_lnb_set_position },
+ { "nativeSendDiseqcMessage", "([B)I", (void *)android_media_tv_Tuner_lnb_send_diseqc_msg },
+ { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_lnb },
};
static bool register_android_media_tv_Tuner(JNIEnv *env) {
@@ -917,6 +1026,13 @@ static bool register_android_media_tv_Tuner(JNIEnv *env) {
ALOGE("Failed to register dvr native methods");
return false;
}
+ if (AndroidRuntime::registerNativeMethods(
+ env, "android/media/tv/tuner/Tuner$Lnb",
+ gLnbMethods,
+ NELEM(gLnbMethods)) != JNI_OK) {
+ ALOGE("Failed to register lnb native methods");
+ return false;
+ }
return true;
}
diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h
index 9f9fb2748581..d37a2d96c60b 100644
--- a/media/jni/android_media_tv_Tuner.h
+++ b/media/jni/android_media_tv_Tuner.h
@@ -39,6 +39,7 @@ using ::android::hardware::tv::tuner::V1_0::FrontendEventType;
using ::android::hardware::tv::tuner::V1_0::FrontendId;
using ::android::hardware::tv::tuner::V1_0::FrontendScanMessage;
using ::android::hardware::tv::tuner::V1_0::FrontendScanMessageType;
+using ::android::hardware::tv::tuner::V1_0::FrontendScanType;
using ::android::hardware::tv::tuner::V1_0::FrontendSettings;
using ::android::hardware::tv::tuner::V1_0::IDemux;
using ::android::hardware::tv::tuner::V1_0::IDescrambler;
@@ -122,6 +123,7 @@ struct JTuner : public RefBase {
jobject getFrontendIds();
jobject openFrontendById(int id);
int tune(const FrontendSettings& settings);
+ int scan(const FrontendSettings& settings, FrontendScanType scanType);
jobject getLnbIds();
jobject openLnbById(int id);
jobject openFilter(DemuxFilterType type, int bufferSize);
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraErrorCollector.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraErrorCollector.java
index 6facec4bfe5b..41914b887b2b 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraErrorCollector.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraErrorCollector.java
@@ -969,7 +969,7 @@ public class CameraErrorCollector extends ErrorCollector {
*/
private static class IntInMatcher extends InMatcher<Integer> {
public IntInMatcher(int[] values) {
- Preconditions.checkNotNull("values", values);
+ Objects.requireNonNull(values, "values");
mValues = new ArrayList<>(values.length);
for (int i : values) {
mValues.add(i);
@@ -1005,7 +1005,7 @@ public class CameraErrorCollector extends ErrorCollector {
*/
private static class BooleanInMatcher extends InMatcher<Boolean> {
public BooleanInMatcher(boolean[] values) {
- Preconditions.checkNotNull("values", values);
+ Objects.requireNonNull(values, "values");
mValues = new ArrayList<>(values.length);
for (boolean i : values) {
mValues.add(i);
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/InMatcher.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/InMatcher.java
index e25a140378d8..c77a042ae38b 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/InMatcher.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/InMatcher.java
@@ -36,7 +36,7 @@ public class InMatcher<T> extends BaseMatcher<T> {
protected Collection<T> mValues;
public InMatcher(Collection<T> values) {
- Preconditions.checkNotNull("values", values);
+ Objects.requireNonNull(values, "values");
mValues = values;
}
diff --git a/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java b/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java
index 6650f9618638..04fccc7e0f94 100644
--- a/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java
+++ b/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java
@@ -16,12 +16,16 @@
package com.android.mediarouteprovider.example;
+import static android.media.MediaRoute2Info.DEVICE_TYPE_SPEAKER;
+import static android.media.MediaRoute2Info.DEVICE_TYPE_TV;
+
import android.content.Intent;
import android.media.MediaRoute2Info;
import android.media.MediaRoute2ProviderInfo;
import android.media.MediaRoute2ProviderService;
-import android.os.Bundle;
+import android.media.RouteSessionInfo;
import android.os.IBinder;
+import android.text.TextUtils;
import java.util.HashMap;
import java.util.Map;
@@ -33,6 +37,14 @@ public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService
public static final String ROUTE_NAME1 = "Sample Route 1";
public static final String ROUTE_ID2 = "route_id2";
public static final String ROUTE_NAME2 = "Sample Route 2";
+ public static final String ROUTE_ID3_SESSION_CREATION_FAILED =
+ "route_id3_session_creation_failed";
+ public static final String ROUTE_NAME3 = "Sample Route 3 - Session creation failed";
+ public static final String ROUTE_ID4_TO_SELECT_AND_DESELECT =
+ "route_id4_to_select_and_deselect";
+ public static final String ROUTE_NAME4 = "Sample Route 4 - Route to select and deselect";
+ public static final String ROUTE_ID5_TO_TRANSFER_TO = "route_id5_to_transfer_to";
+ public static final String ROUTE_NAME5 = "Sample Route 5 - Route to transfer to";
public static final String ROUTE_ID_SPECIAL_CATEGORY = "route_special_category";
public static final String ROUTE_NAME_SPECIAL_CATEGORY = "Special Category Route";
@@ -52,13 +64,29 @@ public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService
"com.android.mediarouteprovider.CATEGORY_SPECIAL";
Map<String, MediaRoute2Info> mRoutes = new HashMap<>();
+ Map<String, Integer> mRouteSessionMap = new HashMap<>();
+ private int mNextSessionId = 1000;
private void initializeRoutes() {
MediaRoute2Info route1 = new MediaRoute2Info.Builder(ROUTE_ID1, ROUTE_NAME1)
.addSupportedCategory(CATEGORY_SAMPLE)
+ .setDeviceType(DEVICE_TYPE_TV)
.build();
MediaRoute2Info route2 = new MediaRoute2Info.Builder(ROUTE_ID2, ROUTE_NAME2)
.addSupportedCategory(CATEGORY_SAMPLE)
+ .setDeviceType(DEVICE_TYPE_SPEAKER)
+ .build();
+ MediaRoute2Info route3 = new MediaRoute2Info.Builder(
+ ROUTE_ID3_SESSION_CREATION_FAILED, ROUTE_NAME3)
+ .addSupportedCategory(CATEGORY_SAMPLE)
+ .build();
+ MediaRoute2Info route4 = new MediaRoute2Info.Builder(
+ ROUTE_ID4_TO_SELECT_AND_DESELECT, ROUTE_NAME4)
+ .addSupportedCategory(CATEGORY_SAMPLE)
+ .build();
+ MediaRoute2Info route5 = new MediaRoute2Info.Builder(
+ ROUTE_ID5_TO_TRANSFER_TO, ROUTE_NAME5)
+ .addSupportedCategory(CATEGORY_SAMPLE)
.build();
MediaRoute2Info routeSpecial =
new MediaRoute2Info.Builder(ROUTE_ID_SPECIAL_CATEGORY, ROUTE_NAME_SPECIAL_CATEGORY)
@@ -79,6 +107,9 @@ public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService
mRoutes.put(route1.getId(), route1);
mRoutes.put(route2.getId(), route2);
+ mRoutes.put(route3.getId(), route3);
+ mRoutes.put(route4.getId(), route4);
+ mRoutes.put(route5.getId(), route5);
mRoutes.put(routeSpecial.getId(), routeSpecial);
mRoutes.put(fixedVolumeRoute.getId(), fixedVolumeRoute);
mRoutes.put(variableVolumeRoute.getId(), variableVolumeRoute);
@@ -96,73 +127,158 @@ public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService
}
@Override
- public void onSelectRoute(String packageName, String routeId, SelectToken token) {
+ public void onControlRequest(String routeId, Intent request) {
+ String action = request.getAction();
+ if (ACTION_REMOVE_ROUTE.equals(action)) {
+ MediaRoute2Info route = mRoutes.get(routeId);
+ if (route != null) {
+ mRoutes.remove(routeId);
+ publishRoutes();
+ mRoutes.put(routeId, route);
+ }
+ }
+ }
+
+ @Override
+ public void onSetVolume(String routeId, int volume) {
MediaRoute2Info route = mRoutes.get(routeId);
if (route == null) {
return;
}
+ volume = Math.min(volume, Math.max(0, route.getVolumeMax()));
mRoutes.put(routeId, new MediaRoute2Info.Builder(route)
- .setClientPackageName(packageName)
+ .setVolume(volume)
.build());
publishRoutes();
- notifyRouteSelected(token, Bundle.EMPTY);
}
@Override
- public void onUnselectRoute(String packageName, String routeId) {
+ public void onUpdateVolume(String routeId, int delta) {
MediaRoute2Info route = mRoutes.get(routeId);
if (route == null) {
return;
}
+ int volume = route.getVolume() + delta;
+ volume = Math.min(volume, Math.max(0, route.getVolumeMax()));
mRoutes.put(routeId, new MediaRoute2Info.Builder(route)
- .setClientPackageName(null)
+ .setVolume(volume)
.build());
publishRoutes();
}
@Override
- public void onControlRequest(String routeId, Intent request) {
- if (ACTION_REMOVE_ROUTE.equals(request.getAction())) {
+ public void onCreateSession(String packageName, String routeId, String controlCategory,
+ long requestId) {
+ MediaRoute2Info route = mRoutes.get(routeId);
+ if (route == null || TextUtils.equals(ROUTE_ID3_SESSION_CREATION_FAILED, routeId)) {
+ // Tell the router that session cannot be created by passing null as sessionInfo.
+ notifySessionCreated(/* sessionInfo= */ null, requestId);
+ return;
+ }
+ maybeDeselectRoute(routeId);
+
+ final int sessionId = mNextSessionId;
+ mNextSessionId++;
+
+ mRoutes.put(routeId, new MediaRoute2Info.Builder(route)
+ .setClientPackageName(packageName)
+ .build());
+ mRouteSessionMap.put(routeId, sessionId);
+
+ RouteSessionInfo sessionInfo = new RouteSessionInfo.Builder(
+ sessionId, packageName, controlCategory)
+ .addSelectedRoute(routeId)
+ .addSelectableRoute(ROUTE_ID4_TO_SELECT_AND_DESELECT)
+ .addTransferrableRoute(ROUTE_ID5_TO_TRANSFER_TO)
+ .build();
+ notifySessionCreated(sessionInfo, requestId);
+ publishRoutes();
+ }
+
+ @Override
+ public void onDestroySession(int sessionId, RouteSessionInfo lastSessionInfo) {
+ for (String routeId : lastSessionInfo.getSelectedRoutes()) {
+ mRouteSessionMap.remove(routeId);
MediaRoute2Info route = mRoutes.get(routeId);
if (route != null) {
- mRoutes.remove(routeId);
- publishRoutes();
- mRoutes.put(routeId, route);
+ mRoutes.put(routeId, new MediaRoute2Info.Builder(route)
+ .setClientPackageName(null)
+ .build());
}
}
}
@Override
- public void onSetVolume(String routeId, int volume) {
+ public void onSelectRoute(int sessionId, String routeId) {
+ RouteSessionInfo sessionInfo = getSessionInfo(sessionId);
MediaRoute2Info route = mRoutes.get(routeId);
- if (route == null) {
+ if (route == null || sessionInfo == null) {
return;
}
- volume = Math.min(volume, Math.max(0, route.getVolumeMax()));
+ maybeDeselectRoute(routeId);
+
mRoutes.put(routeId, new MediaRoute2Info.Builder(route)
- .setVolume(volume)
+ .setClientPackageName(sessionInfo.getPackageName())
.build());
- publishRoutes();
+ mRouteSessionMap.put(routeId, sessionId);
+
+ RouteSessionInfo newSessionInfo = new RouteSessionInfo.Builder(sessionInfo)
+ .addSelectedRoute(routeId)
+ .removeSelectableRoute(routeId)
+ .addDeselectableRoute(routeId)
+ .build();
+ updateSessionInfo(newSessionInfo);
+ notifySessionInfoChanged(newSessionInfo);
}
@Override
- public void onUpdateVolume(String routeId, int delta) {
+ public void onDeselectRoute(int sessionId, String routeId) {
+ RouteSessionInfo sessionInfo = getSessionInfo(sessionId);
MediaRoute2Info route = mRoutes.get(routeId);
- if (route == null) {
+
+ mRouteSessionMap.remove(routeId);
+ if (sessionInfo == null || route == null) {
return;
}
- int volume = route.getVolume() + delta;
- volume = Math.min(volume, Math.max(0, route.getVolumeMax()));
mRoutes.put(routeId, new MediaRoute2Info.Builder(route)
- .setVolume(volume)
+ .setClientPackageName(null)
.build());
- publishRoutes();
+
+ RouteSessionInfo newSessionInfo = new RouteSessionInfo.Builder(sessionInfo)
+ .removeSelectedRoute(routeId)
+ .addSelectableRoute(routeId)
+ .removeDeselectableRoute(routeId)
+ .build();
+ updateSessionInfo(newSessionInfo);
+ notifySessionInfoChanged(newSessionInfo);
+ }
+
+ @Override
+ public void onTransferToRoute(int sessionId, String routeId) {
+ RouteSessionInfo sessionInfo = getSessionInfo(sessionId);
+ RouteSessionInfo newSessionInfo = new RouteSessionInfo.Builder(sessionInfo)
+ .clearSelectedRoutes()
+ .addSelectedRoute(routeId)
+ .removeDeselectableRoute(routeId)
+ .removeTransferrableRoute(routeId)
+ .build();
+ updateSessionInfo(newSessionInfo);
+ notifySessionInfoChanged(newSessionInfo);
+ }
+
+ void maybeDeselectRoute(String routeId) {
+ if (!mRouteSessionMap.containsKey(routeId)) {
+ return;
+ }
+
+ int sessionId = mRouteSessionMap.get(routeId);
+ onDeselectRoute(sessionId, routeId);
}
void publishRoutes() {
MediaRoute2ProviderInfo info = new MediaRoute2ProviderInfo.Builder()
.addRoutes(mRoutes.values())
.build();
- setProviderInfo(info);
+ updateProviderInfo(info);
}
}
diff --git a/media/tests/MediaRouter/Android.bp b/media/tests/MediaRouter/Android.bp
index 611b25a2f128..5a0a50c2ae38 100644
--- a/media/tests/MediaRouter/Android.bp
+++ b/media/tests/MediaRouter/Android.bp
@@ -11,6 +11,7 @@ android_test {
static_libs: [
"android-support-test",
"mockito-target-minus-junit4",
+ "testng"
],
platform_apis: true,
diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2Test.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2Test.java
index 2c60d6b3dec7..10c17dc2c77b 100644
--- a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2Test.java
+++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2Test.java
@@ -16,38 +16,682 @@
package com.android.mediaroutertest;
+import static android.media.MediaRoute2Info.CONNECTION_STATE_CONNECTED;
+import static android.media.MediaRoute2Info.CONNECTION_STATE_CONNECTING;
+import static android.media.MediaRoute2Info.DEVICE_TYPE_SPEAKER;
+import static android.media.MediaRoute2Info.DEVICE_TYPE_TV;
+import static android.media.MediaRoute2Info.PLAYBACK_VOLUME_FIXED;
+import static android.media.MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE;
+
+import static com.android.mediaroutertest.MediaRouterManagerTest.CATEGORIES_ALL;
+import static com.android.mediaroutertest.MediaRouterManagerTest.CATEGORIES_SPECIAL;
+import static com.android.mediaroutertest.MediaRouterManagerTest.CATEGORY_SAMPLE;
+import static com.android.mediaroutertest.MediaRouterManagerTest.CATEGORY_SPECIAL;
+import static com.android.mediaroutertest.MediaRouterManagerTest.ROUTE_ID1;
+import static com.android.mediaroutertest.MediaRouterManagerTest.ROUTE_ID2;
+import static com.android.mediaroutertest.MediaRouterManagerTest.ROUTE_ID3_SESSION_CREATION_FAILED;
+import static com.android.mediaroutertest.MediaRouterManagerTest.ROUTE_ID4_TO_SELECT_AND_DESELECT;
+import static com.android.mediaroutertest.MediaRouterManagerTest.ROUTE_ID5_TO_TRANSFER_TO;
+import static com.android.mediaroutertest.MediaRouterManagerTest.ROUTE_ID_SPECIAL_CATEGORY;
+import static com.android.mediaroutertest.MediaRouterManagerTest.ROUTE_ID_VARIABLE_VOLUME;
+import static com.android.mediaroutertest.MediaRouterManagerTest.SYSTEM_PROVIDER_ID;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.testng.Assert.assertThrows;
+import android.annotation.NonNull;
import android.content.Context;
import android.media.MediaRoute2Info;
import android.media.MediaRouter2;
+import android.media.MediaRouter2.RouteCallback;
+import android.media.MediaRouter2.RouteSessionController;
+import android.media.MediaRouter2.SessionCallback;
+import android.media.RouteSessionInfo;
+import android.net.Uri;
+import android.os.Parcel;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
+import android.text.TextUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Predicate;
+
@RunWith(AndroidJUnit4.class)
@SmallTest
public class MediaRouter2Test {
+ private static final String TAG = "MediaRouter2Test";
Context mContext;
+ private MediaRouter2 mRouter2;
+ private Executor mExecutor;
+
+ private static final int TIMEOUT_MS = 5000;
@Before
public void setUp() throws Exception {
mContext = InstrumentationRegistry.getTargetContext();
+ mRouter2 = MediaRouter2.getInstance(mContext);
+ mExecutor = Executors.newSingleThreadExecutor();
}
@After
public void tearDown() throws Exception {
}
+ /**
+ * Tests if we get proper routes for application that has special control category.
+ */
+ @Test
+ public void testGetRoutes() throws Exception {
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutes(CATEGORIES_SPECIAL);
+
+ assertEquals(1, routes.size());
+ assertNotNull(routes.get(ROUTE_ID_SPECIAL_CATEGORY));
+ }
+
+ @Test
+ public void testRouteInfoEquality() {
+ MediaRoute2Info routeInfo = new MediaRoute2Info.Builder("id", "name")
+ .setDescription("description")
+ .setClientPackageName("com.android.mediaroutertest")
+ .setConnectionState(CONNECTION_STATE_CONNECTING)
+ .setIconUri(new Uri.Builder().path("icon").build())
+ .setVolume(5)
+ .setVolumeMax(20)
+ .addSupportedCategory(CATEGORY_SAMPLE)
+ .setVolumeHandling(PLAYBACK_VOLUME_VARIABLE)
+ .setDeviceType(DEVICE_TYPE_SPEAKER)
+ .build();
+
+ MediaRoute2Info routeInfoRebuilt = new MediaRoute2Info.Builder(routeInfo).build();
+ assertEquals(routeInfo, routeInfoRebuilt);
+
+ Parcel parcel = Parcel.obtain();
+ parcel.writeParcelable(routeInfo, 0);
+ parcel.setDataPosition(0);
+ MediaRoute2Info routeInfoFromParcel = parcel.readParcelable(null);
+
+ assertEquals(routeInfo, routeInfoFromParcel);
+ }
+
+ @Test
+ public void testRouteInfoInequality() {
+ MediaRoute2Info route = new MediaRoute2Info.Builder("id", "name")
+ .setDescription("description")
+ .setClientPackageName("com.android.mediaroutertest")
+ .setConnectionState(CONNECTION_STATE_CONNECTING)
+ .setIconUri(new Uri.Builder().path("icon").build())
+ .addSupportedCategory(CATEGORY_SAMPLE)
+ .setVolume(5)
+ .setVolumeMax(20)
+ .setVolumeHandling(PLAYBACK_VOLUME_VARIABLE)
+ .setDeviceType(DEVICE_TYPE_SPEAKER)
+ .build();
+
+ MediaRoute2Info routeId = new MediaRoute2Info.Builder(route)
+ .setId("another id").build();
+ assertNotEquals(route, routeId);
+
+ MediaRoute2Info routeName = new MediaRoute2Info.Builder(route)
+ .setName("another name").build();
+ assertNotEquals(route, routeName);
+
+ MediaRoute2Info routeDescription = new MediaRoute2Info.Builder(route)
+ .setDescription("another description").build();
+ assertNotEquals(route, routeDescription);
+
+ MediaRoute2Info routeConnectionState = new MediaRoute2Info.Builder(route)
+ .setConnectionState(CONNECTION_STATE_CONNECTED).build();
+ assertNotEquals(route, routeConnectionState);
+
+ MediaRoute2Info routeIcon = new MediaRoute2Info.Builder(route)
+ .setIconUri(new Uri.Builder().path("new icon").build()).build();
+ assertNotEquals(route, routeIcon);
+
+ MediaRoute2Info routeClient = new MediaRoute2Info.Builder(route)
+ .setClientPackageName("another.client.package").build();
+ assertNotEquals(route, routeClient);
+
+ MediaRoute2Info routeCategory = new MediaRoute2Info.Builder(route)
+ .addSupportedCategory(CATEGORY_SPECIAL).build();
+ assertNotEquals(route, routeCategory);
+
+ MediaRoute2Info routeVolume = new MediaRoute2Info.Builder(route)
+ .setVolume(10).build();
+ assertNotEquals(route, routeVolume);
+
+ MediaRoute2Info routeVolumeMax = new MediaRoute2Info.Builder(route)
+ .setVolumeMax(30).build();
+ assertNotEquals(route, routeVolumeMax);
+
+ MediaRoute2Info routeVolumeHandling = new MediaRoute2Info.Builder(route)
+ .setVolumeHandling(PLAYBACK_VOLUME_FIXED).build();
+ assertNotEquals(route, routeVolumeHandling);
+
+ MediaRoute2Info routeDeviceType = new MediaRoute2Info.Builder(route)
+ .setVolume(DEVICE_TYPE_TV).build();
+ assertNotEquals(route, routeDeviceType);
+ }
+
+ @Test
+ public void testControlVolumeWithRouter() throws Exception {
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutes(CATEGORIES_ALL);
+
+ MediaRoute2Info volRoute = routes.get(ROUTE_ID_VARIABLE_VOLUME);
+ assertNotNull(volRoute);
+
+ int originalVolume = volRoute.getVolume();
+ int deltaVolume = (originalVolume == volRoute.getVolumeMax() ? -1 : 1);
+
+ awaitOnRouteChanged(
+ () -> mRouter2.requestUpdateVolume(volRoute, deltaVolume),
+ ROUTE_ID_VARIABLE_VOLUME,
+ (route -> route.getVolume() == originalVolume + deltaVolume));
+
+ awaitOnRouteChanged(
+ () -> mRouter2.requestSetVolume(volRoute, originalVolume),
+ ROUTE_ID_VARIABLE_VOLUME,
+ (route -> route.getVolume() == originalVolume));
+ }
+
+ @Test
+ public void testRegisterSessionCallbackWithInvalidArguments() {
+ Executor executor = mExecutor;
+ SessionCallback callback = new SessionCallback();
+
+ // Tests null executor
+ assertThrows(NullPointerException.class,
+ () -> mRouter2.registerSessionCallback(null, callback));
+
+ // Tests null callback
+ assertThrows(NullPointerException.class,
+ () -> mRouter2.registerSessionCallback(executor, null));
+ }
+
+ @Test
+ public void testUnregisterSessionCallbackWithNullCallback() {
+ // Tests null callback
+ assertThrows(NullPointerException.class,
+ () -> mRouter2.unregisterSessionCallback(null));
+ }
+
+ @Test
+ public void testRequestCreateSessionWithInvalidArguments() {
+ MediaRoute2Info route = new MediaRoute2Info.Builder("id", "name").build();
+ String controlCategory = "controlCategory";
+
+ // Tests null route
+ assertThrows(NullPointerException.class,
+ () -> mRouter2.requestCreateSession(null, controlCategory));
+
+ // Tests null or empty control category
+ assertThrows(IllegalArgumentException.class,
+ () -> mRouter2.requestCreateSession(route, null));
+ assertThrows(IllegalArgumentException.class,
+ () -> mRouter2.requestCreateSession(route, ""));
+ }
+
+ @Test
+ public void testRequestCreateSessionSuccess() throws Exception {
+ final List<String> sampleControlCategory = new ArrayList<>();
+ sampleControlCategory.add(CATEGORY_SAMPLE);
+
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutes(sampleControlCategory);
+ MediaRoute2Info route = routes.get(ROUTE_ID1);
+ assertNotNull(route);
+
+ final CountDownLatch successLatch = new CountDownLatch(1);
+ final CountDownLatch failureLatch = new CountDownLatch(1);
+
+ // Create session with this route
+ SessionCallback sessionCallback = new SessionCallback() {
+ @Override
+ public void onSessionCreated(RouteSessionController controller) {
+ assertNotNull(controller);
+ assertTrue(createRouteMap(controller.getSelectedRoutes()).containsKey(ROUTE_ID1));
+ assertTrue(TextUtils.equals(CATEGORY_SAMPLE, controller.getControlCategory()));
+ successLatch.countDown();
+ }
+
+ @Override
+ public void onSessionCreationFailed(MediaRoute2Info requestedRoute,
+ String requestedControlCategory) {
+ failureLatch.countDown();
+ }
+ };
+
+ // TODO: Remove this once the MediaRouter2 becomes always connected to the service.
+ RouteCallback routeCallback = new RouteCallback();
+ mRouter2.registerRouteCallback(mExecutor, routeCallback);
+
+ try {
+ mRouter2.registerSessionCallback(mExecutor, sessionCallback);
+ mRouter2.requestCreateSession(route, CATEGORY_SAMPLE);
+ assertTrue(successLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+ // onSessionCreationFailed should not be called.
+ assertFalse(failureLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ } finally {
+ // TODO: Release controllers
+ mRouter2.unregisterRouteCallback(routeCallback);
+ mRouter2.unregisterSessionCallback(sessionCallback);
+ }
+ }
+
+ @Test
+ public void testRequestCreateSessionFailure() throws Exception {
+ final List<String> sampleControlCategory = new ArrayList<>();
+ sampleControlCategory.add(CATEGORY_SAMPLE);
+
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutes(sampleControlCategory);
+ MediaRoute2Info route = routes.get(ROUTE_ID3_SESSION_CREATION_FAILED);
+ assertNotNull(route);
+
+ final CountDownLatch successLatch = new CountDownLatch(1);
+ final CountDownLatch failureLatch = new CountDownLatch(1);
+
+ // Create session with this route
+ SessionCallback sessionCallback = new SessionCallback() {
+ @Override
+ public void onSessionCreated(RouteSessionController controller) {
+ successLatch.countDown();
+ }
+
+ @Override
+ public void onSessionCreationFailed(MediaRoute2Info requestedRoute,
+ String requestedControlCategory) {
+ assertEquals(route, requestedRoute);
+ assertTrue(TextUtils.equals(CATEGORY_SAMPLE, requestedControlCategory));
+ failureLatch.countDown();
+ }
+ };
+
+ // TODO: Remove this once the MediaRouter2 becomes always connected to the service.
+ RouteCallback routeCallback = new RouteCallback();
+ mRouter2.registerRouteCallback(mExecutor, routeCallback);
+
+ try {
+ mRouter2.registerSessionCallback(mExecutor, sessionCallback);
+ mRouter2.requestCreateSession(route, CATEGORY_SAMPLE);
+ assertTrue(failureLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+ // onSessionCreated should not be called.
+ assertFalse(successLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ } finally {
+ // TODO: Release controllers
+ mRouter2.unregisterRouteCallback(routeCallback);
+ mRouter2.unregisterSessionCallback(sessionCallback);
+ }
+ }
+
+ @Test
+ public void testRequestCreateSessionMultipleSessions() throws Exception {
+ final List<String> sampleControlCategory = new ArrayList<>();
+ sampleControlCategory.add(CATEGORY_SAMPLE);
+
+ final CountDownLatch successLatch = new CountDownLatch(2);
+ final CountDownLatch failureLatch = new CountDownLatch(1);
+
+ final List<RouteSessionController> createdControllers = new ArrayList<>();
+
+ // Create session with this route
+ SessionCallback sessionCallback = new SessionCallback() {
+ @Override
+ public void onSessionCreated(RouteSessionController controller) {
+ createdControllers.add(controller);
+ successLatch.countDown();
+ }
+
+ @Override
+ public void onSessionCreationFailed(MediaRoute2Info requestedRoute,
+ String requestedControlCategory) {
+ failureLatch.countDown();
+ }
+ };
+
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutes(sampleControlCategory);
+ MediaRoute2Info route1 = routes.get(ROUTE_ID1);
+ MediaRoute2Info route2 = routes.get(ROUTE_ID2);
+ assertNotNull(route1);
+ assertNotNull(route2);
+
+ // TODO: Remove this once the MediaRouter2 becomes always connected to the service.
+ RouteCallback routeCallback = new RouteCallback();
+ mRouter2.registerRouteCallback(mExecutor, routeCallback);
+
+ try {
+ mRouter2.registerSessionCallback(mExecutor, sessionCallback);
+ mRouter2.requestCreateSession(route1, CATEGORY_SAMPLE);
+ mRouter2.requestCreateSession(route2, CATEGORY_SAMPLE);
+ assertTrue(successLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+ // onSessionCreationFailed should not be called.
+ assertFalse(failureLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+ // Created controllers should have proper info
+ assertEquals(2, createdControllers.size());
+ RouteSessionController controller1 = createdControllers.get(0);
+ RouteSessionController controller2 = createdControllers.get(1);
+
+ assertNotEquals(controller1.getSessionId(), controller2.getSessionId());
+ assertTrue(createRouteMap(controller1.getSelectedRoutes()).containsKey(ROUTE_ID1));
+ assertTrue(createRouteMap(controller2.getSelectedRoutes()).containsKey(ROUTE_ID2));
+ assertTrue(TextUtils.equals(CATEGORY_SAMPLE, controller1.getControlCategory()));
+ assertTrue(TextUtils.equals(CATEGORY_SAMPLE, controller2.getControlCategory()));
+ } finally {
+ // TODO: Release controllers
+ mRouter2.unregisterRouteCallback(routeCallback);
+ mRouter2.unregisterSessionCallback(sessionCallback);
+ }
+ }
+
+ @Test
+ public void testSessionCallbackIsNotCalledAfterUnregistered() throws Exception {
+ final List<String> sampleControlCategory = new ArrayList<>();
+ sampleControlCategory.add(CATEGORY_SAMPLE);
+
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutes(sampleControlCategory);
+ MediaRoute2Info route = routes.get(ROUTE_ID1);
+ assertNotNull(route);
+
+ final CountDownLatch successLatch = new CountDownLatch(1);
+ final CountDownLatch failureLatch = new CountDownLatch(1);
+
+ // Create session with this route
+ SessionCallback sessionCallback = new SessionCallback() {
+ @Override
+ public void onSessionCreated(RouteSessionController controller) {
+ successLatch.countDown();
+ }
+
+ @Override
+ public void onSessionCreationFailed(MediaRoute2Info requestedRoute,
+ String requestedControlCategory) {
+ failureLatch.countDown();
+ }
+ };
+
+ // TODO: Remove this once the MediaRouter2 becomes always connected to the service.
+ RouteCallback routeCallback = new RouteCallback();
+ mRouter2.registerRouteCallback(mExecutor, routeCallback);
+
+ try {
+ mRouter2.registerSessionCallback(mExecutor, sessionCallback);
+ mRouter2.requestCreateSession(route, CATEGORY_SAMPLE);
+
+ // Unregisters session callback
+ mRouter2.unregisterSessionCallback(sessionCallback);
+
+ // No session callback methods should be called.
+ assertFalse(successLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ assertFalse(failureLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ } finally {
+ // TODO: Release controllers
+ mRouter2.unregisterRouteCallback(routeCallback);
+ mRouter2.unregisterSessionCallback(sessionCallback);
+ }
+ }
+
+ // TODO: Add tests for illegal inputs if needed (e.g. selecting already selected route)
+ @Test
+ public void testRouteSessionControllerSelectAndDeselectRoute() throws Exception {
+ final List<String> sampleControlCategory = new ArrayList<>();
+ sampleControlCategory.add(CATEGORY_SAMPLE);
+
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutes(sampleControlCategory);
+ MediaRoute2Info routeToCreateSessionWith = routes.get(ROUTE_ID1);
+ assertNotNull(routeToCreateSessionWith);
+
+ final CountDownLatch onSessionCreatedLatch = new CountDownLatch(1);
+ final CountDownLatch onSessionInfoChangedLatchForSelect = new CountDownLatch(1);
+ final CountDownLatch onSessionInfoChangedLatchForDeselect = new CountDownLatch(1);
+ final List<RouteSessionController> controllers = new ArrayList<>();
+
+ // Create session with ROUTE_ID1
+ SessionCallback sessionCallback = new SessionCallback() {
+ @Override
+ public void onSessionCreated(RouteSessionController controller) {
+ assertNotNull(controller);
+ assertTrue(getRouteIds(controller.getSelectedRoutes()).contains(ROUTE_ID1));
+ assertTrue(TextUtils.equals(CATEGORY_SAMPLE, controller.getControlCategory()));
+ controllers.add(controller);
+ onSessionCreatedLatch.countDown();
+ }
+
+ @Override
+ public void onSessionInfoChanged(RouteSessionController controller,
+ RouteSessionInfo oldInfo, RouteSessionInfo newInfo) {
+ if (onSessionCreatedLatch.getCount() != 0
+ || controllers.get(0).getSessionId() != controller.getSessionId()) {
+ return;
+ }
+
+ if (onSessionInfoChangedLatchForSelect.getCount() != 0) {
+ // Check oldInfo
+ assertEquals(controller.getSessionId(), oldInfo.getSessionId());
+ assertEquals(1, oldInfo.getSelectedRoutes().size());
+ assertTrue(oldInfo.getSelectedRoutes().contains(ROUTE_ID1));
+ assertTrue(oldInfo.getSelectableRoutes().contains(
+ ROUTE_ID4_TO_SELECT_AND_DESELECT));
+
+ // Check newInfo
+ assertEquals(controller.getSessionId(), newInfo.getSessionId());
+ assertEquals(2, newInfo.getSelectedRoutes().size());
+ assertTrue(newInfo.getSelectedRoutes().contains(ROUTE_ID1));
+ assertTrue(newInfo.getSelectedRoutes().contains(
+ ROUTE_ID4_TO_SELECT_AND_DESELECT));
+ assertFalse(newInfo.getSelectableRoutes().contains(
+ ROUTE_ID4_TO_SELECT_AND_DESELECT));
+
+ onSessionInfoChangedLatchForSelect.countDown();
+ } else {
+ // Check newInfo
+ assertEquals(controller.getSessionId(), newInfo.getSessionId());
+ assertEquals(1, newInfo.getSelectedRoutes().size());
+ assertTrue(newInfo.getSelectedRoutes().contains(ROUTE_ID1));
+ assertFalse(newInfo.getSelectedRoutes().contains(
+ ROUTE_ID4_TO_SELECT_AND_DESELECT));
+ assertTrue(newInfo.getSelectableRoutes().contains(
+ ROUTE_ID4_TO_SELECT_AND_DESELECT));
+
+ onSessionInfoChangedLatchForDeselect.countDown();
+ }
+ }
+ };
+
+ // TODO: Remove this once the MediaRouter2 becomes always connected to the service.
+ RouteCallback routeCallback = new RouteCallback();
+ mRouter2.registerRouteCallback(mExecutor, routeCallback);
+
+ try {
+ mRouter2.registerSessionCallback(mExecutor, sessionCallback);
+ mRouter2.requestCreateSession(routeToCreateSessionWith, CATEGORY_SAMPLE);
+ assertTrue(onSessionCreatedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+ assertEquals(1, controllers.size());
+ RouteSessionController controller = controllers.get(0);
+ assertTrue(getRouteIds(controller.getSelectableRoutes())
+ .contains(ROUTE_ID4_TO_SELECT_AND_DESELECT));
+
+ // Select ROUTE_ID4_TO_SELECT_AND_DESELECT
+ MediaRoute2Info routeToSelectAndDeselect = routes.get(
+ ROUTE_ID4_TO_SELECT_AND_DESELECT);
+ assertNotNull(routeToSelectAndDeselect);
+
+ controller.selectRoute(routeToSelectAndDeselect);
+ assertTrue(onSessionInfoChangedLatchForSelect.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+ controller.deselectRoute(routeToSelectAndDeselect);
+ assertTrue(onSessionInfoChangedLatchForDeselect.await(
+ TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ } finally {
+ // TODO: Release controllers
+ controllers.clear();
+ mRouter2.unregisterRouteCallback(routeCallback);
+ mRouter2.unregisterSessionCallback(sessionCallback);
+ }
+ }
+
@Test
- public void testGetSelectedRoute_afterCreation() throws Exception {
- MediaRouter2 router = MediaRouter2.getInstance(mContext);
- MediaRoute2Info initiallySelectedRoute = router.getSelectedRoute();
- assertNotNull(initiallySelectedRoute);
+ public void testRouteSessionControllerTransferToRoute() throws Exception {
+ final List<String> sampleControlCategory = new ArrayList<>();
+ sampleControlCategory.add(CATEGORY_SAMPLE);
+
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutes(sampleControlCategory);
+ MediaRoute2Info routeToCreateSessionWith = routes.get(ROUTE_ID1);
+ assertNotNull(routeToCreateSessionWith);
+
+ final CountDownLatch onSessionCreatedLatch = new CountDownLatch(1);
+ final CountDownLatch onSessionInfoChangedLatch = new CountDownLatch(1);
+ final List<RouteSessionController> controllers = new ArrayList<>();
+
+ // Create session with ROUTE_ID1
+ SessionCallback sessionCallback = new SessionCallback() {
+ @Override
+ public void onSessionCreated(RouteSessionController controller) {
+ assertNotNull(controller);
+ assertTrue(getRouteIds(controller.getSelectedRoutes()).contains(ROUTE_ID1));
+ assertTrue(TextUtils.equals(CATEGORY_SAMPLE, controller.getControlCategory()));
+ controllers.add(controller);
+ onSessionCreatedLatch.countDown();
+ }
+
+ @Override
+ public void onSessionInfoChanged(RouteSessionController controller,
+ RouteSessionInfo oldInfo, RouteSessionInfo newInfo) {
+ if (onSessionCreatedLatch.getCount() != 0
+ || controllers.get(0).getSessionId() != controller.getSessionId()) {
+ return;
+ }
+
+ // Check oldInfo
+ assertEquals(controller.getSessionId(), oldInfo.getSessionId());
+ assertEquals(1, oldInfo.getSelectedRoutes().size());
+ assertTrue(oldInfo.getSelectedRoutes().contains(ROUTE_ID1));
+ assertTrue(oldInfo.getTransferrableRoutes().contains(ROUTE_ID5_TO_TRANSFER_TO));
+
+ // Check newInfo
+ assertEquals(controller.getSessionId(), newInfo.getSessionId());
+ assertEquals(1, newInfo.getSelectedRoutes().size());
+ assertFalse(newInfo.getSelectedRoutes().contains(ROUTE_ID1));
+ assertTrue(newInfo.getSelectedRoutes().contains(ROUTE_ID5_TO_TRANSFER_TO));
+ assertFalse(newInfo.getTransferrableRoutes().contains(ROUTE_ID5_TO_TRANSFER_TO));
+
+ onSessionInfoChangedLatch.countDown();
+ }
+ };
+
+ // TODO: Remove this once the MediaRouter2 becomes always connected to the service.
+ RouteCallback routeCallback = new RouteCallback();
+ mRouter2.registerRouteCallback(mExecutor, routeCallback);
+
+ try {
+ mRouter2.registerSessionCallback(mExecutor, sessionCallback);
+ mRouter2.requestCreateSession(routeToCreateSessionWith, CATEGORY_SAMPLE);
+ assertTrue(onSessionCreatedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+ assertEquals(1, controllers.size());
+ RouteSessionController controller = controllers.get(0);
+ assertTrue(getRouteIds(controller.getTransferrableRoutes())
+ .contains(ROUTE_ID5_TO_TRANSFER_TO));
+
+ // Transfer to ROUTE_ID5_TO_TRANSFER_TO
+ MediaRoute2Info routeToTransferTo = routes.get(ROUTE_ID5_TO_TRANSFER_TO);
+ assertNotNull(routeToTransferTo);
+
+ controller.transferToRoute(routeToTransferTo);
+ assertTrue(onSessionInfoChangedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ } finally {
+ // TODO: Release controllers
+ controllers.clear();
+ mRouter2.unregisterRouteCallback(routeCallback);
+ mRouter2.unregisterSessionCallback(sessionCallback);
+ }
+
+ }
+
+ // Helper for getting routes easily
+ static Map<String, MediaRoute2Info> createRouteMap(List<MediaRoute2Info> routes) {
+ Map<String, MediaRoute2Info> routeMap = new HashMap<>();
+ for (MediaRoute2Info route : routes) {
+ // intentionally not using route.getUniqueId() for convenience.
+ routeMap.put(route.getId(), route);
+ }
+ return routeMap;
+ }
+
+ Map<String, MediaRoute2Info> waitAndGetRoutes(List<String> controlCategories)
+ throws Exception {
+ CountDownLatch latch = new CountDownLatch(1);
+
+ // A dummy callback is required to send control category info.
+ RouteCallback routeCallback = new RouteCallback() {
+ @Override
+ public void onRoutesAdded(List<MediaRoute2Info> routes) {
+ for (int i = 0; i < routes.size(); i++) {
+ //TODO: use isSystem() or similar method when it's ready
+ if (!TextUtils.equals(routes.get(i).getProviderId(), SYSTEM_PROVIDER_ID)) {
+ latch.countDown();
+ }
+ }
+ }
+ };
+
+ mRouter2.setControlCategories(controlCategories);
+ mRouter2.registerRouteCallback(mExecutor, routeCallback);
+ try {
+ latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ return createRouteMap(mRouter2.getRoutes());
+ } finally {
+ mRouter2.unregisterRouteCallback(routeCallback);
+ }
+ }
+
+ /**
+ * Returns a list of IDs (not uniqueId) of the given route list.
+ */
+ List<String> getRouteIds(@NonNull List<MediaRoute2Info> routes) {
+ List<String> result = new ArrayList<>();
+ for (MediaRoute2Info route : routes) {
+ result.add(route.getId());
+ }
+ return result;
+ }
+
+ void awaitOnRouteChanged(Runnable task, String routeId,
+ Predicate<MediaRoute2Info> predicate) throws Exception {
+ CountDownLatch latch = new CountDownLatch(1);
+ RouteCallback routeCallback = new RouteCallback() {
+ @Override
+ public void onRoutesChanged(List<MediaRoute2Info> changed) {
+ MediaRoute2Info route = createRouteMap(changed).get(routeId);
+ if (route != null && predicate.test(route)) {
+ latch.countDown();
+ }
+ }
+ };
+ mRouter2.registerRouteCallback(mExecutor, routeCallback);
+ try {
+ task.run();
+ assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ } finally {
+ mRouter2.unregisterRouteCallback(routeCallback);
+ }
}
}
diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
index c70ad8d8755c..83c7c173e8e8 100644
--- a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
+++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
@@ -28,8 +28,9 @@ import android.content.Context;
import android.content.Intent;
import android.media.MediaRoute2Info;
import android.media.MediaRouter2;
+import android.media.MediaRouter2.RouteCallback;
+import android.media.MediaRouter2.SessionCallback;
import android.media.MediaRouter2Manager;
-import android.os.Bundle;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
@@ -37,6 +38,7 @@ import android.text.TextUtils;
import org.junit.After;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -60,10 +62,21 @@ public class MediaRouterManagerTest {
public static final String ROUTE_NAME1 = "Sample Route 1";
public static final String ROUTE_ID2 = "route_id2";
public static final String ROUTE_NAME2 = "Sample Route 2";
+ public static final String ROUTE_ID3_SESSION_CREATION_FAILED =
+ "route_id3_session_creation_failed";
+ public static final String ROUTE_NAME3 = "Sample Route 3 - Session creation failed";
+ public static final String ROUTE_ID4_TO_SELECT_AND_DESELECT =
+ "route_id4_to_select_and_deselect";
+ public static final String ROUTE_NAME4 = "Sample Route 4 - Route to select and deselect";
+ public static final String ROUTE_ID5_TO_TRANSFER_TO = "route_id5_to_transfer_to";
+ public static final String ROUTE_NAME5 = "Sample Route 5 - Route to transfer to";
public static final String ROUTE_ID_SPECIAL_CATEGORY = "route_special_category";
public static final String ROUTE_NAME_SPECIAL_CATEGORY = "Special Category Route";
+ public static final String SYSTEM_PROVIDER_ID =
+ "com.android.server.media/.SystemMediaRoute2Provider";
+
public static final int VOLUME_MAX = 100;
public static final String ROUTE_ID_FIXED_VOLUME = "route_fixed_volume";
public static final String ROUTE_NAME_FIXED_VOLUME = "Fixed Volume Route";
@@ -78,10 +91,7 @@ public class MediaRouterManagerTest {
public static final String CATEGORY_SPECIAL =
"com.android.mediarouteprovider.CATEGORY_SPECIAL";
- // system routes
- private static final String DEFAULT_ROUTE_ID = "DEFAULT_ROUTE";
private static final String CATEGORY_LIVE_AUDIO = "android.media.intent.category.LIVE_AUDIO";
- private static final String CATEGORY_LIVE_VIDEO = "android.media.intent.category.LIVE_VIDEO";
private static final int TIMEOUT_MS = 5000;
@@ -92,11 +102,11 @@ public class MediaRouterManagerTest {
private String mPackageName;
private final List<MediaRouter2Manager.Callback> mManagerCallbacks = new ArrayList<>();
- private final List<MediaRouter2.Callback> mRouterCallbacks = new ArrayList<>();
- private Map<String, MediaRoute2Info> mRoutes;
+ private final List<RouteCallback> mRouteCallbacks = new ArrayList<>();
+ private final List<SessionCallback> mSessionCallbacks = new ArrayList<>();
- private static final List<String> CATEGORIES_ALL = new ArrayList();
- private static final List<String> CATEGORIES_SPECIAL = new ArrayList();
+ public static final List<String> CATEGORIES_ALL = new ArrayList();
+ public static final List<String> CATEGORIES_SPECIAL = new ArrayList();
private static final List<String> CATEGORIES_LIVE_AUDIO = new ArrayList<>();
static {
@@ -109,7 +119,6 @@ public class MediaRouterManagerTest {
CATEGORIES_LIVE_AUDIO.add(CATEGORY_LIVE_AUDIO);
}
-
@Before
public void setUp() throws Exception {
mContext = InstrumentationRegistry.getTargetContext();
@@ -118,10 +127,6 @@ public class MediaRouterManagerTest {
//TODO: If we need to support thread pool executors, change this to thread pool executor.
mExecutor = Executors.newSingleThreadExecutor();
mPackageName = mContext.getPackageName();
-
- // ensure media router 2 client
- addRouterCallback(new MediaRouter2.Callback());
- mRoutes = waitAndGetRoutesWithManager(CATEGORIES_ALL);
}
@After
@@ -168,6 +173,9 @@ public class MediaRouterManagerTest {
@Test
public void testOnRoutesRemoved() throws Exception {
CountDownLatch latch = new CountDownLatch(1);
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(CATEGORIES_ALL);
+
+ addRouterCallback(new RouteCallback());
addManagerCallback(new MediaRouter2Manager.Callback() {
@Override
public void onRoutesRemoved(List<MediaRoute2Info> routes) {
@@ -182,7 +190,7 @@ public class MediaRouterManagerTest {
//TODO: Figure out a more proper way to test.
// (Control requests shouldn't be used in this way.)
- mRouter2.sendControlRequest(mRoutes.get(ROUTE_ID2), new Intent(ACTION_REMOVE_ROUTE));
+ mRouter2.sendControlRequest(routes.get(ROUTE_ID2), new Intent(ACTION_REMOVE_ROUTE));
assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
}
@@ -198,38 +206,37 @@ public class MediaRouterManagerTest {
}
/**
- * Tests if we get proper routes for application that has special control category.
+ * Tests if MR2.SessionCallback.onSessionCreated is called
+ * when a route is selected from MR2Manager.
*/
@Test
- public void testGetRoutes() throws Exception {
- Map<String, MediaRoute2Info> routes = waitAndGetRoutes(CATEGORIES_SPECIAL);
+ public void testRouterOnSessionCreated() throws Exception {
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(CATEGORIES_ALL);
- assertEquals(1, routes.size());
- assertNotNull(routes.get(ROUTE_ID_SPECIAL_CATEGORY));
- }
-
- /**
- * Tests if MR2.Callback.onRouteSelected is called when a route is selected from MR2Manager.
- */
- @Test
- public void testRouterOnRouteSelected() throws Exception {
CountDownLatch latch = new CountDownLatch(1);
- addRouterCallback(new MediaRouter2.Callback() {
+ addManagerCallback(new MediaRouter2Manager.Callback());
+ //TODO: remove this when it's not necessary.
+ addRouterCallback(new MediaRouter2.RouteCallback());
+ addSessionCallback(new SessionCallback() {
@Override
- public void onRouteSelected(MediaRoute2Info route, int reason, Bundle controlHints) {
- if (route != null && TextUtils.equals(route.getId(), ROUTE_ID1)) {
+ public void onSessionCreated(MediaRouter2.RouteSessionController controller) {
+ if (createRouteMap(controller.getSelectedRoutes()).containsKey(ROUTE_ID1)) {
latch.countDown();
}
}
});
- MediaRoute2Info routeToSelect = mRoutes.get(ROUTE_ID1);
+ MediaRoute2Info routeToSelect = routes.get(ROUTE_ID1);
assertNotNull(routeToSelect);
- mManager.selectRoute(mPackageName, routeToSelect);
-
- assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ try {
+ mManager.selectRoute(mPackageName, routeToSelect);
+ assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ } finally {
+ //TODO: release the session
+ //mManager.selectRoute(mPackageName, null);
+ }
}
/**
@@ -237,9 +244,12 @@ public class MediaRouterManagerTest {
* when a route is selected by MR2Manager.
*/
@Test
+ @Ignore("TODO: test session created callback instead of onRouteSelected")
public void testManagerOnRouteSelected() throws Exception {
CountDownLatch latch = new CountDownLatch(1);
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(CATEGORIES_ALL);
+ addRouterCallback(new RouteCallback());
addManagerCallback(new MediaRouter2Manager.Callback() {
@Override
public void onRouteSelected(String packageName, MediaRoute2Info route) {
@@ -250,57 +260,87 @@ public class MediaRouterManagerTest {
}
});
- MediaRoute2Info routeToSelect = mRoutes.get(ROUTE_ID1);
+ MediaRoute2Info routeToSelect = routes.get(ROUTE_ID1);
assertNotNull(routeToSelect);
- mManager.selectRoute(mPackageName, routeToSelect);
+ try {
+ mManager.selectRoute(mPackageName, routeToSelect);
+ assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ } finally {
+ //TODO: release the session
+ //mManager.selectRoute(mPackageName, null);
+ }
+ }
- assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ @Test
+ @Ignore("TODO: enable this when 'releasing session' is implemented")
+ public void testGetActiveRoutes() throws Exception {
+ CountDownLatch latch = new CountDownLatch(1);
+
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(CATEGORIES_ALL);
+ addRouterCallback(new RouteCallback());
+ addManagerCallback(new MediaRouter2Manager.Callback() {
+ @Override
+ public void onRouteSelected(String packageName, MediaRoute2Info route) {
+ if (TextUtils.equals(mPackageName, packageName)
+ && route != null && TextUtils.equals(route.getId(), ROUTE_ID1)) {
+ latch.countDown();
+ }
+ }
+ });
+
+ //TODO: it fails due to not releasing session
+ assertEquals(0, mManager.getActiveSessions().size());
+
+ mManager.selectRoute(mPackageName, routes.get(ROUTE_ID1));
+ latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+
+ assertEquals(1, mManager.getActiveSessions().size());
+
+ //TODO: release the session
+ /*
+ awaitOnRouteChangedManager(
+ () -> mManager.selectRoute(mPackageName, null),
+ ROUTE_ID1,
+ route -> TextUtils.equals(route.getClientPackageName(), null));
+ assertEquals(0, mManager.getActiveRoutes().size());
+ */
}
/**
* Tests selecting and unselecting routes of a single provider.
*/
@Test
+ @Ignore("TODO: enable when session is released")
public void testSingleProviderSelect() throws Exception {
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(CATEGORIES_ALL);
+ addRouterCallback(new RouteCallback());
+
awaitOnRouteChangedManager(
- () -> mManager.selectRoute(mPackageName, mRoutes.get(ROUTE_ID1)),
+ () -> mManager.selectRoute(mPackageName, routes.get(ROUTE_ID1)),
ROUTE_ID1,
route -> TextUtils.equals(route.getClientPackageName(), mPackageName));
awaitOnRouteChangedManager(
- () -> mManager.selectRoute(mPackageName, mRoutes.get(ROUTE_ID2)),
+ () -> mManager.selectRoute(mPackageName, routes.get(ROUTE_ID2)),
ROUTE_ID2,
route -> TextUtils.equals(route.getClientPackageName(), mPackageName));
+ //TODO: release the session
+ /*
awaitOnRouteChangedManager(
- () -> mManager.unselectRoute(mPackageName),
+ () -> mManager.selectRoute(mPackageName, null),
ROUTE_ID2,
route -> TextUtils.equals(route.getClientPackageName(), null));
- }
-
- @Test
- public void testControlVolumeWithRouter() throws Exception {
- Map<String, MediaRoute2Info> routes = waitAndGetRoutes(CATEGORIES_ALL);
-
- MediaRoute2Info volRoute = routes.get(ROUTE_ID_VARIABLE_VOLUME);
- int originalVolume = volRoute.getVolume();
- int deltaVolume = (originalVolume == volRoute.getVolumeMax() ? -1 : 1);
-
- awaitOnRouteChanged(
- () -> mRouter2.requestUpdateVolume(volRoute, deltaVolume),
- ROUTE_ID_VARIABLE_VOLUME,
- (route -> route.getVolume() == originalVolume + deltaVolume));
- awaitOnRouteChanged(
- () -> mRouter2.requestSetVolume(volRoute, originalVolume),
- ROUTE_ID_VARIABLE_VOLUME,
- (route -> route.getVolume() == originalVolume));
+ */
}
@Test
public void testControlVolumeWithManager() throws Exception {
- MediaRoute2Info volRoute = mRoutes.get(ROUTE_ID_VARIABLE_VOLUME);
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(CATEGORIES_ALL);
+ MediaRoute2Info volRoute = routes.get(ROUTE_ID_VARIABLE_VOLUME);
+
int originalVolume = volRoute.getVolume();
int deltaVolume = (originalVolume == volRoute.getVolumeMax() ? -1 : 1);
@@ -317,93 +357,54 @@ public class MediaRouterManagerTest {
@Test
public void testVolumeHandling() throws Exception {
- MediaRoute2Info fixedVolumeRoute = mRoutes.get(ROUTE_ID_FIXED_VOLUME);
- MediaRoute2Info variableVolumeRoute = mRoutes.get(ROUTE_ID_VARIABLE_VOLUME);
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(CATEGORIES_ALL);
+
+ MediaRoute2Info fixedVolumeRoute = routes.get(ROUTE_ID_FIXED_VOLUME);
+ MediaRoute2Info variableVolumeRoute = routes.get(ROUTE_ID_VARIABLE_VOLUME);
assertEquals(PLAYBACK_VOLUME_FIXED, fixedVolumeRoute.getVolumeHandling());
assertEquals(PLAYBACK_VOLUME_VARIABLE, variableVolumeRoute.getVolumeHandling());
assertEquals(VOLUME_MAX, variableVolumeRoute.getVolumeMax());
}
- @Test
- public void testDefaultRoute() throws Exception {
- Map<String, MediaRoute2Info> routes = waitAndGetRoutes(CATEGORIES_LIVE_AUDIO);
-
- assertNotNull(routes.get(DEFAULT_ROUTE_ID));
- }
-
- Map<String, MediaRoute2Info> waitAndGetRoutes(List<String> controlCategories) throws Exception {
- CountDownLatch latch = new CountDownLatch(1);
- MediaRouter2.Callback callback = new MediaRouter2.Callback() {
- @Override
- public void onRoutesAdded(List<MediaRoute2Info> added) {
- if (added.size() > 0) latch.countDown();
- }
- };
- mRouter2.setControlCategories(controlCategories);
- mRouter2.registerCallback(mExecutor, callback);
- try {
- assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
- return createRouteMap(mRouter2.getRoutes());
- } finally {
- mRouter2.unregisterCallback(callback);
- }
- }
-
Map<String, MediaRoute2Info> waitAndGetRoutesWithManager(List<String> controlCategories)
throws Exception {
CountDownLatch latch = new CountDownLatch(2);
// A dummy callback is required to send control category info.
- MediaRouter2.Callback routerCallback = new MediaRouter2.Callback();
+ RouteCallback routeCallback = new RouteCallback();
MediaRouter2Manager.Callback managerCallback = new MediaRouter2Manager.Callback() {
@Override
public void onRoutesAdded(List<MediaRoute2Info> routes) {
- if (routes.size() > 0) {
- latch.countDown();
+ for (int i = 0; i < routes.size(); i++) {
+ //TODO: use isSystem() or similar method when it's ready
+ if (!TextUtils.equals(routes.get(i).getProviderId(), SYSTEM_PROVIDER_ID)) {
+ latch.countDown();
+ break;
+ }
}
}
@Override
- public void onControlCategoriesChanged(String packageName) {
- if (TextUtils.equals(mPackageName, packageName)) {
+ public void onControlCategoriesChanged(String packageName, List<String> categories) {
+ if (TextUtils.equals(mPackageName, packageName)
+ && controlCategories.equals(categories)) {
latch.countDown();
}
}
};
mManager.registerCallback(mExecutor, managerCallback);
mRouter2.setControlCategories(controlCategories);
- mRouter2.registerCallback(mExecutor, routerCallback);
+ mRouter2.registerRouteCallback(mExecutor, routeCallback);
try {
- assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
return createRouteMap(mManager.getAvailableRoutes(mPackageName));
} finally {
- mRouter2.unregisterCallback(routerCallback);
+ mRouter2.unregisterRouteCallback(routeCallback);
mManager.unregisterCallback(managerCallback);
}
}
- void awaitOnRouteChanged(Runnable task, String routeId,
- Predicate<MediaRoute2Info> predicate) throws Exception {
- CountDownLatch latch = new CountDownLatch(1);
- MediaRouter2.Callback callback = new MediaRouter2.Callback() {
- @Override
- public void onRoutesChanged(List<MediaRoute2Info> changed) {
- MediaRoute2Info route = createRouteMap(changed).get(routeId);
- if (route != null && predicate.test(route)) {
- latch.countDown();
- }
- }
- };
- mRouter2.registerCallback(mExecutor, callback);
- try {
- task.run();
- assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
- } finally {
- mRouter2.unregisterCallback(callback);
- }
- }
-
void awaitOnRouteChangedManager(Runnable task, String routeId,
Predicate<MediaRoute2Info> predicate) throws Exception {
CountDownLatch latch = new CountDownLatch(1);
@@ -440,9 +441,14 @@ public class MediaRouterManagerTest {
mManager.registerCallback(mExecutor, callback);
}
- private void addRouterCallback(MediaRouter2.Callback callback) {
- mRouterCallbacks.add(callback);
- mRouter2.registerCallback(mExecutor, callback);
+ private void addRouterCallback(RouteCallback routeCallback) {
+ mRouteCallbacks.add(routeCallback);
+ mRouter2.registerRouteCallback(mExecutor, routeCallback);
+ }
+
+ private void addSessionCallback(SessionCallback sessionCallback) {
+ mSessionCallbacks.add(sessionCallback);
+ mRouter2.registerSessionCallback(mExecutor, sessionCallback);
}
private void clearCallbacks() {
@@ -451,9 +457,14 @@ public class MediaRouterManagerTest {
}
mManagerCallbacks.clear();
- for (MediaRouter2.Callback callback : mRouterCallbacks) {
- mRouter2.unregisterCallback(callback);
+ for (RouteCallback routeCallback : mRouteCallbacks) {
+ mRouter2.unregisterRouteCallback(routeCallback);
+ }
+ mRouteCallbacks.clear();
+
+ for (SessionCallback sessionCallback : mSessionCallbacks) {
+ mRouter2.unregisterSessionCallback(sessionCallback);
}
- mRouterCallbacks.clear();
+ mSessionCallbacks.clear();
}
}
diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/RouteSessionTest.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/RouteSessionTest.java
new file mode 100644
index 000000000000..2e81a646b0db
--- /dev/null
+++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/RouteSessionTest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.mediaroutertest;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.media.RouteSessionInfo;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class RouteSessionTest {
+ private static final String TEST_PACKAGE_NAME = "com.android.mediaroutertest";
+ private static final String TEST_CONTROL_CATEGORY = "com.android.mediaroutertest.category";
+
+ private static final String TEST_ROUTE_ID1 = "route_id1";
+
+ @Test
+ public void testValidity() {
+ RouteSessionInfo emptyPackageSession = new RouteSessionInfo.Builder(1,
+ "",
+ TEST_CONTROL_CATEGORY)
+ .addSelectedRoute(TEST_ROUTE_ID1)
+ .build();
+ RouteSessionInfo emptyCategorySession = new RouteSessionInfo.Builder(1,
+ TEST_PACKAGE_NAME, "")
+ .addSelectedRoute(TEST_ROUTE_ID1)
+ .build();
+
+ RouteSessionInfo emptySelectedRouteSession = new RouteSessionInfo.Builder(1,
+ TEST_PACKAGE_NAME, TEST_CONTROL_CATEGORY)
+ .build();
+
+ RouteSessionInfo validSession = new RouteSessionInfo.Builder(emptySelectedRouteSession)
+ .addSelectedRoute(TEST_ROUTE_ID1)
+ .build();
+
+ assertFalse(emptySelectedRouteSession.isValid());
+ assertFalse(emptyPackageSession.isValid());
+ assertFalse(emptyCategorySession.isValid());
+ assertTrue(validSession.isValid());
+ }
+}
diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
index 177f2b8ee491..203adfc749d2 100644
--- a/native/android/libandroid.map.txt
+++ b/native/android/libandroid.map.txt
@@ -40,6 +40,7 @@ LIBANDROID {
AConfiguration_getOrientation;
AConfiguration_getScreenHeightDp; # introduced-arm=13 introduced-arm64=21 introduced-mips=13 introduced-mips64=21 introduced-x86=13 introduced-x86_64=21
AConfiguration_getScreenLong;
+ AConfiguration_getScreenRound; # introduced=30
AConfiguration_getScreenSize;
AConfiguration_getScreenWidthDp; # introduced-arm=13 introduced-arm64=21 introduced-mips=13 introduced-mips64=21 introduced-x86=13 introduced-x86_64=21
AConfiguration_getSdkVersion;
diff --git a/packages/CarSystemUI/Android.bp b/packages/CarSystemUI/Android.bp
index b2451c91057c..2a8a39a1fe1a 100644
--- a/packages/CarSystemUI/Android.bp
+++ b/packages/CarSystemUI/Android.bp
@@ -53,7 +53,6 @@ android_library {
],
libs: [
- "telephony-common",
"android.car",
],
@@ -108,7 +107,6 @@ android_library {
],
libs: [
"android.test.runner",
- "telephony-common",
"android.test.base",
"android.car",
],
@@ -129,7 +127,6 @@ android_app {
],
libs: [
- "telephony-common",
"android.car",
],
@@ -140,7 +137,7 @@ android_app {
],
platform_apis: true,
- product_specific: true,
+ system_ext_specific: true,
certificate: "platform",
privileged: true,
diff --git a/packages/CarSystemUI/CleanSpec.mk b/packages/CarSystemUI/CleanSpec.mk
new file mode 100644
index 000000000000..ceac67c55f09
--- /dev/null
+++ b/packages/CarSystemUI/CleanSpec.mk
@@ -0,0 +1,50 @@
+# Copyright (C) 2019 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# If you don't need to do a full clean build but would like to touch
+# a file or delete some intermediate files, add a clean step to the end
+# of the list. These steps will only be run once, if they haven't been
+# run before.
+#
+# E.g.:
+# $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
+# $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
+#
+# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
+# files that are missing or have been moved.
+#
+# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
+# Use $(OUT_DIR) to refer to the "out" directory.
+#
+# If you need to re-do something that's already mentioned, just copy
+# the command and add it to the bottom of the list. E.g., if a change
+# that you made last week required touching a file and a change you
+# made today requires touching the same file, just copy the old
+# touch step and add it to the end of the list.
+#
+# *****************************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THE BANNER
+# *****************************************************************
+
+# For example:
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
+#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
+#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/product/priv-app/CarSystemUI)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/product/priv-app/CarSystemUI)
+# ******************************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
+# ******************************************************************
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
index 03bd61ae5e27..cf4ee7d97409 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
@@ -21,6 +21,7 @@ import static com.android.systemui.Dependency.LEAK_REPORT_EMAIL_NAME;
import android.content.Context;
+import com.android.systemui.car.CarDeviceProvisionedControllerImpl;
import com.android.systemui.car.CarNotificationEntryManager;
import com.android.systemui.car.CarNotificationInterruptionStateProvider;
import com.android.systemui.dagger.SystemUIRootComponent;
@@ -31,7 +32,7 @@ import com.android.systemui.power.EnhancedEstimates;
import com.android.systemui.power.EnhancedEstimatesImpl;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsImplementation;
-import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.stackdivider.DividerModule;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
@@ -46,21 +47,19 @@ import com.android.systemui.statusbar.phone.KeyguardEnvironmentImpl;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.volume.CarVolumeDialogComponent;
import com.android.systemui.volume.VolumeDialogComponent;
-import java.util.Optional;
-
import javax.inject.Named;
import javax.inject.Singleton;
import dagger.Binds;
-import dagger.Lazy;
import dagger.Module;
import dagger.Provides;
-@Module
+@Module(includes = {DividerModule.class})
abstract class CarSystemUIModule {
@Binds
@@ -83,12 +82,6 @@ abstract class CarSystemUIModule {
@Singleton
@Provides
- static Divider provideDivider(Context context, Optional<Lazy<Recents>> recentsOptionalLazy) {
- return new Divider(context, recentsOptionalLazy);
- }
-
- @Singleton
- @Provides
static HeadsUpManagerPhone provideHeadsUpManagerPhone(Context context,
StatusBarStateController statusBarStateController,
KeyguardBypassController bypassController) {
@@ -143,4 +136,8 @@ abstract class CarSystemUIModule {
@Binds
abstract StatusBarKeyguardViewManager bindStatusBarKeyguardViewManager(
CarStatusBarKeyguardViewManager keyguardViewManager);
+
+ @Binds
+ abstract DeviceProvisionedController bindDeviceProvisionedController(
+ CarDeviceProvisionedControllerImpl deviceProvisionedController);
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/CarDeviceProvisionedController.java b/packages/CarSystemUI/src/com/android/systemui/car/CarDeviceProvisionedController.java
new file mode 100644
index 000000000000..c870cec67314
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/car/CarDeviceProvisionedController.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.car;
+
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+
+/**
+ * This interface defines controller that monitors the status of SUW progress for each user in
+ * addition to the functionality defined by {@link DeviceProvisionedController}.
+ */
+public interface CarDeviceProvisionedController extends DeviceProvisionedController {
+ /**
+ * Returns {@code true} then SUW is in progress for the given user.
+ */
+ boolean isUserSetupInProgress(int user);
+
+ /**
+ * Returns {@code true} then SUW is in progress for the current user.
+ */
+ default boolean isCurrentUserSetupInProgress() {
+ return isUserSetupInProgress(getCurrentUser());
+ }
+}
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/CarDeviceProvisionedControllerImpl.java b/packages/CarSystemUI/src/com/android/systemui/car/CarDeviceProvisionedControllerImpl.java
new file mode 100644
index 000000000000..38d5211bd0d4
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/car/CarDeviceProvisionedControllerImpl.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.car;
+
+import android.app.ActivityManager;
+import android.car.settings.CarSettings;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.provider.Settings;
+
+import com.android.systemui.Dependency;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.statusbar.policy.DeviceProvisionedControllerImpl;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * A controller that monitors the status of SUW progress for each user in addition to the
+ * functionality provided by {@link DeviceProvisionedControllerImpl}.
+ */
+@Singleton
+public class CarDeviceProvisionedControllerImpl extends DeviceProvisionedControllerImpl implements
+ CarDeviceProvisionedController {
+ private static final Uri USER_SETUP_IN_PROGRESS_URI = Settings.Secure.getUriFor(
+ CarSettings.Secure.KEY_SETUP_WIZARD_IN_PROGRESS);
+ private final ContentObserver mCarSettingsObserver = new ContentObserver(
+ Dependency.get(Dependency.MAIN_HANDLER)) {
+ @Override
+ public void onChange(boolean selfChange, Uri uri, int userId) {
+ if (USER_SETUP_IN_PROGRESS_URI.equals(uri)) {
+ notifyUserSetupInProgressChanged();
+ }
+ }
+ };
+ private final ContentResolver mContentResolver;
+
+ @Inject
+ public CarDeviceProvisionedControllerImpl(Context context, @Main Handler mainHandler,
+ BroadcastDispatcher broadcastDispatcher) {
+ super(context, mainHandler, broadcastDispatcher);
+ mContentResolver = context.getContentResolver();
+ }
+
+ @Override
+ public boolean isUserSetupInProgress(int user) {
+ return Settings.Secure.getIntForUser(mContentResolver,
+ CarSettings.Secure.KEY_SETUP_WIZARD_IN_PROGRESS, /* def= */ 0, user) != 0;
+ }
+
+ @Override
+ public boolean isCurrentUserSetupInProgress() {
+ return isUserSetupInProgress(ActivityManager.getCurrentUser());
+ }
+
+ @Override
+ public void addCallback(DeviceProvisionedListener listener) {
+ super.addCallback(listener);
+ if (listener instanceof CarDeviceProvisionedListener) {
+ ((CarDeviceProvisionedListener) listener).onUserSetupInProgressChanged();
+ }
+ }
+
+ @Override
+ protected void startListening(int user) {
+ mContentResolver.registerContentObserver(
+ USER_SETUP_IN_PROGRESS_URI, /* notifyForDescendants= */ true, mCarSettingsObserver,
+ user);
+ // The SUW Flag observer is registered before super.startListening() so that the observer is
+ // in place before DeviceProvisionedController starts to track user switches which avoids
+ // an edge case where our observer gets registered twice.
+ super.startListening(user);
+ }
+
+ @Override
+ protected void stopListening() {
+ super.stopListening();
+ mContentResolver.unregisterContentObserver(mCarSettingsObserver);
+ }
+
+ @Override
+ public void onUserSwitched(int newUserId) {
+ super.onUserSwitched(newUserId);
+ mContentResolver.unregisterContentObserver(mCarSettingsObserver);
+ mContentResolver.registerContentObserver(
+ USER_SETUP_IN_PROGRESS_URI, /* notifyForDescendants= */ true, mCarSettingsObserver,
+ newUserId);
+ }
+
+ private void notifyUserSetupInProgressChanged() {
+ for (int i = mListeners.size() - 1; i >= 0; --i) {
+ DeviceProvisionedListener listener = mListeners.get(i);
+ if (listener instanceof CarDeviceProvisionedListener) {
+ ((CarDeviceProvisionedListener) listener).onUserSetupInProgressChanged();
+ }
+ }
+ }
+}
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/CarDeviceProvisionedListener.java b/packages/CarSystemUI/src/com/android/systemui/car/CarDeviceProvisionedListener.java
new file mode 100644
index 000000000000..008632223f3f
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/car/CarDeviceProvisionedListener.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.car;
+
+import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
+
+/**
+ * A listener that listens for changes in SUW progress for a user in addition to the
+ * functionality defined by {@link DeviceProvisionedListener}.
+ */
+public interface CarDeviceProvisionedListener extends DeviceProvisionedListener {
+ @Override
+ default void onUserSwitched() {
+ onUserSetupChanged();
+ onUserSetupInProgressChanged();
+ }
+ /**
+ * A callback for when a change occurs in SUW progress for a user.
+ */
+ default void onUserSetupInProgressChanged() {
+ }
+}
diff --git a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBar.java b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBar.java
index 998d2b97f764..59a084e337ad 100644
--- a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBar.java
@@ -33,7 +33,9 @@ import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.RegisterStatusBarResult;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.car.CarDeviceProvisionedController;
+import com.android.systemui.car.CarDeviceProvisionedListener;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NavigationBarController;
@@ -53,7 +55,7 @@ public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks
private final CarNavigationBarController mCarNavigationBarController;
private final WindowManager mWindowManager;
- private final DeviceProvisionedController mDeviceProvisionedController;
+ private final CarDeviceProvisionedController mCarDeviceProvisionedController;
private final CommandQueue mCommandQueue;
private final Lazy<FacetButtonTaskStackListener> mFacetButtonTaskStackListenerLazy;
private final Handler mMainHandler;
@@ -82,6 +84,7 @@ public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks
// To be attached to the navigation bars such that they can close the notification panel if
// it's open.
private boolean mDeviceIsSetUpForUser = true;
+ private boolean mIsUserSetupInProgress = false;
@Inject
public CarNavigationBar(Context context,
@@ -90,7 +93,7 @@ public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks
DeviceProvisionedController deviceProvisionedController,
CommandQueue commandQueue,
Lazy<FacetButtonTaskStackListener> facetButtonTaskStackListenerLazy,
- @MainHandler Handler mainHandler,
+ @Main Handler mainHandler,
Lazy<KeyguardStateController> keyguardStateControllerLazy,
Lazy<NavigationBarController> navigationBarControllerLazy,
SuperStatusBarViewFactory superStatusBarViewFactory,
@@ -98,7 +101,8 @@ public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks
super(context);
mCarNavigationBarController = carNavigationBarController;
mWindowManager = windowManager;
- mDeviceProvisionedController = deviceProvisionedController;
+ mCarDeviceProvisionedController = (CarDeviceProvisionedController)
+ deviceProvisionedController;
mCommandQueue = commandQueue;
mFacetButtonTaskStackListenerLazy = facetButtonTaskStackListenerLazy;
mMainHandler = mainHandler;
@@ -129,9 +133,15 @@ public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks
ex.rethrowFromSystemServer();
}
- mDeviceIsSetUpForUser = mDeviceProvisionedController.isCurrentUserSetup();
- mDeviceProvisionedController.addCallback(
- new DeviceProvisionedController.DeviceProvisionedListener() {
+ mDeviceIsSetUpForUser = mCarDeviceProvisionedController.isCurrentUserSetup();
+ mIsUserSetupInProgress = mCarDeviceProvisionedController.isCurrentUserSetupInProgress();
+ mCarDeviceProvisionedController.addCallback(
+ new CarDeviceProvisionedListener() {
+ @Override
+ public void onUserSetupInProgressChanged() {
+ mMainHandler.post(() -> restartNavBarsIfNecessary());
+ }
+
@Override
public void onUserSetupChanged() {
mMainHandler.post(() -> restartNavBarsIfNecessary());
@@ -152,9 +162,13 @@ public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks
}
private void restartNavBarsIfNecessary() {
- boolean currentUserSetup = mDeviceProvisionedController.isCurrentUserSetup();
- if (mDeviceIsSetUpForUser != currentUserSetup) {
+ boolean currentUserSetup = mCarDeviceProvisionedController.isCurrentUserSetup();
+ boolean currentUserSetupInProgress = mCarDeviceProvisionedController
+ .isCurrentUserSetupInProgress();
+ if (mIsUserSetupInProgress != currentUserSetupInProgress
+ || mDeviceIsSetUpForUser != currentUserSetup) {
mDeviceIsSetUpForUser = currentUserSetup;
+ mIsUserSetupInProgress = currentUserSetupInProgress;
restartNavBars();
}
}
@@ -193,10 +207,14 @@ public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks
// If the UI was rebuilt (day/night change) while the keyguard was up we need to
// correctly respect that state.
if (mKeyguardStateControllerLazy.get().isShowing()) {
- mCarNavigationBarController.showAllKeyguardButtons(mDeviceIsSetUpForUser);
+ mCarNavigationBarController.showAllKeyguardButtons(isDeviceSetupForUser());
}
}
+ private boolean isDeviceSetupForUser() {
+ return mDeviceIsSetUpForUser && !mIsUserSetupInProgress;
+ }
+
private void createNavigationBar(RegisterStatusBarResult result) {
buildNavBarWindows();
buildNavBarContent();
@@ -225,22 +243,22 @@ public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks
}
private void buildNavBarContent() {
- mTopNavigationBarView = mCarNavigationBarController.getTopBar(mDeviceIsSetUpForUser);
+ mTopNavigationBarView = mCarNavigationBarController.getTopBar(isDeviceSetupForUser());
if (mTopNavigationBarView != null) {
mTopNavigationBarWindow.addView(mTopNavigationBarView);
}
- mBottomNavigationBarView = mCarNavigationBarController.getBottomBar(mDeviceIsSetUpForUser);
+ mBottomNavigationBarView = mCarNavigationBarController.getBottomBar(isDeviceSetupForUser());
if (mBottomNavigationBarView != null) {
mBottomNavigationBarWindow.addView(mBottomNavigationBarView);
}
- mLeftNavigationBarView = mCarNavigationBarController.getLeftBar(mDeviceIsSetUpForUser);
+ mLeftNavigationBarView = mCarNavigationBarController.getLeftBar(isDeviceSetupForUser());
if (mLeftNavigationBarView != null) {
mLeftNavigationBarWindow.addView(mLeftNavigationBarView);
}
- mRightNavigationBarView = mCarNavigationBarController.getRightBar(mDeviceIsSetUpForUser);
+ mRightNavigationBarView = mCarNavigationBarController.getRightBar(isDeviceSetupForUser());
if (mRightNavigationBarView != null) {
mRightNavigationBarWindow.addView(mRightNavigationBarView);
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index fbc03c06c6f2..77db54c067c6 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.car;
import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
+import static com.android.systemui.Dependency.TIME_TICK_HANDLER_NAME;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -30,6 +31,7 @@ import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
+import android.os.Handler;
import android.os.PowerManager;
import android.util.DisplayMetrics;
import android.util.Log;
@@ -57,22 +59,27 @@ import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.BatteryMeterView;
import com.android.systemui.Dependency;
+import com.android.systemui.InitController;
import com.android.systemui.Prefs;
import com.android.systemui.R;
-import com.android.systemui.UiOffloadThread;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.bubbles.BubbleController;
+import com.android.systemui.car.CarDeviceProvisionedController;
+import com.android.systemui.car.CarDeviceProvisionedListener;
import com.android.systemui.car.CarServiceProvider;
import com.android.systemui.classifier.FalsingLog;
import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.navigationbar.car.CarNavigationBarController;
+import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.plugins.PluginDependencyProvider;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.qs.car.CarQSFragment;
import com.android.systemui.recents.Recents;
@@ -111,6 +118,7 @@ import com.android.systemui.statusbar.phone.DozeScrimController;
import com.android.systemui.statusbar.phone.DozeServiceHost;
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
+import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
import com.android.systemui.statusbar.phone.LightBarController;
import com.android.systemui.statusbar.phone.LightsOutNotifController;
import com.android.systemui.statusbar.phone.LockscreenLockIconController;
@@ -128,10 +136,12 @@ import com.android.systemui.statusbar.phone.StatusBarWindowController;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.ExtensionController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
import com.android.systemui.statusbar.policy.RemoteInputUriController;
+import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.volume.VolumeComponent;
@@ -139,6 +149,7 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Map;
import java.util.Optional;
+import java.util.concurrent.Executor;
import javax.inject.Named;
import javax.inject.Provider;
@@ -175,11 +186,14 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
private final Object mQueueLock = new Object();
private final CarNavigationBarController mCarNavigationBarController;
+ private final FlingAnimationUtils.Builder mFlingAnimationUtilsBuilder;
private final Lazy<PowerManagerHelper> mPowerManagerHelperLazy;
private final ShadeController mShadeController;
private final CarServiceProvider mCarServiceProvider;
+ private final CarDeviceProvisionedController mCarDeviceProvisionedController;
- private DeviceProvisionedController mDeviceProvisionedController;
+ private boolean mDeviceIsSetUpForUser = true;
+ private boolean mIsUserSetupInProgress = false;
private PowerManagerHelper mPowerManagerHelper;
private FlingAnimationUtils mFlingAnimationUtils;
private NotificationDataManager mNotificationDataManager;
@@ -268,7 +282,7 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
NotificationAlertingManager notificationAlertingManager,
DisplayMetrics displayMetrics,
MetricsLogger metricsLogger,
- UiOffloadThread uiOffloadThread,
+ @UiBackground Executor uiBgExecutor,
NotificationMediaManager notificationMediaManager,
NotificationLockscreenUserManager lockScreenUserManager,
NotificationRemoteInputManager remoteInputManager,
@@ -313,12 +327,20 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
ShadeController shadeController,
StatusBarKeyguardViewManager statusBarKeyguardViewManager,
ViewMediatorCallback viewMediatorCallback,
+ InitController initController,
+ DarkIconDispatcher darkIconDispatcher,
+ @Named(TIME_TICK_HANDLER_NAME) Handler timeTickHandler,
+ PluginDependencyProvider pluginDependencyProvider,
+ KeyguardDismissUtil keyguardDismissUtil,
+ ExtensionController extensionController,
+ UserInfoControllerImpl userInfoControllerImpl,
DismissCallbackRegistry dismissCallbackRegistry,
/* Car Settings injected components. */
CarServiceProvider carServiceProvider,
Lazy<PowerManagerHelper> powerManagerHelperLazy,
Lazy<FullscreenUserSwitcher> fullscreenUserSwitcherLazy,
- CarNavigationBarController carNavigationBarController) {
+ CarNavigationBarController carNavigationBarController,
+ FlingAnimationUtils.Builder flingAnimationUtilsBuilder) {
super(
context,
featureFlags,
@@ -347,7 +369,7 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
notificationAlertingManager,
displayMetrics,
metricsLogger,
- uiOffloadThread,
+ uiBgExecutor,
notificationMediaManager,
lockScreenUserManager,
remoteInputManager,
@@ -392,19 +414,31 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
superStatusBarViewFactory,
statusBarKeyguardViewManager,
viewMediatorCallback,
+ initController,
+ darkIconDispatcher,
+ timeTickHandler,
+ pluginDependencyProvider,
+ keyguardDismissUtil,
+ extensionController,
+ userInfoControllerImpl,
dismissCallbackRegistry);
mScrimController = scrimController;
mLockscreenLockIconController = lockscreenLockIconController;
- mDeviceProvisionedController = deviceProvisionedController;
+ mCarDeviceProvisionedController =
+ (CarDeviceProvisionedController) deviceProvisionedController;
mShadeController = shadeController;
mCarServiceProvider = carServiceProvider;
mPowerManagerHelperLazy = powerManagerHelperLazy;
mFullscreenUserSwitcherLazy = fullscreenUserSwitcherLazy;
mCarNavigationBarController = carNavigationBarController;
+ mFlingAnimationUtilsBuilder = flingAnimationUtilsBuilder;
}
@Override
public void start() {
+ mDeviceIsSetUpForUser = mCarDeviceProvisionedController.isCurrentUserSetup();
+ mIsUserSetupInProgress = mCarDeviceProvisionedController.isCurrentUserSetupInProgress();
+
// Need to initialize screen lifecycle before calling super.start - before switcher is
// created.
mScreenLifecycle = Dependency.get(ScreenLifecycle.class);
@@ -436,8 +470,10 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
R.integer.notification_settle_open_percentage);
mSettleClosePercentage = mContext.getResources().getInteger(
R.integer.notification_settle_close_percentage);
- mFlingAnimationUtils = new FlingAnimationUtils(mContext,
- FLING_ANIMATION_MAX_TIME, FLING_SPEED_UP_FACTOR);
+ mFlingAnimationUtils = mFlingAnimationUtilsBuilder
+ .setMaxLengthSeconds(FLING_ANIMATION_MAX_TIME)
+ .setSpeedUpFactor(FLING_SPEED_UP_FACTOR)
+ .build();
createBatteryController();
mCarBatteryController.startListening();
@@ -445,6 +481,33 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
mPowerManagerHelper = mPowerManagerHelperLazy.get();
mPowerManagerHelper.setCarPowerStateListener(mCarPowerStateListener);
mPowerManagerHelper.connectToCarService();
+
+ mCarDeviceProvisionedController.addCallback(
+ new CarDeviceProvisionedListener() {
+ @Override
+ public void onUserSetupInProgressChanged() {
+ mDeviceIsSetUpForUser = mCarDeviceProvisionedController
+ .isCurrentUserSetup();
+ mIsUserSetupInProgress = mCarDeviceProvisionedController
+ .isCurrentUserSetupInProgress();
+ }
+
+ @Override
+ public void onUserSetupChanged() {
+ mDeviceIsSetUpForUser = mCarDeviceProvisionedController
+ .isCurrentUserSetup();
+ mIsUserSetupInProgress = mCarDeviceProvisionedController
+ .isCurrentUserSetupInProgress();
+ }
+
+ @Override
+ public void onUserSwitched() {
+ mDeviceIsSetUpForUser = mCarDeviceProvisionedController
+ .isCurrentUserSetup();
+ mIsUserSetupInProgress = mCarDeviceProvisionedController
+ .isCurrentUserSetupInProgress();
+ }
+ });
}
/**
@@ -460,16 +523,18 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
@Override
public boolean hideKeyguard() {
boolean result = super.hideKeyguard();
- mCarNavigationBarController.hideAllKeyguardButtons(
- mDeviceProvisionedController.isCurrentUserSetup());
+ mCarNavigationBarController.hideAllKeyguardButtons(isDeviceSetupForUser());
return result;
}
@Override
public void showKeyguard() {
super.showKeyguard();
- mCarNavigationBarController.showAllKeyguardButtons(
- mDeviceProvisionedController.isCurrentUserSetup());
+ mCarNavigationBarController.showAllKeyguardButtons(isDeviceSetupForUser());
+ }
+
+ private boolean isDeviceSetupForUser() {
+ return mDeviceIsSetUpForUser && !mIsUserSetupInProgress;
}
@Override
@@ -531,7 +596,7 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
new HandleBarCloseNotificationGestureListener());
mTopNavBarNotificationTouchListener = (v, event) -> {
- if (!mDeviceProvisionedController.isCurrentUserSetup()) {
+ if (!isDeviceSetupForUser()) {
return true;
}
boolean consumed = openGestureDetector.onTouchEvent(event);
@@ -695,8 +760,8 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
*/
protected void onUseenCountUpdate(int unseenNotificationCount) {
boolean hasUnseen = unseenNotificationCount > 0;
- mCarNavigationBarController.toggleAllNotificationsUnseenIndicator(
- mDeviceProvisionedController.isCurrentUserSetup(), hasUnseen);
+ mCarNavigationBarController.toggleAllNotificationsUnseenIndicator(isDeviceSetupForUser(),
+ hasUnseen);
}
/**
@@ -1001,6 +1066,12 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
mScrimController.setScrimBehindDrawable(mNotificationPanelBackground);
}
+ @Override
+ public void onLocaleListChanged() {
+ connectNotificationsUI();
+ registerNavBarListeners();
+ }
+
/**
* Returns the {@link Drawable} that represents the wallpaper that the user has currently set.
*/
@@ -1262,8 +1333,10 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
@Override
protected void setHeadsUpVisible() {
- // if the Notifications panel is showing don't show the Heads up
- if (!mEnableHeadsUpNotificationWhenNotificationShadeOpen && mPanelExpanded) {
+ // if the Notifications panel is showing or SUW for user is in progress then don't show
+ // heads up notifications
+ if ((!mEnableHeadsUpNotificationWhenNotificationShadeOpen && mPanelExpanded)
+ || !isDeviceSetupForUser()) {
return;
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java
index ff4dc9c7b830..1ebaef702286 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java
@@ -17,32 +17,38 @@
package com.android.systemui.statusbar.car;
import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
+import static com.android.systemui.Dependency.TIME_TICK_HANDLER_NAME;
import android.content.Context;
+import android.os.Handler;
import android.os.PowerManager;
import android.util.DisplayMetrics;
import com.android.internal.logging.MetricsLogger;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.ViewMediatorCallback;
-import com.android.systemui.UiOffloadThread;
+import com.android.systemui.InitController;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.car.CarServiceProvider;
import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.navigationbar.car.CarNavigationBarController;
+import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.plugins.PluginDependencyProvider;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.ScreenPinningRequest;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.stackdivider.Divider;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.FeatureFlags;
+import com.android.systemui.statusbar.FlingAnimationUtils;
import com.android.systemui.statusbar.NavigationBarController;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
@@ -71,6 +77,7 @@ import com.android.systemui.statusbar.phone.DozeScrimController;
import com.android.systemui.statusbar.phone.DozeServiceHost;
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
+import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
import com.android.systemui.statusbar.phone.LightBarController;
import com.android.systemui.statusbar.phone.LightsOutNotifController;
import com.android.systemui.statusbar.phone.LockscreenLockIconController;
@@ -87,14 +94,17 @@ import com.android.systemui.statusbar.phone.StatusBarWindowController;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.ExtensionController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
import com.android.systemui.statusbar.policy.RemoteInputUriController;
+import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.volume.VolumeComponent;
import java.util.Optional;
+import java.util.concurrent.Executor;
import javax.inject.Named;
import javax.inject.Provider;
@@ -142,7 +152,7 @@ public class CarStatusBarModule {
NotificationAlertingManager notificationAlertingManager,
DisplayMetrics displayMetrics,
MetricsLogger metricsLogger,
- UiOffloadThread uiOffloadThread,
+ @UiBackground Executor uiBgExecutor,
NotificationMediaManager notificationMediaManager,
NotificationLockscreenUserManager lockScreenUserManager,
NotificationRemoteInputManager remoteInputManager,
@@ -187,11 +197,19 @@ public class CarStatusBarModule {
ShadeController shadeController,
StatusBarKeyguardViewManager statusBarKeyguardViewManager,
ViewMediatorCallback viewMediatorCallback,
+ InitController initController,
+ DarkIconDispatcher darkIconDispatcher,
+ @Named(TIME_TICK_HANDLER_NAME) Handler timeTickHandler,
+ PluginDependencyProvider pluginDependencyProvider,
+ KeyguardDismissUtil keyguardDismissUtil,
+ ExtensionController extensionController,
+ UserInfoControllerImpl userInfoControllerImpl,
DismissCallbackRegistry dismissCallbackRegistry,
CarServiceProvider carServiceProvider,
Lazy<PowerManagerHelper> powerManagerHelperLazy,
Lazy<FullscreenUserSwitcher> fullscreenUserSwitcherLazy,
- CarNavigationBarController carNavigationBarController) {
+ CarNavigationBarController carNavigationBarController,
+ FlingAnimationUtils.Builder flingAnimationUtilsBuilder) {
return new CarStatusBar(
context,
featureFlags,
@@ -220,7 +238,7 @@ public class CarStatusBarModule {
notificationAlertingManager,
displayMetrics,
metricsLogger,
- uiOffloadThread,
+ uiBgExecutor,
notificationMediaManager,
lockScreenUserManager,
remoteInputManager,
@@ -264,10 +282,18 @@ public class CarStatusBarModule {
shadeController,
statusBarKeyguardViewManager,
viewMediatorCallback,
+ initController,
+ darkIconDispatcher,
+ timeTickHandler,
+ pluginDependencyProvider,
+ keyguardDismissUtil,
+ extensionController,
+ userInfoControllerImpl,
dismissCallbackRegistry,
carServiceProvider,
powerManagerHelperLazy,
fullscreenUserSwitcherLazy,
- carNavigationBarController);
+ carNavigationBarController,
+ flingAnimationUtilsBuilder);
}
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarTrustAgentUnlockDialogHelper.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarTrustAgentUnlockDialogHelper.java
index 2d57be177333..b2f8aad77dd4 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarTrustAgentUnlockDialogHelper.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarTrustAgentUnlockDialogHelper.java
@@ -37,7 +37,7 @@ import android.widget.TextView;
import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.R;
-import com.android.systemui.dagger.qualifiers.MainResources;
+import com.android.systemui.dagger.qualifiers.Main;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -68,7 +68,7 @@ class CarTrustAgentUnlockDialogHelper extends BroadcastReceiver{
private OnHideListener mOnHideListener;
@Inject
- CarTrustAgentUnlockDialogHelper(Context context, @MainResources Resources resources,
+ CarTrustAgentUnlockDialogHelper(Context context, @Main Resources resources,
UserManager userManager, WindowManager windowManager) {
mContext = context;
mResources = resources;
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
index 3d7486859686..f8fc3bbefb01 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
@@ -38,7 +38,7 @@ import androidx.recyclerview.widget.GridLayoutManager;
import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.R;
import com.android.systemui.car.CarServiceProvider;
-import com.android.systemui.dagger.qualifiers.MainResources;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.statusbar.car.CarTrustAgentUnlockDialogHelper.OnHideListener;
import com.android.systemui.statusbar.car.UserGridRecyclerView.UserRecord;
@@ -78,7 +78,7 @@ public class FullscreenUserSwitcher {
@Inject
public FullscreenUserSwitcher(
Context context,
- @MainResources Resources resources,
+ @Main Resources resources,
UserManager userManager,
CarServiceProvider carServiceProvider,
CarTrustAgentUnlockDialogHelper carTrustAgentUnlockDialogHelper) {
diff --git a/packages/CompanionDeviceManager/Android.bp b/packages/CompanionDeviceManager/Android.bp
index a379bfccbe29..1453ec3b63cb 100644
--- a/packages/CompanionDeviceManager/Android.bp
+++ b/packages/CompanionDeviceManager/Android.bp
@@ -15,5 +15,6 @@
android_app {
name: "CompanionDeviceManager",
srcs: ["src/**/*.java"],
+
platform_apis: true,
}
diff --git a/packages/CompanionDeviceManager/AndroidManifest.xml b/packages/CompanionDeviceManager/AndroidManifest.xml
index 42885e8193a7..a9c668599a2a 100644
--- a/packages/CompanionDeviceManager/AndroidManifest.xml
+++ b/packages/CompanionDeviceManager/AndroidManifest.xml
@@ -29,6 +29,7 @@
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
+ <uses-permission android:name="android.permission.RADIO_SCAN_WITHOUT_LOCATION"/>
<application
android:allowClearUserData="true"
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
index d11b5c573ca9..7aa997e39307 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
@@ -37,12 +37,12 @@ import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
+import android.companion.Association;
import android.companion.AssociationRequest;
import android.companion.BluetoothDeviceFilter;
import android.companion.BluetoothLeDeviceFilter;
import android.companion.DeviceFilter;
import android.companion.ICompanionDeviceDiscoveryService;
-import android.companion.ICompanionDeviceDiscoveryServiceCallback;
import android.companion.IFindDeviceCallback;
import android.companion.WifiDeviceFilter;
import android.content.BroadcastReceiver;
@@ -63,6 +63,7 @@ import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
+import com.android.internal.infra.AndroidFuture;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.CollectionUtils;
import com.android.internal.util.Preconditions;
@@ -97,7 +98,7 @@ public class DeviceDiscoveryService extends Service {
DevicesAdapter mDevicesAdapter;
IFindDeviceCallback mFindCallback;
- ICompanionDeviceDiscoveryServiceCallback mServiceCallback;
+ AndroidFuture<Association> mServiceCallback;
boolean mIsScanning = false;
@Nullable DeviceChooserActivity mActivity = null;
@@ -107,7 +108,7 @@ public class DeviceDiscoveryService extends Service {
public void startDiscovery(AssociationRequest request,
String callingPackage,
IFindDeviceCallback findCallback,
- ICompanionDeviceDiscoveryServiceCallback serviceCallback) {
+ AndroidFuture serviceCallback) {
if (DEBUG) {
Log.i(LOG_TAG,
"startDiscovery() called with: filter = [" + request
@@ -303,23 +304,12 @@ public class DeviceDiscoveryService extends Service {
}
void onDeviceSelected(String callingPackage, String deviceAddress) {
- try {
- mServiceCallback.onDeviceSelected(
- //TODO is this the right userId?
- callingPackage, getUserId(), deviceAddress);
- } catch (RemoteException e) {
- Log.e(LOG_TAG, "Failed to record association: "
- + callingPackage + " <-> " + deviceAddress);
- }
+ mServiceCallback.complete(new Association(getUserId(), deviceAddress, callingPackage));
}
void onCancel() {
if (DEBUG) Log.i(LOG_TAG, "onCancel()");
- try {
- mServiceCallback.onDeviceSelectionCancel();
- } catch (RemoteException e) {
- throw new RuntimeException(e);
- }
+ mServiceCallback.cancel(true);
}
class DevicesAdapter extends ArrayAdapter<DeviceFilterPair> {
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 7b2922ba961b..1e19786f5d41 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -102,6 +102,9 @@ public class ExternalStorageProvider extends FileSystemProvider {
DocumentsContract.EXTERNAL_STORAGE_PRIMARY_EMULATED_ROOT_ID;
private static final String ROOT_ID_HOME = "home";
+ private static final String GET_DOCUMENT_URI_CALL = "get_document_uri";
+ private static final String GET_MEDIA_URI_CALL = "get_media_uri";
+
private StorageManager mStorageManager;
private UserManager mUserManager;
@@ -665,7 +668,7 @@ public class ExternalStorageProvider extends FileSystemProvider {
}
break;
}
- case MediaStore.GET_DOCUMENT_URI_CALL: {
+ case GET_DOCUMENT_URI_CALL: {
// All callers must go through MediaProvider
getContext().enforceCallingPermission(
android.Manifest.permission.WRITE_MEDIA_STORAGE, TAG);
@@ -684,7 +687,7 @@ public class ExternalStorageProvider extends FileSystemProvider {
throw new IllegalStateException("File in " + path + " is not found.", e);
}
}
- case MediaStore.GET_MEDIA_URI_CALL: {
+ case GET_MEDIA_URI_CALL: {
// All callers must go through MediaProvider
getContext().enforceCallingPermission(
android.Manifest.permission.WRITE_MEDIA_STORAGE, TAG);
diff --git a/packages/Incremental/NativeAdbDataLoader/jni/com_android_incremental_nativeadb_DataLoaderService.cpp b/packages/Incremental/NativeAdbDataLoader/jni/com_android_incremental_nativeadb_DataLoaderService.cpp
index de92fcd5b2e8..4e49302debcd 100644
--- a/packages/Incremental/NativeAdbDataLoader/jni/com_android_incremental_nativeadb_DataLoaderService.cpp
+++ b/packages/Incremental/NativeAdbDataLoader/jni/com_android_incremental_nativeadb_DataLoaderService.cpp
@@ -177,8 +177,7 @@ private:
android::dataloader::ServiceParamsPtr) final {
CHECK(ifs) << "ifs can't be null";
CHECK(statusListener) << "statusListener can't be null";
- ALOGE("[AdbDataLoader] onCreate: %s/%s/%d", params.staticArgs().c_str(),
- params.packageName().c_str(), (int)params.dynamicArgs().size());
+ ALOGE("[AdbDataLoader] onCreate: %d/%s/%s/%s/%d", params.type(), params.packageName().c_str(), params.className().c_str(), params.arguments().c_str(), (int)params.dynamicArgs().size());
if (params.dynamicArgs().empty()) {
ALOGE("[AdbDataLoader] Invalid DataLoaderParams. Need in/out FDs.");
@@ -204,7 +203,7 @@ private:
}
std::string logFile;
- if (const auto packageName = extractPackageName(params.staticArgs()); !packageName.empty()) {
+ if (const auto packageName = extractPackageName(params.arguments()); !packageName.empty()) {
logFile = android::base::GetProperty("adb.readlog." + packageName, "");
}
if (logFile.empty()) {
@@ -288,8 +287,7 @@ private:
"inode=%d. Ignore.",
static_cast<int>(ino));
mRequestedFiles.erase(fileId);
- mStatusListener->reportStatus(
- INCREMENTAL_DATA_LOADER_NO_CONNECTION);
+ mStatusListener->reportStatus(DATA_LOADER_NO_CONNECTION);
}
}
sendRequest(mOutFd, BLOCK_MISSING, fileId, blockIdx);
@@ -337,7 +335,7 @@ private:
}
if (res < 0) {
ALOGE("[AdbDataLoader] failed to poll. Abort.");
- mStatusListener->reportStatus(INCREMENTAL_DATA_LOADER_NO_CONNECTION);
+ mStatusListener->reportStatus(DATA_LOADER_NO_CONNECTION);
break;
}
if (res == mEventFd) {
@@ -346,7 +344,7 @@ private:
}
if (!readChunk(mInFd, data)) {
ALOGE("[AdbDataLoader] failed to read a message. Abort.");
- mStatusListener->reportStatus(INCREMENTAL_DATA_LOADER_NO_CONNECTION);
+ mStatusListener->reportStatus(DATA_LOADER_NO_CONNECTION);
break;
}
auto remainingData = std::span(data);
diff --git a/packages/Incremental/NativeAdbDataLoader/src/com/android/incremental/nativeadb/NativeAdbDataLoaderService.java b/packages/Incremental/NativeAdbDataLoader/src/com/android/incremental/nativeadb/NativeAdbDataLoaderService.java
index 1f88114becd8..bd5b79594c19 100644
--- a/packages/Incremental/NativeAdbDataLoader/src/com/android/incremental/nativeadb/NativeAdbDataLoaderService.java
+++ b/packages/Incremental/NativeAdbDataLoader/src/com/android/incremental/nativeadb/NativeAdbDataLoaderService.java
@@ -16,10 +16,10 @@
package com.android.incremental.nativeadb;
-import android.service.incremental.IncrementalDataLoaderService;
+import android.service.dataloader.DataLoaderService;
/** This code is used for testing only. */
-public class NativeAdbDataLoaderService extends IncrementalDataLoaderService {
+public class NativeAdbDataLoaderService extends DataLoaderService {
public static final String TAG = "NativeAdbDataLoaderService";
static {
System.loadLibrary("nativeadbdataloaderservice_jni");
diff --git a/packages/PackageInstaller/res/values-fr/strings.xml b/packages/PackageInstaller/res/values-fr/strings.xml
index b85eb9751053..462c60ed748a 100644
--- a/packages/PackageInstaller/res/values-fr/strings.xml
+++ b/packages/PackageInstaller/res/values-fr/strings.xml
@@ -62,7 +62,7 @@
<string name="uninstalling_notification_channel" msgid="840153394325714653">"Désinstallations en cours"</string>
<string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Échec des désinstallations"</string>
<string name="uninstalling" msgid="8709566347688966845">"Désinstallation…"</string>
- <string name="uninstalling_app" msgid="8866082646836981397">"Désinstallation du package <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+ <string name="uninstalling_app" msgid="8866082646836981397">"Désinstallation de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
<string name="uninstall_done" msgid="439354138387969269">"Désinstallation terminée."</string>
<string name="uninstall_done_app" msgid="4588850984473605768">"Le package <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> a été désinstallé"</string>
<string name="uninstall_failed" msgid="1847750968168364332">"Échec de la désinstallation."</string>
diff --git a/packages/PrintSpooler/res/values-cs/strings.xml b/packages/PrintSpooler/res/values-cs/strings.xml
index 1f38e3c70e82..dd2ce5a1f5c0 100644
--- a/packages/PrintSpooler/res/values-cs/strings.xml
+++ b/packages/PrintSpooler/res/values-cs/strings.xml
@@ -54,7 +54,7 @@
<string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Vyhledávací pole je skryto"</string>
<string name="print_add_printer" msgid="1088656468360653455">"Přidat tiskárnu"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Vybrat tiskárnu"</string>
- <string name="print_forget_printer" msgid="5035287497291910766">"Odstranit tiskárnu"</string>
+ <string name="print_forget_printer" msgid="5035287497291910766">"Zapomenout tiskárnu"</string>
<plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
<item quantity="few">Nalezené tiskárny: <xliff:g id="COUNT_1">%1$s</xliff:g></item>
<item quantity="many">Nalezené tiskárny: <xliff:g id="COUNT_1">%1$s</xliff:g></item>
diff --git a/packages/PrintSpooler/res/values-eu/strings.xml b/packages/PrintSpooler/res/values-eu/strings.xml
index 459b4d3093ab..7ccccc9ff261 100644
--- a/packages/PrintSpooler/res/values-eu/strings.xml
+++ b/packages/PrintSpooler/res/values-eu/strings.xml
@@ -32,7 +32,7 @@
<string name="template_page_range" msgid="428638530038286328">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g> orriko tartea"</string>
<string name="pages_range_example" msgid="8558694453556945172">"adib., 1-5, 8,11-13"</string>
<string name="print_preview" msgid="8010217796057763343">"Inprimatze-aurrebista"</string>
- <string name="install_for_print_preview" msgid="6366303997385509332">"Aurrebista ikusteko, instalatu PDF ikustailea"</string>
+ <string name="install_for_print_preview" msgid="6366303997385509332">"Aurrebista ikusteko, instalatu PDF dokumentuen ikustailea"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"Inprimatzeko aplikazioak matxura izan du"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Inprimatze-lana sortzen"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Gorde PDF gisa"</string>
diff --git a/packages/PrintSpooler/res/values-iw/strings.xml b/packages/PrintSpooler/res/values-iw/strings.xml
index 22ef6125b1e9..64db711def15 100644
--- a/packages/PrintSpooler/res/values-iw/strings.xml
+++ b/packages/PrintSpooler/res/values-iw/strings.xml
@@ -108,7 +108,7 @@
</string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"לא ניתן היה לכתוב לקובץ"</string>
<string name="print_error_default_message" msgid="8602678405502922346">"מצטערים, אך זה לא עבד. נסה שוב."</string>
- <string name="print_error_retry" msgid="1426421728784259538">"נסה שוב"</string>
+ <string name="print_error_retry" msgid="1426421728784259538">"כדאי לנסות שוב"</string>
<string name="print_error_printer_unavailable" msgid="8985614415253203381">"המדפסת הזו אינה זמינה כעת."</string>
<string name="print_cannot_load_page" msgid="6179560924492912009">"לא ניתן להציג תצוגה מקדימה"</string>
<string name="print_preparing_preview" msgid="3939930735671364712">"מכין תצוגה מקדימה…"</string>
diff --git a/packages/SettingsLib/SearchWidget/res/values-or/strings.xml b/packages/SettingsLib/SearchWidget/res/values-or/strings.xml
index f160aec1eadd..c2379acf0950 100644
--- a/packages/SettingsLib/SearchWidget/res/values-or/strings.xml
+++ b/packages/SettingsLib/SearchWidget/res/values-or/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="search_menu" msgid="1914043873178389845">"ସର୍ଚ୍ଚ ସେଟିଙ୍ଗ"</string>
+ <string name="search_menu" msgid="1914043873178389845">"ସନ୍ଧାନ ସେଟିଂସ୍"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-af/arrays.xml b/packages/SettingsLib/res/values-af/arrays.xml
index 71b89108b631..d9aaf7dacafc 100644
--- a/packages/SettingsLib/res/values-af/arrays.xml
+++ b/packages/SettingsLib/res/values-af/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>-oudio"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>-oudio"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Aktiveer opsionele kodekke"</item>
- <item msgid="9205039209798344398">"Deaktiveer opsionele kodekke"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Gebruik stelselkeuse (verstek)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>-oudio"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>-oudio"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Aktiveer opsionele kodekke"</item>
- <item msgid="7416462860415701287">"Deaktiveer opsionele kodekke"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Gebruik stelselkeuse (verstek)"</item>
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 6289b8743f55..25903388c6ca 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -227,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Hardewareversnelling vir verbinding"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Wys Bluetooth-toestelle sonder name"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Deaktiveer absolute volume"</string>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Aktiveer Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP-weergawe"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Kies Bluetooth AVRCP-weergawe"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth-oudiokodek"</string>
@@ -275,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Kontroleer programme wat via ADB/ADT geïnstalleer is vir skadelike gedrag."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Bluetooth-toestelle sonder name (net MAC-adresse) sal gewys word"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Deaktiveer die Bluetooth-kenmerk vir absolute volume indien daar volumeprobleme met afgeleë toestelle is, soos onaanvaarbare harde klank of geen beheer nie."</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Aktiveer die Bluetooth Gabeldorsche-kenmerkstapel."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Plaaslike terminaal"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Aktiveer terminaalprogram wat plaaslike skermtoegang bied"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP-kontrolering"</string>
@@ -379,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalie (rooi-groen)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalie (blou-geel)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Kleurregstelling"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"Hierdie kenmerk is eksperimenteel en kan werkverrigting beïnvloed."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Kleurregstelling help mense met kleurblindheid om akkurater kleure te sien"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Geneutraliseer deur <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Ongeveer <xliff:g id="TIME_REMAINING">%1$s</xliff:g> oor"</string>
diff --git a/packages/SettingsLib/res/values-am/arrays.xml b/packages/SettingsLib/res/values-am/arrays.xml
index 9d3dde8f8953..fff7cae377d4 100644
--- a/packages/SettingsLib/res/values-am/arrays.xml
+++ b/packages/SettingsLib/res/values-am/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ኦዲዮ"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ኦዲዮ"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"አማራጭ ኮዴኮችን አንቃ"</item>
- <item msgid="9205039209798344398">"አማራጭ ኮዴኮችን አሰናክል"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"የስርዓቱን ምርጫ (ነባሪ) ተጠቀም"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ኦዲዮ"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ኦዲዮ"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"አማራጭ ኮዴኮችን አንቃ"</item>
- <item msgid="7416462860415701287">"አማራጭ ኮዴኮችን አሰናክል"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"የስርዓቱን ምርጫ (ነባሪ) ተጠቀም"</item>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 45545a707eb6..8277711a9870 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -227,6 +227,7 @@
<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">"የብሉቱዝ AVRCP ስሪት"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"የብሉቱዝ AVRCP ስሪት ይምረጡ"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"የብሉቱዝ ኦዲዮ ኮዴክ"</string>
@@ -275,6 +276,7 @@
<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="8472344901097607030">"የብሉቱዝ Gabeldorche ባህሪ ቁልልን ያነቃል።"</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"አካባቢያዊ ተርሚናል"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"የአካባቢያዊ ሼል መዳረሻ የሚያቀርብ የተርሚናል መተግበሪያ አንቃ"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"የHDCP ምልከታ"</string>
@@ -379,7 +381,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="5190814747212060815">"ይህ ባህሪ የሙከራ ነውና አፈጻጸም ላይ ተጽዕኖ ሊኖረው ይችላል።"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"ቀለም ማስተካከያ የቀለም ማየት የማይችሉ ሰዎች ተጨማሪ ትክክለኛ ቀለማትን እንዲመለከቱ ያስችላቸዋል"</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>
diff --git a/packages/SettingsLib/res/values-ar/arrays.xml b/packages/SettingsLib/res/values-ar/arrays.xml
index 610d1ee6bfd2..7fc65a36e04a 100644
--- a/packages/SettingsLib/res/values-ar/arrays.xml
+++ b/packages/SettingsLib/res/values-ar/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"صوت <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="2908219194098827570">"صوت <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"تفعيل برامج الترميز الاختيارية"</item>
- <item msgid="9205039209798344398">"إيقاف برامج الترميز الاختيارية"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"استخدام اختيار النظام (تلقائي)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"صوت <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="3517061573669307965">"صوت <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"تفعيل برامج الترميز الاختيارية"</item>
- <item msgid="7416462860415701287">"إيقاف برامج الترميز الاختيارية"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"استخدام اختيار النظام (تلقائي)"</item>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index af06fc7e9d7d..d4e1b63c4ca5 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -227,6 +227,7 @@
<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">"‏إصدار Bluetooth AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"‏اختيار إصدار Bluetooth AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"برنامج ترميز صوت بلوتوث"</string>
@@ -275,6 +276,7 @@
<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="8472344901097607030">"‏تفعيل حِزم ميزة Bluetooth Gabeldorche"</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"تطبيق طرفي محلي"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"تفعيل تطبيق طرفي يوفر إمكانية الدخول إلى واجهة النظام المحلية"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"‏التحقق من HDCP"</string>
@@ -379,7 +381,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="5190814747212060815">"هذه الميزة تجريبية وقد تؤثر في الأداء."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"تساعد ميزة تصحيح الألوان المصابين بعمى الألوان على رؤية الألوان بدقة أكبر"</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>
diff --git a/packages/SettingsLib/res/values-as/arrays.xml b/packages/SettingsLib/res/values-as/arrays.xml
index 1fc1c50651af..1a044f5ade70 100644
--- a/packages/SettingsLib/res/values-as/arrays.xml
+++ b/packages/SettingsLib/res/values-as/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> অডিঅ\'"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> অডিঅ’"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"বিকল্প ক\'ডেকসমূহ সক্ষম কৰক"</item>
- <item msgid="9205039209798344398">"বিকল্প ক\'ডেকসমূহ অসক্ষম কৰক"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"ছিষ্টেমৰ বাছনি ব্যৱহাৰ কৰক (ডিফ\'ল্ট)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> অডিঅ’"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> অডিঅ’"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"বিকল্প ক\'ডেকসমূহ সক্ষম কৰক"</item>
- <item msgid="7416462860415701287">"ঐচ্ছিক ক’ডেকসমূহ অক্ষম কৰক"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"ছিষ্টেমৰ বাছনি ব্যৱহাৰ কৰক (ডিফ\'ল্ট)"</item>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index 49eabe1620eb..3f85fe3dad37 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -227,6 +227,7 @@
<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">"ব্লুটুথ AVRCP সংস্কৰণ"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"ব্লুটুথ AVRCP সংস্কৰণ বাছনি কৰক"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"ব্লুটুথ অডিঅ’ ক’ডেক"</string>
@@ -275,6 +276,7 @@
<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="8472344901097607030">"ব্লুটুথ Gabeldorche সুবিধাৰ সমষ্টিটো সক্ষম কৰে।"</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"স্থানীয় টাৰ্মিনেল"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"স্থানীয় শ্বেল প্ৰৱেশাধিকাৰ দিয়া টাৰ্মিনেল এপ্ সক্ষম কৰক"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP পৰীক্ষণ"</string>
@@ -379,7 +381,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="5190814747212060815">"এই সুবিধাটো পৰীক্ষামূলক, সেয়ে ই কাৰ্যক্ষমতাৰ ওপৰত প্ৰভাৱ পেলাব পাৰে।"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"ৰং শুধৰণী কৰা কার্যই বর্ণান্ধলোকসকলক ৰংবোৰ অধিক সঠিককৈ দেখাত সহায় কৰে"</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>
diff --git a/packages/SettingsLib/res/values-az/arrays.xml b/packages/SettingsLib/res/values-az/arrays.xml
index 23b667a40b9a..eb81381a4439 100644
--- a/packages/SettingsLib/res/values-az/arrays.xml
+++ b/packages/SettingsLib/res/values-az/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Şəxsi Kodekləri Aktiv edin"</item>
- <item msgid="9205039209798344398">"Şəxsi Kodekləri Deaktiv edin"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Sistem Seçimini istifadə edin (Defolt)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Şəxsi Kodekləri Aktiv edin"</item>
- <item msgid="7416462860415701287">"Şəxsi Kodekləri Deaktiv edin"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Sistem Seçimini istifadə edin (Defolt)"</item>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 158f13a14229..3a1a54341aaf 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -227,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Birləşmə üçün avadanlıq akselerasiyası"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Bluetooth cihazlarını adsız göstərin"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Mütləq səs həcmi deaktiv edin"</string>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorsche\'ni aktiv edin"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP Versiya"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Bluetooth AVRCP Versiyasını seçin"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth Audio Kodek"</string>
@@ -275,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"ADB/ADT vasitəsi ilə quraşdırılmış tətbiqləri zərərli davranış üzrə yoxlayın."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Adsız Bluetooth cihazları (yalnız MAC ünvanları) göstəriləcək"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Uzaqdan idarə olunan cihazlarda dözülməz yüksək səs həcmi və ya nəzarət çatışmazlığı kimi səs problemləri olduqda Bluetooth mütləq səs həcmi xüsusiyyətini deaktiv edir."</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Bluetooth Gabeldorche xüsusiyyətini aktiv edir."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Yerli terminal"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Yerli örtük girişini təklif edən terminal tətbiqi aktiv edin"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP yoxlanılır"</string>
@@ -379,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaliya (qırmızı-yaşıl)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaliya (göy-sarı)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Rəng düzəlişi"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"Bu funksiya eksperimentaldır və performansa təsir edə bilər."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Rəng düzəlişi rəng korluğu olanların daha yaxşı görməsinə kömək edir"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> tərəfindən qəbul edilmir"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Təxminən <xliff:g id="TIME_REMAINING">%1$s</xliff:g> qalıb"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml b/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
index 07b7286ba52d..c7b63b3f7f3e 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Omogući opcionalne kodeke"</item>
- <item msgid="9205039209798344398">"Onemogući opcionalne kodeke"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Koristi izbor sistema (podrazumevano)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Omogući opcionalne kodeke"</item>
- <item msgid="7416462860415701287">"Onemogući opcionalne kodeke"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Koristi izbor sistema (podrazumevano)"</item>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 2709df5a483e..02e5e3b5c435 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -227,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Hardversko ubrzanje privezivanja"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Prikaži Bluetooth uređaje bez naziva"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Onemogući glavno podešavanje jačine zvuka"</string>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Omogući Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Verzija Bluetooth AVRCP-a"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Izaberite verziju Bluetooth AVRCP-a"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth audio kodek"</string>
@@ -275,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Proverava da li su aplikacije instalirane preko ADB-a/ADT-a štetne."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Biće prikazani Bluetooth uređaji bez naziva (samo sa MAC adresama)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Onemogućava glavno podešavanje jačine zvuka na Bluetooth uređaju u slučaju problema sa jačinom zvuka na daljinskim uređajima, kao što su izuzetno velika jačina zvuka ili nedostatak kontrole."</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Omogućava grupu Bluetooth Gabeldorche funkcija."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Lokalni terminal"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Omogući apl. terminala za pristup lokalnom komandnom okruženju"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP provera"</string>
@@ -379,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalija (crveno-zeleno)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalija (plavo-žuto)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Korekcija boja"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"Ova funkcija je eksperimentalna i može da utiče na kvalitet rada."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Korekcija boja pomaže ljudima koji su daltonisti da preciznije vide boje"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Zamenjuje ga <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g>–<xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Preostalo je oko <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-be/arrays.xml b/packages/SettingsLib/res/values-be/arrays.xml
index fa2f93d9bdce..9eaab6a6829a 100644
--- a/packages/SettingsLib/res/values-be/arrays.xml
+++ b/packages/SettingsLib/res/values-be/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"Аўдыя <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="2908219194098827570">"Аўдыя <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Уключыць дадатковыя кодэкі"</item>
- <item msgid="9205039209798344398">"Адключыць дадатковыя кодэкі"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Выбар сістэмы (стандартны)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"Аўдыя <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="3517061573669307965">"Аўдыя <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Уключыць дадатковыя кодэкі"</item>
- <item msgid="7416462860415701287">"Адключыць дадатковыя кодэкі"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Выбар сістэмы (стандартны)"</item>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 40295ea2e9e1..481dfb0fd697 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -227,6 +227,7 @@
<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>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Уключыць Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Версія Bluetooth AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Выбраць версію Bluetooth AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Кодэк Bluetooth Audio"</string>
@@ -275,6 +276,7 @@
<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="8472344901097607030">"Уключае стос функцый Bluetooth Gabeldorche."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Лакальны тэрмінал"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Уключэнне прыкладання тэрмінала, якое прапануе доступ да лакальнай абалонкі"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"Праверка HDCP"</string>
@@ -379,7 +381,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="5190814747212060815">"Гэта функцыя з\'яўляецца эксперыментальнай і можа паўплываць на прадукцыйнасць."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Карэкцыя колеру дазваляе людзям з парушэннямі колеравага зроку лепш распазнаваць выявы на экране"</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>
diff --git a/packages/SettingsLib/res/values-bg/arrays.xml b/packages/SettingsLib/res/values-bg/arrays.xml
index cf70712cb744..e7976fcc7bd5 100644
--- a/packages/SettingsLib/res/values-bg/arrays.xml
+++ b/packages/SettingsLib/res/values-bg/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"Аудио: <xliff:g id="APTX">aptX™</xliff:g> от <xliff:g id="QUALCOMM">Qualcomm®</xliff:g>"</item>
<item msgid="2908219194098827570">"Аудио: <xliff:g id="APTX_HD">aptX™ HD</xliff:g> от <xliff:g id="QUALCOMM">Qualcomm®</xliff:g>"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Активиране на кодеците по избор"</item>
- <item msgid="9205039209798344398">"Деактивиране на кодеците по избор"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Използване на сист. избор (стандартно)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"Аудио: <xliff:g id="APTX">aptX™</xliff:g> от <xliff:g id="QUALCOMM">Qualcomm®</xliff:g>"</item>
<item msgid="3517061573669307965">"Аудио: <xliff:g id="APTX_HD">aptX™ HD</xliff:g> от <xliff:g id="QUALCOMM">Qualcomm®</xliff:g>"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Активиране на кодеците по избор"</item>
- <item msgid="7416462860415701287">"Деактивиране на кодеците по избор"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Използване на сист. избор (стандартно)"</item>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 7b2537402077..2a0264039a78 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -227,6 +227,7 @@
<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>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Активиране на Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Версия на AVRCP за Bluetooth"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Избиране на версия на AVRCP за Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Аудиокодек за Bluetooth"</string>
@@ -275,6 +276,7 @@
<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="8472344901097607030">"Активира стека на функциите на Bluetooth Gabeldorsche."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Локален терминал"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Актив. на прил. за терминал с достъп до локалния команден ред"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"Проверка с HDCP"</string>
@@ -379,7 +381,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="5190814747212060815">"Тази функция е експериментална и може да се отрази на ефективността."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Коригирането на цветовете помага на хората с цветна слепота да виждат по-точни цветове"</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>
diff --git a/packages/SettingsLib/res/values-bn/arrays.xml b/packages/SettingsLib/res/values-bn/arrays.xml
index bff22ee6364f..a67b9eb493c4 100644
--- a/packages/SettingsLib/res/values-bn/arrays.xml
+++ b/packages/SettingsLib/res/values-bn/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> অডিও"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> অডিও"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"ঐচ্ছিক কোডেক সক্ষম করুন"</item>
- <item msgid="9205039209798344398">"ঐচ্ছিক কোডেক অক্ষম করুন"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"সিস্টেমের নির্বাচন ব্যবহার করুন (ডিফল্ট)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> অডিও"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> অডিও"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"ঐচ্ছিক কোডেক সক্ষম করুন"</item>
- <item msgid="7416462860415701287">"ঐচ্ছিক কোডেক অক্ষম করুন"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"সিস্টেমের নির্বাচন ব্যবহার করুন (ডিফল্ট)"</item>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index c41a3e590730..9bebe419470b 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -227,6 +227,7 @@
<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">"ব্লুটুথ AVRCP ভার্সন"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"ব্লুটুথ AVRCP ভার্সন বেছে নিন"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"ব্লুটুথ অডিও কোডেক"</string>
@@ -275,6 +276,7 @@
<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="8472344901097607030">"ব্লুটুথ Gabeldorche ফিচার স্ট্যাক চালু করা হয়েছে।"</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"স্থানীয় টার্মিনাল"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"স্থানীয় শেল অ্যাক্সেসের প্রস্তাব করে এমন টার্মিনাল অ্যাপ্লিকেশন সক্ষম করুন"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP পরীক্ষণ"</string>
@@ -379,7 +381,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="5190814747212060815">"এই বৈশিষ্ট্যটি পরীক্ষামূলক এবং এটি কার্য-সম্পাদনা প্রভাবিত করতে পারে।"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"রঙ অ্যাডজাস্ট করার সেটিংস, বর্ণান্ধতা আছে এমন ব্যক্তিদের আরও সঠিকভাবে রঙ চিনতে সাহায্য করে"</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>
diff --git a/packages/SettingsLib/res/values-bs/arrays.xml b/packages/SettingsLib/res/values-bs/arrays.xml
index 63337eb7355a..d8b2bcd25fc1 100644
--- a/packages/SettingsLib/res/values-bs/arrays.xml
+++ b/packages/SettingsLib/res/values-bs/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Omogući opcionalne kodeke"</item>
- <item msgid="9205039209798344398">"Onemogući opcionalne kodeke"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Korištenje odabira sistema (zadano)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Omogući opcionalne kodeke"</item>
- <item msgid="7416462860415701287">"Onemogući opcionalne kodeke"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Korištenje odabira sistema (zadano)"</item>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 381fe4b41945..f2446ad7ba07 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -227,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Hardversko ubrzavanje za povezivanje putem mobitela"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Prikaži Bluetooth uređaje bez naziva"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Onemogući apsolutnu jačinu zvuka"</string>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Omogući Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP verzija"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Odaberite Bluetooth AVRCP verziju"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth Audio kodek"</string>
@@ -275,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Provjerava da li se u aplikacijama instaliranim putem ADB-a/ADT-a javlja zlonamjerno ponašanje."</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="8472344901097607030">"Omogućava grupisanje funkcije Bluetooth Gabeldorsche."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Lokalni terminal"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Omogući terminalnu aplik. koja nudi pristup lok. kom. okruženju"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP provjera"</string>
@@ -379,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalija (crveno-zeleno)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalija (plavo-žuto)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Ispravka boje"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"Ova funkcija je eksperimentalna i može uticati na performanse."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Ispravka boje pomaže daltonistima da preciznije vide boje"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Zamjenjuje <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Preostalo je još oko <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-ca/arrays.xml b/packages/SettingsLib/res/values-ca/arrays.xml
index f8cda1c4fe7e..600a7ce6c808 100644
--- a/packages/SettingsLib/res/values-ca/arrays.xml
+++ b/packages/SettingsLib/res/values-ca/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"Àudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="2908219194098827570">"Àudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Activa els còdecs opcionals"</item>
- <item msgid="9205039209798344398">"Desactiva els còdecs opcionals"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Utilitza selecció del sistema (predeterminada)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"Àudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="3517061573669307965">"Àudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Activa els còdecs opcionals"</item>
- <item msgid="7416462860415701287">"Desactiva els còdecs opcionals"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Utilitza selecció del sistema (predeterminada)"</item>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 3257dc5a9383..e33fd29e9a8c 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -227,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Acceleració per maquinari per a compartició de xarxa"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Mostra els dispositius Bluetooth sense el nom"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Desactiva el volum absolut"</string>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Activa Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Versió AVRCP de Bluetooth"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Selecciona la versió AVRCP de Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Còdec d\'àudio per Bluetooth"</string>
@@ -275,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Comprova les aplicacions instal·lades mitjançant ADB/ADT per detectar comportaments perillosos"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Es mostraran els dispositius Bluetooth sense el nom (només l\'adreça MAC)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Desactiva la funció de volum absolut del Bluetooth en cas que es produeixin problemes de volum amb dispositius remots, com ara un volum massa alt o una manca de control."</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Activa el conjunt de funcions de Bluetooth Gabeldorsche."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Terminal local"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Activa l\'aplicació de terminal que ofereix accés al shell local"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"Comprovació d\'HDCP"</string>
@@ -379,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalia (vermell-verd)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalia (blau-groc)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Correcció del color"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"Aquesta funció és experimental i pot afectar el rendiment."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"La correcció del color ajuda les persones daltòniques a veure colors més precisos"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"S\'ha substituït per <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g>: <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Temps restant aproximat: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-cs/arrays.xml b/packages/SettingsLib/res/values-cs/arrays.xml
index 554fae555d3c..e7474a92c972 100644
--- a/packages/SettingsLib/res/values-cs/arrays.xml
+++ b/packages/SettingsLib/res/values-cs/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"Zvuk <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="2908219194098827570">"Zvuk <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Povolit volitelné kodeky"</item>
- <item msgid="9205039209798344398">"Zakázat volitelné kodeky"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Použít systémový výběr (výchozí)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"Zvuk <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="3517061573669307965">"Zvuk <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Povolit volitelné kodeky"</item>
- <item msgid="7416462860415701287">"Zakázat volitelné kodeky"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Použít systémový výběr (výchozí)"</item>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 92ba7d16934e..e7875107cadb 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -227,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Hardwarová akcelerace tetheringu"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Zobrazovat zařízení Bluetooth bez názvů"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Zakázat absolutní hlasitost"</string>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Zapnout funkci Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Verze profilu Bluetooth AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Vyberte verzi profilu Bluetooth AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth Audio – kodek"</string>
@@ -275,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Kontrolovat škodlivost aplikací nainstalovaných pomocí nástroje ADB/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="8472344901097607030">"Zapnout sadu funkcí Bluetooth Gabeldorche."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Místní terminál"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Aktivovat terminálovou aplikaci pro místní přístup k prostředí shell"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"Kontrola HDCP"</string>
@@ -379,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomálie (červená a zelená)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomálie (modrá a žlutá)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Korekce barev"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"Funkce je experimentální a může mít vliv na výkon."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Korekce barev pomáhá barvoslepým lidem vidět přesnější barvy"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Přepsáno nastavením <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Zbývá asi <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-da/arrays.xml b/packages/SettingsLib/res/values-da/arrays.xml
index 76b50190e44e..0394562207a9 100644
--- a/packages/SettingsLib/res/values-da/arrays.xml
+++ b/packages/SettingsLib/res/values-da/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>-lyd"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>-lyd"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Aktivér Optional Codecs"</item>
- <item msgid="9205039209798344398">"Deaktiver Optional Codecs"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Brug systemvalg (standard)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>-lyd"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>-lyd"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Aktivér Optional Codecs"</item>
- <item msgid="7416462860415701287">"Deaktiver Optional Codecs"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Brug systemvalg (standard)"</item>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index d836b4a4057a..4e36e388026a 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -227,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Hardwareacceleration ved netdeling"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Vis Bluetooth-enheder uden navne"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Deaktiver absolut lydstyrke"</string>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Aktivér Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"AVRCP-version for Bluetooth"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Vælg AVRCP-version for Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth-lydcodec"</string>
@@ -275,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Tjek apps, der er installeret via ADB/ADT, for skadelig adfærd."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Bluetooth-enheder uden navne (kun MAC-adresser) vises"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Deaktiverer funktionen til absolut lydstyrke via Bluetooth i tilfælde af problemer med lydstyrken på eksterne enheder, f.eks. uacceptabel høj lyd eller manglende kontrol."</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Aktiverer funktioner fra Bluetooth Gabeldorche"</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Lokal terminal"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Aktivér terminalappen, der giver lokal shell-adgang"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP-kontrol"</string>
@@ -379,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanopi (rød-grøn)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanopi (blå-gul)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Korriger farver"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"Denne funktion er eksperimentel og kan påvirke ydeevnen."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Farvekorrigering gør det nemmere for farveblinde at se farver mere nøjagtigt"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Tilsidesat af <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Ca. <xliff:g id="TIME_REMAINING">%1$s</xliff:g> tilbage"</string>
diff --git a/packages/SettingsLib/res/values-de/arrays.xml b/packages/SettingsLib/res/values-de/arrays.xml
index 10083ba98369..d7d3226d9bb4 100644
--- a/packages/SettingsLib/res/values-de/arrays.xml
+++ b/packages/SettingsLib/res/values-de/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>-Audio"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>-Audio"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Optionale Codecs aktivieren"</item>
- <item msgid="9205039209798344398">"Optionale Codecs deaktivieren"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Systemauswahl verwenden (Standard)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>-Audio"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>-Audio"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Optionale Codecs aktivieren"</item>
- <item msgid="7416462860415701287">"Optionale Codecs deaktivieren"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Systemauswahl verwenden (Standard)"</item>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index dff8247ac9a4..63699065a651 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Mittel"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Schnell"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Sehr schnell"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Abgelaufen"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> – <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Nicht verbunden"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Verbindung wird getrennt..."</string>
@@ -228,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Hardwarebeschleunigung für Tethering"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Bluetooth-Geräte ohne Namen anzeigen"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Absolute Lautstärkeregelung deaktivieren"</string>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Bluetooth-Gabeldorsche aktivieren"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP-Version"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Bluetooth AVRCP-Version auswählen"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth-Audio-Codec"</string>
@@ -276,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Über ADB/ADT installierte Apps werden auf schädliches Verhalten geprüft"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Bluetooth-Geräte werden ohne Namen und nur mit ihren MAC-Adressen angezeigt"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Deaktiviert die Funktion \"Absolute Lautstärkeregelung\" für Bluetooth-Geräte, falls auf Remote-Geräten Probleme mit der Lautstärke auftreten, wie beispielsweise übermäßig laute Wiedergabe oder fehlende Steuerungsmöglichkeiten."</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Aktiviert das Bluetooth-Gabeldorsche-Funktionspaket."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Lokales Terminal"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Terminal-App mit Zugriff auf lokale Shell aktivieren"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP-Prüfung"</string>
@@ -380,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalie (Rot-Grün-Sehschwäche)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalie (Blau-Gelb-Sehschwäche)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Farbkorrektur"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"Hierbei handelt es sich um eine experimentelle Funktion, die sich auf die Leistung auswirken kann."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Die Farbkorrektur hilft farbenblinden Menschen, Farben besser zu erkennen"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Außer Kraft gesetzt von \"<xliff:g id="TITLE">%1$s</xliff:g>\""</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Noch etwa <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-el/arrays.xml b/packages/SettingsLib/res/values-el/arrays.xml
index aa80c4950cd9..5c4ef134776b 100644
--- a/packages/SettingsLib/res/values-el/arrays.xml
+++ b/packages/SettingsLib/res/values-el/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"Ήχος <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="2908219194098827570">"Ήχος <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Ενεργοποίηση προαιρετικών κωδικοποιητών"</item>
- <item msgid="9205039209798344398">"Απενεργοποίηση προαιρετικών κωδικοποιητών"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Χρήση επιλογής συστήματος (Προεπιλογή)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"Ήχος <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="3517061573669307965">"Ήχος <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Ενεργοποίηση προαιρετικών κωδικοποιητών"</item>
- <item msgid="7416462860415701287">"Απενεργοποίηση προαιρετικών κωδικοποιητών"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Χρήση επιλογής συστήματος (Προεπιλογή)"</item>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index a86d2594cd55..194324f7de5c 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -227,6 +227,7 @@
<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>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Ενεργοποίηση Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Έκδοση AVRCP Bluetooth"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Επιλογή έκδοσης AVRCP Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Κωδικοποιητής ήχου Bluetooth"</string>
@@ -275,6 +276,7 @@
<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="8472344901097607030">"Ενεργοποιεί τη στοίβα λειτουργιών Bluetooth Gabeldorche."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Τοπική τερματική εφαρμογή"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Ενεργοπ.τερμ.εφαρμογής που προσφέρει πρόσβαση στο τοπικό κέλυφος"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"Έλεγχος HDCP"</string>
@@ -379,7 +381,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="5190814747212060815">"Αυτή η λειτουργία είναι πειραματική και ενδεχομένως να επηρεάσει τις επιδόσεις."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Η διόρθωση χρωμάτων βοηθάει τους ανθρώπους με αχρωματοψία να βλέπουν τα χρώματα με μεγαλύτερη ακρίβεια"</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>
diff --git a/packages/SettingsLib/res/values-en-rAU/arrays.xml b/packages/SettingsLib/res/values-en-rAU/arrays.xml
index 1453cb3f21fd..ae1fb78d97f6 100644
--- a/packages/SettingsLib/res/values-en-rAU/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rAU/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Enable Optional Codecs"</item>
- <item msgid="9205039209798344398">"Disable Optional Codecs"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Use system selection (default)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Enable Optional Codecs"</item>
- <item msgid="7416462860415701287">"Disable Optional Codecs"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Use system selection (default)"</item>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index cadafce21840..92ed8e5359b6 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -227,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Tethering hardware acceleration"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Show Bluetooth devices without names"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Disable absolute volume"</string>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Enable Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP version"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Select Bluetooth AVRCP Version"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth audio codec"</string>
@@ -275,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Check apps installed via ADB/ADT for harmful behaviour."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Bluetooth devices without names (MAC addresses only) will be displayed"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Disables the Bluetooth absolute volume feature in case of volume issues with remote devices such as unacceptably loud volume or lack of control."</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Enables the Bluetooth Gabeldorsche feature stack."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Local terminal"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Enable terminal app that offers local shell access"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP checking"</string>
@@ -379,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (red-green)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (blue-yellow)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Colour correction"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"This feature is experimental and may affect performance."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Colour correction helps people with colour blindness to see more accurate colours"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left"</string>
diff --git a/packages/SettingsLib/res/values-en-rCA/arrays.xml b/packages/SettingsLib/res/values-en-rCA/arrays.xml
index 1453cb3f21fd..ae1fb78d97f6 100644
--- a/packages/SettingsLib/res/values-en-rCA/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rCA/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Enable Optional Codecs"</item>
- <item msgid="9205039209798344398">"Disable Optional Codecs"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Use system selection (default)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Enable Optional Codecs"</item>
- <item msgid="7416462860415701287">"Disable Optional Codecs"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Use system selection (default)"</item>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index cadafce21840..92ed8e5359b6 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -227,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Tethering hardware acceleration"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Show Bluetooth devices without names"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Disable absolute volume"</string>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Enable Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP version"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Select Bluetooth AVRCP Version"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth audio codec"</string>
@@ -275,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Check apps installed via ADB/ADT for harmful behaviour."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Bluetooth devices without names (MAC addresses only) will be displayed"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Disables the Bluetooth absolute volume feature in case of volume issues with remote devices such as unacceptably loud volume or lack of control."</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Enables the Bluetooth Gabeldorsche feature stack."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Local terminal"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Enable terminal app that offers local shell access"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP checking"</string>
@@ -379,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (red-green)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (blue-yellow)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Colour correction"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"This feature is experimental and may affect performance."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Colour correction helps people with colour blindness to see more accurate colours"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/arrays.xml b/packages/SettingsLib/res/values-en-rGB/arrays.xml
index 1453cb3f21fd..ae1fb78d97f6 100644
--- a/packages/SettingsLib/res/values-en-rGB/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rGB/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Enable Optional Codecs"</item>
- <item msgid="9205039209798344398">"Disable Optional Codecs"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Use system selection (default)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Enable Optional Codecs"</item>
- <item msgid="7416462860415701287">"Disable Optional Codecs"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Use system selection (default)"</item>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index cadafce21840..92ed8e5359b6 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -227,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Tethering hardware acceleration"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Show Bluetooth devices without names"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Disable absolute volume"</string>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Enable Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP version"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Select Bluetooth AVRCP Version"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth audio codec"</string>
@@ -275,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Check apps installed via ADB/ADT for harmful behaviour."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Bluetooth devices without names (MAC addresses only) will be displayed"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Disables the Bluetooth absolute volume feature in case of volume issues with remote devices such as unacceptably loud volume or lack of control."</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Enables the Bluetooth Gabeldorsche feature stack."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Local terminal"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Enable terminal app that offers local shell access"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP checking"</string>
@@ -379,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (red-green)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (blue-yellow)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Colour correction"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"This feature is experimental and may affect performance."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Colour correction helps people with colour blindness to see more accurate colours"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/arrays.xml b/packages/SettingsLib/res/values-en-rIN/arrays.xml
index 1453cb3f21fd..ae1fb78d97f6 100644
--- a/packages/SettingsLib/res/values-en-rIN/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rIN/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Enable Optional Codecs"</item>
- <item msgid="9205039209798344398">"Disable Optional Codecs"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Use system selection (default)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Enable Optional Codecs"</item>
- <item msgid="7416462860415701287">"Disable Optional Codecs"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Use system selection (default)"</item>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index cadafce21840..92ed8e5359b6 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -227,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Tethering hardware acceleration"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Show Bluetooth devices without names"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Disable absolute volume"</string>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Enable Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP version"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Select Bluetooth AVRCP Version"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth audio codec"</string>
@@ -275,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Check apps installed via ADB/ADT for harmful behaviour."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Bluetooth devices without names (MAC addresses only) will be displayed"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Disables the Bluetooth absolute volume feature in case of volume issues with remote devices such as unacceptably loud volume or lack of control."</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Enables the Bluetooth Gabeldorsche feature stack."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Local terminal"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Enable terminal app that offers local shell access"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP checking"</string>
@@ -379,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (red-green)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (blue-yellow)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Colour correction"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"This feature is experimental and may affect performance."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Colour correction helps people with colour blindness to see more accurate colours"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left"</string>
diff --git a/packages/SettingsLib/res/values-en-rXC/arrays.xml b/packages/SettingsLib/res/values-en-rXC/arrays.xml
index c1ce26e2f960..af5d7f3d943e 100644
--- a/packages/SettingsLib/res/values-en-rXC/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rXC/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‏‏‎‏‎‎‏‎‎‎‎‎‏‏‎‎‏‎‏‎‎‏‏‎‏‏‏‏‏‏‎‎‎‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‎‏‎‏‎‏‏‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="QUALCOMM">Qualcomm®</xliff:g>‎‏‎‎‏‏‏‎ ‎‏‎‎‏‏‎<xliff:g id="APTX">aptX™</xliff:g>‎‏‎‎‏‏‏‎ audio‎‏‎‎‏‎"</item>
<item msgid="2908219194098827570">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‏‏‏‏‏‎‎‏‎‏‏‎‏‏‎‎‏‎‎‏‏‏‎‏‏‏‏‎‎‎‎‎‏‎‎‏‏‎‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="QUALCOMM">Qualcomm®</xliff:g>‎‏‎‎‏‏‏‎ ‎‏‎‎‏‏‎<xliff:g id="APTX_HD">aptX™ HD</xliff:g>‎‏‎‎‏‏‏‎ audio‎‏‎‎‏‎"</item>
<item msgid="3825367753087348007">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‏‎‏‎‎‎‏‎‏‏‎‎‏‏‎‏‏‏‏‏‎‏‏‎‏‎‎‎‎‏‎‏‎‏‎‎‎‎‎‎‎‎‏‎‏‏‎‏‏‎‏‎‎‏‎‎‏‏‏‎LDAC‎‏‎‎‏‎"</item>
- <item msgid="5832677994279829983">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‎‎‎‏‏‏‏‎‎‎‏‏‏‎‏‎‏‎‏‏‎‏‏‏‎‏‏‏‎‏‎‎‎‏‎‎‏‎‎‏‎‎‏‏‎‎‎‎‎‎‏‏‏‎‏‏‏‏‏‎Enable Optional Codecs‎‏‎‎‏‎"</item>
- <item msgid="9205039209798344398">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‏‏‎‏‏‏‏‎‎‏‏‎‎‏‎‎‎‎‎‏‎‎‏‏‏‎‎‏‎‎‏‎‏‎‎‏‏‏‏‎‏‏‎‎‏‏‏‎‎Disable Optional Codecs‎‏‎‎‏‎"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‎‎‎‏‏‏‎‏‏‎‏‎‏‎‏‎‎‏‏‏‏‎‎‏‎‏‎‎‏‎‏‎‎‎‏‏‎‎‏‎‎‏‏‏‎‏‏‏‎‎‎‎‎Use System Selection (Default)‎‏‎‎‏‎"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‏‏‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎‎‏‎‏‎‎‎‎‎‏‏‎‏‏‎‏‎‏‎‏‎‎‎‎‎‎‎‏‎‏‎‏‎‎‏‏‎‎‏‎‎‏‏‎<xliff:g id="QUALCOMM">Qualcomm®</xliff:g>‎‏‎‎‏‏‏‎ ‎‏‎‎‏‏‎<xliff:g id="APTX">aptX™</xliff:g>‎‏‎‎‏‏‏‎ audio‎‏‎‎‏‎"</item>
<item msgid="3517061573669307965">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‎‎‎‏‏‎‎‏‏‏‏‎‎‎‏‏‏‎‎‏‏‎‏‏‏‎‏‏‏‏‏‎‏‏‏‏‎‏‏‏‏‎‎‎‏‎‎‎‏‏‎‎‎‏‏‏‏‎‏‎‎‏‎‎‏‏‎<xliff:g id="QUALCOMM">Qualcomm®</xliff:g>‎‏‎‎‏‏‏‎ ‎‏‎‎‏‏‎<xliff:g id="APTX_HD">aptX™ HD</xliff:g>‎‏‎‎‏‏‏‎ audio‎‏‎‎‏‎"</item>
<item msgid="2553206901068987657">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‏‏‎‏‏‎‏‏‏‎‏‏‎‏‎‎‎‎‎‎‏‎‎‏‏‎‎‎‏‎‏‎‎‎‎‏‎‎‏‎‏‎‏‏‏‏‏‏‎‏‎‎‎‎‏‎‎‏‎LDAC‎‏‎‎‏‎"</item>
- <item msgid="221347164942544028">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‎‏‏‎‎‎‏‎‎‏‎‎‏‏‎‎‎‏‎‎‎‎‏‎‎‏‎‏‏‏‎‎‎‏‎‎‏‏‏‎‎‎‎‏‎‏‎‏‏‎‎‏‎‎‏‏‏‎‎‎Enable Optional Codecs‎‏‎‎‏‎"</item>
- <item msgid="7416462860415701287">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‏‏‎‏‏‎‎‏‎‎‏‎‎‎‏‏‎‏‎‏‏‎‏‎‏‏‎‏‏‎‎‏‏‏‏‎‏‎‎‏‎‎‏‎‎‎‏‎‎‏‎‎‏‏‏‎Disable Optional Codecs‎‏‎‎‏‎"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‏‎‎‏‏‎‏‏‏‎‎‏‎‏‏‎‎‎‎‎‎‎‏‏‏‎‎‏‏‎‏‏‎‎‏‏‏‏‎‏‏‏‏‏‎‏‎‏‎‎‎‏‏‎‎‏‏‏‏‎Use System Selection (Default)‎‏‎‎‏‎"</item>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index 444dbcb98241..9813efd14427 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -227,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‎‏‎‎‎‏‏‏‏‏‎‎‏‎‏‎‎‏‎‎‎‎‏‏‎‎‏‎‏‏‎‏‎‏‏‏‎‏‎‏‎‏‏‎‎‎‏‎‎‎‎‎‎‏‏‎‎‏‎Tethering hardware acceleration‎‏‎‎‏‎"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‏‎‎‏‏‎‏‎‎‎‏‎‎‏‏‏‎‏‏‎‎‏‏‏‎‏‏‏‏‎‎‎‏‎‎‎‏‏‎‎‏‏‏‎‏‏‏‎‎‏‏‏‏‏‏‏‎‏‏‎Show Bluetooth devices without names‎‏‎‎‏‎"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‏‎‎‎‎‏‎‎‏‏‏‏‏‎‎‎‎‎‏‏‎‏‎‎‏‏‎‎‎‏‎‏‏‏‏‎‎‎‏‏‎‎‏‎‏‏‏‎‎‏‏‏‏‏‎‏‎‏‎‎Disable absolute volume‎‏‎‎‏‎"</string>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‎‏‎‎‏‏‎‏‏‎‎‎‏‏‎‏‎‎‏‏‏‎‏‎‏‎‎‏‎‏‏‎‎‎‏‏‎‏‏‎‎‏‏‎‏‎‏‏‎‎‎‎Enable Gabeldorsche‎‏‎‎‏‎"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‏‏‏‏‎‏‏‏‏‎‏‎‎‏‎‏‎‏‏‏‏‎‏‎‎‎‏‎‎‎‎‎‎‏‏‏‎‎‎‎‎‎‏‏‏‏‎‎‎‎‎‏‏‏‏‎‏‏‏‎Bluetooth AVRCP Version‎‏‎‎‏‎"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‏‎‎‏‎‏‏‏‎‏‏‏‏‎‎‎‏‏‏‏‏‏‏‎‎‎‎‎‎‎‏‎‎‎‏‎‎‎‏‏‎‎‎‎‏‎‏‏‎‎‎‎‎‏‎Select Bluetooth AVRCP Version‎‏‎‎‏‎"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‏‎‏‎‎‏‏‎‏‏‎‎‎‏‏‎‎‎‎‎‎‏‏‏‏‎‎‏‎‏‏‎‎‎‎‏‎‏‎‏‎‎‎‏‎‏‏‎‏‏‎‏‏‏‎‏‏‏‎‎Bluetooth Audio Codec‎‏‎‎‏‎"</string>
@@ -275,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‏‎‎‏‎‎‏‎‏‎‎‎‏‏‏‏‎‏‏‏‎‎‎‎‎‎‎‏‏‎‏‎‏‎‎‎‎‎‎‏‏‏‎‏‎‎‎‏‎‎‏‏‎‏‏‏‏‏‎Check apps installed via ADB/ADT for harmful behavior.‎‏‎‎‏‎"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‎‏‎‏‏‎‏‎‏‏‎‏‎‎‎‏‎‏‎‏‏‏‏‎‎‎‏‎‏‎‎‏‏‎‎‏‏‏‎‏‏‏‏‎‎‏‎‏‏‏‎‎‎‏‎‏‎‏‏‎Bluetooth devices without names (MAC addresses only) will be displayed‎‏‎‎‏‎"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‎‏‏‏‏‎‏‎‏‏‏‏‏‎‏‏‎‎‎‎‏‎‎‎‎‎‎‏‏‎‏‏‏‏‎‎‏‎‎‎‏‏‏‎‎‎‎‎‎‏‏‎‎‏‎‎‎‎‏‎Disables the Bluetooth absolute volume feature in case of volume issues with remote devices such as unacceptably loud volume or lack of control.‎‏‎‎‏‎"</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‎‏‎‎‏‏‏‏‎‏‎‎‎‎‏‏‎‎‏‏‎‎‏‎‎‏‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‎‏‏‏‏‎‏‏‏‎‏‏‎‎Enables the Bluetooth Gabeldorche feature stack.‎‏‎‎‏‎"</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‏‎‏‎‎‏‏‎‏‏‏‏‏‏‎‏‎‎‏‏‎‏‎‏‏‏‎‎‎‏‎‏‎‏‏‎‎‎‏‏‏‏‏‎‎‎‎‏‏‏‎‏‎‏‎‎‏‏‎‎Local terminal‎‏‎‎‏‎"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‏‎‎‏‏‎‏‏‏‎‏‎‎‎‏‏‎‎‎‏‏‎‏‎‏‎‏‏‎‎‎‎‎‎‏‏‎‎‎‎‎‏‏‎‏‏‎‏‎‏‏‏‏‏‎‏‎‎‎Enable terminal app that offers local shell access‎‏‎‎‏‎"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‎‏‏‏‏‎‎‏‎‏‏‎‏‎‎‎‏‎‏‏‏‎‏‏‏‏‎‎‏‎‏‎‎‏‎‏‎‎‏‏‎‏‎‏‏‎‎‎‏‏‏‎‏‏‏‎‎‏‎‎HDCP checking‎‏‎‎‏‎"</string>
@@ -379,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‎‏‎‎‏‏‎‎‎‎‎‎‎‎‏‎‏‎‏‎‎‏‎‏‏‎‎‎‏‎‏‎‎‏‎‏‎‏‎‎‎‎‎‏‏‏‎‎‏‏‏‎‎‎‎Protanomaly (red-green)‎‏‎‎‏‎"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‎‎‎‏‎‏‏‎‎‎‏‏‏‎‏‏‎‏‏‎‎‏‎‏‏‏‎‎‏‎‏‎‏‎‎‎‏‎‏‎‏‏‎‏‎‏‎‏‏‎‏‎‏‏‎Tritanomaly (blue-yellow)‎‏‎‎‏‎"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‎‎‏‎‎‏‎‎‎‎‎‏‏‏‎‎‎‎‎‎‎‏‏‎‏‎‏‏‎‏‎‏‏‎‎‎‏‎‏‏‎‎‏‏‎‎‏‏‏‎‏‎‎‎‏‎‏‏‎‎Color correction‎‏‎‎‏‎"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‎‎‎‎‎‎‎‏‎‎‏‎‏‏‏‏‎‏‎‏‎‎‎‎‎‏‎‏‎‏‎‏‏‏‎‎‏‏‎‏‏‏‏‎‎‎‏‏‎‎‎‏‎‎‎‏‏‏‏‎This feature is experimental and may affect performance.‎‏‎‎‏‎"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‏‎‏‎‎‎‎‎‎‎‎‏‎‎‏‎‎‏‎‏‏‎‎‎‎‏‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‎‎‎‎‏‏‎‎Color correction helps people with color blindness to see more accurate colors‎‏‎‎‏‎"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‏‏‎‏‎‎‏‎‏‎‏‎‏‎‏‎‏‎‏‏‎‏‎‎‎‎‏‎‏‏‎‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‎‏‎Overridden by ‎‏‎‎‏‏‎<xliff:g id="TITLE">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‎‏‏‏‏‎‎‏‎‏‏‏‎‎‏‏‎‎‎‎‏‏‎‎‏‏‏‎‎‎‏‏‏‎‎‏‏‎‎‏‎‎‏‏‎‎‏‏‎‏‎‎‎‎‏‏‏‎‏‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%1$s</xliff:g>‎‏‎‎‏‏‏‎ - ‎‏‎‎‏‏‎<xliff:g id="TIME_STRING">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‏‎‎‎‎‎‏‎‏‎‏‎‏‎‏‎‏‏‎‎‏‎‏‏‎‎‏‎‏‏‎‏‏‎‎‏‎‏‏‎‏‏‏‎‏‏‎‏‎‎‏‏‏‎About ‎‏‎‎‏‏‎<xliff:g id="TIME_REMAINING">%1$s</xliff:g>‎‏‎‎‏‏‏‎ left‎‏‎‎‏‎"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/arrays.xml b/packages/SettingsLib/res/values-es-rUS/arrays.xml
index 788e21f277fb..d37ffb781087 100644
--- a/packages/SettingsLib/res/values-es-rUS/arrays.xml
+++ b/packages/SettingsLib/res/values-es-rUS/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="2908219194098827570">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Habilitar códecs opcionales"</item>
- <item msgid="9205039209798344398">"Inhabilitar códecs opcionales"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Usar selección del sistema (predeterminado)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="3517061573669307965">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Habilitar códecs opcionales"</item>
- <item msgid="7416462860415701287">"Inhabilitar códecs opcionales"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Usar selección del sistema (predeterminado)"</item>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 6a6f800c4684..8899c072bf5b 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -147,7 +147,7 @@
<string name="tether_settings_title_wifi" msgid="4803402057533895526">"Hotspot portátil"</string>
<string name="tether_settings_title_bluetooth" msgid="916519902721399656">"Conexión Bluetooth"</string>
<string name="tether_settings_title_usb_bluetooth" msgid="1727111807207577322">"Compartir conexión"</string>
- <string name="tether_settings_title_all" msgid="8910259483383010470">"Hotspots y dispositivos portátiles"</string>
+ <string name="tether_settings_title_all" msgid="8910259483383010470">"Conexión móvil y hotspot"</string>
<string name="managed_user_title" msgid="449081789742645723">"Todas las apps de trabajo"</string>
<string name="user_guest" msgid="6939192779649870792">"Invitado"</string>
<string name="unknown" msgid="3544487229740637809">"Desconocido"</string>
@@ -224,9 +224,10 @@
<string name="wifi_verbose_logging" msgid="1785910450009679371">"Habilitar registro detallado de Wi-Fi"</string>
<string name="wifi_scan_throttling" msgid="2985624788509913617">"Limitación de búsqueda de Wi-Fi"</string>
<string name="mobile_data_always_on" msgid="8275958101875563572">"Datos móviles siempre activados"</string>
- <string name="tethering_hardware_offload" msgid="4116053719006939161">"Aceleración de hardware de conexión mediante dispositivo portátil"</string>
+ <string name="tethering_hardware_offload" msgid="4116053719006939161">"Aceleración de hardware de conexión mediante dispositivo móvil"</string>
<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 de AVRCP del Bluetooth"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Selecciona la versión de AVRCP del Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Códec del audio Bluetooth"</string>
@@ -265,7 +266,7 @@
<string name="allow_mock_location_summary" msgid="179780881081354579">"Permitir ubicaciones de prueba"</string>
<string name="debug_view_attributes" msgid="3539609843984208216">"Habilitar inspección de atributos de vista"</string>
<string name="mobile_data_always_on_summary" msgid="1112156365594371019">"Mantener siempre los datos móviles activos, incluso cuando esté activada la conexión Wi‑Fi (para cambiar de red de forma rápida)."</string>
- <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Usar la aceleración de hardware de conexión mediante dispositivo portátil si está disponible"</string>
+ <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Usar la aceleración de hardware de conexión mediante dispositivo móvil si está disponible"</string>
<string name="adb_warning_title" msgid="7708653449506485728">"¿Permitir depuración por USB?"</string>
<string name="adb_warning_message" msgid="8145270656419669221">"La depuración por USB solo está indicada para actividades de programación. Úsala para copiar datos entre tu computadora y el dispositivo, para instalar aplicaciones en el dispositivo sin recibir notificaciones y para leer datos de registro."</string>
<string name="adb_keys_warning_message" msgid="2968555274488101220">"¿Quieres revocar el acceso a la depuración por USB desde todas la computadoras que autorizaste hasta ahora?"</string>
@@ -275,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Comprobar que las aplicaciones instaladas mediante ADB/ADT no ocasionen daños"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Se mostrarán los dispositivos Bluetooth sin nombre (solo direcciones MAC)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Inhabilita la función de volumen absoluto de Bluetooth si se producen problemas de volumen con dispositivos remotos (por ejemplo, volumen demasiado alto o falta de control)."</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Habilita la pila de funciones de Bluetooth Gabeldorsche."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Terminal local"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Habilitar aplicac. de terminal que ofrece acceso al shell local"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"Comprobación HDCP"</string>
@@ -379,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalía (rojo-verde)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalía (azul-amarillo)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Corrección de color"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"Esta función es experimental y puede afectar el rendimiento."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"La corrección de colores ayuda a las personas con daltonismo a ver colores más exactos"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Reemplazado por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Tiempo restante: aproximadamente <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-es/arrays.xml b/packages/SettingsLib/res/values-es/arrays.xml
index aed4a4e37644..04d4b2de5c87 100644
--- a/packages/SettingsLib/res/values-es/arrays.xml
+++ b/packages/SettingsLib/res/values-es/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="2908219194098827570">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Habilitar códecs opcionales"</item>
- <item msgid="9205039209798344398">"Inhabilitar códecs opcionales"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Usar preferencia del sistema (predeterminado)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="3517061573669307965">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Habilitar códecs opcionales"</item>
- <item msgid="7416462860415701287">"Inhabilitar códecs opcionales"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Usar preferencia del sistema (predeterminado)"</item>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index e29773ab0218..83ae2df2e8aa 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -227,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Aceleración por hardware para conexión compartida"</string>
<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_a2dp_codec_type" msgid="952001408455456494">"Códec de audio de Bluetooth"</string>
@@ -275,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Comprobar las aplicaciones instaladas mediante ADB/ADT para detectar comportamientos dañinos"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Mostrar dispositivos Bluetooth sin nombre (solo direcciones MAC)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Inhabilitar la función de volumen absoluto de Bluetooth si se producen problemas de volumen con dispositivos remotos (por ejemplo, volumen demasiado alto o falta de control)"</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Habilita la pila de funciones de Bluetooth Gabeldorsche."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Terminal local"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Habilitar aplicación de terminal que ofrece acceso a shell local"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"Comprobación de HDCP"</string>
@@ -379,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalía (rojo-verde)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalía (azul-amarillo)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Corrección de color"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"Esta función es experimental y puede afectar al rendimiento."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"La corrección del color ayuda a las personas con daltonismo a ver los colores más reales"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Anulado por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g>: <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Tiempo restante aproximado: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-et/arrays.xml b/packages/SettingsLib/res/values-et/arrays.xml
index 6a03c1407975..14a68b0e211a 100644
--- a/packages/SettingsLib/res/values-et/arrays.xml
+++ b/packages/SettingsLib/res/values-et/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"Heli: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="2908219194098827570">"Heli: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Lubatakse valikulised kodekid"</item>
- <item msgid="9205039209798344398">"Keelatakse valikulised kodekid"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Süsteemi valiku kasutamine (vaikeseade)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"Heli: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="3517061573669307965">"Heli: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Lubatakse valikulised kodekid"</item>
- <item msgid="7416462860415701287">"Keelatakse valikulised kodekid"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Süsteemi valiku kasutamine (vaikeseade)"</item>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index f425e1e9fb89..297e965ca476 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -227,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Ühenduse jagamise riistvaraline kiirendus"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Kuva ilma nimedeta Bluetoothi seadmed"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Keela absoluutne helitugevus"</string>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Luba Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetoothi AVRCP versioon"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Valige Bluetoothi AVRCP versioon"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetoothi heli kodek"</string>
@@ -275,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Kontrolli, kas ADB/ADT-ga installitud rakendused on ohtlikud."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Kuvatakse ilma nimedeta (ainult MAC-aadressidega) Bluetoothi seadmed"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Keelatakse Bluetoothi absoluutse helitugevuse funktsioon, kui kaugseadmetega on helitugevuse probleeme (nt liiga vali heli või juhitavuse puudumine)."</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Lubab Bluetoothi Gabeldorche\'i funktsiooni virnastamise."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Kohalik terminal"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Luba kohalikku turvalist juurdepääsu pakkuv terminalirakendus"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP-kontrollimine"</string>
@@ -379,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaalia (punane-roheline)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaalia (sinine-kollane)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Värvide korrigeerimine"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"See funktsioon on katseline ja võib mõjutada toimivust."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Värviparanduse funktsioon aitab värvipimedatel värve täpsemini näha"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Alistas <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Ligikaudu <xliff:g id="TIME_REMAINING">%1$s</xliff:g> jäänud"</string>
diff --git a/packages/SettingsLib/res/values-eu/arrays.xml b/packages/SettingsLib/res/values-eu/arrays.xml
index 3dd699365e4d..e87413cd5a47 100644
--- a/packages/SettingsLib/res/values-eu/arrays.xml
+++ b/packages/SettingsLib/res/values-eu/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audioa"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audioa"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Gaitu aukerako kodekak"</item>
- <item msgid="9205039209798344398">"Desgaitu aukerako kodekak"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Erabili sistema-hautapena (lehenetsia)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audioa"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audioa"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Gaitu aukerako kodekak"</item>
- <item msgid="7416462860415701287">"Desgaitu aukerako kodekak"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Erabili sistema-hautapena (lehenetsia)"</item>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index e9810e502310..07d5ccbb840f 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -227,6 +227,8 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Konexioa partekatzeko hardwarearen azelerazioa"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Erakutsi Bluetooth gailuak izenik gabe"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Desgaitu bolumen absolutua"</string>
+ <!-- no translation found for bluetooth_enable_gabeldorsche (9131730396242883416) -->
+ <skip />
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP bertsioa"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Hautatu Bluetooth AVRCP bertsioa"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth bidezko audioaren kodeka"</string>
@@ -275,6 +277,8 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Egiaztatu ADB/ADT bidez instalatutako aplikazioak portaera kaltegarriak atzemateko"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Bluetooth gailuak izenik gabe (MAC helbideak soilik) erakutsiko dira"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Bluetooth bidezko bolumen absolutuaren eginbidea desgaitu egiten du urruneko gailuetan arazoak hautematen badira; esaterako, bolumena ozenegia bada edo ezin bada kontrolatu"</string>
+ <!-- no translation found for bluetooth_enable_gabeldorsche_summary (8472344901097607030) -->
+ <skip />
<string name="enable_terminal_title" msgid="3834790541986303654">"Tokiko terminala"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Gaitu tokiko shell-sarbidea duen terminal-aplikazioa"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP egiaztapena"</string>
@@ -379,7 +383,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanopia (gorri-berdeak)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanopia (urdin-horia)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Koloreen zuzenketa"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"Eginbidea esperimentala da eta eragina izan dezake funtzionamenduan."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Kolore-zuzenketak kolore zehatzagoak ikusten laguntzen die koloreentzako itsutasuna duten pertsonei."</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> hobespena gainjarri zaio"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> inguru gelditzen dira"</string>
diff --git a/packages/SettingsLib/res/values-fa/arrays.xml b/packages/SettingsLib/res/values-fa/arrays.xml
index d5248055dced..ba56d24974ba 100644
--- a/packages/SettingsLib/res/values-fa/arrays.xml
+++ b/packages/SettingsLib/res/values-fa/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"صوت <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="2908219194098827570">"صوت <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"فعال کردن کدک‌های اختیاری"</item>
- <item msgid="9205039209798344398">"غیرفعال کردن کدک‌های اختیاری"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"استفاده از انتخاب سیستم (پیش‌فرض)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"صوت <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="3517061573669307965">"صوت <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"فعال کردن کدک‌های اختیاری"</item>
- <item msgid="7416462860415701287">"غیرفعال کردن کدک‌های اختیاری"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"استفاده از انتخاب سیستم (پیش‌فرض)"</item>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 2f25ab2f66ce..61fe37a81cf4 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -227,6 +227,7 @@
<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">"‏نسخه AVRCP بلوتوث"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"‏انتخاب نسخه AVRCP بلوتوث"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"کدک بلوتوث صوتی"</string>
@@ -275,6 +276,7 @@
<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="8472344901097607030">"‏دسته ویژگی Gabeldorche، بلوتوث را فعال می‌کند."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"ترمینال محلی"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"فعال کردن ترمینال برنامه‌ کاربردی که دسترسی به برنامه محلی را پیشنهاد می‌کند"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"‏بررسی HDCP"</string>
@@ -379,7 +381,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="5190814747212060815">"این ویژگی آزمایشی است و ممکن است عملکرد را تحت تأثیر قرار دهد."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"تصحیح رنگ به افراد مبتلا به کوررنگی کمک می‌کند رنگ‌ها را دقیق‌تر ببینند"</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>
diff --git a/packages/SettingsLib/res/values-fi/arrays.xml b/packages/SettingsLib/res/values-fi/arrays.xml
index 6f3489ca3362..79a46ba71cff 100644
--- a/packages/SettingsLib/res/values-fi/arrays.xml
+++ b/packages/SettingsLib/res/values-fi/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ‑ääni"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ‑ääni"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Ota valinnaiset koodekit käyttöön"</item>
- <item msgid="9205039209798344398">"Poista valinnaiset koodekit käytöstä"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Käytä järjestelmän valintaa (oletus)."</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ‑ääni"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ‑ääni"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Ota valinnaiset koodekit käyttöön"</item>
- <item msgid="7416462860415701287">"Poista valinnaiset koodekit käytöstä"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Käytä järjestelmän valintaa (oletus)."</item>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index a9904af047e8..7e8b160c21b1 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -227,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Laitteistokiihdytyksen yhteyden jakaminen"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Näytä nimettömät Bluetooth-laitteet"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Poista yleinen äänenvoimakkuuden säätö käytöstä"</string>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Ota Gabeldorsche käyttöön"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetoothin AVRCP-versio"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Valitse Bluetoothin AVRCP-versio"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth-äänen koodekki"</string>
@@ -275,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Tarkista ADB:n/ADT:n kautta asennetut sovellukset haitallisen toiminnan varalta."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Näytetään Bluetooth-laitteet, joilla ei ole nimiä (vain MAC-osoitteet)."</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Bluetoothin yleinen äänenvoimakkuuden säätö poistetaan käytöstä ongelmien välttämiseksi esimerkiksi silloin, kun laitteen äänenvoimakkuus on liian kova tai sitä ei voi säätää."</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Bluetoothin Gabeldorche-ominaisuuspino tulee käyttöön."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Paikallinen pääte"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Ota käyttöön päätesov. joka mahdollistaa paikall. liittymäkäytön"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP-tarkistus"</string>
@@ -379,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalia (puna-vihersokeus)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalia (sini-keltasokeus)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Värikorjaus"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"Tämä ominaisuus on kokeellinen ja voi vaikuttaa suorituskykyyn."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Värinkorjaus auttaa värisokeita tulkitsemaan värejä"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Tämän ohittaa <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Noin <xliff:g id="TIME_REMAINING">%1$s</xliff:g> jäljellä"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/arrays.xml b/packages/SettingsLib/res/values-fr-rCA/arrays.xml
index d6147cdd1a89..3ee320993876 100644
--- a/packages/SettingsLib/res/values-fr-rCA/arrays.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="2908219194098827570">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Activer les codecs optionnels"</item>
- <item msgid="9205039209798344398">"Désactiver les codecs optionnels"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Utiliser sélect. du système (par défaut)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="3517061573669307965">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Activer les codecs optionnels"</item>
- <item msgid="7416462860415701287">"Désactiver les codecs optionnels"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Utiliser sélect. du système (par défaut)"</item>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 0f1c213c1974..d21eeefe5bb2 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -227,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Accélération matérielle pour le partage de connexion"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Afficher les appareils Bluetooth sans nom"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Désactiver le volume absolu"</string>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Activer le Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Version du profil Bluetooth AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Sélectionner la version du profil Bluetooth AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Codec audio Bluetooth"</string>
@@ -275,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Vérifier que les applications installées par ADB/ADT ne présentent pas de comportement dangereux."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Les appareils Bluetooth sans nom (adresses MAC seulement) seront affichés"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Désactive la fonctionnalité de volume absolu par Bluetooth en cas de problème de volume sur les appareils à distance, par exemple si le volume est trop élevé ou s\'il ne peut pas être contrôlé."</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Active la pile de la fonctionnalité Bluetooth Gabeldorche."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Terminal local"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Activer l\'application Terminal permettant l\'accès au shell local"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"Vérification HDCP"</string>
@@ -379,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalie (rouge/vert)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalie (bleu/jaune)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Correction des couleurs"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"Cette fonctionnalité est expérimentale et peut affecter les performances."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"La correction des couleurs aide les personnes atteintes de daltonisme à mieux percevoir les couleurs"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Remplacé par <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> : <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Il reste environ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-fr/arrays.xml b/packages/SettingsLib/res/values-fr/arrays.xml
index 39f782684b35..e23fc6a594ad 100644
--- a/packages/SettingsLib/res/values-fr/arrays.xml
+++ b/packages/SettingsLib/res/values-fr/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="2908219194098827570">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Activer les codecs facultatifs"</item>
- <item msgid="9205039209798344398">"Désactiver les codecs facultatifs"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Utiliser la sélection du système (par défaut)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="3517061573669307965">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Activer les codecs facultatifs"</item>
- <item msgid="7416462860415701287">"Désactiver les codecs facultatifs"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Utiliser la sélection du système (par défaut)"</item>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 0bfb3c7e8151..23dd5a83e113 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -60,9 +60,8 @@
<string name="speed_label_okay" msgid="1253594383880810424">"Correct"</string>
<string name="speed_label_medium" msgid="9078405312828606976">"Moyenne"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Élevée"</string>
- <string name="speed_label_very_fast" msgid="8215718029533182439">"Très élevée"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="speed_label_very_fast" msgid="8215718029533182439">"Très rapide"</string>
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Arrivé à expiration"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Déconnecté"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Déconnexion…"</string>
@@ -228,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Accélération matérielle pour le partage de connexion"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Afficher les appareils Bluetooth sans nom"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Désactiver le volume absolu"</string>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Activer Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Version Bluetooth AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Sélectionner la version Bluetooth AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Codec audio Bluetooth"</string>
@@ -276,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Vérifier que les applications installées par ADB/ADT ne présentent pas de comportement dangereux"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Les appareils Bluetooth sans nom (adresses MAC seulement) seront affichés"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Désactive la fonctionnalité de volume absolu du Bluetooth en cas de problème de volume sur les appareils à distance, par exemple si le volume est trop élevé ou s\'il ne peut pas être contrôlé"</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Active la pile de fonctionnalités Bluetooth Gabeldorsche."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Terminal local"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Activer l\'application Terminal permettant l\'accès au shell local"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"Vérification HDCP"</string>
@@ -380,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalie (rouge/vert)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalie (bleu-jaune)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Correction couleur"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"Cette fonctionnalité est expérimentale et peut affecter les performances."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"La correction des couleurs aide les personnes atteintes de daltonisme à mieux percevoir les couleurs"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Remplacé par <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Temps restant : environ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-gl/arrays.xml b/packages/SettingsLib/res/values-gl/arrays.xml
index e59ec51718a4..c0a5a80782c0 100644
--- a/packages/SettingsLib/res/values-gl/arrays.xml
+++ b/packages/SettingsLib/res/values-gl/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="2908219194098827570">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Activar códecs opcionais"</item>
- <item msgid="9205039209798344398">"Desactivar códecs opcionais"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Usa a selección do sistema (predeterminado)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="3517061573669307965">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Activa os códecs opcionais"</item>
- <item msgid="7416462860415701287">"Desactiva os códecs opcionais"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Usar selección do sistema (predeterminado)"</item>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 213d33ae0cac..c8f6f81c3426 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -227,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Aceleración de hardware para conexión compartida"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Mostrar dispositivos Bluetooth sen nomes"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Desactivar volume absoluto"</string>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Activar Gabeldorsche"</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 a versión de Bluetooth AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Códec de audio por Bluetooth"</string>
@@ -275,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Comproba as aplicacións instaladas a través de ADB/ADT para detectar comportamento perigoso"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Mostraranse dispositivos Bluetooth sen nomes (só enderezos MAC)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Desactiva a función do volume absoluto do Bluetooth en caso de que se produzan problemas de volume cos dispositivos remotos, como volume demasiado alto ou falta de control"</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Activa a pilla de funcións Bluetooth Gabeldorche."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Terminal local"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Activa a aplicación terminal que ofrece acceso ao shell local"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"Comprobación HDCP"</string>
@@ -379,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalía (vermello-verde)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalía (azul-amarelo)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Corrección da cor"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"Esta función é experimental e pode afectar ao rendemento."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"A corrección das cores axuda ás persoas con daltonismo a ver as cores con maior precisión"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Anulado por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Tempo restante aproximado: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-gu/arrays.xml b/packages/SettingsLib/res/values-gu/arrays.xml
index 35a940486768..75c904d5a158 100644
--- a/packages/SettingsLib/res/values-gu/arrays.xml
+++ b/packages/SettingsLib/res/values-gu/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ઑડિઓ"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ઑડિઓ"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"વૈકલ્પિક કોડેક સક્ષમ કરો"</item>
- <item msgid="9205039209798344398">"વૈકલ્પિક કોડેક અક્ષમ કરો"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"સિસ્ટમ પસંદગીનો ઉપયોગ કરો (ડિફૉલ્ટ)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ઑડિઓ"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ઑડિઓ"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"વૈકલ્પિક કોડેક સક્ષમ કરો"</item>
- <item msgid="7416462860415701287">"વૈકલ્પિક કોડેક અક્ષમ કરો"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"સિસ્ટમ પસંદગીનો ઉપયોગ કરો (ડિફૉલ્ટ)"</item>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 8192d47036a7..d274674b238b 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -227,6 +227,7 @@
<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">"બ્લૂટૂથ AVRCP સંસ્કરણ"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"બ્લૂટૂથ AVRCP સંસ્કરણ પસંદ કરો"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"બ્લૂટૂથ ઑડિઓ કોડેક"</string>
@@ -275,6 +276,7 @@
<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="8472344901097607030">"બ્લૂટૂથ Gabeldorche સુવિધા સ્ટૅક ચાલુ કરે છે."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"સ્થાનિક ટર્મિનલ"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"સ્થાનિક શેલ અ‍ૅક્સેસની ઑફર કરતી ટર્મિનલ એપ્લિકેશનને સક્ષમ કરો"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP તપાસણી"</string>
@@ -379,7 +381,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="5190814747212060815">"આ સુવિધા પ્રાયોગિક છે અને કામગીરી પર અસર કરી શકે છે."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"રંગ સુધારણા રંગ અંધત્વવાળા લોકોને વધુ સચોટ રંગો જોવામાં સહાય કરે છે"</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>
diff --git a/packages/SettingsLib/res/values-hi/arrays.xml b/packages/SettingsLib/res/values-hi/arrays.xml
index 4a3eca6f33c5..ffaf80a21413 100644
--- a/packages/SettingsLib/res/values-hi/arrays.xml
+++ b/packages/SettingsLib/res/values-hi/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ऑडियो"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ऑडियो"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"वैकल्पिक कोडेक चालू करें"</item>
- <item msgid="9205039209798344398">"वैकल्पिक कोडेक अक्षम करें"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"सिस्टम से चुने जाने का उपयोग करें (डिफ़ॉल्ट)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ऑडियो"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ऑडियो"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"वैकल्पिक कोडेक चालू करें"</item>
- <item msgid="7416462860415701287">"वैकल्पिक कोडेक अक्षम करें"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"सिस्टम से चुने जाने का उपयोग करें (डिफ़ॉल्ट)"</item>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 207a479253ac..154f38604b26 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -60,7 +60,7 @@
<string name="speed_label_okay" msgid="1253594383880810424">"ठीक है"</string>
<string name="speed_label_medium" msgid="9078405312828606976">"मध्यम"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"तेज़"</string>
- <string name="speed_label_very_fast" msgid="8215718029533182439">"अत्‍यधिक तेज़"</string>
+ <string name="speed_label_very_fast" msgid="8215718029533182439">"बहुत ज़्यादा तेज़"</string>
<string name="wifi_passpoint_expired" msgid="6540867261754427561">"समयसीमा खत्म हो गई"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"डिसकनेक्ट किया गया"</string>
@@ -227,6 +227,8 @@
<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>
+ <!-- no translation found for bluetooth_enable_gabeldorsche (9131730396242883416) -->
+ <skip />
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"ब्लूटूथ एवीआरसीपी वर्शन"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"ब्लूटूथ AVRCP वर्शन चुनें"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"ब्लूटूथ ऑडियो कोडेक"</string>
@@ -275,6 +277,8 @@
<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>
+ <!-- no translation found for bluetooth_enable_gabeldorsche_summary (8472344901097607030) -->
+ <skip />
<string name="enable_terminal_title" msgid="3834790541986303654">"स्थानीय टर्मिनल"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"लोकल शेल तक पहुंचने की सुविधा देने वाले टर्मिनल ऐप को चालू करें"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"एचडीसीपी जाँच"</string>
@@ -379,7 +383,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="5190814747212060815">"यह सुविधा प्रायोगिक है और निष्पादन को प्रभावित कर सकती है."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"रंग में सुधार करने की सेटिंग, वर्णान्धता (कलर ब्लाइंडनेस) वाले लोगों को ज़्यादा सटीक रंग देखने में मदद करती है"</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>
@@ -409,7 +413,7 @@
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> में पूरा चार्ज हो जाएगा"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"अज्ञात"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"चार्ज हो रही है"</string>
- <string name="battery_info_status_charging_lower" msgid="8696042568167401574">"चार्ज किया जा रहा है"</string>
+ <string name="battery_info_status_charging_lower" msgid="8696042568167401574">"चार्ज हो रही है"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"चार्ज नहीं हो रही है"</string>
<string name="battery_info_status_not_charging" msgid="8330015078868707899">"प्लग इन है, अभी चार्ज नहीं हो सकती"</string>
<string name="battery_info_status_full" msgid="4443168946046847468">"पूरी"</string>
diff --git a/packages/SettingsLib/res/values-hr/arrays.xml b/packages/SettingsLib/res/values-hr/arrays.xml
index f5e419430dd2..ec979f6852dc 100644
--- a/packages/SettingsLib/res/values-hr/arrays.xml
+++ b/packages/SettingsLib/res/values-hr/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Omogućivanje izbornih kodeka"</item>
- <item msgid="9205039209798344398">"Onemogućivanje izbornih kodeka"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Upotreba odabira sustava (zadano)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Omogućivanje izbornih kodeka"</item>
- <item msgid="7416462860415701287">"Onemogućivanje izbornih kodeka"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Upotreba odabira sustava (zadano)"</item>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 97a58625b3d5..84adcaab19eb 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -227,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Hardversko ubrzanje za modemsko povezivanje"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Prikaži Bluetooth uređaje bez naziva"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Onemogući apsolutnu glasnoću"</string>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Omogući Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Verzija AVRCP-a za Bluetooth"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Odaberite verziju AVRCP-a za Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Kodek za Bluetooth Audio"</string>
@@ -275,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Provjerite uzrokuju li aplikacije instalirane putem ADB-a/ADT-a poteškoće"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Prikazivat će se Bluetooth uređaji bez naziva (samo MAC adrese)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Onemogućuje Bluetoothovu značajku apsolutne glasnoće ako udaljeni uređaji imaju poteškoća sa zvukom, kao što su neprihvatljiva glasnoća ili nepostojanje kontrole"</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Omogućuje nizove značajke Bluetooth Gabeldorche."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Lokalni terminal"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Omogući aplikaciju terminala koja nudi pristup lokalnoj ovojnici"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP provjera"</string>
@@ -379,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalija (crveno – zeleno)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalija (plavo – žuto)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Korekcija boje"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"Ova je značajka eksperimentalna i može utjecati na performanse."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Korekcija boje pomaže slijepima za boje da vide preciznije boje"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Premošćeno postavkom <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Još otprilike <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-hu/arrays.xml b/packages/SettingsLib/res/values-hu/arrays.xml
index 78f08e4236e4..64d92e4d7377 100644
--- a/packages/SettingsLib/res/values-hu/arrays.xml
+++ b/packages/SettingsLib/res/values-hu/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"Hang: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="2908219194098827570">"Hang: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Nem kötelező kodekek engedélyezése"</item>
- <item msgid="9205039209798344398">"Nem kötelező kodekek letiltása"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Rendszerérték (alapértelmezett)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"Hang: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="3517061573669307965">"Hang: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Engedélyezi a nem kötelező kodekeket"</item>
- <item msgid="7416462860415701287">"Letiltja a nem kötelező kodekeket"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Rendszerérték (alapértelmezett)"</item>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index cba6c6554b8a..cb87e5628d88 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -227,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Internetmegosztás hardveres gyorsítása"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Név nélküli Bluetooth-eszközök megjelenítése"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Abszolút hangerő funkció letiltása"</string>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"A Gabeldorsche engedélyezése"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"A Bluetooth AVRCP-verziója"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"A Bluetooth AVRCP-verziójának kiválasztása"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth hang – Kodek"</string>
@@ -275,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Az ADB/ADT útján telepített alkalmazások ellenőrzése kártékony viselkedésre."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Név nélküli Bluetooth-eszközök jelennek meg (csak MAC-címekkel)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Letiltja a Bluetooth abszolút hangerő funkcióját a távoli eszközökkel kapcsolatos hangerőproblémák – például elfogadhatatlanul magas vagy nem vezérelhető hangerő – esetén."</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Engedélyezi a Bluetooth Gabeldorche funkcióit."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Helyi végpont"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Végalkalmazás engedélyezése a helyi rendszerhéj eléréséhez"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP ellenőrzés"</string>
@@ -379,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomália (piros– zöld)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomália (kék–sárga)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Színkorrekció"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"Ez egy kísérleti funkció, és hatással lehet a teljesítményre."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"A színkorrekció segít a színtévesztőknek abban, hogy pontosabban lássák a színeket"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Felülírva erre: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Körülbelül <xliff:g id="TIME_REMAINING">%1$s</xliff:g> maradt hátra"</string>
diff --git a/packages/SettingsLib/res/values-hy/arrays.xml b/packages/SettingsLib/res/values-hy/arrays.xml
index d95141ba6f39..b1226f4d76a6 100644
--- a/packages/SettingsLib/res/values-hy/arrays.xml
+++ b/packages/SettingsLib/res/values-hy/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> աուդիո"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> աուդիո"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Միացնել լրացուցիչ կոդեկները"</item>
- <item msgid="9205039209798344398">"Անջատել լրացուցիչ կոդեկները"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Օգտագործել համակարգի կարգավորումը (կանխադրված)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> աուդիո"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> աուդիո"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Միացնել լրացուցիչ կոդեկները"</item>
- <item msgid="7416462860415701287">"Անջատել լրացուցիչ կոդեկները"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Օգտագործել համակարգի կարգավորումը (կանխադրված)"</item>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index a76c9609079e..6c30d4ee942a 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -227,6 +227,7 @@
<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>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Միացնել Gabeldorsche-ը"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP տարբերակը"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Ընտրել Bluetooth AVRCP տարբերակը"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth աուդիո կոդեկ"</string>
@@ -275,6 +276,7 @@
<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="8472344901097607030">"Միացնել Bluetooth Gabeldorche գործառույթի զտիչը"</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Տեղային տերմինալ"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Միացնել տերմինալային հավելվածը, որն առաջարկում է մուտք տեղային խեցի"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP ստուգում"</string>
@@ -379,7 +381,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="5190814747212060815">"Սա փորձնական գործառույթ է և կարող է ազդել սարքի աշխատանքի վրա:"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Գունաշտկումն օգնում է գունային դալտոնիզմ ունեցող մարդկանց ավելի ճշգրիտ տեսնել գույները"</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>
diff --git a/packages/SettingsLib/res/values-in/arrays.xml b/packages/SettingsLib/res/values-in/arrays.xml
index 53a4a36fc799..9d2528a45255 100644
--- a/packages/SettingsLib/res/values-in/arrays.xml
+++ b/packages/SettingsLib/res/values-in/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="2908219194098827570">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Aktifkan Codec Opsional"</item>
- <item msgid="9205039209798344398">"Nonaktifkan Codec Opsional"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Gunakan Pilihan Sistem (Default)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="3517061573669307965">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Aktifkan Codec Opsional"</item>
- <item msgid="7416462860415701287">"Nonaktifkan Codec Opsional"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Gunakan Pilihan Sistem (Default)"</item>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 0feae4ee2266..654c06cc7b10 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -227,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Akselerasi hardware tethering"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Tampilkan perangkat Bluetooth tanpa nama"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Nonaktifkan volume absolut"</string>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Aktifkan Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Versi AVRCP Bluetooth"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Pilih Versi AVRCP Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Codec Audio Bluetooth"</string>
@@ -275,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Periksa perilaku membahayakan dalam aplikasi yang terpasang 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="8472344901097607030">"Aktifkan stack fitur Gabeldorche Bluetooth."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Terminal lokal"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Aktifkan aplikasi terminal yang menawarkan akses kerangka lokal"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"Pemeriksaan HDCP"</string>
@@ -379,7 +381,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="5190814747212060815">"Fitur ini bersifat eksperimental dan dapat memengaruhi kinerja."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Koreksi warna membantu orang penderita buta warna untuk melihat warna yang lebih akurat"</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>
diff --git a/packages/SettingsLib/res/values-is/arrays.xml b/packages/SettingsLib/res/values-is/arrays.xml
index 294e90685abb..1ac19f1ecc48 100644
--- a/packages/SettingsLib/res/values-is/arrays.xml
+++ b/packages/SettingsLib/res/values-is/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> hljóð"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> hljóð"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Gera valfrjálsa kóðara virka"</item>
- <item msgid="9205039209798344398">"Gera valfrjálsa kóðara óvirka"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Nota val kerfisins (sjálfgefið)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> hljóð"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> hljóð"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Gera valfrjálsa kóðara virka"</item>
- <item msgid="7416462860415701287">"Gera valfrjálsa kóðara óvirka"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Nota val kerfisins (sjálfgefið)"</item>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index d45f43318ea2..86626152c077 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -227,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Vélbúnaðarhröðun fyrir tjóðrun"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Sýna Bluetooth-tæki án heita"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Slökkva á samstillingu hljóðstyrks"</string>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Virkja Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP-útgáfa"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Velja Bluetooth AVRCP-útgáfu"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth hljóðkóðari"</string>
@@ -275,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Kanna skaðlega hegðun forrita sem sett eru upp frá ADB/ADT."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Bluetooth-tæki án heita (aðeins MAC-vistfang) verða birt"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Slekkur á samstillingu Bluetooth-hljóðstyrks ef vandamál koma upp með hljóðstyrk hjá fjartengdum tækjum, svo sem of hár hljóðstyrkur eða erfiðleikar við stjórnun."</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Virkjar Bluetooth Gabeldorche eiginleikastafla."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Staðbundin skipanalína"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Virkja skipanalínuforrit sem leyfir staðbundinn skeljaraðgang"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP-athugun"</string>
@@ -379,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Litblinda (rauðgræn)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Litblinda (blágul)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Litaleiðrétting"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"Þessi eiginleiki er á tilraunastigi og getur haft áhrif á frammistöðu."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Litaleiðrétting hjálpar fólki með litblindu að sjá réttari liti"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Hnekkt af <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Um það bil <xliff:g id="TIME_REMAINING">%1$s</xliff:g> eftir"</string>
diff --git a/packages/SettingsLib/res/values-it/arrays.xml b/packages/SettingsLib/res/values-it/arrays.xml
index 94959ee27305..44c519b0c20c 100644
--- a/packages/SettingsLib/res/values-it/arrays.xml
+++ b/packages/SettingsLib/res/values-it/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="2908219194098827570">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Attiva codec facoltativi"</item>
- <item msgid="9205039209798344398">"Disattiva codec facoltativi"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Usa selezione di sistema (predefinita)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="3517061573669307965">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Attiva codec facoltativi"</item>
- <item msgid="7416462860415701287">"Disattiva codec facoltativi"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Usa selezione di sistema (predefinita)"</item>
@@ -150,7 +146,7 @@
<item msgid="5001852592115448348">", attivo (telefono)"</item>
</string-array>
<string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Off"</item>
+ <item msgid="1191094707770726722">"OFF"</item>
<item msgid="7839165897132179888">"64 kB"</item>
<item msgid="2715700596495505626">"256 kB"</item>
<item msgid="7099386891713159947">"1 MB"</item>
@@ -158,13 +154,13 @@
<item msgid="8243549501764402572">"16 MB"</item>
</string-array>
<string-array name="select_logd_size_lowram_titles">
- <item msgid="1145807928339101085">"Off"</item>
+ <item msgid="1145807928339101085">"OFF"</item>
<item msgid="4064786181089783077">"64 kB"</item>
<item msgid="3052710745383602630">"256 kB"</item>
<item msgid="3691785423374588514">"1 MB"</item>
</string-array>
<string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Off"</item>
+ <item msgid="409235464399258501">"OFF"</item>
<item msgid="4195153527464162486">"64 kB/buffer log"</item>
<item msgid="7464037639415220106">"256 kB/buffer log"</item>
<item msgid="8539423820514360724">"1 MB/buffer log"</item>
@@ -172,13 +168,13 @@
<item msgid="7892098981256010498">"16 MB/buffer log"</item>
</string-array>
<string-array name="select_logpersist_titles">
- <item msgid="704720725704372366">"Off"</item>
+ <item msgid="704720725704372366">"OFF"</item>
<item msgid="6014837961827347618">"Tutti"</item>
<item msgid="7387060437894578132">"Tutti tranne il segnale radio"</item>
<item msgid="7300881231043255746">"solo kernel"</item>
</string-array>
<string-array name="select_logpersist_summaries">
- <item msgid="97587758561106269">"Off"</item>
+ <item msgid="97587758561106269">"OFF"</item>
<item msgid="7126170197336963369">"Tutti i buffer log"</item>
<item msgid="7167543126036181392">"Tutti tranne i buffer log del segnale radio"</item>
<item msgid="5135340178556563979">"solo buffer log kernel"</item>
@@ -231,17 +227,17 @@
<item msgid="7345673972166571060">"Stack di chiamate su glGetError"</item>
</string-array>
<string-array name="show_non_rect_clip_entries">
- <item msgid="2482978351289846212">"Off"</item>
+ <item msgid="2482978351289846212">"OFF"</item>
<item msgid="3405519300199774027">"Area ritaglio non rettangolare blu"</item>
<item msgid="1212561935004167943">"Evidenzia cmd disegno test in verde"</item>
</string-array>
<string-array name="track_frame_time_entries">
- <item msgid="634406443901014984">"Off"</item>
+ <item msgid="634406443901014984">"OFF"</item>
<item msgid="1288760936356000927">"Su schermo sotto forma di barre"</item>
<item msgid="5023908510820531131">"Tra <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">"Off"</item>
+ <item msgid="1968128556747588800">"OFF"</item>
<item msgid="3033215374382962216">"Mostra aree overdraw"</item>
<item msgid="3474333938380896988">"Mostra aree con deuteranomalia"</item>
</string-array>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index fe111fc0fcd4..0e98d981859b 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -206,7 +206,7 @@
<string name="enable_adb" msgid="8072776357237289039">"Debug USB"</string>
<string name="enable_adb_summary" msgid="3711526030096574316">"Modalità debug quando è connesso tramite USB"</string>
<string name="clear_adb_keys" msgid="3010148733140369917">"Revoca autorizzazioni debug USB"</string>
- <string name="bugreport_in_power" msgid="8664089072534638709">"Scorciatoria segnalazione bug"</string>
+ <string name="bugreport_in_power" msgid="8664089072534638709">"Scorciatoia segnalazione bug"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Mostra un pulsante per segnalare i bug nel menu di accensione"</string>
<string name="keep_screen_on" msgid="1187161672348797558">"Rimani attivo"</string>
<string name="keep_screen_on_summary" msgid="1510731514101925829">"Lo schermo non va mai in stand-by se sotto carica"</string>
@@ -227,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Tethering accelerazione hardware"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Mostra dispositivi Bluetooth senza nome"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Disattiva volume assoluto"</string>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Attiva Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Versione Bluetooth AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Seleziona versione Bluetooth AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Codec audio Bluetooth"</string>
@@ -243,7 +244,7 @@
<string name="bluetooth_select_a2dp_codec_streaming_label" msgid="2040810756832027227">"Streaming: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
<string name="select_private_dns_configuration_title" msgid="7887550926056143018">"DNS privato"</string>
<string name="select_private_dns_configuration_dialog_title" msgid="3731422918335951912">"Seleziona modalità DNS privato"</string>
- <string name="private_dns_mode_off" msgid="7065962499349997041">"Off"</string>
+ <string name="private_dns_mode_off" msgid="7065962499349997041">"OFF"</string>
<string name="private_dns_mode_opportunistic" msgid="1947864819060442354">"Automatico"</string>
<string name="private_dns_mode_provider" msgid="3619040641762557028">"Nome host del provider DNS privato"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="6564868953748514595">"Inserisci il nome host del provider DNS"</string>
@@ -275,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Controlla che le app installate tramite ADB/ADT non abbiano un comportamento dannoso"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Verranno mostrati solo dispositivi Bluetooth senza nome (solo indirizzo MAC)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Disattiva la funzione del volume assoluto Bluetooth in caso di problemi con il volume dei dispositivi remoti, ad esempio un volume troppo alto o la mancanza di controllo"</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Consente di attivare lo stack delle funzionalità Bluetooth Gabeldorche."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Terminale locale"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Abilita l\'app Terminale che offre l\'accesso alla shell locale"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"Verifica HDCP"</string>
@@ -379,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalìa (rosso-verde)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalìa (blu-giallo)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Correzione del colore"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"Questa funzione è sperimentale e potrebbe influire sulle prestazioni."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"La correzione del colore consente alle persone daltoniche di vedere colori più accurati"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Valore sostituito da <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Tempo rimanente: <xliff:g id="TIME_REMAINING">%1$s</xliff:g> circa"</string>
diff --git a/packages/SettingsLib/res/values-iw/arrays.xml b/packages/SettingsLib/res/values-iw/arrays.xml
index 9b9f6e44566a..c8fc6d34c258 100644
--- a/packages/SettingsLib/res/values-iw/arrays.xml
+++ b/packages/SettingsLib/res/values-iw/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"אודיו <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="2908219194098827570">"אודיו <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"‏הפעלה של Codecs אופציונליים"</item>
- <item msgid="9205039209798344398">"‏השבתה של Codecs אופציונליים"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"השתמש בבחירת המערכת (ברירת המחדל)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"אודיו <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="3517061573669307965">"אודיו <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"‏הפעלה של Codecs אופציונליים"</item>
- <item msgid="7416462860415701287">"‏השבתה של Codecs אופציונליים"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"שימוש בבחירת המערכת (ברירת המחדל)"</item>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 8b47c54e5b9e..30a6295d8e45 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -227,6 +227,7 @@
<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>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"‏הפעלת Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"‏Bluetooth גרסה AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"‏בחר Bluetooth גרסה AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"‏Codec אודיו ל-Bluetooth"</string>
@@ -275,6 +276,7 @@
<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="8472344901097607030">"‏הפעלת מקבץ הפיצ\'רים של Bluetooth Gabeldorche."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"מסוף מקומי"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"הפעל אפליקציית מסוף המציעה גישה מקומית למעטפת"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"‏בדיקת HDCP"</string>
@@ -379,7 +381,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="5190814747212060815">"תכונה זו היא ניסיונית ועשויה להשפיע על הביצועים."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"תיקון צבע עוזר למשתמשים עם עיוורון צבעים לראות צבעים מדויקים יותר"</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>
diff --git a/packages/SettingsLib/res/values-ja/arrays.xml b/packages/SettingsLib/res/values-ja/arrays.xml
index 5bca96d0a880..fdc68c6864dc 100644
--- a/packages/SettingsLib/res/values-ja/arrays.xml
+++ b/packages/SettingsLib/res/values-ja/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> オーディオ"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> オーディオ"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"オプションのコーデックの有効化"</item>
- <item msgid="9205039209798344398">"オプションのコーデックの無効化"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"システムの選択(デフォルト)を使用"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> オーディオ"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> オーディオ"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"オプションのコーデックを有効にします"</item>
- <item msgid="7416462860415701287">"オプションのコーデックを無効にします"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"システムの選択(デフォルト)を使用"</item>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index c955a392ea73..22efe44f2162 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -227,6 +227,7 @@
<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>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorsche を有効にする"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP バージョン"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Bluetooth AVRCP バージョンを選択する"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth オーディオ コーデック"</string>
@@ -275,6 +276,7 @@
<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="8472344901097607030">"Bluetooth Gabeldorche 機能スタックを有効にします。"</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"ローカルターミナル"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"ローカルシェルアクセスを提供するターミナルアプリを有効にします"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCPチェック"</string>
@@ -379,7 +381,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="5190814747212060815">"この機能は試験運用機能であり、パフォーマンスに影響することがあります。"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"色補正機能を利用すると、色覚異常のユーザーがより正確に色を判別できるようになります"</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>
diff --git a/packages/SettingsLib/res/values-ka/arrays.xml b/packages/SettingsLib/res/values-ka/arrays.xml
index 6ffafb32c050..dda3b0757d0e 100644
--- a/packages/SettingsLib/res/values-ka/arrays.xml
+++ b/packages/SettingsLib/res/values-ka/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> აუდიო"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> აუდიო"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"არასავალდებულო კოდეკების ჩართვა"</item>
- <item msgid="9205039209798344398">"არასავალდებულო კოდეკების გათიშვა"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"სისტემის არჩეულის გამოყენება (ნაგულისხმევი)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> აუდიო"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> აუდიო"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"არასავალდებულო კოდეკების ჩართვა"</item>
- <item msgid="7416462860415701287">"არასავალდებულო კოდეკების გათიშვა"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"სისტემის არჩეულის გამოყენება (ნაგულისხმევი)"</item>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index d8fda4b34125..0139f586a6f9 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -227,6 +227,7 @@
<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>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorsche-ის ჩართვა"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth-ის AVRCP-ის ვერსია"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"აირჩიეთ Bluetooth-ის AVRCP-ის ვერსია"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth აუდიოს კოდეკი"</string>
@@ -275,6 +276,7 @@
<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="8472344901097607030">"ჩართავს Bluetooth Gabeldorche-ის ფუნქციების დასტას."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"ადგილობრივი ტერმინალი"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"ლოკალურ გარსზე წვდომის ტერმინალური აპლიკაციის ჩართვა"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP შემოწმება"</string>
@@ -379,7 +381,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="5190814747212060815">"ეს ფუნქცია საცდელია და შეიძლება გავლენა იქონიოს ფუნქციონალობაზე."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"ფერის კორექცია ეხმარება ფერითი სიბრმავის მქონე ადამიანებს, უფრო ზუსტად გაარჩიონ ფერები"</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>
diff --git a/packages/SettingsLib/res/values-kk/arrays.xml b/packages/SettingsLib/res/values-kk/arrays.xml
index 26e4ce4d9e4b..70119c870865 100644
--- a/packages/SettingsLib/res/values-kk/arrays.xml
+++ b/packages/SettingsLib/res/values-kk/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> аудиокодегі"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> аудиокодегі"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Қосымша кодектерді қосу"</item>
- <item msgid="9205039209798344398">"Қосымша кодектерді өшіру"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Жүйенің таңдағанын алу (әдепкі)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> аудиокодегі"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> аудиокодегі"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Қосымша кодектерді қосу"</item>
- <item msgid="7416462860415701287">"Қосымша кодектерді өшіру"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Жүйенің таңдағанын алу (әдепкі)"</item>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 025532dbb349..f7a773a95aa9 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -227,6 +227,7 @@
<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>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorsche функциясын іске қосу"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP нұсқасы"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Bluetooth AVRCP нұсқасын таңдау"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth аудиокодегі"</string>
@@ -275,6 +276,7 @@
<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="8472344901097607030">"Bluetooth Gabeldorche функциясын іске қосады."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Жергілікті терминал"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Жергілікті шелл-код қол жетімділігін ұсынатын терминалды қолданбаны қосу"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP тексеру"</string>
@@ -379,7 +381,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="5190814747212060815">"Бұл мүмкіндік эксперименттік болып табылады және өнімділікке әсер етуі мүмкін."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Түсті түзету түсті ажырата алмайтын адамдарға оларды дәлірек көруге көмектеседі"</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>
diff --git a/packages/SettingsLib/res/values-km/arrays.xml b/packages/SettingsLib/res/values-km/arrays.xml
index d57762038562..327754bd43aa 100644
--- a/packages/SettingsLib/res/values-km/arrays.xml
+++ b/packages/SettingsLib/res/values-km/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g>សំឡេង <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g>សំឡេង <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"បើក​កូឌិក​ប្រភេទ​ស្រេច​ចិត្ត"</item>
- <item msgid="9205039209798344398">"បិទ​កូឌិក​ប្រភេទ​ស្រេច​ចិត្ត"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"ប្រើ​ការ​ជ្រើសរើស​ប្រព័ន្ធ (លំនាំ​ដើម)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g>សំឡេង <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g>សំឡេង <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"បើក​កូឌិក​ប្រភេទ​ស្រេច​ចិត្ត"</item>
- <item msgid="7416462860415701287">"បិទ​កូឌិក​ប្រភេទ​ស្រេច​ចិត្ត"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"ប្រើ​ការ​ជ្រើសរើស​ប្រព័ន្ធ (លំនាំ​ដើម)"</item>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index e9f5ab0ff18d..5c64a403cea8 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -60,7 +60,7 @@
<string name="speed_label_okay" msgid="1253594383880810424">"យល់ព្រម"</string>
<string name="speed_label_medium" msgid="9078405312828606976">"មធ្យម"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"លឿន"</string>
- <string name="speed_label_very_fast" msgid="8215718029533182439">"លឿន​ណាស់"</string>
+ <string name="speed_label_very_fast" msgid="8215718029533182439">"លឿន​ខ្លាំង"</string>
<string name="wifi_passpoint_expired" msgid="6540867261754427561">"ផុតកំណត់"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"បាន​ផ្ដាច់"</string>
@@ -227,6 +227,7 @@
<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">"កំណែប្ល៊ូធូស AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"ជ្រើសរើសកំណែប្ល៊ូធូស AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"កូឌិក​សំឡេង​ប៊្លូធូស"</string>
@@ -275,6 +276,7 @@
<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="8472344901097607030">"បើក​ជង់​មុខងារ​ប៊្លូធូស Gabeldorche​។"</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"ស្ថានីយ​មូលដ្ឋាន"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"បើក​កម្មវិធី​ស្ថានីយ​ដែល​ផ្ដល់​ការ​ចូល​សែល​មូលដ្ឋាន"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"ពិនិត្យ HDCP"</string>
@@ -379,7 +381,7 @@
<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="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"មុខងារនេះ​គឺ​ជា​ការ​ពិសោធន៍ ហើយ​អាច​ប៉ះពាល់​ដំណើរការ​។"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"ការកែតម្រូវ​ពណ៌​ជួយដល់​អ្នកដែល​មិនអាច​បែងចែក​ពណ៌​ឱ្យមើលឃើញ​ពណ៌ដែលត្រឹមត្រូវ​ជាមុន"</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>
diff --git a/packages/SettingsLib/res/values-kn/arrays.xml b/packages/SettingsLib/res/values-kn/arrays.xml
index 956fd6b2170c..b06af1c13f45 100644
--- a/packages/SettingsLib/res/values-kn/arrays.xml
+++ b/packages/SettingsLib/res/values-kn/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ಆಡಿಯೋ"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ಆಡಿಯೋ"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"ಐಚ್ಛಿಕ ಕೋಡೆಕ್‌ಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</item>
- <item msgid="9205039209798344398">"ಐಚ್ಛಿಕ ಕೋಡೆಕ್‌ಗಳನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"ಸಿಸ್ಟಂ ಆಯ್ಕೆಯನ್ನು ಬಳಸಿ (ಡಿಫಾಲ್ಟ್)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ಆಡಿಯೋ"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ಆಡಿಯೋ"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"ಐಚ್ಛಿಕ ಕೋಡೆಕ್‌ಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</item>
- <item msgid="7416462860415701287">"ಐಚ್ಛಿಕ ಕೋಡೆಕ್‌ಗಳನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"ಸಿಸ್ಟಂ ಆಯ್ಕೆಯನ್ನು ಬಳಸಿ (ಡಿಫಾಲ್ಟ್)"</item>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 4feccaf2f1a0..08a0db72df29 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -227,6 +227,7 @@
<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">"ಬ್ಲೂಟೂತ್ AVRCP ಆವೃತ್ತಿ"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"ಬ್ಲೂಟೂತ್ AVRCP ಆವೃತ್ತಿಯನ್ನು ಆಯ್ಕೆ ಮಾಡಿ"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"ಬ್ಲೂಟೂತ್ ಆಡಿಯೋ ಕೋಡೆಕ್"</string>
@@ -275,6 +276,7 @@
<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="8472344901097607030">"ಬ್ಲೂಟೂತ್ Gabeldorche ವೈಶಿಷ್ಟ್ಯದ ಸ್ಟ್ಯಾಕ್‌ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸುತ್ತದೆ."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"ಸ್ಥಳೀಯ ಟರ್ಮಿನಲ್"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"ಸ್ಥಳೀಯ ಶೆಲ್ ಪ್ರವೇಶವನ್ನು ಒದಗಿಸುವ ಟರ್ಮಿನಲ್ ಅಪ್ಲಿಕೇಶನ್ ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP ಪರೀಕ್ಷಿಸುವಿಕೆ"</string>
@@ -379,7 +381,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="5190814747212060815">"ಇದು ಪ್ರಾಯೋಗಿಕ ವೈಶಿಷ್ಟ್ಯವಾಗಿದೆ. ಕಾರ್ಯಕ್ಷಮತೆ ಮೇಲೆ ಪರಿಣಾಮ ಬೀರಬಹುದು."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"ವರ್ಣ ಅಂಧತ್ವ ಹೊಂದಿರುವ ಜನರಿಗೆ ಬಣ್ಣಗಳನ್ನು ಹೆಚ್ಚು ನಿಖರವಾಗಿ ವೀಕ್ಷಿಸಲು ಬಣ್ಣ ತಿದ್ದುಪಡಿ ಸಹಾಯ ಮಾಡುತ್ತದೆ"</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>
diff --git a/packages/SettingsLib/res/values-ko/arrays.xml b/packages/SettingsLib/res/values-ko/arrays.xml
index 07d6b55ff936..9f7a751e3d62 100644
--- a/packages/SettingsLib/res/values-ko/arrays.xml
+++ b/packages/SettingsLib/res/values-ko/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> 오디오"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> 오디오"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"선택사항 코덱 사용 설정"</item>
- <item msgid="9205039209798344398">"선택사항 코덱 사용 중지"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"시스템 설정 사용(기본)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> 오디오"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> 오디오"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"선택사항 코덱 사용 설정"</item>
- <item msgid="7416462860415701287">"선택사항 코덱 사용 중지"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"시스템 설정 사용(기본)"</item>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 4707ef8e372f..d93b1cd7ea78 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -227,6 +227,7 @@
<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">"블루투스 AVRCP 버전"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"블루투스 AVRCP 버전 선택"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"블루투스 오디오 코덱"</string>
@@ -275,6 +276,7 @@
<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="8472344901097607030">"블루투스 Gabeldorche 기능 스택을 사용 설정합니다."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"로컬 터미널"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"로컬 셸 액세스를 제공하는 터미널 앱 사용"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP 확인"</string>
@@ -379,7 +381,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="5190814747212060815">"실험실 기능이며 성능에 영향을 줄 수 있습니다."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"색상 보정을 사용하면 색맹인 사용자가 색상을 정확하게 구분하는 데 도움이 됩니다."</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>
diff --git a/packages/SettingsLib/res/values-ky/arrays.xml b/packages/SettingsLib/res/values-ky/arrays.xml
index 77f596e31c70..b2eaf9fee406 100644
--- a/packages/SettingsLib/res/values-ky/arrays.xml
+++ b/packages/SettingsLib/res/values-ky/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> аудио"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> аудио"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Кошумча кодекстер иштетилсин"</item>
- <item msgid="9205039209798344398">"Кошумча кодекстер өчүрүлсүн"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Тутум тандаганды колдонуу (демейки)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> аудио"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> аудио"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Кошумча кодекстер иштетилсин"</item>
- <item msgid="7416462860415701287">"Кошумча кодекстер өчүрүлсүн"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Тутум тандаганды колдонуу (демейки)"</item>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 2197a9f3750f..a24dd65ba8bb 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -227,6 +227,7 @@
<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>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorsche функциясын иштетүү"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP версиясы"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Bluetooth AVRCP версиясын тандоо"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth аудио кодек"</string>
@@ -275,6 +276,7 @@
<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="8472344901097607030">"Bluetooth Gabeldorche функциясынын топтомун иштетет."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Жергиликтүү терминал"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Жергиликтүү буйрук кабыгын сунуштаган терминалга уруксат берүү"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP текшерүү"</string>
@@ -379,7 +381,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="5190814747212060815">"Бул сынамык мүмкүнчүлүк болгондуктан, түзмөктүн иштешине таасир этиши мүмкүн."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Түстү тууралоо жөндөөсү түстөрдү айырмалап көрбөгөн адамдарга түстөрдү тагыраак билүүгө жардам берет"</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>
diff --git a/packages/SettingsLib/res/values-lo/arrays.xml b/packages/SettingsLib/res/values-lo/arrays.xml
index 9deeebbfc952..7e7ea1f86615 100644
--- a/packages/SettingsLib/res/values-lo/arrays.xml
+++ b/packages/SettingsLib/res/values-lo/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"ສຽງ <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="2908219194098827570">"ສຽງ <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"ເປີດໃຊ້ Codecs ແບບເສີມ"</item>
- <item msgid="9205039209798344398">"ປິດການໃຊ້ Codecs ແບບເສີມ"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"ໃຊ້ການເລືອກຂອງລະບົບ (ຄ່າເລີ່ມຕົ້ນ)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"ສຽງ <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="3517061573669307965">"ສຽງ <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"ເປີດໃຊ້ Codecs ແບບເສີມ"</item>
- <item msgid="7416462860415701287">"ປິດການໃຊ້ Codecs ແບບເສີມ"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"ໃຊ້ການເລືອກຂອງລະບົບ (ຄ່າເລີ່ມຕົ້ນ)"</item>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index de3f644b8700..3f93483f5239 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -227,6 +227,7 @@
<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>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"ເປີດໃຊ້ Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"ເວີຊັນ Bluetooth AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"ເລືອກເວີຊັນ Bluetooth AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth Audio Codec"</string>
@@ -275,6 +276,7 @@
<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="8472344901097607030">"ເປີດໃຊ້ການວາງຊ້ອນຄຸນສົມບັດ Bluetooth Gabeldorche."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Terminal ໃນໂຕເຄື່ອງ"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"ເປີດນຳໃຊ້ແອັບຯ Terminal ທີ່ໃຫ້ການເຂົ້າເຖິງ shell ໃນໂຕເຄື່ອງໄດ້"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"ການກວດສອບ HDCP"</string>
@@ -379,7 +381,7 @@
<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="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"​ຄຸນ​ສົມ​ບັດ​ນີ້​ກຳ​ລັງ​ຢູ່​ໃນ​ການ​ທົດ​ລອງ​ແລະ​ອາດ​ມີ​ຜົນ​ຕໍ່​ປະ​ສິດ​ທິ​ພາບ."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"ການແກ້ໄຂສີຈະຊ່ວຍໃຫ້ຄົນທີ່ຕາບອດສີເຫັນສີຕ່າງໆໄດ້ຖືກຕ້ອງຍິ່ງຂຶ້ນ"</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>
diff --git a/packages/SettingsLib/res/values-lt/arrays.xml b/packages/SettingsLib/res/values-lt/arrays.xml
index 2a4913f8748e..3356efb94dd5 100644
--- a/packages/SettingsLib/res/values-lt/arrays.xml
+++ b/packages/SettingsLib/res/values-lt/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> garsas"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> garsas"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Įgalinti nebūtinus kodekus"</item>
- <item msgid="9205039209798344398">"Išjungti nebūtinus kodekus"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Naudoti sistemos pasirink. (numatytasis)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> garsas"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> garsas"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Įgalinti nebūtinus kodekus"</item>
- <item msgid="7416462860415701287">"Išjungti nebūtinus kodekus"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Naudoti sistemos pasirink. (numatytasis)"</item>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 6157a8700044..940909307b61 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -227,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Įrenginio kaip modemo naudojimo aparatinės įrangos spartinimas"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Rodyti „Bluetooth“ įrenginius be pavadinimų"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Išjungti didžiausią garsą"</string>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Įgalinti „Gabeldorsche“"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"„Bluetooth“ AVRCP versija"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Pasirinkite „Bluetooth“ AVRCP versiją"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"„Bluetooth“ garso kodekas"</string>
@@ -275,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Patikrinkite, ar programų, įdiegtų naudojant ADB / ADT, veikimas nėra žalingas."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Bus rodomi „Bluetooth“ įrenginiai be pavadinimų (tik MAC adresai)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Išjungiama „Bluetooth“ didžiausio garso funkcija, jei naudojant nuotolinio valdymo įrenginius kyla problemų dėl garso, pvz., garsas yra per didelis arba jo negalima tinkamai valdyti."</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Įgalinama „Bluetooth Gabeldorche“ funkcijų grupė."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Vietinis terminalas"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Įgal. terminalo progr., siūlančią prieigą prie viet. apvalkalo"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP tikrinimas"</string>
@@ -379,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalija (raudona, žalia)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalija (mėlyna, geltona)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Spalvų taisymas"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"Ši funkcija yra eksperimentinė ir ji gali turėti įtakos našumui."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Naudojant spalvų taisymo funkciją daltonikai gali geriau matyti spalvas"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Nepaisyta naudojant nuostatą „<xliff:g id="TITLE">%1$s</xliff:g>“"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Liko maždaug <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-lv/arrays.xml b/packages/SettingsLib/res/values-lv/arrays.xml
index d9b73a22b161..2f0f5072f06f 100644
--- a/packages/SettingsLib/res/values-lv/arrays.xml
+++ b/packages/SettingsLib/res/values-lv/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Iespējot neobligātos kodekus"</item>
- <item msgid="9205039209798344398">"Atspējot neobligātos kodekus"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Sistēmas atlases izmantošana (nokl.)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Iespējot neobligātos kodekus"</item>
- <item msgid="7416462860415701287">"Atspējot neobligātos kodekus"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Sistēmas atlases izmantošana (nokl.)"</item>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index 51b909c3bb53..b51b69af472c 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -227,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Paātrināta aparatūras darbība piesaistei"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Rādīt Bluetooth ierīces bez nosaukumiem"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Atspējot absolūto skaļumu"</string>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Iespējot Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP versija"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Atlasiet Bluetooth AVRCP versiju"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth audio kodeks"</string>
@@ -275,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Pārbaudīt, vai lietotņu, kuru instalēšanai izmantots ADB/ADT, darbība nav kaitīga."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Tiks parādītas Bluetooth ierīces bez nosaukumiem (tikai MAC adreses)."</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Atspējo Bluetooth absolūtā skaļuma funkciju skaļuma problēmu gadījumiem attālajās ierīcēs, piemēram, ja ir nepieņemami liels skaļums vai nav iespējas kontrolēt skaļumu."</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Šis iestatījums iespējo funkciju grupu Bluetooth Gabeldorche."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Vietējā beigu lietotne"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Iespējot beigu lietotni, kurā piedāvāta vietējā čaulas piekļuve"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP pārbaude"</string>
@@ -379,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomālija (sarkans/zaļš)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomālija (zils/dzeltens)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Krāsu korekcija"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"Šī funkcija ir eksperimentāla un var ietekmēt veiktspēju."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Krāsu korekcija palīdz cilvēkiem ar krāsu aklumu redzēt precīzākas krāsas."</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Jaunā preference: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> — <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Aptuvenais atlikušais laiks: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-mk/arrays.xml b/packages/SettingsLib/res/values-mk/arrays.xml
index db7782d58945..3753a51ab674 100644
--- a/packages/SettingsLib/res/values-mk/arrays.xml
+++ b/packages/SettingsLib/res/values-mk/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> аудио"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> аудио"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Овозможување на „Кодеци по избор“"</item>
- <item msgid="9205039209798344398">"Оневозможување на „Кодеци по избор“"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Користи избор на системот (стандардно)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> аудио"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> аудио"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Овозможи ја „Кодеци по избор“"</item>
- <item msgid="7416462860415701287">"Оневозможи ја „Кодеци по избор“"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Користи избор на системот (стандардно)"</item>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index 9a0d2da73642..d38301e74f32 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -227,6 +227,7 @@
<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>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Овозможи Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Верзија Bluetooth AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Изберете верзија Bluetooth AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Кодек за аудио преку Bluetooth"</string>
@@ -275,6 +276,7 @@
<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="8472344901097607030">"Ја овозможува функцијата Bluetooth Gabeldorche."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Локален терминал"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Овозможи апликација на терминал што овозможува локален пристап кон школка."</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"Проверување HDCP"</string>
@@ -379,7 +381,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="5190814747212060815">"Функцијата е експериментална и може да влијае на изведбата."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Корекцијата на бои им помага на луѓето со далтонизам попрецизно да ги гледаат боите"</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>
diff --git a/packages/SettingsLib/res/values-ml/arrays.xml b/packages/SettingsLib/res/values-ml/arrays.xml
index 32bf2420c37f..1e0799420f06 100644
--- a/packages/SettingsLib/res/values-ml/arrays.xml
+++ b/packages/SettingsLib/res/values-ml/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ഓഡിയോ"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ഓഡിയോ"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"ഓപ്ഷണൽ കോഡെകുകൾ പ്രവർത്തനക്ഷമമാക്കുക"</item>
- <item msgid="9205039209798344398">"ഓപ്ഷണൽ കോഡെകുകൾ പ്രവർത്തനരഹിതമാക്കുക"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"സിസ്റ്റം സെലക്ഷൻ ഉപയോഗിക്കൂ ‌(ഡിഫോൾട്ട്)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ഓഡിയോ"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ഓഡിയോ"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"ഓപ്ഷണൽ കോഡെകുകൾ പ്രവർത്തനക്ഷമമാക്കുക"</item>
- <item msgid="7416462860415701287">"ഓപ്ഷണൽ കോഡെകുകൾ പ്രവർത്തനരഹിതമാക്കുക"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"സിസ്റ്റം സെലക്ഷൻ ഉപയോഗിക്കൂ ‌(ഡിഫോൾട്ട്)"</item>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index e9558fcdaa0a..27019d105191 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -60,7 +60,7 @@
<string name="speed_label_okay" msgid="1253594383880810424">"ശരി"</string>
<string name="speed_label_medium" msgid="9078405312828606976">"ഇടത്തരം"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"വേഗത്തിൽ"</string>
- <string name="speed_label_very_fast" msgid="8215718029533182439">"വളരെ വേഗത്തിൽ"</string>
+ <string name="speed_label_very_fast" msgid="8215718029533182439">"അതിവേഗം"</string>
<string name="wifi_passpoint_expired" msgid="6540867261754427561">"കാലഹരണപ്പെട്ടത്"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"വിച്ഛേദിച്ചു"</string>
@@ -227,6 +227,7 @@
<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>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorsche പ്രവർത്തനക്ഷമമാക്കുക"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP പതിപ്പ്"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Bluetooth AVRCP പതിപ്പ് തിരഞ്ഞെടുക്കുക"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth ഓഡിയോ കോഡെക്"</string>
@@ -275,6 +276,7 @@
<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="8472344901097607030">"Bluetooth Gabeldorche ഫീച്ചർ സ്‌റ്റാക്ക് പ്രവർത്തനക്ഷമമാക്കുന്നു."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"പ്രാദേശിക ടെർമിനൽ"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"പ്രാദേശിക ഷെൽ ആക്‌സസ് നൽകുന്ന ടെർമിനൽ അപ്ലിക്കേഷൻ പ്രവർത്തനക്ഷമമാക്കുക"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP പരിശോധന"</string>
@@ -379,7 +381,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="5190814747212060815">"ഈ ഫീച്ചർ പരീക്ഷണാത്മകമായതിനാൽ പ്രകടനത്തെ ബാധിച്ചേക്കാം."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"വർണ്ണം ശരിയാക്കൽ, വർണ്ണാന്ധത ബാധിച്ച ആളുകൾക്ക് നിറങ്ങൾ കൂടുതൽ കൃത്യമായി കാണാൻ സഹായിക്കുന്നു"</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>
diff --git a/packages/SettingsLib/res/values-mn/arrays.xml b/packages/SettingsLib/res/values-mn/arrays.xml
index 4f582464abb9..d1eca7be8321 100644
--- a/packages/SettingsLib/res/values-mn/arrays.xml
+++ b/packages/SettingsLib/res/values-mn/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> аудио"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> аудио"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Нэмэлт кодлогчийг идэвхжүүлэх"</item>
- <item msgid="9205039209798344398">"Нэмэлт кодлогчийг идэвхгүй болгох"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Системийн сонголтыг ашиглах (Өгөгдмөл)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> аудио"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> аудио"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Нэмэлт кодлогчийг идэвхжүүлэх"</item>
- <item msgid="7416462860415701287">"Нэмэлт кодлогчийг идэвхгүй болгох"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Системийн сонголтыг ашиглах (Өгөгдмөл)"</item>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 4997f0b1528a..f0136c916758 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -227,6 +227,7 @@
<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>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorsche-г идэвхжүүлэх"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP хувилбар"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Bluetooth AVRCP хувилбарыг сонгох"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth аудио кодлогч"</string>
@@ -275,6 +276,7 @@
<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="8472344901097607030">"Bluetooth Gabeldorsche онцлогийн өрөлтийг идэвхжүүлдэг."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Локал терминал"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Локал суурьт хандалт хийх боломж олгодог терминалын апп-г идэвхжүүлэх"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP шалгах"</string>
@@ -379,7 +381,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="5190814747212060815">"Энэ функц туршилтынх бөгөөд ажиллагаанд нөлөөлж болзошгүй."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Өнгөний залруулга нь өнгөний сохортой хүмүүст илүү оновчтой өнгө харахад тусалдаг"</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>
@@ -393,7 +395,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Ойролцоогоор <xliff:g id="TIME">%1$s</xliff:g> хүртэл барих ёстой (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Ойролцоогоор <xliff:g id="TIME">%1$s</xliff:g> хүртэл барих ёстой"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"<xliff:g id="TIME">%1$s</xliff:g> хүртэл"</string>
- <string name="power_suggestion_extend_battery" msgid="5233928707465237447">"<xliff:g id="TIME">%1$s</xliff:g>-с хойш батарейны ажиллах хугацааг сунгах"</string>
+ <string name="power_suggestion_extend_battery" msgid="5233928707465237447">"<xliff:g id="TIME">%1$s</xliff:g>-с хойш батарейн ажиллах хугацааг сунгах"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"<xliff:g id="THRESHOLD">%1$s</xliff:g>-с бага хугацаа үлдсэн"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"<xliff:g id="THRESHOLD">%1$s</xliff:g>-с бага хугацаа үлдсэн (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g>-с их хугацаа үлдсэн (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-mr/arrays.xml b/packages/SettingsLib/res/values-mr/arrays.xml
index 0be16d800122..e62e6ff53f0c 100644
--- a/packages/SettingsLib/res/values-mr/arrays.xml
+++ b/packages/SettingsLib/res/values-mr/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ऑडिओ"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ऑडिओ"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"पर्यायी कोडेक सुरू करा"</item>
- <item msgid="9205039209798344398">"पर्यायी कोडेक अक्षम करा"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"सिस्टम निवड वापरा (डीफॉल्ट)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ऑडिओ"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ऑडिओ"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"पर्यायी कोडेक सुरू करा"</item>
- <item msgid="7416462860415701287">"पर्यायी कोडेक अक्षम करा"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"सिस्टम निवड वापरा (डीफॉल्ट)"</item>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 1dbd59213932..4d8069e8b9ea 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -227,6 +227,7 @@
<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">"गाबलडॉर्ष सुरू करा"</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_a2dp_codec_type" msgid="952001408455456494">"ब्लूटूथ ऑडिओ कोडेक"</string>
@@ -275,6 +276,7 @@
<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="8472344901097607030">"ब्लूटूथ गाबलडॉर्ष वैशिष्ट्य स्टॅक सुरू करते."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"स्थानिक टर्मिनल"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"स्थानिक शेल प्रवेश देणारा टर्मिनल अ‍ॅप सुरू करा"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP तपासणी"</string>
@@ -379,7 +381,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="5190814747212060815">"हे वैशिष्‍ट्य प्रायोगिक आहे आणि कदाचित कार्यप्रदर्शन प्रभावित करू शकते."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"रंग सुधारणा ही वर्णांधता असलेल्या लोकांना रंग अधिक अचूक दिसण्यात मदत करते"</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>
diff --git a/packages/SettingsLib/res/values-ms/arrays.xml b/packages/SettingsLib/res/values-ms/arrays.xml
index 4c155672d83a..91dd81c62432 100644
--- a/packages/SettingsLib/res/values-ms/arrays.xml
+++ b/packages/SettingsLib/res/values-ms/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="2908219194098827570">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Dayakan Codec Pilihan"</item>
- <item msgid="9205039209798344398">"Lumpuhkan Codec Pilihan"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Gunakan Pilihan Sistem (Lalai)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="3517061573669307965">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Dayakan Codec Pilihan"</item>
- <item msgid="7416462860415701287">"Lumpuhkan Codec Pilihan"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Gunakan Pilihan Sistem (Lalai)"</item>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index 790480d7ea04..7efc987598c3 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -227,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Pecutan perkakasan penambatan"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Tunjukkan peranti Bluetooth tanpa nama"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Lumpuhkan kelantangan mutlak"</string>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Dayakan Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Versi AVRCP Bluetooth"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Pilih Versi AVRCP Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Codec Audio Bluetooth"</string>
@@ -275,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Semak apl yang dipasang melalui ADB/ADT untuk tingkah laku yang berbahaya."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Peranti Bluetooth tanpa nama (alamat MAC sahaja) akan dipaparkan"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Lumpuhkan ciri kelantangan mutlak Bluetooth dalam kes isu kelantangan menggunakan peranti kawalan jauh seperti kelantangan yang sangat kuat atau tidak dapat mengawal."</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Mendayakan tindanan ciri Bluetooth Gabeldorche."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Terminal setempat"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Dayakan apl terminal yang menawarkan akses shell tempatan"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"Penyemakan HDCP"</string>
@@ -379,7 +381,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">"Pembetulan warna"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"Ciri ini adalah percubaan dan boleh menjejaskan prestasi."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Pembetulan warna membantu orang yang mengalami kebutaan warna melihat warna yang lebih tepat"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Diatasi oleh <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Kira-kira <xliff:g id="TIME_REMAINING">%1$s</xliff:g> lagi"</string>
diff --git a/packages/SettingsLib/res/values-my/arrays.xml b/packages/SettingsLib/res/values-my/arrays.xml
index a33039fca5db..9c4a2b933b04 100644
--- a/packages/SettingsLib/res/values-my/arrays.xml
+++ b/packages/SettingsLib/res/values-my/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> အသံ"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> အသံ"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"စိတ်ကြိုက်ထည့်သွင်းနိုင်သော ကိုးဒက်ခ်များကို ဖွင့်ပါ"</item>
- <item msgid="9205039209798344398">"စိတ်ကြိုက်ထည့်သွင်းနိုင်သော ကိုးဒက်ခ်များကို ပိတ်ပါ"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"စနစ်ရွေးချယ်မှုကို အသုံးပြုပါ (မူရင်း)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> အသံ"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> အသံ"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"စိတ်ကြိုက်ထည့်သွင်းနိုင်သော ကိုးဒက်ခ်များကို ဖွင့်ပါ"</item>
- <item msgid="7416462860415701287">"စိတ်ကြိုက်ထည့်သွင်းနိုင်သော ကိုးဒက်ခ်များကို ပိတ်ပါ"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"စနစ်ရွေးချယ်မှုကို အသုံးပြုပါ (မူရင်း)"</item>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index dc81d056ac0f..befdaa9e093d 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -227,6 +227,7 @@
<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">"ဘလူးတုသ် AVRCP ဗားရှင်း"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"ဘလူးတုသ် AVRCP ဗားရှင်းကို ရွေးပါ"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"ဘလူးတုသ်အသံ ကိုးဒက်ခ်"</string>
@@ -275,6 +276,7 @@
<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="8472344901097607030">"ဘလူးတုသ် Gabeldorche အထူးတည်းဖြတ်ခြင်းကို ဖွင့်သည်။"</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"လိုကယ်တာမီနယ်"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"local shell အသုံးပြုခွင့်ကမ်းလှမ်းသော တာမင်နယ်အပလီကေးရှင်းဖွင့်ပါ"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP စစ်ဆေးမှု"</string>
@@ -379,7 +381,7 @@
<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="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"ဤဝန်ဆောင်မှုမှာ စမ်းသပ်အဆင့်သာဖြစ်၍ လုပ်ဆောင်မှုအားနည်းနိုင်သည်။"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"အရောင်ပြင်ဆင်ခြင်းက အရောင်ကန်းသူများအတွက် ပိုမိုမှန်ကန်သော အရောင်များဖြင့် ကြည့်နိုင်ရန် ကူညီမည်"</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>
diff --git a/packages/SettingsLib/res/values-nb/arrays.xml b/packages/SettingsLib/res/values-nb/arrays.xml
index 47c589ab4ce1..ed045ad549dd 100644
--- a/packages/SettingsLib/res/values-nb/arrays.xml
+++ b/packages/SettingsLib/res/values-nb/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>-lyd"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>-lyd"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Slå på valgfrie kodeker"</item>
- <item msgid="9205039209798344398">"Slå av valgfrie kodeker"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Bruk systemvalg (standard)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>-lyd"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>-lyd"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Slå på valgfrie kodeker"</item>
- <item msgid="7416462860415701287">"Slå av valgfrie kodeker"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Bruk systemvalg (standard)"</item>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index d0e4966721cd..cb0931f60502 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -227,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Maskinvareakselerasjon for internettdeling"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Vis Bluetooth-enheter uten navn"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Slå av funksjonen for absolutt volum"</string>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Aktiver Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP-versjon"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Velg Bluetooth AVRCP-versjon"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Kodek for Bluetooth-lyd"</string>
@@ -275,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Sjekk apper som er installert via ADB/ADT, for skadelig atferd."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Bluetooth-enheter uten navn (bare MAC-adresser) vises"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Slår av funksjonen for absolutt volum via Bluetooth i tilfelle det oppstår volumrelaterte problemer med eksterne enheter, for eksempel uakseptabelt høyt volum eller mangel på kontroll."</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Aktiverer funksjonsstabelen Bluetooth Gabeldorche."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Lokal terminal"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Aktiver terminalappen som gir lokal kommandolistetilgang"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP-kontroll"</string>
@@ -379,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomali (rød-grønn)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomali (blå-gul)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Fargekorrigering"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"Dette er en eksperimentell funksjon som kan gjøre at telefonen ikke fungerer optimalt."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Med fargekorrigering kan personer med fargeblindhet se mer nøyaktige farger"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Overstyres av <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Omtrent <xliff:g id="TIME_REMAINING">%1$s</xliff:g> gjenstår"</string>
diff --git a/packages/SettingsLib/res/values-ne/arrays.xml b/packages/SettingsLib/res/values-ne/arrays.xml
index 8177aeb9fd74..c8ee48b86e5e 100644
--- a/packages/SettingsLib/res/values-ne/arrays.xml
+++ b/packages/SettingsLib/res/values-ne/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> अडियो"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> अडियो"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"वैकल्पिक कोडेकहरूलाई सक्षम पार्नुहोस्"</item>
- <item msgid="9205039209798344398">"वैकल्पिक कोडेकहरूलाई असक्षम पार्नुहोस्"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"प्रणालीको चयन प्रयोग गर्नुहोस् (पूर्वनिर्धारित)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> अडियो"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> अडियो"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"वैकल्पिक कोडेकहरूलाई सक्षम पार्नुहोस्"</item>
- <item msgid="7416462860415701287">"वैकल्पिक कोडेकहरूलाई असक्षम पार्नुहोस्"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"प्रणालीको चयन प्रयोग गर्नुहोस् (पूर्वनिर्धारित)"</item>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index d8ed4cbcf36f..c7ffc6400f1d 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -227,6 +227,7 @@
<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">"ब्लुटुथको AVRCP संस्करण"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"ब्लुटुथको AVRCP संस्करण चयन गर्नुहोस्"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"ब्लुटुथ अडियोको कोडेक"</string>
@@ -275,6 +276,7 @@
<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="8472344901097607030">"ब्लुटुथ Gabeldorche सुविधाको स्ट्याक सक्षम पार्नुहोस्।"</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"स्थानीय टर्मिनल"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"स्थानीय सेल पहुँच प्रदान गर्ने टर्मिनल अनुप्रयोग सक्षम गर्नुहोस्"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP जाँच गर्दै"</string>
@@ -379,7 +381,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="5190814747212060815">"यो सुविधा प्रयोगात्मक छ र प्रदर्शनमा असर गर्न सक्छ।"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"रङ सुधार गर्नुले रङ छुट्याउन नसक्ने मान्छेलाई थप सही रङ देख्न मद्दत गर्दछ"</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>
diff --git a/packages/SettingsLib/res/values-nl/arrays.xml b/packages/SettingsLib/res/values-nl/arrays.xml
index df61902357a8..d86dab687530 100644
--- a/packages/SettingsLib/res/values-nl/arrays.xml
+++ b/packages/SettingsLib/res/values-nl/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Optionele codecs inschakelen"</item>
- <item msgid="9205039209798344398">"Optionele codecs uitschakelen"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Systeemselectie gebruiken (standaard)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Optionele codecs inschakelen"</item>
- <item msgid="7416462860415701287">"Optionele codecs uitschakelen"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Systeemselectie gebruiken (standaard)"</item>
@@ -257,7 +253,7 @@
<item msgid="3358668781763928157">"Opladen"</item>
<item msgid="7804797564616858506">"MTP (Media Transfer Protocol)"</item>
<item msgid="910925519184248772">"PTP (Picture Transfer Protocol)"</item>
- <item msgid="3825132913289380004">"RNDIS (USB-Ethernet)"</item>
+ <item msgid="3825132913289380004">"RNDIS (USB-ethernet)"</item>
<item msgid="8828567335701536560">"Audiobron"</item>
<item msgid="8688681727755534982">"MIDI"</item>
</string-array>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index d5ce54050aff..a196ccf1c651 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -227,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Hardwareversnelling voor tethering"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Bluetooth-apparaten zonder namen weergeven"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Absoluut volume uitschakelen"</string>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorsche inschakelen"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth-AVRCP-versie"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Bluetooth-AVRCP-versie selecteren"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth-audiocodec"</string>
@@ -275,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Apps die zijn geïnstalleerd via ADB/ADT, controleren op schadelijk gedrag"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Bluetooth-apparaten zonder namen (alleen MAC-adressen) worden weergegeven"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Hiermee wordt de functie voor absoluut volume van Bluetooth uitgeschakeld in geval van volumeproblemen met externe apparaten, zoals een onacceptabel hoog volume of geen volumeregeling."</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Hierdoor wordt de Gabeldorsche-functiestack voor bluetooth ingeschakeld"</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Lokale terminal"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Terminal-app inschakelen die lokale shell-toegang biedt"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP-controle"</string>
@@ -379,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalie (rood-groen)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalie (blauw-geel)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Kleurcorrectie"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"Deze functie is experimenteel en kan invloed hebben op de prestaties."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Met behulp van kleurcorrectie kunnen mensen die kleurenblind zijn, nauwkeurigere kleuren te zien krijgen"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Overschreven door <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Nog ongeveer <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-or/arrays.xml b/packages/SettingsLib/res/values-or/arrays.xml
index fd982d784a55..2553978a5742 100644
--- a/packages/SettingsLib/res/values-or/arrays.xml
+++ b/packages/SettingsLib/res/values-or/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ଅଡିଓ"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ଅଡିଓ"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"ବିକଳ୍ପ କୋଡେକ୍ସକୁ ସକ୍ଷମ କରନ୍ତୁ"</item>
- <item msgid="9205039209798344398">"ବିକଳ୍ପ କୋଡେକ୍‌ଗୁଡ଼ିକୁ ଅକ୍ଷମ କରନ୍ତୁ"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"ସିଷ୍ଟମ୍‌ର ଚୟନ (ଡିଫଲ୍ଟ୍) ବ୍ୟବହାର କରନ୍ତୁ"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ଅଡିଓ"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ଅଡିଓ"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"ବିକଳ୍ପ କୋଡେକ୍ସ ସକ୍ଷମ କରନ୍ତୁ"</item>
- <item msgid="7416462860415701287">"ବିକଳ୍ପ କୋଡେକ୍ସ ଅକ୍ଷମ କରନ୍ତୁ"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"ସିଷ୍ଟମ୍‌ର ଚୟନ (ଡିଫଲ୍ଟ୍) ବ୍ୟବହାର କରନ୍ତୁ"</item>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index 024bd3c5deab..faa399dfe336 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -227,6 +227,7 @@
<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">"ଗାବେଲ୍‌ଡୋର୍ସ ସକ୍ରିୟ କରନ୍ତୁ"</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_a2dp_codec_type" msgid="952001408455456494">"ବ୍ଲୁଟୁଥ୍‌ ଅଡିଓ କୋଡେକ୍‌"</string>
@@ -275,6 +276,7 @@
<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="8472344901097607030">"ବ୍ଲୁଟୁଥ୍ ଗାବେଲ୍‌ଡୋର୍ସ ଫିଚର୍ ଷ୍ଟକ୍ ସକ୍ଷମ କରେ।"</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"ସ୍ଥାନୀୟ ଟର୍ମିନାଲ୍‌"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"ସ୍ଥାନୀୟ ଶେଲ୍‌କୁ ଆକ‌ସେସ୍‌ ଦେଉଥିବା ଟର୍ମିନଲ୍‌ ଆପ୍‌କୁ ସକ୍ଷମ କରନ୍ତୁ"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP ଯାଞ୍ଚ କରୁଛି"</string>
@@ -379,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"ପ୍ରୋଟାନୋମାଲି (ଲାଲ୍‌-ସବୁଜ)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (ନୀଳ-ହଳଦିଆ)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"ରଙ୍ଗ ସଠିକତା"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"ଏହି ପରୀକ୍ଷାମୂଳକ ବୈଶିଷ୍ଟ୍ୟ ପର୍ଫର୍ମେନ୍ସକୁ ପ୍ରଭାବିତ କରିପାରେ।"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"କଲର୍ କରେକ୍ସନ୍ ରଙ୍ଗ ଚିହ୍ନିବାରେ ସମସ୍ୟା ଥିବା ଲୋକମାନଙ୍କୁ ଅଧିକ ସଠିକ୍ ରଙ୍ଗ ଦେଖିବାରେ ସାହାଯ୍ୟ କରିଥାଏ"</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>
diff --git a/packages/SettingsLib/res/values-pa/arrays.xml b/packages/SettingsLib/res/values-pa/arrays.xml
index f8ac4ff79238..8acc4391adac 100644
--- a/packages/SettingsLib/res/values-pa/arrays.xml
+++ b/packages/SettingsLib/res/values-pa/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ਆਡੀਓ"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ਆਡੀਓ"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"ਵਿਕਲਪਿਕ ਕੋਡੈਕ ਚਾਲੂ ਕਰੋ"</item>
- <item msgid="9205039209798344398">"ਵਿਕਲਪਿਕ ਕੋਡੈਕ ਅਯੋਗ ਬਣਾਓ"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"ਸਿਸਟਮ ਚੋਣ ਦੀ ਵਰਤੋਂ ਕਰੋ (ਪੂਰਵ-ਨਿਰਧਾਰਤ)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ਆਡੀਓ"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ਆਡੀਓ"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"ਵਿਕਲਪਿਕ ਕੋਡੈਕ ਚਾਲੂ ਕਰੋ"</item>
- <item msgid="7416462860415701287">"ਵਿਕਲਪਿਕ ਕੋਡੈਕ ਅਯੋਗ ਬਣਾਓ"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"ਸਿਸਟਮ ਚੋਣ ਦੀ ਵਰਤੋਂ ਕਰੋ (ਪੂਰਵ-ਨਿਰਧਾਰਤ)"</item>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 042bbf7d3ba3..cd83c2cb4bee 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -227,6 +227,7 @@
<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">"ਬਲੂਟੁੱਥ AVRCP ਵਰਜਨ"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"ਬਲੂਟੁੱਥ AVRCP ਵਰਜਨ ਚੁਣੋ"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"ਬਲੂਟੁੱਥ ਆਡੀਓ ਕੋਡੇਕ"</string>
@@ -275,6 +276,7 @@
<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="8472344901097607030">"ਬਲੂਟੁੱਥ Gabeldorche ਵਿਸ਼ੇਸ਼ਤਾ ਸਟੈਕ ਨੂੰ ਚਾਲੂ ਕਰਦਾ ਹੈ।"</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"ਸਥਾਨਕ ਟਰਮੀਨਲ"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"ਟਰਮੀਨਲ ਐਪ ਨੂੰ ਚਾਲੂ ਕਰੋ ਜੋ ਸਥਾਨਕ ਸ਼ੈਲ ਪਹੁੰਚ ਪੇਸ਼ਕਸ਼ ਕਰਦਾ ਹੈ"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP ਜਾਂਚ"</string>
@@ -379,7 +381,7 @@
<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="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"ਇਹ ਵਿਸ਼ੇਸ਼ਤਾ ਪ੍ਰਯੋਗਾਤਮਿਕ ਹੈ ਅਤੇ ਪ੍ਰਦਰਸ਼ਨ ਤੇ ਅਸਰ ਪਾ ਸਕਦੀ ਹੈ।"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"ਰੰਗ ਸੁਧਾਈ ਨਾਲ ਰੰਗਾਂ ਦੇ ਅੰਨ੍ਹਾਪਣ ਦੇ ਸ਼ਿਕਾਰ ਲੋਕਾਂ ਦੀ ਵਧੇਰੇ ਸਟੀਕ ਰੰਗਾਂ ਨੂੰ ਦੇਖਣ ਵਿੱਚ ਮਦਦ ਕੀਤੀ ਜਾਂਦੀ ਹੈ"</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>
diff --git a/packages/SettingsLib/res/values-pl/arrays.xml b/packages/SettingsLib/res/values-pl/arrays.xml
index 81c619b58f6c..00b23bca41ad 100644
--- a/packages/SettingsLib/res/values-pl/arrays.xml
+++ b/packages/SettingsLib/res/values-pl/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="2908219194098827570">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Włącz opcjonalne kodeki"</item>
- <item msgid="9205039209798344398">"Wyłącz opcjonalne kodeki"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Użyj wyboru systemu (domyślnie)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="3517061573669307965">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Włączenie opcjonalnych kodeków"</item>
- <item msgid="7416462860415701287">"Wyłączenie opcjonalnych kodeków"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Użyj wyboru systemu (domyślnie)"</item>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 78566790b3f8..b47365b49f5e 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -227,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Akceleracja sprzętowa tetheringu"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Pokaż urządzenia Bluetooth bez nazw"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Wyłącz głośność bezwzględną"</string>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Włącz Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Wersja AVRCP Bluetooth"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Wybierz wersję AVRCP Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Kodek dźwięku Bluetooth"</string>
@@ -275,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Sprawdź, czy aplikacje zainstalowane przez ADB/ADT nie zachowują się w szkodliwy sposób"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Zostaną wyświetlone urządzenia Bluetooth bez nazw (tylko adresy MAC)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Wyłącza funkcję Głośność bezwzględna Bluetooth, jeśli występują problemy z urządzeniami zdalnymi, np. zbyt duża głośność lub brak kontroli."</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Włącza funkcje Bluetooth Gabeldorche."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Terminal lokalny"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Włącz terminal, który umożliwia dostęp do powłoki lokalnej"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"Sprawdzanie HDCP"</string>
@@ -379,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalia (czerwony-zielony)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalia (niebieski-żółty)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Korekcja kolorów"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"To jest funkcja eksperymentalna i może wpływać na działanie urządzenia."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Korekcja kolorów pomaga osobom z zaburzeniami rozpoznawania barw lepiej je widzieć."</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Nadpisana przez <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Jeszcze około <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/arrays.xml b/packages/SettingsLib/res/values-pt-rBR/arrays.xml
index a1d444ed98b0..4e23c197d430 100644
--- a/packages/SettingsLib/res/values-pt-rBR/arrays.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="2908219194098827570">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Ativar codecs opcionais"</item>
- <item msgid="9205039209798344398">"Desativar codecs opcionais"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Usar seleção do sistema (padrão)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="3517061573669307965">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Ativar codecs opcionais"</item>
- <item msgid="7416462860415701287">"Desativar codecs opcionais"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Usar seleção do sistema (padrão)"</item>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 6a3220023e9f..4cccad4eab69 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -227,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Aceleração de hardware de 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>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Versão do Bluetooth AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Selecionar versão do Bluetooth AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Codec de áudio Bluetooth"</string>
@@ -275,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Verificar comportamento nocivo em apps instalados via ADB/ADT"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Dispositivos Bluetooth sem nomes (somente endereços MAC) serão exibidos"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Desativa o recurso Bluetooth de volume absoluto em caso de problemas com o volume em dispositivos remotos, como volume excessivamente alto ou falta de controle"</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Ativa a pilha de recursos Bluetooth Gabeldorsche."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Terminal local"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Ativar o app terminal que oferece acesso ao shell local"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"Verificação HDCP"</string>
@@ -320,7 +322,7 @@
<string name="show_non_rect_clip" msgid="7499758654867881817">"Depurar operações de corte não retangulares"</string>
<string name="track_frame_time" msgid="522674651937771106">"Classificar renderização HWUI"</string>
<string name="enable_gpu_debug_layers" msgid="4986675516188740397">"Ativar camadas de depuração de GPU"</string>
- <string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"Permitir carreg. de camadas de depuração de GPU p/ apps de dep"</string>
+ <string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"Permitir carregamento de camadas de depuração de GPU p/ apps de depuração"</string>
<string name="window_animation_scale_title" msgid="5236381298376812508">"Escala de animação da janela"</string>
<string name="transition_animation_scale_title" msgid="1278477690695439337">"Escala de animação de transição"</string>
<string name="animator_duration_scale_title" msgid="7082913931326085176">"Escala de duração do Animator"</string>
@@ -379,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalia (vermelho-verde)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalia (azul-amarelo)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Correção de cor"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"Este recurso é experimental e pode afetar o desempenho."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"A correção de cores ajuda pessoas com daltonismo a ver cores de forma mais precisa"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Substituído por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Tempo restante aproximado: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/arrays.xml b/packages/SettingsLib/res/values-pt-rPT/arrays.xml
index 8b7a9deb151d..98e9c8746459 100644
--- a/packages/SettingsLib/res/values-pt-rPT/arrays.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="2908219194098827570">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Ativar codecs opcionais"</item>
- <item msgid="9205039209798344398">"Desativar codecs opcionais"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Utilizar seleção do sistema (predefinido)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="3517061573669307965">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Ativar codecs opcionais"</item>
- <item msgid="7416462860415701287">"Desativar codecs opcionais"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Utilizar seleção do sistema (predefinido)"</item>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index caf1ba4141e5..6e80bd2258b3 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -227,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Aceleração de hardware para ligação (à Internet) via telemóvel"</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 o Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Versão de Bluetooth AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Selecionar versão de Bluetooth AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Codec de áudio Bluetooth"</string>
@@ -275,6 +276,7 @@
<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>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Ativa a pilha de funcionalidades Bluetooth Gabeldorche."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Terminal local"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Ativar aplicação terminal que oferece acesso local à shell"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"Verificação HDCP"</string>
@@ -379,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalia (vermelho-verde)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalia (azul-amarelo)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Correção da cor"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"Esta funcionalidade é experimental e pode afetar o desempenho."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"A correção de cor ajuda as pessoas com daltonismo a ver cores mais precisas."</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Substituído por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Resta(m) cerca de <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-pt/arrays.xml b/packages/SettingsLib/res/values-pt/arrays.xml
index a1d444ed98b0..4e23c197d430 100644
--- a/packages/SettingsLib/res/values-pt/arrays.xml
+++ b/packages/SettingsLib/res/values-pt/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="2908219194098827570">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Ativar codecs opcionais"</item>
- <item msgid="9205039209798344398">"Desativar codecs opcionais"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Usar seleção do sistema (padrão)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="3517061573669307965">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Ativar codecs opcionais"</item>
- <item msgid="7416462860415701287">"Desativar codecs opcionais"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Usar seleção do sistema (padrão)"</item>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 6a3220023e9f..4cccad4eab69 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -227,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Aceleração de hardware de 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>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Versão do Bluetooth AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Selecionar versão do Bluetooth AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Codec de áudio Bluetooth"</string>
@@ -275,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Verificar comportamento nocivo em apps instalados via ADB/ADT"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Dispositivos Bluetooth sem nomes (somente endereços MAC) serão exibidos"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Desativa o recurso Bluetooth de volume absoluto em caso de problemas com o volume em dispositivos remotos, como volume excessivamente alto ou falta de controle"</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Ativa a pilha de recursos Bluetooth Gabeldorsche."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Terminal local"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Ativar o app terminal que oferece acesso ao shell local"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"Verificação HDCP"</string>
@@ -320,7 +322,7 @@
<string name="show_non_rect_clip" msgid="7499758654867881817">"Depurar operações de corte não retangulares"</string>
<string name="track_frame_time" msgid="522674651937771106">"Classificar renderização HWUI"</string>
<string name="enable_gpu_debug_layers" msgid="4986675516188740397">"Ativar camadas de depuração de GPU"</string>
- <string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"Permitir carreg. de camadas de depuração de GPU p/ apps de dep"</string>
+ <string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"Permitir carregamento de camadas de depuração de GPU p/ apps de depuração"</string>
<string name="window_animation_scale_title" msgid="5236381298376812508">"Escala de animação da janela"</string>
<string name="transition_animation_scale_title" msgid="1278477690695439337">"Escala de animação de transição"</string>
<string name="animator_duration_scale_title" msgid="7082913931326085176">"Escala de duração do Animator"</string>
@@ -379,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalia (vermelho-verde)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalia (azul-amarelo)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Correção de cor"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"Este recurso é experimental e pode afetar o desempenho."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"A correção de cores ajuda pessoas com daltonismo a ver cores de forma mais precisa"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Substituído por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Tempo restante aproximado: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-ro/arrays.xml b/packages/SettingsLib/res/values-ro/arrays.xml
index 0d899c0cf959..befb771624dc 100644
--- a/packages/SettingsLib/res/values-ro/arrays.xml
+++ b/packages/SettingsLib/res/values-ro/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="2908219194098827570">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Activați codecurile opționale"</item>
- <item msgid="9205039209798344398">"Dezactivați codecurile opționale"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Folosiți selectarea sistemului (prestabilit)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="3517061573669307965">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Activați codecurile opționale"</item>
- <item msgid="7416462860415701287">"Dezactivați codecurile opționale"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Folosiți selectarea sistemului (prestabilit)"</item>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 38cd60fc7d7d..a7429328ab06 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -227,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Accelerare hardware pentru tethering"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Afișați dispozitivele Bluetooth fără nume"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Dezactivați volumul absolut"</string>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Activați Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Versiunea AVRCP pentru Bluetooth"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Selectați versiunea AVRCP pentru Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Codec audio Bluetooth"</string>
@@ -275,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Verificați aplicațiile instalate utilizând ADB/ADT, pentru a detecta un comportament dăunător."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Vor fi afișate dispozitivele Bluetooth fără nume (numai adresele MAC)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Dezactivează funcția Bluetooth de volum absolut în cazul problemelor de volum apărute la dispozitivele la distanță, cum ar fi volumul mult prea ridicat sau lipsa de control asupra acestuia."</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Activează setul de funcții Bluetooth Gabeldorche."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Aplicație terminal locală"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Activați aplicația terminal care oferă acces la shell local"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"Verificare HDCP"</string>
@@ -379,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalie (roșu-verde)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalie (albastru-galben)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Corecția culorii"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"Această funcție este experimentală și poate afecta performanțele."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Corecția culorii ajută persoanele cu daltonism să vadă culori mai exacte"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Valoare înlocuită de <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Timp aproximativ rămas: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-ru/arrays.xml b/packages/SettingsLib/res/values-ru/arrays.xml
index 0a211a1c1c29..d0d04d6d5b6c 100644
--- a/packages/SettingsLib/res/values-ru/arrays.xml
+++ b/packages/SettingsLib/res/values-ru/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"Аудиокодек: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="2908219194098827570">"Аудиокодек: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Включить дополнительные кодеки"</item>
- <item msgid="9205039209798344398">"Отключить дополнительные кодеки"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Выбор системы (по умолчанию)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"Аудиокодек: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="3517061573669307965">"Аудиокодек: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Включить дополнительные кодеки"</item>
- <item msgid="7416462860415701287">"Отключить дополнительные кодеки"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Выбор системы (по умолчанию)"</item>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 124bf13a5357..769b5f3c2687 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -227,13 +227,14 @@
<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>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Включить Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Версия Bluetooth AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Выберите версию Bluetooth AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Аудиокодек Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Запустить аудиокодек для Bluetooth\nВыбор"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Частота дискретизации аудио Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Запустить аудиокодек для Bluetooth\nВыбор: частота дискретизации"</string>
- <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Серым окрашены неподдерживаемые функции"</string>
+ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"Серым цветом показаны варианты, не поддерживаемые телефоном или наушниками"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"Бит на выборку аудио Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Запустить аудиокодек для Bluetooth\nВыбор: разрядность"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Режим аудиоканала Bluetooth"</string>
@@ -275,6 +276,7 @@
<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="8472344901097607030">"Включить стек Bluetooth Gabeldorche"</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Локальный терминальный доступ"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Разрешить терминальный доступ к локальной оболочке"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"Проверка HDCP"</string>
@@ -379,7 +381,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="5190814747212060815">"Это экспериментальная функция, она может снизить производительность устройства."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Коррекция цвета помогает пользователям с нарушениями цветового зрения лучше различать изображение на экране."</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>
diff --git a/packages/SettingsLib/res/values-si/arrays.xml b/packages/SettingsLib/res/values-si/arrays.xml
index abd6244a2519..4764d4768ead 100644
--- a/packages/SettingsLib/res/values-si/arrays.xml
+++ b/packages/SettingsLib/res/values-si/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ශ්‍රව්‍යය"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ශ්‍රව්‍යය"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"විකල්පමය කොඩෙක් සබල කරන්න"</item>
- <item msgid="9205039209798344398">"විකල්පමය කොඩෙක් අබල කරන්න"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"පද්ධති තේරීම භාවිත කරන්න (පෙරනිමි)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ශ්‍රව්‍යය"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ශ්‍රව්‍යය"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"විකල්පමය කොඩෙක් සබල කරන්න"</item>
- <item msgid="7416462860415701287">"විකල්පමය කොඩෙක් අබල කරන්න"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"පද්ධති තේරීම භාවිත කරන්න (පෙරනිමි)"</item>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index d5fbb6b6974d..1d925bfda8d5 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -227,6 +227,7 @@
<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">"බ්ලූටූත් AVRCP අනුවාදය"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"බ්ලූටූත් AVRCP අනුවාදය තෝරන්න"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"බ්ලූටූත් ශ්‍රව්‍ය Codec"</string>
@@ -275,6 +276,7 @@
<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="8472344901097607030">"බ්ලූටූත් Gabeldorche විශේෂාංග අට්ටිය සබල කරයි."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"අභ්‍යන්තර අන්තය"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"දේශීය ෂෙල් ප්‍රවේශනය පිරිනමන ටර්මිනල් යෙදුම සබල කරන්න"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP පරික්ෂාව"</string>
@@ -379,7 +381,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="5190814747212060815">"මෙම විශේෂාංගය පරීක්ෂණාත්මක සහ ඇතැම් විට ක්‍රියාකාරිත්වයට බලපෑ හැක."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"වර්ණ අන්ධතාවෙන් පෙළෙන පුද්ගලයන්ට වඩාත් නිරවද්‍ය වර්ණ බැලීමට වර්ණ නිවැරදි කිරීම සහාය වේ"</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>
diff --git a/packages/SettingsLib/res/values-sk/arrays.xml b/packages/SettingsLib/res/values-sk/arrays.xml
index bcb8d10456cf..427ee45bcfa2 100644
--- a/packages/SettingsLib/res/values-sk/arrays.xml
+++ b/packages/SettingsLib/res/values-sk/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"Zvuk: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="2908219194098827570">"Zvuk: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Povoliť voliteľné kodeky"</item>
- <item msgid="9205039209798344398">"Zakázať voliteľné kodeky"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Použiť voľbu systému (predvolené)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"Zvuk: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="3517061573669307965">"Zvuk: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Povoliť voliteľné kodeky"</item>
- <item msgid="7416462860415701287">"Zakázať voliteľné kodeky"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Použiť voľbu systému (predvolené)"</item>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index ba13586ec3bb..e022c363b7f8 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -55,12 +55,12 @@
<string name="osu_completing_sign_up" msgid="8412636665040390901">"Dokončuje sa registrácia…"</string>
<string name="osu_sign_up_failed" msgid="5605453599586001793">"Registráciu sa nepodarilo dokončiť. Klepnutím to skúste znova."</string>
<string name="osu_sign_up_complete" msgid="7640183358878916847">"Registrácia je dokončená. Pripája sa…"</string>
- <string name="speed_label_very_slow" msgid="8526005255731597666">"Veľmi nízka"</string>
- <string name="speed_label_slow" msgid="6069917670665664161">"Nízka"</string>
+ <string name="speed_label_very_slow" msgid="8526005255731597666">"Veľmi pomalá"</string>
+ <string name="speed_label_slow" msgid="6069917670665664161">"Pomalá"</string>
<string name="speed_label_okay" msgid="1253594383880810424">"OK"</string>
<string name="speed_label_medium" msgid="9078405312828606976">"Stredná"</string>
- <string name="speed_label_fast" msgid="2677719134596044051">"Vysoká"</string>
- <string name="speed_label_very_fast" msgid="8215718029533182439">"Veľmi vysoká"</string>
+ <string name="speed_label_fast" msgid="2677719134596044051">"Rýchla"</string>
+ <string name="speed_label_very_fast" msgid="8215718029533182439">"Veľmi rýchla"</string>
<string name="wifi_passpoint_expired" msgid="6540867261754427561">"Platnosť vypršala"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Odpojený"</string>
@@ -227,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Hardvérová akcelerácia tetheringu"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Zobrazovať zariadenia Bluetooth bez názvov"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Zakázať absolútnu hlasitosť"</string>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Povoliť Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Verzia rozhrania Bluetooth AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Zvoľte verziu rozhrania Bluetooth AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth Audio – kodek"</string>
@@ -275,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Kontrolovať škodlivosť aplikácií nainštalovaných pomocou nástroja ADB alebo ADT"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Zariadenia Bluetooth sa budú zobrazovať bez názvov (iba adresy MAC)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Umožňuje zakázať funkciu absolútnej hlasitosti rozhrania Bluetooth v prípade problémov s hlasitosťou vo vzdialených zariadeniach, ako je napríklad neprijateľne vysoká hlasitosť alebo absencia ovládacích prvkov."</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Umožňuje povoliť skupiny funkcií Bluetooth Gabeldorche."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Miestny terminál"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Povoliť terminálovú apl. na miestny prístup k prostrediu shell"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"Kontrola HDCP"</string>
@@ -379,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomália (červená a zelená)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomália (modrá a žltá)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Úprava farieb"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"Funkcia je experimentálna a môže mať vplyv na výkonnosť."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Korekcia farieb pomáha farboslepým ľuďom vidieť presnejšie farby"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Prekonané predvoľbou <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Zostáva približne <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-sq/arrays.xml b/packages/SettingsLib/res/values-sq/arrays.xml
index 7b75ba57d639..26ba289b96fe 100644
--- a/packages/SettingsLib/res/values-sq/arrays.xml
+++ b/packages/SettingsLib/res/values-sq/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"Audioja e <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="2908219194098827570">"Audioja e <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Aktivizo kodekët opsionalë"</item>
- <item msgid="9205039209798344398">"Çaktivizo kodekët opsionalë"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Përdor përzgjedhjen e sistemit (e parazgjedhur)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"Audioja e <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="3517061573669307965">"Audioja e <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Aktivizo kodekët opsionalë"</item>
- <item msgid="7416462860415701287">"Çaktivizo kodekët opsionalë"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Përdor përzgjedhjen e sistemit (e parazgjedhur)"</item>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 15b2ed36fcdb..c7c423018cdc 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -227,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Përshpejtimi i harduerit për ndarjen e lidhjes (internet)"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Shfaq pajisjet me Bluetooth pa emra"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Çaktivizo volumin absolut"</string>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Aktivizo Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Versioni AVRCP i Bluetooth-it"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Zgjidh versionin AVRCP të Bluetooth-it"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Kodeku Bluetooth Audio"</string>
@@ -275,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Kontrollo aplikacionet e instaluara nëpërmjet ADB/ADT për sjellje të dëmshme."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Pajisjet me Bluetooth do të shfaqen pa emra (vetëm adresat MAC)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Çaktivizon funksionin e volumit absolut të Bluetooth në rast të problemeve të volumit me pajisjet në largësi, si p.sh. një volum i lartë i papranueshëm ose mungesa e kontrollit."</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Aktivizon grupin e veçorive të Bluetooth Gabeldorche."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Terminali lokal"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Aktivizo aplikacionin terminal që ofron qasje në guaskën lokale"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"Kontrolli HDCP"</string>
@@ -379,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomali (e kuqe - e gjelbër)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomali (e kaltër - e verdhë)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Korrigjimi i ngjyrës"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"Ky funksion është eksperimental dhe mund të ndikojë në veprimtari."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Korrigjimi i ngjyrës i ndihmon njerëzit me daltonizëm të shohin ngjyra më të sakta"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Mbivendosur nga <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Rreth <xliff:g id="TIME_REMAINING">%1$s</xliff:g> të mbetura"</string>
diff --git a/packages/SettingsLib/res/values-sr/arrays.xml b/packages/SettingsLib/res/values-sr/arrays.xml
index 63c2c4184fdf..c543ac1a7fde 100644
--- a/packages/SettingsLib/res/values-sr/arrays.xml
+++ b/packages/SettingsLib/res/values-sr/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> аудио"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> аудио"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Омогући опционалне кодеке"</item>
- <item msgid="9205039209798344398">"Онемогући опционалне кодеке"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Користи избор система (подразумевано)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> аудио"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> аудио"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Омогући опционалне кодеке"</item>
- <item msgid="7416462860415701287">"Онемогући опционалне кодеке"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Користи избор система (подразумевано)"</item>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 381edef5318e..a395d7b96725 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -227,6 +227,7 @@
<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>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Омогући Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Верзија Bluetooth AVRCP-а"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Изаберите верзију Bluetooth AVRCP-а"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth аудио кодек"</string>
@@ -275,6 +276,7 @@
<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="8472344901097607030">"Омогућава групу Bluetooth Gabeldorche функција."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Локални терминал"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Омогући апл. терминала за приступ локалном командном окружењу"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP провера"</string>
@@ -379,7 +381,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="5190814747212060815">"Ова функција је експериментална и може да утиче на квалитет рада."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Корекција боја помаже људима који су далтонисти да прецизније виде боје"</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>
diff --git a/packages/SettingsLib/res/values-sv/arrays.xml b/packages/SettingsLib/res/values-sv/arrays.xml
index e9ebdfa82af1..c31b80c0eac8 100644
--- a/packages/SettingsLib/res/values-sv/arrays.xml
+++ b/packages/SettingsLib/res/values-sv/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>-ljud"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>-ljud"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Aktivera valfria kodekar"</item>
- <item msgid="9205039209798344398">"Inaktivera valfria kodekar"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Använd systemval (standardinställning)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>-ljud"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>-ljud"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Aktivera valfria kodekar"</item>
- <item msgid="7416462860415701287">"Inaktivera valfria kodekar"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Använd systemval (standardinställning)"</item>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 65fbe2036e0e..f021cc2db25c 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -227,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Maskinvaruacceleration för internetdelning"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Visa namnlösa Bluetooth-enheter"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Inaktivera Absolute volume"</string>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Aktivera Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"AVRCP-version för Bluetooth"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Välj AVRCP-version för Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Ljudkodek för Bluetooth"</string>
@@ -275,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Kontrollera om appar som installeras via ADB/ADT kan vara skadliga."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Bluetooth-enheter utan namn (enbart MAC-adresser) visas"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Inaktivera Bluetooth-funktionen Absolute volume om det skulle uppstå problem med volymen på fjärrenheter, t.ex. alldeles för hög volym eller brist på kontroll."</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Aktiverar funktionsgruppen Bluetooth Gabeldorche."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Lokal terminal"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Aktivera en terminalapp som ger åtkomst till hyllor lokalt"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP-kontroll"</string>
@@ -379,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomali (rött-grönt)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomali (blått-gult)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Färgkorrigering"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"Den här funktionen är experimentell och kan påverka prestandan."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Med färgkorrigering kan färgblinda personer se mer korrekta färger"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Har åsidosatts av <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Cirka <xliff:g id="TIME_REMAINING">%1$s</xliff:g> kvar"</string>
diff --git a/packages/SettingsLib/res/values-sw/arrays.xml b/packages/SettingsLib/res/values-sw/arrays.xml
index 0d7a969457fb..ff488583fa68 100644
--- a/packages/SettingsLib/res/values-sw/arrays.xml
+++ b/packages/SettingsLib/res/values-sw/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"Sauti ya <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="2908219194098827570">"Sauti ya <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Washa Kodeki Zisizo za Lazima"</item>
- <item msgid="9205039209798344398">"Zima Kodeki Zisizo za Lazima"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Tumia Uteuzi wa Mfumo (Chaguomsingi)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"Sauti ya <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="3517061573669307965">"Sauti ya <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Washa Kodeki Zisizo za Lazima"</item>
- <item msgid="7416462860415701287">"Zima Kodeki Zisizo za Lazima"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Tumia Uteuzi wa Mfumo (Chaguomsingi)"</item>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index e6ccc6580dd7..42422fb26133 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -227,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Kuongeza kasi kwa kutumia maunzi ili kusambaza mtandao"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Onyesha vifaa vya Bluetooth visivyo na majina"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Zima sauti kamili"</string>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Washa Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Toleo la Bluetooth AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Chagua Toleo la Bluetooth AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Kodeki ya Sauti ya Bluetooth"</string>
@@ -275,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Kagua iwapo programu zilizosakinishwa kupitia ADB/ADT zina tabia ya kudhuru."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Itaonyesha vifaa vya Bluetooth bila majina (anwani za MAC pekee)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Huzima kipengele cha Bluetooth cha sauti kamili kunapotokea matatizo ya sauti katika vifaa vya mbali kama vile sauti ya juu mno au inaposhindikana kuidhibiti."</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Huwasha rafu ya kipengele cha Bluetooth Gabeldorche."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Kituo cha karibu"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Washa programu ya mwisho inayotoa ufikiaji mkuu wa karibu"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"Inakagua HDCP"</string>
@@ -379,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (nyekundu-kijani)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (samawati-manjano)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Usahihishaji wa rangi"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"Kipengele hiki ni cha majaribio na huenda kikaathiri utendaji wa kifaa chako."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Urekebishaji wa rangi huwasaidia watu wenye matatizo ya kutofautisha rangi ili waone rangi nyingi sahihi"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Imetanguliwa na <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Zimesalia takribani <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-ta/arrays.xml b/packages/SettingsLib/res/values-ta/arrays.xml
index 5a797fc85be4..5668b6d8c327 100644
--- a/packages/SettingsLib/res/values-ta/arrays.xml
+++ b/packages/SettingsLib/res/values-ta/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ஆடியோ"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ஆடியோ"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"கட்டாயமில்லா கோடெக்குகளை இயக்கு"</item>
- <item msgid="9205039209798344398">"கட்டாயமில்லா கோடெக்குகளை முடக்கு"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"சாதனத் தேர்வைப் பயன்படுத்து (இயல்பு)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ஆடியோ"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ஆடியோ"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"கட்டாயமில்லா கோடெக்குகளை இயக்கு"</item>
- <item msgid="7416462860415701287">"கட்டாயமில்லா கோடெக்குகளை முடக்கு"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"சாதனத் தேர்வைப் பயன்படுத்து (இயல்பு)"</item>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index f0f4bef97fba..295399d4a046 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -227,6 +227,8 @@
<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>
+ <!-- no translation found for bluetooth_enable_gabeldorsche (9131730396242883416) -->
+ <skip />
<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_a2dp_codec_type" msgid="952001408455456494">"புளூடூத் ஆடியோ கோடெக்"</string>
@@ -275,6 +277,8 @@
<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>
+ <!-- no translation found for bluetooth_enable_gabeldorsche_summary (8472344901097607030) -->
+ <skip />
<string name="enable_terminal_title" msgid="3834790541986303654">"அக முனையம்"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"அக ஷெல் அணுகலை வழங்கும் இறுதிப் ஆப்ஸை இயக்கு"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP சரிபார்ப்பு"</string>
@@ -379,7 +383,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="5190814747212060815">"இது சோதனை முறையிலான அம்சம், இது செயல்திறனைப் பாதிக்கலாம்."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"வண்ணத் திருத்தத்தால் நிறக்குருடு உள்ளவர்களால் வண்ணங்களை இன்னும் துல்லியமாகப் பார்க்க முடியும்"</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>
diff --git a/packages/SettingsLib/res/values-te/arrays.xml b/packages/SettingsLib/res/values-te/arrays.xml
index 73d58def49ab..70068bfe0033 100644
--- a/packages/SettingsLib/res/values-te/arrays.xml
+++ b/packages/SettingsLib/res/values-te/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ఆడియో"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ఆడియో"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"ఐచ్ఛిక కోడెక్‌లను ప్రారంభించు"</item>
- <item msgid="9205039209798344398">"ఐచ్ఛిక కోడెక్‌లను నిలిపివేయి"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"సిస్టమ్ ఎంపికను ఉపయోగించండి (డిఫాల్ట్)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ఆడియో"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ఆడియో"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"ఐచ్ఛిక కోడెక్‌లను ప్రారంభించు"</item>
- <item msgid="7416462860415701287">"ఐచ్ఛిక కోడెక్‌లను నిలిపివేయి"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"సిస్టమ్ ఎంపికను ఉపయోగించండి (డిఫాల్ట్)"</item>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index cf5097eacc57..f92b8af24cf7 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -227,6 +227,7 @@
<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">"బ్లూటూత్ AVRCP వెర్షన్"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"బ్లూటూత్ AVRCP సంస్కరణను ఎంచుకోండి"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"బ్లూటూత్ ఆడియో కోడెక్"</string>
@@ -275,6 +276,7 @@
<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="8472344901097607030">"బ్లూటూత్ ఫీచర్ స్ట్యాక్‌ను ఎనేబుల్ చేస్తుంది."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"స్థానిక టెర్మినల్"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"స్థానిక షెల్ ప్రాప్యతను అందించే టెర్మినల్ అనువర్తనాన్ని ప్రారంభించు"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP తనిఖీ"</string>
@@ -379,7 +381,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="5190814747212060815">"ఈ ఫీచ‌ర్‌ ప్రయోగాత్మకమైనది, పనితీరుపై ప్రభావం చూపవచ్చు."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"రంగు సవరణ అనేది వర్ణాంధత్వం ఉన్న వ్యక్తులకు మరింత ఖచ్చితమైన రంగులను చూడడానికి సహాయపడుతుంది"</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>
diff --git a/packages/SettingsLib/res/values-th/arrays.xml b/packages/SettingsLib/res/values-th/arrays.xml
index 3073ac787e18..20333b72aff7 100644
--- a/packages/SettingsLib/res/values-th/arrays.xml
+++ b/packages/SettingsLib/res/values-th/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"เสียง <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="2908219194098827570">"เสียง <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"เปิดใช้ตัวแปลงรหัสที่ไม่บังคับ"</item>
- <item msgid="9205039209798344398">"ปิดใช้ตัวแปลงรหัสที่ไม่บังคับ"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"ใช้การเลือกของระบบ (ค่าเริ่มต้น)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"เสียง <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="3517061573669307965">"เสียง <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"เปิดใช้ตัวแปลงรหัสที่ไม่บังคับ"</item>
- <item msgid="7416462860415701287">"ปิดใช้ตัวแปลงรหัสที่ไม่บังคับ"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"ใช้การเลือกของระบบ (ค่าเริ่มต้น)"</item>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 145e1616601d..19ae491d4763 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -227,6 +227,7 @@
<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">"เวอร์ชันของบลูทูธ AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"เลือกเวอร์ชันของบลูทูธ AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"ตัวแปลงสัญญาณเสียงบลูทูธ"</string>
@@ -275,6 +276,7 @@
<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="8472344901097607030">"เปิดใช้สแต็กฟีเจอร์ Bluetooth Gabeldorche"</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"เทอร์มินัลในตัวเครื่อง"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"เปิดใช้งานแอปเทอร์มินัลที่ให้การเข้าถึงเชลล์ในตัวเครื่อง"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"การตรวจสอบ HDCP"</string>
@@ -379,7 +381,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="5190814747212060815">"ฟีเจอร์นี้เป็นแบบทดลองและอาจส่งผลต่อประสิทธิภาพการทำงาน"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"การแก้ไขสีช่วยให้ผู้ที่มีอาการตาบอดสีเห็นสีต่างๆ ได้ตรงตามจริงยิ่งขึ้น"</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>
diff --git a/packages/SettingsLib/res/values-tl/arrays.xml b/packages/SettingsLib/res/values-tl/arrays.xml
index 1ad3559d0598..473480722213 100644
--- a/packages/SettingsLib/res/values-tl/arrays.xml
+++ b/packages/SettingsLib/res/values-tl/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> na audio"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> na audio"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"I-enable ang Mga Opsyonal na Codec"</item>
- <item msgid="9205039209798344398">"I-disable ang Mga Opsyonal na Codec"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Gamitin ang Pagpili ng System (Default)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> na audio"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> na audio"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"I-enable ang Mga Opsyonal na Codec"</item>
- <item msgid="7416462860415701287">"I-disable ang Mga Opsyonal na Codec"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Gamitin ang Pagpili ng System (Default)"</item>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index e1907732c2e7..f6dfdba83b2e 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -227,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Hardware acceleration para sa pag-tether"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Ipakita ang mga Bluetooth device na walang pangalan"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"I-disable ang absolute volume"</string>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"I-enable ang Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bersyon ng AVRCP ng Bluetooth"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Pumili ng Bersyon ng AVRCP ng Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth Audio Codec"</string>
@@ -275,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Tingnan kung may nakakahamak na pagkilos sa apps na na-install sa pamamagitan ng ADB/ADT."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Ipapakita ang mga Bluetooth device na walang pangalan (mga MAC address lang)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Dini-disable ang absolute volume feature ng Bluetooth kung may mga isyu sa volume ang mga malayong device gaya ng hindi katanggap-tanggap na malakas na volume o kawalan ng kontrol."</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Ine-enable ang stack ng feature ng Bluetooth Gabeldorche."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Lokal na terminal"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Paganahin ang terminal app na nag-aalok ng lokal na shell access"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"Pagsusuring HDCP"</string>
@@ -379,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (pula-berde)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (asul-dilaw)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Pagtatama ng kulay"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"Ang feature na ito ay pinag-eeksperimentuhan at maaaring makaapekto sa performance."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Ang pagwawasto ng kulay ay nakakatulong sa mga taong may color blindness na makita ang mga mas tamang kulay"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Na-override ng <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Humigit-kumulang <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ang natitira"</string>
diff --git a/packages/SettingsLib/res/values-tr/arrays.xml b/packages/SettingsLib/res/values-tr/arrays.xml
index c7e6cced2075..ac6e0f502bfb 100644
--- a/packages/SettingsLib/res/values-tr/arrays.xml
+++ b/packages/SettingsLib/res/values-tr/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ses"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ses"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"İsteğe Bağlı Codec\'leri Etkinleştir"</item>
- <item msgid="9205039209798344398">"İsteğe Bağlı Codec\'leri Devre Dışı Bırak"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Sistem Seçimini Kullan (Varsayılan)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ses"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ses"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"İsteğe Bağlı Codec\'leri Etkinleştir"</item>
- <item msgid="7416462860415701287">"İsteğe Bağlı Codec\'leri Devre Dışı Bırak"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Sistem Seçimini Kullan (Varsayılan)"</item>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index dc11e80eba31..554d62e7164d 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -227,6 +227,7 @@
<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>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Mutlak sesi iptal et"</string>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorsche\'yi etkileştir"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP Sürümü"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Bluetooth AVRCP Sürümünü seçin"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth Ses Codec\'i"</string>
@@ -275,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"ADB/ADT üzerinden yüklenen uygulamaları zararlı davranışlara karşı denetle."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Adsız Bluetooth cihazları (yalnızca MAC adresleri) gösterilecek"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Uzak cihazda sesin aşırı yüksek olması veya kontrol edilememesi gibi ses sorunları olması ihtimaline karşı Bluetooh mutlak ses özelliğini iptal eder."</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Bluetooth Gabeldorche özellik grubunu etkinleştirir."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Yerel terminal"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Yerel kabuk erişimi sunan terminal uygulamasını etkinleştir"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP denetimi"</string>
@@ -379,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Kırmızı renk körlüğü (kırmızı-yeşil)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Mavi renk körlüğü (mavi-sarı)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Renk düzeltme"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"Bu özellik deneyseldir ve performansı etkileyebilir."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Renk düzeltme, renk körlüğü olan kişilerin daha doğru renkler görmelerine yardımcı olur"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> tarafından geçersiz kılındı"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Yaklaşık <xliff:g id="TIME_REMAINING">%1$s</xliff:g> kaldı"</string>
diff --git a/packages/SettingsLib/res/values-uk/arrays.xml b/packages/SettingsLib/res/values-uk/arrays.xml
index 2148c0c85c8e..effd49608921 100644
--- a/packages/SettingsLib/res/values-uk/arrays.xml
+++ b/packages/SettingsLib/res/values-uk/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"Аудіо <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="2908219194098827570">"Аудіо <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Увімкнути додаткові кодеки"</item>
- <item msgid="9205039209798344398">"Вимкнути додаткові кодеки"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Використовувати вибір системи (за умовчанням)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"Аудіо <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="3517061573669307965">"Аудіо <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Увімкнути додаткові кодеки"</item>
- <item msgid="7416462860415701287">"Вимкнути додаткові кодеки"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Використовувати вибір системи (за умовчанням)"</item>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index f8a88b834a2b..17f2393e9320 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -178,7 +178,7 @@
<string name="tts_status_checking" msgid="8026559918948285013">"Перевірка…"</string>
<string name="tts_engine_settings_title" msgid="7849477533103566291">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
<string name="tts_engine_settings_button" msgid="477155276199968948">"Запускати налаштування системи"</string>
- <string name="tts_engine_preference_section_title" msgid="3861562305498624904">"Бажана система"</string>
+ <string name="tts_engine_preference_section_title" msgid="3861562305498624904">"Система за умовчанням"</string>
<string name="tts_general_section_title" msgid="8919671529502364567">"Загальні"</string>
<string name="tts_reset_speech_pitch_title" msgid="7149398585468413246">"Скинути рівень звуку мовлення"</string>
<string name="tts_reset_speech_pitch_summary" msgid="6822904157021406449">"Установлено рівень звуку за умовчанням для читання тексту."</string>
@@ -227,6 +227,7 @@
<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>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Увімкнути Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Версія Bluetooth AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Виберіть версію Bluetooth AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Кодек для аудіо Bluetooth"</string>
@@ -275,6 +276,7 @@
<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="8472344901097607030">"Вмикає функції Bluetooth Gabeldorche."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Локальний термінал"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Увімк. програму-термінал, що надає локальний доступ до оболонки"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"Перевірка HDCP"</string>
@@ -379,7 +381,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="5190814747212060815">"Це експериментальна функція. Вона може вплинути на продуктивність."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Корекція кольору допомагає людям із дальтонізмом бачити точніші кольори"</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>
diff --git a/packages/SettingsLib/res/values-ur/arrays.xml b/packages/SettingsLib/res/values-ur/arrays.xml
index f0303db6ee55..d5a59ac78a5b 100644
--- a/packages/SettingsLib/res/values-ur/arrays.xml
+++ b/packages/SettingsLib/res/values-ur/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> آڈیو"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> آڈیو"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"اختیاری کوڈیکز کو فعال کریں"</item>
- <item msgid="9205039209798344398">"اختیاری کوڈیکز کو غیر فعال کریں"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"سسٹم انتخاب کا استعمال کریں (ڈیفالٹ)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> آڈیو"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> آڈیو"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"اختیاری کوڈیکز کو فعال کریں"</item>
- <item msgid="7416462860415701287">"اختیاری کوڈیکز کو غیر فعال کریں"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"سسٹم انتخاب کا استعمال کریں (ڈیفالٹ)"</item>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 246b6a217f6b..6830c595ef2d 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -227,6 +227,7 @@
<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">"‏بلوٹوتھ AVRCP ورژن"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"‏بلوٹوتھ AVRCP ورژن منتخب کریں"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"بلوٹوتھ آڈیو کوڈیک"</string>
@@ -275,6 +276,7 @@
<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="8472344901097607030">"‏بلوٹوتھ Gabeldorche خصوصیت کے انبار کو فعال کرتا ہے۔"</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"مقامی ٹرمینل"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"مقامی شیل رسائی پیش کرنے والی ٹرمینل ایپ فعال کریں"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"‏HDCP چیکنگ"</string>
@@ -379,7 +381,7 @@
<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="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"یہ خصوصیت تجرباتی ہے اور اس کی وجہ سے کاکردگی متاثر ہو سکتی ہے۔"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"رنگ کی درستگی رنگ نہ دکھائی دینے والے لوگوں کی رنگوں کو مزید درست طریقے سے دیکھنے میں مدد کرتی ہے"</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>
diff --git a/packages/SettingsLib/res/values-uz/arrays.xml b/packages/SettingsLib/res/values-uz/arrays.xml
index 9a55f45589ca..4d30e4638902 100644
--- a/packages/SettingsLib/res/values-uz/arrays.xml
+++ b/packages/SettingsLib/res/values-uz/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audiokodeki"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audiokodeki"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Boshqa kodeklarni yoqish"</item>
- <item msgid="9205039209798344398">"Boshqa kodeklarni o‘chirib qo‘yish"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Tizim tanlovi (birlamchi)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audiokodeki"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audiokodeki"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Boshqa kodeklarni yoqish"</item>
- <item msgid="7416462860415701287">"Boshqa kodeklarni o‘chirib qo‘yish"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Tizim tanlovi (birlamchi)"</item>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 87cc2a08337a..52ec545d9e80 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -227,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Modem rejimida apparatli tezlashtirish"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Bluetooth qurilmalarini nomlarisiz ko‘rsatish"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Tovush balandligining mutlaq darajasini faolsizlantirish"</string>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorsche funksiyasini yoqish"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP versiyasi"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Bluetooth AVRCP versiyasini tanlang"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth audio kodeki"</string>
@@ -275,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"ADB/ADT orqali o‘rnatilgan ilovalar xavfsizligini tekshiring"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Bluetooth qurilmalari nomsiz (faqat MAC manzillari) ko‘rsatiladi"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Masofadan ulanadigan qurilmalar bilan muammolar yuz berganda, jumladan, juda baland ovoz yoki sozlamalarni boshqarib bo‘lmaydigan holatlarda Bluetooth ovozi balandligining mutlaq darajasini o‘chirib qo‘yadi."</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Bluetooth Gabeldorche funksiyasini ishga tushiradi."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Mahalliy terminal"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Mahalliy terminalga kirishga ruxsat beruvchi terminal ilovani faollashtirish"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP tekshiruvi"</string>
@@ -379,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaliya (qizil/yashil)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaliya (ko‘k/sariq)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Rangni tuzatish"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"Bu funksiya tajribaviy bo‘lib, u qurilma unumdorligiga ta’sir qilishi mumkin."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Ranglarni sozlash ranglarni farqlashda muammosi bor insonlarga (masalan, daltoniklarga) aniq koʻrishda yordam beradi"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> bilan almashtirildi"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Taxminan <xliff:g id="TIME_REMAINING">%1$s</xliff:g> qoldi"</string>
diff --git a/packages/SettingsLib/res/values-vi/arrays.xml b/packages/SettingsLib/res/values-vi/arrays.xml
index f643136638d2..edfe89e0b0ee 100644
--- a/packages/SettingsLib/res/values-vi/arrays.xml
+++ b/packages/SettingsLib/res/values-vi/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"Âm thanh <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="2908219194098827570">"Âm thanh <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Bật codec tùy chọn"</item>
- <item msgid="9205039209798344398">"Tắt codec tùy chọn"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Sử dụng lựa chọn của hệ thống (Mặc định)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"Âm thanh <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="3517061573669307965">"Âm thanh <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Bật codec tùy chọn"</item>
- <item msgid="7416462860415701287">"Tắt codec tùy chọn"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Sử dụng lựa chọn của hệ thống (Mặc định)"</item>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 0a9726a04aef..2a124646cd5f 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -227,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Tăng tốc phần cứng khi chia sẻ kết nối"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Hiển thị các thiết bị Bluetooth không có tên"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Vô hiệu hóa âm lượng tuyệt đối"</string>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Bật tính năng Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Phiên bản Bluetooth AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Chọn phiên bản Bluetooth AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Codec âm thanh Bluetooth"</string>
@@ -275,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Kiểm tra các ứng dụng được cài đặt qua ADB/ADT để xem có hoạt động gây hại hay không."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Các thiết bị Bluetooth không có tên (chỉ có địa chỉ MAC) sẽ được hiển thị"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Vô hiệu hóa tính năng âm lượng tuyệt đối qua Bluetooth trong trường hợp xảy ra sự cố về âm lượng với các thiết bị từ xa, chẳng hạn như âm lượng lớn không thể chấp nhận được hoặc thiếu kiểm soát."</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Bật ngăn xếp tính năng Bluetooth Gabeldorche."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Dòng lệnh cục bộ"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Bật ứng dụng dòng lệnh cung cấp quyền truy cập vỏ cục bộ"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"Kiểm tra HDCP"</string>
@@ -379,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Mù màu đỏ không hoàn toàn (đỏ-xanh lục)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Mù màu (xanh lam-vàng)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Sửa màu"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"Tính năng này là tính năng thử nghiệm và có thể ảnh hưởng đến hoạt động."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Tùy chọn sửa màu giúp những người bị mù màu thấy màu sắc chính xác hơn"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Bị ghi đè bởi <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Còn khoảng <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -457,7 +459,7 @@
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Bật"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Bật chế độ Không làm phiền"</string>
<string name="zen_mode_settings_summary_off" msgid="3832876036123504076">"Không bao giờ"</string>
- <string name="zen_interruption_level_priority" msgid="5392140786447823299">"Chỉ ưu tiên"</string>
+ <string name="zen_interruption_level_priority" msgid="5392140786447823299">"Chỉ cho các mục ưu tiên"</string>
<string name="zen_mode_and_condition" msgid="8877086090066332516">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
<string name="zen_alarm_warning_indef" msgid="4146527909616457163">"Bạn sẽ không nghe thấy báo thức tiếp theo lúc <xliff:g id="WHEN">%1$s</xliff:g> của mình trừ khi bạn tắt chức năng này trước"</string>
<string name="zen_alarm_warning" msgid="245729928048586280">"Bạn sẽ không nghe thấy báo thức tiếp theo lúc <xliff:g id="WHEN">%1$s</xliff:g> của mình"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/arrays.xml b/packages/SettingsLib/res/values-zh-rCN/arrays.xml
index fb4cba53c144..992e3e083358 100644
--- a/packages/SettingsLib/res/values-zh-rCN/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> 音频"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> 音频"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"启用可选编解码器"</item>
- <item msgid="9205039209798344398">"停用可选编解码器"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"使用系统选择(默认)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> 音频"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> 音频"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"启用可选编解码器"</item>
- <item msgid="7416462860415701287">"停用可选编解码器"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"使用系统选择(默认)"</item>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 514e67731922..3fe925b11293 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -227,6 +227,7 @@
<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">"蓝牙 AVRCP 版本"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"选择蓝牙 AVRCP 版本"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"蓝牙音频编解码器"</string>
@@ -275,6 +276,7 @@
<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="8472344901097607030">"启用“蓝牙 Gabeldorche”功能堆栈。"</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"本地终端"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"启用终端应用,以便在本地访问 Shell"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP 检查"</string>
@@ -379,7 +381,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="5190814747212060815">"这是实验性功能,性能可能不稳定。"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"颜色校正功能有助于色盲用户看到更准确的颜色"</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>
diff --git a/packages/SettingsLib/res/values-zh-rHK/arrays.xml b/packages/SettingsLib/res/values-zh-rHK/arrays.xml
index a084f340a6af..d91e61ec3032 100644
--- a/packages/SettingsLib/res/values-zh-rHK/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> 音訊"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> 音訊"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"啟用選用的編解碼器"</item>
- <item msgid="9205039209798344398">"停用選用的編解碼器"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"使用系統選擇 (預設)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> 音訊"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> 音訊"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"啟用選用的編解碼器"</item>
- <item msgid="7416462860415701287">"停用選用的編解碼器"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"使用系統選擇 (預設)"</item>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 261e8d02e5c0..ed6d5054ba8c 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -227,6 +227,7 @@
<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">"藍牙 AVRCP 版本"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"選擇藍牙 AVRCP 版本"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"藍牙音訊編解碼器"</string>
@@ -275,6 +276,7 @@
<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="8472344901097607030">"啟用藍牙 Gabeldorche 功能組合。"</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"本機終端機"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"啟用可提供本機命令介面存取權的終端機應用程式"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP 檢查"</string>
@@ -379,7 +381,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="5190814747212060815">"這是實驗性功能,效能尚待改善。"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"色彩校正有助色盲人士看到更準確的顏色"</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>
diff --git a/packages/SettingsLib/res/values-zh-rTW/arrays.xml b/packages/SettingsLib/res/values-zh-rTW/arrays.xml
index c3cb8e5a1519..f39ab84c56bc 100644
--- a/packages/SettingsLib/res/values-zh-rTW/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> 音訊"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> 音訊"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"啟用選用的轉碼器"</item>
- <item msgid="9205039209798344398">"停用選用的轉碼器"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"系統自動選擇 (預設)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> 音訊"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> 音訊"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"啟用選用的轉碼器"</item>
- <item msgid="7416462860415701287">"停用選用的轉碼器"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"系統自動選擇 (預設)"</item>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index d0ba3d03d713..45866d4fde92 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -227,6 +227,7 @@
<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">"藍牙 AVRCP 版本"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"選取藍牙 AVRCP 版本"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"藍牙音訊轉碼器"</string>
@@ -275,6 +276,7 @@
<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="8472344901097607030">"啟用藍牙 Gabeldorsche 功能堆疊。"</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"本機終端機"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"啟用可提供本機命令介面存取權的終端機應用程式"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP 檢查"</string>
@@ -379,7 +381,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="5190814747212060815">"這是一項實驗性功能,可能會對效能造成影響。"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"色彩校正可協助色盲使用者看見較準確的色彩"</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>
diff --git a/packages/SettingsLib/res/values-zu/arrays.xml b/packages/SettingsLib/res/values-zu/arrays.xml
index 3e8a2b03a454..5c93cc5b16b1 100644
--- a/packages/SettingsLib/res/values-zu/arrays.xml
+++ b/packages/SettingsLib/res/values-zu/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> umsindo"</item>
<item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> umsindo"</item>
<item msgid="3825367753087348007">"I-LDAC"</item>
- <item msgid="5832677994279829983">"Nika amandla amakhodekhi akhethekayo"</item>
- <item msgid="9205039209798344398">"Khubaza amakhodekhi akhethekayo"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Sebenzisa ukukhetha kwesistimu (Okuzenzakalelayo)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> umsindo"</item>
<item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> umsindo"</item>
<item msgid="2553206901068987657">"I-LDAC"</item>
- <item msgid="221347164942544028">"Nika amandla amakhodekhi akhethekayo"</item>
- <item msgid="7416462860415701287">"Khubaza amakhodekhi akhethekayo"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Sebenzisa ukukhetha kwesistimu (Okuzenzakalelayo)"</item>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index f8cc50bc8335..8b004f96d4f3 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -227,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"I-Tethering hardware acceleration"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Bonisa amadivayisi e-Bluetooth ngaphandle kwamagama"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Khubaza ivolumu ngokuphelele"</string>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Nika amandla i-Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Inguqulo ye-Bluetooth ye-AVRCP"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Khetha inguqulo ye-Bluetooth AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"I-Bluetooth Audio Codec"</string>
@@ -275,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Hlola izinhlelo zokusebenza ezifakiwe nge-ADB/ADT ngokuziphatha okuyingozi."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Amadivayisi e-Bluetooth anganawo amagama (Amakheli e-MAC kuphela) azoboniswa"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Ikhubaza isici esiphelele sevolumu ye-Bluetooth uma kuba nezinkinga zevolumu ngamadivayisi esilawuli kude ezifana nevolumu ephezulu noma eshoda ngokulawuleka."</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Inika amandla isitaki sesici se-Bluetooth Gabeldorche."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Itheminali yasendaweni"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Nika amandla uhlelo lokusebenza letheminali olunikeza ukufinyelela kwasendaweni kwe-shell"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"Ihlola i-HDCP"</string>
@@ -379,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"I-Protanomaly (bomvu-luhlaza)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"I-Tritanomaly (luhlaza okwesibhakabhaka-phuzi)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Ukulungiswa kombala"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"Lesi sici esesilingo futhi singathinta ukusebenza."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Ukulungisa umbala kusiza abantu abangaboni imibala ukubona ngokuqondile"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Igitshezwe ngaphezulu yi-<xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Cishe u-<xliff:g id="TIME_REMAINING">%1$s</xliff:g> osele"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index 14f233d958e6..de523d9f9bc8 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -1,7 +1,5 @@
package com.android.settingslib;
-import static android.telephony.ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN;
-
import android.annotation.ColorInt;
import android.content.Context;
import android.content.Intent;
@@ -25,6 +23,8 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.print.PrintManager;
import android.provider.Settings;
+import android.telephony.AccessNetworkConstants;
+import android.telephony.NetworkRegistrationInfo;
import android.telephony.ServiceState;
import com.android.internal.annotations.VisibleForTesting;
@@ -412,15 +412,30 @@ public class Utils {
// service" or "emergency calls only" text that indicates that voice
// is not available. Note that we ignore the IWLAN service state
// because that state indicates the use of VoWIFI and not cell service
- int state = serviceState.getState();
- int dataState = serviceState.getDataRegState();
+ final int state = serviceState.getState();
+ final int dataState = serviceState.getDataRegistrationState();
+
if (state == ServiceState.STATE_OUT_OF_SERVICE
|| state == ServiceState.STATE_EMERGENCY_ONLY) {
- if (dataState == ServiceState.STATE_IN_SERVICE
- && serviceState.getDataNetworkType() != RIL_RADIO_TECHNOLOGY_IWLAN) {
+ if (dataState == ServiceState.STATE_IN_SERVICE && isNotInIwlan(serviceState)) {
return ServiceState.STATE_IN_SERVICE;
}
}
return state;
}
+
+ private static boolean isNotInIwlan(ServiceState serviceState) {
+ final NetworkRegistrationInfo networkRegWlan = serviceState.getNetworkRegistrationInfo(
+ NetworkRegistrationInfo.DOMAIN_PS,
+ AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
+ if (networkRegWlan == null) {
+ return true;
+ }
+
+ final boolean isInIwlan = (networkRegWlan.getRegistrationState()
+ == NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
+ || (networkRegWlan.getRegistrationState()
+ == NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING);
+ return !isInIwlan;
+ }
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
index 58655a2b930a..b4b55f363020 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
@@ -203,13 +203,6 @@ public class HearingAidProfile implements LocalBluetoothProfile {
}
}
- public int getVolume() {
- if (mService == null) {
- return 0;
- }
- return mService.getVolume();
- }
-
public void setVolume(int volume) {
if (mService == null) {
return;
@@ -224,20 +217,6 @@ public class HearingAidProfile implements LocalBluetoothProfile {
return mService.getHiSyncId(device);
}
- public int getDeviceSide(BluetoothDevice device) {
- if (mService == null) {
- return BluetoothHearingAid.SIDE_LEFT;
- }
- return mService.getDeviceSide(device);
- }
-
- public int getDeviceMode(BluetoothDevice device) {
- if (mService == null) {
- return BluetoothHearingAid.MODE_MONAURAL;
- }
- return mService.getDeviceMode(device);
- }
-
public String toString() {
return NAME;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/EventLogWriter.java b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/EventLogWriter.java
index 5b9281cb9d2e..d84e57a38ee4 100644
--- a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/EventLogWriter.java
+++ b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/EventLogWriter.java
@@ -40,8 +40,12 @@ public class EventLogWriter implements LogWriter {
}
@Override
- public void hidden(Context context, int category) {
- MetricsLogger.hidden(context, category);
+ public void hidden(Context context, int category, int visibleTime) {
+ final LogMaker logMaker = new LogMaker(category)
+ .setType(MetricsProto.MetricsEvent.TYPE_CLOSE)
+ .addTaggedData(MetricsProto.MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE,
+ visibleTime);
+ MetricsLogger.action(logMaker);
}
@Override
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/LogWriter.java b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/LogWriter.java
index 9d9c17f3b443..d4ef3d7b24a2 100644
--- a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/LogWriter.java
+++ b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/LogWriter.java
@@ -31,7 +31,7 @@ public interface LogWriter {
/**
* Logs a visibility event when view becomes hidden.
*/
- void hidden(Context context, int category);
+ void hidden(Context context, int category, int visibleTime);
/**
* Logs an user action.
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/MetricsFeatureProvider.java b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/MetricsFeatureProvider.java
index a82231a597c3..c34c365c1bfa 100644
--- a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/MetricsFeatureProvider.java
+++ b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/MetricsFeatureProvider.java
@@ -83,9 +83,15 @@ public class MetricsFeatureProvider {
}
}
- public void hidden(Context context, int category) {
+ /**
+ * Logs an event when target page is hidden.
+ *
+ * @param category the target page id
+ * @param visibleTime the time spending on target page since being visible
+ */
+ public void hidden(Context context, int category, int visibleTime) {
for (LogWriter writer : mLoggerWriters) {
- writer.hidden(context, category);
+ writer.hidden(context, category, visibleTime);
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixin.java b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixin.java
index 0a1a1226d0a3..61e47f8f8dd8 100644
--- a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixin.java
+++ b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixin.java
@@ -40,7 +40,8 @@ public class VisibilityLoggerMixin implements LifecycleObserver, OnAttach {
private MetricsFeatureProvider mMetricsFeature;
private int mSourceMetricsCategory = MetricsProto.MetricsEvent.VIEW_UNKNOWN;
- private long mTimestamp;
+ private long mCreationTimestamp;
+ private long mVisibleTimestamp;
public VisibilityLoggerMixin(int metricsCategory, MetricsFeatureProvider metricsFeature) {
mMetricsCategory = metricsCategory;
@@ -49,7 +50,7 @@ public class VisibilityLoggerMixin implements LifecycleObserver, OnAttach {
@Override
public void onAttach() {
- mTimestamp = SystemClock.elapsedRealtime();
+ mCreationTimestamp = SystemClock.elapsedRealtime();
}
@OnLifecycleEvent(Event.ON_RESUME)
@@ -57,8 +58,9 @@ public class VisibilityLoggerMixin implements LifecycleObserver, OnAttach {
if (mMetricsFeature == null || mMetricsCategory == METRICS_CATEGORY_UNKNOWN) {
return;
}
- if (mTimestamp != 0L) {
- final int elapse = (int) (SystemClock.elapsedRealtime() - mTimestamp);
+ mVisibleTimestamp = SystemClock.elapsedRealtime();
+ if (mCreationTimestamp != 0L) {
+ final int elapse = (int) (mVisibleTimestamp - mCreationTimestamp);
mMetricsFeature.visible(null /* context */, mSourceMetricsCategory,
mMetricsCategory, elapse);
} else {
@@ -69,9 +71,10 @@ public class VisibilityLoggerMixin implements LifecycleObserver, OnAttach {
@OnLifecycleEvent(Event.ON_PAUSE)
public void onPause() {
- mTimestamp = 0;
+ mCreationTimestamp = 0;
if (mMetricsFeature != null && mMetricsCategory != METRICS_CATEGORY_UNKNOWN) {
- mMetricsFeature.hidden(null /* context */, mMetricsCategory);
+ final int elapse = (int) (SystemClock.elapsedRealtime() - mVisibleTimestamp);
+ mMetricsFeature.hidden(null /* context */, mMetricsCategory, elapse);
}
}
@@ -84,7 +87,7 @@ public class VisibilityLoggerMixin implements LifecycleObserver, OnAttach {
if (mMetricsFeature == null || mMetricsCategory == METRICS_CATEGORY_UNKNOWN) {
return;
}
- final int elapse = (int) (SystemClock.elapsedRealtime() - mTimestamp);
+ final int elapse = (int) (SystemClock.elapsedRealtime() - mCreationTimestamp);
mMetricsFeature.action(METRICS_CATEGORY_UNKNOWN, action, mMetricsCategory, key, elapse);
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java
index 732e8dba3e44..99c7dcf52818 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java
@@ -17,9 +17,8 @@ package com.android.settingslib.media;
import android.content.Context;
import android.graphics.drawable.Drawable;
-import android.widget.Toast;
-
-import androidx.mediarouter.media.MediaRouter;
+import android.media.MediaRoute2Info;
+import android.media.MediaRouter2Manager;
import com.android.settingslib.R;
import com.android.settingslib.bluetooth.BluetoothUtils;
@@ -31,22 +30,28 @@ public class InfoMediaDevice extends MediaDevice {
private static final String TAG = "InfoMediaDevice";
- private MediaRouter.RouteInfo mRouteInfo;
+ private final MediaRoute2Info mRouteInfo;
+ private final MediaRouter2Manager mRouterManager;
+ private final String mPackageName;
- InfoMediaDevice(Context context, MediaRouter.RouteInfo info) {
+ InfoMediaDevice(Context context, MediaRouter2Manager routerManager, MediaRoute2Info info,
+ String packageName) {
super(context, MediaDeviceType.TYPE_CAST_DEVICE);
+ mRouterManager = routerManager;
mRouteInfo = info;
+ mPackageName = packageName;
initDeviceRecord();
}
@Override
public String getName() {
- return mRouteInfo.getName();
+ return mRouteInfo.getName().toString();
}
@Override
public String getSummary() {
- return null;
+ return mRouteInfo.getClientPackageName() != null
+ ? mContext.getString(R.string.bluetooth_active_no_battery_level) : null;
}
@Override
@@ -63,15 +68,14 @@ public class InfoMediaDevice extends MediaDevice {
@Override
public boolean connect() {
- //TODO(b/121083246): use SystemApi to transfer media
setConnectedRecord();
- Toast.makeText(mContext, "This is cast device !", Toast.LENGTH_SHORT).show();
- return false;
+ mRouterManager.selectRoute(mPackageName, mRouteInfo);
+ return true;
}
@Override
public void disconnect() {
- //TODO(b/121083246): disconnected last select device
+ //TODO(b/144535188): disconnected last select device
}
@Override
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
index bc8e2c35291d..e008cd038317 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
@@ -17,13 +17,16 @@ package com.android.settingslib.media;
import android.app.Notification;
import android.content.Context;
-import android.util.Log;
-
-import androidx.mediarouter.media.MediaRouteSelector;
-import androidx.mediarouter.media.MediaRouter;
+import android.media.MediaRoute2Info;
+import android.media.MediaRouter2Manager;
+import android.text.TextUtils;
import com.android.internal.annotations.VisibleForTesting;
+import java.util.List;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
/**
* InfoMediaManager provide interface to get InfoMediaDevice list.
*/
@@ -32,62 +35,75 @@ public class InfoMediaManager extends MediaManager {
private static final String TAG = "InfoMediaManager";
@VisibleForTesting
- final MediaRouterCallback mMediaRouterCallback = new MediaRouterCallback();
+ final RouterManagerCallback mMediaRouterCallback = new RouterManagerCallback();
@VisibleForTesting
- MediaRouteSelector mSelector;
+ final Executor mExecutor = Executors.newSingleThreadExecutor();
@VisibleForTesting
- MediaRouter mMediaRouter;
+ MediaRouter2Manager mRouterManager;
private String mPackageName;
+ private MediaDevice mCurrentConnectedDevice;
- InfoMediaManager(Context context, String packageName, Notification notification) {
+ public InfoMediaManager(Context context, String packageName, Notification notification) {
super(context, notification);
- mMediaRouter = MediaRouter.getInstance(context);
- mPackageName = packageName;
- mSelector = new MediaRouteSelector.Builder()
- .addControlCategory(getControlCategoryByPackageName(mPackageName))
- .build();
+ mRouterManager = MediaRouter2Manager.getInstance(context);
+ if (packageName != null) {
+ mPackageName = packageName;
+ }
}
@Override
public void startScan() {
mMediaDevices.clear();
- mMediaRouter.addCallback(mSelector, mMediaRouterCallback,
- MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY);
+ mRouterManager.registerCallback(mExecutor, mMediaRouterCallback);
}
@VisibleForTesting
String getControlCategoryByPackageName(String packageName) {
//TODO(b/117129183): Use package name to get ControlCategory.
//Since api not ready, return fixed ControlCategory for prototype.
- return "com.google.android.gms.cast.CATEGORY_CAST/4F8B3483";
+ return "com.google.android.gms.cast.CATEGORY_CAST";
}
@Override
public void stopScan() {
- mMediaRouter.removeCallback(mMediaRouterCallback);
+ mRouterManager.unregisterCallback(mMediaRouterCallback);
}
- class MediaRouterCallback extends MediaRouter.Callback {
- @Override
- public void onRouteAdded(MediaRouter router, MediaRouter.RouteInfo route) {
- MediaDevice mediaDevice = findMediaDevice(MediaDeviceUtils.getId(route));
- if (mediaDevice == null) {
- mediaDevice = new InfoMediaDevice(mContext, route);
- Log.d(TAG, "onRouteAdded() route : " + route.getName());
- mMediaDevices.add(mediaDevice);
- dispatchDeviceAdded(mediaDevice);
+ /**
+ * Get current device that played media.
+ * @return MediaDevice
+ */
+ public MediaDevice getCurrentConnectedDevice() {
+ return mCurrentConnectedDevice;
+ }
+
+ class RouterManagerCallback extends MediaRouter2Manager.Callback {
+
+ private void refreshDevices() {
+ mMediaDevices.clear();
+ mCurrentConnectedDevice = null;
+ for (MediaRoute2Info route : mRouterManager.getAvailableRoutes(mPackageName)) {
+ final MediaDevice device = new InfoMediaDevice(mContext, mRouterManager, route,
+ mPackageName);
+ if (TextUtils.equals(route.getClientPackageName(), mPackageName)) {
+ mCurrentConnectedDevice = device;
+ }
+ mMediaDevices.add(device);
}
+ dispatchDeviceListAdded();
+ }
+
+ @Override
+ public void onRoutesAdded(List<MediaRoute2Info> routes) {
+ refreshDevices();
}
@Override
- public void onRouteRemoved(MediaRouter router, MediaRouter.RouteInfo route) {
- final MediaDevice mediaDevice = findMediaDevice(MediaDeviceUtils.getId(route));
- if (mediaDevice != null) {
- Log.d(TAG, "onRouteRemoved() route : " + route.getName());
- mMediaDevices.remove(mediaDevice);
- dispatchDeviceRemoved(mediaDevice);
+ public void onControlCategoriesChanged(String packageName, List<String> controlCategories) {
+ if (TextUtils.equals(mPackageName, packageName)) {
+ refreshDevices();
}
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
index 4e16c66d736b..5b4ef3a47386 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
@@ -18,6 +18,7 @@ package com.android.settingslib.media;
import android.app.Notification;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
+import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.IntDef;
@@ -59,6 +60,8 @@ public class LocalMediaManager implements BluetoothCallback {
private Context mContext;
private BluetoothMediaManager mBluetoothMediaManager;
private LocalBluetoothManager mLocalBluetoothManager;
+ private InfoMediaManager mInfoMediaManager;
+ private String mPackageName;
@VisibleForTesting
List<MediaDevice> mMediaDevices = new ArrayList<>();
@@ -87,6 +90,7 @@ public class LocalMediaManager implements BluetoothCallback {
public LocalMediaManager(Context context, String packageName, Notification notification) {
mContext = context;
+ mPackageName = packageName;
mLocalBluetoothManager =
LocalBluetoothManager.getInstance(context, /* onInitCallback= */ null);
if (mLocalBluetoothManager == null) {
@@ -96,6 +100,7 @@ public class LocalMediaManager implements BluetoothCallback {
mBluetoothMediaManager =
new BluetoothMediaManager(context, mLocalBluetoothManager, notification);
+ mInfoMediaManager = new InfoMediaManager(context, packageName, notification);
}
@VisibleForTesting
@@ -104,6 +109,7 @@ public class LocalMediaManager implements BluetoothCallback {
mContext = context;
mLocalBluetoothManager = localBluetoothManager;
mBluetoothMediaManager = bluetoothMediaManager;
+ mInfoMediaManager = infoMediaManager;
}
/**
@@ -126,8 +132,7 @@ public class LocalMediaManager implements BluetoothCallback {
return;
}
- //TODO(b/121083246): Update it once remote media API is ready.
- if (mCurrentConnectedDevice != null && !(connectDevice instanceof InfoMediaDevice)) {
+ if (mCurrentConnectedDevice != null) {
mCurrentConnectedDevice.disconnect();
}
@@ -157,6 +162,10 @@ public class LocalMediaManager implements BluetoothCallback {
mMediaDevices.clear();
mBluetoothMediaManager.registerCallback(mMediaDeviceCallback);
mBluetoothMediaManager.startScan();
+ if (!TextUtils.isEmpty(mPackageName)) {
+ mInfoMediaManager.registerCallback(mMediaDeviceCallback);
+ mInfoMediaManager.startScan();
+ }
}
private void addPhoneDeviceIfNecessary() {
@@ -191,6 +200,10 @@ public class LocalMediaManager implements BluetoothCallback {
public void stopScan() {
mBluetoothMediaManager.unregisterCallback(mMediaDeviceCallback);
mBluetoothMediaManager.stopScan();
+ if (!TextUtils.isEmpty(mPackageName)) {
+ mInfoMediaManager.unregisterCallback(mMediaDeviceCallback);
+ mInfoMediaManager.stopScan();
+ }
}
/**
@@ -253,7 +266,9 @@ public class LocalMediaManager implements BluetoothCallback {
}
}
addPhoneDeviceIfNecessary();
- mCurrentConnectedDevice = updateCurrentConnectedDevice();
+ final MediaDevice infoMediaDevice = mInfoMediaManager.getCurrentConnectedDevice();
+ mCurrentConnectedDevice = infoMediaDevice != null
+ ? infoMediaDevice : updateCurrentConnectedDevice();
updatePhoneMediaDeviceSummary();
dispatchDeviceListUpdate();
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/MediaDeviceUtils.java b/packages/SettingsLib/src/com/android/settingslib/media/MediaDeviceUtils.java
index 4b8e706c0d0c..df6929e114ee 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/MediaDeviceUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/MediaDeviceUtils.java
@@ -16,8 +16,7 @@
package com.android.settingslib.media;
import android.bluetooth.BluetoothDevice;
-
-import androidx.mediarouter.media.MediaRouter;
+import android.media.MediaRoute2Info;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
@@ -49,12 +48,12 @@ public class MediaDeviceUtils {
}
/**
- * Use RouteInfo id to represent unique id
+ * Use MediaRoute2Info id to represent unique id
*
- * @param route the RouteInfo
- * @return RouteInfo id
+ * @param route the MediaRoute2Info
+ * @return MediaRoute2Info id
*/
- public static String getId(MediaRouter.RouteInfo route) {
+ public static String getId(MediaRoute2Info route) {
return route.getId();
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/MediaOutputSliceConstants.java b/packages/SettingsLib/src/com/android/settingslib/media/MediaOutputSliceConstants.java
index e600cb892c44..248b118f6ece 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/MediaOutputSliceConstants.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/MediaOutputSliceConstants.java
@@ -27,6 +27,11 @@ public class MediaOutputSliceConstants {
public static final String KEY_MEDIA_OUTPUT = "media_output";
/**
+ * Key for the Remote Media slice.
+ */
+ public static final String KEY_REMOTE_MEDIA = "remote_media";
+
+ /**
* Activity Action: Show a settings dialog containing {@link MediaDevice} to transfer media.
*/
public static final String ACTION_MEDIA_OUTPUT =
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java
index 23e2949372aa..ebca962a918e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java
@@ -46,7 +46,7 @@ public class DataUsageUtils {
}
final String[] mergedSubscriberIds = telephonyManager.createForSubscriptionId(subId)
- .getMergedSubscriberIdsFromGroup();
+ .getMergedImsisFromGroup();
if (ArrayUtils.isEmpty(mergedSubscriberIds)) {
Log.i(TAG, "mergedSubscriberIds is null.");
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java
index fc69b1a657d4..11829451f640 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java
@@ -34,6 +34,8 @@ import android.media.AudioManager;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.provider.Settings;
+import android.telephony.AccessNetworkConstants;
+import android.telephony.NetworkRegistrationInfo;
import android.telephony.ServiceState;
import android.text.TextUtils;
@@ -69,6 +71,8 @@ public class UtilsTest {
private LocationManager mLocationManager;
@Mock
private ServiceState mServiceState;
+ @Mock
+ private NetworkRegistrationInfo mNetworkRegistrationInfo;
@Before
public void setUp() {
@@ -207,35 +211,47 @@ public class UtilsTest {
@Test
public void isInService_voiceInService_returnTrue() {
when(mServiceState.getState()).thenReturn(ServiceState.STATE_IN_SERVICE);
+
assertThat(Utils.isInService(mServiceState)).isTrue();
}
@Test
public void isInService_voiceOutOfServiceDataInService_returnTrue() {
when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
- when(mServiceState.getDataRegState()).thenReturn(ServiceState.STATE_IN_SERVICE);
+ when(mServiceState.getDataRegistrationState()).thenReturn(ServiceState.STATE_IN_SERVICE);
+ when(mServiceState.getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_PS,
+ AccessNetworkConstants.TRANSPORT_TYPE_WLAN)).thenReturn(mNetworkRegistrationInfo);
+ when(mNetworkRegistrationInfo.getRegistrationState()).thenReturn(
+ NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN);
+
assertThat(Utils.isInService(mServiceState)).isTrue();
}
@Test
public void isInService_voiceOutOfServiceDataInServiceOnIwLan_returnFalse() {
when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
- when(mServiceState.getDataNetworkType())
- .thenReturn(ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN);
- when(mServiceState.getDataRegState()).thenReturn(ServiceState.STATE_IN_SERVICE);
+ when(mServiceState.getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_PS,
+ AccessNetworkConstants.TRANSPORT_TYPE_WLAN)).thenReturn(mNetworkRegistrationInfo);
+ when(mNetworkRegistrationInfo.getRegistrationState()).thenReturn(
+ NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
+ when(mServiceState.getDataRegistrationState()).thenReturn(ServiceState.STATE_IN_SERVICE);
+
assertThat(Utils.isInService(mServiceState)).isFalse();
}
@Test
public void isInService_voiceOutOfServiceDataOutOfService_returnFalse() {
when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
- when(mServiceState.getDataRegState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+ when(mServiceState.getDataRegistrationState()).thenReturn(
+ ServiceState.STATE_OUT_OF_SERVICE);
+
assertThat(Utils.isInService(mServiceState)).isFalse();
}
@Test
public void isInService_ServiceStatePowerOff_returnFalse() {
when(mServiceState.getState()).thenReturn(ServiceState.STATE_POWER_OFF);
+
assertThat(Utils.isInService(mServiceState)).isFalse();
}
@@ -248,6 +264,7 @@ public class UtilsTest {
@Test
public void getCombinedServiceState_ServiceStatePowerOff_returnPowerOff() {
when(mServiceState.getState()).thenReturn(ServiceState.STATE_POWER_OFF);
+
assertThat(Utils.getCombinedServiceState(mServiceState)).isEqualTo(
ServiceState.STATE_POWER_OFF);
}
@@ -255,6 +272,7 @@ public class UtilsTest {
@Test
public void getCombinedServiceState_voiceInService_returnInService() {
when(mServiceState.getState()).thenReturn(ServiceState.STATE_IN_SERVICE);
+
assertThat(Utils.getCombinedServiceState(mServiceState)).isEqualTo(
ServiceState.STATE_IN_SERVICE);
}
@@ -262,15 +280,35 @@ public class UtilsTest {
@Test
public void getCombinedServiceState_voiceOutOfServiceDataInService_returnInService() {
when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
- when(mServiceState.getDataRegState()).thenReturn(ServiceState.STATE_IN_SERVICE);
+ when(mServiceState.getDataRegistrationState()).thenReturn(ServiceState.STATE_IN_SERVICE);
+ when(mServiceState.getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_PS,
+ AccessNetworkConstants.TRANSPORT_TYPE_WLAN)).thenReturn(mNetworkRegistrationInfo);
+ when(mNetworkRegistrationInfo.getRegistrationState()).thenReturn(
+ NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN);
+
assertThat(Utils.getCombinedServiceState(mServiceState)).isEqualTo(
ServiceState.STATE_IN_SERVICE);
}
@Test
+ public void getCombinedServiceState_voiceOutOfServiceDataInServiceOnIwLan_returnOutOfService() {
+ when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+ when(mServiceState.getDataRegistrationState()).thenReturn(ServiceState.STATE_IN_SERVICE);
+ when(mServiceState.getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_PS,
+ AccessNetworkConstants.TRANSPORT_TYPE_WLAN)).thenReturn(mNetworkRegistrationInfo);
+ when(mNetworkRegistrationInfo.getRegistrationState()).thenReturn(
+ NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
+
+ assertThat(Utils.getCombinedServiceState(mServiceState)).isEqualTo(
+ ServiceState.STATE_OUT_OF_SERVICE);
+ }
+
+ @Test
public void getCombinedServiceState_voiceOutOfServiceDataOutOfService_returnOutOfService() {
when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
- when(mServiceState.getDataRegState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+ when(mServiceState.getDataRegistrationState()).thenReturn(
+ ServiceState.STATE_OUT_OF_SERVICE);
+
assertThat(Utils.getCombinedServiceState(mServiceState)).isEqualTo(
ServiceState.STATE_OUT_OF_SERVICE);
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixinTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixinTest.java
index f070a37aa659..7de36e8b0d89 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixinTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixinTest.java
@@ -88,7 +88,7 @@ public class VisibilityLoggerMixinTest {
mMixin.onPause();
verify(mMetricsFeature, times(1))
- .hidden(nullable(Context.class), eq(TestInstrumentable.TEST_METRIC));
+ .hidden(nullable(Context.class), eq(TestInstrumentable.TEST_METRIC), anyInt());
}
@Test
@@ -98,7 +98,7 @@ public class VisibilityLoggerMixinTest {
mMixin.onPause();
verify(mMetricsFeature, never())
- .hidden(nullable(Context.class), anyInt());
+ .hidden(nullable(Context.class), anyInt(), anyInt());
}
@Test
@@ -109,7 +109,7 @@ public class VisibilityLoggerMixinTest {
mMixin.onPause();
verify(mMetricsFeature, never())
- .hidden(nullable(Context.class), anyInt());
+ .hidden(nullable(Context.class), anyInt(), anyInt());
}
@Test
@@ -121,7 +121,7 @@ public class VisibilityLoggerMixinTest {
verify(testActivity.mMetricsFeatureProvider, times(1)).visible(any(), anyInt(), anyInt(),
anyInt());
ac.pause().stop().destroy();
- verify(testActivity.mMetricsFeatureProvider, times(1)).hidden(any(), anyInt());
+ verify(testActivity.mMetricsFeatureProvider, times(1)).hidden(any(), anyInt(), anyInt());
}
public static class TestActivity extends FragmentActivity {
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAccessesTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAccessesTest.java
index e936c359e281..68a3729432d8 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAccessesTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAccessesTest.java
@@ -17,8 +17,7 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
-import android.util.LongSparseLongArray;
-import android.util.Pair;
+import android.util.LongSparseArray;
import org.junit.Before;
import org.junit.Ignore;
@@ -159,14 +158,11 @@ public class RecentLocationAccessesTest {
private OpEntry createOpEntryWithTime(int op, long time) {
// Slot for background access timestamp.
- final LongSparseLongArray accessTimes = new LongSparseLongArray();
- accessTimes.put(AppOpsManager.makeKey(AppOpsManager.UID_STATE_BACKGROUND,
- AppOpsManager.OP_FLAG_SELF), time);
-
- OpFeatureEntry.Builder featureEntry = new OpFeatureEntry.Builder(false, accessTimes,
- null /*rejectTimes*/, null /*durations*/, null /* proxyUids */,
- null /* proxyPackages */, null /* proxyFeatureIds */);
- return new OpEntry(op, AppOpsManager.MODE_ALLOWED,
- new Pair[]{new Pair(null, featureEntry)});
+ final LongSparseArray<AppOpsManager.NoteOpEvent> accessEvents = new LongSparseArray<>();
+ accessEvents.put(AppOpsManager.makeKey(AppOpsManager.UID_STATE_BACKGROUND,
+ AppOpsManager.OP_FLAG_SELF), new AppOpsManager.NoteOpEvent(time, -1, null));
+
+ return new OpEntry(op, AppOpsManager.MODE_ALLOWED, Collections.singletonMap(null,
+ new OpFeatureEntry(op, false, accessEvents, null)));
}
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java
index 3fde48b18b63..3f8d758ae64f 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java
@@ -17,6 +17,7 @@ import android.content.res.Resources;
import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
+import android.util.LongSparseArray;
import android.util.LongSparseLongArray;
import android.util.Pair;
@@ -158,17 +159,11 @@ public class RecentLocationAppsTest {
}
private OpEntry createOpEntryWithTime(int op, long time, int duration) {
- final LongSparseLongArray accessTimes = new LongSparseLongArray();
- accessTimes.put(AppOpsManager.makeKey(AppOpsManager.UID_STATE_TOP,
- AppOpsManager.OP_FLAG_SELF), time);
- final LongSparseLongArray durations = new LongSparseLongArray();
- durations.put(AppOpsManager.makeKey(AppOpsManager.UID_STATE_TOP,
- AppOpsManager.OP_FLAG_SELF), duration);
-
- OpFeatureEntry.Builder featureEntry = new OpFeatureEntry.Builder(false, accessTimes,
- null /*rejectTimes*/, durations, null /* proxyUids */,
- null /* proxyPackages */, null /* proxyFeatureIds */);
- return new OpEntry(op, AppOpsManager.MODE_ALLOWED,
- new Pair[]{new Pair(null, featureEntry)});
+ final LongSparseArray<AppOpsManager.NoteOpEvent> accessEvents = new LongSparseArray<>();
+ accessEvents.put(AppOpsManager.makeKey(AppOpsManager.UID_STATE_TOP,
+ AppOpsManager.OP_FLAG_SELF), new AppOpsManager.NoteOpEvent(time, duration, null));
+
+ return new OpEntry(op, AppOpsManager.MODE_ALLOWED, Collections.singletonMap(null,
+ new OpFeatureEntry(op, false, accessEvents, null)));
}
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaDeviceTest.java
new file mode 100644
index 000000000000..c9db0d13a7e7
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaDeviceTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.media;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.media.MediaRoute2Info;
+import android.media.MediaRouter2Manager;
+
+import com.android.settingslib.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class InfoMediaDeviceTest {
+
+ private static final String TEST_PACKAGE_NAME = "com.test.packagename";
+ private static final String TEST_ID = "test_id";
+ private static final String TEST_NAME = "test_name";
+
+ @Mock
+ private MediaRouter2Manager mRouterManager;
+ @Mock
+ private MediaRoute2Info mRouteInfo;
+
+
+ private Context mContext;
+ private InfoMediaDevice mInfoMediaDevice;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+
+ mInfoMediaDevice = new InfoMediaDevice(mContext, mRouterManager, mRouteInfo,
+ TEST_PACKAGE_NAME);
+ }
+
+ @Test
+ public void getName_shouldReturnName() {
+ when(mRouteInfo.getName()).thenReturn(TEST_NAME);
+
+ assertThat(mInfoMediaDevice.getName()).isEqualTo(TEST_NAME);
+ }
+
+ @Test
+ public void getSummary_clientPackageNameIsNull_returnNull() {
+ when(mRouteInfo.getClientPackageName()).thenReturn(null);
+
+ assertThat(mInfoMediaDevice.getSummary()).isEqualTo(null);
+ }
+
+ @Test
+ public void getSummary_clientPackageNameIsNotNull_returnActive() {
+ when(mRouteInfo.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME);
+
+ assertThat(mInfoMediaDevice.getSummary())
+ .isEqualTo(mContext.getString(R.string.bluetooth_active_no_battery_level));
+ }
+
+ @Test
+ public void getId_shouldReturnId() {
+ when(mRouteInfo.getId()).thenReturn(TEST_ID);
+
+ assertThat(mInfoMediaDevice.getId()).isEqualTo(TEST_ID);
+ }
+
+ @Test
+ public void connect_shouldSelectRoute() {
+ mInfoMediaDevice.connect();
+
+ verify(mRouterManager).selectRoute(TEST_PACKAGE_NAME, mRouteInfo);
+ }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java
index b11cf69b04f4..67f6dd903841 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java
@@ -23,9 +23,8 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
-
-import androidx.mediarouter.media.MediaRouteSelector;
-import androidx.mediarouter.media.MediaRouter;
+import android.media.MediaRoute2Info;
+import android.media.MediaRouter2Manager;
import org.junit.Before;
import org.junit.Test;
@@ -35,6 +34,9 @@ import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
+import java.util.ArrayList;
+import java.util.List;
+
@RunWith(RobolectricTestRunner.class)
public class InfoMediaManagerTest {
@@ -42,9 +44,7 @@ public class InfoMediaManagerTest {
private static final String TEST_ID = "test_id";
@Mock
- private MediaRouter mMediaRouter;
- @Mock
- private MediaRouteSelector mSelector;
+ private MediaRouter2Manager mRouterManager;
private InfoMediaManager mInfoMediaManager;
private Context mContext;
@@ -55,82 +55,70 @@ public class InfoMediaManagerTest {
mContext = RuntimeEnvironment.application;
mInfoMediaManager = new InfoMediaManager(mContext, TEST_PACKAGE_NAME, null);
- mInfoMediaManager.mMediaRouter = mMediaRouter;
- mInfoMediaManager.mSelector = mSelector;
+ mInfoMediaManager.mRouterManager = mRouterManager;
}
@Test
public void stopScan_shouldRemoveCallback() {
mInfoMediaManager.stopScan();
- verify(mMediaRouter).removeCallback(mInfoMediaManager.mMediaRouterCallback);
+ verify(mRouterManager).unregisterCallback(mInfoMediaManager.mMediaRouterCallback);
}
@Test
public void startScan_shouldAddCallback() {
mInfoMediaManager.startScan();
- verify(mMediaRouter).addCallback(mSelector, mInfoMediaManager.mMediaRouterCallback,
- MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY);
+ verify(mRouterManager).registerCallback(mInfoMediaManager.mExecutor,
+ mInfoMediaManager.mMediaRouterCallback);
}
@Test
- public void onRouteAdded_mediaDeviceNotExistInList_addMediaDevice() {
- final MediaRouter.RouteInfo info = mock(MediaRouter.RouteInfo.class);
+ public void onRouteAdded_shouldAddMediaDevice() {
+ final MediaRoute2Info info = mock(MediaRoute2Info.class);
when(info.getId()).thenReturn(TEST_ID);
+ when(info.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME);
+
+ final List<MediaRoute2Info> routes = new ArrayList<>();
+ routes.add(info);
+ when(mRouterManager.getAvailableRoutes(TEST_PACKAGE_NAME)).thenReturn(routes);
final MediaDevice mediaDevice = mInfoMediaManager.findMediaDevice(TEST_ID);
assertThat(mediaDevice).isNull();
- mInfoMediaManager.mMediaRouterCallback.onRouteAdded(mMediaRouter, info);
+ mInfoMediaManager.mMediaRouterCallback.onRoutesAdded(routes);
final MediaDevice infoDevice = mInfoMediaManager.mMediaDevices.get(0);
assertThat(infoDevice.getId()).isEqualTo(TEST_ID);
+ assertThat(mInfoMediaManager.getCurrentConnectedDevice()).isEqualTo(infoDevice);
+ assertThat(mInfoMediaManager.mMediaDevices).hasSize(routes.size());
}
@Test
- public void onRouteAdded_mediaDeviceExistInList_doNothing() {
- final MediaRouter.RouteInfo info = mock(MediaRouter.RouteInfo.class);
+ public void onControlCategoriesChanged_samePackageName_shouldAddMediaDevice() {
+ final MediaRoute2Info info = mock(MediaRoute2Info.class);
when(info.getId()).thenReturn(TEST_ID);
- final InfoMediaDevice infoDevice = new InfoMediaDevice(mContext, info);
- mInfoMediaManager.mMediaDevices.add(infoDevice);
-
- final MediaDevice mediaDevice = mInfoMediaManager.findMediaDevice(TEST_ID);
- final int size = mInfoMediaManager.mMediaDevices.size();
- assertThat(mediaDevice).isNotNull();
-
- mInfoMediaManager.mMediaRouterCallback.onRouteAdded(mMediaRouter, info);
+ when(info.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME);
- assertThat(mInfoMediaManager.mMediaDevices).hasSize(size);
- }
-
- @Test
- public void onRouteRemoved_mediaDeviceExistInList_removeMediaDevice() {
- final MediaRouter.RouteInfo info = mock(MediaRouter.RouteInfo.class);
- when(info.getId()).thenReturn(TEST_ID);
- final InfoMediaDevice infoDevice = new InfoMediaDevice(mContext, info);
- mInfoMediaManager.mMediaDevices.add(infoDevice);
+ final List<MediaRoute2Info> routes = new ArrayList<>();
+ routes.add(info);
+ when(mRouterManager.getAvailableRoutes(TEST_PACKAGE_NAME)).thenReturn(routes);
final MediaDevice mediaDevice = mInfoMediaManager.findMediaDevice(TEST_ID);
- assertThat(mediaDevice).isNotNull();
- assertThat(mInfoMediaManager.mMediaDevices).hasSize(1);
+ assertThat(mediaDevice).isNull();
- mInfoMediaManager.mMediaRouterCallback.onRouteRemoved(mMediaRouter, info);
+ mInfoMediaManager.mMediaRouterCallback.onControlCategoriesChanged(TEST_PACKAGE_NAME, null);
- assertThat(mInfoMediaManager.mMediaDevices).isEmpty();
+ final MediaDevice infoDevice = mInfoMediaManager.mMediaDevices.get(0);
+ assertThat(infoDevice.getId()).isEqualTo(TEST_ID);
+ assertThat(mInfoMediaManager.getCurrentConnectedDevice()).isEqualTo(infoDevice);
+ assertThat(mInfoMediaManager.mMediaDevices).hasSize(routes.size());
}
@Test
- public void onRouteRemoved_mediaDeviceNotExistInList_doNothing() {
- final MediaRouter.RouteInfo info = mock(MediaRouter.RouteInfo.class);
- when(info.getId()).thenReturn(TEST_ID);
-
- final MediaDevice mediaDevice = mInfoMediaManager.findMediaDevice(TEST_ID);
- final int size = mInfoMediaManager.mMediaDevices.size();
- assertThat(mediaDevice).isNull();
-
- mInfoMediaManager.mMediaRouterCallback.onRouteRemoved(mMediaRouter, info);
+ public void onControlCategoriesChanged_differentPackageName_doNothing() {
+ mInfoMediaManager.mMediaRouterCallback.onControlCategoriesChanged("com.fake.play", null);
- assertThat(mInfoMediaManager.mMediaDevices).hasSize(size);
+ assertThat(mInfoMediaManager.mMediaDevices).hasSize(0);
}
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java
index 23d2c74218cc..02cb83e0281a 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java
@@ -22,8 +22,8 @@ import static org.mockito.Mockito.when;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
-
-import androidx.mediarouter.media.MediaRouter;
+import android.media.MediaRoute2Info;
+import android.media.MediaRouter2Manager;
import com.android.settingslib.bluetooth.A2dpProfile;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
@@ -56,6 +56,7 @@ public class MediaDeviceTest {
private static final String ROUTER_ID_1 = "RouterId_1";
private static final String ROUTER_ID_2 = "RouterId_2";
private static final String ROUTER_ID_3 = "RouterId_3";
+ private static final String TEST_PACKAGE_NAME = "com.test.playmusic";
private final BluetoothClass mHeadreeClass =
new BluetoothClass(BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES);
private final BluetoothClass mCarkitClass =
@@ -76,11 +77,11 @@ public class MediaDeviceTest {
@Mock
private LocalBluetoothManager mLocalBluetoothManager;
@Mock
- private MediaRouter.RouteInfo mRouteInfo1;
+ private MediaRoute2Info mRouteInfo1;
@Mock
- private MediaRouter.RouteInfo mRouteInfo2;
+ private MediaRoute2Info mRouteInfo2;
@Mock
- private MediaRouter.RouteInfo mRouteInfo3;
+ private MediaRoute2Info mRouteInfo3;
@Mock
private LocalBluetoothProfileManager mProfileManager;
@Mock
@@ -99,6 +100,7 @@ public class MediaDeviceTest {
private InfoMediaDevice mInfoMediaDevice3;
private List<MediaDevice> mMediaDevices = new ArrayList<>();
private PhoneMediaDevice mPhoneMediaDevice;
+ private MediaRouter2Manager mMediaRouter2Manager;
@Before
public void setUp() {
@@ -134,9 +136,13 @@ public class MediaDeviceTest {
mBluetoothMediaDevice1 = new BluetoothMediaDevice(mContext, mCachedDevice1);
mBluetoothMediaDevice2 = new BluetoothMediaDevice(mContext, mCachedDevice2);
mBluetoothMediaDevice3 = new BluetoothMediaDevice(mContext, mCachedDevice3);
- mInfoMediaDevice1 = new InfoMediaDevice(mContext, mRouteInfo1);
- mInfoMediaDevice2 = new InfoMediaDevice(mContext, mRouteInfo2);
- mInfoMediaDevice3 = new InfoMediaDevice(mContext, mRouteInfo3);
+ mMediaRouter2Manager = MediaRouter2Manager.getInstance(mContext);
+ mInfoMediaDevice1 = new InfoMediaDevice(mContext, mMediaRouter2Manager, mRouteInfo1,
+ TEST_PACKAGE_NAME);
+ mInfoMediaDevice2 = new InfoMediaDevice(mContext, mMediaRouter2Manager, mRouteInfo2,
+ TEST_PACKAGE_NAME);
+ mInfoMediaDevice3 = new InfoMediaDevice(mContext, mMediaRouter2Manager, mRouteInfo3,
+ TEST_PACKAGE_NAME);
mPhoneMediaDevice = new PhoneMediaDevice(mContext, mLocalBluetoothManager);
}
@@ -364,5 +370,4 @@ public class MediaDeviceTest {
assertThat(mMediaDevices.get(5)).isEqualTo(mBluetoothMediaDevice1);
assertThat(mMediaDevices.get(6)).isEqualTo(mBluetoothMediaDevice2);
}
-
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceUtilsTest.java
index 1e5545f8539f..30a6ad2576db 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceUtilsTest.java
@@ -21,8 +21,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when;
import android.bluetooth.BluetoothDevice;
-
-import androidx.mediarouter.media.MediaRouter;
+import android.media.MediaRoute2Info;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
@@ -44,7 +43,7 @@ public class MediaDeviceUtilsTest {
@Mock
private BluetoothDevice mBluetoothDevice;
@Mock
- private MediaRouter.RouteInfo mRouteInfo;
+ private MediaRoute2Info mRouteInfo;
@Before
public void setUp() {
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageUtilsTest.java
index 5cae6116a59c..d98f50beadf5 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageUtilsTest.java
@@ -87,7 +87,7 @@ public class DataUsageUtilsTest {
public void getMobileTemplate_groupUuidNull_returnMobileAll() {
when(mSubscriptionManager.getActiveSubscriptionInfo(SUB_ID)).thenReturn(mInfo1);
when(mInfo1.getGroupUuid()).thenReturn(null);
- when(mTelephonyManager.getMergedSubscriberIdsFromGroup())
+ when(mTelephonyManager.getMergedImsisFromGroup())
.thenReturn(new String[] {SUBSCRIBER_ID});
final NetworkTemplate networkTemplate = DataUsageUtils.getMobileTemplate(mContext, SUB_ID);
@@ -99,7 +99,7 @@ public class DataUsageUtilsTest {
public void getMobileTemplate_groupUuidExist_returnMobileMerged() {
when(mSubscriptionManager.getActiveSubscriptionInfo(SUB_ID)).thenReturn(mInfo1);
when(mInfo1.getGroupUuid()).thenReturn(mParcelUuid);
- when(mTelephonyManager.getMergedSubscriberIdsFromGroup())
+ when(mTelephonyManager.getMergedImsisFromGroup())
.thenReturn(new String[] {SUBSCRIBER_ID, SUBSCRIBER_ID_2});
final NetworkTemplate networkTemplate = DataUsageUtils.getMobileTemplate(mContext, SUB_ID);
diff --git a/packages/SettingsProvider/res/values/blocked_settings.xml b/packages/SettingsProvider/res/values/blocked_settings.xml
new file mode 100644
index 000000000000..b54b74ee1d3e
--- /dev/null
+++ b/packages/SettingsProvider/res/values/blocked_settings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<!-- These are arrays of settings which should not be restored to this device -->
+<resources>
+ <string-array name="restore_blocked_device_specific_settings" />
+ <string-array name="restore_blocked_global_settings" />
+ <string-array name="restore_blocked_secure_settings" />
+ <string-array name="restore_blocked_system_settings" />
+</resources> \ No newline at end of file
diff --git a/packages/SettingsProvider/res/values/overlayable.xml b/packages/SettingsProvider/res/values/overlayable.xml
new file mode 100644
index 000000000000..dc41a77d0e2d
--- /dev/null
+++ b/packages/SettingsProvider/res/values/overlayable.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+ <overlayable name="SettingsToNotRestore">
+ <policy type="product|system|vendor">
+ <item type="array" name="restore_blocked_device_specific_settings" />
+ <item type="array" name="restore_blocked_global_settings" />
+ <item type="array" name="restore_blocked_secure_settings" />
+ <item type="array" name="restore_blocked_system_settings" />
+ </policy>
+ </overlayable>
+</resources>
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
index 22d843b1dc90..049b9f0e903e 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
@@ -159,5 +159,6 @@ public class SecureSettings {
Settings.Secure.AWARE_TAP_PAUSE_GESTURE_COUNT,
Settings.Secure.AWARE_TAP_PAUSE_TOUCH_COUNT,
Settings.Secure.PEOPLE_STRIP,
+ Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE,
};
}
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index 4b10557e34d9..ed06fa71cff1 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -239,5 +239,9 @@ public class SecureSettingsValidators {
VALIDATORS.put(Secure.DISPLAY_DENSITY_FORCED, NON_NEGATIVE_INTEGER_VALIDATOR);
VALIDATORS.put(Secure.TAP_GESTURE, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.PEOPLE_STRIP, BOOLEAN_VALIDATOR);
+ VALIDATORS.put(Secure.ACCESSIBILITY_MAGNIFICATION_MODE,
+ new InclusiveIntegerRangeValidator(
+ Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN,
+ Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW));
}
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index c19a340498e7..fb558abe3865 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -66,6 +66,7 @@ import java.io.IOException;
import java.io.OutputStream;
import java.time.DateTimeException;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
@@ -250,7 +251,13 @@ public class SettingsBackupAgent extends BackupAgentHelper {
@Override
public void onRestore(BackupDataInput data, int appVersionCode,
- ParcelFileDescriptor newState) throws IOException {
+ ParcelFileDescriptor newState) {
+ throw new RuntimeException("SettingsBackupAgent has been migrated to use key exclusion");
+ }
+
+ @Override
+ public void onRestore(BackupDataInput data, long appVersionCode,
+ ParcelFileDescriptor newState, Set<String> dynamicBlockList) throws IOException {
if (DEBUG) {
Log.d(TAG, "onRestore(): appVersionCode: " + appVersionCode
@@ -266,7 +273,7 @@ public class SettingsBackupAgent extends BackupAgentHelper {
}
// versionCode of com.android.providers.settings corresponds to SDK_INT
- mRestoredFromSdkInt = appVersionCode;
+ mRestoredFromSdkInt = (int) appVersionCode;
HashSet<String> movedToGlobal = new HashSet<String>();
Settings.System.getMovedToGlobalSettings(movedToGlobal);
@@ -292,16 +299,29 @@ public class SettingsBackupAgent extends BackupAgentHelper {
switch (key) {
case KEY_SYSTEM :
restoreSettings(data, Settings.System.CONTENT_URI, movedToGlobal,
- movedToSecure);
+ movedToSecure, R.array.restore_blocked_system_settings,
+ dynamicBlockList);
mSettingsHelper.applyAudioSettings();
break;
case KEY_SECURE :
- restoreSettings(data, Settings.Secure.CONTENT_URI, movedToGlobal, null);
+ restoreSettings(
+ data,
+ Settings.Secure.CONTENT_URI,
+ movedToGlobal,
+ null,
+ R.array.restore_blocked_secure_settings,
+ dynamicBlockList);
break;
case KEY_GLOBAL :
- restoreSettings(data, Settings.Global.CONTENT_URI, null, movedToSecure);
+ restoreSettings(
+ data,
+ Settings.Global.CONTENT_URI,
+ null,
+ movedToSecure,
+ R.array.restore_blocked_global_settings,
+ dynamicBlockList);
break;
case KEY_WIFI_SUPPLICANT :
@@ -345,7 +365,10 @@ public class SettingsBackupAgent extends BackupAgentHelper {
case KEY_DEVICE_SPECIFIC_CONFIG:
byte[] restoredDeviceSpecificConfig = new byte[size];
data.readEntityData(restoredDeviceSpecificConfig, 0, size);
- restoreDeviceSpecificConfig(restoredDeviceSpecificConfig);
+ restoreDeviceSpecificConfig(
+ restoredDeviceSpecificConfig,
+ R.array.restore_blocked_device_specific_settings,
+ dynamicBlockList);
break;
default :
@@ -394,14 +417,22 @@ public class SettingsBackupAgent extends BackupAgentHelper {
byte[] buffer = new byte[nBytes];
in.readFully(buffer, 0, nBytes);
restoreSettings(buffer, nBytes, Settings.System.CONTENT_URI, movedToGlobal,
- movedToSecure);
+ movedToSecure, R.array.restore_blocked_system_settings,
+ Collections.emptySet());
// secure settings
nBytes = in.readInt();
if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of secure settings data");
if (nBytes > buffer.length) buffer = new byte[nBytes];
in.readFully(buffer, 0, nBytes);
- restoreSettings(buffer, nBytes, Settings.Secure.CONTENT_URI, movedToGlobal, null);
+ restoreSettings(
+ buffer,
+ nBytes,
+ Settings.Secure.CONTENT_URI,
+ movedToGlobal,
+ null,
+ R.array.restore_blocked_secure_settings,
+ Collections.emptySet());
// Global only if sufficiently new
if (version >= FULL_BACKUP_ADDED_GLOBAL) {
@@ -411,7 +442,8 @@ public class SettingsBackupAgent extends BackupAgentHelper {
in.readFully(buffer, 0, nBytes);
movedToGlobal.clear(); // no redirection; this *is* the global namespace
restoreSettings(buffer, nBytes, Settings.Global.CONTENT_URI, movedToGlobal,
- movedToSecure);
+ movedToSecure, R.array.restore_blocked_global_settings,
+ Collections.emptySet());
}
// locale
@@ -612,8 +644,13 @@ public class SettingsBackupAgent extends BackupAgentHelper {
return baos.toByteArray();
}
- private void restoreSettings(BackupDataInput data, Uri contentUri,
- HashSet<String> movedToGlobal, Set<String> movedToSecure) {
+ private void restoreSettings(
+ BackupDataInput data,
+ Uri contentUri,
+ HashSet<String> movedToGlobal,
+ Set<String> movedToSecure,
+ int blockedSettingsArrayId,
+ Set<String> dynamicBlockList) {
byte[] settings = new byte[data.getDataSize()];
try {
data.readEntityData(settings, 0, settings.length);
@@ -621,16 +658,44 @@ public class SettingsBackupAgent extends BackupAgentHelper {
Log.e(TAG, "Couldn't read entity data");
return;
}
- restoreSettings(settings, settings.length, contentUri, movedToGlobal, movedToSecure);
+ restoreSettings(
+ settings,
+ settings.length,
+ contentUri,
+ movedToGlobal,
+ movedToSecure,
+ blockedSettingsArrayId,
+ dynamicBlockList);
}
- private void restoreSettings(byte[] settings, int bytes, Uri contentUri,
- HashSet<String> movedToGlobal, Set<String> movedToSecure) {
- restoreSettings(settings, 0, bytes, contentUri, movedToGlobal, movedToSecure);
+ private void restoreSettings(
+ byte[] settings,
+ int bytes,
+ Uri contentUri,
+ HashSet<String> movedToGlobal,
+ Set<String> movedToSecure,
+ int blockedSettingsArrayId,
+ Set<String> dynamicBlockList) {
+ restoreSettings(
+ settings,
+ 0,
+ bytes,
+ contentUri,
+ movedToGlobal,
+ movedToSecure,
+ blockedSettingsArrayId,
+ dynamicBlockList);
}
- private void restoreSettings(byte[] settings, int pos, int bytes, Uri contentUri,
- HashSet<String> movedToGlobal, Set<String> movedToSecure) {
+ private void restoreSettings(
+ byte[] settings,
+ int pos,
+ int bytes,
+ Uri contentUri,
+ HashSet<String> movedToGlobal,
+ Set<String> movedToSecure,
+ int blockedSettingsArrayId,
+ Set<String> dynamicBlockList) {
if (DEBUG) {
Log.i(TAG, "restoreSettings: " + contentUri);
}
@@ -662,9 +727,20 @@ public class SettingsBackupAgent extends BackupAgentHelper {
SettingsHelper settingsHelper = mSettingsHelper;
ContentResolver cr = getContentResolver();
- final int whiteListSize = whitelist.length;
- for (int i = 0; i < whiteListSize; i++) {
- String key = whitelist[i];
+ Set<String> blockedSettings = getBlockedSettings(blockedSettingsArrayId);
+
+ for (String key : whitelist) {
+ boolean isBlockedBySystem = blockedSettings != null && blockedSettings.contains(key);
+ if (isBlockedBySystem || isBlockedByDynamicList(dynamicBlockList, contentUri, key)) {
+ Log.i(
+ TAG,
+ "Key "
+ + key
+ + " removed from restore by "
+ + (isBlockedBySystem ? "system" : "dynamic")
+ + " block list");
+ continue;
+ }
String value = null;
boolean hasValueToRestore = false;
@@ -722,6 +798,19 @@ public class SettingsBackupAgent extends BackupAgentHelper {
}
}
+ private boolean isBlockedByDynamicList(Set<String> dynamicBlockList, Uri areaUri, String key) {
+ String contentKey = Uri.withAppendedPath(areaUri, key).toString();
+ return dynamicBlockList.contains(contentKey);
+ }
+
+ // There may be other sources of blocked settings, so I'm separating out this
+ // code to make it easy to modify in the future.
+ @VisibleForTesting
+ protected Set<String> getBlockedSettings(int blockedSettingsArrayId) {
+ String[] blockedSettings = getResources().getStringArray(blockedSettingsArrayId);
+ return new HashSet<>(Arrays.asList(blockedSettings));
+ }
+
private boolean isValidSettingValue(String key, String value,
Map<String, Validator> validators) {
if (key == null || validators == null) {
@@ -998,10 +1087,13 @@ public class SettingsBackupAgent extends BackupAgentHelper {
* Restore the device specific settings.
*
* @param data The byte array holding a backed up version of another devices settings.
+ * @param blockedSettingsArrayId The string array resource holding the settings not to restore.
+ * @param dynamicBlocklist The dynamic list of settings not to restore fed into this agent.
* @return true if the restore succeeded, false if it was stopped.
*/
@VisibleForTesting
- boolean restoreDeviceSpecificConfig(byte[] data) {
+ boolean restoreDeviceSpecificConfig(byte[] data, int blockedSettingsArrayId,
+ Set<String> dynamicBlocklist) {
// We're using an AtomicInteger to wrap the position int and allow called methods to
// modify it.
AtomicInteger pos = new AtomicInteger(0);
@@ -1013,7 +1105,14 @@ public class SettingsBackupAgent extends BackupAgentHelper {
int dataStart = pos.get();
restoreSettings(
- data, dataStart, data.length, Settings.Secure.CONTENT_URI, null, null);
+ data,
+ dataStart,
+ data.length,
+ Settings.Secure.CONTENT_URI,
+ null,
+ null,
+ blockedSettingsArrayId,
+ dynamicBlocklist);
updateWindowManagerIfNeeded(originalDensity);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 016896f52a75..0e3f81b81e02 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1820,6 +1820,9 @@ class SettingsProtoDumpUtil {
dumpSetting(s, p,
Settings.Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS,
SecureSettingsProto.Accessibility.INTERACTIVE_UI_TIMEOUT_MS);
+ dumpSetting(s, p,
+ Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE,
+ SecureSettingsProto.Accessibility.ACCESSIBILITY_MAGNIFICATION_MODE);
p.end(accessibilityToken);
dumpSetting(s, p,
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 19ff2444e6ca..443811faf164 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -87,6 +87,7 @@ public class SettingsBackupTest {
Settings.System.VOLUME_ACCESSIBILITY, // used internally, changing value will
// not change volume
Settings.System.VOLUME_ALARM, // deprecated since API 2?
+ Settings.System.VOLUME_ASSISTANT, // candidate for backup?
Settings.System.VOLUME_BLUETOOTH_SCO, // deprecated since API 2?
Settings.System.VOLUME_MASTER, // candidate for backup?
Settings.System.VOLUME_MUSIC, // deprecated since API 2?
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsBackupAgentTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsBackupAgentTest.java
index 57e22db6a55c..e6508823c7e3 100644
--- a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsBackupAgentTest.java
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsBackupAgentTest.java
@@ -37,14 +37,14 @@ import android.test.mock.MockContentResolver;
import androidx.test.runner.AndroidJUnit4;
-import com.android.internal.annotations.VisibleForTesting;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@@ -85,12 +85,33 @@ public class SettingsBackupAgentTest extends BaseSettingsProviderTest {
assertEquals("Not all values backed up.", TEST_VALUES.keySet(), helper.mReadEntries);
- mAgentUnderTest.restoreDeviceSpecificConfig(settingsBackup);
+ mAgentUnderTest.restoreDeviceSpecificConfig(
+ settingsBackup,
+ R.array.restore_blocked_device_specific_settings,
+ Collections.emptySet());
assertEquals("Not all values were restored.", TEST_VALUES, helper.mWrittenValues);
}
@Test
+ public void testRoundTripDeviceSpecificSettingsWithBlock() throws IOException {
+ TestSettingsHelper helper = new TestSettingsHelper(mContext);
+ mAgentUnderTest.mSettingsHelper = helper;
+
+ byte[] settingsBackup = mAgentUnderTest.getDeviceSpecificConfiguration();
+
+ assertEquals("Not all values backed up.", TEST_VALUES.keySet(), helper.mReadEntries);
+ mAgentUnderTest.setBlockedSettings(TEST_VALUES.keySet().toArray(new String[0]));
+
+ mAgentUnderTest.restoreDeviceSpecificConfig(
+ settingsBackup,
+ R.array.restore_blocked_device_specific_settings,
+ Collections.emptySet());
+
+ assertTrue("Not all values were blocked.", helper.mWrittenValues.isEmpty());
+ }
+
+ @Test
public void testGeneratedHeaderMatchesCurrentDevice() throws IOException {
mAgentUnderTest.mSettingsHelper = new TestSettingsHelper(mContext);
@@ -148,7 +169,10 @@ public class SettingsBackupAgentTest extends BaseSettingsProviderTest {
assertFalse(
"Blocking isSourceAcceptable did not stop restore",
- mAgentUnderTest.restoreDeviceSpecificConfig(data));
+ mAgentUnderTest.restoreDeviceSpecificConfig(
+ data,
+ R.array.restore_blocked_device_specific_settings,
+ Collections.emptySet()));
}
private byte[] generateUncorruptedHeader() throws IOException {
@@ -184,14 +208,34 @@ public class SettingsBackupAgentTest extends BaseSettingsProviderTest {
}
}
+ private byte[] generateSingleKeyTestBackupData(String key, String value) throws IOException {
+ try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
+ os.write(SettingsBackupAgent.toByteArray(key));
+ os.write(SettingsBackupAgent.toByteArray(value));
+ return os.toByteArray();
+ }
+ }
+
private static class TestFriendlySettingsBackupAgent extends SettingsBackupAgent {
private Boolean mForcedDeviceInfoRestoreAcceptability = null;
+ private String[] mBlockedSettings = null;
void setForcedDeviceInfoRestoreAcceptability(boolean value) {
mForcedDeviceInfoRestoreAcceptability = value;
}
- @VisibleForTesting
+ void setBlockedSettings(String... blockedSettings) {
+ mBlockedSettings = blockedSettings;
+ }
+
+ @Override
+ protected Set<String> getBlockedSettings(int blockedSettingsArrayId) {
+ return mBlockedSettings == null
+ ? super.getBlockedSettings(blockedSettingsArrayId)
+ : new HashSet<>(Arrays.asList(mBlockedSettings));
+ }
+
+ @Override
boolean isSourceAcceptable(byte[] data, AtomicInteger pos) {
return mForcedDeviceInfoRestoreAcceptability == null
? super.isSourceAcceptable(data, pos)
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 51bf441fe119..aefdce48d989 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -227,6 +227,9 @@
<!-- Permission required for CTS test - TetheringManagerTest -->
<uses-permission android:name="android.permission.TETHER_PRIVILEGED"/>
+ <!-- Permission required for CTS test - CtsOsTestCases -->
+ <uses-permission android:name="android.permission.MANAGE_CRATES"/>
+
<application android:label="@string/app_label"
android:theme="@android:style/Theme.DeviceDefault.DayNight"
android:defaultToDeviceProtectedStorage="true"
diff --git a/packages/Shell/res/values-uk/strings.xml b/packages/Shell/res/values-uk/strings.xml
index 28f3aecca17b..f62d117a248b 100644
--- a/packages/Shell/res/values-uk/strings.xml
+++ b/packages/Shell/res/values-uk/strings.xml
@@ -18,27 +18,27 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Оболонка"</string>
<string name="bugreport_notification_channel" msgid="2574150205913861141">"Звіти про помилки"</string>
- <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Генерується повідомлення про помилку <xliff:g id="ID">#%d</xliff:g>"</string>
- <string name="bugreport_finished_title" msgid="4429132808670114081">"Повідомлення про помилку <xliff:g id="ID">#%d</xliff:g> створено"</string>
- <string name="bugreport_updating_title" msgid="4423539949559634214">"Додаються деталі до повідомлення про помилку"</string>
+ <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Створюється звіт про помилку <xliff:g id="ID">#%d</xliff:g>"</string>
+ <string name="bugreport_finished_title" msgid="4429132808670114081">"Звіт про помилку <xliff:g id="ID">#%d</xliff:g> створено"</string>
+ <string name="bugreport_updating_title" msgid="4423539949559634214">"У звіт про помилку додаються деталі"</string>
<string name="bugreport_updating_wait" msgid="3322151947853929470">"Зачекайте…"</string>
<string name="bugreport_finished_text" product="watch" msgid="1223616207145252689">"Звіт про помилку невдовзі з’явиться на телефоні"</string>
- <string name="bugreport_finished_text" product="tv" msgid="5758325479058638893">"Виберіть, щоб надіслати повідомлення про помилку"</string>
- <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Торкніться, щоб надіслати повідомлення про помилку"</string>
+ <string name="bugreport_finished_text" product="tv" msgid="5758325479058638893">"Виберіть, щоб надіслати звіт про помилку"</string>
+ <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Торкніться, щоб надіслати звіт про помилку"</string>
<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_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_dont_repeat" msgid="6179945398364357318">"Більше не показувати"</string>
<string name="bugreport_storage_title" msgid="5332488144740527109">"Звіти про помилки"</string>
- <string name="bugreport_unreadable_text" msgid="586517851044535486">"Не вдалося прочитати звіт про помилки"</string>
- <string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"Не вдалося додати деталі повідомлення про помилку у файл .zip"</string>
+ <string name="bugreport_unreadable_text" msgid="586517851044535486">"Не вдалося прочитати звіт про помилку"</string>
+ <string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"Не вдалося додати деталі звіту про помилку у файл .zip"</string>
<string name="bugreport_unnamed" msgid="2800582406842092709">"без назви"</string>
<string name="bugreport_info_action" msgid="2158204228510576227">"Деталі"</string>
<string name="bugreport_screenshot_action" msgid="8677781721940614995">"Знімок екрана"</string>
<string name="bugreport_screenshot_taken" msgid="5684211273096253120">"Знімок екрана зроблено."</string>
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Не вдалося зробити знімок екрана."</string>
- <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Деталі повідомлення про помилку <xliff:g id="ID">#%d</xliff:g>"</string>
+ <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Деталі звіту про помилку <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Назва файлу"</string>
<string name="bugreport_info_title" msgid="2306030793918239804">"Назва помилки"</string>
<string name="bugreport_info_description" msgid="5072835127481627722">"Опис помилки"</string>
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index 404e791291d8..c238d7d49f9b 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -42,6 +42,7 @@ android_library {
"res",
],
static_libs: [
+ "WindowManager-Shell",
"SystemUIPluginLib",
"SystemUISharedLib",
"SettingsLib",
@@ -80,7 +81,7 @@ android_library {
filegroup {
name: "SystemUI-tests-utils",
srcs: [
- "tests/src/com/android/systemui/statusbar/NotificationEntryBuilder.java",
+ "tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryBuilder.java",
"tests/src/com/android/systemui/statusbar/RankingBuilder.java",
"tests/src/com/android/systemui/statusbar/SbnBuilder.java",
],
@@ -154,7 +155,7 @@ android_app {
resource_dirs: [],
platform_apis: true,
- product_specific: true,
+ system_ext_specific: true,
certificate: "platform",
privileged: true,
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index a8318d6a6717..2a1e74e18fb7 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -174,6 +174,9 @@
<!-- Adding Quick Settings tiles -->
<uses-permission android:name="android.permission.BIND_QUICK_SETTINGS_TILE" />
+ <!-- Adding Controls to SystemUI -->
+ <uses-permission android:name="android.permission.BIND_CONTROLS" />
+
<!-- Quick Settings tile: Night Mode / Dark Theme -->
<uses-permission android:name="android.permission.MODIFY_DAY_NIGHT_MODE" />
diff --git a/packages/Tethering/CleanSpec.mk b/packages/SystemUI/CleanSpec.mk
index 70db351a6928..2a2e4e44e834 100644
--- a/packages/Tethering/CleanSpec.mk
+++ b/packages/SystemUI/CleanSpec.mk
@@ -43,10 +43,8 @@
#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
-
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/priv-app/Tethering)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/priv-app/InProcessTethering)
-
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/product/priv-app/SystemUI)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/product/priv-app/SystemUI)
# ******************************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
# ******************************************************************
diff --git a/packages/SystemUI/res-keyguard/values-af/strings.xml b/packages/SystemUI/res-keyguard/values-af/strings.xml
index b7f29a17b1ba..92dd9fd96111 100644
--- a/packages/SystemUI/res-keyguard/values-af/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-af/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Jy het jou PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> keer verkeerd ingetik. \n\nProbeer weer oor <xliff:g id="NUMBER_1">%2$d</xliff:g> sekondes."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Jy het jou wagwoord <xliff:g id="NUMBER_0">%1$d</xliff:g> keer verkeerd ingetik. \n\nProbeer weer oor <xliff:g id="NUMBER_1">%2$d</xliff:g> sekondes."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Jy het jou ontsluitpatroon <xliff:g id="NUMBER_0">%1$d</xliff:g> keer verkeerd geteken. \n\nProbeer weer oor <xliff:g id="NUMBER_1">%2$d</xliff:g> sekondes."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Verkeerde SIM-PIN-kode. Jy sal nou jou diensverskaffer moet kontak om jou toestel te ontsluit."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">Verkeerde SIM-PIN-kode. Jy het <xliff:g id="NUMBER_1">%d</xliff:g> pogings oor.</item>
diff --git a/packages/SystemUI/res-keyguard/values-am/strings.xml b/packages/SystemUI/res-keyguard/values-am/strings.xml
index c94ba8bf22e8..f94c20f9ad01 100644
--- a/packages/SystemUI/res-keyguard/values-am/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-am/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"ፒንዎን <xliff:g id="NUMBER_0">%1$d</xliff:g> ጊዜ በትክክል አልተየቡም። \n\nበ<xliff:g id="NUMBER_1">%2$d</xliff:g> ሰኮንዶች ውስጥ እንደገና ይሞክሩ።"</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"የይለፍ ቃልዎን <xliff:g id="NUMBER_0">%1$d</xliff:g> ጊዜ ትክክል ባልሆነ መንገድ ተይበዋል።\n\nበ<xliff:g id="NUMBER_1">%2$d</xliff:g> ሰኮንዶች ውስጥ እንደገና ይሞክሩ።"</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"የመክፈቻ ስርዓተ ጥለቱን <xliff:g id="NUMBER_0">%1$d</xliff:g> ጊዜ ትክክል ባልሆነ መንገድ ስለውታል።\n\nበ<xliff:g id="NUMBER_1">%2$d</xliff:g> ሰኮንዶች ውስጥ እንደገና ይሞክሩ።"</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"ልክ ያልሆነ የሲም ፒን ኮድ። አሁን መሣሪያዎን ለማስከፈት አገልግሎት አቅራቢዎን ማነጋገር አለብዎት።"</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="one">ልክ ያልሆነ የሲም ፒን ኮድ፣ <xliff:g id="NUMBER_1">%d</xliff:g> ሙከራዎች ይቀረዎታል።</item>
diff --git a/packages/SystemUI/res-keyguard/values-ar/strings.xml b/packages/SystemUI/res-keyguard/values-ar/strings.xml
index fe10afa48b4f..efe4088a06f9 100644
--- a/packages/SystemUI/res-keyguard/values-ar/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ar/strings.xml
@@ -89,14 +89,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"لقد كتبت رقم التعريف الشخصي بشكل غير صحيح <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. \n\nأعد المحاولة خلال <xliff:g id="NUMBER_1">%2$d</xliff:g> ثانية."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"لقد كتبت كلمة المرور بشكل غير صحيح <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. \n\nأعد المحاولة خلال <xliff:g id="NUMBER_1">%2$d</xliff:g> ثانية."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"لقد رسمت نقش فتح القفل بطريقة غير صحيحة <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. \n\nأعد المحاولة خلال <xliff:g id="NUMBER_1">%2$d</xliff:g> ثانية."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"‏رمز \"رقم التعريف الشخصي\" لشريحة SIM غير صحيح، ويلزمك الاتصال الآن بمشغّل شبكة الجوّال لإلغاء قفل الجهاز."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="zero">‏رمز رقم التعريف الشخصي لشريحة SIM غير صحيح، ولم تتبق لديك أي محاولات (<xliff:g id="NUMBER_1">%d</xliff:g>).</item>
diff --git a/packages/SystemUI/res-keyguard/values-as/strings.xml b/packages/SystemUI/res-keyguard/values-as/strings.xml
index f814c3a0e979..3b51e480b7dd 100644
--- a/packages/SystemUI/res-keyguard/values-as/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-as/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"আপুনি আপোনাৰ পিন <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুলকৈ লিখিছে। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g>ছেকেণ্ডৰ পিছত আকৌ চেষ্টা কৰক।"</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"আপুনি আপোনাৰ পাছৱৰ্ড <xliff:g id="NUMBER_0">%1$d</xliff:g>বাৰ ভুলকৈ লিখিছে। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ছেকেণ্ডৰ পাছত আকৌ চেষ্টা কৰক।"</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"আপুনি আপোনাৰ আনলক আৰ্হি <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুলকৈ আঁকিছে। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g>ছেকেণ্ডৰ পিছত আকৌ চেষ্টা কৰক।"</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"ছিমৰ ভুল পিন ক\'ড, আপোনাৰ ডিভাইচটো আনলক কৰিবলৈ আপুনি এতিয়া আপোনাৰ বাহকৰ সৈতে যোগাযোগ কৰিবই লাগিব।"</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="one">ছিমৰ ভুল পিন ক’ড, আপুনি আৰু <xliff:g id="NUMBER_1">%d</xliff:g> বাৰ প্ৰয়াস কৰিব পাৰিব।</item>
diff --git a/packages/SystemUI/res-keyguard/values-az/strings.xml b/packages/SystemUI/res-keyguard/values-az/strings.xml
index e04f3054d0dd..d63c23f4d1f6 100644
--- a/packages/SystemUI/res-keyguard/values-az/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-az/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"PIN kodu <xliff:g id="NUMBER_0">%1$d</xliff:g> dəfə yanlış daxil etdiniz. \n \n<xliff:g id="NUMBER_1">%2$d</xliff:g> saniyə sonra yenidən cəhd edin."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Parolu <xliff:g id="NUMBER_0">%1$d</xliff:g> dəfə yanlış daxil etdiniz. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> saniyə sonra yenidən cəhd edin."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Kilid modelini <xliff:g id="NUMBER_0">%1$d</xliff:g> dəfə yanlış çəkdiniz. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> saniyə sonra yenidən cəhd edin."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Yanlış SIM PIN kodu  cihazın açılması üçün operatorla indi əlaqə saxlamalısınız."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">Yanlış SIM PIN kodu, <xliff:g id="NUMBER_1">%d</xliff:g> cəhdiniz qalır.</item>
diff --git a/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml b/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml
index 82dca6b95afe..e206958d1e95 100644
--- a/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml
@@ -86,14 +86,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Uneli ste pogrešan PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nProbajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> sek."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Uneli ste pogrešnu lozinku <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nProbajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> sek."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Nacrtali ste netačan šablon za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nProbajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> sek."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Netačan PIN kôd za SIM. Sada morate da kontaktirate mobilnog operatera da biste otključali uređaj."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="one">Netačan PIN kôd za SIM. Imate još <xliff:g id="NUMBER_1">%d</xliff:g> pokušaj.</item>
diff --git a/packages/SystemUI/res-keyguard/values-be/strings.xml b/packages/SystemUI/res-keyguard/values-be/strings.xml
index d9a450846f0b..569e705fbcc2 100644
--- a/packages/SystemUI/res-keyguard/values-be/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-be/strings.xml
@@ -87,14 +87,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Вы няправільна ўвялі PIN-код столькі разоў: <xliff:g id="NUMBER_0">%1$d</xliff:g>. \n\nПаўтарыце спробу праз <xliff:g id="NUMBER_1">%2$d</xliff:g> с."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Вы няправільна ўвялі пароль столькі разоў: <xliff:g id="NUMBER_0">%1$d</xliff:g>. \n\nПаўтарыце спробу праз <xliff:g id="NUMBER_1">%2$d</xliff:g> с."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Вы няправільна ўвялі ўзор разблакіроўкі столькі разоў: <xliff:g id="NUMBER_0">%1$d</xliff:g>. \n\nПаўтарыце спробу праз <xliff:g id="NUMBER_1">%2$d</xliff:g> с."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Няправільны PIN-код SIM-карты, цяпер вы павінны звязацца з аператарам для разблакіроўкі прылады."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="one">Няправільны PIN-код SIM-карты, у вас засталася <xliff:g id="NUMBER_1">%d</xliff:g> спроба.</item>
diff --git a/packages/SystemUI/res-keyguard/values-bg/strings.xml b/packages/SystemUI/res-keyguard/values-bg/strings.xml
index 3b68a42a5ce7..d015be320e20 100644
--- a/packages/SystemUI/res-keyguard/values-bg/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-bg/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Въведохте неправилно ПИН кода си <xliff:g id="NUMBER_0">%1$d</xliff:g> пъти. \n\nОпитайте отново след <xliff:g id="NUMBER_1">%2$d</xliff:g> секунди."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Въведохте неправилно паролата си <xliff:g id="NUMBER_0">%1$d</xliff:g> пъти. \n\nОпитайте отново след <xliff:g id="NUMBER_1">%2$d</xliff:g> секунди."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Начертахте неправилно фигурата си за отключване <xliff:g id="NUMBER_0">%1$d</xliff:g> пъти. \n\nОпитайте отново след <xliff:g id="NUMBER_1">%2$d</xliff:g> секунди."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Неправилен ПИН код за SIM картата – сега трябва да се свържете с оператора си, за да отключите устройството."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">Неправилен ПИН код за SIM картата – остават ви <xliff:g id="NUMBER_1">%d</xliff:g> опита.</item>
diff --git a/packages/SystemUI/res-keyguard/values-bn/strings.xml b/packages/SystemUI/res-keyguard/values-bn/strings.xml
index 7d0d4b926277..8eae6e6e2e18 100644
--- a/packages/SystemUI/res-keyguard/values-bn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-bn/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"আপনি আপনার পিন টাইপ করতে <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুল করেছেন৷ \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> সেকেন্ডের মধ্যে আবার চেষ্টা করুন৷"</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুলভাবে আপনার পাসওয়ার্ড লিখেছেন।\n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> সেকেন্ডের মধ্যে আবার চেষ্টা করুন।"</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুলভাবে আপনার আনলকের প্যাটার্ন এঁকেছেন।\n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> সেকেন্ডের মধ্যে আবার চেষ্টা করুন।"</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"ভুল সিম পিন কোড দিয়েছেন, আপনার ডিভাইসটি আনলক করতে এখন আপনাকে অবশ্যই আপনার পরিষেবা প্রদানকারীর সাথে যোগাযোগ করতে হবে।"</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="one">সিমের পিন কোডটি ভুল, আপনি আর <xliff:g id="NUMBER_1">%d</xliff:g> বার চেষ্টা করতে পারেন।</item>
diff --git a/packages/SystemUI/res-keyguard/values-bs/strings.xml b/packages/SystemUI/res-keyguard/values-bs/strings.xml
index 99140ce543ea..286b08be1c5e 100644
--- a/packages/SystemUI/res-keyguard/values-bs/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-bs/strings.xml
@@ -86,14 +86,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Pogrešno ste unijeli PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nPokušajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Pogrešno ste unijeli lozinku <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nPokušajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Pogrešno ste nacrtali svoj uzorak za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nPokušajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"PIN za SIM karticu je netačan. Za otključavanje uređaja sada se morate obratiti svom operateru."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="one">PIN za SIM karticu je netačan. Imate još <xliff:g id="NUMBER_1">%d</xliff:g> pokušaj.</item>
diff --git a/packages/SystemUI/res-keyguard/values-ca/strings.xml b/packages/SystemUI/res-keyguard/values-ca/strings.xml
index 7bb3677e3316..cb7fa37b281d 100644
--- a/packages/SystemUI/res-keyguard/values-ca/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ca/strings.xml
@@ -53,7 +53,7 @@
<string name="keyguard_accessibility_password" msgid="3524161948484801450">"Contrasenya del dispositiu"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"Zona del PIN de la SIM"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"Zona del PUK de la SIM"</string>
- <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"S\'ha definit la pròxima alarma per a l\'hora següent: <xliff:g id="ALARM">%1$s</xliff:g>"</string>
+ <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"S\'ha configurat la propera alarma (<xliff:g id="ALARM">%1$s</xliff:g>)"</string>
<string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Suprimeix"</string>
<string name="disable_carrier_button_text" msgid="7153361131709275746">"Desactiva l\'eSIM"</string>
<string name="error_disable_esim_title" msgid="3802652622784813119">"No es pot desactivar l\'eSIM"</string>
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Has escrit el PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. \n\nTorna-ho a provar d\'aquí a <xliff:g id="NUMBER_1">%2$d</xliff:g> segons."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Has escrit la contrasenya <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. \n\nTorna-ho a provar d\'aquí a <xliff:g id="NUMBER_1">%2$d</xliff:g> segons."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Has dibuixat el patró de desbloqueig <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. \n\nTorna-ho a provar d\'aquí a <xliff:g id="NUMBER_1">%2$d</xliff:g> segons."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"El codi PIN de la SIM no és correcte. Contacta amb l\'operador de telefonia mòbil per desbloquejar el dispositiu."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">El codi PIN de la SIM no és correcte. Et queden <xliff:g id="NUMBER_1">%d</xliff:g> intents.</item>
diff --git a/packages/SystemUI/res-keyguard/values-cs/strings.xml b/packages/SystemUI/res-keyguard/values-cs/strings.xml
index 7e430d6d9d3d..4f0c0ffa4962 100644
--- a/packages/SystemUI/res-keyguard/values-cs/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-cs/strings.xml
@@ -87,14 +87,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Již <xliff:g id="NUMBER_0">%1$d</xliff:g>krát jste zadali nesprávný kód PIN. \n\nZkuste to znovu za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Již <xliff:g id="NUMBER_0">%1$d</xliff:g>krát jste nesprávně zadali heslo. \n\nZkuste to znovu za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Již <xliff:g id="NUMBER_0">%1$d</xliff:g>krát jste zadali nesprávné bezpečnostní gesto. \n\nZkuste to znovu za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Zadali jste nesprávný kód PIN SIM karty. Nyní musíte za účelem odemknutí zařízení kontaktovat svého operátora."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="few">Zadali jste nesprávný kód PIN SIM karty. Máte ještě <xliff:g id="NUMBER_1">%d</xliff:g> pokusy.</item>
diff --git a/packages/SystemUI/res-keyguard/values-da/strings.xml b/packages/SystemUI/res-keyguard/values-da/strings.xml
index a66f02b92465..e486fc625699 100644
--- a/packages/SystemUI/res-keyguard/values-da/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-da/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Du har indtastet en forkert pinkode <xliff:g id="NUMBER_0">%1$d</xliff:g> gange. \n\nPrøv igen om <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunder."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Du har indtastet din adgangskode forkert <xliff:g id="NUMBER_0">%1$d</xliff:g> gange. \n\nPrøv igen om <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunder."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Du har tegnet dit oplåsningsmønster forkert <xliff:g id="NUMBER_0">%1$d</xliff:g> gange. \n\nPrøv igen om <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunder."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Forkert pinkode til SIM-kort. Du er nu nødt til at kontakte dit mobilselskab for at låse din enhed op."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="one">Forkert pinkode til SIM-kort. Du har <xliff:g id="NUMBER_1">%d</xliff:g> forsøg tilbage.</item>
diff --git a/packages/SystemUI/res-keyguard/values-de/strings.xml b/packages/SystemUI/res-keyguard/values-de/strings.xml
index 7c0839acf496..06d012f4e84d 100644
--- a/packages/SystemUI/res-keyguard/values-de/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-de/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Du hast deine PIN <xliff:g id="NUMBER_0">%1$d</xliff:g>-mal falsch eingegeben.\n\nBitte versuche es in <xliff:g id="NUMBER_1">%2$d</xliff:g> Sekunden noch einmal."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Du hast dein Passwort <xliff:g id="NUMBER_0">%1$d</xliff:g>-mal falsch eingegeben.\n\nBitte versuche es in <xliff:g id="NUMBER_1">%2$d</xliff:g> Sekunden noch einmal."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Du hast dein Entsperrungsmuster <xliff:g id="NUMBER_0">%1$d</xliff:g>-mal falsch gezeichnet. \n\nBitte versuche es in <xliff:g id="NUMBER_1">%2$d</xliff:g> Sekunden noch einmal."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Falscher PIN-Code der SIM-Karte. Bitte wende dich an deinen Mobilfunkanbieter, damit er dein Gerät entsperrt."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">Falscher PIN-Code der SIM-Karte. Du hast noch <xliff:g id="NUMBER_1">%d</xliff:g> Versuche.</item>
diff --git a/packages/SystemUI/res-keyguard/values-el/strings.xml b/packages/SystemUI/res-keyguard/values-el/strings.xml
index e9bd207a6f12..176428421476 100644
--- a/packages/SystemUI/res-keyguard/values-el/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-el/strings.xml
@@ -41,7 +41,7 @@
<string name="keyguard_low_battery" msgid="1868012396800230904">"Συνδέστε τον φορτιστή."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Πατήστε \"Μενού\" για ξεκλείδωμα."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Κλειδωμένο δίκτυο"</string>
- <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Δεν υπάρχει κάρτα SIM"</string>
+ <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Δεν υπάρχει SIM"</string>
<string name="keyguard_missing_sim_instructions" msgid="1162120926141335918">"Τοποθετήστε μια κάρτα SIM."</string>
<string name="keyguard_missing_sim_instructions_long" msgid="2712623293749378570">"Η κάρτα SIM δεν υπάρχει ή δεν είναι δυνατή η ανάγνωσή της. Τοποθετήστε μια κάρτα SIM."</string>
<string name="keyguard_permanent_disabled_sim_message_short" msgid="5842745213110966962">"Η κάρτα SIM δεν μπορεί να χρησιμοποιηθεί."</string>
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Έχετε πληκτρολογήσει τον αριθμό PIN εσφαλμένα <xliff:g id="NUMBER_0">%1$d</xliff:g> φορές. \n\nΠροσπαθήστε ξανά σε <xliff:g id="NUMBER_1">%2$d</xliff:g> δευτερόλεπτα."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Έχετε πληκτρολογήσει τον κωδικό πρόσβασης εσφαλμένα <xliff:g id="NUMBER_0">%1$d</xliff:g> φορές. \n\nΠροσπαθήστε ξανά σε <xliff:g id="NUMBER_1">%2$d</xliff:g> δευτερόλεπτα."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Σχεδιάσατε εσφαλμένα το μοτίβο ξεκλειδώματος<xliff:g id="NUMBER_0">%1$d</xliff:g> φορές. \n\nΠροσπαθήστε ξανά σε <xliff:g id="NUMBER_1">%2$d</xliff:g> δευτερόλεπτα."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Λανθασμένος κωδικός PIN κάρτας SIM. Θα πρέπει να επικοινωνήσετε με την εταιρεία κινητής τηλεφωνίας σας για να ξεκλειδώσετε τη συσκευή σας."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">Λανθασμένος κωδικός PIN κάρτας SIM. Απομένουν άλλες <xliff:g id="NUMBER_1">%d</xliff:g> προσπάθειες.</item>
diff --git a/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml b/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml
index 969a8d67921d..92a15949a8ab 100644
--- a/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"You have incorrectly typed your PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> times. \n\nTry again in <xliff:g id="NUMBER_1">%2$d</xliff:g> seconds."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"You have incorrectly typed your password <xliff:g id="NUMBER_0">%1$d</xliff:g> times. \n\nTry again in <xliff:g id="NUMBER_1">%2$d</xliff:g> seconds."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. \n\nTry again in <xliff:g id="NUMBER_1">%2$d</xliff:g> seconds."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Incorrect SIM PIN code; you must now contact your operator to unlock your device."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">Incorrect SIM PIN code. You have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts.</item>
diff --git a/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml b/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml
index fcc08878668b..719f1a18a744 100644
--- a/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"You have incorrectly typed your PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> times. \n\nTry again in <xliff:g id="NUMBER_1">%2$d</xliff:g> seconds."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"You have incorrectly typed your password <xliff:g id="NUMBER_0">%1$d</xliff:g> times. \n\nTry again in <xliff:g id="NUMBER_1">%2$d</xliff:g> seconds."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. \n\nTry again in <xliff:g id="NUMBER_1">%2$d</xliff:g> seconds."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Incorrect SIM PIN code; you must now contact your operator to unlock your device."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">Incorrect SIM PIN code. You have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts.</item>
diff --git a/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml b/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml
index 969a8d67921d..92a15949a8ab 100644
--- a/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"You have incorrectly typed your PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> times. \n\nTry again in <xliff:g id="NUMBER_1">%2$d</xliff:g> seconds."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"You have incorrectly typed your password <xliff:g id="NUMBER_0">%1$d</xliff:g> times. \n\nTry again in <xliff:g id="NUMBER_1">%2$d</xliff:g> seconds."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. \n\nTry again in <xliff:g id="NUMBER_1">%2$d</xliff:g> seconds."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Incorrect SIM PIN code; you must now contact your operator to unlock your device."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">Incorrect SIM PIN code. You have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts.</item>
diff --git a/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml b/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml
index 969a8d67921d..92a15949a8ab 100644
--- a/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"You have incorrectly typed your PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> times. \n\nTry again in <xliff:g id="NUMBER_1">%2$d</xliff:g> seconds."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"You have incorrectly typed your password <xliff:g id="NUMBER_0">%1$d</xliff:g> times. \n\nTry again in <xliff:g id="NUMBER_1">%2$d</xliff:g> seconds."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. \n\nTry again in <xliff:g id="NUMBER_1">%2$d</xliff:g> seconds."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Incorrect SIM PIN code; you must now contact your operator to unlock your device."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">Incorrect SIM PIN code. You have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts.</item>
diff --git a/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml b/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml
index 80df3be320b9..25ab6159998e 100644
--- a/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Escribiste tu PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> veces de manera incorrecta. \n\nVuelve a intentarlo en <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Escribiste tu contraseña <xliff:g id="NUMBER_0">%1$d</xliff:g> veces de manera incorrecta. \n\nVuelve a intentarlo en <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Dibujaste tu patrón de desbloqueo <xliff:g id="NUMBER_0">%1$d</xliff:g> veces de manera incorrecta. \n\nVuelve a intentarlo en <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"El código PIN de la tarjeta SIM es incorrecto. Debes comunicarte con tu proveedor para desbloquear el dispositivo."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">El código PIN de la tarjeta SIM es incorrecto. Te quedan <xliff:g id="NUMBER_1">%d</xliff:g> intentos más.</item>
diff --git a/packages/SystemUI/res-keyguard/values-es/strings.xml b/packages/SystemUI/res-keyguard/values-es/strings.xml
index abfaf3a451c8..ce323c7f65a7 100644
--- a/packages/SystemUI/res-keyguard/values-es/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-es/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Has fallado <xliff:g id="NUMBER_0">%1$d</xliff:g> veces al escribir el PIN. \n\nVuelve a intentarlo dentro de <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Has fallado <xliff:g id="NUMBER_0">%1$d</xliff:g> veces al introducir la contraseña. \n\nVuelve a intentarlo dentro de <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Has fallado <xliff:g id="NUMBER_0">%1$d</xliff:g> veces al dibujar el patrón de desbloqueo. \n\nVuelve a intentarlo dentro de <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"El código PIN de la tarjeta SIM es incorrecto. Debes ponerte en contacto con tu operador para desbloquear el dispositivo."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">El código PIN de la tarjeta SIM es incorrecto. Quedan <xliff:g id="NUMBER_1">%d</xliff:g> intentos.</item>
diff --git a/packages/SystemUI/res-keyguard/values-et/strings.xml b/packages/SystemUI/res-keyguard/values-et/strings.xml
index bf8d06718a9e..331a95c73c5e 100644
--- a/packages/SystemUI/res-keyguard/values-et/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-et/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Olete PIN-koodi <xliff:g id="NUMBER_0">%1$d</xliff:g> korda valesti sisestanud. \n\nProovige <xliff:g id="NUMBER_1">%2$d</xliff:g> sekundi pärast uuesti."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Olete parooli <xliff:g id="NUMBER_0">%1$d</xliff:g> korda valesti sisestanud. \n\nProovige <xliff:g id="NUMBER_1">%2$d</xliff:g> sekundi pärast uuesti."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Olete oma avamismustrit <xliff:g id="NUMBER_0">%1$d</xliff:g> korda valesti joonistanud. \n\nProovige <xliff:g id="NUMBER_1">%2$d</xliff:g> sekundi pärast uuesti."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"SIM-kaardi vale PIN-kood. Seadme avamiseks peate nüüd ühendust võtma oma operaatoriga."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">SIM-kaardi vale PIN-kood. Teil on jäänud veel <xliff:g id="NUMBER_1">%d</xliff:g> katset.</item>
diff --git a/packages/SystemUI/res-keyguard/values-eu/strings.xml b/packages/SystemUI/res-keyguard/values-eu/strings.xml
index 6cf00d8f458f..3ff224b9e55a 100644
--- a/packages/SystemUI/res-keyguard/values-eu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-eu/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"<xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz idatzi duzu PIN kodea, baina huts egin duzu denetan. \n\nSaiatu berriro <xliff:g id="NUMBER_1">%2$d</xliff:g> segundo barru."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"<xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz idatzi duzu pasahitza, baina huts egin duzu denetan. \n\nSaiatu berriro <xliff:g id="NUMBER_1">%2$d</xliff:g> segundo barru."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"<xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz marraztu duzu desblokeatzeko eredua, baina huts egin duzu denetan. \n\nSaiatu berriro <xliff:g id="NUMBER_1">%2$d</xliff:g> segundo barru."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"SIM txartelaren PIN kodea ez da zuzena. Gailua desblokeatzeko, operadorearekin jarri beharko duzu harremanetan."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">Ez da zuzena SIM txartelaren PIN kodea. <xliff:g id="NUMBER_1">%d</xliff:g> saiakera geratzen zaizkizu gailua desblokeatzeko.</item>
diff --git a/packages/SystemUI/res-keyguard/values-fa/strings.xml b/packages/SystemUI/res-keyguard/values-fa/strings.xml
index 6fbe804093eb..5e696369634e 100644
--- a/packages/SystemUI/res-keyguard/values-fa/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fa/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"پین خود را <xliff:g id="NUMBER_0">%1$d</xliff:g> بار اشتباه تایپ کردید. \n\nپس از <xliff:g id="NUMBER_1">%2$d</xliff:g> ثانیه دوباره امتحان کنید."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"گذرواژه خود را <xliff:g id="NUMBER_0">%1$d</xliff:g> بار اشتباه تایپ کردید. \n\nپس از <xliff:g id="NUMBER_1">%2$d</xliff:g> ثانیه دوباره امتحان کنید."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"الگوی باز کردن قفل را <xliff:g id="NUMBER_0">%1$d</xliff:g> بار اشتباه کشیدید. \n\nلطفاً پس از <xliff:g id="NUMBER_1">%2$d</xliff:g> ثانیه دوباره امتحان کنید."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"کد پین سیم‌کارت اشتباه است، اکنون برای باز کردن قفل دستگاهتان باید با شرکت مخابراتی تماس بگیرید."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="one">کد پین سیم‌کارت اشتباه است، <xliff:g id="NUMBER_1">%d</xliff:g> بار دیگر می‌توانید تلاش کنید.</item>
diff --git a/packages/SystemUI/res-keyguard/values-fi/strings.xml b/packages/SystemUI/res-keyguard/values-fi/strings.xml
index 6d26e3686dfb..54bc4d8cba58 100644
--- a/packages/SystemUI/res-keyguard/values-fi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fi/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Olet kirjoittanut PIN-koodin väärin <xliff:g id="NUMBER_0">%1$d</xliff:g> kertaa. \n\nYritä uudelleen <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunnin kuluttua."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Olet kirjoittanut salasanan väärin <xliff:g id="NUMBER_0">%1$d</xliff:g> kertaa. \n\nYritä uudelleen <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunnin kuluttua."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Olet piirtänyt lukituksenpoistokuvion väärin <xliff:g id="NUMBER_0">%1$d</xliff:g> kertaa. \n\nYritä uudelleen <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunnin kuluttua."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Virheellinen SIM-kortin PIN-koodi. Sinun on nyt otettava yhteys operaattoriin laitteen lukituksen avaamiseksi."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">Virheellinen SIM-kortin PIN-koodi. Sinulla on <xliff:g id="NUMBER_1">%d</xliff:g> yritystä jäljellä.</item>
diff --git a/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml b/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml
index 53255af72e7c..3e858c2ecf12 100644
--- a/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Vous avez entré un NIP incorrect à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. \n\nVeuillez réessayer dans <xliff:g id="NUMBER_1">%2$d</xliff:g> secondes."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Vous avez entré un mot de passe incorrect à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises.\n\nVeuillez réessayer dans <xliff:g id="NUMBER_1">%2$d</xliff:g> secondes."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Vous avez dessiné un schéma de déverrouillage incorrect à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises.\n\nVeuillez réessayer dans <xliff:g id="NUMBER_1">%2$d</xliff:g> secondes."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"NIP de carte SIM incorrect. Vous devez maintenant communiquer avec votre fournisseur de services pour déverrouiller votre appareil."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="one">Le NIP de la carte SIM incorrect. Il vous reste <xliff:g id="NUMBER_1">%d</xliff:g> tentative.</item>
diff --git a/packages/SystemUI/res-keyguard/values-fr/strings.xml b/packages/SystemUI/res-keyguard/values-fr/strings.xml
index ff3ed5395363..8551fab7281f 100644
--- a/packages/SystemUI/res-keyguard/values-fr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fr/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Vous avez saisi un code incorrect à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises.\n\nRéessayez dans <xliff:g id="NUMBER_1">%2$d</xliff:g> secondes."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Vous avez saisi un mot de passe incorrect à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises.\n\nRéessayez dans <xliff:g id="NUMBER_1">%2$d</xliff:g> secondes."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Vous avez dessiné un schéma de déverrouillage incorrect à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises.\n\nRéessayez dans <xliff:g id="NUMBER_1">%2$d</xliff:g> secondes."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Code PIN de la carte SIM incorrect. Vous devez désormais contacter votre opérateur pour déverrouiller votre appareil."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="one">Code PIN de la carte SIM incorrect. Il vous reste <xliff:g id="NUMBER_1">%d</xliff:g> tentative.</item>
diff --git a/packages/SystemUI/res-keyguard/values-gl/strings.xml b/packages/SystemUI/res-keyguard/values-gl/strings.xml
index d7f6b6a245e2..420649eeca60 100644
--- a/packages/SystemUI/res-keyguard/values-gl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-gl/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Introduciches o PIN incorrectamente <xliff:g id="NUMBER_0">%1$d</xliff:g> veces. \n\nTéntao de novo en <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Introduciches o contrasinal incorrectamente <xliff:g id="NUMBER_0">%1$d</xliff:g> veces. \n\nTéntao de novo en <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Debuxaches incorrectamente o padrón de desbloqueo <xliff:g id="NUMBER_0">%1$d</xliff:g> veces. \n\nTéntao de novo en <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"O código PIN da SIM non é correcto. Agora debes contactar co operador para desbloquear o dispositivo."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">O código PIN da SIM é incorrecto. Quédanche <xliff:g id="NUMBER_1">%d</xliff:g> intentos.</item>
diff --git a/packages/SystemUI/res-keyguard/values-gu/strings.xml b/packages/SystemUI/res-keyguard/values-gu/strings.xml
index c3b7602adcd6..b02d3d97b39f 100644
--- a/packages/SystemUI/res-keyguard/values-gu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-gu/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"તમારો પિન તમે <xliff:g id="NUMBER_0">%1$d</xliff:g> વખત ખોટી રીતે લખ્યો છે. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> સેકન્ડમાં ફરીથી પ્રયાસ કરો."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"તમારો પાસવર્ડ તમે <xliff:g id="NUMBER_0">%1$d</xliff:g> વખત ખોટી રીતે લખ્યો છે. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> સેકંડમાં ફરીથી પ્રયાસ કરો."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"તમારી અનલૉક પૅટર્ન તમે <xliff:g id="NUMBER_0">%1$d</xliff:g> વખત ખોટી રીતે દોરી છે. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> સેકન્ડમાં ફરીથી પ્રયાસ કરો."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"ખોટો સિમ પિન કોડ, તમારે હવે તમારું ઉપકરણ અનલૉક કરવા માટે તમારા કૅરીઅરનો સંપર્ક કરવો આવશ્યક છે."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="one">ખોટો સિમ પિન કોડ, તમારી પાસે <xliff:g id="NUMBER_1">%d</xliff:g> પ્રયાસ બાકી છે.</item>
diff --git a/packages/SystemUI/res-keyguard/values-hi/strings.xml b/packages/SystemUI/res-keyguard/values-hi/strings.xml
index 1c5ceadd8dd6..f6b15de0e97e 100644
--- a/packages/SystemUI/res-keyguard/values-hi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hi/strings.xml
@@ -41,7 +41,7 @@
<string name="keyguard_low_battery" msgid="1868012396800230904">"अपना चार्जर कनेक्‍ट करें."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"लॉक खोलने के लिए मेन्यू दबाएं."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"नेटवर्क लॉक किया हुआ है"</string>
- <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"कोई SIM कार्ड नहीं है"</string>
+ <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"कोई सिम कार्ड नहीं है"</string>
<string name="keyguard_missing_sim_instructions" msgid="1162120926141335918">"SIM कार्ड लगाएं."</string>
<string name="keyguard_missing_sim_instructions_long" msgid="2712623293749378570">"SIM कार्ड मौजूद नहीं है या उसे पढ़ा नहीं जा सकता है. कोई SIM कार्ड लगाएं."</string>
<string name="keyguard_permanent_disabled_sim_message_short" msgid="5842745213110966962">"बेकार SIM कार्ड."</string>
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"आप अपना पिन <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से लिख चुके हैं. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> सेकंड में फिर से कोशिश करें."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"आप अपना पासवर्ड <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से लिख चुके हैं. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> सेकंड में फिर से कोशिश करें."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"आपने अपने लॉक खोलने के पैटर्न को <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से ड्रॉ किया है. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> सेकंड में फिर से कोशिश करें."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"गलत SIM पिन कोड, अपने डिवाइस को अनलॉक करने के लिए अब आपको अपनी मोबाइल और इंटरनेट सेवा देने वाली कंपनी से संपर्क करना होगा."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="one">गलत सिम पिन कोड, आप <xliff:g id="NUMBER_1">%d</xliff:g> बार और कोशिश कर सकते हैं.</item>
diff --git a/packages/SystemUI/res-keyguard/values-hr/strings.xml b/packages/SystemUI/res-keyguard/values-hr/strings.xml
index ee7a40350ba2..49db3f88669a 100644
--- a/packages/SystemUI/res-keyguard/values-hr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hr/strings.xml
@@ -86,14 +86,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Netočno ste unijeli PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> put/a. \n\nPokušajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Netočno ste unijeli zaporku <xliff:g id="NUMBER_0">%1$d</xliff:g> put/a. \n\nPokušajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Netočno ste iscrtali uzorak za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> put/a. \n\nPokušajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Netočan PIN kôd SIM kartice; sada morate kontaktirati svog mobilnog operatera da bi otključao vaš uređaj."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="one">PIN kôd SIM-a nije točan. Imate još <xliff:g id="NUMBER_1">%d</xliff:g> pokušaj.</item>
diff --git a/packages/SystemUI/res-keyguard/values-hu/strings.xml b/packages/SystemUI/res-keyguard/values-hu/strings.xml
index 2f358a063f46..c26998f01ff0 100644
--- a/packages/SystemUI/res-keyguard/values-hu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hu/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"<xliff:g id="NUMBER_0">%1$d</xliff:g> alkalommal helytelenül adta meg a PIN-kódot.\n\nPróbálja újra <xliff:g id="NUMBER_1">%2$d</xliff:g> másodperc múlva."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"<xliff:g id="NUMBER_0">%1$d</xliff:g> alkalommal helytelenül adta meg a jelszót.\n\nPróbálja újra <xliff:g id="NUMBER_1">%2$d</xliff:g> másodperc múlva."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"<xliff:g id="NUMBER_0">%1$d</xliff:g> alkalommal rosszul rajzolta le a feloldási mintát.\n\nPróbálja újra <xliff:g id="NUMBER_1">%2$d</xliff:g> másodperc múlva."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Helytelen PIN-kód a SIM-kártyához. Az eszköz feloldása érdekében, kérjük, vegye fel a kapcsolatot szolgáltatójával."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">Helytelen PIN-kód a SIM-kártyához. Még <xliff:g id="NUMBER_1">%d</xliff:g> próbálkozása maradt.</item>
diff --git a/packages/SystemUI/res-keyguard/values-hy/strings.xml b/packages/SystemUI/res-keyguard/values-hy/strings.xml
index 7da8ed4b8a5b..ad949d48fe0c 100644
--- a/packages/SystemUI/res-keyguard/values-hy/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hy/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Դուք սխալ եք մուտքագրել ձեր PIN կոդը <xliff:g id="NUMBER_0">%1$d</xliff:g> անգամ: \n\nՓորձեք կրկին <xliff:g id="NUMBER_1">%2$d</xliff:g> վայրկյանից։"</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Դուք սխալ եք մուտքագրել ձեր գաղտնաբառը <xliff:g id="NUMBER_0">%1$d</xliff:g> անգամ: \n\nՓորձեք կրկին <xliff:g id="NUMBER_1">%2$d</xliff:g> վայրկյանից:"</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Դուք սխալ եք մուտքագրել ձեր ապակողպման նախշը <xliff:g id="NUMBER_0">%1$d</xliff:g> անգամ: \n\nՓորձեք կրկին <xliff:g id="NUMBER_1">%2$d</xliff:g> վայրկյանից։"</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"SIM PIN կոդը սխալ է։ Այժմ պետք է դիմեք ձեր օպերատորին՝ սարքն արգելահանելու համար:"</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="one">Incorrect SIM PIN code, you have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts.</item>
diff --git a/packages/SystemUI/res-keyguard/values-in/strings.xml b/packages/SystemUI/res-keyguard/values-in/strings.xml
index 406b00e6e369..875d8d51c50b 100644
--- a/packages/SystemUI/res-keyguard/values-in/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-in/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Anda telah <xliff:g id="NUMBER_0">%1$d</xliff:g> kali salah mengetik PIN. \n\nCoba lagi dalam <xliff:g id="NUMBER_1">%2$d</xliff:g> detik."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Anda telah <xliff:g id="NUMBER_0">%1$d</xliff:g> kali salah mengetik sandi. \n\nCoba lagi dalam <xliff:g id="NUMBER_1">%2$d</xliff:g> detik."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Anda telah <xliff:g id="NUMBER_0">%1$d</xliff:g> kali salah menggambar pola pembuka kunci. \n\nCoba lagi dalam <xliff:g id="NUMBER_1">%2$d</xliff:g> detik."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Kode PIN SIM salah. Hubungi operator untuk membuka kunci perangkat."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">Kode PIN SIM salah, sisa, sisa <xliff:g id="NUMBER_1">%d</xliff:g> percobaan.</item>
diff --git a/packages/SystemUI/res-keyguard/values-is/strings.xml b/packages/SystemUI/res-keyguard/values-is/strings.xml
index 4f87df6bb68e..e40cdca33034 100644
--- a/packages/SystemUI/res-keyguard/values-is/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-is/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Þú hefur slegið inn rangt PIN-númer <xliff:g id="NUMBER_0">%1$d</xliff:g> sinnum. \n\nReyndu aftur eftir <xliff:g id="NUMBER_1">%2$d</xliff:g> sekúndur."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Þú hefur slegið inn rangt aðgangsorð <xliff:g id="NUMBER_0">%1$d</xliff:g> sinnum. \n\nReyndu aftur eftir <xliff:g id="NUMBER_1">%2$d</xliff:g> sekúndur."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Þú hefur teiknað rangt opnunarmynstur <xliff:g id="NUMBER_0">%1$d</xliff:g> sinnum. \n\nReyndu aftur eftir <xliff:g id="NUMBER_1">%2$d</xliff:g> sekúndur."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Rangt PIN-númer SIM-korts. Nú þarftu að hafa samband við símafyrirtækið til að opna fyrir tækið."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="one">Rangt PIN-númer SIM-korts. Þú átt <xliff:g id="NUMBER_1">%d</xliff:g> tilraun eftir.</item>
diff --git a/packages/SystemUI/res-keyguard/values-it/strings.xml b/packages/SystemUI/res-keyguard/values-it/strings.xml
index f714bf7cfde7..16767d1771fe 100644
--- a/packages/SystemUI/res-keyguard/values-it/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-it/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Hai digitato il tuo PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> volte in modo errato. \n\nRiprova tra <xliff:g id="NUMBER_1">%2$d</xliff:g> secondi."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Hai digitato la tua password <xliff:g id="NUMBER_0">%1$d</xliff:g> volte in modo errato. \n\nRiprova tra <xliff:g id="NUMBER_1">%2$d</xliff:g> secondi."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"<xliff:g id="NUMBER_0">%1$d</xliff:g> tentativi errati di inserimento della sequenza di sblocco. \n\nRiprova tra <xliff:g id="NUMBER_1">%2$d</xliff:g> secondi."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Codice PIN della SIM errato. Devi contattare l\'operatore per sbloccare il dispositivo."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">Codice PIN della SIM errato. Hai ancora <xliff:g id="NUMBER_1">%d</xliff:g> tentativi a disposizione.</item>
diff --git a/packages/SystemUI/res-keyguard/values-iw/strings.xml b/packages/SystemUI/res-keyguard/values-iw/strings.xml
index 2af519224c2d..e054f629836e 100644
--- a/packages/SystemUI/res-keyguard/values-iw/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-iw/strings.xml
@@ -87,14 +87,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"הקלדת קוד גישה שגוי <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. \n\nנסה שוב בעוד <xliff:g id="NUMBER_1">%2$d</xliff:g> שניות."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"הקלדת סיסמה שגויה <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים.\n\nנסה שוב בעוד <xliff:g id="NUMBER_1">%2$d</xliff:g> שניות."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"שרטטת קו ביטול נעילה שגוי <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. \n\nנסה שוב בעוד <xliff:g id="NUMBER_1">%2$d</xliff:g> שניות."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"‏קוד הגישה של כרטיס ה-SIM שגוי. צור קשר עם הספק כדי לבטל את נעילת המכשיר."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="two">‏קוד הגישה של כרטיס ה-SIM שגוי. נותרו לך עוד <xliff:g id="NUMBER_1">%d</xliff:g> ניסיונות.</item>
diff --git a/packages/SystemUI/res-keyguard/values-ja/strings.xml b/packages/SystemUI/res-keyguard/values-ja/strings.xml
index 5f0d83fb81bc..957d78a8b440 100644
--- a/packages/SystemUI/res-keyguard/values-ja/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ja/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"PIN の入力を <xliff:g id="NUMBER_0">%1$d</xliff:g> 回間違えました。\n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> 秒後にもう一度お試しください。"</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"パスワードの入力を <xliff:g id="NUMBER_0">%1$d</xliff:g> 回間違えました。\n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> 秒後にもう一度お試しください。"</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"ロック解除パターンの入力を <xliff:g id="NUMBER_0">%1$d</xliff:g> 回間違えました。\n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> 秒後にもう一度お試しください。"</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"SIM PIN コードが無効です。お使いのデバイスをロック解除するには携帯通信会社にお問い合わせいただく必要があります。"</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">SIM PIN コードが無効です。入力できるのはあと <xliff:g id="NUMBER_1">%d</xliff:g> 回です。</item>
diff --git a/packages/SystemUI/res-keyguard/values-ka/strings.xml b/packages/SystemUI/res-keyguard/values-ka/strings.xml
index cd1719b16922..d0d15fec7172 100644
--- a/packages/SystemUI/res-keyguard/values-ka/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ka/strings.xml
@@ -41,7 +41,7 @@
<string name="keyguard_low_battery" msgid="1868012396800230904">"შეაერთეთ დამტენი."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"განსაბლოკად დააჭირეთ მენიუს."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"ქსელი ჩაკეტილია"</string>
- <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"SIM ბარათი არ არის"</string>
+ <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"SIM ბარ. არაა"</string>
<string name="keyguard_missing_sim_instructions" msgid="1162120926141335918">"ჩადეთ SIM ბარათი."</string>
<string name="keyguard_missing_sim_instructions_long" msgid="2712623293749378570">"SIM ბარათი არ არის ან არ იკითხება. ჩადეთ SIM ბარათი."</string>
<string name="keyguard_permanent_disabled_sim_message_short" msgid="5842745213110966962">"SIM ბარათი გამოუსადეგარია."</string>
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"თქვენ არასწორად შეიყვანეთ PIN-კოდი <xliff:g id="NUMBER_0">%1$d</xliff:g>-ჯერ. \n\nცადეთ ხელახლა <xliff:g id="NUMBER_1">%2$d</xliff:g> წამში."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"თქვენ არასწორად აკრიფეთ პაროლი <xliff:g id="NUMBER_0">%1$d</xliff:g>-ჯერ. \n\nცადეთ ხელახლა <xliff:g id="NUMBER_1">%2$d</xliff:g> წამში."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"თქვენ არასწორად დახატეთ განბლოკვის ნიმუში <xliff:g id="NUMBER_0">%1$d</xliff:g>-ჯერ. \n\nცადეთ ხელახლა <xliff:g id="NUMBER_1">%2$d</xliff:g> წამში."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"SIM ბარათის PIN-კოდი არასწორია. ახლა თქვენი მოწყობილობის განსაბლოკად თქვენს ოპერატორთან დაკავშირება მოგიწევთ."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">SIM ბარათის PIN-კოდი არასწორია. თქვენ დაგრჩათ <xliff:g id="NUMBER_1">%d</xliff:g> მცდელობა.</item>
diff --git a/packages/SystemUI/res-keyguard/values-kk/strings.xml b/packages/SystemUI/res-keyguard/values-kk/strings.xml
index 0b78b579786e..96972a7577cf 100644
--- a/packages/SystemUI/res-keyguard/values-kk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-kk/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"PIN коды <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате енгізілді. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> секундтан кейін әркетті қайталаңыз."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Құпия сөз <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате енгізілді. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> секундтан кейін әрекетті қайталаңыз."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Құлыпты ашу өрнегі <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате енгізілді. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> секундтан кейін әрекетті қайталаңыз."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"SIM PIN коды дұрыс емес, операторға хабарласып, құрылғының құлпын ашуды сұраңыз."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">SIM PIN коды дұрыс емес. <xliff:g id="NUMBER_1">%d</xliff:g> әрекет қалды.</item>
diff --git a/packages/SystemUI/res-keyguard/values-km/strings.xml b/packages/SystemUI/res-keyguard/values-km/strings.xml
index a07c299dda49..24b5c23a6732 100644
--- a/packages/SystemUI/res-keyguard/values-km/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-km/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"អ្នក​បាន​វាយ​បញ្ចូល​កូដ PIN របស់​អ្នក​មិន​ត្រឹមត្រូវ​ចំនួន <xliff:g id="NUMBER_0">%1$d</xliff:g> ដង​ហើយ។ \n\nសូម​ព្យាយាម​ម្ដង​ទៀត​ក្នុង​រយៈ​ពេល <xliff:g id="NUMBER_1">%2$d</xliff:g> វិនាទី​ទៀត។"</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"អ្នក​បាន​វាយ​បញ្ចូល​ពាក្យ​សម្ងាត់​របស់​អ្នក​មិន​ត្រឹមត្រូវ​ចំនួន <xliff:g id="NUMBER_0">%1$d</xliff:g> ដង​ហើយ។ \n\nសូម​ព្យាយាម​ម្ដង​ទៀត​ក្នុង​រយៈ​ពេល <xliff:g id="NUMBER_1">%2$d</xliff:g> វិនាទី​ទៀត។"</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"អ្នក​បាន​គូរ​លំនាំ​ដោះ​សោ​របស់​អ្នក​មិន​ត្រឹមត្រូវ​ចំនួន <xliff:g id="NUMBER_0">%1$d</xliff:g> ដង​ហើយ។ \n\nសូមព្យាយាម​ម្ដង​ទៀត​ក្នុង​រយៈ​ពេល <xliff:g id="NUMBER_1">%2$d</xliff:g> វិនាទី​ទៀត។"</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"កូដ PIN របស់​ស៊ីម​មិន​ត្រឹមត្រូវ​ទេ អ្នក​ត្រូវ​ទាក់ទង​ទៅក្រុមហ៊ុន​បម្រើ​សេវា​ទូរសព្ទ​របស់​អ្នក​ឥឡូវ​នេះ ដើម្បី​ដោះ​សោ​ឧបករណ៍​របស់​អ្នក។"</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">កូដ PIN របស់​ស៊ីម​មិន​ត្រឹមត្រូវ​ទេ អ្នក​អាច​ព្យាយាម​បាន <xliff:g id="NUMBER_1">%d</xliff:g> ដងទៀត។</item>
diff --git a/packages/SystemUI/res-keyguard/values-kn/strings.xml b/packages/SystemUI/res-keyguard/values-kn/strings.xml
index 2c88419a1cba..785ca4338326 100644
--- a/packages/SystemUI/res-keyguard/values-kn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-kn/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"ನಿಮ್ಮ ಪಿನ್‌ ಅನ್ನು ನೀವು <xliff:g id="NUMBER_0">%1$d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಟೈಪ್ ಮಾಡಿದ್ದೀರಿ. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ಸೆಕೆಂಡುಗಳಲ್ಲಿ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"ನಿಮ್ಮ ಪಾಸ್‍‍ವರ್ಡ್ ಅನ್ನು ನೀವು <xliff:g id="NUMBER_0">%1$d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ನಮೂದಿಸಿದ್ದೀರಿ. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> ಸೆಕೆಂಡುಗಳಲ್ಲಿ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"ನಿಮ್ಮ ಅನ್‍‍ಲಾಕ್ ಪ್ಯಾಟರ್ನ್‌ ಅನ್ನು <xliff:g id="NUMBER_0">%1$d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಎಳೆದಿದ್ದೀರಿ. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ಸೆಕೆಂಡುಗಳಲ್ಲಿ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"ಸಿಮ್‌ ಪಿನ್‌ ಕೋಡ್‌ ತಪ್ಪಾಗಿದೆ, ನಿಮ್ಮ ಸಾಧನವನ್ನು ಅನ್‌ಲಾಕ್‌ ಮಾಡಲು ನೀವು ಈ ಕೂಡಲೇ ನಿಮ್ಮ ವಾಹಕವನ್ನು ಸಂಪರ್ಕಿಸಬೇಕು."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="one">ಸಿಮ್‌ ಪಿನ್ ಕೋಡ್‌ ತಪ್ಪಾಗಿದೆ, ನಿಮಗೆ <xliff:g id="NUMBER_1">%d</xliff:g> ಪ್ರಯತ್ನಗಳು ಬಾಕಿ ಉಳಿದಿವೆ.</item>
diff --git a/packages/SystemUI/res-keyguard/values-ko/strings.xml b/packages/SystemUI/res-keyguard/values-ko/strings.xml
index bdbd3d99ce06..6ae5935fea1a 100644
--- a/packages/SystemUI/res-keyguard/values-ko/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ko/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"PIN을 <xliff:g id="NUMBER_0">%1$d</xliff:g>번 잘못 입력했습니다. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g>초 후에 다시 시도하세요."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"비밀번호를 <xliff:g id="NUMBER_0">%1$d</xliff:g>번 잘못 입력했습니다. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g>초 후에 다시 시도하세요."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"잠금해제 패턴을 <xliff:g id="NUMBER_0">%1$d</xliff:g>번 잘못 그렸습니다. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g>초 후에 다시 시도하세요."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"잘못된 SIM PIN코드입니다. 이동통신사에 문의하여 기기를 잠금 해제해야 합니다."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">잘못된 SIM PIN 코드입니다. 입력을 <xliff:g id="NUMBER_1">%d</xliff:g>번 더 시도할 수 있습니다.</item>
diff --git a/packages/SystemUI/res-keyguard/values-ky/strings.xml b/packages/SystemUI/res-keyguard/values-ky/strings.xml
index 8e9c794ad095..9675cc9d39b2 100644
--- a/packages/SystemUI/res-keyguard/values-ky/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ky/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"PIN-кодуңузду <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тердиңиз. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> секунддан кийин дагы аракет кылып көрүңүз."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Сырсөзүңүздү <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тердиңиз. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> секунддан кийин дагы аракет кылып көрүңүз."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Кулпуну ачуучу графикалык ачкычты <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тарттыңыз. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> секунддан кийин дагы аракет кылып көрүңүз."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"SIM-картанын PIN-коду туура эмес. Эми түзмөктү бөгөттөн чыгаруу үчүн байланыш операторуңузга кайрылышыңыз керек."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">SIM-картанын PIN-коду туура эмес, сизде <xliff:g id="NUMBER_1">%d</xliff:g> аракет калды.</item>
diff --git a/packages/SystemUI/res-keyguard/values-lo/strings.xml b/packages/SystemUI/res-keyguard/values-lo/strings.xml
index 3ae088bcf914..ebaffb13d5b4 100644
--- a/packages/SystemUI/res-keyguard/values-lo/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-lo/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"ທ່ານພິມລະຫັດ PIN ຂອງທ່ານຜິດ <xliff:g id="NUMBER_0">%1$d</xliff:g> ເທື່ອແລ້ວ. \n\nກະລຸນາລອງໃໝ່ໃນອີກ <xliff:g id="NUMBER_1">%2$d</xliff:g> ວິນາທີ."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"ທ່ານພິມລະຫັດຜ່ານຜິດ <xliff:g id="NUMBER_0">%1$d</xliff:g> ເທື່ອແລ້ວ. \n\nໃຫ້ລອງໃໝ່ອີກຄັ້ງໃນອີກ <xliff:g id="NUMBER_1">%2$d</xliff:g> ວິນາທີ."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"ທ່ານແຕ້ມຮູບແບບປົດລັອກບໍ່ຖືກ <xliff:g id="NUMBER_0">%1$d</xliff:g> ເທື່ອແລ້ວ. \n\nລອງໃໝ່ໃນອີກ <xliff:g id="NUMBER_1">%2$d</xliff:g> ວິນາທີ."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"ລະຫັດ PIN ຂອງ SIM ບໍ່ຖືກຕ້ອງທ່ານຕ້ອງຕິດຕໍ່ຫາຜູ່ໃຫ້ບໍລິການ ເພື່ອປົດລັອກອຸປະກອນຂອງທ່ານ."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">ລະຫັດ SIM PIN ບໍ່ຖືກຕ້ອງ, ທ່ານຍັງພະຍາຍາມໄດ້ອີກ <xliff:g id="NUMBER_1">%d</xliff:g> ຄັ້ງ.</item>
diff --git a/packages/SystemUI/res-keyguard/values-lt/strings.xml b/packages/SystemUI/res-keyguard/values-lt/strings.xml
index 3d637f0e7113..4d598f6bfb6d 100644
--- a/packages/SystemUI/res-keyguard/values-lt/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-lt/strings.xml
@@ -87,14 +87,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"<xliff:g id="NUMBER_0">%1$d</xliff:g> kart. netinkamai įvedėte PIN kodą. \n\nBandykite dar kartą po <xliff:g id="NUMBER_1">%2$d</xliff:g> sek."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"<xliff:g id="NUMBER_0">%1$d</xliff:g> kart. netinkamai įvedėte slaptažodį. \n\nBandykite dar kartą po <xliff:g id="NUMBER_1">%2$d</xliff:g> sek."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"<xliff:g id="NUMBER_0">%1$d</xliff:g> kart. netinkamai nupiešėte atrakinimo piešinį. \n\nBandykite dar kartą po <xliff:g id="NUMBER_1">%2$d</xliff:g> sek."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Netinkamas SIM kortelės PIN kodas. Reikės susisiekti su operatoriumi, kad atrakintų įrenginį."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="one">Netinkamas SIM kortelės PIN kodas. Liko <xliff:g id="NUMBER_1">%d</xliff:g> bandymas.</item>
diff --git a/packages/SystemUI/res-keyguard/values-lv/strings.xml b/packages/SystemUI/res-keyguard/values-lv/strings.xml
index 2c24f4ad2718..fad67d536e58 100644
--- a/packages/SystemUI/res-keyguard/values-lv/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-lv/strings.xml
@@ -86,14 +86,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Jūs <xliff:g id="NUMBER_0">%1$d</xliff:g> reizi(-es) esat ievadījis nepareizu PIN kodu.\n\nMēģiniet vēlreiz pēc <xliff:g id="NUMBER_1">%2$d</xliff:g> sekundes(-ēm)."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Jūs <xliff:g id="NUMBER_0">%1$d</xliff:g> reizi(-es) esat ievadījis nepareizu paroli.\n\nMēģiniet vēlreiz pēc <xliff:g id="NUMBER_1">%2$d</xliff:g> sekundes(-ēm)."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Jūs <xliff:g id="NUMBER_0">%1$d</xliff:g> reizi(-es) esat nepareizi uzzīmējis atbloķēšanas kombināciju.\n\nMēģiniet vēlreiz pēc <xliff:g id="NUMBER_1">%2$d</xliff:g> sekundes(-ēm)."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Nepareizs SIM kartes PIN kods. Lai atbloķētu ierīci, sazinieties ar mobilo sakaru operatoru."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="zero">Nepareizs SIM kartes PIN kods. Varat mēģināt vēl <xliff:g id="NUMBER_1">%d</xliff:g> reizes.</item>
diff --git a/packages/SystemUI/res-keyguard/values-mk/strings.xml b/packages/SystemUI/res-keyguard/values-mk/strings.xml
index d434bc4a1200..1397f467e116 100644
--- a/packages/SystemUI/res-keyguard/values-mk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-mk/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Погрешно сте го напишале вашиот PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> пати. \n\nОбидете се повторно за <xliff:g id="NUMBER_1">%2$d</xliff:g> секунди."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Погрешно сте ја напишале вашата лозинка <xliff:g id="NUMBER_0">%1$d</xliff:g> пати. \n\nОбидете се повторно за <xliff:g id="NUMBER_1">%2$d</xliff:g> секунди."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Погрешно сте ја нацртале вашата шема за отклучување <xliff:g id="NUMBER_0">%1$d</xliff:g> пати. \n\nОбидете се повторно за <xliff:g id="NUMBER_1">%2$d</xliff:g> секунди."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Погрешен PIN-код за SIM, сега мора да контактирате со вашиот оператор за да го отклучите уредот."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="one">Погрешен PIN-код за SIM, ви преостанува уште <xliff:g id="NUMBER_1">%d</xliff:g> обид.</item>
diff --git a/packages/SystemUI/res-keyguard/values-ml/strings.xml b/packages/SystemUI/res-keyguard/values-ml/strings.xml
index 3992e17a8757..f82f822ca26c 100644
--- a/packages/SystemUI/res-keyguard/values-ml/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ml/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"നിങ്ങൾ <xliff:g id="NUMBER_0">%1$d</xliff:g> തവണ പിൻ ‌തെറ്റായി ‌ടൈപ്പുചെയ്തു. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> സെക്കന്റിനു‌ശേഷം വീണ്ടും ശ്രമിക്കുക."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"നിങ്ങൾ <xliff:g id="NUMBER_0">%1$d</xliff:g> തവണ നിങ്ങളുടെ പാസ്‌വേഡ് ‌തെറ്റായി ‌ടൈപ്പുചെയ്തു. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> സെക്കന്റിനു‌ശേഷം വീണ്ടും ശ്രമിക്കുക."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"നിങ്ങൾ <xliff:g id="NUMBER_0">%1$d</xliff:g> തവണ അൺലോക്ക് പാറ്റേൺ ‌തെറ്റായി ‌വരച്ചു. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> സെക്കന്റിനു‌ശേഷം വീണ്ടും ശ്രമിക്കുക."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"സിം പിൻ കോഡ് തെറ്റാണ്, നിങ്ങളുടെ ഉപകരണം അൺലോക്കുചെയ്യാൻ ഇനി നിങ്ങളുടെ കാരിയറുമായി ബന്ധപ്പെടണം."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">സിം പിൻ കോഡ് തെറ്റാണ്, നിങ്ങൾക്ക് <xliff:g id="NUMBER_1">%d</xliff:g> ശ്രമങ്ങൾ കൂടി ശേഷിക്കുന്നു.</item>
diff --git a/packages/SystemUI/res-keyguard/values-mn/strings.xml b/packages/SystemUI/res-keyguard/values-mn/strings.xml
index ba80daf7ece4..462017af1922 100644
--- a/packages/SystemUI/res-keyguard/values-mn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-mn/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Та ПИН кодоо <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу орууллаа. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> секундын дараа дахин оролдоно уу."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Та нууц үгээ <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу орууллаа. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> секундын дараа дахин оролдоно уу."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Та тайлах хээг <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу орууллаа. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> секундын дараа дахин оролдоно уу."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"SIM-н ПИН кодыг буруу оруулсан тул та төхөөрөмжийнхөө түгжээг тайлахын тулд оператор компанитайгаа холбогдоно уу."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">SIM-н ПИН код буруу байна. Танд <xliff:g id="NUMBER_1">%d</xliff:g> оролдлого үлдлээ.</item>
diff --git a/packages/SystemUI/res-keyguard/values-mr/strings.xml b/packages/SystemUI/res-keyguard/values-mr/strings.xml
index 9d46fb9c3344..0166791dc3ba 100644
--- a/packages/SystemUI/res-keyguard/values-mr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-mr/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"तुम्ही तुमचा PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा चुकीच्या पद्धतीने टाइप केला आहे. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"तुम्ही तुमचा पासवर्ड <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा चुकीच्या पद्धतीने टाइप केला आहे. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"तुम्ही तुमचा अनलॉक पॅटर्न <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा अयोग्यरितीने काढला. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"सिम पिन कोड चुकीचा आहे तुम्ही आता तुमचे डिव्हाइस अनलॉक करण्‍यासाठी तुमच्या वाहकाशी संपर्क साधावा."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">चुकीचा सिम पिन कोड, तुमच्याकडे <xliff:g id="NUMBER_1">%d</xliff:g> प्रयत्न शिल्लक आहेत.</item>
diff --git a/packages/SystemUI/res-keyguard/values-ms/strings.xml b/packages/SystemUI/res-keyguard/values-ms/strings.xml
index 7c8e1b8b9ba5..67500866f3d4 100644
--- a/packages/SystemUI/res-keyguard/values-ms/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ms/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Anda telah tersilap taip PIN sebanyak <xliff:g id="NUMBER_0">%1$d</xliff:g> kali. \n\nCuba lagi dalam <xliff:g id="NUMBER_1">%2$d</xliff:g> saat."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Anda telah tersilap taip kata laluan sebanyak <xliff:g id="NUMBER_0">%1$d</xliff:g> kali. \n\nCuba lagi dalam <xliff:g id="NUMBER_1">%2$d</xliff:g> saat."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Anda telah tersilap lukis corak buka kunci sebanyak <xliff:g id="NUMBER_0">%1$d</xliff:g> kali. \n\nCuba lagi dalam <xliff:g id="NUMBER_1">%2$d</xliff:g> saat."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Kod PIN SIM salah. Anda mesti menghubungi pembawa anda untuk membuka kunci peranti."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">Kod PIN SIM salah, tinggal <xliff:g id="NUMBER_1">%d</xliff:g> percubaan.</item>
diff --git a/packages/SystemUI/res-keyguard/values-my/strings.xml b/packages/SystemUI/res-keyguard/values-my/strings.xml
index 19a5c25a8e8b..3b32f06e19cd 100644
--- a/packages/SystemUI/res-keyguard/values-my/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-my/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"သင်သည် ပင်နံပါတ်ကို <xliff:g id="NUMBER_0">%1$d</xliff:g> ကြိမ်မှားယွင်းစွာ ထည့်ခဲ့ပါသည်။ \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> စက္ကန့်အကြာတွင် ထပ်စမ်းကြည့်ပါ။"</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"သင်သည် စကားဝှက်ကို <xliff:g id="NUMBER_0">%1$d</xliff:g> ကြိမ်မှားယွင်းစွာ ထည့်ခဲ့ပါသည်။ \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> စက္ကန့်အကြာတွင် ထပ်စမ်းကြည့်ပါ။"</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"သင်သည် ပုံစံကို <xliff:g id="NUMBER_0">%1$d</xliff:g> ကြိမ်မှားယွင်းစွာ ဆွဲခဲ့ပါသည်။ \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> စက္ကန့်အကြာတွင် ထပ်စမ်းကြည့်ပါ။"</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"ဆင်းမ်ကဒ်ပင်နံပါတ် မှားယွင်းနေသောကြောင့် ယခုအခါ သင့်စက်ပစ္စည်းအား လော့ခ်ဖွင့်ရန် ဝန်ဆောင်မှုပေးသူကို ဆက်သွယ်ရပါမည်။"</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">ဆင်းမ်ပင်နံပါတ် မှန်ကန်မှုမရှိပါ။ <xliff:g id="NUMBER_1">%d</xliff:g> ကြိမ် စမ်းသပ်ခွင့်ရှိပါသေးသည်။</item>
diff --git a/packages/SystemUI/res-keyguard/values-nb/strings.xml b/packages/SystemUI/res-keyguard/values-nb/strings.xml
index d5aa0e1b2009..ebd8f2922ba2 100644
--- a/packages/SystemUI/res-keyguard/values-nb/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-nb/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Du har oppgitt feil PIN-kode <xliff:g id="NUMBER_0">%1$d</xliff:g> ganger. \n\nPrøv på nytt om <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunder."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Du har tastet inn passordet ditt feil <xliff:g id="NUMBER_0">%1$d</xliff:g> ganger. \n\nPrøv på nytt om <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunder."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Du har tegnet opplåsningsmønsteret ditt feil <xliff:g id="NUMBER_0">%1$d</xliff:g> ganger. \n\nPrøv på nytt om <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunder."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Feil PIN-kode for SIM-kortet. Du må nå kontakte operatøren din for å låse opp enheten."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">Feil PIN-kode for SIM-kortet. Du har <xliff:g id="NUMBER_1">%d</xliff:g> forsøk igjen.</item>
diff --git a/packages/SystemUI/res-keyguard/values-ne/strings.xml b/packages/SystemUI/res-keyguard/values-ne/strings.xml
index 763dc035ed20..0cec32e9a90c 100644
--- a/packages/SystemUI/res-keyguard/values-ne/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ne/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"तपाईंले <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक गलत तरिकाले आफ्नो PIN प्रविष्ट गर्नुभएको छ। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> सेकेन्डमा फेरि प्रयास गर्नुहोस्।"</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"तपाईंले <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक आफ्नो गलत पासवर्ड प्रविष्ट गर्नुभएको छ। \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> सेकेन्डमा फेरि प्रयास गर्नुहोस्।"</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"तपाईंले <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक गलत तरिकाले आफ्नो अनलक ढाँचा कोर्नुभएको छ। \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> सेकेन्डमा फेरि कोसिस गर्नुहोस्।"</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"SIM को PIN कोड गलत छ। तपाईंले अब आफ्नो यन्त्र खोल्न आफ्नो सेवा प्रदायकलाई सम्पर्क गर्नै पर्ने हुन्छ।"</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">SIM को PIN कोड गलत छ, तपाईं अझै <xliff:g id="NUMBER_1">%d</xliff:g> पटक प्रयास गर्न सक्नुहुन्छ।</item>
diff --git a/packages/SystemUI/res-keyguard/values-nl/strings.xml b/packages/SystemUI/res-keyguard/values-nl/strings.xml
index 953e32d3a7c7..aa783e84b892 100644
--- a/packages/SystemUI/res-keyguard/values-nl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-nl/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Je hebt je pincode <xliff:g id="NUMBER_0">%1$d</xliff:g> keer onjuist getypt. \n\nProbeer het over <xliff:g id="NUMBER_1">%2$d</xliff:g> seconden opnieuw."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Je hebt je wachtwoord <xliff:g id="NUMBER_0">%1$d</xliff:g> keer onjuist getypt. \n\nProbeer het over <xliff:g id="NUMBER_1">%2$d</xliff:g> seconden opnieuw."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Je hebt je ontgrendelingspatroon <xliff:g id="NUMBER_0">%1$d</xliff:g> keer onjuist getekend. \n\nProbeer het over <xliff:g id="NUMBER_1">%2$d</xliff:g> seconden opnieuw."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Onjuiste pincode voor simkaart. Je moet nu contact opnemen met je provider om je apparaat te ontgrendelen."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">Onjuiste pincode voor simkaart. Je hebt nog <xliff:g id="NUMBER_1">%d</xliff:g> pogingen over.</item>
diff --git a/packages/SystemUI/res-keyguard/values-or/strings.xml b/packages/SystemUI/res-keyguard/values-or/strings.xml
index 32738d8c8e27..8bbdcf1e9eb6 100644
--- a/packages/SystemUI/res-keyguard/values-or/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-or/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"ଆପଣଙ୍କ PIN ଆପଣ <xliff:g id="NUMBER_0">%1$d</xliff:g>ଥର ଭୁଲ ଭାବେ ଟାଇପ୍‍ କରିଛନ୍ତି। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ସେକେଣ୍ଡ ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"ଆପଣଙ୍କ ପାସ୍‌ୱର୍ଡକୁ ଆପଣ <xliff:g id="NUMBER_0">%1$d</xliff:g> ଥର ଭୁଲ ଭାବେ ଟାଇପ୍ କରିଛନ୍ତି। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ସେକେଣ୍ଡ ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"ଆପଣଙ୍କ ଲକ୍‍ ଖୋଲିବା ପାଟର୍ନକୁ ଆପଣ <xliff:g id="NUMBER_0">%1$d</xliff:g>ଥର ଭୁଲ ଭାବେ ଅଙ୍କନ କରିଛନ୍ତି। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ସେକେଣ୍ଡ ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"ଭୁଲ SIM PIN କୋଡ୍‌, ଆପଣଙ୍କ ଡିଭାଇସକୁ ଅନଲକ୍‌ କରିବା ପାଇଁ ଏବେ ହିଁ ନିଜ କେରିଅର୍‌ଙ୍କ ସହ ସମ୍ପର୍କ କରନ୍ତୁ।"</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">ଭୁଲ SIM PIN କୋଡ୍, ଆପଣଙ୍କର ଆଉ <xliff:g id="NUMBER_1">%d</xliff:g>ଟି ପ୍ରୟାସ ବାକି ରହିଛି।</item>
diff --git a/packages/SystemUI/res-keyguard/values-pa/strings.xml b/packages/SystemUI/res-keyguard/values-pa/strings.xml
index c53f42fac31e..78e066526840 100644
--- a/packages/SystemUI/res-keyguard/values-pa/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pa/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"ਤੁਸੀਂ ਆਪਣਾ ਪਿੰਨ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟਾਈਪ ਕੀਤਾ ਹੈ। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਪਾਸਵਰਡ ਗਲਤ ਢੰਗ ਨਾਲ ਟਾਈਪ ਕੀਤਾ ਹੈ।\n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਅਣਲਾਕ ਪੈਟਰਨ ਗਲਤ ਢੰਗ ਨਾਲ ਉਲੀਕਿਆ ਹੈ। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"ਗਲਤ ਸਿਮ ਪਿੰਨ ਕੋਡ, ਆਪਣੇ ਡੀਵਾਈਸ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਲਈ ਹੁਣ ਤੁਹਾਨੂੰ ਲਾਜ਼ਮੀ ਤੌਰ \'ਤੇ ਆਪਣੇ ਕੈਰੀਅਰ ਨਾਲ ਸੰਪਰਕ ਕਰਨਾ ਚਾਹੀਦਾ ਹੈ।"</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="one">ਗਲਤ ਸਿਮ ਪਿੰਨ ਕੋਡ, ਤੁਹਾਡੇ ਕੋਲ <xliff:g id="NUMBER_1">%d</xliff:g> ਕੋਸ਼ਿਸ਼ ਬਾਕੀ ਹੈ।</item>
diff --git a/packages/SystemUI/res-keyguard/values-pl/strings.xml b/packages/SystemUI/res-keyguard/values-pl/strings.xml
index e3d78780feeb..9b6f857456d6 100644
--- a/packages/SystemUI/res-keyguard/values-pl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pl/strings.xml
@@ -87,14 +87,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> wpisałeś nieprawidłowy kod PIN. \n\nSpróbuj ponownie za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> wpisałeś nieprawidłowe hasło. \n\nSpróbuj ponownie za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> nieprawidłowo narysowałeś wzór odblokowania. \n\nSpróbuj ponownie za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Nieprawidłowy kod PIN karty SIM. Musisz teraz skontaktować się z operatorem, by odblokował Twoje urządzenie."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="few">Nieprawidłowy kod PIN karty SIM. Masz jeszcze <xliff:g id="NUMBER_1">%d</xliff:g> próby.</item>
diff --git a/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml
index b74aea9e42b5..cc0c044c445a 100644
--- a/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Você digitou seu PIN incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. \n\nTente novamente em <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Você digitou sua senha incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. \n\nTente novamente em <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Você desenhou sua sequência de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. \n\nTente novamente em <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Código PIN do chip incorreto. Entre em contato com a operadora para desbloquear o dispositivo."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="one">Código PIN do chip incorreto. Tentativas restantes: <xliff:g id="NUMBER_1">%d</xliff:g>.</item>
diff --git a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
index e8600c8c119d..5af8bc09a05b 100644
--- a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Introduziu o PIN incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. \n\nTente novamente dentro de <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Introduziu a palavra-passe incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. \n\nTente novamente dentro de <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Desenhou a sua padrão de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. \n\nTente novamente dentro de <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Código PIN do cartão SIM incorreto. Tem de contactar o seu operador para desbloquear o dispositivo."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">Código PIN do cartão SIM incorreto. Tem mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas.</item>
diff --git a/packages/SystemUI/res-keyguard/values-pt/strings.xml b/packages/SystemUI/res-keyguard/values-pt/strings.xml
index b74aea9e42b5..cc0c044c445a 100644
--- a/packages/SystemUI/res-keyguard/values-pt/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pt/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Você digitou seu PIN incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. \n\nTente novamente em <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Você digitou sua senha incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. \n\nTente novamente em <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Você desenhou sua sequência de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. \n\nTente novamente em <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Código PIN do chip incorreto. Entre em contato com a operadora para desbloquear o dispositivo."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="one">Código PIN do chip incorreto. Tentativas restantes: <xliff:g id="NUMBER_1">%d</xliff:g>.</item>
diff --git a/packages/SystemUI/res-keyguard/values-ro/strings.xml b/packages/SystemUI/res-keyguard/values-ro/strings.xml
index f8a39f0e8290..8122241e6613 100644
--- a/packages/SystemUI/res-keyguard/values-ro/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ro/strings.xml
@@ -86,14 +86,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Ați introdus incorect codul PIN de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori.\n\nÎncercați din nou peste <xliff:g id="NUMBER_1">%2$d</xliff:g> secunde."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Ați introdus incorect parola de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. \n\nÎncercați din nou peste <xliff:g id="NUMBER_1">%2$d</xliff:g> secunde."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Ați desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. \n\nÎncercați din nou peste <xliff:g id="NUMBER_1">%2$d</xliff:g> secunde."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Codul PIN pentru cardul SIM este incorect. Contactați operatorul pentru a vă debloca dispozitivul."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="few">Codul PIN pentru cardul SIM este incorect. V-au mai rămas <xliff:g id="NUMBER_1">%d</xliff:g> încercări.</item>
diff --git a/packages/SystemUI/res-keyguard/values-ru/strings.xml b/packages/SystemUI/res-keyguard/values-ru/strings.xml
index 4b38fdc9ce66..b80b479ca29a 100644
--- a/packages/SystemUI/res-keyguard/values-ru/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ru/strings.xml
@@ -87,14 +87,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Вы ввели неверный PIN-код несколько раз (<xliff:g id="NUMBER_0">%1$d</xliff:g>).\n\nПовторите попытку через <xliff:g id="NUMBER_1">%2$d</xliff:g> сек."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Вы ввели неверный пароль несколько раз (<xliff:g id="NUMBER_0">%1$d</xliff:g>).\n\nПовторите попытку через <xliff:g id="NUMBER_1">%2$d</xliff:g> сек."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Вы начертили неверный графический ключ несколько раз (<xliff:g id="NUMBER_0">%1$d</xliff:g>).\n\nПовторите попытку через <xliff:g id="NUMBER_1">%2$d</xliff:g> сек."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Неверный PIN-код. Обратитесь к оператору связи, чтобы разблокировать SIM-карту."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="one">Неверный PIN-код. Осталась <xliff:g id="NUMBER_1">%d</xliff:g> попытка.</item>
diff --git a/packages/SystemUI/res-keyguard/values-si/strings.xml b/packages/SystemUI/res-keyguard/values-si/strings.xml
index d64601810d49..1cd876f15d47 100644
--- a/packages/SystemUI/res-keyguard/values-si/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-si/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"ඔබ PIN අංකය <xliff:g id="NUMBER_0">%1$d</xliff:g> වාරයක් වැරදියට ටයිප් කොට ඇත.\n\n තත්පර <xliff:g id="NUMBER_1">%2$d</xliff:g> ක් ඇතුළත නැවත උත්සාහ කරන්න."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"ඔබ මුරපදය වාර <xliff:g id="NUMBER_0">%1$d</xliff:g> ක් වැරදියට ටයිප්කොට ඇත. \n\nතත්පර <xliff:g id="NUMBER_1">%2$d</xliff:g> කින් නැවත උත්සහ කරන්න."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"ඔබ <xliff:g id="NUMBER_0">%1$d</xliff:g> වාරයක් අගුළු ඇරීමේ රටාව වැරදියට ඇඳ ඇත. \n\nතත්පර <xliff:g id="NUMBER_1">%2$d</xliff:g> ක් ඇතුළත නැවත උත්සාහ කරන්න."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"වැරදී SIM PIN කේතයකි, ඔබගේ දුරකතනයේ අඟුල හැරීමට ඔබගේ වාහකයා ඔබ දැන් සම්බන්ධ කරගත යුතුය."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="one">වැරදී SIM PIN කේතයකි, ඔබගේ දුරකථනයේ අඟුල හැරීමට ඔබගේ වාහකයා සම්බන්ධ කරගැනීමට පෙර ඔබ සතුව තවත් උත්සාහයන් <xliff:g id="NUMBER_1">%d</xliff:g>ක් ඉතිරිව ඇත.</item>
diff --git a/packages/SystemUI/res-keyguard/values-sk/strings.xml b/packages/SystemUI/res-keyguard/values-sk/strings.xml
index 7be6ed20e935..801a7dbccf6d 100644
--- a/packages/SystemUI/res-keyguard/values-sk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sk/strings.xml
@@ -87,14 +87,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Už <xliff:g id="NUMBER_0">%1$d</xliff:g>-krát ste zadali nesprávny kód PIN. \n\nSkúste to znova o <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Už <xliff:g id="NUMBER_0">%1$d</xliff:g>-krát ste zadali nesprávne heslo. \n\nSkúste to znova o <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Už <xliff:g id="NUMBER_0">%1$d</xliff:g>-krát ste použili nesprávny bezpečnostný vzor. \n\nSkúste to znova o <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Nesprávny kód PIN SIM karty. Teraz musíte kontaktovať svojho operátora, aby vám odomkol zariadenie."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="few">Nesprávny kód PIN SIM karty. Zostávajú vám <xliff:g id="NUMBER_1">%d</xliff:g> pokusy.</item>
diff --git a/packages/SystemUI/res-keyguard/values-sl/strings.xml b/packages/SystemUI/res-keyguard/values-sl/strings.xml
index 6286d10ae40c..a141ed7ffaa6 100644
--- a/packages/SystemUI/res-keyguard/values-sl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sl/strings.xml
@@ -87,14 +87,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Kodo PIN ste <xliff:g id="NUMBER_0">%1$d</xliff:g>-krat vnesli napačno. \n\nPoskusite znova čez <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Geslo ste <xliff:g id="NUMBER_0">%1$d</xliff:g>-krat vnesli napačno. \n\nPoskusite znova čez <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Vzorec za odklepanje ste <xliff:g id="NUMBER_0">%1$d</xliff:g>-krat nepravilno narisali. \n\nPoskusite znova čez <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Napačna koda PIN kartice SIM. Zdaj se boste morali za odklenitev naprave obrniti na operaterja."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="one">Napačna koda PIN kartice SIM. Na voljo imate še <xliff:g id="NUMBER_1">%d</xliff:g> poskus.</item>
diff --git a/packages/SystemUI/res-keyguard/values-sq/strings.xml b/packages/SystemUI/res-keyguard/values-sq/strings.xml
index 3980b0eb98dc..1d34e3f8e099 100644
--- a/packages/SystemUI/res-keyguard/values-sq/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sq/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"E ke shkruar <xliff:g id="NUMBER_0">%1$d</xliff:g> herë gabimisht kodin PIN.\n\nProvo sërish për <xliff:g id="NUMBER_1">%2$d</xliff:g> sekonda."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"E ke shkruar <xliff:g id="NUMBER_0">%1$d</xliff:g> herë gabimisht fjalëkalimin.\n\nProvo sërish për <xliff:g id="NUMBER_1">%2$d</xliff:g> sekonda."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Ke tentuar <xliff:g id="NUMBER_0">%1$d</xliff:g> herë pa sukses për të vizatuar motivin tënd. \n\nProvo sërish për <xliff:g id="NUMBER_1">%2$d</xliff:g> sekonda."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Kodi PIN i kartës SIM është i pasaktë. Tani duhet të kontaktosh me operatorin për ta shkyçur pajisjen tënde."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">Kodi PIN i kartës SIM është i pasaktë. Të kanë mbetur edhe <xliff:g id="NUMBER_1">%d</xliff:g> tentativa.</item>
diff --git a/packages/SystemUI/res-keyguard/values-sr/strings.xml b/packages/SystemUI/res-keyguard/values-sr/strings.xml
index 9d5ed2831dba..f83df3f8925e 100644
--- a/packages/SystemUI/res-keyguard/values-sr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sr/strings.xml
@@ -86,14 +86,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Унели сте погрешан PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. \n\nПробајте поново за <xliff:g id="NUMBER_1">%2$d</xliff:g> сек."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Унели сте погрешну лозинку <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. \n\nПробајте поново за <xliff:g id="NUMBER_1">%2$d</xliff:g> сек."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Нацртали сте нетачан шаблон за откључавање <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. \n\nПробајте поново за <xliff:g id="NUMBER_1">%2$d</xliff:g> сек."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Нетачан PIN кôд за SIM. Сада морате да контактирате мобилног оператера да бисте откључали уређај."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="one">Нетачан PIN кôд за SIM. Имате још <xliff:g id="NUMBER_1">%d</xliff:g> покушај.</item>
diff --git a/packages/SystemUI/res-keyguard/values-sv/strings.xml b/packages/SystemUI/res-keyguard/values-sv/strings.xml
index 595f4118e3e6..a037bffa4da2 100644
--- a/packages/SystemUI/res-keyguard/values-sv/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sv/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Du har angett fel pinkod <xliff:g id="NUMBER_0">%1$d</xliff:g> gånger. \n\nFörsök igen om <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunder."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Du har angett fel lösenord <xliff:g id="NUMBER_0">%1$d</xliff:g> gånger. \n\nFörsök igen om <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunder."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Du har ritat ditt grafiska lösenord fel <xliff:g id="NUMBER_0">%1$d</xliff:g> gånger. \n\nFörsök igen om <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunder."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Du angav fel pinkod för SIM-kortet och måste nu kontakta operatören för att låsa upp enheten."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">Du angav fel pinkod för SIM-kortet. <xliff:g id="NUMBER_1">%d</xliff:g> försök återstår.</item>
diff --git a/packages/SystemUI/res-keyguard/values-sw/strings.xml b/packages/SystemUI/res-keyguard/values-sw/strings.xml
index cb6409e2eed1..efa5ecfd44fd 100644
--- a/packages/SystemUI/res-keyguard/values-sw/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sw/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Umeandika vibaya PIN mara <xliff:g id="NUMBER_0">%1$d</xliff:g>. \n\n Jaribu tena baada ya sekunde <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Umeandika vibaya nenosiri lako mara <xliff:g id="NUMBER_0">%1$d</xliff:g>. \n\n Jaribu tena baada ya sekunde <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Umechora vibaya mchoro wako wa kufungua mara <xliff:g id="NUMBER_0">%1$d</xliff:g>. \n\n Jaribu tena baada ya sekunde <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Nambari ya PIN ya SIM si sahihi, sasa lazima uwasiliane na mtoa huduma za mtandao ndipo ufungue kifaa chako."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">Nambari ya PIN ya SIM si sahihi. Una nafasi zingine <xliff:g id="NUMBER_1">%d</xliff:g> za kujaribu.</item>
diff --git a/packages/SystemUI/res-keyguard/values-ta/strings.xml b/packages/SystemUI/res-keyguard/values-ta/strings.xml
index 63e1a1e78eec..96dbbb0314d6 100644
--- a/packages/SystemUI/res-keyguard/values-ta/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ta/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"உங்கள் பின்னை <xliff:g id="NUMBER_0">%1$d</xliff:g> முறை தவறாக உள்ளிட்டுவிட்டீர்கள். \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> வினாடிகளில் மீண்டும் முயலவும்."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"உங்கள் கடவுச்சொல்லை <xliff:g id="NUMBER_0">%1$d</xliff:g> முறை தவறாக உள்ளிட்டுவிட்டீர்கள். \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> வினாடிகளில் மீண்டும் முயலவும்."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"திறப்பதற்கான பேட்டர்னை, <xliff:g id="NUMBER_0">%1$d</xliff:g> முறை தவறாக வரைந்துவிட்டீர்கள். \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> வினாடிகளில் மீண்டும் முயலவும்."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"சிம்மின் பின் குறியீடு தவறானது. இனி சாதனத்தைத் திறக்க, உங்கள் தொலைத்தொடர்பு நிறுவனத்தைத் தொடர்புகொள்ள வேண்டும்."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">சிம்மின் பின் குறியீடு தவறானது, இன்னும் நீங்கள் <xliff:g id="NUMBER_1">%d</xliff:g> முறை முயலலாம்.</item>
diff --git a/packages/SystemUI/res-keyguard/values-te/strings.xml b/packages/SystemUI/res-keyguard/values-te/strings.xml
index a2f45c9740b1..74386bc7a487 100644
--- a/packages/SystemUI/res-keyguard/values-te/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-te/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"మీరు మీ పిన్‌ను <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా టైప్ చేసారు. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"మీరు మీ పాస్‌వర్డ్‌ను <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా టైప్ చేసారు. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"మీరు మీ అన్‌లాక్ నమూనాను <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా గీసారు. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"SIM పిన్ కోడ్ తప్పు, ఇప్పుడు మీ డివైజ్‌ను అన్‌లాక్ చేయాలంటే, మీరు తప్పనిసరిగా మీ క్యారియర్‌ను సంప్రదించాలి."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">SIM పిన్ కోడ్ తప్పు, మీకు మరో <xliff:g id="NUMBER_1">%d</xliff:g> ప్రయత్నాలు మిగిలి ఉన్నాయి.</item>
diff --git a/packages/SystemUI/res-keyguard/values-th/strings.xml b/packages/SystemUI/res-keyguard/values-th/strings.xml
index ce40efb8a808..aa9e693db0fa 100644
--- a/packages/SystemUI/res-keyguard/values-th/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-th/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"คุณพิมพ์ PIN ไม่ถูกต้อง <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้งแล้ว \n\nโปรดลองอีกครั้งใน <xliff:g id="NUMBER_1">%2$d</xliff:g> วินาที"</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"คุณพิมพ์รหัสผ่านไม่ถูกต้อง <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้งแล้ว \n\nโปรดลองอีกครั้งใน <xliff:g id="NUMBER_1">%2$d</xliff:g> วินาที"</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"คุณวาดรูปแบบการปลดล็อกไม่ถูกต้อง <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้งแล้ว \n\nโปรดลองอีกครั้งในอีก <xliff:g id="NUMBER_1">%2$d</xliff:g> วินาที"</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"รหัส PIN ของซิมไม่ถูกต้อง ตอนนี้คุณต้องติดต่อผู้ให้บริการเพื่อปลดล็อกอุปกรณ์ของคุณ"</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">รหัส PIN ของซิมไม่ถูกต้อง คุณพยายามได้อีก <xliff:g id="NUMBER_1">%d</xliff:g> ครั้ง</item>
diff --git a/packages/SystemUI/res-keyguard/values-tl/strings.xml b/packages/SystemUI/res-keyguard/values-tl/strings.xml
index 15f9616b0d85..7b7e17dc8dcb 100644
--- a/packages/SystemUI/res-keyguard/values-tl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-tl/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Na-type mo nang mali ang iyong PIN nang <xliff:g id="NUMBER_0">%1$d</xliff:g> (na) beses. \n\nSubukang muli sa loob ng <xliff:g id="NUMBER_1">%2$d</xliff:g> (na) segundo."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Na-type mo nang hindi tama ang iyong password nang <xliff:g id="NUMBER_0">%1$d</xliff:g> (na) beses. \n\nSubukang muli sa loob ng <xliff:g id="NUMBER_1">%2$d</xliff:g> (na) segundo."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Naguhit mo nang hindi tama ang iyong pattern sa pag-unlock nang <xliff:g id="NUMBER_0">%1$d</xliff:g> (na) beses. \n\nSubukang muli sa loob ng <xliff:g id="NUMBER_1">%2$d</xliff:g> (na) segundo."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Mali ang PIN code ng SIM, dapat ka nang makipag-ugnayan sa iyong carrier upang i-unlock ang iyong device."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="one">Mali ang PIN code ng SIM, mayroon kang <xliff:g id="NUMBER_1">%d</xliff:g> natitirang pagsubok.</item>
diff --git a/packages/SystemUI/res-keyguard/values-tr/strings.xml b/packages/SystemUI/res-keyguard/values-tr/strings.xml
index 2ddf26eaf83a..8c0caead0bdb 100644
--- a/packages/SystemUI/res-keyguard/values-tr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-tr/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"PIN kodunuzu <xliff:g id="NUMBER_0">%1$d</xliff:g> kez yanlış girdiniz. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> saniye içinde tekrar deneyin."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Şifrenizi <xliff:g id="NUMBER_0">%1$d</xliff:g> kez yanlış yazdınız. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> saniye içinde tekrar deneyin."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Kilit açma deseninizi <xliff:g id="NUMBER_0">%1$d</xliff:g> kez yanlış çizdiniz. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> saniye içinde tekrar deneyin."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Yanlış SIM PIN kodu. Cihazınızın kilidini açmak için artık operatörünüzle bağlantı kurmanız gerekiyor."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">Yanlış SIM PIN kodu, <xliff:g id="NUMBER_1">%d</xliff:g> deneme hakkınız kaldı.</item>
diff --git a/packages/SystemUI/res-keyguard/values-uk/strings.xml b/packages/SystemUI/res-keyguard/values-uk/strings.xml
index fd157454dd1a..6e5ce0f142dc 100644
--- a/packages/SystemUI/res-keyguard/values-uk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-uk/strings.xml
@@ -87,14 +87,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"PIN-код неправильно введено стільки разів: <xliff:g id="NUMBER_0">%1$d</xliff:g>. \n\nПовторіть спробу через <xliff:g id="NUMBER_1">%2$d</xliff:g> с."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Пароль неправильно введено стільки разів: <xliff:g id="NUMBER_0">%1$d</xliff:g>. \n\nПовторіть спробу через <xliff:g id="NUMBER_1">%2$d</xliff:g> с."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Ключ розблокування неправильно намальовано стільки разів: <xliff:g id="NUMBER_0">%1$d</xliff:g>. \n\nПовторіть спробу через <xliff:g id="NUMBER_1">%2$d</xliff:g> с."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Неправильний PIN-код SIM-карти. Зв’яжіться зі своїм оператором, щоб розблокувати пристрій."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="one">Неправильний PIN-код SIM-карти. У вас залишилася <xliff:g id="NUMBER_1">%d</xliff:g> спроба.</item>
diff --git a/packages/SystemUI/res-keyguard/values-ur/strings.xml b/packages/SystemUI/res-keyguard/values-ur/strings.xml
index 04d29c60d5f3..7b946aaf40da 100644
--- a/packages/SystemUI/res-keyguard/values-ur/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ur/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"‏آپ نے اپنا PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> بار غلط طریقے سے ٹائپ کیا ہے۔ \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> سیکنڈ میں دوبارہ کوشش کریں۔"</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"آپ نے اپنا پاسورڈ <xliff:g id="NUMBER_0">%1$d</xliff:g> بار غلط طریقے سے ٹائپ کیا ہے۔ \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> سیکنڈ میں دوبارہ کوشش کریں۔"</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"آپ نے اپنا غیر مقفل کرنے کا پیٹرن <xliff:g id="NUMBER_0">%1$d</xliff:g> بار غلط طریقے سے ڈرا کیا ہے۔ \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> سیکنڈ میں دوبارہ کوشش کریں۔"</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"‏غلط SIM PIN کوڈ، اب آپ کو اپنا آلہ غیر مقفل کرنے کیلئے اپنے کیریئر سے رابطہ کرنا ہوگا۔"</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">‏غلط SIM PIN کوڈ، آپ کے پاس <xliff:g id="NUMBER_1">%d</xliff:g> کوششیں بچی ہیں۔</item>
diff --git a/packages/SystemUI/res-keyguard/values-uz/strings.xml b/packages/SystemUI/res-keyguard/values-uz/strings.xml
index ce461febc775..a6c2aa055c0b 100644
--- a/packages/SystemUI/res-keyguard/values-uz/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-uz/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"PIN kod <xliff:g id="NUMBER_0">%1$d</xliff:g> marta xato kiritildi. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> soniyadan keyin qaytadan urining."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Parol <xliff:g id="NUMBER_0">%1$d</xliff:g> marta xato kiritildi. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> soniyadan keyin qaytadan urining."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Grafik kalit <xliff:g id="NUMBER_0">%1$d</xliff:g> marta xato kiritildi. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> soniyadan keyin qayta urining."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"SIM kartaning PIN kodi xato. Qurilma qulfini ochish uchun operatoringizga murojaat qiling."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">SIM kartaning PIN kodi noto‘g‘ri. Sizda yana <xliff:g id="NUMBER_1">%d</xliff:g> ta urinish qoldi.</item>
diff --git a/packages/SystemUI/res-keyguard/values-vi/strings.xml b/packages/SystemUI/res-keyguard/values-vi/strings.xml
index 3ac2cd263461..31737fca5e4d 100644
--- a/packages/SystemUI/res-keyguard/values-vi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-vi/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Bạn đã nhập sai mã PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> lần. \n\nHãy thử lại sau <xliff:g id="NUMBER_1">%2$d</xliff:g> giây."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Bạn đã nhập sai mật khẩu <xliff:g id="NUMBER_0">%1$d</xliff:g> lần. \n\nHãy thử lại sau <xliff:g id="NUMBER_1">%2$d</xliff:g> giây."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Bạn đã vẽ không chính xác hình mở khóa <xliff:g id="NUMBER_0">%1$d</xliff:g> lần. \n\nHãy thử lại sau <xliff:g id="NUMBER_1">%2$d</xliff:g> giây."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Mã PIN của SIM không chính xác, bây giờ bạn phải liên hệ với nhà cung cấp dịch vụ để mở khóa thiết bị của mình."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">Mã PIN của SIM không chính xác, bạn còn <xliff:g id="NUMBER_1">%d</xliff:g> lần thử.</item>
diff --git a/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml
index 0d979466d1b8..b4bff5fab6d6 100644
--- a/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"您已经 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次输错 PIN 码。\n\n请在 <xliff:g id="NUMBER_1">%2$d</xliff:g> 秒后重试。"</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"您已经 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次输错密码。\n\n请在 <xliff:g id="NUMBER_1">%2$d</xliff:g> 秒后重试。"</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"您已经 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次画错解锁图案。\n\n请在 <xliff:g id="NUMBER_1">%2$d</xliff:g> 秒后重试。"</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"SIM 卡 PIN 码不正确,您现在必须联系运营商为您解锁设备。"</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">SIM 卡 PIN 码不正确,您还有 <xliff:g id="NUMBER_1">%d</xliff:g> 次尝试机会。</item>
diff --git a/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml
index 1f55b32dfa0d..b3d387706fa5 100644
--- a/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"您已輸入錯誤的 PIN 碼 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次。\n\n請在 <xliff:g id="NUMBER_1">%2$d</xliff:g> 秒後再試一次。"</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"您已輸入錯誤的密碼 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次。\n\n請在 <xliff:g id="NUMBER_1">%2$d</xliff:g> 秒後再試一次。"</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"您已畫錯解鎖圖案 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次。\n\n請在 <xliff:g id="NUMBER_1">%2$d</xliff:g> 秒後再試一次。"</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"SIM 卡 PIN 碼不正確,您現在必須聯絡流動網絡供應商為您的裝置解鎖。"</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">SIM 卡的 PIN 碼不正確,您還有 <xliff:g id="NUMBER_1">%d</xliff:g> 次輸入機會。</item>
diff --git a/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml
index 97653c9e4d89..03dec4852771 100644
--- a/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"你已輸入錯誤的 PIN 碼 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次。\n\n請在 <xliff:g id="NUMBER_1">%2$d</xliff:g> 秒後再試一次。"</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"你已輸入錯誤的密碼 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次。\n\n請在 <xliff:g id="NUMBER_1">%2$d</xliff:g> 秒後再試一次。"</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"你已畫出錯誤的解鎖圖案 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次。\n\n請在 <xliff:g id="NUMBER_1">%2$d</xliff:g> 秒後再試一次。"</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"SIM 卡的 PIN 碼輸入錯誤,你現在必須請電信業者為裝置解鎖。"</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="other">SIM 卡的 PIN 碼輸入錯誤,你還可以再試 <xliff:g id="NUMBER_1">%d</xliff:g> 次。</item>
diff --git a/packages/SystemUI/res-keyguard/values-zu/strings.xml b/packages/SystemUI/res-keyguard/values-zu/strings.xml
index fe81d02acb93..5ab567f706c3 100644
--- a/packages/SystemUI/res-keyguard/values-zu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zu/strings.xml
@@ -85,14 +85,6 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Ubhale iphinikhodi ykho ngendlela engafanele izikhathi ezingu-<xliff:g id="NUMBER_0">%1$d</xliff:g>. \n\nZama futhi emasekhondini angu-<xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Ubhale iphasiwedi yakho ngendlela engafanele <xliff:g id="NUMBER_0">%1$d</xliff:g> izikhathi. \n\nZama futhi emasekhondini angu-<xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Udwebe iphathini yakho yokuvula ngendlela engafanele-<xliff:g id="NUMBER_0">%1$d</xliff:g>. \n\n Zama futhi emasekhondini angu-<xliff:g id="NUMBER_1">%2$d</xliff:g>"</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip />
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip />
<string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Ikhodi yephinikhodi ye-SIM engalungile manje kumele uxhumane nenkampini yenethiwekhi yakho ukuvula idivayisi yakho."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
<item quantity="one">Ikhodi engalungile yephinikhodi ye-SIM, unemizamo engu-<xliff:g id="NUMBER_1">%d</xliff:g> esele.</item>
diff --git a/packages/SystemUI/res-product/values-af/strings.xml b/packages/SystemUI/res-product/values-af/strings.xml
index 61ccec87f23b..9b99a4faaac5 100644
--- a/packages/SystemUI/res-product/values-af/strings.xml
+++ b/packages/SystemUI/res-product/values-af/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -16,42 +17,27 @@
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"Geen SIM-kaart in tablet nie."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"Geen SIM-kaart in foon nie."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"PIN-kodes stem nie ooreen nie"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Jy het die tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> keer verkeerd probeer ontsluit. Na nóg <xliff:g id="NUMBER_1">%2$d</xliff:g> onsuksesvolle pogings sal hierdie tablet teruggestel word, wat al sy data sal uitvee."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Jy het die foon <xliff:g id="NUMBER_0">%1$d</xliff:g> keer verkeerd probeer ontsluit. Na nóg <xliff:g id="NUMBER_1">%2$d</xliff:g> onsuksesvolle pogings sal hierdie foon teruggestel word, wat al sy data sal uitvee."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Jy het die tablet <xliff:g id="NUMBER">%d</xliff:g> keer verkeerd probeer ontsluit. Hierdie tablet sal teruggestel word, wat al sy data sal uitvee."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Jy het die foon <xliff:g id="NUMBER">%d</xliff:g> keer verkeerd probeer ontsluit. Hierdie foon sal teruggestel word, wat al sy data sal uitvee."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Jy het die tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> keer verkeerd probeer ontsluit. Na nóg <xliff:g id="NUMBER_1">%2$d</xliff:g> onsuksesvolle pogings sal hierdie gebruiker verwyder word, wat alle gebruikerdata sal uitvee."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Jy het die foon <xliff:g id="NUMBER_0">%1$d</xliff:g> keer verkeerd probeer ontsluit. Na nóg <xliff:g id="NUMBER_1">%2$d</xliff:g> onsuksesvolle pogings sal hierdie gebruiker verwyder word, wat alle gebruikerdata sal uitvee."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Die Android TV-toestel gaan binnekort afskakel; druk \'n knoppie om dit aan te hou."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Die toestel gaan binnekort afskakel; druk om dit aan te hou."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Jy het die tablet <xliff:g id="NUMBER">%d</xliff:g> keer verkeerd probeer ontsluit. Die werkprofiel sal verwyder word, wat alle profieldata sal uitvee."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Jy het die foon <xliff:g id="NUMBER">%d</xliff:g> keer verkeerd probeer ontsluit. Die werkprofiel sal verwyder word, wat alle profieldata sal uitvee."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Jy het jou ontsluitpatroon <xliff:g id="NUMBER_0">%1$d</xliff:g> keer verkeerd geteken. Na nóg <xliff:g id="NUMBER_1">%2$d</xliff:g> onsuksesvolle pogings sal jy gevra word om jou e-posrekening te gebruik om jou tablet te ontsluit.\n\n Probeer weer oor <xliff:g id="NUMBER_2">%3$d</xliff:g> sekondes."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Jy het jou ontsluitpatroon <xliff:g id="NUMBER_0">%1$d</xliff:g> keer verkeerd geteken. Na nóg <xliff:g id="NUMBER_1">%2$d</xliff:g> onsuksesvolle pogings sal jy gevra word om jou e-posrekening te gebruik om jou foon te ontsluit.\n\n Probeer weer oor <xliff:g id="NUMBER_2">%3$d</xliff:g> sekondes."</string>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Herbelyn foon om vinniger te laai"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Herbelyn foon om draadloos te laai"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Die Android TV-toestel sal binnekort afskakel; druk \'n knoppie om dit aan te hou."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Die toestel gaan binnekort afskakel; druk om dit aan te hou."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Geen SIM-kaart in tablet nie."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Geen SIM-kaart in foon nie."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"PIN-kodes stem nie ooreen nie"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Jy het die tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> keer verkeerd probeer ontsluit. Na nóg <xliff:g id="NUMBER_1">%2$d</xliff:g> onsuksesvolle pogings sal hierdie tablet teruggestel word, wat al sy data sal uitvee."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Jy het die foon <xliff:g id="NUMBER_0">%1$d</xliff:g> keer verkeerd probeer ontsluit. Na nóg <xliff:g id="NUMBER_1">%2$d</xliff:g> onsuksesvolle pogings sal hierdie foon teruggestel word, wat al sy data sal uitvee."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Jy het die tablet <xliff:g id="NUMBER">%d</xliff:g> keer verkeerd probeer ontsluit. Hierdie tablet sal teruggestel word, wat al sy data sal uitvee."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Jy het die foon <xliff:g id="NUMBER">%d</xliff:g> keer verkeerd probeer ontsluit. Hierdie foon sal teruggestel word, wat al sy data sal uitvee."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Jy het die tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> keer verkeerd probeer ontsluit. Na nóg <xliff:g id="NUMBER_1">%2$d</xliff:g> onsuksesvolle pogings sal hierdie gebruiker verwyder word, wat alle gebruikerdata sal uitvee."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Jy het die foon <xliff:g id="NUMBER_0">%1$d</xliff:g> keer verkeerd probeer ontsluit. Na nóg <xliff:g id="NUMBER_1">%2$d</xliff:g> onsuksesvolle pogings sal hierdie gebruiker verwyder word, wat alle gebruikerdata sal uitvee."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Jy het die tablet <xliff:g id="NUMBER">%d</xliff:g> keer verkeerd probeer ontsluit. Hierdie gebruiker sal verwyder word, wat alle gebruikerdata sal uitvee."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Jy het die foon <xliff:g id="NUMBER">%d</xliff:g> keer verkeerd probeer ontsluit. Hierdie gebruiker sal verwyder word, wat alle gebruikerdata sal uitvee."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Jy het die tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> keer verkeerd probeer ontsluit. Na nóg <xliff:g id="NUMBER_1">%2$d</xliff:g> onsuksesvolle pogings sal die werkprofiel verwyder word, wat alle profieldata sal uitvee."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Jy het die foon <xliff:g id="NUMBER_0">%1$d</xliff:g> keer verkeerd probeer ontsluit. Na nóg <xliff:g id="NUMBER_1">%2$d</xliff:g> onsuksesvolle pogings sal die werkprofiel verwyder word, wat alle profieldata sal uitvee."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Jy het die tablet <xliff:g id="NUMBER">%d</xliff:g> keer verkeerd probeer ontsluit. Die werkprofiel sal verwyder word, wat alle profieldata sal uitvee."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Jy het die foon <xliff:g id="NUMBER">%d</xliff:g> keer verkeerd probeer ontsluit. Die werkprofiel sal verwyder word, wat alle profieldata sal uitvee."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Jy het jou ontsluitpatroon <xliff:g id="NUMBER_0">%1$d</xliff:g> keer verkeerd geteken. Na nóg <xliff:g id="NUMBER_1">%2$d</xliff:g> onsuksesvolle pogings sal jy gevra word om jou e-posrekening te gebruik om jou tablet te ontsluit.\n\n Probeer weer oor <xliff:g id="NUMBER_2">%3$d</xliff:g> sekondes."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Jy het jou ontsluitpatroon <xliff:g id="NUMBER_0">%1$d</xliff:g> keer verkeerd geteken. Na nóg <xliff:g id="NUMBER_1">%2$d</xliff:g> onsuksesvolle pogings sal jy gevra word om jou e-posrekening te gebruik om jou foon te ontsluit.\n\n Probeer weer oor <xliff:g id="NUMBER_2">%3$d</xliff:g> sekondes."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-am/strings.xml b/packages/SystemUI/res-product/values-am/strings.xml
index 4628b2b93b9a..4da032934a83 100644
--- a/packages/SystemUI/res-product/values-am/strings.xml
+++ b/packages/SystemUI/res-product/values-am/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"በጡባዊ ውስጥ ምንም ሲም ካርድ የለም።"</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"በስልክ ውስጥ ምንም ሲም ካርድ የለም።"</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"ፒን ኮዶቹ አይገጣጠሙም"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"ጡባዊውን <xliff:g id="NUMBER_0">%1$d</xliff:g> ጊዜ ትክክል ባልሆነ መልኩ ለማስከፈት ሞክረዋል። ከ<xliff:g id="NUMBER_1">%2$d</xliff:g> ተጨማሪ ያልተሳኩ ሙከራዎች በኋላ ይህ ጡባዊ ዳግም ይጀመራል፣ ይህም ሁሉንም ውሂብ ይሰርዛል።"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"ስልኩን <xliff:g id="NUMBER_0">%1$d</xliff:g> ጊዜ ትክክል ባልሆነ መልኩ ለማስከፈት ሞክረዋል። ከ<xliff:g id="NUMBER_1">%2$d</xliff:g> ተጨማሪ ያልተሳኩ ሙከራዎች በኋላ ይህ ስልክ ዳግም ይጀመራል፣ ይህም ሁሉንም ውሂብ ይሰርዛል።"</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"ጡባዊውን <xliff:g id="NUMBER">%d</xliff:g> ጊዜ ትክክል ባልሆነ ሁኔታ ለማስከፈት ሞክረዋል። ስልኩ ዳግም ይጀመራል፣ ይህም ሁሉንም ውሂቡን ይሰርዛል።"</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"ስልኩን <xliff:g id="NUMBER">%d</xliff:g> ጊዜ ትክክል ባልሆነ ሁኔታ ለማስከፈት ሞክረዋል። ስልኩ ዳግም ይጀመራል፣ ይህም ሁሉንም ውሂቡን ይሰርዛል።"</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"ጡባዊውን <xliff:g id="NUMBER_0">%1$d</xliff:g> ጊዜ ትክክል ባልሆነ መልኩ ለማስከፈት ሞክረዋል። ከ<xliff:g id="NUMBER_1">%2$d</xliff:g> ተጨማሪ ያልተሳኩ ሙከራዎች በኋላ ይህ ተጠቃሚ ይወገዳል፣ ይህም ሁሉንም የተጠቃሚ ውሂብ ይሰርዛል።"</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"ስልኩን <xliff:g id="NUMBER_0">%1$d</xliff:g> ጊዜ ትክክል ባልሆነ መልኩ ለማስከፈት ሞክረዋል። ከ<xliff:g id="NUMBER_1">%2$d</xliff:g> ተጨማሪ ያልተሳኩ ሙከራዎች በኋላ ይህ ተጠቃሚ ይወገዳል፣ ይህም ሁሉንም የተጠቃሚ ውሂብ ይሰርዛል።"</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"የAndroid TV መሣሪያው በቅርቡ ይጠፋል፣ እንደበራ ለማቆየት ይጫኑ።"</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"መሣሪያው በቅርቡ ይጠፋል፤ እንደበራ ለማቆየት ይጫኑ።"</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"ጡባዊውን <xliff:g id="NUMBER">%d</xliff:g> ጊዜ ትክክል ባልሆነ መልኩ ለመክፈት ሞክረዋል። የስራ መገለጫው ይወገዳል፣ ይህም ሁሉንም የመገለጫ ውሂብ ይሰርዛል።"</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"ስልኩን <xliff:g id="NUMBER">%d</xliff:g> ጊዜ ትክክል ባልሆነ መልኩ ለመክፈት ሞክረዋል። የስራ መገለጫው ይወገዳል፣ ይህም ሁሉንም የመገለጫ ውሂብ ይሰርዛል።"</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"የመክፈቻ ስርዓተ ጥለቱን <xliff:g id="NUMBER_0">%1$d</xliff:g> ጊዜ በትክክል አልሳሉትም። ከ<xliff:g id="NUMBER_1">%2$d</xliff:g> ተጨማሪ ያልተሳኩ ሙከራዎች በኋላ የኢሜይል መለያ ተጠቅመው ጡባዊዎን እንዲከፍቱ ይጠየቃሉ።\n\n ከ<xliff:g id="NUMBER_2">%3$d</xliff:g> ከሰከንዶች በኋላ እንደገና ይሞክሩ።"</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"የመክፈቻ ስርዓተ ጥለቱን <xliff:g id="NUMBER_0">%1$d</xliff:g> ጊዜ በትክክል አልሳሉትም። ከ<xliff:g id="NUMBER_1">%2$d</xliff:g> ተጨማሪ ያልተሳኩ ሙከራዎች በኋላ የኢሜይል መለያ ተጠቅመው ስልክዎን እንዲከፍቱ ይጠየቃሉ።\n\nእባክዎ ከ<xliff:g id="NUMBER_2">%3$d</xliff:g> ሰከንዶች በኋላ እንደገና ይሞክሩ።"</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"በፍጥነት ኃይል ለመሙላት ስልኩን ዳግም ያሰልፉት"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"ያለገመድ ኃይል ለመሙላት ስልኩን ዳግም ያሰልፉት"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"የAndroid TV መሣሪያው በቅርቡ ይጠፋል፤ እንደበራ ለማቆየት ይጫኑ።"</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"መሣሪያው በቅርቡ ይጠፋል፤ እንደበራ ለማቆየት ይጫኑ።"</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"በጡባዊ ውስጥ ምንም ሲም ካርድ የለም።"</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"በስልክ ውስጥ ምንም ሲም ካርድ የለም።"</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"የፒን ኮዶቹ አይዛመዱም"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"ጡባዊውን <xliff:g id="NUMBER_0">%1$d</xliff:g> ጊዜ ትክክል ባልሆነ መልኩ ለማስከፈት ሞክረዋል። ከ<xliff:g id="NUMBER_1">%2$d</xliff:g> ተጨማሪ ያልተሳኩ ሙከራዎች በኋላ ይህ ጡባዊ ዳግም ይጀመራል፣ ይህም ሁሉንም ውሂብ ይሰርዛል።"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"ስልኩን <xliff:g id="NUMBER_0">%1$d</xliff:g> ጊዜ ትክክል ባልሆነ መልኩ ለመክፈት ሞክረዋል። ከ<xliff:g id="NUMBER_1">%2$d</xliff:g> ተጨማሪ ያልተሳኩ ሙከራዎች በኋላ ይህ ስልክ ዳግም ይጀመራል፣ ይህም ሁሉንም ውሂብ ይሰርዛል።"</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"ጡባዊውን <xliff:g id="NUMBER">%d</xliff:g> ጊዜ ትክክል ባልሆነ ሁኔታ ለመክፈት ሞክረዋል። ስልኩ ዳግም ይጀመራል፣ ይህም ሁሉንም ውሂቡን ይሰርዛል።"</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"ስልኩን <xliff:g id="NUMBER">%d</xliff:g> ጊዜ ትክክል ባልሆነ ሁኔታ ለማስከፈት ሞክረዋል። ስልኩ ዳግም ይጀመራል፣ ይህም ሁሉንም ውሂቡን ይሰርዛል።"</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"ጡባዊውን <xliff:g id="NUMBER_0">%1$d</xliff:g> ጊዜ ትክክል ባልሆነ መልኩ ለመክፈት ሞክረዋል። ከ<xliff:g id="NUMBER_1">%2$d</xliff:g> ተጨማሪ ያልተሳኩ ሙከራዎች በኋላ ይህ ተጠቃሚ ይወገዳል፣ ይህም ሁሉንም የተጠቃሚ ውሂብ ይሰርዛል።"</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"ስልኩን <xliff:g id="NUMBER_0">%1$d</xliff:g> ጊዜ ትክክል ባልሆነ መልኩ ለመክፈት ሞክረዋል። ከ<xliff:g id="NUMBER_1">%2$d</xliff:g> ተጨማሪ ያልተሳኩ ሙከራዎች በኋላ ይህ ተጠቃሚ ይወገዳል፣ ይህም ሁሉንም የተጠቃሚ ውሂብ ይሰርዛል።"</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"ጡባዊውን <xliff:g id="NUMBER">%d</xliff:g> ጊዜ ትክክል ባልሆነ መልኩ ለመክፈት ሞክረዋል። ይህ ተጠቃሚ ይወገዳል፣ ይህም ሁሉንም የተጠቃሚ ውሂብ ይሰርዛል።"</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"ስልኩን <xliff:g id="NUMBER">%d</xliff:g> ጊዜ ትክክል ባልሆነ መልኩ ለማስከፈት ሞክረዋል። ይህ ተጠቃሚ ይወገዳል፣ ይህም ሁሉንም የተጠቃሚ ውሂብ ይሰርዛል።"</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"ጡባዊውን <xliff:g id="NUMBER_0">%1$d</xliff:g> ጊዜ ትክክል ባልሆነ መልኩ ለመክፈት ሞክረዋል። ከ<xliff:g id="NUMBER_1">%2$d</xliff:g> ተጨማሪ ያልተሳኩ ሙከራዎች በኋላ የስራ መገለጫው ይወገዳል፣ ይህም ሁሉንም የመገለጫ ውሂብ ይሰርዛል።"</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"ስልኩን <xliff:g id="NUMBER_0">%1$d</xliff:g> ጊዜ ትክክል ባልሆነ መልኩ ለመክፈት ሞክረዋል። ከ<xliff:g id="NUMBER_1">%2$d</xliff:g> ተጨማሪ ያልተሳኩ ሙከራዎች በኋላ የስራ መገለጫው ይወገዳል፣ ይህም ሁሉንም የመገለጫ ውሂብ ይሰርዛል።"</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"ጡባዊውን <xliff:g id="NUMBER">%d</xliff:g> ጊዜ ትክክል ባልሆነ መልኩ ለመክፈት ሞክረዋል። የስራ መገለጫው ይወገዳል፣ ይህም ሁሉንም የመገለጫ ውሂብ ይሰርዛል።"</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"ስልኩን <xliff:g id="NUMBER">%d</xliff:g> ጊዜ ትክክል ባልሆነ መልኩ ለመክፈት ሞክረዋል። የስራ መገለጫው ይወገዳል፣ ይህም ሁሉንም የመገለጫ ውሂብ ይሰርዛል።"</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"የመክፈቻ ስርዓተ ጥለቱን <xliff:g id="NUMBER_0">%1$d</xliff:g> ጊዜ በትክክል አልሳሉትም። ከ<xliff:g id="NUMBER_1">%2$d</xliff:g> ተጨማሪ ያልተሳኩ ሙከራዎች በኋላ የኢሜይል መለያ ተጠቅመው ጡባዊዎን እንዲከፍቱ ይጠየቃሉ።\n\n ከ<xliff:g id="NUMBER_2">%3$d</xliff:g> ከሰከንዶች በኋላ እንደገና ይሞክሩ።"</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"የመክፈቻ ስርዓተ ጥለቱን <xliff:g id="NUMBER_0">%1$d</xliff:g> ጊዜ በትክክል አልሳሉትም። ከ<xliff:g id="NUMBER_1">%2$d</xliff:g> ተጨማሪ ያልተሳኩ ሙከራዎች በኋላ የኢሜይል መለያ ተጠቅመው ስልክዎን እንዲከፍቱ ይጠየቃሉ።\n\nእባክዎ ከ<xliff:g id="NUMBER_2">%3$d</xliff:g> ሰከንዶች በኋላ እንደገና ይሞክሩ።"</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-ar/strings.xml b/packages/SystemUI/res-product/values-ar/strings.xml
index 09aa42eb2a00..d64e18b5b06c 100644
--- a/packages/SystemUI/res-product/values-ar/strings.xml
+++ b/packages/SystemUI/res-product/values-ar/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"‏ليست هناك شريحة SIM في الجهاز اللوحي."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"‏ليست هناك شريحة SIM في الهاتف."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"لا يتطابق رمز رقم التعريف الشخصي"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"أخطأت في محاولة إلغاء قفل الجهاز اللوحي <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. بعد <xliff:g id="NUMBER_1">%2$d</xliff:g> محاولة غير ناجحة أخرى، ستتم إعادة تعيين هذا الجهاز، ومن ثم يتم حذف جميع بياناته."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"أخطأت في محاولة إلغاء قفل الهاتف <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. بعد <xliff:g id="NUMBER_1">%2$d</xliff:g> محاولة غير ناجحة أخرى، ستتم إعادة تعيين هذا الهاتف، ومن ثم يتم حذف جميع بياناته."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"أخطأت في محاولة إلغاء قفل الجهاز اللوحي <xliff:g id="NUMBER">%d</xliff:g> مرة. ستتم إعادة تعيين هذا الجهاز، ومن ثم يتم حذف جميع بياناته."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"أخطأت في محاولة إلغاء قفل الهاتف <xliff:g id="NUMBER">%d</xliff:g> مرة. ستتم إعادة تعيين هذا الهاتف، ومن ثم يتم حذف جميع بياناته."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"أخطأت في محاولة إلغاء قفل الجهاز اللوحي <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. بعد <xliff:g id="NUMBER_1">%2$d</xliff:g> محاولة غير ناجحة أخرى، ستتم إزالة هذا المستخدم، ومن ثم يتم حذف جميع بيانات المستخدم."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"أخطأت في محاولة إلغاء قفل الهاتف <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. بعد <xliff:g id="NUMBER_1">%2$d</xliff:g> محاولة غير ناجحة أخرى، ستتم إزالة هذا المستخدم، ومن ثم يتم حذف جميع بيانات المستخدم."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"‏سيتم إيقاف جهاز Android TV قريبًا، اضغط على أحد الأزرار لمواصلة تشغيله."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"سيتم إيقاف الجهاز قريبًا، اضغط لمواصلة تشغيله."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"أخطأت في محاولة إلغاء قفل الجهاز اللوحي <xliff:g id="NUMBER">%d</xliff:g> مرة. ستتم إزالة الملف الشخصي للعمل، ومن ثم يتم حذف جميع بياناته."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"أخطأت في محاولة إلغاء قفل الهاتف <xliff:g id="NUMBER">%d</xliff:g> مرة. ستتم إزالة الملف الشخصي للعمل، ومن ثم يتم حذف جميع بياناته."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"لقد رسمت نقش فتح القفل بشكل غير صحيح <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. بعد إجراء <xliff:g id="NUMBER_1">%2$d</xliff:g> من المحاولات غير الناجحة الأخرى، ستطالَب بإلغاء تأمين الجهاز اللوحي باستخدام معلومات حساب بريد إلكتروني.\n\n أعد المحاولة خلال <xliff:g id="NUMBER_2">%3$d</xliff:g> ثانية."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"لقد رسمت نقش فتح القفل بشكل غير صحيح <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. بعد إجراء <xliff:g id="NUMBER_1">%2$d</xliff:g> من المحاولات غير الناجحة الأخرى، ستُطالب بإلغاء تأمين الهاتف باستخدام حساب بريد إلكتروني لإلغاء تأمين الهاتف.\n\n أعد المحاولة خلال <xliff:g id="NUMBER_2">%3$d</xliff:g> ثانية."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"إعادة ضبط الهاتف لشحنه بشكلٍ أسرع"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"إعادة ضبط الهاتف لشحنه لاسلكيًا"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"‏سيتم إيقاف جهاز Android TV قريبًا، اضغط على أحد الأزرار لمواصلة تشغيله."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"سيتم إيقاف الجهاز قريبًا، اضغط لمواصلة تشغيله."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"‏ليس هناك شريحة SIM في الجهاز اللوحي."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"‏ليس هناك شريحة SIM في الهاتف."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"لا يتطابق ما أدخلته مع رمز رقم التعريف الشخصي"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"أخطأت في محاولة فتح قفل الجهاز اللوحي <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. بعد <xliff:g id="NUMBER_1">%2$d</xliff:g> محاولة غير ناجحة أخرى، ستتم إعادة ضبط هذا الجهاز، ومن ثم يتم حذف جميع بياناته."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"أخطأت في محاولة فتح قفل الهاتف <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. بعد <xliff:g id="NUMBER_1">%2$d</xliff:g> محاولة غير ناجحة أخرى، ستتم إعادة ضبط هذا الهاتف، ومن ثم يتم حذف جميع بياناته."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"أخطأت في محاولة فتح قفل الجهاز اللوحي <xliff:g id="NUMBER">%d</xliff:g> مرة. ستتم إعادة ضبط هذا الجهاز، ومن ثم يتم حذف جميع بياناته."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"أخطأت في محاولة فتح قفل الهاتف <xliff:g id="NUMBER">%d</xliff:g> مرة. ستتم إعادة ضبط هذا الهاتف، ومن ثم يتم حذف جميع بياناته."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"أخطأت في محاولة فتح قفل الجهاز اللوحي <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. بعد <xliff:g id="NUMBER_1">%2$d</xliff:g> محاولة غير ناجحة أخرى، ستتم إزالة الملف الشخصي لهذا المستخدم، ومن ثم يتم حذف جميع بيانات المستخدم."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"أخطأت في محاولة فتح قفل الهاتف <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. بعد <xliff:g id="NUMBER_1">%2$d</xliff:g> محاولة غير ناجحة أخرى، ستتم إزالة الملف الشخصي لهذا المستخدم، ومن ثم يتم حذف جميع بياناته."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"أخطأت في محاولة فتح قفل الجهاز اللوحي <xliff:g id="NUMBER">%d</xliff:g> مرة. ستتم إزالة الملف الشخصي لهذا المستخدم، ومن ثم يتم حذف جميع بياناته."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"أخطأت في محاولة فتح قفل الهاتف <xliff:g id="NUMBER">%d</xliff:g> مرة. ستتم إزالة الملف الشخصي لهذا المستخدم، ومن ثم يتم حذف جميع بياناته."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"أخطأت في محاولة فتح قفل الجهاز اللوحي <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. بعد <xliff:g id="NUMBER_1">%2$d</xliff:g> محاولة غير ناجحة أخرى، ستتم إزالة الملف الشخصي للعمل، ومن ثم يتم حذف جميع بيانات الملف الشخصي."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"أخطأت في محاولة فتح قفل الهاتف <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. بعد <xliff:g id="NUMBER_1">%2$d</xliff:g> محاولة غير ناجحة أخرى، ستتم إزالة الملف الشخصي للعمل، ومن ثم يتم حذف جميع بيانات الملف الشخصي."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"أخطأت في محاولة فتح قفل الجهاز اللوحي <xliff:g id="NUMBER">%d</xliff:g> مرة. ستتم إزالة الملف الشخصي للعمل، ومن ثم يتم حذف جميع بياناته."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"أخطأت في محاولة فتح قفل الهاتف <xliff:g id="NUMBER">%d</xliff:g> مرة. ستتم إزالة الملف الشخصي للعمل، ومن ثم يتم حذف جميع بياناته."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"رسمت نقش فتح القفل بشكل غير صحيح <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. بعد إجراء <xliff:g id="NUMBER_1">%2$d</xliff:g> محاولة غير ناجحة أخرى، ستُطالَب بفتح قفل الجهاز اللوحي باستخدام معلومات حساب بريد إلكتروني.\n\n يُرجى إعادة المحاولة خلال <xliff:g id="NUMBER_2">%3$d</xliff:g> ثانية."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"رسمت نقش فتح القفل بشكل غير صحيح <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. بعد إجراء <xliff:g id="NUMBER_1">%2$d</xliff:g> محاولة غير ناجحة أخرى، ستُطالَب بفتح قفل الهاتف باستخدام حساب بريد إلكتروني.\n\n يُرجى إعادة المحاولة خلال <xliff:g id="NUMBER_2">%3$d</xliff:g> ثانية."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-as/strings.xml b/packages/SystemUI/res-product/values-as/strings.xml
index 1f1ca094c201..80a679f224d6 100644
--- a/packages/SystemUI/res-product/values-as/strings.xml
+++ b/packages/SystemUI/res-product/values-as/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,46 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"টেবলেটত ছিম কার্ড নাই।"</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"ফ\'নত ছিম কার্ড নাই।"</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"পিন ক\'ড মিলা নাই"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"আপুনি টেবলেটটো আনলক কৰিবলৈ <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুল প্ৰয়াস কৰিছে আৰু <xliff:g id="NUMBER_1">%2$d</xliff:g> বাৰ ভুল প্ৰয়াস কৰিলে টেবলেটটো ৰিছেট কৰা হ\'ব, যি কার্যই টেবলেটটোত থকা সকলো ডেটা মচিব।"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"আপুনি ফ\'নটো আনলক কৰিবলৈ <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুল প্ৰয়াস কৰিছে আৰু <xliff:g id="NUMBER_1">%2$d</xliff:g> বাৰ ভুল প্ৰয়াস কৰিলে ফ\'নটো ৰিছেট কৰা হ\'ব, যি কার্যই ফ\'নটোত থকা সকলো ডেটা মচিব।"</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"আপুনি টেবলেটটো আনলক কৰিবলৈ <xliff:g id="NUMBER">%d</xliff:g> বাৰ ভুল প্ৰয়াস কৰিছে। এই টেবলেটটো ৰিছেট কৰা হ\'ব, যি কার্যই ইয়াৰ সকলো ডেটা মচিব।"</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"আপুনি ফ\'নটো আনলক কৰিবলৈ <xliff:g id="NUMBER">%d</xliff:g> বাৰ ভুল প্ৰয়াস কৰিছে। এই ফ\'নটো ৰিছেট কৰা হ\'ব, যিয়ে ইয়াৰ সকলো ডেটা মচিব।"</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"আপুনি টেবলেটটো আনলক কৰিবলৈ <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুল প্ৰয়াস কৰিছে আৰু <xliff:g id="NUMBER_1">%2$d</xliff:g> বাৰ ভুল প্ৰয়াস কৰিলে এই ব্যৱহাৰকাৰীক আঁতৰোৱা হ\'ব, যিয়ে ব্যৱহাৰকাৰীৰ সকলো ডেটা মচিব।"</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"আপুনি ফ\'নটো আনলক কৰিবলৈ <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুল প্ৰয়াস কৰিছে। আৰু <xliff:g id="NUMBER_1">%2$d</xliff:g> বাৰ ভুল প্ৰয়াস কৰিলে এই ব্যৱহাৰকাৰীক আঁতৰোৱা হ\'ব, যিয়ে ব্যৱহাৰকাৰীৰ সকলো ডেটা মচিব।"</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for notification_bubble_title (8330481035191903164) -->
- <skip/>
- <!-- no translation found for notification_channel_summary_bubble (7235935211580860537) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Android TV ডিভাইচটো অতি সোনকালে অফ হ\'ব, এইটো অন ৰাখিবলৈ যিকোনো এটা বুটাম টিপক।"</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"এই ডিভাইচটো অতি সোনকালে অফ হ\'ব, এইটো অন ৰাখিবলৈ টিপক।"</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"আপুনি টেবলেটটো আনলক কৰিবলৈ <xliff:g id="NUMBER">%d</xliff:g> বাৰ ভুল প্ৰয়াস কৰিছে। আপোনাৰ কৰ্মস্থানৰ প্ৰ\'ফাইলটো আঁতৰোৱা হ\'ব, যি কার্যই প্ৰ\'ফাইলটোৰ সকলো ডেটা মচিব।"</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"আপুনি ফ\'নটো আনলক কৰিবলৈ <xliff:g id="NUMBER">%d</xliff:g> বাৰ ভুল প্ৰয়াস কৰিছে। আপোনাৰ কৰ্মস্থানৰ প্ৰ\'ফাইলটো আঁতৰোৱা হ\'ব, যিয়ে প্ৰ\'ফাইলটোৰ সকলো ডেটা মচিব।"</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"আপুনি আপোনাৰ আনলক আৰ্হিটো <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুলকৈ আঁকিছে। <xliff:g id="NUMBER_1">%2$d</xliff:g>তকৈ বেছি বাৰ ভুল আৰ্হি আঁকিলে আপোনাৰ টেবলেটটো কোনো একাউণ্টৰ জৰিয়তে আনলক কৰিবলৈ কোৱা হ\'ব।\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> ছেকেণ্ডৰ পিছত আকৌ চেষ্টা কৰক।"</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"আপুনি আপোনাৰ আনলক আৰ্হিটো <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুলকৈ আঁকিছে। <xliff:g id="NUMBER_1">%2$d</xliff:g>তকৈ বেছি বাৰ ভুল আৰ্হি আঁকিলে আপোনাৰ ফ\'নটো কোনো একাউণ্টৰ জৰিয়তে আনলক কৰিবলৈ কোৱা হ\'ব।\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> ছেকেণ্ডৰ পিছত আকৌ চেষ্টা কৰক।"</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"খৰতকীয়াকৈ চাৰ্জ কৰিবলৈ ফ’নটো পুনৰ সংৰেখিত কৰক"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"তাঁৰৰ অবিহনে চাৰ্জ কৰিবলৈ ফ’নটো পুনৰ সংৰেখিত কৰক"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Android TV ডিভাইচটো সোনকালেই অফ হ’ব, এইটো অন কৰি ৰাখিবলৈ এটা বুটাম টিপক।"</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"এই ডিভাইচটো সোনকালেই অফ হ’ব; এইটো অন কৰি ৰাখিবলৈ টিপক।"</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"টেবলেটটোত ছিম কার্ড নাই।"</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"ফ’নটোত ছিম কার্ড নাই।"</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"পিন ক’ড মিলা নাই"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"আপুনি টেবলেটটো আনলক কৰিবলৈ <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰিছে। আৰু <xliff:g id="NUMBER_1">%2$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰাৰ পাছত এই টেবলেটটো ৰিছেট কৰা হ’ব, যিয়ে ইয়াৰ সকলো ডেটা মচি পেলাব।"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"আপুনি ফ’নটো আনলক কৰিবলৈ <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰিছে। আৰু <xliff:g id="NUMBER_1">%2$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰাৰ পাছত এই ফ’নটো ৰিছেট কৰা হ’ব, যিয়ে ইয়াৰ সকলো ডেটা মচি পেলাব।"</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"আপুনি টেবলেটটো আনলক কৰিবলৈ <xliff:g id="NUMBER">%d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰিছে। এই টেবলেটটো ৰিছেট কৰা হ’ব, যিয়ে ইয়াৰ সকলো ডেটা মচি পেলাব।"</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"আপুনি ফ’নটো আনলক কৰিবলৈ <xliff:g id="NUMBER">%d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰিছে। এই ফ’নটো ৰিছেট কৰা হ’ব, যিয়ে ইয়াৰ সকলো ডেটা মচি পেলাব।"</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"আপুনি টেবলেটটো আনলক কৰিবলৈ <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰিছে। আৰু <xliff:g id="NUMBER_1">%2$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰাৰ পাছত এই ব্যৱহাৰকাৰীজনক আঁতৰোৱা হ’ব, যিয়ে ব্যৱহাৰকাৰীৰ সকলো ডেটা মচি পেলাব।"</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"আপুনি ফ’নটো আনলক কৰিবলৈ <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰিছে। আৰু <xliff:g id="NUMBER_1">%2$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰাৰ পাছত এই ব্যৱহাৰকাৰীজনক আঁতৰোৱা হ’ব, যিয়ে ব্যৱহাৰকাৰীৰ সকলো ডেটা মচি পেলাব।"</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"আপুনি টেবলেটটো আনলক কৰিবলৈ <xliff:g id="NUMBER">%d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰিছে। এই ব্যৱহাৰকাৰীজনক আঁতৰোৱা হ’ব, যিয়ে ব্যৱহাৰকাৰীৰ সকলো ডেটা মচি পেলাব।"</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"আপুনি ফ’নটো আনলক কৰিবলৈ <xliff:g id="NUMBER">%d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰিছে। এই ব্যৱহাৰকাৰীজনক আঁতৰোৱা হ’ব, যিয়ে ব্যৱহাৰকাৰীৰ সকলো ডেটা মচি পেলাব।"</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"আপুনি টেবলেটটো আনলক কৰিবলৈ <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰিছে। আৰু <xliff:g id="NUMBER_1">%2$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰাৰ পাছত কৰ্মস্থানৰ প্ৰ’ফাইলটো আঁতৰোৱা হ’ব, যিয়ে প্ৰ’ফাইলটোৰ সকলো ডেটা মচি পেলাব।"</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"আপুনি ফ’নটো আনলক কৰিবলৈ <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰিছে। আৰু <xliff:g id="NUMBER_1">%2$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰাৰ পাছত কৰ্মস্থানৰ প্ৰ’ফাইলটো আঁতৰোৱা হ’ব, যিয়ে প্ৰ’ফাইলৰ সকলো ডেটা মচি পেলাব।"</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"আপুনি টেবলেটটো আনলক কৰিবলৈ <xliff:g id="NUMBER">%d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰিছে। কৰ্মস্থানৰ প্ৰ’ফাইলটো আঁতৰোৱা হ’ব, যিয়ে প্ৰ’ফাইলটোৰ সকলো ডেটা মচি পেলাব।"</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"আপুনি ফ’নটো আনলক কৰিবলৈ <xliff:g id="NUMBER">%d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰিছে। কৰ্মস্থানৰ প্ৰ’ফাইলটো আঁতৰোৱা হ’ব, যিয়ে প্ৰ’ফাইলটোৰ সকলো ডেটা মচি পেলাব।"</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"আপুনি নিজৰ আনলক কৰা আৰ্হিটো <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুলকৈ আঁকিছে। আৰু <xliff:g id="NUMBER_1">%2$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰাৰ পাছত আপোনাক নিজৰ টেবলেটটো এটা ইমেইল একাউণ্টৰ জৰিয়তে আনলক কৰিবলৈ কোৱা হ’ব।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ছেকেণ্ডৰ পাছত পুনৰ চেষ্টা কৰক।"</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"আপুনি নিজৰ আনলক কৰা আৰ্হিটো <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুলকৈ আঁকিছে। আৰু <xliff:g id="NUMBER_1">%2$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰাৰ পাছত আপোনাক নিজৰ ফ’নটো এটা ইমেইল একাউণ্টৰ জৰিয়তে আনলক কৰিবলৈ কোৱা হ’ব।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ছেকেণ্ডৰ পাছত পুনৰ চেষ্টা কৰক।"</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-az/strings.xml b/packages/SystemUI/res-product/values-az/strings.xml
index c34b1422e07a..47a0ef0eb8dd 100644
--- a/packages/SystemUI/res-product/values-az/strings.xml
+++ b/packages/SystemUI/res-product/values-az/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"Planşetdə SIM kart yoxdur."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"Telefonda SIM kart yoxdur."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"PIN kodlar uyğun gəlmir"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Planşetin kilidini açmaq üçün <xliff:g id="NUMBER_0">%1$d</xliff:g> dəfə yanlış cəhdlər etmisiniz. Daha <xliff:g id="NUMBER_1">%2$d</xliff:g> uğursuz cəhddən sonra bu planşet sıfırlanacaq və bütün data silinəcək."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Telefonun kilidini açmaq üçün <xliff:g id="NUMBER_0">%1$d</xliff:g> dəfə yanlış cəhdlər etmisiniz. Daha <xliff:g id="NUMBER_1">%2$d</xliff:g> uğursuz cəhddən sonra bu telefon sıfırlanacaq və bütün data silinəcək."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Planşetin kilidini açmaq üçün <xliff:g id="NUMBER">%d</xliff:g> dəfə yanlış cəhdlər etmisiniz. Bu planşet sıfırlanacaq və bütün data silinəcək."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Telefonun kilidini açmaq üçün <xliff:g id="NUMBER">%d</xliff:g> dəfə yanlış cəhdlər etmisiniz. Bu telefon sıfırlanacaq və bütün data silinəcək."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Planşetin kilidini açmaq üçün <xliff:g id="NUMBER_0">%1$d</xliff:g> dəfə yanlış cəhdlər etdiniz. Daha <xliff:g id="NUMBER_1">%2$d</xliff:g> uğursuz cəhddən sonra bu istifadəçi silinəcək və bütün istifadəçi datası ləğv ediləcək."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Telefonun kilidini açmaq üçün <xliff:g id="NUMBER_0">%1$d</xliff:g> dəfə yanlış cəhdlər etdiniz. Daha <xliff:g id="NUMBER_1">%2$d</xliff:g> uğursuz cəhddən sonra bu istifadəçi silinəcək və bütün istifadəçi datası ləğv ediləcək."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Android TV cihazı tezliklə sönəcək; aktiv saxlamaq üçün düyməyə basın."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Cihaz tezliklə sönəcək; aktiv saxlamaq üçün basın."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Planşetin kilidini açmaq üçün <xliff:g id="NUMBER">%d</xliff:g> dəfə yanlış cəhdlər etmisiniz. İş profili silinəcək və bütün data ləğv ediləcək."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Telefonun kilidini açmaq üçün <xliff:g id="NUMBER">%d</xliff:g> dəfə yanlış cəhdlər etmisiniz. İş profili silinəcək və bütün data ləğv ediləcək."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Kilid açma modelini <xliff:g id="NUMBER_0">%1$d</xliff:g> dəfə yanlış çəkmisiniz. Daha <xliff:g id="NUMBER_1">%2$d</xliff:g> uğursuz cəhddən sonra planşet kilidini e-poçt hesabınızla açmaq tələb olunacaq.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> saniyə sonra yenidən cəhd edin."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Kilid açma modelini artıq <xliff:g id="NUMBER_0">%1$d</xliff:g> dəfə yanlış çəkmisiniz. Daha <xliff:g id="NUMBER_1">%2$d</xliff:g> uğursuz cəhddən sonra telefon kilidini e-poçt hesabınızla açmaq tələb olunacaq.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> saniyə sonra yenidən cəhd edin."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Sürətli şarj etmək üçün telefonu doğru yerləşdirin"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Simsiz şarj etmək üçün telefonu doğru yerləşdirin"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Android TV cihazı tezliklə deaktiv olacaq; aktiv saxlamaq üçün düyməyə basın."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Cihaz tezliklə deaktiv olacaq; aktiv saxlamaq üçün basın."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Planşetdə SIM kart yoxdur."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Telefonda SIM kart yoxdur."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"PIN kodlar uyğun gəlmir"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Planşetin kilidini açmaq üçün <xliff:g id="NUMBER_0">%1$d</xliff:g> dəfə yanlış cəhd etmisiniz. Daha <xliff:g id="NUMBER_1">%2$d</xliff:g> uğursuz cəhddən sonra bu planşet sıfırlanacaq və bütün data silinəcək."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Telefonun kilidini açmaq üçün <xliff:g id="NUMBER_0">%1$d</xliff:g> dəfə yanlış cəhd etmisiniz. Daha <xliff:g id="NUMBER_1">%2$d</xliff:g> uğursuz cəhddən sonra bu telefon sıfırlanacaq və bütün data silinəcək."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Planşetin kilidini açmaq üçün <xliff:g id="NUMBER">%d</xliff:g> dəfə yanlış cəhd etmisiniz. Bu planşet sıfırlanacaq və bütün data silinəcək."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Telefonun kilidini açmaq üçün <xliff:g id="NUMBER">%d</xliff:g> dəfə yanlış cəhd etmisiniz. Bu telefon sıfırlanacaq və bütün data silinəcək."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Planşetin kilidini açmaq üçün <xliff:g id="NUMBER_0">%1$d</xliff:g> dəfə yanlış cəhd etdiniz. Daha <xliff:g id="NUMBER_1">%2$d</xliff:g> uğursuz cəhddən sonra bu istifadəçi silinəcək və bütün istifadəçi datası ləğv ediləcək."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Telefonun kilidini açmaq üçün <xliff:g id="NUMBER_0">%1$d</xliff:g> dəfə yanlış cəhd etdiniz. Daha <xliff:g id="NUMBER_1">%2$d</xliff:g> uğursuz cəhddən sonra bu istifadəçi silinəcək və bütün istifadəçi datası ləğv ediləcək."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Planşetin kilidini açmaq üçün <xliff:g id="NUMBER">%d</xliff:g> dəfə yanlış cəhd etmisiniz. Bu istifadəçi silinəcək və bütün data ləğv ediləcək."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Telefonun kilidini açmaq üçün <xliff:g id="NUMBER">%d</xliff:g> dəfə yanlış cəhd etmisiniz. Bu istifadəçi silinəcək və bütün data ləğv ediləcək."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Planşetin kilidini açmaq üçün <xliff:g id="NUMBER_0">%1$d</xliff:g> dəfə yanlış cəhd etmisiniz. Daha <xliff:g id="NUMBER_1">%2$d</xliff:g> uğursuz cəhddən sonra iş profili silinəcək və bütün profil datası ləğv ediləcək."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Telefonun kilidini açmaq üçün <xliff:g id="NUMBER_0">%1$d</xliff:g> dəfə yanlış cəhd etmisiniz. Daha <xliff:g id="NUMBER_1">%2$d</xliff:g> uğursuz cəhddən sonra iş profili silinəcək və bütün profil datası ləğv ediləcək."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Planşetin kilidini açmaq üçün <xliff:g id="NUMBER">%d</xliff:g> dəfə yanlış cəhd etmisiniz. İş profili silinəcək və bütün data ləğv ediləcək."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Telefonun kilidini açmaq üçün <xliff:g id="NUMBER">%d</xliff:g> dəfə yanlış cəhd etmisiniz. İş profili silinəcək və bütün data ləğv ediləcək."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Kilid açma modelini <xliff:g id="NUMBER_0">%1$d</xliff:g> dəfə yanlış çəkmisiniz. Daha <xliff:g id="NUMBER_1">%2$d</xliff:g> uğursuz cəhddən sonra planşet kilidini e-poçt hesabınızla açmaq tələb olunacaq.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> saniyə sonra yenidən cəhd edin."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Kilid açma modelini artıq <xliff:g id="NUMBER_0">%1$d</xliff:g> dəfə yanlış çəkmisiniz. Daha <xliff:g id="NUMBER_1">%2$d</xliff:g> uğursuz cəhddən sonra telefon kilidini e-poçt hesabınızla açmaq tələb olunacaq.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> saniyə sonra yenidən cəhd edin."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-b+sr+Latn/strings.xml b/packages/SystemUI/res-product/values-b+sr+Latn/strings.xml
index e753e74703b9..5eb81a45e629 100644
--- a/packages/SystemUI/res-product/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res-product/values-b+sr+Latn/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"U tabletu nema SIM kartice."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"U telefonu nema SIM kartice."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"PIN kodovi se ne podudaraju"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Pogrešno ste pokušali da otključate tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Ako pogrešno pokušate još <xliff:g id="NUMBER_1">%2$d</xliff:g> puta, ovaj tablet će se resetovati, čime se brišu svi podaci korisnika."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Pogrešno ste pokušali da otključate telefon <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Ako pogrešno pokušate još <xliff:g id="NUMBER_1">%2$d</xliff:g> puta, ovaj telefon će se resetovati, čime se brišu svi podaci korisnika."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Pogrešno ste pokušali da otključate tablet <xliff:g id="NUMBER">%d</xliff:g> puta. Ovaj tablet će se resetovati, čime se brišu svi podaci."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Pogrešno ste pokušali da otključate telefon <xliff:g id="NUMBER">%d</xliff:g> puta. Ovaj telefon će se resetovati, čime se brišu svi podaci."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Pogrešno ste pokušali da otključate tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Ako pogrešno pokušate još <xliff:g id="NUMBER_1">%2$d</xliff:g> puta, uklonićemo ovog korisnika, čime se brišu svi podaci korisnika."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Pogrešno ste pokušali da otključate telefon <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Ako pogrešno pokušate još <xliff:g id="NUMBER_1">%2$d</xliff:g> puta, uklonićemo ovog korisnika, čime se brišu svi podaci korisnika."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Android TV će se uskoro isključiti. Pritisnite dugme da bi ostao uključen."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Uređaj će se uskoro isključiti. Pritisnite da bi ostao uključen."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Pogrešno ste pokušali da otključate tablet <xliff:g id="NUMBER">%d</xliff:g> puta. Uklonićemo profil za Work, čime se brišu svi podaci sa profila."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Pogrešno ste pokušali da otključate telefon <xliff:g id="NUMBER">%d</xliff:g> puta. Uklonićemo profil za Work, čime se brišu svi podaci sa profila."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Netačno ste nacrtali šablon za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Ako pogrešno pokušate još <xliff:g id="NUMBER_1">%2$d</xliff:g> puta, zatražićemo da otključate tablet pomoću imejl naloga.\n\n Probajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> sek."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Netačno ste nacrtali šablon za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Ako pogrešno pokušate još <xliff:g id="NUMBER_1">%2$d</xliff:g> puta, zatražićemo da otključate telefon pomoću imejl naloga.\n\n Probajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> sek."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Ponovo postavite telefon radi bržeg punjenja"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Ponovo postavite telefon radi bežičnog punjenja"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Android TV će se uskoro isključiti. Pritisnite dugme da bi ostao uključen."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Uređaj će se uskoro isključiti. Pritisnite da bi ostao uključen."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"U tabletu nema SIM kartice."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"U telefonu nema SIM kartice."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"PIN kodovi se ne podudaraju"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Pogrešno ste pokušali da otključate tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Ako pogrešno pokušate još <xliff:g id="NUMBER_1">%2$d</xliff:g> puta, ovaj tablet će se resetovati, čime se brišu svi podaci korisnika."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Pogrešno ste pokušali da otključate telefon <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Ako pogrešno pokušate još <xliff:g id="NUMBER_1">%2$d</xliff:g> puta, ovaj telefon će se resetovati, čime se brišu svi podaci korisnika."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Pogrešno ste pokušali da otključate tablet <xliff:g id="NUMBER">%d</xliff:g> puta. Ovaj tablet će se resetovati, čime se brišu svi podaci."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Pogrešno ste pokušali da otključate telefon <xliff:g id="NUMBER">%d</xliff:g> puta. Ovaj telefon će se resetovati, čime se brišu svi podaci."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Pogrešno ste pokušali da otključate tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Ako pogrešno pokušate još <xliff:g id="NUMBER_1">%2$d</xliff:g> puta, uklonićemo ovog korisnika, čime se brišu svi podaci korisnika."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Pogrešno ste pokušali da otključate telefon <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Ako pogrešno pokušate još <xliff:g id="NUMBER_1">%2$d</xliff:g> puta, uklonićemo ovog korisnika, čime se brišu svi podaci korisnika."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Pogrešno ste pokušali da otključate tablet <xliff:g id="NUMBER">%d</xliff:g> puta. Uklonićemo ovog korisnika, čime se brišu svi podaci korisnika."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Pogrešno ste pokušali da otključate telefon <xliff:g id="NUMBER">%d</xliff:g> puta. Uklonićemo ovog korisnika, čime se brišu svi podaci korisnika."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Pogrešno ste pokušali da otključate tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Ako pogrešno pokušate još <xliff:g id="NUMBER_1">%2$d</xliff:g> puta, uklonićemo profil za Work, čime se brišu svi podaci sa profila."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Pogrešno ste pokušali da otključate telefon <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Ako pogrešno pokušate još <xliff:g id="NUMBER_1">%2$d</xliff:g> puta, uklonićemo profil za Work, čime se brišu svi podaci sa profila."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Pogrešno ste pokušali da otključate tablet <xliff:g id="NUMBER">%d</xliff:g> puta. Uklonićemo profil za Work, čime se brišu svi podaci sa profila."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Pogrešno ste pokušali da otključate telefon <xliff:g id="NUMBER">%d</xliff:g> puta. Uklonićemo profil za Work, čime se brišu svi podaci sa profila."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Netačno ste nacrtali šablon za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Ako pogrešno pokušate još <xliff:g id="NUMBER_1">%2$d</xliff:g> puta, zatražićemo da otključate tablet pomoću imejl naloga.\n\n Probajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> sek."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Netačno ste nacrtali šablon za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Ako pogrešno pokušate još <xliff:g id="NUMBER_1">%2$d</xliff:g> puta, zatražićemo da otključate telefon pomoću imejl naloga.\n\n Probajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> sek."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-be/strings.xml b/packages/SystemUI/res-product/values-be/strings.xml
index e2dbd245cc39..64a67f794971 100644
--- a/packages/SystemUI/res-product/values-be/strings.xml
+++ b/packages/SystemUI/res-product/values-be/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,45 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"У планшэце няма SIM-карты."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"У тэлефоне няма SIM-карты."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"PIN-коды не супадаюць"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Вы не змаглі разблакіраваць планшэт столькі разоў: <xliff:g id="NUMBER_0">%1$d</xliff:g>. Пасля яшчэ некалькіх няўдалых спроб (<xliff:g id="NUMBER_1">%2$d</xliff:g>) ён будзе скінуты да заводскіх налад, гэта прывядзе да выдалення ўсіх даных."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Вы не змаглі разблакіраваць тэлефон столькі разоў: <xliff:g id="NUMBER_0">%1$d</xliff:g>. Пасля яшчэ некалькіх няўдалых спроб (<xliff:g id="NUMBER_1">%2$d</xliff:g>) ён будзе скінуты да заводскіх налад, гэта прывядзе да выдалення ўсіх даных."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Вы не змаглі разблакіраваць планшэт столькі разоў: <xliff:g id="NUMBER">%d</xliff:g>. Цяпер ён будзе скінуты да заводскіх налад, гэта прывядзе да выдалення ўсіх даных."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Вы не змаглі разблакіраваць тэлефон столькі разоў: <xliff:g id="NUMBER">%d</xliff:g>. Цяпер ён будзе скінуты да заводскіх налад, гэта прывядзе да выдалення ўсіх даных."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Вы не змаглі разблакіраваць планшэт столькі разоў: <xliff:g id="NUMBER_0">%1$d</xliff:g>. Пасля яшчэ некалькіх няўдалых спроб (<xliff:g id="NUMBER_1">%2$d</xliff:g>) гэты карыстальнік будзе выдалены, гэта прывядзе да выдалення ўсіх карыстальніцкіх даных."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Вы не змаглі разблакіраваць тэлефон столькі разоў: <xliff:g id="NUMBER_0">%1$d</xliff:g>. Пасля яшчэ некалькіх няўдалых спроб (<xliff:g id="NUMBER_1">%2$d</xliff:g>) гэты карыстальнік будзе выдалены, гэта прывядзе да выдалення ўсіх карыстальніцкіх даных."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- String.format failed for translation -->
- <!-- no translation found for accessibility_battery_level (5143715405241138822) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Прылада Android TV неўзабаве выключыцца. Каб пакінуць яе ўключанай, націсніце кнопку."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Прылада неўзабаве выключыцца. Націсніце, каб пакінуць яе ўключанай."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Вы не змаглі разблакіраваць планшэт столькі разоў: <xliff:g id="NUMBER">%d</xliff:g>. Працоўны профіль будзе выдалены, гэта прывядзе да выдалення ўсіх даных у профілі."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Вы не змаглі разблакіраваць тэлефон столькі разоў: <xliff:g id="NUMBER">%d</xliff:g>. Працоўны профіль будзе выдалены, гэта прывядзе да выдалення ўсіх даных у профілі."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Вы няправільна ўвялі ўзор разблакіроўкі столькі разоў: <xliff:g id="NUMBER_0">%1$d</xliff:g>. Пасля яшчэ некалькіх няўдалых спроб (<xliff:g id="NUMBER_1">%2$d</xliff:g>) вам будзе прапанавана разблакіраваць планшэт, увайшоўшы ва ўліковы запіс электроннай пошты.\n\n Паўтарыце спробу праз <xliff:g id="NUMBER_2">%3$d</xliff:g> с."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Вы няправільна ўвялі ўзор разблакіроўкі столькі разоў: <xliff:g id="NUMBER_0">%1$d</xliff:g>. Пасля яшчэ некалькіх няўдалых спроб (<xliff:g id="NUMBER_1">%2$d</xliff:g>) вам будзе прапанавана разблакіраваць тэлефон, увайшоўшы ва ўліковы запіс электроннай пошты.\n\n Паўтарыце спробу праз <xliff:g id="NUMBER_2">%3$d</xliff:g> с."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Папраўце тэлефон на док-станцыі для хутчэйшай зарадкі"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Папраўце тэлефон на док-станцыі для бесправадной зарадкі"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Прылада Android TV неўзабаве выключыцца. Каб пакінуць яе ўключанай, націсніце кнопку."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Прылада неўзабаве выключыцца. Націсніце, каб пакінуць яе ўключанай."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"У планшэце няма SIM-карты."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"У тэлефоне няма SIM-карты."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"PIN-коды не супадаюць"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Вы не змаглі разблакіраваць планшэт столькі разоў: <xliff:g id="NUMBER_0">%1$d</xliff:g>. Пасля яшчэ некалькіх няўдалых спроб (<xliff:g id="NUMBER_1">%2$d</xliff:g>) ён будзе скінуты да заводскіх налад, і гэта прывядзе да выдалення ўсіх даных."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Вы не змаглі разблакіраваць тэлефон столькі разоў: <xliff:g id="NUMBER_0">%1$d</xliff:g>. Пасля яшчэ некалькіх няўдалых спроб (<xliff:g id="NUMBER_1">%2$d</xliff:g>) ён будзе скінуты да заводскіх налад, і гэта прывядзе да выдалення ўсіх даных."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Вы не змаглі разблакіраваць планшэт столькі разоў: <xliff:g id="NUMBER">%d</xliff:g>. Цяпер ён будзе скінуты да заводскіх налад, і гэта прывядзе да выдалення ўсіх даных."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Вы не змаглі разблакіраваць тэлефон столькі разоў: <xliff:g id="NUMBER">%d</xliff:g>. Цяпер ён будзе скінуты да заводскіх налад, і гэта прывядзе да выдалення ўсіх даных."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Вы не змаглі разблакіраваць планшэт столькі разоў: <xliff:g id="NUMBER_0">%1$d</xliff:g>. Пасля яшчэ некалькіх няўдалых спроб (<xliff:g id="NUMBER_1">%2$d</xliff:g>) гэты карыстальнік будзе выдалены, і гэта прывядзе да выдалення ўсіх карыстальніцкіх даных."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Вы не змаглі разблакіраваць тэлефон столькі разоў: <xliff:g id="NUMBER_0">%1$d</xliff:g>. Пасля яшчэ некалькіх няўдалых спроб (<xliff:g id="NUMBER_1">%2$d</xliff:g>) гэты карыстальнік будзе выдалены, і гэта прывядзе да выдалення ўсіх карыстальніцкіх даных."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Вы не змаглі разблакіраваць планшэт столькі разоў: <xliff:g id="NUMBER">%d</xliff:g>. Гэты карыстальнік будзе выдалены, і гэта прывядзе да выдалення ўсіх карыстальніцкіх даных."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Вы не змаглі разблакіраваць тэлефон столькі разоў: <xliff:g id="NUMBER">%d</xliff:g>. Гэты карыстальнік будзе выдалены, і гэта прывядзе да выдалення ўсіх карыстальніцкіх даных."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Вы не змаглі разблакіраваць планшэт столькі разоў: <xliff:g id="NUMBER_0">%1$d</xliff:g>. Пасля яшчэ некалькіх няўдалых спроб (<xliff:g id="NUMBER_1">%2$d</xliff:g>) працоўны профіль будзе выдалены, і гэта прывядзе да выдалення ўсіх даных у профілі."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Вы не змаглі разблакіраваць тэлефон столькі разоў: <xliff:g id="NUMBER_0">%1$d</xliff:g>. Пасля яшчэ некалькіх няўдалых спроб (<xliff:g id="NUMBER_1">%2$d</xliff:g>) працоўны профіль будзе выдалены, і гэта прывядзе да выдалення ўсіх даных у профілі."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Вы не змаглі разблакіраваць планшэт столькі разоў: <xliff:g id="NUMBER">%d</xliff:g>. Працоўны профіль будзе выдалены, і гэта прывядзе да выдалення ўсіх даных у профілі."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Вы не змаглі разблакіраваць тэлефон столькі разоў: <xliff:g id="NUMBER">%d</xliff:g>. Працоўны профіль будзе выдалены, і гэта прывядзе да выдалення ўсіх даных у профілі."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Вы няправільна ўвялі ўзор разблакіроўкі столькі разоў: <xliff:g id="NUMBER_0">%1$d</xliff:g>. Пасля яшчэ некалькіх няўдалых спроб (<xliff:g id="NUMBER_1">%2$d</xliff:g>) вам будзе прапанавана разблакіраваць планшэт, увайшоўшы ва ўліковы запіс электроннай пошты.\n\n Паўтарыце спробу праз <xliff:g id="NUMBER_2">%3$d</xliff:g> с."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Вы няправільна ўвялі ўзор разблакіроўкі столькі разоў: <xliff:g id="NUMBER_0">%1$d</xliff:g>. Пасля яшчэ некалькіх няўдалых спроб (<xliff:g id="NUMBER_1">%2$d</xliff:g>) вам будзе прапанавана разблакіраваць тэлефон, увайшоўшы ва ўліковы запіс электроннай пошты.\n\n Паўтарыце спробу праз <xliff:g id="NUMBER_2">%3$d</xliff:g> с."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-bg/strings.xml b/packages/SystemUI/res-product/values-bg/strings.xml
index 4ae6d4c50670..83eefe58cb61 100644
--- a/packages/SystemUI/res-product/values-bg/strings.xml
+++ b/packages/SystemUI/res-product/values-bg/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"В таблета няма SIM карта."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"В телефона няма SIM карта."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"ПИН кодовете не съвпадат"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Опитахте да отключите таблета и сбъркахте <xliff:g id="NUMBER_0">%1$d</xliff:g> пъти. След още <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешни опита той ще бъде нулиран, при което ще се изтрият всичките му данни."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Опитахте да отключите телефона и сбъркахте <xliff:g id="NUMBER_0">%1$d</xliff:g> пъти. След още <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешни опита той ще бъде нулиран, при което ще се изтрият всичките му данни."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Опитахте да отключите таблета и сбъркахте <xliff:g id="NUMBER">%d</xliff:g> пъти. Той ще бъде нулиран, при което ще се изтрият всичките му данни."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Опитахте да отключите телефона и сбъркахте <xliff:g id="NUMBER">%d</xliff:g> пъти. Той ще бъде нулиран, при което ще се изтрият всичките му данни."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Опитахте да отключите таблета и сбъркахте <xliff:g id="NUMBER_0">%1$d</xliff:g> пъти. След още <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешни опита този потребител ще бъде премахнат, при което ще се изтрият всички данни за него."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Опитахте да отключите телефона и сбъркахте <xliff:g id="NUMBER_0">%1$d</xliff:g> пъти. След още <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешни опита този потребител ще бъде премахнат, при което ще се изтрият всички данни за него."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Устройството с Android TV скоро ще се изключи. Натиснете бутон, за да остане включено."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Устройството скоро ще се изключи. Натиснете, за да остане включено."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Опитахте да отключите таблета и сбъркахте <xliff:g id="NUMBER">%d</xliff:g> пъти. Служебният потребителски профил ще бъде премахнат, при което ще се изтрият всички данни за него."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Опитахте да отключите телефона и сбъркахте <xliff:g id="NUMBER">%d</xliff:g> пъти. Служебният потребителски профил ще бъде премахнат, при което ще се изтрият всички данни за него."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Начертахте неправилно фигурата си за отключване <xliff:g id="NUMBER_0">%1$d</xliff:g> пъти. След още <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешни опита ще бъдете помолени да отключите таблета си посредством имейл адрес.\n\n Опитайте отново след <xliff:g id="NUMBER_2">%3$d</xliff:g> секунди."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Начертахте неправилно фигурата си за отключване <xliff:g id="NUMBER_0">%1$d</xliff:g> пъти. След още <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешни опита ще бъдете помолени да отключите телефона посредством имейл адрес.\n\n Опитайте отново след <xliff:g id="NUMBER_2">%3$d</xliff:g> секунди."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Подравнете отново телефона за по-бързо зареждане"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Подравнете отново телефона за безжично зареждане"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Устройството с Android TV скоро ще се изключи. Натиснете бутон, за да остане включено."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Устройството скоро ще се изключи. Натиснете, за да остане включено."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"В таблета няма SIM карта."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"В телефона няма SIM карта."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"ПИН кодовете не съвпадат"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Опитахте да отключите таблета и сбъркахте <xliff:g id="NUMBER_0">%1$d</xliff:g> пъти. След още <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешни опита той ще бъде нулиран, при което ще се изтрият всичките му данни."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Опитахте да отключите телефона и сбъркахте <xliff:g id="NUMBER_0">%1$d</xliff:g> пъти. След още <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешни опита той ще бъде нулиран, при което ще се изтрият всичките му данни."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Опитахте да отключите таблета и сбъркахте <xliff:g id="NUMBER">%d</xliff:g> пъти. Той ще бъде нулиран, при което ще се изтрият всичките му данни."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Опитахте да отключите телефона и сбъркахте <xliff:g id="NUMBER">%d</xliff:g> пъти. Той ще бъде нулиран, при което ще се изтрият всичките му данни."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Опитахте да отключите таблета и сбъркахте <xliff:g id="NUMBER_0">%1$d</xliff:g> пъти. След още <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешни опита този потребител ще бъде премахнат, при което ще се изтрият всички данни за него."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Опитахте да отключите телефона и сбъркахте <xliff:g id="NUMBER_0">%1$d</xliff:g> пъти. След още <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешни опита този потребител ще бъде премахнат, при което ще се изтрият всички данни за него."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Опитахте да отключите таблета и сбъркахте <xliff:g id="NUMBER">%d</xliff:g> пъти. Този потребител ще бъде премахнат, при което ще се изтрият всички данни за него."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Опитахте да отключите телефона и сбъркахте <xliff:g id="NUMBER">%d</xliff:g> пъти. Този потребител ще бъде премахнат, при което ще се изтрият всички данни за него."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Опитахте да отключите таблета и сбъркахте <xliff:g id="NUMBER_0">%1$d</xliff:g> пъти. След още <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешни опита служебният потребителски профил ще бъде премахнат, при което ще се изтрият всички данни за него."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Опитахте да отключите телефона и сбъркахте <xliff:g id="NUMBER_0">%1$d</xliff:g> пъти. След още <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешни опита служебният потребителски профил ще бъде премахнат, при което ще се изтрият всички данни за него."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Опитахте да отключите таблета и сбъркахте <xliff:g id="NUMBER">%d</xliff:g> пъти. Служебният потребителски профил ще бъде премахнат, при което ще се изтрият всички данни за него."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Опитахте да отключите телефона и сбъркахте <xliff:g id="NUMBER">%d</xliff:g> пъти. Служебният потребителски профил ще бъде премахнат, при което ще се изтрият всички данни за него."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Начертахте неправилно фигурата си за отключване <xliff:g id="NUMBER_0">%1$d</xliff:g> пъти. След още <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешни опита ще бъдете помолени да отключите таблета си посредством имейл адрес.\n\n Опитайте отново след <xliff:g id="NUMBER_2">%3$d</xliff:g> секунди."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Начертахте неправилно фигурата си за отключване <xliff:g id="NUMBER_0">%1$d</xliff:g> пъти. След още <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешни опита ще бъдете помолени да отключите телефона посредством имейл адрес.\n\n Опитайте отново след <xliff:g id="NUMBER_2">%3$d</xliff:g> секунди."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-bn/strings.xml b/packages/SystemUI/res-product/values-bn/strings.xml
index 260f7bca8ba5..0b4cf71e0de4 100644
--- a/packages/SystemUI/res-product/values-bn/strings.xml
+++ b/packages/SystemUI/res-product/values-bn/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,46 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"ট্যাবলেটের মধ্যে কোনো সিম কার্ড নেই।"</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"ফোনের মধ্যে কোনো সিম কার্ড নেই।"</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"পিন কোডগুলি মিলছে না"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুলভাবে ট্যাবলেটটি আনলক করার চেষ্টা করেছেন। আরও <xliff:g id="NUMBER_1">%2$d</xliff:g> বার অসফল প্রচেষ্টার পর এই ট্যাবলেটটিকে রিসেট করা হবে, যার ফলে এর সমস্ত ডেটা মুছে যাবে।"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুলভাবে ফোনটি আনলক করার চেষ্টা করেছেন। আরও <xliff:g id="NUMBER_1">%2$d</xliff:g> বার অসফল প্রচেষ্টার পর এই ফোনটিকে রিসেট করা হবে, যার ফলে এর সমস্ত ডেটা মুছে যাবে।"</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"আপনি <xliff:g id="NUMBER">%d</xliff:g> বার ভুলভাবে ট্যাবলেটটি আনলক করার চেষ্টা করেছেন। এই ফোনটিকে রিসেট করা হবে, যার ফলে এর সমস্ত ডেটা মুছে যাবে।"</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"আপনি <xliff:g id="NUMBER">%d</xliff:g> বার ভুলভাবে ফোনটি আনলক করার চেষ্টা করেছেন। এই ফোনটিকে রিসেট করা হবে, যার ফলে এর সমস্ত ডেটা মুছে যাবে।"</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুলভাবে ট্যাবলেটটি আনলক করার চেষ্টা করেছেন। আরও <xliff:g id="NUMBER_1">%2$d</xliff:g> বার অসফল প্রচেষ্টার পর এই ব্যবহারকারীকে সরিয়ে দেওয়া হবে, যার ফলে ব্যবহারকারীর সমস্ত ডেটা মুছে যাবে।"</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুলভাবে ফোনটি আনলক করার চেষ্টা করেছেন। আরও <xliff:g id="NUMBER_1">%2$d</xliff:g> বার অসফল প্রচেষ্টার পর এই ব্যবহারকারীকে সরিয়ে দেওয়া হবে, যার ফলে ব্যবহারকারীর সমস্ত ডেটা মুছে যাবে।"</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for notification_bubble_title (8330481035191903164) -->
- <skip/>
- <!-- no translation found for notification_channel_summary_bubble (7235935211580860537) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Android TV ডিভাইস শীঘ্রই বন্ধ হয়ে যাবে, চালু রাখতে বোতাম প্রেস করুন।"</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"ডিভাইস শীঘ্রই বন্ধ হয়ে যাবে, চালু রাখতে প্রেস করুন।"</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"আপনি <xliff:g id="NUMBER">%d</xliff:g> বার ভুলভাবে ট্যাবলেটটি আনলক করার চেষ্টা করেছেন। কাজের প্রোফাইলটি সরিয়ে দেওয়া হবে, যার ফলে প্রোফাইলের সমস্ত ডেটা মুছে যাবে।"</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"আপনি <xliff:g id="NUMBER">%d</xliff:g> বার ভুলভাবে ফোনটি আনলক করার চেষ্টা করেছেন। কাজের প্রোফাইলটি সরিয়ে দেওয়া হবে, যার ফলে প্রোফাইলের সমস্ত ডেটা মুছে যাবে।"</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুলভাবে আনলকের প্যাটার্ন এঁকেছেন। আরও <xliff:g id="NUMBER_1">%2$d</xliff:g> বার অসফল প্রচেষ্টার পর আপনাকে একটি ইমেল অ্যাকাউন্টের মাধ্যমে আপনার ট্যাবলেটটি আনলক করতে বলা হবে।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> সেকেন্ডের মধ্যে আবার চেষ্টা করুন।"</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুলভাবে আনলকের প্যাটার্ন এঁকেছেন। আরও <xliff:g id="NUMBER_1">%2$d</xliff:g> বার অসফল প্রচেষ্টার পর আপনাকে একটি ইমেল অ্যাকাউন্টের মাধ্যমে আপনার ফোনটি আনলক করতে বলা হবে।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> সেকেন্ডের মধ্যে আবার চেষ্টা করুন।"</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"দ্রুত চার্জের জন্য ফোনটিকে সঠিকভাবে রাখুন"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"ওয়্যারলেস চার্জ করতে ফোনটিকে সঠিকভাবে রাখুন"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Android TV ডিভাইস শীঘ্রই বন্ধ হয়ে যাবে, চালু রাখতে বোতাম প্রেস করুন।"</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"ডিভাইস শীঘ্রই বন্ধ হয়ে যাবে, চালু রাখতে প্রেস করুন।"</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"ট্যাবলেটের মধ্যে কোনও সিম কার্ড নেই।"</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"ফোনে কোনও সিম কার্ড নেই।"</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"পিন কোডগুলি মিলছে না"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুল পদ্ধতিতে ট্যাবলেট আনলক করার চেষ্টা করেছেন। আরও <xliff:g id="NUMBER_1">%2$d</xliff:g> বার এটি করলে ট্যাবলেটটি রিসেট করা হবে এবং তার ফলে সমস্ত ডেটা মুছে যাবে।"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুল পদ্ধতিতে ফোন আনলক করার চেষ্টা করেছেন। আরও <xliff:g id="NUMBER_1">%2$d</xliff:g> বার এটি করলে ফোনটি রিসেট করা হবে এবং তার ফলে সমস্ত ডেটা মুছে যাবে।"</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"আপনি <xliff:g id="NUMBER">%d</xliff:g> বার ভুল পদ্ধতিতে ট্যাবলেট আনলক করার চেষ্টা করেছেন। এই ট্যাবলেটটি রিসেট করা হবে, যার ফলে এর সমস্ত ডেটা মুছে যাবে।"</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"আপনি <xliff:g id="NUMBER">%d</xliff:g> বার ভুল পদ্ধতিতে ফোন আনলক করার চেষ্টা করেছেন। এই ফোনটিকে রিসেট করা হবে, যার ফলে এর সমস্ত ডেটা মুছে যাবে।"</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুল পদ্ধতিতে ট্যাবলেট আনলক করার চেষ্টা করেছেন। আরও <xliff:g id="NUMBER_1">%2$d</xliff:g> বার এটি করলে ব্যবহারকারীকে সরিয়ে দেওয়া হবে এবং তার ফলে ব্যবহারকারীর সমস্ত ডেটা মুছে যাবে।"</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুল পদ্ধতিতে ফোন আনলক করার চেষ্টা করেছেন। আরও <xliff:g id="NUMBER_1">%2$d</xliff:g> বার এটি করলে ব্যবহারকারীকে সরিয়ে দেওয়া হবে এবং তার ফলে ব্যবহারকারীর সমস্ত ডেটা মুছে যাবে।"</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"আপনি <xliff:g id="NUMBER">%d</xliff:g> বার ভুল পদ্ধতিতে ট্যাবলেট আনলক করার চেষ্টা করেছেন। এই ব্যবহারকারীকে সরিয়ে দেওয়া হবে, যার ফলে ব্যবহারকারীর সমস্ত ডেটা মুছে যাবে।"</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"আপনি <xliff:g id="NUMBER">%d</xliff:g> বার ভুল পদ্ধতিতে ফোন আনলক করার চেষ্টা করেছেন। এই ব্যবহারকারীকে সরিয়ে দেওয়া হবে, যার ফলে ব্যবহারকারীর সমস্ত ডেটা মুছে যাবে।"</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুল পদ্ধতিতে ট্যাবলেটটি আনলক করার চেষ্টা করেছেন। আরও <xliff:g id="NUMBER_1">%2$d</xliff:g> বার এটি করলে অফিস প্রোফাইলটি সরিয়ে দেওয়া হবে এবং তার ফলে প্রোফাইলের সমস্ত ডেটা মুছে যাবে।"</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুল পদ্ধতিতে ফোন আনলক করার চেষ্টা করেছেন। আরও <xliff:g id="NUMBER_1">%2$d</xliff:g> বার এটি করলে অফিস প্রোফাইলটি সরিয়ে দেওয়া হবে এবং তার ফলে সমস্ত ডেটা মুছে যাবে।"</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"আপনি <xliff:g id="NUMBER">%d</xliff:g> বার ভুল পদ্ধতিতে ট্যাবলেট আনলক করার চেষ্টা করেছেন। অফিস প্রোফাইলটি সরিয়ে দেওয়া হবে, যার ফলে প্রোফাইলের সমস্ত ডেটা মুছে যাবে।"</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"আপনি <xliff:g id="NUMBER">%d</xliff:g> বার ভুল পদ্ধতিতে ফোন আনলক করার চেষ্টা করেছেন। অফিস প্রোফাইলটি সরিয়ে দেওয়া হবে, যার ফলে প্রোফাইলের সমস্ত ডেটা মুছে যাবে।"</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুল পদ্ধতিতে প্যাটার্ন আনলক করার চেষ্টা করেছেন। আরও <xliff:g id="NUMBER_1">%2$d</xliff:g> বার এটি করলে আপনাকে প্যাটার্ন আনলক করতে একটি ইমেল অ্যাকাউন্ট ব্যবহার করতে বলা হবে।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> সেকেন্ড পরে আবার চেষ্টা করুন।"</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুল পদ্ধতিতে প্যাটার্ন আনলক করার চেষ্টা করেছেন। আরও <xliff:g id="NUMBER_1">%2$d</xliff:g> বার এটি করলে আপনাকে প্যাটার্ন আনলক করতে একটি ইমেল অ্যাকাউন্ট ব্যবহারের করতে বলা হবে।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> সেকেন্ড পরে আবার চেষ্টা করুন।"</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-bs/strings.xml b/packages/SystemUI/res-product/values-bs/strings.xml
index b9beecf3f0f5..eb319943eb13 100644
--- a/packages/SystemUI/res-product/values-bs/strings.xml
+++ b/packages/SystemUI/res-product/values-bs/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,45 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"Nema SIM kartice u tabletu."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"Nema SIM kartice u telefonu."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"PIN-ovi se ne poklapaju"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Pokušali ste <xliff:g id="NUMBER_0">%1$d</xliff:g> puta neispravno otključati tablet. U slučaju još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja bez uspjeha, tablet će se vratiti na fabričke postavke i svi podaci će se izbrisati."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Pokušali ste <xliff:g id="NUMBER_0">%1$d</xliff:g> puta neispravno otključati telefon. U slučaju još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja bez uspjeha, telefon će se vratiti na fabričke postavke i svi podaci će se izbrisati."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Pokušali ste <xliff:g id="NUMBER">%d</xliff:g> puta neispravno otključati tablet. Tablet će se sada vratiti na fabričke postavke i svi podaci će se izbrisati."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Pokušali ste <xliff:g id="NUMBER">%d</xliff:g> puta neispravno otključati telefon. Telefon će se sada vratiti na fabričke postavke i svi podaci će se izbrisati."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Pokušali ste <xliff:g id="NUMBER_0">%1$d</xliff:g> puta neispravno otključati tablet. U slučaju još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja bez uspjeha, ovaj korisnik će se ukloniti i svi podaci korisnika će se izbrisati."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Pokušali ste <xliff:g id="NUMBER_0">%1$d</xliff:g> puta neispravno otključati telefon. U slučaju još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja bez uspjeha, ovaj korisnik će se ukloniti i svi podaci korisnika će se izbrisati."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- String.format failed for translation -->
- <!-- no translation found for volume_stream_content_description_unmute (7729576371406792977) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Android TV uređaj će se uskoro isključiti. Pritisnite dugme da ostane uključen."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Uređaj će se uskoro isključiti. Pritisnite da ostane uključen."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Pokušali ste <xliff:g id="NUMBER">%d</xliff:g> puta neispravno otključati tablet. Poslovni profil će se ukloniti i svi podaci s profila će se izbrisati."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Pokušali ste <xliff:g id="NUMBER">%d</xliff:g> puta neispravno otključati telefon. Poslovni profil će se ukloniti i svi podaci s profila će se izbrisati."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Pogrešno ste nacrtali uzorak za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. U slučaju još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja bez uspjeha, od vas će se tražiti da tablet otključate koristeći račun e-pošte.\n\n Pokušajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Pogrešno ste nacrtali uzorak za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. U slučaju još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja bez uspjeha, od vas će se tražiti da telefon otključate koristeći račun e-pošte.\n\n Pokušajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Ponovo poravnajte telefon radi bržeg punjenja"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Ponovo poravnajte telefon radi bežičnog punjenja"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Android TV uređaj će se uskoro isključiti. Pritisnite neko dugme da ostane uključen."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Uređaj će se uskoro isključiti. Pritisnite da ostane uključen."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Nema SIM kartice u tabletu."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Nema SIM kartice u telefonu."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"PIN-ovi se ne podudaraju"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Pokušali ste neispravno otključati tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. U slučaju još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja bez uspjeha, tablet će se vratiti na zadano i svi podaci će se izbrisati."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Pokušali ste neispravno otključati tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. U slučaju još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja bez uspjeha, telefon će se vratiti na zadano i svi podaci će se izbrisati."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Pokušali ste neispravno otključati tablet <xliff:g id="NUMBER">%d</xliff:g> puta. Tablet će se vratiti na zadano i svi podaci će se izbrisati."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Pokušali ste neispravno otključati telefon <xliff:g id="NUMBER">%d</xliff:g> puta. Telefon će se vratiti na zadano i svi podaci će se izbrisati."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Pokušali ste neispravno otključati tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. U slučaju još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja bez uspjeha, ovaj korisnik će se ukloniti i svi podaci korisnika će se izbrisati."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Pokušali ste neispravno otključati telefon <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. U slučaju još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja bez uspjeha, ovaj korisnik će se ukloniti i svi podaci korisnika će se izbrisati."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Pokušali ste neispravno otključati tablet <xliff:g id="NUMBER">%d</xliff:g> puta. Korisnik će se ukloniti i svi podaci korisnika će se izbrisati."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Pokušali ste neispravno otključati telefon <xliff:g id="NUMBER">%d</xliff:g> puta. Korisnik će se ukloniti i svi podaci korisnika će se izbrisati."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Pokušali ste neispravno otključati tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. U slučaju još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja bez uspjeha, radni profil će se ukloniti i svi podaci s profila će se izbrisati."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Pokušali ste neispravno otključati telefon <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. U slučaju još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja bez uspjeha, radni profil će se ukloniti i svi podaci s profila će se izbrisati."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Pokušali ste neispravno otključati tablet <xliff:g id="NUMBER">%d</xliff:g> puta. Radni profil će se ukloniti i svi podaci s profila će se izbrisati."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Pokušali ste neispravno otključati telefon <xliff:g id="NUMBER">%d</xliff:g> puta. Radni profil će se ukloniti i svi podaci s profila će se izbrisati."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Pogrešno ste nacrtali uzorak za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. U slučaju još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja bez uspjeha, od vas će se tražiti da otključate tablet pomoću računa e-pošte. \n\n Pokušajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Pogrešno ste nacrtali uzorak za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. U slučaju još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja bez uspjeha, od vas će se tražiti da otključate telefon pomoću računa e-pošte. \n\n Pokušajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-ca/strings.xml b/packages/SystemUI/res-product/values-ca/strings.xml
index 20d8e2fc1fec..8c5c83ac2fac 100644
--- a/packages/SystemUI/res-product/values-ca/strings.xml
+++ b/packages/SystemUI/res-product/values-ca/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"No hi ha cap SIM a la tauleta."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"No hi ha cap SIM al telèfon."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"Els codis PIN no coincideixen"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Has provat de desbloquejar la tauleta <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. Si falles <xliff:g id="NUMBER_1">%2$d</xliff:g> vegades més, la tauleta es restablirà i se\'n suprimiran totes les dades."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Has provat de desbloquejar el telèfon <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. Si falles <xliff:g id="NUMBER_1">%2$d</xliff:g> vegades més, el telèfon es restablirà i se\'n suprimiran totes les dades."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Has provat de desbloquejar la tauleta <xliff:g id="NUMBER">%d</xliff:g> vegades de manera incorrecta. La tauleta es restablirà i se\'n suprimiran totes les dades."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Has provat de desbloquejar el telèfon <xliff:g id="NUMBER">%d</xliff:g> vegades de manera incorrecta. El telèfon es restablirà i se\'n suprimiran totes les dades."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Has provat de desbloquejar la tauleta <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. Si falles <xliff:g id="NUMBER_1">%2$d</xliff:g> vegades més, l\'usuari se suprimirà, juntament amb totes les seves dades."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Has provat de desbloquejar el telèfon <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. Si falles <xliff:g id="NUMBER_1">%2$d</xliff:g> vegades més, l\'usuari se suprimirà, juntament amb totes les seves dades."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"El dispositiu Android TV s\'apagarà aviat; prem un botó per mantenir-lo encès."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"El dispositiu s\'apagarà aviat; prem per mantenir-lo encès."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Has provat de desbloquejar la tauleta <xliff:g id="NUMBER">%d</xliff:g> vegades de manera incorrecta. El perfil professional se suprimirà, juntament amb totes les dades que contingui."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Has provat de desbloquejar el telèfon <xliff:g id="NUMBER">%d</xliff:g> vegades de manera incorrecta. El perfil professional se suprimirà, juntament amb totes les dades que contingui."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Has dibuixat el patró de desbloqueig <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. Si falles <xliff:g id="NUMBER_1">%2$d</xliff:g> vegades més, se\'t demanarà que desbloquegis la tauleta amb un compte de correu electrònic.\n\n Torna-ho a provar d\'aquí a <xliff:g id="NUMBER_2">%3$d</xliff:g> segons."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Has dibuixat el patró de desbloqueig <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. Si falles <xliff:g id="NUMBER_1">%2$d</xliff:g> vegades més, se\'t demanarà que desbloquegis el telèfon amb un compte de correu electrònic.\n\n Torna-ho a provar d\'aquí a <xliff:g id="NUMBER_2">%3$d</xliff:g> segons."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Col·loca bé el telèfon per carregar-lo més ràpidament"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Col·loca bé el telèfon per carregar-lo sense fil"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"El dispositiu Android TV s\'apagarà aviat; prem un botó per mantenir-lo encès."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"El dispositiu s\'apagarà aviat; prem per mantenir-lo encès."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"No hi ha cap targeta SIM a la tauleta."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"No hi ha cap targeta SIM al telèfon."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"Els codis PIN no coincideixen"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Has provat de desbloquejar la tauleta <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. Si falles <xliff:g id="NUMBER_1">%2$d</xliff:g> vegades més, la tauleta es restablirà i se\'n suprimiran totes les dades."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Has provat de desbloquejar el telèfon <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. Si falles <xliff:g id="NUMBER_1">%2$d</xliff:g> vegades més, el telèfon es restablirà i se\'n suprimiran totes les dades."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Has provat de desbloquejar la tauleta <xliff:g id="NUMBER">%d</xliff:g> vegades de manera incorrecta. La tauleta es restablirà i se\'n suprimiran totes les dades."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Has provat de desbloquejar el telèfon <xliff:g id="NUMBER">%d</xliff:g> vegades de manera incorrecta. El telèfon es restablirà i se\'n suprimiran totes les dades."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Has provat de desbloquejar la tauleta <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. Si falles <xliff:g id="NUMBER_1">%2$d</xliff:g> vegades més, l\'usuari se suprimirà, juntament amb totes les seves dades."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Has provat de desbloquejar el telèfon <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. Si falles <xliff:g id="NUMBER_1">%2$d</xliff:g> vegades més, l\'usuari se suprimirà, juntament amb totes les seves dades."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Has provat de desbloquejar la tauleta <xliff:g id="NUMBER">%d</xliff:g> vegades de manera incorrecta. L\'usuari se suprimirà, juntament amb totes les seves dades."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Has provat de desbloquejar el telèfon <xliff:g id="NUMBER">%d</xliff:g> vegades de manera incorrecta. L\'usuari se suprimirà, juntament amb totes les seves dades."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Has provat de desbloquejar la tauleta <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. Si falles <xliff:g id="NUMBER_1">%2$d</xliff:g> vegades més, el perfil professional se suprimirà, juntament amb totes les dades que contingui."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Has provat de desbloquejar el telèfon <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. Si falles <xliff:g id="NUMBER_1">%2$d</xliff:g> vegades més, el perfil professional se suprimirà, juntament amb totes les dades que contingui."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Has provat de desbloquejar la tauleta <xliff:g id="NUMBER">%d</xliff:g> vegades de manera incorrecta. El perfil professional se suprimirà, juntament amb totes les dades que contingui."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Has provat de desbloquejar el telèfon <xliff:g id="NUMBER">%d</xliff:g> vegades de manera incorrecta. El perfil professional se suprimirà, juntament amb totes les dades que contingui."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Has dibuixat el patró de desbloqueig <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. Si falles <xliff:g id="NUMBER_1">%2$d</xliff:g> vegades més, se\'t demanarà que desbloquegis la tauleta amb un compte de correu electrònic.\n\n Torna-ho a provar d\'aquí a <xliff:g id="NUMBER_2">%3$d</xliff:g> segons."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Has dibuixat el patró de desbloqueig <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. Si falles <xliff:g id="NUMBER_1">%2$d</xliff:g> vegades més, se\'t demanarà que desbloquegis el telèfon amb un compte de correu electrònic.\n\n Torna-ho a provar d\'aquí a <xliff:g id="NUMBER_2">%3$d</xliff:g> segons."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-cs/strings.xml b/packages/SystemUI/res-product/values-cs/strings.xml
index feb3d950bb59..b54c5b7ba6e6 100644
--- a/packages/SystemUI/res-product/values-cs/strings.xml
+++ b/packages/SystemUI/res-product/values-cs/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"V tabletu není SIM karta."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"V telefonu není SIM karta."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"Kódy PIN se neshodují"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Již jste se <xliff:g id="NUMBER_0">%1$d</xliff:g>krát pokusili odemknout tablet nesprávným způsobem. Po <xliff:g id="NUMBER_1">%2$d</xliff:g> dalších neúspěšných pokusech bude tablet resetován, čímž se z něj smažou všechna data."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Již jste se <xliff:g id="NUMBER_0">%1$d</xliff:g>krát pokusili odemknout telefon nesprávným způsobem. Po <xliff:g id="NUMBER_1">%2$d</xliff:g> dalších neúspěšných pokusech bude telefon resetován, čímž se z něj smažou všechna data."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Již jste se <xliff:g id="NUMBER">%d</xliff:g>krát pokusili odemknout tablet nesprávným způsobem. Tablet bude resetován, čímž z něj budou smazána všechna data."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Již jste se <xliff:g id="NUMBER">%d</xliff:g>krát pokusili odemknout telefon nesprávným způsobem. Telefon bude resetován, čímž z něj budou smazána všechna data."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Již jste se <xliff:g id="NUMBER_0">%1$d</xliff:g>krát pokusili odemknout tablet nesprávným způsobem. Po <xliff:g id="NUMBER_1">%2$d</xliff:g> dalších neúspěšných pokusech bude tento uživatel odstraněn, čímž se smažou všechna jeho data."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Již jste se <xliff:g id="NUMBER_0">%1$d</xliff:g>krát pokusili odemknout telefon nesprávným způsobem. Po <xliff:g id="NUMBER_1">%2$d</xliff:g> dalších neúspěšných pokusech bude tento uživatel odstraněn, čímž se smažou všechna jeho data."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Zařízení Android TV se brzy vypne, stisknutím tlačítka ho ponecháte zapnuté."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Zařízení se brzy vypne, stisknutím ho ponecháte zapnuté."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Již jste se <xliff:g id="NUMBER">%d</xliff:g>krát pokusili odemknout tablet nesprávným způsobem. Pracovní profil bude odstraněn, čímž budou smazána všechna jeho data."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Již jste se <xliff:g id="NUMBER">%d</xliff:g>krát pokusili odemknout telefon nesprávným způsobem. Pracovní profil bude odstraněn, čímž budou smazána všechna jeho data."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Již <xliff:g id="NUMBER_0">%1$d</xliff:g>krát jste nesprávně zadali své bezpečnostní gesto. Po <xliff:g id="NUMBER_1">%2$d</xliff:g>dalších neúspěšných pokusech budete požádáni o odemčení tabletu pomocí e-mailového účtu.\n\n Zkuste to znovu za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Již <xliff:g id="NUMBER_0">%1$d</xliff:g>krát jste nesprávně zadali své bezpečnostní gesto. Po <xliff:g id="NUMBER_1">%2$d</xliff:g> dalších neúspěšných pokusech budete požádáni o odemčení telefonu pomocí e-mailového účtu.\n\n Zkuste to znovu za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Zarovnejte telefon, aby se nabíjel rychleji"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Zarovnejte telefon, aby se nabíjel bezdrátově"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Zařízení Android TV se brzy vypne, stisknutím tlačítka ho ponecháte zapnuté."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Zařízení se brzy vypne, stisknutím ho ponecháte zapnuté."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"V tabletu není SIM karta."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"V telefonu není SIM karta."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"Kódy PIN se neshodují"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Již <xliff:g id="NUMBER_0">%1$d</xliff:g>krát jste se pokusili odemknout tablet nesprávným způsobem. Po <xliff:g id="NUMBER_1">%2$d</xliff:g> dalších neúspěšných pokusech bude tablet resetován, čímž se z něj smažou všechna data."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Již <xliff:g id="NUMBER_0">%1$d</xliff:g>krát jste se pokusili odemknout telefon nesprávným způsobem. Po <xliff:g id="NUMBER_1">%2$d</xliff:g> dalších neúspěšných pokusech bude telefon resetován, čímž se z něj smažou všechna data."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Již <xliff:g id="NUMBER">%d</xliff:g>krát jste se pokusili odemknout tablet nesprávným způsobem. Tablet bude resetován, čímž z něj budou smazána všechna data."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Již <xliff:g id="NUMBER">%d</xliff:g>krát jste se pokusili odemknout telefon nesprávným způsobem. Telefon bude resetován, čímž z něj budou smazána všechna data."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Již <xliff:g id="NUMBER_0">%1$d</xliff:g>krát jste se pokusili odemknout tablet nesprávným způsobem. Po <xliff:g id="NUMBER_1">%2$d</xliff:g> dalších neúspěšných pokusech bude tento uživatel odstraněn, čímž se smažou všechna jeho data."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Již <xliff:g id="NUMBER_0">%1$d</xliff:g>krát jste se pokusili odemknout telefon nesprávným způsobem. Po <xliff:g id="NUMBER_1">%2$d</xliff:g> dalších neúspěšných pokusech bude tento uživatel odstraněn, čímž se smažou všechna jeho data."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Již <xliff:g id="NUMBER">%d</xliff:g>krát jste se pokusili odemknout tablet nesprávným způsobem. Uživatel bude odstraněn, čímž budou smazána všechna jeho data."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Již <xliff:g id="NUMBER">%d</xliff:g>krát jste se pokusili odemknout telefon nesprávným způsobem. Uživatel bude odstraněn, čímž budou smazána všechna jeho data."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Již <xliff:g id="NUMBER_0">%1$d</xliff:g>krát jste se pokusili odemknout tablet nesprávným způsobem. Po <xliff:g id="NUMBER_1">%2$d</xliff:g> dalších neúspěšných pokusech bude pracovní profil odstraněn, čímž se smažou všechna jeho data."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Již <xliff:g id="NUMBER_0">%1$d</xliff:g>krát jste se pokusili odemknout telefon nesprávným způsobem. Po <xliff:g id="NUMBER_1">%2$d</xliff:g> dalších neúspěšných pokusech bude pracovní profil odstraněn, čímž se smažou všechna jeho data."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Již <xliff:g id="NUMBER">%d</xliff:g>krát jste se pokusili odemknout tablet nesprávným způsobem. Pracovní profil bude odstraněn, čímž budou smazána všechna jeho data."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Již <xliff:g id="NUMBER">%d</xliff:g>krát jste se pokusili odemknout telefon nesprávným způsobem. Pracovní profil bude odstraněn, čímž budou smazána všechna jeho data."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Již <xliff:g id="NUMBER_0">%1$d</xliff:g>krát jste nesprávně zadali své bezpečnostní gesto. Po <xliff:g id="NUMBER_1">%2$d</xliff:g>dalších neúspěšných pokusech budete požádáni o odemčení tabletu pomocí e-mailového účtu.\n\n Zkuste to znovu za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Již <xliff:g id="NUMBER_0">%1$d</xliff:g>krát jste nesprávně zadali své bezpečnostní gesto. Po <xliff:g id="NUMBER_1">%2$d</xliff:g> dalších neúspěšných pokusech budete požádáni o odemčení telefonu pomocí e-mailového účtu.\n\n Zkuste to znovu za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-da/strings.xml b/packages/SystemUI/res-product/values-da/strings.xml
index 0a7135c40776..040c63dc55fb 100644
--- a/packages/SystemUI/res-product/values-da/strings.xml
+++ b/packages/SystemUI/res-product/values-da/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"Der er ikke noget SIM-kort i denne tablet."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"Der er ikke noget SIM-kort i telefonen."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"Pinkoderne stemmer ikke overens"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Du har forsøgt at låse denne tablet op med den forkerte adgangskode <xliff:g id="NUMBER_0">%1$d</xliff:g> gange. Efter endnu <xliff:g id="NUMBER_1">%2$d</xliff:g> mislykkede forsøg nulstilles denne tablet, hvilket sletter alle dens data."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Du har forsøgt at låse telefonen op med den forkerte adgangskode <xliff:g id="NUMBER_0">%1$d</xliff:g> gange. Efter endnu <xliff:g id="NUMBER_1">%2$d</xliff:g> mislykkede forsøg nulstilles denne telefon, hvilket sletter alle dens data."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Du har forsøgt at låse denne tablet op på forkert vis <xliff:g id="NUMBER">%d</xliff:g> gange. Denne tablet nulstilles, hvilket sletter alle dens data."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Du har forsøgt at låse telefonen op på forkert vis <xliff:g id="NUMBER">%d</xliff:g> gange. Telefonen nulstilles, hvilket sletter alle dens data."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Du har forsøgt at låse denne tablet op med den forkerte adgangskode <xliff:g id="NUMBER_0">%1$d</xliff:g> gange. Efter endnu <xliff:g id="NUMBER_1">%2$d</xliff:g> mislykkede forsøg fjernes denne bruger, hvilket sletter alle brugerdata."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Du har forsøgt at låse telefonen op med den forkerte adgangskode <xliff:g id="NUMBER_0">%1$d</xliff:g> gange. Efter endnu <xliff:g id="NUMBER_1">%2$d</xliff:g> mislykkede forsøg fjernes denne bruger, hvilket sletter alle brugerdata."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Android TV-enheden slukker snart. Tryk på en knap for at holde den tændt."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Enheden slukker snart. Tryk for at holde den tændt."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Du har forsøgt at låse denne tablet op på forkert vis <xliff:g id="NUMBER">%d</xliff:g> gange. Arbejdsprofilen fjernes, hvilket sletter alle profildata."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Du har forsøgt at låse telefonen op på forkert vis <xliff:g id="NUMBER">%d</xliff:g> gange. Arbejdsprofilen fjernes, hvilket sletter alle profildata."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Du har tegnet dit oplåsningsmønster forkert <xliff:g id="NUMBER_0">%1$d</xliff:g> gange. Efter endnu <xliff:g id="NUMBER_1">%2$d</xliff:g> mislykkede forsøg bliver du bedt om at låse din tablet op ved hjælp af en mailkonto.\n\n Prøv igen om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Du har tegnet dit oplåsningsmønster forkert <xliff:g id="NUMBER_0">%1$d</xliff:g> gange. Efter endnu <xliff:g id="NUMBER_1">%2$d</xliff:g> mislykkede forsøg bliver du bedt om at låse din telefon op ved hjælp af en mailkonto.\n\n Prøv igen om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Juster telefonens placering for at oplade den hurtigere"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Juster telefonens placering for at oplade den trådløst"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Android TV-enheden slukker snart. Tryk på en knap for at holde den tændt."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Enheden slukker snart. Tryk for at holde den tændt."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Der er ikke noget SIM-kort i denne tablet."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Der er ikke noget SIM-kort i telefonen."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"Pinkoderne stemmer ikke overens"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Du har forsøgt at låse denne tablet op med den forkerte adgangskode <xliff:g id="NUMBER_0">%1$d</xliff:g> gange. Efter endnu <xliff:g id="NUMBER_1">%2$d</xliff:g> mislykkede forsøg nulstilles denne tablet, hvilket sletter alle dens data."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Du har forsøgt at låse telefonen op med den forkerte adgangskode <xliff:g id="NUMBER_0">%1$d</xliff:g> gange. Efter endnu <xliff:g id="NUMBER_1">%2$d</xliff:g> mislykkede forsøg nulstilles denne telefon, hvilket sletter alle dens data."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Du har forsøgt at låse denne tablet op på forkert vis <xliff:g id="NUMBER">%d</xliff:g> gange. Denne tablet nulstilles, hvilket sletter alle dens data."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Du har forsøgt at låse telefonen op på forkert vis <xliff:g id="NUMBER">%d</xliff:g> gange. Telefonen nulstilles, hvilket sletter alle dens data."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Du har forsøgt at låse denne tablet op med den forkerte adgangskode <xliff:g id="NUMBER_0">%1$d</xliff:g> gange. Efter endnu <xliff:g id="NUMBER_1">%2$d</xliff:g> mislykkede forsøg fjernes denne bruger, hvilket sletter alle brugerdata."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Du har forsøgt at låse telefonen op med den forkerte adgangskode <xliff:g id="NUMBER_0">%1$d</xliff:g> gange. Efter endnu <xliff:g id="NUMBER_1">%2$d</xliff:g> mislykkede forsøg fjernes denne bruger, hvilket sletter alle brugerdata."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Du har forsøgt at låse denne tablet op på forkert vis <xliff:g id="NUMBER">%d</xliff:g> gange. Brugeren fjernes, hvilket sletter alle brugerdata."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Du har forsøgt at låse telefonen op på forkert vis <xliff:g id="NUMBER">%d</xliff:g> gange. Brugeren fjernes, hvilket sletter alle brugerdata."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Du har forsøgt at låse denne tablet op med den forkerte adgangskode <xliff:g id="NUMBER_0">%1$d</xliff:g> gange. Efter endnu <xliff:g id="NUMBER_1">%2$d</xliff:g> mislykkede forsøg fjernes arbejdsprofilen, hvilket sletter alle profildata."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Du har forsøgt at låse telefonen op med den forkerte adgangskode <xliff:g id="NUMBER_0">%1$d</xliff:g> gange. Efter endnu <xliff:g id="NUMBER_1">%2$d</xliff:g> mislykkede forsøg fjernes arbejdsprofilen, hvilket sletter alle profildata."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Du har forsøgt at låse denne tablet op med den forkerte adgangskode <xliff:g id="NUMBER">%d</xliff:g> gange. Arbejdsprofilen fjernes, hvilket sletter alle profildata."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Du har forsøgt at låse telefonen op med den forkerte adgangskode <xliff:g id="NUMBER">%d</xliff:g> gange. Arbejdsprofilen fjernes, hvilket sletter alle profildata."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Du har tegnet dit oplåsningsmønster forkert <xliff:g id="NUMBER_0">%1$d</xliff:g> gange. Efter endnu <xliff:g id="NUMBER_1">%2$d</xliff:g> mislykkede forsøg bliver du bedt om at låse din tablet op ved hjælp af en mailkonto.\n\n Prøv igen om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Du har tegnet dit oplåsningsmønster forkert <xliff:g id="NUMBER_0">%1$d</xliff:g> gange. Efter endnu <xliff:g id="NUMBER_1">%2$d</xliff:g> mislykkede forsøg bliver du bedt om at låse din telefon op ved hjælp af en mailkonto.\n\n Prøv igen om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-de/strings.xml b/packages/SystemUI/res-product/values-de/strings.xml
index 0c0c5138be9d..c7b738cb0fbe 100644
--- a/packages/SystemUI/res-product/values-de/strings.xml
+++ b/packages/SystemUI/res-product/values-de/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,48 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"Keine SIM-Karte im Tablet."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"Keine SIM-Karte im Telefon."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"PIN-Codes stimmen nicht überein"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Du hast <xliff:g id="NUMBER_0">%1$d</xliff:g>-mal erfolglos versucht, das Tablet zu entsperren. Nach <xliff:g id="NUMBER_1">%2$d</xliff:g> weiteren erfolglosen Versuchen wird dieses Tablet zurückgesetzt. Dadurch werden alle Gerätedaten gelöscht."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Du hast <xliff:g id="NUMBER_0">%1$d</xliff:g>-mal erfolglos versucht, das Telefon zu entsperren. Nach <xliff:g id="NUMBER_1">%2$d</xliff:g> weiteren erfolglosen Versuchen wird dieses Telefon zurückgesetzt. Dadurch werden alle Gerätedaten gelöscht."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Du hast <xliff:g id="NUMBER">%d</xliff:g>-mal erfolglos versucht, das Tablet zu entsperren. Dieses Tablet wird nun zurückgesetzt und alle Gerätedaten werden gelöscht."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Du hast <xliff:g id="NUMBER">%d</xliff:g>-mal erfolglos versucht, das Telefon zu entsperren. Dieses Telefon wird nun zurückgesetzt und alle Gerätedaten werden gelöscht."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Du hast <xliff:g id="NUMBER_0">%1$d</xliff:g>-mal erfolglos versucht, das Tablet zu entsperren. Nach <xliff:g id="NUMBER_1">%2$d</xliff:g> weiteren erfolglosen Versuchen wird dieser Nutzer entfernt. Dadurch werden alle Nutzerdaten gelöscht."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Du hast <xliff:g id="NUMBER_0">%1$d</xliff:g>-mal erfolglos versucht, das Telefon zu entsperren. Nach <xliff:g id="NUMBER_1">%2$d</xliff:g> weiteren erfolglosen Versuchen wird dieser Nutzer entfernt. Dadurch werden alle Nutzerdaten gelöscht."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- String.format failed for translation -->
- <!-- no translation found for accessibility_battery_level (5143715405241138822) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- String.format failed for translation -->
- <!-- no translation found for accessibility_battery_level_charging (8892191177774027364) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Das Android TV-Gerät wird demnächst abgeschaltet. Drücke eine Taste, damit es eingeschaltet bleibt."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Das Gerät wird demnächst abgeschaltet. Drücke beispielsweise eine Taste oder berühre den Bildschirm, damit es eingeschaltet bleibt."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Du hast <xliff:g id="NUMBER">%d</xliff:g>-mal erfolglos versucht, das Tablet zu entsperren. Das Arbeitsprofil wird nun entfernt und alle Profildaten werden gelöscht."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Du hast <xliff:g id="NUMBER">%d</xliff:g>-mal erfolglos versucht, das Telefon zu entsperren. Das Arbeitsprofil wird nun entfernt und alle Profildaten werden gelöscht."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Du hast dein Entsperrungsmuster <xliff:g id="NUMBER_0">%1$d</xliff:g>-mal falsch gezeichnet. Nach <xliff:g id="NUMBER_1">%2$d</xliff:g> weiteren erfolglosen Versuchen wirst du aufgefordert, dein Tablet mithilfe eines E-Mail-Kontos zu entsperren.\n\n Versuche es in <xliff:g id="NUMBER_2">%3$d</xliff:g> Sekunden noch einmal."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Du hast dein Entsperrungsmuster <xliff:g id="NUMBER_0">%1$d</xliff:g>-mal falsch gezeichnet. Nach <xliff:g id="NUMBER_1">%2$d</xliff:g> weiteren erfolglosen Versuchen wirst du aufgefordert, dein Telefon mithilfe eines E-Mail-Kontos zu entsperren.\n\n Versuche es in <xliff:g id="NUMBER_2">%3$d</xliff:g> Sekunden noch einmal."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Smartphone genau platzieren, um es schneller zu laden"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Smartphone genau platzieren, um es kabellos zu laden"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Das Android TV-Gerät wird gleich ausgeschaltet. Falls es eingeschaltet bleiben soll, drücke beispielsweise eine Taste oder berühre den Bildschirm."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Das Gerät wird gleich ausgeschaltet. Falls es eingeschaltet bleiben soll, drücke beispielsweise eine Taste oder berühre den Bildschirm."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Keine SIM-Karte im Tablet."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Keine SIM-Karte im Smartphone."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"PIN-Codes stimmen nicht überein"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Du hast <xliff:g id="NUMBER_0">%1$d</xliff:g>-mal erfolglos versucht, das Tablet zu entsperren. Nach <xliff:g id="NUMBER_1">%2$d</xliff:g> weiteren erfolglosen Versuchen wird dieses Tablet zurückgesetzt. Dadurch werden alle Gerätedaten gelöscht."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Du hast <xliff:g id="NUMBER_0">%1$d</xliff:g>-mal erfolglos versucht, das Smartphone zu entsperren. Nach <xliff:g id="NUMBER_1">%2$d</xliff:g> weiteren erfolglosen Versuchen wird es zurückgesetzt. Dadurch werden alle Gerätedaten gelöscht."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Du hast <xliff:g id="NUMBER">%d</xliff:g>-mal erfolglos versucht, das Tablet zu entsperren. Es wird nun zurückgesetzt und alle Gerätedaten werden gelöscht."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Du hast <xliff:g id="NUMBER">%d</xliff:g>-mal erfolglos versucht, das Smartphone zu entsperren. Es wird nun zurückgesetzt und alle Gerätedaten werden gelöscht."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Du hast <xliff:g id="NUMBER_0">%1$d</xliff:g>-mal erfolglos versucht, das Tablet zu entsperren. Nach <xliff:g id="NUMBER_1">%2$d</xliff:g> weiteren erfolglosen Versuchen wird dieser Nutzer entfernt. Dadurch werden alle Nutzerdaten gelöscht."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Du hast <xliff:g id="NUMBER_0">%1$d</xliff:g>-mal erfolglos versucht, das Smartphone zu entsperren. Nach <xliff:g id="NUMBER_1">%2$d</xliff:g> weiteren erfolglosen Versuchen wird dieser Nutzer entfernt. Dadurch werden alle Nutzerdaten gelöscht."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Du hast <xliff:g id="NUMBER">%d</xliff:g>-mal erfolglos versucht, das Tablet zu entsperren. Dieser Nutzer wird nun entfernt und alle Nutzerdaten werden gelöscht."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Du hast <xliff:g id="NUMBER">%d</xliff:g>-mal erfolglos versucht, das Smartphone zu entsperren. Dieser Nutzer wird nun entfernt und alle Nutzerdaten werden gelöscht."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Du hast <xliff:g id="NUMBER_0">%1$d</xliff:g>-mal erfolglos versucht, das Tablet zu entsperren. Nach <xliff:g id="NUMBER_1">%2$d</xliff:g> weiteren erfolglosen Versuchen wird das Arbeitsprofil entfernt. Dadurch werden alle Profildaten gelöscht."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Du hast <xliff:g id="NUMBER_0">%1$d</xliff:g>-mal erfolglos versucht, das Smartphone zu entsperren. Nach <xliff:g id="NUMBER_1">%2$d</xliff:g> weiteren erfolglosen Versuchen wird das Arbeitsprofil entfernt. Dadurch werden alle Profildaten gelöscht."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Du hast <xliff:g id="NUMBER">%d</xliff:g>-mal erfolglos versucht, das Tablet zu entsperren. Das Arbeitsprofil wird nun entfernt und alle Profildaten werden gelöscht."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Du hast <xliff:g id="NUMBER">%d</xliff:g>-mal erfolglos versucht, das Smartphone zu entsperren. Das Arbeitsprofil wird nun entfernt und alle Profildaten werden gelöscht."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Du hast dein Entsperrungsmuster <xliff:g id="NUMBER_0">%1$d</xliff:g>-mal falsch gezeichnet. Nach <xliff:g id="NUMBER_1">%2$d</xliff:g> weiteren erfolglosen Versuchen wirst du aufgefordert, dein Tablet mithilfe eines E-Mail-Kontos zu entsperren.\n\n Versuche es in <xliff:g id="NUMBER_2">%3$d</xliff:g> Sekunden noch einmal."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Du hast dein Entsperrungsmuster <xliff:g id="NUMBER_0">%1$d</xliff:g>-mal falsch gezeichnet. Nach <xliff:g id="NUMBER_1">%2$d</xliff:g> weiteren erfolglosen Versuchen wirst du aufgefordert, dein Smartphone mithilfe eines E-Mail-Kontos zu entsperren.\n\n Versuche es in <xliff:g id="NUMBER_2">%3$d</xliff:g> Sekunden noch einmal."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-el/strings.xml b/packages/SystemUI/res-product/values-el/strings.xml
index cd76dac0879f..d9cf683a4bbe 100644
--- a/packages/SystemUI/res-product/values-el/strings.xml
+++ b/packages/SystemUI/res-product/values-el/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"Δεν υπάρχει κάρτα SIM στο tablet."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"Δεν υπάρχει κάρτα SIM στο τηλέφωνο."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"Δεν υπάρχει αντιστοιχία μεταξύ των κωδικών PIN"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Δοκιμάσατε να ξεκλειδώσετε το tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> φορές χωρίς επιτυχία. Μετά από <xliff:g id="NUMBER_1">%2$d</xliff:g> ακόμα ανεπιτυχείς προσπάθειες, αυτό το tablet θα ρυθμιστεί εκ νέου και θα διαγραφούν όλα τα δεδομένα του."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Δοκιμάσατε να ξεκλειδώσετε το τηλέφωνο <xliff:g id="NUMBER_0">%1$d</xliff:g> φορές χωρίς επιτυχία. Μετά από <xliff:g id="NUMBER_1">%2$d</xliff:g> ακόμα ανεπιτυχείς προσπάθειες, αυτό το τηλέφωνο θα ρυθμιστεί εκ νέου και θα διαγραφούν όλα τα δεδομένα του."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Δοκιμάσατε να ξεκλειδώσετε αυτό το tablet <xliff:g id="NUMBER">%d</xliff:g> φορές χωρίς επιτυχία. Αυτό το tablet θα ρυθμιστεί εκ νέου και θα διαγραφούν όλα τα δεδομένα του."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Δοκιμάσατε να ξεκλειδώσετε το τηλέφωνο <xliff:g id="NUMBER">%d</xliff:g> φορές χωρίς επιτυχία. Αυτό το τηλέφωνο θα ρυθμιστεί εκ νέου και θα διαγραφούν όλα τα δεδομένα του."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Δοκιμάσατε να ξεκλειδώσετε το tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> φορές χωρίς επιτυχία. Μετά από <xliff:g id="NUMBER_1">%2$d</xliff:g> ακόμα ανεπιτυχείς προσπάθειες, αυτός ο χρήστης θα καταργηθεί και θα διαγραφούν όλα τα δεδομένα χρήστη."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Δοκιμάσατε να ξεκλειδώσετε το τηλέφωνο <xliff:g id="NUMBER_0">%1$d</xliff:g> φορές χωρίς επιτυχία. Μετά από <xliff:g id="NUMBER_1">%2$d</xliff:g> ακόμα ανεπιτυχείς προσπάθειες, αυτός ο χρήστης θα καταργηθεί και θα διαγραφούν όλα τα δεδομένα χρήστη."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Η συσκευή Android TV σύντομα θα απενεργοποιηθεί. Πατήστε ένα κουμπί για να την κρατήσετε ενεργοποιημένη."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Η συσκευή σύντομα θα απενεργοποιηθεί. Πατήστε για να την κρατήσετε ενεργοποιημένη."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Δοκιμάσατε να ξεκλειδώσετε το tablet <xliff:g id="NUMBER">%d</xliff:g> φορές χωρίς επιτυχία. Το προφίλ εργασίας θα καταργηθεί και θα διαγραφούν όλα τα δεδομένα προφίλ."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Δοκιμάσατε να ξεκλειδώσετε το τηλέφωνο <xliff:g id="NUMBER">%d</xliff:g> φορές χωρίς επιτυχία. Το προφίλ εργασίας θα καταργηθεί και θα διαγραφούν όλα τα δεδομένα προφίλ."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Σχεδιάσατε το μοτίβο ξεκλειδώματος εσφαλμένα <xliff:g id="NUMBER_0">%1$d</xliff:g> φορές. Μετά από <xliff:g id="NUMBER_1">%2$d</xliff:g> ακόμα ανεπιτυχείς προσπάθειες, θα σας ζητηθεί να ξεκλειδώσετε το tablet με τη χρήση ενός λογαριασμού ηλεκτρονικού ταχυδρομείου.\n\n Δοκιμάστε να συνδεθείτε ξανά σε <xliff:g id="NUMBER_2">%3$d</xliff:g> δευτερόλεπτα."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Σχεδιάσατε το μοτίβο ξεκλειδώματος εσφαλμένα <xliff:g id="NUMBER_0">%1$d</xliff:g> φορές. Μετά από <xliff:g id="NUMBER_1">%2$d</xliff:g> ακόμα ανεπιτυχείς προσπάθειες, θα σας ζητηθεί να ξεκλειδώσετε το τηλέφωνό σας με τη χρήση ενός λογαριασμού ηλεκτρονικού ταχυδρομείου.\n\n Δοκιμάστε ξανά σε <xliff:g id="NUMBER_2">%3$d</xliff:g> δευτερόλεπτα."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Ευθυγραμμίστε ξανά το τηλέφωνο για ταχύτερη φόρτιση"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Ευθυγραμμίστε ξανά το τηλέφωνο, για να το φορτίσετε ασύρματα"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Η συσκευή Android TV σύντομα θα απενεργοποιηθεί. Πατήστε ένα κουμπί, για να την κρατήσετε ενεργοποιημένη."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Η συσκευή σύντομα θα απενεργοποιηθεί. Πατήστε, για να την κρατήσετε ενεργοποιημένη."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Δεν υπάρχει κάρτα SIM στο tablet."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Δεν υπάρχει κάρτα SIM στο τηλέφωνο."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"Οι κωδικοί PIN δεν ταυτίζονται"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Δοκιμάσατε να ξεκλειδώσετε το tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> φορές χωρίς επιτυχία. Μετά από <xliff:g id="NUMBER_1">%2$d</xliff:g> ακόμα ανεπιτυχείς προσπάθειες, θα γίνει επαναφορά του tablet και θα διαγραφούν όλα τα δεδομένα του."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Δοκιμάσατε να ξεκλειδώσετε το τηλέφωνο <xliff:g id="NUMBER_0">%1$d</xliff:g> φορές χωρίς επιτυχία. Μετά από <xliff:g id="NUMBER_1">%2$d</xliff:g> ακόμα ανεπιτυχείς προσπάθειες, θα γίνει επαναφορά του τηλεφώνου και θα διαγραφούν όλα τα δεδομένα του."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Δοκιμάσατε να ξεκλειδώσετε αυτό το tablet <xliff:g id="NUMBER">%d</xliff:g> φορές χωρίς επιτυχία. Θα γίνει επαναφορά του tablet και θα διαγραφούν όλα τα δεδομένα του."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Δοκιμάσατε να ξεκλειδώσετε το τηλέφωνο <xliff:g id="NUMBER">%d</xliff:g> φορές χωρίς επιτυχία. Θα γίνει επαναφορά του τηλεφώνου και θα διαγραφούν όλα τα δεδομένα του."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Δοκιμάσατε να ξεκλειδώσετε το tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> φορές χωρίς επιτυχία. Μετά από <xliff:g id="NUMBER_1">%2$d</xliff:g> ακόμα ανεπιτυχείς προσπάθειες, αυτός ο χρήστης θα καταργηθεί και θα διαγραφούν όλα τα δεδομένα χρήστη."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Δοκιμάσατε να ξεκλειδώσετε το τηλέφωνο <xliff:g id="NUMBER_0">%1$d</xliff:g> φορές χωρίς επιτυχία. Μετά από <xliff:g id="NUMBER_1">%2$d</xliff:g> ακόμα ανεπιτυχείς προσπάθειες, αυτός ο χρήστης θα καταργηθεί και θα διαγραφούν όλα τα δεδομένα χρήστη."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Δοκιμάσατε να ξεκλειδώσετε το tablet <xliff:g id="NUMBER">%d</xliff:g> φορές χωρίς επιτυχία. Αυτός ο χρήστης θα καταργηθεί και θα διαγραφούν όλα τα δεδομένα χρήστη."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Δοκιμάσατε να ξεκλειδώσετε το τηλέφωνο <xliff:g id="NUMBER">%d</xliff:g> φορές χωρίς επιτυχία. Αυτός ο χρήστης θα καταργηθεί και θα διαγραφούν όλα τα δεδομένα χρήστη."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Δοκιμάσατε να ξεκλειδώσετε το tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> φορές χωρίς επιτυχία. Μετά από <xliff:g id="NUMBER_1">%2$d</xliff:g> ακόμα ανεπιτυχείς προσπάθειες, το προφίλ εργασίας θα καταργηθεί και θα διαγραφούν όλα τα δεδομένα προφίλ."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Δοκιμάσατε να ξεκλειδώσετε το τηλέφωνο <xliff:g id="NUMBER_0">%1$d</xliff:g> φορές χωρίς επιτυχία. Μετά από <xliff:g id="NUMBER_1">%2$d</xliff:g> ακόμα ανεπιτυχείς προσπάθειες, το προφίλ εργασίας θα καταργηθεί και θα διαγραφούν όλα τα δεδομένα προφίλ."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Δοκιμάσατε να ξεκλειδώσετε το tablet <xliff:g id="NUMBER">%d</xliff:g> φορές χωρίς επιτυχία. Το προφίλ εργασίας θα καταργηθεί και θα διαγραφούν όλα τα δεδομένα προφίλ."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Δοκιμάσατε να ξεκλειδώσετε το τηλέφωνο <xliff:g id="NUMBER">%d</xliff:g> φορές χωρίς επιτυχία. Το προφίλ εργασίας θα καταργηθεί και θα διαγραφούν όλα τα δεδομένα προφίλ."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Σχεδιάσατε το μοτίβο ξεκλειδώματος εσφαλμένα <xliff:g id="NUMBER_0">%1$d</xliff:g> φορές. Μετά από <xliff:g id="NUMBER_1">%2$d</xliff:g> ακόμα ανεπιτυχείς προσπάθειες, θα σας ζητηθεί να ξεκλειδώσετε το tablet με τη χρήση ενός λογαριασμού ηλεκτρονικού ταχυδρομείου.\n\n Δοκιμάστε να συνδεθείτε ξανά σε <xliff:g id="NUMBER_2">%3$d</xliff:g> δευτερόλεπτα."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Σχεδιάσατε το μοτίβο ξεκλειδώματος εσφαλμένα <xliff:g id="NUMBER_0">%1$d</xliff:g> φορές. Μετά από <xliff:g id="NUMBER_1">%2$d</xliff:g> ακόμα ανεπιτυχείς προσπάθειες, θα σας ζητηθεί να ξεκλειδώσετε το τηλέφωνό σας με τη χρήση ενός λογαριασμού ηλεκτρονικού ταχυδρομείου.\n\n Δοκιμάστε ξανά σε <xliff:g id="NUMBER_2">%3$d</xliff:g> δευτερόλεπτα."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-en-rAU/strings.xml b/packages/SystemUI/res-product/values-en-rAU/strings.xml
index 9e8ed2f23309..040fda8c4eda 100644
--- a/packages/SystemUI/res-product/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res-product/values-en-rAU/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"No SIM card in tablet."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"No SIM card in phone."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"PIN codes do not match"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, this tablet will be reset, which will delete all its data."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, this phone will be reset, which will delete all its data."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER">%d</xliff:g> times. This tablet will be reset, which will delete all its data."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER">%d</xliff:g> times. This phone will be reset, which will delete all its data."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, this user will be removed, which will delete all user data."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, this user will be removed, which will delete all user data."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"The Android TV device will soon turn off; press a button to keep it on."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"The device will soon turn off; press to keep it on."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER">%d</xliff:g> times. The work profile will be removed, which will delete all profile data."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER">%d</xliff:g> times. The work profile will be removed, which will delete all profile data."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your tablet using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your phone using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Realign phone for faster charging"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Realign phone to charge wirelessly"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"The Android TV device will soon turn off; press a button to keep it on."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"The device will soon turn off; press to keep it on."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"No SIM card in tablet."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"No SIM card in phone."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"PIN codes do not match"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, this tablet will be reset, which will delete all its data."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, this phone will be reset, which will delete all its data."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER">%d</xliff:g> times. This tablet will be reset, which will delete all its data."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER">%d</xliff:g> times. This phone will be reset, which will delete all its data."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, this user will be removed, which will delete all user data."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, this user will be removed, which will delete all user data."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER">%d</xliff:g> times. This user will be removed, which will delete all user data."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER">%d</xliff:g> times. This user will be removed, which will delete all user data."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, the work profile will be removed, which will delete all profile data."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, the work profile will be removed, which will delete all profile data."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER">%d</xliff:g> times. The work profile will be removed, which will delete all profile data."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER">%d</xliff:g> times. The work profile will be removed, which will delete all profile data."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your tablet using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your phone using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-en-rCA/strings.xml b/packages/SystemUI/res-product/values-en-rCA/strings.xml
index 9e8ed2f23309..040fda8c4eda 100644
--- a/packages/SystemUI/res-product/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res-product/values-en-rCA/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"No SIM card in tablet."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"No SIM card in phone."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"PIN codes do not match"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, this tablet will be reset, which will delete all its data."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, this phone will be reset, which will delete all its data."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER">%d</xliff:g> times. This tablet will be reset, which will delete all its data."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER">%d</xliff:g> times. This phone will be reset, which will delete all its data."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, this user will be removed, which will delete all user data."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, this user will be removed, which will delete all user data."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"The Android TV device will soon turn off; press a button to keep it on."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"The device will soon turn off; press to keep it on."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER">%d</xliff:g> times. The work profile will be removed, which will delete all profile data."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER">%d</xliff:g> times. The work profile will be removed, which will delete all profile data."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your tablet using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your phone using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Realign phone for faster charging"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Realign phone to charge wirelessly"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"The Android TV device will soon turn off; press a button to keep it on."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"The device will soon turn off; press to keep it on."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"No SIM card in tablet."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"No SIM card in phone."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"PIN codes do not match"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, this tablet will be reset, which will delete all its data."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, this phone will be reset, which will delete all its data."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER">%d</xliff:g> times. This tablet will be reset, which will delete all its data."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER">%d</xliff:g> times. This phone will be reset, which will delete all its data."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, this user will be removed, which will delete all user data."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, this user will be removed, which will delete all user data."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER">%d</xliff:g> times. This user will be removed, which will delete all user data."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER">%d</xliff:g> times. This user will be removed, which will delete all user data."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, the work profile will be removed, which will delete all profile data."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, the work profile will be removed, which will delete all profile data."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER">%d</xliff:g> times. The work profile will be removed, which will delete all profile data."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER">%d</xliff:g> times. The work profile will be removed, which will delete all profile data."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your tablet using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your phone using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-en-rGB/strings.xml b/packages/SystemUI/res-product/values-en-rGB/strings.xml
index 9e8ed2f23309..040fda8c4eda 100644
--- a/packages/SystemUI/res-product/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res-product/values-en-rGB/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"No SIM card in tablet."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"No SIM card in phone."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"PIN codes do not match"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, this tablet will be reset, which will delete all its data."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, this phone will be reset, which will delete all its data."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER">%d</xliff:g> times. This tablet will be reset, which will delete all its data."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER">%d</xliff:g> times. This phone will be reset, which will delete all its data."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, this user will be removed, which will delete all user data."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, this user will be removed, which will delete all user data."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"The Android TV device will soon turn off; press a button to keep it on."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"The device will soon turn off; press to keep it on."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER">%d</xliff:g> times. The work profile will be removed, which will delete all profile data."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER">%d</xliff:g> times. The work profile will be removed, which will delete all profile data."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your tablet using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your phone using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Realign phone for faster charging"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Realign phone to charge wirelessly"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"The Android TV device will soon turn off; press a button to keep it on."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"The device will soon turn off; press to keep it on."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"No SIM card in tablet."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"No SIM card in phone."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"PIN codes do not match"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, this tablet will be reset, which will delete all its data."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, this phone will be reset, which will delete all its data."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER">%d</xliff:g> times. This tablet will be reset, which will delete all its data."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER">%d</xliff:g> times. This phone will be reset, which will delete all its data."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, this user will be removed, which will delete all user data."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, this user will be removed, which will delete all user data."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER">%d</xliff:g> times. This user will be removed, which will delete all user data."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER">%d</xliff:g> times. This user will be removed, which will delete all user data."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, the work profile will be removed, which will delete all profile data."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, the work profile will be removed, which will delete all profile data."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER">%d</xliff:g> times. The work profile will be removed, which will delete all profile data."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER">%d</xliff:g> times. The work profile will be removed, which will delete all profile data."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your tablet using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your phone using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-en-rIN/strings.xml b/packages/SystemUI/res-product/values-en-rIN/strings.xml
index 9e8ed2f23309..040fda8c4eda 100644
--- a/packages/SystemUI/res-product/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res-product/values-en-rIN/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"No SIM card in tablet."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"No SIM card in phone."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"PIN codes do not match"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, this tablet will be reset, which will delete all its data."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, this phone will be reset, which will delete all its data."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER">%d</xliff:g> times. This tablet will be reset, which will delete all its data."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER">%d</xliff:g> times. This phone will be reset, which will delete all its data."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, this user will be removed, which will delete all user data."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, this user will be removed, which will delete all user data."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"The Android TV device will soon turn off; press a button to keep it on."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"The device will soon turn off; press to keep it on."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER">%d</xliff:g> times. The work profile will be removed, which will delete all profile data."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER">%d</xliff:g> times. The work profile will be removed, which will delete all profile data."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your tablet using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your phone using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Realign phone for faster charging"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Realign phone to charge wirelessly"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"The Android TV device will soon turn off; press a button to keep it on."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"The device will soon turn off; press to keep it on."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"No SIM card in tablet."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"No SIM card in phone."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"PIN codes do not match"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, this tablet will be reset, which will delete all its data."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, this phone will be reset, which will delete all its data."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER">%d</xliff:g> times. This tablet will be reset, which will delete all its data."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER">%d</xliff:g> times. This phone will be reset, which will delete all its data."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, this user will be removed, which will delete all user data."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, this user will be removed, which will delete all user data."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER">%d</xliff:g> times. This user will be removed, which will delete all user data."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER">%d</xliff:g> times. This user will be removed, which will delete all user data."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, the work profile will be removed, which will delete all profile data."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, the work profile will be removed, which will delete all profile data."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"You have incorrectly attempted to unlock the tablet <xliff:g id="NUMBER">%d</xliff:g> times. The work profile will be removed, which will delete all profile data."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER">%d</xliff:g> times. The work profile will be removed, which will delete all profile data."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your tablet using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your phone using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-en-rXC/strings.xml b/packages/SystemUI/res-product/values-en-rXC/strings.xml
index 28062888d376..c8c38fa809c2 100644
--- a/packages/SystemUI/res-product/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res-product/values-en-rXC/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,32 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‎‎‎‎‎‏‎‏‎‎‎‏‎‏‎‎‎‏‏‎‎‎‎‎‎‏‎‎‎‏‎‎‎‎‏‏‏‏‎‎‎‎‎‎‏‏‏‎‎‎‎‎‎‏‎‎The Android TV device will soon turn off; press a button to keep it on.‎‏‎‎‏‎"</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‎‎‎‏‎‏‎‏‏‏‎‏‏‎‏‏‏‏‎‏‎‏‎‎‏‎‎‏‎‎‎‎‏‎‎‏‏‏‏‎‏‎‎‎‏‏‏‏‎‎‏‏‎‏‏‎The device will soon turn off; press to keep it on.‎‏‎‎‏‎"</string>
-<string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‏‏‎‏‏‏‎‏‏‎‎‏‎‏‎‎‎‎‏‎‏‏‏‎‏‎‎‎‏‎‏‏‏‏‏‎‎‏‏‏‎‎‏‎‎‎‏‎‏‎‏‎‎‎‏‏‎No SIM card in tablet.‎‏‎‎‏‎"</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‎‎‎‏‏‏‎‎‎‏‎‎‎‏‏‏‏‎‏‎‎‎‎‏‏‏‏‎‎‏‎‎‎‎‎‎‏‎‏‎‏‎‏‎‏‎‏‏‎‏‏‎‎‏‏‏‎No SIM card in phone.‎‏‎‎‏‎"</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‎‏‏‎‏‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‎‎‎‏‏‏‏‎‏‎‎‎‎‎‏‏‎‎‎‎‎‏‏‎‎‏‏‎‏‏‏‎‏‎‏‏‎‎PIN codes does not match‎‏‎‎‏‎"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‏‏‏‏‏‎‎‎‎‏‏‎‎‎‏‎‎‏‏‏‏‎‎‏‏‎‎‏‏‏‏‏‎‎‏‏‎‎‏‎‏‏‎‏‏‏‏‏‏‎‏‎‏‎‎‎‏‎You have incorrectly attempted to unlock the tablet ‎‏‎‎‏‏‎<xliff:g id="NUMBER_0">%1$d</xliff:g>‎‏‎‎‏‏‏‎ times. After ‎‏‎‎‏‏‎<xliff:g id="NUMBER_1">%2$d</xliff:g>‎‏‎‎‏‏‏‎ more unsuccessful attempts, this tablet will be reset, which will delete all its data.‎‏‎‎‏‎"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‏‎‎‎‎‎‏‏‏‏‎‎‎‏‏‎‏‏‎‏‎‏‎‎‎‏‎‎‏‎‎‎‎‏‏‏‎‏‏‎‏‏‏‏‏‎‏‎‏‏‎‎‎‎‎‎You have incorrectly attempted to unlock the phone ‎‏‎‎‏‏‎<xliff:g id="NUMBER_0">%1$d</xliff:g>‎‏‎‎‏‏‏‎ times. After ‎‏‎‎‏‏‎<xliff:g id="NUMBER_1">%2$d</xliff:g>‎‏‎‎‏‏‏‎ more unsuccessful attempts, this phone will be reset, which will delete all its data.‎‏‎‎‏‎"</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‎‎‏‎‎‎‏‏‎‏‏‎‏‏‏‏‏‎‎‎‏‎‎‏‎‎‎‏‏‎‏‏‎‏‏‏‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‎‎You have incorrectly attempted to unlock the tablet ‎‏‎‎‏‏‎<xliff:g id="NUMBER">%d</xliff:g>‎‏‎‎‏‏‏‎ times. This tablet will be reset, which will delete all its data.‎‏‎‎‏‎"</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‏‏‏‏‎‎‏‎‎‏‎‏‏‏‏‏‏‏‎‎‏‏‎‎‏‏‏‎‏‏‎‏‎‎‎‎‎‎‏‎‎‏‏‎‏‏‏‏‎‎‏‎‏‎‎‎You have incorrectly attempted to unlock the phone ‎‏‎‎‏‏‎<xliff:g id="NUMBER">%d</xliff:g>‎‏‎‎‏‏‏‎ times. This phone will be reset, which will delete all its data.‎‏‎‎‏‎"</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‏‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‎‏‏‏‎‏‏‏‏‎‎‎‏‎‏‏‎‏‏‎‎‎‎‏‏‎‎‏‏‏‎‏‎‎‎‎‎You have incorrectly attempted to unlock the tablet ‎‏‎‎‏‏‎<xliff:g id="NUMBER_0">%1$d</xliff:g>‎‏‎‎‏‏‏‎ times. After ‎‏‎‎‏‏‎<xliff:g id="NUMBER_1">%2$d</xliff:g>‎‏‎‎‏‏‏‎ more unsuccessful attempts, this user will be removed, which will delete all user data.‎‏‎‎‏‎"</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‎‏‏‎‏‎‏‎‎‎‏‎‏‎‏‎‏‏‎‏‎‎‏‎‎‎‎‎‎‏‏‎‏‏‏‏‏‏‏‏‎‏‏‏‎‏‏‏‎‏‎‏‏‏‎‎‎‎You have incorrectly attempted to unlock the phone ‎‏‎‎‏‏‎<xliff:g id="NUMBER_0">%1$d</xliff:g>‎‏‎‎‏‏‏‎ times. After ‎‏‎‎‏‏‎<xliff:g id="NUMBER_1">%2$d</xliff:g>‎‏‎‎‏‏‏‎ more unsuccessful attempts, this user will be removed, which will delete all user data.‎‏‎‎‏‎"</string>
- <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="9046628517316763961">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‏‎‎‎‎‎‏‎‏‎‎‏‎‏‏‎‏‎‎‏‎‎‏‎‏‎‏‏‎‎‏‎‏‎‏‏‎‏‎‎‎‎‏‎‎‏‏‏‎‎‏‎You have incorrectly attempted to unlock the tablet ‎‏‎‎‏‏‎<xliff:g id="NUMBER">%d</xliff:g>‎‏‎‎‏‏‏‎ times. This user will be removed, which will delete all user data.‎‏‎‎‏‎"</string>
- <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3588779327358321092">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‏‏‏‎‎‏‏‎‏‏‏‏‎‎‏‏‏‏‏‎‎‏‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‎‏‎‏‎‎‎‎‎‏‏‏‎‎‎‏‎‎‎You have incorrectly attempted to unlock the phone ‎‏‎‎‏‏‎<xliff:g id="NUMBER">%d</xliff:g>‎‏‎‎‏‏‏‎ times. This user will be removed, which will delete all user data.‎‏‎‎‏‎"</string>
- <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="6114158710353725041">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‏‎‏‏‎‎‏‏‏‎‏‏‎‏‎‏‏‏‏‎‎‏‏‏‏‏‎‏‏‏‎‏‏‏‏‏‏‏‎‏‎‎‎‎‏‏‎‎‏‏‏‎‎‎‏‎You have incorrectly attempted to unlock the tablet ‎‏‎‎‏‏‎<xliff:g id="NUMBER_0">%1$d</xliff:g>‎‏‎‎‏‏‏‎ times. After ‎‏‎‎‏‏‎<xliff:g id="NUMBER_1">%2$d</xliff:g>‎‏‎‎‏‏‏‎ more unsuccessful attempts, the work profile will be removed, which will delete all profile data.‎‏‎‎‏‎"</string>
- <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="8345451368768804892">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‏‏‎‎‎‏‎‏‏‏‎‎‎‎‏‏‎‎‎‏‏‎‎‎‎‎‎‏‏‏‎‎‎You have incorrectly attempted to unlock the phone ‎‏‎‎‏‏‎<xliff:g id="NUMBER_0">%1$d</xliff:g>‎‏‎‎‏‏‏‎ times. After ‎‏‎‎‏‏‎<xliff:g id="NUMBER_1">%2$d</xliff:g>‎‏‎‎‏‏‏‎ more unsuccessful attempts, the work profile will be removed, which will delete all profile data.‎‏‎‎‏‎"</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‎‎‎‏‏‎‎‏‎‎‎‏‏‏‎‎‏‏‎‎‏‏‎‏‏‏‏‎‏‎‏‎‏‏‎‎‏‎‏‏‏‏‎‎‏‎‎‎‏‎‏‎You have incorrectly attempted to unlock the tablet ‎‏‎‎‏‏‎<xliff:g id="NUMBER">%d</xliff:g>‎‏‎‎‏‏‏‎ times. The work profile will be removed, which will delete all profile data.‎‏‎‎‏‎"</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‎‏‏‎‏‏‏‎‏‏‎‏‎‏‎‏‏‏‎‏‏‏‎‏‎‎‏‏‏‎‏‏‎‎‏‎‎‏‏‎‎‎‎‎‏‏‏‏‎‎‏‎‏‎‏‎‏‎‎‎You have incorrectly attempted to unlock the phone ‎‏‎‎‏‏‎<xliff:g id="NUMBER">%d</xliff:g>‎‏‎‎‏‏‏‎ times. The work profile will be removed, which will delete all profile data.‎‏‎‎‏‎"</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‎‎‎‏‏‎‏‏‎‏‎‏‏‏‏‎‎‎‎‎‎‏‎‏‎‏‎‎‎‎‎‏‏‏‎‎‏‎‏‎‎‎‏‏‎‎‎‎‎‏‎‏‏‏‎‎‎You have incorrectly drawn your unlock pattern ‎‏‎‎‏‏‎<xliff:g id="NUMBER_0">%1$d</xliff:g>‎‏‎‎‏‏‏‎ times. After ‎‏‎‎‏‏‎<xliff:g id="NUMBER_1">%2$d</xliff:g>‎‏‎‎‏‏‏‎ more unsuccessful attempts, you will be asked to unlock your tablet using an email account.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎ Try again in ‎‏‎‎‏‏‎<xliff:g id="NUMBER_2">%3$d</xliff:g>‎‏‎‎‏‏‏‎ seconds.‎‏‎‎‏‎"</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‏‏‏‎‎‏‏‏‏‏‎‏‏‏‎‎‏‎‎‎‏‏‏‎‏‏‏‎‎‏‏‎‎‎‏‏‎‎‎‎‏‏‏‎‎‎‏‎‎‏‎‏‎‎‎‏‎You have incorrectly drawn your unlock pattern ‎‏‎‎‏‏‎<xliff:g id="NUMBER_0">%1$d</xliff:g>‎‏‎‎‏‏‏‎ times. After ‎‏‎‎‏‏‎<xliff:g id="NUMBER_1">%2$d</xliff:g>‎‏‎‎‏‏‏‎ more unsuccessful attempts, you will be asked to unlock your phone using an email account.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎ Try again in ‎‏‎‎‏‏‎<xliff:g id="NUMBER_2">%3$d</xliff:g>‎‏‎‎‏‏‏‎ seconds.‎‏‎‎‏‎"</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‎‏‏‏‎‎‏‎‎‏‎‏‏‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‏‎‏‏‎‎‎‎‎‎‏‎‏‎‏‏‎‎‏‏‎‎‎‎Realign phone for faster charging‎‏‎‎‏‎"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‏‎‎‏‏‏‏‏‎‎‏‏‏‏‎‎‏‏‎‏‏‎‎‏‎‎‎‎‎‏‎‏‎‎‏‎‏‎‏‏‏‏‎‎‏‏‎‎‏‎‏‏‏‎‎‎‎‎Realign phone to charge wirelessly‎‏‎‎‏‎"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‏‏‏‏‏‎‎‎‏‏‎‏‏‎‎‎‏‎‎‎‏‎‎‎‏‎‎‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‏‎‏‎‎‎‏‎‎‏‏‏‎The Android TV device will soon turn off; press a button to keep it on.‎‏‎‎‏‎"</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‎‎‎‎‏‎‎‏‏‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‎‏‏‎‏‎‎‎‏‏‎‏‎‏‎‏‏‎‏‎‏‏‎‎‎‎‎‎‎The device will soon turn off; press to keep it on.‎‏‎‎‏‎"</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‏‎‏‎‎‎‏‏‏‏‎‏‎‎‏‏‎‎‎‎‏‎‏‏‎‎‎‎‏‏‏‏‎‏‏‏‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‏‎‏‏‎No SIM card in tablet.‎‏‎‎‏‎"</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‏‎‎‎‏‎‏‎‎‎‎‏‏‎‎‏‏‏‏‏‏‎‎‏‏‎‎‏‏‏‏‎‎‏‎‎‏‏‏‎‎‎‏‎‎‎‏‏‎‎‏‏‏‏‎No SIM card in phone.‎‏‎‎‏‎"</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‏‎‎‏‎‎‎‎‏‏‏‏‎‎‏‎‎‏‏‏‎‏‏‏‎‏‎‎‏‏‎‎‎‏‎‎‎‏‏‎‏‏‏‎‎‎‎‏‎‎‏‏‏‏‎‏‏‎PIN codes does not match‎‏‎‎‏‎"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‎‎‎‏‏‎‎‎‏‏‎‎‎‎‎‏‎‎‏‎‏‏‏‏‏‎‎‎‏‎‎‎‏‏‏‏‏‎‎‎‎‎‏‏‏‎‏‎‏‎‏‎‏‎‎‎‎‎You have incorrectly attempted to unlock the tablet ‎‏‎‎‏‏‎<xliff:g id="NUMBER_0">%1$d</xliff:g>‎‏‎‎‏‏‏‎ times. After ‎‏‎‎‏‏‎<xliff:g id="NUMBER_1">%2$d</xliff:g>‎‏‎‎‏‏‏‎ more unsuccessful attempts, this tablet will be reset, which will delete all its data.‎‏‎‎‏‎"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‎‎‎‎‎‎‏‎‏‎‏‎‎‎‎‎‏‏‎‏‎‏‎‏‏‏‏‏‎‏‏‏‏‏‎‎‎‏‏‎‎‎‏‏‎‎‏‏‎‏‎‏‏‏‏‏‎You have incorrectly attempted to unlock the phone ‎‏‎‎‏‏‎<xliff:g id="NUMBER_0">%1$d</xliff:g>‎‏‎‎‏‏‏‎ times. After ‎‏‎‎‏‏‎<xliff:g id="NUMBER_1">%2$d</xliff:g>‎‏‎‎‏‏‏‎ more unsuccessful attempts, this phone will be reset, which will delete all its data.‎‏‎‎‏‎"</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‎‏‏‎‎‎‎‎‏‏‎‏‎‏‎‏‎‏‎‏‏‏‏‏‎‏‏‎‏‏‎‎‎‎‎‎‎‏‏‎‏‏‎You have incorrectly attempted to unlock the tablet ‎‏‎‎‏‏‎<xliff:g id="NUMBER">%d</xliff:g>‎‏‎‎‏‏‏‎ times. This tablet will be reset, which will delete all its data.‎‏‎‎‏‎"</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‎‎‏‎‎‎‎‏‏‎‏‎‏‎‏‏‎‎‎‎‏‏‏‏‎‎‎‎‏‎‏‎‎‏‎‎‎‎‏‏‏‎‏‏‎‎‎‎‎‎‏‎‏‎‏‎You have incorrectly attempted to unlock the phone ‎‏‎‎‏‏‎<xliff:g id="NUMBER">%d</xliff:g>‎‏‎‎‏‏‏‎ times. This phone will be reset, which will delete all its data.‎‏‎‎‏‎"</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‏‎‏‎‎‏‏‏‏‏‏‎‎‎‏‎‎‎‎‎‎‎‎‎‏‏‏‏‏‏‏‎‎‎‎‏‏‏‎‏‎‎‏‏‎‏‏‎‏‏‎‏‎‏‏‏‎You have incorrectly attempted to unlock the tablet ‎‏‎‎‏‏‎<xliff:g id="NUMBER_0">%1$d</xliff:g>‎‏‎‎‏‏‏‎ times. After ‎‏‎‎‏‏‎<xliff:g id="NUMBER_1">%2$d</xliff:g>‎‏‎‎‏‏‏‎ more unsuccessful attempts, this user will be removed, which will delete all user data.‎‏‎‎‏‎"</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‏‏‎‏‏‏‎‏‏‎‎‏‎‎‏‏‎‏‏‎‎‏‏‎‎‎‎‎‏‎‏‏‏‎‏‏‏‏‏‏‎You have incorrectly attempted to unlock the phone ‎‏‎‎‏‏‎<xliff:g id="NUMBER_0">%1$d</xliff:g>‎‏‎‎‏‏‏‎ times. After ‎‏‎‎‏‏‎<xliff:g id="NUMBER_1">%2$d</xliff:g>‎‏‎‎‏‏‏‎ more unsuccessful attempts, this user will be removed, which will delete all user data.‎‏‎‎‏‎"</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‎‎‎‏‏‏‎‏‏‎‎‏‎‏‎‎‎‏‎‎‎‎‏‏‏‏‎‎‎‏‏‏‏‎‎‏‏‎‎‎‎‏‏‎‎‏‎‏‎‏‏‎You have incorrectly attempted to unlock the tablet ‎‏‎‎‏‏‎<xliff:g id="NUMBER">%d</xliff:g>‎‏‎‎‏‏‏‎ times. This user will be removed, which will delete all user data.‎‏‎‎‏‎"</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‎‏‎‏‏‎‏‎‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‎‎‏‎‎‎‎‎‏‎‎‎‏‏‏‎‎‎‏‏‎‎‎‏‏‏‎‏‏‎‏‏‎‎You have incorrectly attempted to unlock the phone ‎‏‎‎‏‏‎<xliff:g id="NUMBER">%d</xliff:g>‎‏‎‎‏‏‏‎ times. This user will be removed, which will delete all user data.‎‏‎‎‏‎"</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‎‎‏‎‎‎‎‏‎‏‎‏‎‎‎‎‎‏‏‎‎‎‎‏‎‏‏‎‎‎‏‎‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‎‎‏‏‎‎You have incorrectly attempted to unlock the tablet ‎‏‎‎‏‏‎<xliff:g id="NUMBER_0">%1$d</xliff:g>‎‏‎‎‏‏‏‎ times. After ‎‏‎‎‏‏‎<xliff:g id="NUMBER_1">%2$d</xliff:g>‎‏‎‎‏‏‏‎ more unsuccessful attempts, the work profile will be removed, which will delete all profile data.‎‏‎‎‏‎"</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‎‎‎‎‏‎‏‎‏‎‎‎‏‎‎‎‎‎‎‎‏‎‏‎‎‎‏‏‎‏‏‏‏‎‎‏‎‎‎‏‎You have incorrectly attempted to unlock the phone ‎‏‎‎‏‏‎<xliff:g id="NUMBER_0">%1$d</xliff:g>‎‏‎‎‏‏‏‎ times. After ‎‏‎‎‏‏‎<xliff:g id="NUMBER_1">%2$d</xliff:g>‎‏‎‎‏‏‏‎ more unsuccessful attempts, the work profile will be removed, which will delete all profile data.‎‏‎‎‏‎"</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‎‏‎‎‏‏‎‎‏‎‏‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‎‎‎‏‏‏‏‏‎‏‎‎‏‎‏‎‏‎‎‏‏‎‎‎‏‎‎‏‏‏‎You have incorrectly attempted to unlock the tablet ‎‏‎‎‏‏‎<xliff:g id="NUMBER">%d</xliff:g>‎‏‎‎‏‏‏‎ times. The work profile will be removed, which will delete all profile data.‎‏‎‎‏‎"</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‏‏‏‏‏‎‏‎‏‎‎‏‎‏‏‏‏‎‎‎‎‎‎‎‏‏‏‏‎‎‎‏‏‎‏‎‏‏‎‎‏‏‎‎‎‎‎‏‎‎‏‏‎‏‏‎‎You have incorrectly attempted to unlock the phone ‎‏‎‎‏‏‎<xliff:g id="NUMBER">%d</xliff:g>‎‏‎‎‏‏‏‎ times. The work profile will be removed, which will delete all profile data.‎‏‎‎‏‎"</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‏‏‎‏‎‎‎‎‎‎‏‏‏‎‎‏‏‎‎‏‏‎‎‎‏‎‎‎‏‏‎‏‎‏‏‏‎‎‎‏‏‎‎‎‏‎‏‎‏‏‏‏‏‎‎‎‎You have incorrectly drawn your unlock pattern ‎‏‎‎‏‏‎<xliff:g id="NUMBER_0">%1$d</xliff:g>‎‏‎‎‏‏‏‎ times. After ‎‏‎‎‏‏‎<xliff:g id="NUMBER_1">%2$d</xliff:g>‎‏‎‎‏‏‏‎ more unsuccessful attempts, you will be asked to unlock your tablet using an email account.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎ Try again in ‎‏‎‎‏‏‎<xliff:g id="NUMBER_2">%3$d</xliff:g>‎‏‎‎‏‏‏‎ seconds.‎‏‎‎‏‎"</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‎‎‏‎‎‏‏‏‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‏‎‎‎‏‏‎‎‎‏‏‏‎‏‏‎‎‎‎‎‏‏‏‏‎‎‏‏‏‎‏‏‎‏‎You have incorrectly drawn your unlock pattern ‎‏‎‎‏‏‎<xliff:g id="NUMBER_0">%1$d</xliff:g>‎‏‎‎‏‏‏‎ times. After ‎‏‎‎‏‏‎<xliff:g id="NUMBER_1">%2$d</xliff:g>‎‏‎‎‏‏‏‎ more unsuccessful attempts, you will be asked to unlock your phone using an email account.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎ Try again in ‎‏‎‎‏‏‎<xliff:g id="NUMBER_2">%3$d</xliff:g>‎‏‎‎‏‏‏‎ seconds.‎‏‎‎‏‎"</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-es-rUS/strings.xml b/packages/SystemUI/res-product/values-es-rUS/strings.xml
index 85d3dbaee64c..7310799771d0 100644
--- a/packages/SystemUI/res-product/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res-product/values-es-rUS/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"No hay tarjeta SIM en la tablet."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"No hay tarjeta SIM en el teléfono."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"Los códigos PIN no coinciden"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Intentaste desbloquear la tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> veces de manera incorrecta. Después de <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos más, se restablecerá la tablet, lo que borrará todos los datos."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Intentaste desbloquear el teléfono <xliff:g id="NUMBER_0">%1$d</xliff:g> veces de manera incorrecta. Después de <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos más, se restablecerá el teléfono, lo que borrará todos los datos."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Intentaste desbloquear la tablet <xliff:g id="NUMBER">%d</xliff:g> veces de manera incorrecta. Se restablecerá la tablet, lo que borrará todos los datos."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Intentaste desbloquear el teléfono <xliff:g id="NUMBER">%d</xliff:g> veces de manera incorrecta. Se restablecerá el teléfono, lo que borrará todos los datos."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Intentaste desbloquear la tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> veces de manera incorrecta. Después de <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos más, se quitará este usuario, lo que borrará todos los datos asociados."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Intentaste desbloquear el teléfono <xliff:g id="NUMBER_0">%1$d</xliff:g> veces de manera incorrecta. Después de <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos más, se quitará este usuario, lo que borrará todos los datos asociados."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Pronto se apagará el dispositivo Android TV; presiona un botón para mantenerlo encendido."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Pronto se apagará el dispositivo; presiona para mantenerlo encendido."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Intentaste desbloquear la tablet <xliff:g id="NUMBER">%d</xliff:g> veces de manera incorrecta. Se quitará el perfil de trabajo, lo que borrará todos los datos asociados."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Intentaste desbloquear el teléfono <xliff:g id="NUMBER">%d</xliff:g> veces de manera incorrecta. Se quitará el perfil de trabajo, lo que borrará todos los datos asociados."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Dibujaste incorrectamente tu patrón de desbloqueo <xliff:g id="NUMBER_0">%1$d</xliff:g> veces. Luego de <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos más, se te solicitará que desbloquees tu tablet mediante una cuenta de correo electrónico.\n\n Vuelve a intentarlo en <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Dibujaste incorrectamente tu patrón de desbloqueo <xliff:g id="NUMBER_0">%1$d</xliff:g> veces. Luego de <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos más, se te solicitará que desbloquees tu dispositivo mediante una cuenta de correo electrónico.\n\n Vuelve a intentarlo en <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Vuelve a alinear el teléfono para cargarlo más rápido"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Vuelve a alinear el teléfono para cargarlo inalámbricamente"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Pronto se apagará el dispositivo Android TV. Presiona un botón para mantenerlo encendido."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Pronto se apagará el dispositivo. Presiona para mantenerlo encendido."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"No hay tarjeta SIM en la tablet."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"No hay ninguna tarjeta SIM en el teléfono."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"Los códigos PIN no coinciden"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Intentaste desbloquear la tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> veces de manera incorrecta. Después de <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos más, se restablecerá la tablet, lo que borrará todos los datos."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Intentaste desbloquear el teléfono <xliff:g id="NUMBER_0">%1$d</xliff:g> veces de manera incorrecta. Después de <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos más, se restablecerá el teléfono, lo que borrará todos los datos."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Intentaste desbloquear la tablet <xliff:g id="NUMBER">%d</xliff:g> veces de manera incorrecta. Se restablecerá la tablet, lo que borrará todos los datos."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Intentaste desbloquear el teléfono <xliff:g id="NUMBER">%d</xliff:g> veces de manera incorrecta. Se restablecerá el teléfono, lo que borrará todos los datos."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Intentaste desbloquear la tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> veces de manera incorrecta. Después de <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos más, se quitará este usuario, lo que borrará todos los datos asociados."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Intentaste desbloquear el teléfono <xliff:g id="NUMBER_0">%1$d</xliff:g> veces de manera incorrecta. Después de <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos más, se quitará este usuario, lo que borrará todos los datos asociados."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Intentaste desbloquear la tablet <xliff:g id="NUMBER">%d</xliff:g> veces de manera incorrecta. Se quitará el usuario, lo que borrará todos los datos asociados."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Intentaste desbloquear el teléfono <xliff:g id="NUMBER">%d</xliff:g> veces de manera incorrecta. Se quitará el usuario, lo que borrará todos los datos asociados."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Intentaste desbloquear la tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> veces de manera incorrecta. Después de <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos más, se quitará el perfil de trabajo, lo que borrará todos los datos asociados."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Intentaste desbloquear el teléfono <xliff:g id="NUMBER_0">%1$d</xliff:g> veces de manera incorrecta. Después de <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos más, se quitará el perfil de trabajo, lo que borrará todos los datos asociados."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Intentaste desbloquear la tablet <xliff:g id="NUMBER">%d</xliff:g> veces de manera incorrecta. Se quitará el perfil de trabajo, lo que borrará todos los datos asociados."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Intentaste desbloquear el teléfono <xliff:g id="NUMBER">%d</xliff:g> veces de manera incorrecta. Se quitará el perfil de trabajo, lo que borrará todos los datos asociados."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Dibujaste el patrón de desbloqueo <xliff:g id="NUMBER_0">%1$d</xliff:g> veces de manera incorrecta. Después de <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos más, se te solicitará que desbloquees la tablet mediante una cuenta de correo electrónico.\n\n Vuelve a intentarlo en <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Dibujaste el patrón de desbloqueo <xliff:g id="NUMBER_0">%1$d</xliff:g> veces de manera incorrecta. Después de <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos más, se te solicitará que desbloquees el dispositivo mediante una cuenta de correo electrónico.\n\n Vuelve a intentarlo en <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-es/strings.xml b/packages/SystemUI/res-product/values-es/strings.xml
index ed94cb27ea00..7ac98b257f3e 100644
--- a/packages/SystemUI/res-product/values-es/strings.xml
+++ b/packages/SystemUI/res-product/values-es/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"No se ha insertado ninguna tarjeta SIM en el tablet."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"No se ha insertado ninguna tarjeta SIM en el teléfono."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"Los códigos PIN no coinciden"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Has fallado <xliff:g id="NUMBER_0">%1$d</xliff:g> veces al desbloquear el tablet. Si fallas otras <xliff:g id="NUMBER_1">%2$d</xliff:g> veces, se recuperarán los ajustes de fábrica de este tablet y se eliminarán todos sus datos."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Has fallado <xliff:g id="NUMBER_0">%1$d</xliff:g> veces al desbloquear el teléfono. Si fallas otras <xliff:g id="NUMBER_1">%2$d</xliff:g> veces, se recuperarán los ajustes de fábrica de este teléfono y se eliminarán todos sus datos."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Has fallado <xliff:g id="NUMBER">%d</xliff:g> veces al desbloquear el tablet. Se recuperarán los ajustes de fábrica de este tablet y se eliminarán todos sus datos."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Has fallado <xliff:g id="NUMBER">%d</xliff:g> veces al desbloquear el teléfono. Se recuperarán los ajustes de fábrica de este teléfono y se eliminarán todos sus datos."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Has fallado <xliff:g id="NUMBER_0">%1$d</xliff:g> veces al desbloquear el tablet. Si fallas otras <xliff:g id="NUMBER_1">%2$d</xliff:g> veces, se quitará a este usuario y se eliminarán todos sus datos."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Has fallado <xliff:g id="NUMBER_0">%1$d</xliff:g> veces al desbloquear el teléfono. Si fallas otras <xliff:g id="NUMBER_1">%2$d</xliff:g> veces, se quitará a este usuario y se eliminarán todos sus datos."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"El dispositivo Android TV pronto se apagará; pulsa un botón para evitarlo."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"El dispositivo pronto se apagará si no interactúas con él."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Has fallado <xliff:g id="NUMBER">%d</xliff:g> veces al desbloquear el tablet. Se quitará este perfil de trabajo se quitará y se eliminarán todos sus datos."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Has fallado <xliff:g id="NUMBER">%d</xliff:g> veces al desbloquear el teléfono. Se quitará este perfil de trabajo y se eliminarán todos sus datos."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Has fallado <xliff:g id="NUMBER_0">%1$d</xliff:g> veces al dibujar el patrón de desbloqueo. Si fallas otras <xliff:g id="NUMBER_1">%2$d</xliff:g> veces, tendrás que usar una cuenta de correo electrónico para desbloquear el tablet.\n\n Vuelve a intentarlo en <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Has fallado <xliff:g id="NUMBER_0">%1$d</xliff:g> veces al dibujar el patrón de desbloqueo. Si fallas otras <xliff:g id="NUMBER_1">%2$d</xliff:g> veces, tendrás que usar una cuenta de correo electrónico para desbloquear el teléfono.\n\n Vuelve a intentarlo en <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Coloca bien el teléfono para cargarlo más rápido"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Coloca bien el teléfono para cargarlo de manera inalámbrica"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"El dispositivo Android TV pronto se apagará; pulsa un botón para evitarlo."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"El dispositivo pronto se apagará si no interactúas con él."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"No hay ninguna tarjeta SIM en el tablet."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"No hay ninguna tarjeta SIM en el teléfono."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"Los códigos PIN no coinciden"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Has intentado desbloquear el tablet de forma incorrecta <xliff:g id="NUMBER_0">%1$d</xliff:g> veces. Si se producen <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos más, se restablecerá el tablet y se eliminarán todos sus datos."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Has intentado desbloquear el teléfono de forma incorrecta <xliff:g id="NUMBER_0">%1$d</xliff:g> veces. Si se producen <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos más, se restablecerá el teléfono y se eliminarán todos sus datos."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Has intentado desbloquear el tablet de forma incorrecta <xliff:g id="NUMBER">%d</xliff:g> veces. Se restablecerá el tablet y se eliminarán todos sus datos."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Has intentado desbloquear el teléfono de forma incorrecta <xliff:g id="NUMBER">%d</xliff:g> veces. Se restablecerá el teléfono y se eliminarán todos sus datos."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Has intentado desbloquear el tablet de forma incorrecta <xliff:g id="NUMBER_0">%1$d</xliff:g> veces. Si se producen <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos más, se quitará este usuario y se eliminarán todos sus datos."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Has intentado desbloquear el teléfono de forma incorrecta <xliff:g id="NUMBER_0">%1$d</xliff:g> veces. Si se producen <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos más, se quitará este usuario y se eliminarán todos sus datos."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Has intentado desbloquear el tablet de forma incorrecta <xliff:g id="NUMBER">%d</xliff:g> veces. Se quitará este usuario y se eliminarán todos sus datos."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Has intentado desbloquear el teléfono de forma incorrecta <xliff:g id="NUMBER">%d</xliff:g> veces. Se quitará este usuario y se eliminarán todos sus datos."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Has intentado desbloquear el tablet de forma incorrecta <xliff:g id="NUMBER_0">%1$d</xliff:g> veces. Si se producen <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos más, se quitará el perfil de trabajo y se eliminarán todos sus datos."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Has intentado desbloquear el teléfono de forma incorrecta <xliff:g id="NUMBER_0">%1$d</xliff:g> veces. Si se producen <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos más, se quitará el perfil de trabajo y se eliminarán todos sus datos."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Has intentado desbloquear el tablet de forma incorrecta <xliff:g id="NUMBER">%d</xliff:g> veces. Se quitará este perfil de trabajo y se eliminarán todos sus datos."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Has intentado desbloquear el teléfono de forma incorrecta <xliff:g id="NUMBER">%d</xliff:g> veces. Se quitará este perfil de trabajo y se eliminarán todos sus datos."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Has dibujado un patrón de desbloqueo incorrecto <xliff:g id="NUMBER_0">%1$d</xliff:g> veces. Si se producen <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos más, se te pedirá que desbloquees el tablet con una cuenta de correo electrónico.\n\n Vuelve a intentarlo en <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Has dibujado un patrón de desbloqueo incorrecto <xliff:g id="NUMBER_0">%1$d</xliff:g> veces. Si se producen <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos más, se te pedirá que desbloquees el teléfono con una cuenta de correo electrónico.\n\n Vuelve a intentarlo en <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-et/strings.xml b/packages/SystemUI/res-product/values-et/strings.xml
index 1c4688ae325a..1337c227f790 100644
--- a/packages/SystemUI/res-product/values-et/strings.xml
+++ b/packages/SystemUI/res-product/values-et/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"Tahvelarvutis pole SIM-kaarti."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"Telefonis pole SIM-kaarti."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"PIN-koodid ei ole vastavuses"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Olete püüdnud <xliff:g id="NUMBER_0">%1$d</xliff:g> korda tahvelarvutit valesti avada. Pärast veel <xliff:g id="NUMBER_1">%2$d</xliff:g> ebaõnnestunud katset tahvelarvuti lähtestatakse ja kõik selle andmed kustutatakse."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Olete püüdnud <xliff:g id="NUMBER_0">%1$d</xliff:g> korda telefoni valesti avada. Pärast veel <xliff:g id="NUMBER_1">%2$d</xliff:g> ebaõnnestunud katset telefon lähtestatakse ja kõik selle andmed kustutatakse."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Olete püüdnud <xliff:g id="NUMBER">%d</xliff:g> korda tahvelarvutit valesti avada. Tahvelarvuti lähtestatakse ja kõik selle andmed kustutatakse."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Olete püüdnud <xliff:g id="NUMBER">%d</xliff:g> korda telefoni valesti avada. Telefon lähtestatakse ja kõik selle andmed kustutatakse."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Olete püüdnud <xliff:g id="NUMBER_0">%1$d</xliff:g> korda tahvelarvutit valesti avada. Pärast veel <xliff:g id="NUMBER_1">%2$d</xliff:g> ebaõnnestunud katset kasutaja eemaldatakse ja kõik kasutajaandmed kustutatakse."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Olete püüdnud <xliff:g id="NUMBER_0">%1$d</xliff:g> korda telefoni valesti avada. Pärast veel <xliff:g id="NUMBER_1">%2$d</xliff:g> ebaõnnestunud katset kasutaja eemaldatakse ja kõik kasutajaandmed kustutatakse."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Android TV seade lülitub varsti välja; selle aktiivsena hoidmiseks vajutage nuppu."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Seade lülitub värsti välja; selle aktiivsena hoidmiseks vajutage nuppu."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Olete püüdnud <xliff:g id="NUMBER">%d</xliff:g> korda tahvelarvutit valesti avada. Tööprofiil eemaldatakse ja kõik profiiliandmed kustutatakse."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Olete püüdnud <xliff:g id="NUMBER">%d</xliff:g> korda telefoni valesti avada. Tööprofiil eemaldatakse ja kõik profiiliandmed kustutatakse."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Joonistasite oma avamismustri <xliff:g id="NUMBER_0">%1$d</xliff:g> korda valesti. Pärast veel <xliff:g id="NUMBER_1">%2$d</xliff:g> ebaõnnestunud katset palutakse teil tahvelarvuti avada meilikontoga.\n\n Proovige uuesti <xliff:g id="NUMBER_2">%3$d</xliff:g> sekundi pärast."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Joonistasite oma avamismustri <xliff:g id="NUMBER_0">%1$d</xliff:g> korda valesti. Pärast veel <xliff:g id="NUMBER_1">%2$d</xliff:g> ebaõnnestunud katset palutakse teil telefon avada meilikontoga.\n\n Proovige uuesti <xliff:g id="NUMBER_2">%3$d</xliff:g> sekundi pärast."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Kiiremaks laadimiseks asetage telefon õigesti"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Juhtmeta laadimiseks asetage telefon õigesti"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Android TV seade lülitub varsti välja; selle aktiivsena hoidmiseks vajutage nuppu."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Seade lülitub värsti välja; selle aktiivsena hoidmiseks vajutage nuppu."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Tahvelarvutis pole SIM-kaarti."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Telefonis pole SIM-kaarti."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"PIN-koodid ei ole vastavuses"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Olete püüdnud <xliff:g id="NUMBER_0">%1$d</xliff:g> korda tahvelarvutit valesti avada. Pärast veel <xliff:g id="NUMBER_1">%2$d</xliff:g> ebaõnnestunud katset tahvelarvuti lähtestatakse ja kõik selle andmed kustutatakse."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Olete püüdnud <xliff:g id="NUMBER_0">%1$d</xliff:g> korda telefoni valesti avada. Pärast veel <xliff:g id="NUMBER_1">%2$d</xliff:g> ebaõnnestunud katset telefon lähtestatakse ja kõik selle andmed kustutatakse."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Olete püüdnud <xliff:g id="NUMBER">%d</xliff:g> korda tahvelarvutit valesti avada. Tahvelarvuti lähtestatakse ja kõik selle andmed kustutatakse."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Olete püüdnud <xliff:g id="NUMBER">%d</xliff:g> korda telefoni valesti avada. Telefon lähtestatakse ja kõik selle andmed kustutatakse."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Olete püüdnud <xliff:g id="NUMBER_0">%1$d</xliff:g> korda tahvelarvutit valesti avada. Pärast veel <xliff:g id="NUMBER_1">%2$d</xliff:g> ebaõnnestunud katset kasutaja eemaldatakse ja kõik kasutajaandmed kustutatakse."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Olete püüdnud <xliff:g id="NUMBER_0">%1$d</xliff:g> korda telefoni valesti avada. Pärast veel <xliff:g id="NUMBER_1">%2$d</xliff:g> ebaõnnestunud katset kasutaja eemaldatakse ja kõik kasutajaandmed kustutatakse."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Olete püüdnud <xliff:g id="NUMBER">%d</xliff:g> korda tahvelarvutit valesti avada. Kasutaja eemaldatakse ja kõik kasutajaandmed kustutatakse."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Olete püüdnud <xliff:g id="NUMBER">%d</xliff:g> korda telefoni valesti avada. Kasutaja eemaldatakse ja kõik kasutajaandmed kustutatakse."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Olete püüdnud <xliff:g id="NUMBER_0">%1$d</xliff:g> korda tahvelarvutit valesti avada. Pärast veel <xliff:g id="NUMBER_1">%2$d</xliff:g> ebaõnnestunud katset tööprofiil eemaldatakse ja kõik profiiliandmed kustutatakse."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Olete püüdnud <xliff:g id="NUMBER_0">%1$d</xliff:g> korda telefoni valesti avada. Pärast veel <xliff:g id="NUMBER_1">%2$d</xliff:g> ebaõnnestunud katset tööprofiil eemaldatakse ja kõik profiiliandmed kustutatakse."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Olete püüdnud <xliff:g id="NUMBER">%d</xliff:g> korda tahvelarvutit valesti avada. Tööprofiil eemaldatakse ja kõik profiiliandmed kustutatakse."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Olete püüdnud <xliff:g id="NUMBER">%d</xliff:g> korda telefoni valesti avada. Tööprofiil eemaldatakse ja kõik profiiliandmed kustutatakse."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Joonistasite oma avamismustri <xliff:g id="NUMBER_0">%1$d</xliff:g> korda valesti. Pärast veel <xliff:g id="NUMBER_1">%2$d</xliff:g> ebaõnnestunud katset palutakse teil tahvelarvuti avada meilikontoga.\n\n Proovige uuesti <xliff:g id="NUMBER_2">%3$d</xliff:g> sekundi pärast."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Joonistasite oma avamismustri <xliff:g id="NUMBER_0">%1$d</xliff:g> korda valesti. Pärast veel <xliff:g id="NUMBER_1">%2$d</xliff:g> ebaõnnestunud katset palutakse teil telefon avada meilikontoga.\n\n Proovige uuesti <xliff:g id="NUMBER_2">%3$d</xliff:g> sekundi pärast."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-eu/strings.xml b/packages/SystemUI/res-product/values-eu/strings.xml
index 265400abaa22..7c061f2a1506 100644
--- a/packages/SystemUI/res-product/values-eu/strings.xml
+++ b/packages/SystemUI/res-product/values-eu/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"Ez dago SIM txartelik tabletan."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"Ez dago SIM txartelik telefonoan."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"PIN kodeak ez datoz bat"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"<xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz saiatu zara tableta desblokeatzen, baina huts egin duzu denetan. Beste <xliff:g id="NUMBER_1">%2$d</xliff:g> aldiz huts egiten baduzu, berrezarri egingo da tableta eta, ondorioz, bertako datu guztiak ezabatuko dira."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"<xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz saiatu zara telefonoa desblokeatzen, baina huts egin duzu denetan. Beste <xliff:g id="NUMBER_1">%2$d</xliff:g> aldiz huts egiten baduzu, berrezarri egingo da telefonoa eta, ondorioz, bertako datu guztiak ezabatuko dira."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"<xliff:g id="NUMBER">%d</xliff:g> aldiz saiatu zara tableta desblokeatzen, baina huts egin duzu denetan. Tableta berrezarri egingo da eta, ondorioz, bertako datu guztiak ezabatuko dira."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"<xliff:g id="NUMBER">%d</xliff:g> aldiz saiatu zara telefonoa desblokeatzen, baina huts egin duzu denetan. Telefonoa berrezarri egingo da eta, ondorioz, bertako datu guztiak ezabatuko dira."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"<xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz saiatu zara tableta desblokeatzen, baina huts egin duzu denetan. Beste <xliff:g id="NUMBER_1">%2$d</xliff:g> aldiz huts egiten baduzu, kendu egingo da erabiltzailea eta, ondorioz, haren datu guztiak ezabatuko dira."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"<xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz saiatu zara telefonoa desblokeatzen, baina huts egin duzu denetan. Beste <xliff:g id="NUMBER_1">%2$d</xliff:g> aldiz huts egiten baduzu, kendu egingo da erabiltzailea eta, ondorioz, haren datu guztiak ezabatuko dira."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Android TV gailua laster itzaliko da; sakatu botoi bat piztuta mantentzeko."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Gailua laster itzaliko da; sakatu piztuta mantentzeko."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"<xliff:g id="NUMBER">%d</xliff:g> aldiz saiatu zara tableta desblokeatzen, baina huts egin duzu denetan. Laneko profila kendu egingo da eta, ondorioz, profileko datu guztiak ezabatuko dira."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"<xliff:g id="NUMBER">%d</xliff:g> aldiz saiatu zara telefonoa desblokeatzen, baina huts egin duzu denetan. Laneko profila kendu egingo da eta, ondorioz, profileko datu guztiak ezabatuko dira."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"<xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz marraztu duzu desblokeatzeko eredua, baina huts egin duzu denetan. Beste <xliff:g id="NUMBER_1">%2$d</xliff:g> aldiz huts egiten baduzu, tableta posta-kontu baten bidez desblokeatzeko eskatuko dizugu.\n\n Saiatu berriro <xliff:g id="NUMBER_2">%3$d</xliff:g> segundo barru."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"<xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz marraztu duzu desblokeatzeko eredua, baina huts egin duzu denetan. Beste <xliff:g id="NUMBER_1">%2$d</xliff:g> aldiz huts egiten baduzu, telefonoa posta-kontu baten bidez desblokeatzeko eskatuko dizugu.\n\n Saiatu berriro <xliff:g id="NUMBER_2">%3$d</xliff:g> segundo barru."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Jarri ondo telefonoa, bizkorrago karga dadin"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Jarri ondo telefonoa, haririk gabe karga dadin"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Android TV gailua laster itzaliko da; sakatu botoi bat piztuta mantentzeko."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Gailua laster itzaliko da; sakatu piztuta mantentzeko."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Ez dago SIM txartelik tabletan."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Ez dago SIM txartelik telefonoan."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"PIN kodeak ez datoz bat"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"<xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz saiatu zara tableta desblokeatzen, baina huts egin duzu denetan. Beste <xliff:g id="NUMBER_1">%2$d</xliff:g> aldiz huts egiten baduzu, berrezarri egingo da tableta eta, ondorioz, bertako datu guztiak ezabatuko dira."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"<xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz saiatu zara telefonoa desblokeatzen, baina huts egin duzu denetan. Beste <xliff:g id="NUMBER_1">%2$d</xliff:g> aldiz huts egiten baduzu, berrezarri egingo da telefonoa eta, ondorioz, bertako datu guztiak ezabatuko dira."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"<xliff:g id="NUMBER">%d</xliff:g> aldiz saiatu zara tableta desblokeatzen, baina huts egin duzu denetan. Tableta berrezarri egingo da eta, ondorioz, bertako datu guztiak ezabatuko dira."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"<xliff:g id="NUMBER">%d</xliff:g> aldiz saiatu zara telefonoa desblokeatzen, baina huts egin duzu denetan. Telefonoa berrezarri egingo da eta, ondorioz, bertako datu guztiak ezabatuko dira."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"<xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz saiatu zara tableta desblokeatzen, baina huts egin duzu denetan. Beste <xliff:g id="NUMBER_1">%2$d</xliff:g> aldiz huts egiten baduzu, kendu egingo da erabiltzailea eta, ondorioz, haren datu guztiak ezabatuko dira."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"<xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz saiatu zara telefonoa desblokeatzen, baina huts egin duzu denetan. Beste <xliff:g id="NUMBER_1">%2$d</xliff:g> aldiz huts egiten baduzu, kendu egingo da erabiltzailea eta, ondorioz, haren datu guztiak ezabatuko dira."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"<xliff:g id="NUMBER">%d</xliff:g> aldiz saiatu zara tableta desblokeatzen, baina huts egin duzu denetan. Erabiltzailea kendu egingo da eta, ondorioz, haren datu guztiak ezabatuko dira."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"<xliff:g id="NUMBER">%d</xliff:g> aldiz saiatu zara telefonoa desblokeatzen, baina huts egin duzu denetan. Erabiltzailea kendu egingo da eta, ondorioz, haren datu guztiak ezabatuko dira."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"<xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz saiatu zara tableta desblokeatzen, baina huts egin duzu denetan. Beste <xliff:g id="NUMBER_1">%2$d</xliff:g> aldiz huts egiten baduzu, kendu egingo da laneko profila eta, ondorioz, profileko datu guztiak ezabatuko dira."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"<xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz saiatu zara telefonoa desblokeatzen, baina huts egin duzu denetan. Beste <xliff:g id="NUMBER_1">%2$d</xliff:g> aldiz huts egiten baduzu, kendu egingo da laneko profila eta, ondorioz, profileko datu guztiak ezabatuko dira."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"<xliff:g id="NUMBER">%d</xliff:g> aldiz saiatu zara tableta desblokeatzen, baina huts egin duzu denetan. Laneko profila kendu egingo da eta, ondorioz, profileko datu guztiak ezabatuko dira."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"<xliff:g id="NUMBER">%d</xliff:g> aldiz saiatu zara telefonoa desblokeatzen, baina huts egin duzu denetan. Laneko profila kendu egingo da eta, ondorioz, profileko datu guztiak ezabatuko dira."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Desblokeatzeko eredua oker marraztu duzu <xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz. Beste <xliff:g id="NUMBER_1">%2$d</xliff:g> aldiz oker marrazten baduzu, tableta posta-kontu baten bidez desblokeatzeko eskatuko dizugu.\n\n Saiatu berriro <xliff:g id="NUMBER_2">%3$d</xliff:g> segundo barru."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Desblokeatzeko eredua oker marraztu duzu <xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz. Beste <xliff:g id="NUMBER_1">%2$d</xliff:g> aldiz oker marrazten baduzu, telefonoa posta-kontu baten bidez desblokeatzeko eskatuko dizugu.\n\n Saiatu berriro <xliff:g id="NUMBER_2">%3$d</xliff:g> segundo barru."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-fa/strings.xml b/packages/SystemUI/res-product/values-fa/strings.xml
index 018c17dd22bf..08ec54ecff92 100644
--- a/packages/SystemUI/res-product/values-fa/strings.xml
+++ b/packages/SystemUI/res-product/values-fa/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"سیم‌کارت درون رایانهٔ لوحی نیست."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"سیم‌کارت درون تلفن نیست."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"کدهای پین منطبق نیستند"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"<xliff:g id="NUMBER_0">%1$d</xliff:g> تلاش ناموفق برای باز کردن قفل رایانه لوحی داشته‌اید. پس از <xliff:g id="NUMBER_1">%2$d</xliff:g> تلاش ناموفق دیگر، این رایانه لوحی بازنشانی می‌شود که با آن همه داده‌هایش حذف می‌شود."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"<xliff:g id="NUMBER_0">%1$d</xliff:g> تلاش ناموفق برای باز کردن قفل تلفن داشته‌اید. پس از <xliff:g id="NUMBER_1">%2$d</xliff:g> تلاش ناموفق دیگر، تلفن بازنشانی می‌شود که با آن همه داده‌هایش حذف می‌شود."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"<xliff:g id="NUMBER">%d</xliff:g> تلاش ناموفق برای باز کردن قفل رایانه لوحی داشته‌اید. این رایانه لوحی بازنشانی می‌شود که با آن همه داده‌هایش حذف می‌شود."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"<xliff:g id="NUMBER">%d</xliff:g> تلاش ناموفق برای باز کردن قفل تلفن داشته‌اید. این تلفن بازنشانی می‌شود که با آن همه داده‌هایش حذف می‌شود."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"<xliff:g id="NUMBER_0">%1$d</xliff:g> تلاش ناموفق برای باز کردن قفل رایانه لوحی داشته‌اید. پس از <xliff:g id="NUMBER_1">%2$d</xliff:g> تلاش ناموفق دیگر، این کاربر پاک می‌شود که با آن همه داده‌های کاربر حذف می‌شود."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"<xliff:g id="NUMBER_0">%1$d</xliff:g> تلاش ناموفق برای باز کردن قفل تلفن داشته‌اید. پس از <xliff:g id="NUMBER_1">%2$d</xliff:g> تلاش ناموفق دیگر، این کاربر پاک می‌شود که با آن همه داده‌های کاربر حذف می‌شود."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"‏دستگاه Android TV به‌زودی خاموش می‌شود، برای روشن نگه‌داشتن آن، دکمه‌ای را فشار دهید."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"دستگاه به‌زودی خاموش می‌شود، برای روشن نگه‌داشتن آن فشار دهید."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"<xliff:g id="NUMBER">%d</xliff:g> تلاش ناموفق برای باز کردن قفل رایانه لوحی داشته‌اید. نمایه کاری پاک می‌شود که با آن همه داده‌های نمایه حذف می‌شود."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"<xliff:g id="NUMBER">%d</xliff:g> تلاش ناموفق برای باز کردن قفل تلفن داشته‌اید. نمایه کاری پاک می‌شود که با آن همه داده‌های نمایه حذف می‌شود."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"‏شما الگوی باز کردن قفل را <xliff:g id="NUMBER_0">%1$d</xliff:g> بار اشتباه کشیده‎اید. بعد از <xliff:g id="NUMBER_1">%2$d</xliff:g> تلاش ناموفق، از شما خواسته می‎شود که با استفاده از یک حساب ایمیل قفل رایانه لوحی خود را باز کنید.\n\n لطفاً پس از <xliff:g id="NUMBER_2">%3$d</xliff:g> ثانیه دوباره امتحان کنید."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"‏شما الگوی باز کردن قفل را <xliff:g id="NUMBER_0">%1$d</xliff:g> بار اشتباه کشیده‌اید. پس از <xliff:g id="NUMBER_1">%2$d</xliff:g> تلاش ناموفق، از شما خواسته می‎شود که با استفاده از یک حساب ایمیل قفل تلفن را باز کنید.\n\n لطفاً پس از <xliff:g id="NUMBER_2">%3$d</xliff:g> ثانیه دوباره امتحان کنید."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"برای شارژ سریع، تلفن را هم‌تراز کنید"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"برای شارژ بی‌سیم، تلفن را هم‌تراز کنید"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"‏دستگاه Android TV به‌زودی خاموش می‌شود، برای روشن نگه‌داشتن آن، دکمه‌ای را فشار دهید."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"دستگاه به‌زودی خاموش می‌شود، برای روشن نگه‌داشتن آن فشار دهید."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"سیم‌کارت درون رایانهٔ لوحی نیست."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"سیم‌کارت درون تلفن نیست."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"کدهای پین منطبق نیستند"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"<xliff:g id="NUMBER_0">%1$d</xliff:g> تلاش ناموفق برای باز کردن قفل رایانه لوحی داشته‌اید. پس از <xliff:g id="NUMBER_1">%2$d</xliff:g> تلاش ناموفق دیگر، این رایانه لوحی بازنشانی می‌شود که با آن همه داده‌هایش حذف می‌شود."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"<xliff:g id="NUMBER_0">%1$d</xliff:g> تلاش ناموفق برای باز کردن قفل تلفن داشته‌اید. پس از <xliff:g id="NUMBER_1">%2$d</xliff:g> تلاش ناموفق دیگر، تلفن بازنشانی می‌شود که با آن همه داده‌هایش حذف می‌شود."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"<xliff:g id="NUMBER">%d</xliff:g> تلاش ناموفق برای باز کردن قفل رایانه لوحی داشته‌اید. این رایانه لوحی بازنشانی می‌شود که با آن همه داده‌هایش حذف می‌شود."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"<xliff:g id="NUMBER">%d</xliff:g> تلاش ناموفق برای باز کردن قفل تلفن داشته‌اید. این تلفن بازنشانی می‌شود که با آن همه داده‌هایش حذف می‌شود."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"<xliff:g id="NUMBER_0">%1$d</xliff:g> تلاش ناموفق برای باز کردن قفل رایانه لوحی داشته‌اید. پس از <xliff:g id="NUMBER_1">%2$d</xliff:g> تلاش ناموفق دیگر، این کاربر پاک می‌شود که با آن همه داده‌های کاربر حذف می‌شود."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"<xliff:g id="NUMBER_0">%1$d</xliff:g> تلاش ناموفق برای باز کردن قفل تلفن داشته‌اید. پس از <xliff:g id="NUMBER_1">%2$d</xliff:g> تلاش ناموفق دیگر، این کاربر پاک می‌شود که با آن همه داده‌های کاربر حذف می‌شود."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"<xliff:g id="NUMBER">%d</xliff:g> تلاش ناموفق برای باز کردن قفل رایانه لوحی داشته‌اید. این کاربر پام می‌شود که با آن همه داده‌های کاربر حذف می‌شود."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"<xliff:g id="NUMBER">%d</xliff:g> تلاش ناموفق برای باز کردن قفل تلفن داشته‌اید. این کاربر پاک می‌شود که با آن همه داده‌های کاربر حذف می‌شود."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"<xliff:g id="NUMBER_0">%1$d</xliff:g> تلاش ناموفق برای باز کردن قفل رایانه لوحی داشته‌اید. پس از <xliff:g id="NUMBER_1">%2$d</xliff:g> تلاش ناموفق دیگر، نمایه کاری پاک می‌شود که با آن همه داده‌های نمایه حذف می‌شود."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"<xliff:g id="NUMBER_0">%1$d</xliff:g> تلاش ناموفق برای باز کردن قفل تلفن داشته‌اید. پس از <xliff:g id="NUMBER_1">%2$d</xliff:g> تلاش ناموفق دیگر، نمایه کاری پاک می‌شود که با آن همه داده‌های نمایه حذف می‌شود."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"<xliff:g id="NUMBER">%d</xliff:g> تلاش ناموفق برای باز کردن قفل رایانه لوحی داشته‌اید. نمایه کاری پاک می‌شود که با آن همه داده‌های نمایه حذف می‌شود."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"<xliff:g id="NUMBER">%d</xliff:g> تلاش ناموفق برای باز کردن قفل تلفن داشته‌اید. نمایه کاری پاک می‌شود که با آن همه داده‌های نمایه حذف می‌شود."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"‏شما الگوی باز کردن قفل را <xliff:g id="NUMBER_0">%1$d</xliff:g> بار اشتباه کشیده‌اید. بعد از <xliff:g id="NUMBER_1">%2$d</xliff:g> تلاش ناموفق، از شما خواسته می‎شود که با استفاده از یک حساب ایمیل قفل رایانه لوحی خود را باز کنید.\n\n لطفاً پس از <xliff:g id="NUMBER_2">%3$d</xliff:g> ثانیه دوباره امتحان کنید."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"شما الگوی باز کردن قفل را <xliff:g id="NUMBER_0">%1$d</xliff:g> بار اشتباه کشیده‌اید. پس از <xliff:g id="NUMBER_1">%2$d</xliff:g> تلاش ناموفق، از شما خواسته می‌شود که با استفاده از یک حساب ایمیل قفل تلفن را باز کنید.\n\n لطفاً پس از <xliff:g id="NUMBER_2">%3$d</xliff:g> ثانیه دوباره امتحان کنید."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-fi/strings.xml b/packages/SystemUI/res-product/values-fi/strings.xml
index 377b577e3823..340c0672ef73 100644
--- a/packages/SystemUI/res-product/values-fi/strings.xml
+++ b/packages/SystemUI/res-product/values-fi/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"Tabletissa ei ole SIM-korttia."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"Puhelimessa ei ole SIM-korttia."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"PIN-koodit eivät täsmää"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Yritit avata tabletin lukituksen virheellisillä tiedoilla <xliff:g id="NUMBER_0">%1$d</xliff:g> kertaa. Jos <xliff:g id="NUMBER_1">%2$d</xliff:g> seuraavaa yritystä epäonnistuu, tämä puhelin nollataan ja kaikki sen tiedot poistetaan."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Yritit avata puhelimen lukituksen virheellisillä tiedoilla <xliff:g id="NUMBER_0">%1$d</xliff:g> kertaa. Jos <xliff:g id="NUMBER_1">%2$d</xliff:g> seuraavaa yritystä epäonnistuu, tämä puhelin nollataan ja kaikki sen tiedot poistetaan."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Yritit avata tabletin lukituksen virheellisillä tiedoilla <xliff:g id="NUMBER">%d</xliff:g> kertaa. Tämä tabletti nollataan ja kaikki sen tiedot poistetaan."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Yritit avata puhelimen lukituksen virheellisillä tiedoilla <xliff:g id="NUMBER">%d</xliff:g> kertaa. Tämä puhelin nollataan ja kaikki sen tiedot poistetaan."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Yritit avata tabletin lukituksen virheellisillä tiedoilla <xliff:g id="NUMBER_0">%1$d</xliff:g> kertaa. Jos <xliff:g id="NUMBER_1">%2$d</xliff:g> seuraavaa yritystä epäonnistuu, tämä käyttäjä ja kaikki sen käyttäjätiedot poistetaan."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Yritit avata puhelimen lukituksen virheellisillä tiedoilla <xliff:g id="NUMBER_0">%1$d</xliff:g> kertaa. Jos <xliff:g id="NUMBER_1">%2$d</xliff:g> seuraavaa yritystä epäonnistuu, tämä käyttäjä ja kaikki käyttäjän tiedot poistetaan."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Android TV ‑laite sammuu pian. Pidä se päällä painamalla painiketta."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Laite sammuu pian. Pidä se päällä painamalla jotakin."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Yritit avata tabletin lukituksen virheellisillä tiedoilla <xliff:g id="NUMBER">%d</xliff:g> kertaa. Työprofiili ja kaikki sen tiedot poistetaan."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Yritit avata puhelimen lukituksen virheellisillä tiedoilla <xliff:g id="NUMBER">%d</xliff:g> kertaa. Työprofiili ja kaikki sen tiedot poistetaan."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Piirsit lukituksenpoistokuvion väärin <xliff:g id="NUMBER_0">%1$d</xliff:g> kertaa. Jos piirrät kuvion väärin vielä <xliff:g id="NUMBER_1">%2$d</xliff:g> kertaa, sinua pyydetään avaamaan tabletin lukitus sähköpostitilin avulla.\n\n Yritä uudelleen <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunnin kuluttua."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Piirsit lukituksenpoistokuvion väärin <xliff:g id="NUMBER_0">%1$d</xliff:g> kertaa. Jos piirrät kuvion väärin vielä <xliff:g id="NUMBER_1">%2$d</xliff:g> kertaa, sinua pyydetään avaamaan puhelimesi lukitus sähköpostitilin avulla.\n\n Yritä uudelleen <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunnin kuluttua."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Siirrä puhelinta, jotta se latautuu nopeammin"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Siirrä puhelinta, jotta se latautuu langattomasti"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Android TV ‑laite sammuu pian. Pidä se päällä painamalla painiketta."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Laite sammuu pian. Pidä se päällä painamalla."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Tabletissa ei ole SIM-korttia."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Puhelimessa ei ole SIM-korttia."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"PIN-koodit eivät täsmää"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Yritit avata tabletin lukituksen virheellisillä tiedoilla <xliff:g id="NUMBER_0">%1$d</xliff:g> kertaa. Jos <xliff:g id="NUMBER_1">%2$d</xliff:g> seuraavaa yritystä epäonnistuu, tämä puhelin nollataan ja kaikki sen data poistetaan."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Yritit avata puhelimen lukituksen virheellisillä tiedoilla <xliff:g id="NUMBER_0">%1$d</xliff:g> kertaa. Jos <xliff:g id="NUMBER_1">%2$d</xliff:g> seuraavaa yritystä epäonnistuu, tämä puhelin nollataan ja kaikki sen data poistetaan."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Yritit avata tabletin lukituksen virheellisillä tiedoilla <xliff:g id="NUMBER">%d</xliff:g> kertaa. Tämä tabletti nollataan ja kaikki sen data poistetaan."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Yritit avata puhelimen lukituksen virheellisillä tiedoilla <xliff:g id="NUMBER">%d</xliff:g> kertaa. Tämä puhelin nollataan ja kaikki sen data poistetaan."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Yritit avata tabletin lukituksen virheellisillä tiedoilla <xliff:g id="NUMBER_0">%1$d</xliff:g> kertaa. Jos <xliff:g id="NUMBER_1">%2$d</xliff:g> seuraavaa yritystä epäonnistuu, tämä käyttäjä ja kaikki sen käyttäjädata poistetaan."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Yritit avata puhelimen lukituksen virheellisillä tiedoilla <xliff:g id="NUMBER_0">%1$d</xliff:g> kertaa. Jos <xliff:g id="NUMBER_1">%2$d</xliff:g> seuraavaa yritystä epäonnistuu, tämä käyttäjä ja kaikki käyttäjän data poistetaan."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Yritit avata tabletin lukituksen virheellisillä tiedoilla <xliff:g id="NUMBER">%d</xliff:g> kertaa. Tämä käyttäjä ja kaikki käyttäjän data poistetaan."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Yritit avata puhelimen lukituksen virheellisillä tiedoilla <xliff:g id="NUMBER">%d</xliff:g> kertaa. Tämä käyttäjä ja kaikki käyttäjän data poistetaan."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Yritit avata tabletin lukituksen virheellisillä tiedoilla <xliff:g id="NUMBER_0">%1$d</xliff:g> kertaa. Jos <xliff:g id="NUMBER_1">%2$d</xliff:g> seuraavaa yritystä epäonnistuu, työprofiili ja kaikki sen data poistetaan."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Yritit avata puhelimen lukituksen virheellisillä tiedoilla <xliff:g id="NUMBER_0">%1$d</xliff:g> kertaa. Jos <xliff:g id="NUMBER_1">%2$d</xliff:g> seuraavaa yritystä epäonnistuu, työprofiili ja kaikki sen data poistetaan."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Yritit avata tabletin lukituksen virheellisillä tiedoilla <xliff:g id="NUMBER">%d</xliff:g> kertaa. Työprofiili ja kaikki sen data poistetaan."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Yritit avata puhelimen lukituksen virheellisillä tiedoilla <xliff:g id="NUMBER">%d</xliff:g> kertaa. Työprofiili ja kaikki sen data poistetaan."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Piirsit lukituksenpoistokuvion väärin <xliff:g id="NUMBER_0">%1$d</xliff:g> kertaa. Jos piirrät kuvion väärin vielä <xliff:g id="NUMBER_1">%2$d</xliff:g> kertaa, sinua pyydetään avaamaan tabletin lukitus sähköpostitilin avulla.\n\n Yritä uudelleen <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunnin kuluttua."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Piirsit lukituksenpoistokuvion väärin <xliff:g id="NUMBER_0">%1$d</xliff:g> kertaa. Jos piirrät kuvion väärin vielä <xliff:g id="NUMBER_1">%2$d</xliff:g> kertaa, sinua pyydetään avaamaan puhelimesi lukitus sähköpostitilin avulla.\n\n Yritä uudelleen <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunnin kuluttua."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-fr-rCA/strings.xml b/packages/SystemUI/res-product/values-fr-rCA/strings.xml
index 44299379cb32..e56234bad207 100644
--- a/packages/SystemUI/res-product/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res-product/values-fr-rCA/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"Aucune carte SIM n\'est insérée dans la tablette."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"Aucune carte SIM n\'est insérée dans le téléphone."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"Les NIP ne correspondent pas."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Vous avez tenté de déverrouiller cette tablette à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. Après <xliff:g id="NUMBER_1">%2$d</xliff:g> tentative(s) infructueuse(s) supplémentaire(s), cette tablette sera réinitialisée, ce qui entraînera la suppression de toutes les données qu\'elle contient."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Vous avez tenté de déverrouiller ce téléphone à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. Après <xliff:g id="NUMBER_1">%2$d</xliff:g> tentative(s) infructueuse(s) supplémentaire(s), le téléphone sera réinitialisé, ce qui entraînera la suppression de toutes les données qu\'il contient."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Vous avez tenté de déverrouiller cette tablette à <xliff:g id="NUMBER">%d</xliff:g> reprises. Cette tablette sera réinitialisée, ce qui entraîne la suppression de toutes les données qu\'elle contient."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Vous avez tenté de déverrouiller ce téléphone à <xliff:g id="NUMBER">%d</xliff:g> reprises. Ce téléphone sera réinitialisé, ce qui entraîne la suppression de toutes les données qu\'il contient."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Vous avez tenté de déverrouiller cette tablette à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. Après <xliff:g id="NUMBER_1">%2$d</xliff:g> tentative(s) infructueuse(s) supplémentaire(s), cet utilisateur sera supprimé, ce qui entraînera la suppression de toutes ses données."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Vous avez tenté de déverrouiller ce téléphone à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. Après <xliff:g id="NUMBER_1">%2$d</xliff:g> tentative(s) infructueuse(s) supplémentaire(s), cet utilisateur sera supprimé, ce qui entraînera la suppression de toutes ses données."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"L\'appareil Android TV va bientôt s\'éteindre. Appuyez sur un bouton pour le laisser allumé."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"L\'appareil va bientôt s\'éteindre. Interagissez avec lui pour le laisser allumé."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Vous avez tenté de déverrouiller cette tablette à <xliff:g id="NUMBER">%d</xliff:g> reprises. Le profil professionnel sera supprimé, ce qui entraîne la suppression de toutes ses données."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Vous avez tenté de déverrouiller ce téléphone à <xliff:g id="NUMBER">%d</xliff:g> reprises. Le profil professionnel sera supprimé, ce qui entraîne la suppression de toutes ses données."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Vous avez dessiné un schéma de déverrouillage incorrect à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%2$d</xliff:g> fois, vous devrez déverrouiller votre tablette à l\'aide d\'un compte de courriel.\n\nVeuillez réessayer dans <xliff:g id="NUMBER_2">%3$d</xliff:g> secondes."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Vous avez dessiné un schéma de déverrouillage incorrect à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%2$d</xliff:g> fois, vous devrez déverrouiller votre téléphone à l\'aide d\'un compte de courriel.\n\nVeuillez réessayer dans <xliff:g id="NUMBER_2">%3$d</xliff:g> secondes."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Réalignez le téléphone pour le recharger plus rapidement"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Réalignez le téléphone pour effectuer la recharge sans fil"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"L\'appareil Android TV va bientôt s\'éteindre. Appuyez sur un bouton pour le laisser allumé."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"L\'appareil va bientôt s\'éteindre. Interagissez avec lui pour le laisser allumé."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Aucune carte SIM n\'est insérée dans la tablette."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Aucune carte SIM n\'est insérée dans le téléphone."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"Les NIP ne correspondent pas."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Vous avez tenté de déverrouiller cette tablette à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. Après <xliff:g id="NUMBER_1">%2$d</xliff:g> tentative(s) infructueuse(s) supplémentaire(s), cette tablette sera réinitialisée, ce qui entraînera la suppression de toutes les données qu\'elle contient."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Vous avez tenté de déverrouiller ce téléphone à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. Après <xliff:g id="NUMBER_1">%2$d</xliff:g> tentative(s) infructueuse(s) supplémentaire(s), le téléphone sera réinitialisé, ce qui entraînera la suppression de toutes les données qu\'il contient."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Vous avez tenté de déverrouiller cette tablette à <xliff:g id="NUMBER">%d</xliff:g> reprises. Cette tablette sera réinitialisée, ce qui entraîne la suppression de toutes les données qu\'elle contient."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Vous avez tenté de déverrouiller ce téléphone à <xliff:g id="NUMBER">%d</xliff:g> reprises. Ce téléphone sera réinitialisé, ce qui entraîne la suppression de toutes les données qu\'il contient."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Vous avez tenté de déverrouiller cette tablette à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. Après <xliff:g id="NUMBER_1">%2$d</xliff:g> tentative(s) infructueuse(s) supplémentaire(s), cet utilisateur sera supprimé, ce qui entraînera la suppression de toutes ses données."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Vous avez tenté de déverrouiller ce téléphone à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. Après <xliff:g id="NUMBER_1">%2$d</xliff:g> tentative(s) infructueuse(s) supplémentaire(s), cet utilisateur sera supprimé, ce qui entraînera la suppression de toutes ses données."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Vous avez tenté de déverrouiller cette tablette à <xliff:g id="NUMBER">%d</xliff:g> reprises. Cet utilisateur sera supprimé, ce qui entraîne la suppression de toutes ses données."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Vous avez tenté de déverrouiller ce téléphone à <xliff:g id="NUMBER">%d</xliff:g> reprises. Cet utilisateur sera supprimé, ce qui entraîne la suppression de toutes ses données."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Vous avez tenté de déverrouiller cette tablette à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. Après <xliff:g id="NUMBER_1">%2$d</xliff:g> tentative(s) infructueuse(s) supplémentaire(s), le profil professionnel sera supprimé, ce qui entraînera la suppression de toutes ses données."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Vous avez tenté de déverrouiller ce téléphone à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. Après <xliff:g id="NUMBER_1">%2$d</xliff:g> tentative(s) infructueuse(s) supplémentaire(s), le profil professionnel sera supprimé, ce qui entraînera la suppression de toutes ses données."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Vous avez tenté de déverrouiller cette tablette à <xliff:g id="NUMBER">%d</xliff:g> reprises. Le profil professionnel sera supprimé, ce qui entraîne la suppression de toutes ses données."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Vous avez tenté de déverrouiller ce téléphone à <xliff:g id="NUMBER">%d</xliff:g> reprises. Le profil professionnel sera supprimé, ce qui entraîne la suppression de toutes ses données."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Vous avez dessiné un schéma de déverrouillage incorrect à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%2$d</xliff:g> fois, vous devrez déverrouiller votre tablette à l\'aide d\'un compte de courriel.\n\nVeuillez réessayer dans <xliff:g id="NUMBER_2">%3$d</xliff:g> secondes."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Vous avez dessiné un schéma de déverrouillage incorrect à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%2$d</xliff:g> fois, vous devrez déverrouiller votre téléphone à l\'aide d\'un compte de courriel.\n\nVeuillez réessayer dans <xliff:g id="NUMBER_2">%3$d</xliff:g> secondes."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-fr/strings.xml b/packages/SystemUI/res-product/values-fr/strings.xml
index 2838c02d538d..075d5ef2142d 100644
--- a/packages/SystemUI/res-product/values-fr/strings.xml
+++ b/packages/SystemUI/res-product/values-fr/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"Aucune carte SIM n\'est insérée dans la tablette."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"Aucune carte SIM n\'est insérée dans le téléphone."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"Les codes PIN ne correspondent pas"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Vous avez tenté de déverrouiller la tablette à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%2$d</xliff:g> fois, elle sera réinitialisée et toutes les données qu\'elle contient seront supprimées."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Vous avez tenté de déverrouiller le téléphone à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%2$d</xliff:g> fois, il sera réinitialisé et toutes les données qu\'il contient seront supprimées."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Vous avez tenté de déverrouiller la tablette à <xliff:g id="NUMBER">%d</xliff:g> reprises. Elle va être réinitialisée et toutes les données qu\'elle contient seront supprimées."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Vous avez tenté de déverrouiller le téléphone à <xliff:g id="NUMBER">%d</xliff:g> reprises. Il va être réinitialisé et toutes les données qu\'il contient seront supprimées."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Vous avez tenté de déverrouiller la tablette à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%2$d</xliff:g> fois, ce compte utilisateur et toutes les données associées seront supprimés."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Vous avez tenté de déverrouiller le téléphone à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%2$d</xliff:g> fois, ce compte utilisateur et toutes les données associées seront supprimés."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"L\'appareil Android TV va bientôt passer en mode Veille. Appuyez sur un bouton pour qu\'il reste allumé."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"L\'appareil va bientôt passer en mode Veille. Appuyez dessus pour qu\'il reste allumé."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Vous avez tenté de déverrouiller la tablette à <xliff:g id="NUMBER">%d</xliff:g> reprises. Le profil professionnel et toutes les données associées vont être supprimés."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Vous avez tenté de déverrouiller le téléphone à <xliff:g id="NUMBER">%d</xliff:g> reprises. Le profil professionnel et toutes les données associées vont être supprimés."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Vous avez dessiné un schéma de déverrouillage incorrect à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%2$d</xliff:g> fois, vous devrez déverrouiller votre tablette à l\'aide d\'un compte de messagerie électronique.\n\nRéessayez dans <xliff:g id="NUMBER_2">%3$d</xliff:g> secondes."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Vous avez dessiné un schéma de déverrouillage incorrect à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%2$d</xliff:g> fois, vous devrez déverrouiller votre téléphone à l\'aide d\'un compte de messagerie électronique.\n\nRéessayez dans <xliff:g id="NUMBER_2">%3$d</xliff:g> secondes."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Réalignez le téléphone pour le recharger plus rapidement"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Réalignez le téléphone pour le recharger sans fil"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"L\'appareil Android TV va bientôt passer en mode Veille. Appuyez sur un bouton pour qu\'il reste allumé."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"L\'appareil va bientôt passer en mode Veille. Appuyez dessus pour qu\'il reste allumé."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Aucune carte SIM n\'est insérée dans la tablette."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Aucune carte SIM n\'est insérée dans le téléphone."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"Les codes PIN ne correspondent pas"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Vous avez tenté de déverrouiller la tablette à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%2$d</xliff:g> fois, elle sera réinitialisée et toutes les données qu\'elle contient seront supprimées."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Vous avez tenté de déverrouiller le téléphone à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%2$d</xliff:g> fois, il sera réinitialisé et toutes les données qu\'il contient seront supprimées."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Vous avez tenté de déverrouiller la tablette à <xliff:g id="NUMBER">%d</xliff:g> reprises. Elle va être réinitialisée et toutes les données qu\'elle contient seront supprimées."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Vous avez tenté de déverrouiller le téléphone à <xliff:g id="NUMBER">%d</xliff:g> reprises. Il va être réinitialisé et toutes les données qu\'il contient seront supprimées."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Vous avez tenté de déverrouiller la tablette à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%2$d</xliff:g> fois, ce compte utilisateur et toutes les données associées seront supprimés."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Vous avez tenté de déverrouiller le téléphone à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%2$d</xliff:g> fois, ce compte utilisateur et toutes les données associées seront supprimés."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Vous avez tenté de déverrouiller la tablette à <xliff:g id="NUMBER">%d</xliff:g> reprises. Cet utilisateur et toutes les données associées vont être supprimés."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Vous avez tenté de déverrouiller le téléphone à <xliff:g id="NUMBER">%d</xliff:g> reprises. Cet utilisateur et toutes les données associées vont être supprimés."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Vous avez tenté de déverrouiller la tablette à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%2$d</xliff:g> fois, le profil professionnel et toutes les données associées seront supprimés."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Vous avez tenté de déverrouiller le téléphone à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%2$d</xliff:g> fois, le profil professionnel et toutes les données associées seront supprimés."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Vous avez tenté de déverrouiller la tablette à <xliff:g id="NUMBER">%d</xliff:g> reprises. Le profil professionnel et toutes les données associées vont être supprimés."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Vous avez tenté de déverrouiller le téléphone à <xliff:g id="NUMBER">%d</xliff:g> reprises. Le profil professionnel et toutes les données associées vont être supprimés."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Vous avez dessiné un schéma de déverrouillage incorrect à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%2$d</xliff:g> fois, vous devrez déverrouiller votre tablette à l\'aide d\'un compte de messagerie électronique.\n\nRéessayez dans <xliff:g id="NUMBER_2">%3$d</xliff:g> secondes."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Vous avez dessiné un schéma de déverrouillage incorrect à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%2$d</xliff:g> fois, vous devrez déverrouiller votre téléphone à l\'aide d\'un compte de messagerie électronique.\n\nRéessayez dans <xliff:g id="NUMBER_2">%3$d</xliff:g> secondes."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-gl/strings.xml b/packages/SystemUI/res-product/values-gl/strings.xml
index b1e045f1a0e2..7af382f3de96 100644
--- a/packages/SystemUI/res-product/values-gl/strings.xml
+++ b/packages/SystemUI/res-product/values-gl/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"Non hai ningunha tarxeta SIM na tableta."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"Non hai ningunha tarxeta SIM no teléfono."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"Os códigos PIN non coinciden"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Tentaches desbloquear a tableta <xliff:g id="NUMBER_0">%1$d</xliff:g> veces de forma incorrecta. Se realizas <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos máis, restablecerase a tableta e, por conseguinte, eliminaranse todos os seus datos."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Tentaches desbloquear o teléfono <xliff:g id="NUMBER_0">%1$d</xliff:g> veces de forma incorrecta. Se realizas <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos máis, restablecerase o teléfono e, por conseguinte, eliminaranse todos os seus datos."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Tentaches desbloquear a tableta <xliff:g id="NUMBER">%d</xliff:g> veces de forma incorrecta. Restablecerase a tableta e, por conseguinte, eliminaranse todos os seus datos."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Tentaches desbloquear o teléfono <xliff:g id="NUMBER">%d</xliff:g> veces de forma incorrecta. Restablecerase o teléfono e, por conseguinte, eliminaranse todos os seus datos."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Tentaches desbloquear a tableta <xliff:g id="NUMBER_0">%1$d</xliff:g> veces de forma incorrecta. Se realizas <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos máis, quitarase este usuario e, por conseguinte, todos os datos do usuario."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Tentaches desbloquear o teléfono <xliff:g id="NUMBER_0">%1$d</xliff:g> veces de forma incorrecta. Se realizas <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos máis, quitarase este usuario e, por conseguinte, todos os datos do usuario."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Pronto se apagará o dispositivo Android TV. Preme un botón para mantelo acendido."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Pronto se apagará o dispositivo. Tócao para mantelo acendido."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Tentaches desbloquear a tableta <xliff:g id="NUMBER">%d</xliff:g> veces de forma incorrecta. Quitarase o perfil de traballo e, por conseguinte, todos os datos do perfil."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Tentaches desbloquear o teléfono <xliff:g id="NUMBER">%d</xliff:g> veces de forma incorrecta. Quitarase o perfil de traballo e, por conseguinte, todos os datos do perfil."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Debuxaches o padrón de desbloqueo incorrectamente <xliff:g id="NUMBER_0">%1$d</xliff:g> veces. Se realizas <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos máis, terás que desbloquear a tableta a través dunha conta de correo electrónico.\n\n Téntao de novo en <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Debuxaches o padrón de desbloqueo incorrectamente <xliff:g id="NUMBER_0">%1$d</xliff:g> veces. Se realizas <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos máis, terás que desbloquear o teléfono a través dunha conta de correo electrónico.\n\n Téntao de novo en <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Aliña de novo o teléfono para cargalo máis rápido"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Aliña de novo o teléfono para cargalo sen fíos"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Pronto se apagará o dispositivo Android TV. Preme un botón para mantelo acendido."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Pronto se apagará o teléfono. Tócao para mantelo acendido."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Non hai ningunha tarxeta SIM na tableta."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Non hai ningunha tarxeta SIM no teléfono."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"Os códigos PIN non coinciden"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Tentaches desbloquear a tableta <xliff:g id="NUMBER_0">%1$d</xliff:g> veces de forma incorrecta. Se realizas <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos máis, restablecerase a tableta e, por conseguinte, eliminaranse todos os seus datos."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Tentaches desbloquear o teléfono <xliff:g id="NUMBER_0">%1$d</xliff:g> veces de forma incorrecta. Se realizas <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos máis, restablecerase o teléfono e, por conseguinte, eliminaranse todos os seus datos."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Tentaches desbloquear a tableta <xliff:g id="NUMBER">%d</xliff:g> veces de forma incorrecta. Restablecerase a tableta e, por conseguinte, eliminaranse todos os seus datos."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Tentaches desbloquear o teléfono <xliff:g id="NUMBER">%d</xliff:g> veces de forma incorrecta. Restablecerase o teléfono e, por conseguinte, eliminaranse todos os seus datos."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Tentaches desbloquear a tableta <xliff:g id="NUMBER_0">%1$d</xliff:g> veces de forma incorrecta. Se realizas <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos máis, quitarase este usuario e, por conseguinte, todos os seus datos."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Tentaches desbloquear o teléfono <xliff:g id="NUMBER_0">%1$d</xliff:g> veces de forma incorrecta. Se realizas <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos máis, quitarase este usuario e, por conseguinte, todos os seus datos."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Tentaches desbloquear a tableta <xliff:g id="NUMBER">%d</xliff:g> veces de forma incorrecta. Quitarase este usuario e, por conseguinte, todos os seus datos."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Tentaches desbloquear o teléfono <xliff:g id="NUMBER">%d</xliff:g> veces de forma incorrecta. Quitarase este usuario e, por conseguinte, todos os seus datos."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Tentaches desbloquear a tableta <xliff:g id="NUMBER_0">%1$d</xliff:g> veces de forma incorrecta. Se realizas <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos máis, quitarase o perfil de traballo e, por conseguinte, todos os datos do perfil."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Tentaches desbloquear o teléfono <xliff:g id="NUMBER_0">%1$d</xliff:g> veces de forma incorrecta. Se realizas <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos máis, quitarase o perfil de traballo e, por conseguinte, todos os seus datos."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Tentaches desbloquear a tableta <xliff:g id="NUMBER">%d</xliff:g> veces de forma incorrecta. Quitarase o perfil de traballo e, por conseguinte, todos os seus datos."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Tentaches desbloquear o teléfono <xliff:g id="NUMBER">%d</xliff:g> veces de forma incorrecta. Quitarase o perfil de traballo e, por conseguinte, todos os seus datos."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Debuxaches o padrón de desbloqueo <xliff:g id="NUMBER_0">%1$d</xliff:g> veces de forma incorrecta. Se realizas <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos máis, terás que desbloquear a tableta a través dunha conta de correo electrónico.\n\n Téntao de novo en <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Debuxaches o padrón de desbloqueo <xliff:g id="NUMBER_0">%1$d</xliff:g> veces de forma incorrecta. Se realizas <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos máis, terás que desbloquear o teléfono a través dunha conta de correo electrónico.\n\n Téntao de novo en <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-gu/strings.xml b/packages/SystemUI/res-product/values-gu/strings.xml
index 1a9228ed0e79..58b3ed9aebe8 100644
--- a/packages/SystemUI/res-product/values-gu/strings.xml
+++ b/packages/SystemUI/res-product/values-gu/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,46 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"ટૅબ્લેટમાં સિમ કાર્ડ નથી."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"ફોનમાં સિમ કાર્ડ નથી."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"પિન કોડ મેળ ખાતા નથી"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"તમે ટૅબ્લેટને <xliff:g id="NUMBER_0">%1$d</xliff:g> વખત ખોટી રીતે અનલૉક કરવાનો પ્રયાસ કર્યો છે. વધુ <xliff:g id="NUMBER_1">%2$d</xliff:g> અસફળ પ્રયાસો પછી, આ ટૅબ્લેટ ફરીથી સેટ કરવામાં આવશે, જે તેનો તમામ ડેટા કાઢી નાખશે."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"તમે ફોનને <xliff:g id="NUMBER_0">%1$d</xliff:g> વખત ખોટી રીતે અનલૉક કરવાનો પ્રયાસ કર્યો છે. વધુ <xliff:g id="NUMBER_1">%2$d</xliff:g> અસફળ પ્રયાસો પછી, આ ફોન ફરીથી સેટ કરવામાં આવશે, જે તેનો તમામ ડેટા કાઢી નાખશે."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"તમે ટૅબ્લેટને <xliff:g id="NUMBER">%d</xliff:g> વખત ખોટી રીતે અનલૉક કરવાનો પ્રયાસ કર્યો છે. આ ટૅબ્લેટ ફરીથી સેટ થશે, જે તેનો તમામ ડેટા કાઢી નાખશે."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"તમે ફોનને <xliff:g id="NUMBER">%d</xliff:g> વખત ખોટી રીતે અનલૉક કરવાનો પ્રયાસ કર્યો છે. આ ફોન ફરીથી સેટ કરાશે, જે તેનો તમામ ડેટા કાઢી નાખશે."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"તમે ટૅબ્લેટને <xliff:g id="NUMBER_0">%1$d</xliff:g> વખત ખોટી રીતે અનલૉક કરવાનો પ્રયાસ કર્યો છે. <xliff:g id="NUMBER_1">%2$d</xliff:g> વધુ અસફળ પ્રયાસો પછી, આ વપરાશકર્તાને દૂર કરવામાં આવશે, જે તમામ વપરાશકર્તા ડેટાને કાઢી નાખશે."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"તમે ફોનને <xliff:g id="NUMBER_0">%1$d</xliff:g> વખત ખોટી રીતે અનલૉક કરવાનો પ્રયાસ કર્યો છે. વધુ <xliff:g id="NUMBER_1">%2$d</xliff:g> અસફળ પ્રયાસો પછી, આ વપરાશકર્તાને દૂર કરવામાં આવશે, જે તમામ વપરાશકર્તા ડેટા કાઢી નાખશે."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for notification_bubble_title (8330481035191903164) -->
- <skip/>
- <!-- no translation found for notification_channel_summary_bubble (7235935211580860537) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Android ટીવી ડિવાઇસ ટૂંક સમયમાં બંધ થશે; તેને ચાલુ રાખવા માટે બટન દબાવો."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"ડિવાઇસ ટૂંક સમયમાં બંધ થશે; તેને ચાલુ રાખવા માટે દબાવો."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"તમે ટૅબ્લેટને <xliff:g id="NUMBER">%d</xliff:g> વખત ખોટી રીતે અનલૉક કરવાનો પ્રયાસ કર્યો છે. આ કાર્યાલયની પ્રોફાઇલ દૂર કરવામાં આવશે, જે તમામ પ્રોફાઇલ ડેટાને કાઢી નાખશે."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"તમે ફોનને <xliff:g id="NUMBER">%d</xliff:g> વખત ખોટી રીતે અનલૉક કરવાનો પ્રયાસ કર્યો છે. આ કાર્યાલયની પ્રોફાઇલ દૂર કરવામાં આવશે, જે તમામ પ્રોફાઇલ ડેટાને કાઢી નાખશે."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"તમે તમારી અનલૉક પૅટર્ન <xliff:g id="NUMBER_0">%1$d</xliff:g> વખત ખોટી રીતે દોરી છે. વધુ <xliff:g id="NUMBER_1">%2$d</xliff:g> અસફળ પ્રયાસો પછી, તમને એક ઇમેઇલ એકાઉન્ટનો ઉપયોગ કરીને તમારા ટૅબ્લેટને અનલૉક કરવાનું કહેવામાં આવશે.\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> સેકન્ડમાં ફરી પ્રયાસ કરો."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"તમે તમારી અનલૉક પૅટર્ન <xliff:g id="NUMBER_0">%1$d</xliff:g> વખત ખોટી રીતે દોરી છે. વધુ <xliff:g id="NUMBER_1">%2$d</xliff:g> અસફળ પ્રયાસો પછી, તમને ઇમેઇલ એકાઉન્ટનો ઉપયોગ કરીને ફોન અનલૉક કરવાનું કહેવામાં આવશે.\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> સેકન્ડમાં ફરીથી પ્રયાસ કરો."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"ફોનને ઝડપથી ચાર્જ કરવા માટે ફરીથી ગોઠવો"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"ફોનને વાયરલેસ રીતે ચાર્જ કરવા માટે ફરીથી ગોઠવો"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Android TV ડિવાઇસ ટૂંક સમયમાં બંધ થશે; તેને ચાલુ રાખવા માટે બટન દબાવો."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"ડિવાઇસ ટૂંક સમયમાં બંધ થશે; તેને ચાલુ રાખવા માટે દબાવો."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"ટૅબ્લેટમાં સિમ કાર્ડ નથી."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"ફોનમાં સિમ કાર્ડ નથી."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"પિન કોડ મેળ ખાતા નથી"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"તમે ટૅબ્લેટને <xliff:g id="NUMBER_0">%1$d</xliff:g> વખત ખોટી રીતે અનલૉક કરવાનો પ્રયાસ કર્યો છે. વધુ <xliff:g id="NUMBER_1">%2$d</xliff:g> અસફળ પ્રયાસો પછી, આ ટૅબ્લેટ રીસેટ કરવામાં આવશે, જે તેનો તમામ ડેટા ડિલીટ કરી દેશે."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"તમે ફોનને <xliff:g id="NUMBER_0">%1$d</xliff:g> વખત ખોટી રીતે અનલૉક કરવાનો પ્રયાસ કર્યો છે. વધુ <xliff:g id="NUMBER_1">%2$d</xliff:g> અસફળ પ્રયાસો પછી, આ ફોન રીસેટ કરવામાં આવશે, જે તેનો તમામ ડેટા ડિલીટ કરી દેશે."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"તમે ટૅબ્લેટને <xliff:g id="NUMBER">%d</xliff:g> વખત ખોટી રીતે અનલૉક કરવાનો પ્રયાસ કર્યો છે. આ ટૅબ્લેટ રીસેટ કરવામાં આવશે, જે તેનો તમામ ડેટા ડિલીટ કરી દેશે."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"તમે ફોનને <xliff:g id="NUMBER">%d</xliff:g> વખત ખોટી રીતે અનલૉક કરવાનો પ્રયાસ કર્યો છે. આ ફોન રીસેટ કરવામાં આવશે, જે તેનો તમામ ડેટા ડિલીટ કરી દેશે."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"તમે ટૅબ્લેટને <xliff:g id="NUMBER_0">%1$d</xliff:g> વખત ખોટી રીતે અનલૉક કરવાનો પ્રયાસ કર્યો છે. <xliff:g id="NUMBER_1">%2$d</xliff:g> વધુ અસફળ પ્રયાસો પછી, આ વપરાશકર્તાને કાઢી નાખવામાં આવશે, જે તમામ વપરાશકર્તા ડેટાને ડિલીટ કરી દેશે."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"તમે ફોનને <xliff:g id="NUMBER_0">%1$d</xliff:g> વખત ખોટી રીતે અનલૉક કરવાનો પ્રયાસ કર્યો છે. વધુ <xliff:g id="NUMBER_1">%2$d</xliff:g> અસફળ પ્રયાસો પછી, આ વપરાશકર્તા કાઢી નાખવામાં આવશે, જે તમામ વપરાશકર્તા ડેટા ડિલીટ કરી દેશે."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"તમે ટૅબ્લેટને <xliff:g id="NUMBER">%d</xliff:g> વખત ખોટી રીતે અનલૉક કરવાનો પ્રયાસ કર્યો છે. આ વપરાશકર્તાને કાઢી નાખવામાં આવશે, જે તમામ વપરાશકર્તા ડેટાને ડિલીટ કરી દેશે."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"તમે ફોનને <xliff:g id="NUMBER">%d</xliff:g> વખત ખોટી રીતે અનલૉક કરવાનો પ્રયાસ કર્યો છે. આ વપરાશકર્તાને કાઢી નાખવામાં આવશે, જે તમામ વપરાશકર્તા ડેટાને ડિલીટ કરી દેશે."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"તમે ટૅબ્લેટને <xliff:g id="NUMBER_0">%1$d</xliff:g> વખત ખોટી રીતે અનલૉક કરવાનો પ્રયાસ કર્યો છે. વધુ <xliff:g id="NUMBER_1">%2$d</xliff:g> અસફળ પ્રયાસ પછી, કાર્યાલયની પ્રોફાઇલ કાઢી નાખવામાં આવશે, જે તમામ પ્રોફાઇલ ડેટાને ડિલીટ કરી દેશે."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"તમે ફોનને <xliff:g id="NUMBER_0">%1$d</xliff:g> વખત ખોટી રીતે અનલૉક કરવાનો પ્રયાસ કર્યો છે. વધુ <xliff:g id="NUMBER_1">%2$d</xliff:g> અસફળ પ્રયાસ પછી, કાર્યાલયની પ્રોફાઇલ કાઢી નાખવામાં આવશે, જે તમામ પ્રોફાઇલ ડેટાને ડિલીટ કરી દેશે."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"તમે ટૅબ્લેટને <xliff:g id="NUMBER">%d</xliff:g> વખત ખોટી રીતે અનલૉક કરવાનો પ્રયાસ કર્યો છે. આ કાર્યાલયની પ્રોફાઇલ કાઢી નાખવામાં આવશે, જે તમામ વપરાશકર્તા ડેટાને ડિલીટ કરી દેશે."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"તમે ફોનને <xliff:g id="NUMBER">%d</xliff:g> વખત ખોટી રીતે અનલૉક કરવાનો પ્રયાસ કર્યો છે. આ કાર્યાલયની પ્રોફાઇલ કાઢી નાખવામાં આવશે, જે તમામ પ્રોફાઇલ ડેટાને ડિલીટ કરી દેશે."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"તમે તમારી અનલૉક પૅટર્ન <xliff:g id="NUMBER_0">%1$d</xliff:g> વખત ખોટી રીતે દોરી છે. વધુ <xliff:g id="NUMBER_1">%2$d</xliff:g> અસફળ પ્રયાસો પછી, તમને એક ઇમેઇલ એકાઉન્ટનો ઉપયોગ કરીને તમારા ટૅબ્લેટને અનલૉક કરવાનું કહેવામાં આવશે.\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> સેકન્ડમાં ફરી પ્રયાસ કરો."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"તમે તમારી અનલૉક પૅટર્ન <xliff:g id="NUMBER_0">%1$d</xliff:g> વખત ખોટી રીતે દોરી છે. વધુ <xliff:g id="NUMBER_1">%2$d</xliff:g> અસફળ પ્રયાસો પછી, તમને ઇમેઇલ એકાઉન્ટનો ઉપયોગ કરીને તમારા ફોનને અનલૉક કરવાનું કહેવામાં આવશે.\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> સેકન્ડમાં ફરીથી પ્રયાસ કરો."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-hi/strings.xml b/packages/SystemUI/res-product/values-hi/strings.xml
index 7babf18dc0f9..188a4104cab4 100644
--- a/packages/SystemUI/res-product/values-hi/strings.xml
+++ b/packages/SystemUI/res-product/values-hi/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"टैबलेट में कोई SIM कार्ड नहीं है."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"फ़ोन में कोई SIM कार्ड नहीं है."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"पिन कोड का मिलान नहीं हो रहा है"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"आपने टैबलेट को अनलॉक करने के लिए <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से कोशिश की है. <xliff:g id="NUMBER_1">%2$d</xliff:g> और असफल कोशिशों के बाद, इस टैबलेट को रीसेट कर दिया जाएगा, जिससे इसका सारा डेटा हट जाएगा."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"आपने फ़ोन को अनलॉक करने के लिए <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से कोशिश की है. <xliff:g id="NUMBER_1">%2$d</xliff:g> और असफल कोशिशों के बाद, इस फ़ोन को रीसेट कर दिया जाएगा, जिससे इसका सारा डेटा हट जाएगा."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"आपने टैबलेट को अनलॉक करने के लिए <xliff:g id="NUMBER">%d</xliff:g> बार गलत तरीके से कोशिश की है. इस टैबलेट को रीसेट कर दिया जाएगा, जिससे इसका सारा डेटा हट जाएगा."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"आपने फ़ोन को अनलॉक करने के लिए <xliff:g id="NUMBER">%d</xliff:g> बार गलत तरीके से कोशिश की है. इस फ़ोन को रीसेट कर दिया जाएगा, जिससे इसका सारा डेटा हट जाएगा."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"आपने टैबलेट का लॉक खोलने के लिए <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से कोशिश की है. <xliff:g id="NUMBER_1">%2$d</xliff:g> बार और गलत कोशिश करने पर, इस उपयोगकर्ता को निकाल दिया जाएगा, जिससे सभी उपयोगकर्ता डेटा मिट जाएगा."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"आपने फ़ोन का लॉक खोलने के लिए <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से कोशिश की है. <xliff:g id="NUMBER_1">%2$d</xliff:g> बार और गलत कोशिश करने पर, इस उपयोगकर्ता को निकाल दिया जाएगा, जिससे सभी उपयोगकर्ता डेटा मिट जाएगा."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Android TV डिवाइस जल्द ही बंद हो जाएगा. इसे चालू रखने के लिए किसी बटन को दबाएं."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"डिवाइस जल्द ही बंद हो जाएगा. इसे चालू रखने के लिए स्क्रीन पर टैप करें या किसी बटन को दबाएं."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"आपने टैबलेट को अनलॉक करने के लिए <xliff:g id="NUMBER">%d</xliff:g> बार गलत तरीके से कोशिश की है. वर्क प्रोफ़ाइल को निकाल दिया जाएगा, जिससे सभी प्रोफ़ाइल डेटा हट जाएगा."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"आपने फ़ोन को अनलॉक करने के लिए <xliff:g id="NUMBER">%d</xliff:g> बार गलत तरीके से कोशिश की है. वर्क प्रोफ़ाइल को निकाल दिया जाएगा, जिससे सभी प्रोफ़ाइल डेटा हट जाएगा."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"आपने अपने लॉक खोलने के पैटर्न को <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से ड्रॉ किया है. अगर आपने <xliff:g id="NUMBER_1">%2$d</xliff:g> बार और गलत ड्रॉ किया, तो आपसे अपने टैबलेट को किसी ईमेल खाते का इस्तेमाल करके अनलॉक करने के लिए कहा जाएगा.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकंड बाद फिर से कोशिश करें."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"आपने अपने लॉक खोलने के पैटर्न को <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से ड्रॉ किया है. अगर आपने <xliff:g id="NUMBER_1">%2$d</xliff:g> बार और गलत ड्रॉ किया, तो आपसे अपने फ़ोन को किसी ईमेल खाते का इस्तेमाल करके अनलॉक करने के लिए कहा जाएगा.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकंड बाद फिर से कोशिश करें."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"फ़ोन को फ़ास्ट चार्ज करने के लिए डॉक पर ठीक तरह से रखें"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"फ़ोन को वायरलेस चार्जिंग के लिए डॉक पर ठीक तरह से रखें"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Android TV डिवाइस जल्द ही बंद हो जाएगा. इसे चालू रखने के लिए किसी बटन को दबाएं."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"डिवाइस जल्द ही बंद हो जाएगा. इसे चालू रखने के लिए किसी बटन को दबाएं."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"टैबलेट में कोई SIM कार्ड नहीं है."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"फ़ोन में कोई SIM कार्ड नहीं है."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"पिन कोड मेल नहीं खा रहा"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"आप टैबलेट को अनलॉक करने के लिए <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत पासवर्ड डाल चुके हैं. इसलिए, <xliff:g id="NUMBER_1">%2$d</xliff:g> और गलत पासवर्ड डालने के बाद, इस टैबलेट को रीसेट कर दिया जाएगा. ऐसा होने पर, इसका सारा डेटा मिट जाएगा."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"आप फ़ोन को अनलॉक करने के लिए <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत पासवर्ड डाल चुके हैं. इसलिए, <xliff:g id="NUMBER_1">%2$d</xliff:g> और गलत पासवर्ड डालने के बाद, इस फ़ोन को रीसेट कर दिया जाएगा. ऐसा होने पर, इसका सारा डेटा मिट जाएगा."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"आप टैबलेट को अनलॉक करने के लिए <xliff:g id="NUMBER">%d</xliff:g> बार गलत पासवर्ड डाल चुके हैं. इस टैबलेट को रीसेट किया जाएगा जिससे इसका सारा डेटा मिट जाएगा."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"आप फ़ोन को अनलॉक करने के लिए <xliff:g id="NUMBER">%d</xliff:g> बार गलत पासवर्ड डाल चुके हैं. इस फ़ोन को रीसेट किया जाएगा जिससे इसका सारा डेटा मिट जाएगा."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"आप टैबलेट को अनलॉक करने के लिए <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत पासवर्ड डाल चुके हैं. इसलिए, <xliff:g id="NUMBER_1">%2$d</xliff:g> और गलत पासवर्ड डालने के बाद, इस उपयोगकर्ता को हटा दिया जाएगा. ऐसा होने पर, उपयोगकर्ता का सारा डेटा मिट जाएगा."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"आप फ़ोन को अनलॉक करने के लिए <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत पासवर्ड डाल चुके हैं. इसलिए, <xliff:g id="NUMBER_1">%2$d</xliff:g> और गलत पासवर्ड डालने के बाद, इस उपयोगकर्ता को हटा दिया जाएगा. ऐसा होने पर, उपयोगकर्ता का सारा डेटा मिट जाएगा."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"आप टैबलेट को अनलॉक करने के लिए <xliff:g id="NUMBER">%d</xliff:g> बार गलत पासवर्ड डाल चुके हैं. इस उपयोगकर्ता को हटा दिया जाएगा जिससे उपयोगकर्ता का सारा डेटा मिट जाएगा."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"आप फ़ोन को अनलॉक करने के लिए <xliff:g id="NUMBER">%d</xliff:g> बार गलत पासवर्ड डाल चुके हैं. इस उपयोगकर्ता को हटा दिया जाएगा जिससे उपयोगकर्ता का सारा डेटा मिट जाएगा."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"आप टैबलेट को अनलॉक करने के लिए <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत पासवर्ड डाल चुके हैं. इसलिए, <xliff:g id="NUMBER_1">%2$d</xliff:g> और गलत पासवर्ड डालने के बाद, वर्क प्रोफ़ाइल को हटा दिया जाएगा. ऐसा होने पर, प्रोफ़ाइल का सारा डेटा मिट जाएगा."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"आप फ़ोन को अनलॉक करने के लिए <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत पासवर्ड डाल चुके हैं. इसलिए, <xliff:g id="NUMBER_1">%2$d</xliff:g> और गलत पासवर्ड डालने के बाद, वर्क प्रोफ़ाइल को हटा दिया जाएगा. ऐसा होने पर, प्रोफ़ाइल का सारा डेटा मिट जाएगा."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"आप टैबलेट को अनलॉक करने के लिए <xliff:g id="NUMBER">%d</xliff:g> बार गलत पासवर्ड डाल चुके हैं. इस वर्क प्रोफ़ाइल को हटा दिया जाएगा जिससे उपयोगकर्ता की प्रोफ़ाइल का सारा डेटा मिट जाएगा."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"आप फ़ोन को अनलॉक करने के लिए <xliff:g id="NUMBER">%d</xliff:g> बार गलत पासवर्ड डाल चुके हैं. इसकी वजह से वर्क प्रोफ़ाइल को हटा दिया जाएगा जिससे उपयोगकर्ता की प्रोफ़ाइल का सारा डेटा मिट जाएगा."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"आपने लॉक खोलने के पैटर्न को <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से बनाया है. इसलिए, <xliff:g id="NUMBER_1">%2$d</xliff:g> और गलत पैटर्न बनाने के बाद, टैबलेट को अनलॉक करने के लिए आपसे ईमेल खाते का इस्तेमाल करने को कहा जाएगा.\n\n अनलॉक करने के लिए <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकंड में फिर से कोशिश करें."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"आपने लॉक खोलने के पैटर्न को <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से बनाया है. इसलिए, <xliff:g id="NUMBER_1">%2$d</xliff:g> और गलत पैटर्न बनाने के बाद, आपसे फ़ोन को अनलॉक करने के लिए ईमेल खाते का इस्तेमाल करने को कहा जाएगा.\n\n अनलॉक करने के लिए <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकंड में फिर से कोशिश करें."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-hr/strings.xml b/packages/SystemUI/res-product/values-hr/strings.xml
index 690f58a28acd..549f38c599ae 100644
--- a/packages/SystemUI/res-product/values-hr/strings.xml
+++ b/packages/SystemUI/res-product/values-hr/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"U tabletu nema SIM kartice."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"U telefonu nema SIM kartice."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"PIN kodovi nisu jednaki"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Neuspješno ste pokušali otključati tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> put/a. Nakon još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja tablet će se vratiti na zadano, a time će se izbrisati i svi podaci na njemu."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Neuspješno ste pokušali otključati telefon <xliff:g id="NUMBER_0">%1$d</xliff:g> put/a. Nakon još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja telefon će se vratiti na zadano, a time će se izbrisati i svi podaci na njemu."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Neuspješno ste pokušali otključati tablet <xliff:g id="NUMBER">%d</xliff:g> put/a. Tablet će se vratiti na zadano, a time će se izbrisati i svi podaci na njemu."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Neuspješno ste pokušali otključati telefon <xliff:g id="NUMBER">%d</xliff:g> put/a. Telefon će se vratiti na zadano, a time će se izbrisati i svi podaci na njemu."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Neuspješno ste pokušali otključati tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> put/a. Nakon još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja taj će se korisnik ukloniti, a time će se izbrisati i svi njegovi podaci."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Neuspješno ste pokušali otključati telefon <xliff:g id="NUMBER_0">%1$d</xliff:g> put/a. Nakon još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja taj će se korisnik ukloniti, a time će se izbrisati i svi njegovi podaci."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Uređaj Android TV uskoro će se isključiti. Pritisnite gumb da bi ostao uključen."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Uređaj će se uskoro isključiti. Pritisnite da bi ostao uključen."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Neuspješno ste pokušali otključati tablet <xliff:g id="NUMBER">%d</xliff:g> put/a. Radni će se profil ukloniti, a time će se izbrisati i svi njegovi podaci."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Neuspješno ste pokušali otključati telefon <xliff:g id="NUMBER">%d</xliff:g> put/a. Radni će se profil ukloniti, a time će se izbrisati i svi njegovi podaci."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Netočno ste iscrtali uzorak za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> put/a. Nakon još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja morat ćete otključati tablet pomoću računa e-pošte.\n\n Pokušajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Netočno ste iscrtali uzorak za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> put/a. Nakon još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja morat ćete otključati telefon pomoću računa e-pošte.\n\n Pokušajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Ponovo namjestite telefon da bi se brže punio"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Ponovo namjestite telefon da bi se punio bežično"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Uređaj Android TV uskoro će se isključiti. Pritisnite gumb da bi ostao uključen."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Uređaj će se uskoro isključiti. Pritisnite da bi ostao uključen."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"U tabletu nema SIM kartice."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"U telefonu nema SIM kartice."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"PIN kodovi nisu jednaki"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Neuspješno ste pokušali otključati tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> put/a. Nakon još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja tablet će se vratiti na zadano, a time će se izbrisati i svi podaci na njemu."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Neuspješno ste pokušali otključati telefon <xliff:g id="NUMBER_0">%1$d</xliff:g> put/a. Nakon još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja telefon će se vratiti na zadano, a time će se izbrisati i svi podaci na njemu."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Neuspješno ste pokušali otključati tablet <xliff:g id="NUMBER">%d</xliff:g> put/a. Tablet će se vratiti na zadano, a time će se izbrisati i svi podaci na njemu."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Neuspješno ste pokušali otključati telefon <xliff:g id="NUMBER">%d</xliff:g> put/a. Telefon će se vratiti na zadano, a time će se izbrisati i svi podaci na njemu."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Neuspješno ste pokušali otključati tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> put/a. Nakon još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja taj će se korisnik ukloniti, a time će se izbrisati i svi njegovi podaci."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Neuspješno ste pokušali otključati telefon <xliff:g id="NUMBER_0">%1$d</xliff:g> put/a. Nakon još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja taj će se korisnik ukloniti, a time će se izbrisati i svi njegovi podaci."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Neuspješno ste pokušali otključati tablet <xliff:g id="NUMBER">%d</xliff:g> put/a. Taj će se korisnik ukloniti, a time će se izbrisati i svi njegovi podaci."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Neuspješno ste pokušali otključati telefon <xliff:g id="NUMBER">%d</xliff:g> put/a. Taj će se korisnik ukloniti, a time će se izbrisati i svi njegovi podaci."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Neuspješno ste pokušali otključati tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> put/a. Nakon još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja radni će se profil ukloniti, a time će se izbrisati i svi njegovi podaci."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Neuspješno ste pokušali otključati telefon <xliff:g id="NUMBER_0">%1$d</xliff:g> put/a. Nakon još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja radni će se profil ukloniti, a time će se izbrisati i svi njegovi podaci."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Neuspješno ste pokušali otključati tablet <xliff:g id="NUMBER">%d</xliff:g> put/a. Radni će se profil ukloniti, a time će se izbrisati i svi njegovi podaci."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Neuspješno ste pokušali otključati telefon <xliff:g id="NUMBER">%d</xliff:g> put/a. Radni će se profil ukloniti, a time će se izbrisati i svi njegovi podaci."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Netočno ste iscrtali uzorak za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> put/a. Nakon još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja morat ćete otključati tablet pomoću računa e-pošte.\n\n Pokušajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Netočno ste iscrtali uzorak za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> put/a. Nakon još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja morat ćete otključati telefon pomoću računa e-pošte.\n\n Pokušajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-hu/strings.xml b/packages/SystemUI/res-product/values-hu/strings.xml
index 26160e4158e7..00ba65113e80 100644
--- a/packages/SystemUI/res-product/values-hu/strings.xml
+++ b/packages/SystemUI/res-product/values-hu/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"Nincs SIM-kártya a táblagépben."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"Nincs SIM-kártya a telefonban."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"A PIN-kódok nem egyeznek"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"<xliff:g id="NUMBER_0">%1$d</xliff:g> alkalommal próbálkozott sikertelenül a táblagép zárolásának feloldásával. További <xliff:g id="NUMBER_1">%2$d</xliff:g> sikertelen kísérlet után a rendszer visszaállítja a táblagépet, és ezzel az összes adat törlődik róla."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"<xliff:g id="NUMBER_0">%1$d</xliff:g> alkalommal próbálkozott sikertelenül a telefon zárolásának feloldásával. További <xliff:g id="NUMBER_1">%2$d</xliff:g> sikertelen kísérlet után a rendszer visszaállítja a telefont, és ezzel az összes adat törlődik róla."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"<xliff:g id="NUMBER">%d</xliff:g> alkalommal próbálkozott sikertelenül a táblagép zárolásának feloldásával. A rendszer visszaállítja a táblagépet, és ezzel a rajta lévő összes adat törlődik."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"<xliff:g id="NUMBER">%d</xliff:g> alkalommal próbálkozott sikertelenül a telefon zárolásának feloldásával. A rendszer visszaállítja a telefont, és ezzel a rajta lévő összes adat törlődik."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"<xliff:g id="NUMBER_0">%1$d</xliff:g> alkalommal próbálkozott sikertelenül a táblagép zárolásának feloldásával. További <xliff:g id="NUMBER_1">%2$d</xliff:g> sikertelen kísérlet után a rendszer eltávolítja a felhasználót, és ezzel a felhasználó összes adata törlődik majd."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"<xliff:g id="NUMBER_0">%1$d</xliff:g> alkalommal próbálkozott sikertelenül a telefon zárolásának feloldásával. További <xliff:g id="NUMBER_1">%2$d</xliff:g> sikertelen kísérlet után a rendszer eltávolítja a felhasználót, és ezzel a felhasználó összes adata törlődik majd."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Az Android TV eszköz hamarosan kikapcsol. Nyomja meg valamelyik gombot, hogy bekapcsolva tarthassa."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Az eszköz hamarosan kikapcsol. Nyomja meg, hogy bekapcsolva tarthassa."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"<xliff:g id="NUMBER">%d</xliff:g> alkalommal próbálkozott sikertelenül a táblagép zárolásának feloldásával. A rendszer eltávolítja a munkaprofilt, és ezzel a profil összes adata törlődik."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"<xliff:g id="NUMBER">%d</xliff:g> alkalommal próbálkozott sikertelenül a telefon zárolásának feloldásával. A rendszer eltávolítja a munkaprofilt, és ezzel a profil összes adata törlődik."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"<xliff:g id="NUMBER_0">%1$d</xliff:g> alkalommal helytelenül rajzolta le a feloldási mintát. További <xliff:g id="NUMBER_1">%2$d</xliff:g> sikertelen kísérlet után e-mail-fiók használatával kell feloldania táblagépét.\n\nPróbálja újra <xliff:g id="NUMBER_2">%3$d</xliff:g> másodperc múlva."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"<xliff:g id="NUMBER_0">%1$d</xliff:g> alkalommal helytelenül rajzolta le a feloldási mintát. További <xliff:g id="NUMBER_1">%2$d</xliff:g> sikertelen kísérlet után e-mail-fiók használatával kell feloldania telefonját.\n\nPróbálja újra <xliff:g id="NUMBER_2">%3$d</xliff:g> másodperc múlva."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Igazítsa a helyére a telefont a gyorsabb töltéshez"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Igazítsa a helyére a telefont a vezeték nélküli töltéshez"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Az Android TV eszköz hamarosan kikapcsol. Nyomja meg valamelyik gombot, hogy bekapcsolva tarthassa."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Az eszköz hamarosan kikapcsol. Nyomja meg, hogy bekapcsolva tarthassa."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Nincs SIM-kártya a táblagépben."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Nincs SIM-kártya a telefonban."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"A PIN-kódok nem egyeznek"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"<xliff:g id="NUMBER_0">%1$d</xliff:g> alkalommal próbálkozott sikertelenül a táblagép zárolásának feloldásával. További <xliff:g id="NUMBER_1">%2$d</xliff:g> sikertelen kísérlet után a rendszer visszaállítja a táblagépet, és ezzel az összes adat törlődik róla."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"<xliff:g id="NUMBER_0">%1$d</xliff:g> alkalommal próbálkozott sikertelenül a telefon zárolásának feloldásával. További <xliff:g id="NUMBER_1">%2$d</xliff:g> sikertelen kísérlet után a rendszer visszaállítja a telefont, és ezzel az összes adat törlődik róla."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"<xliff:g id="NUMBER">%d</xliff:g> alkalommal próbálkozott sikertelenül a táblagép zárolásának feloldásával. A rendszer visszaállítja a táblagépet, és ezzel a rajta lévő összes adat törlődik."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"<xliff:g id="NUMBER">%d</xliff:g> alkalommal próbálkozott sikertelenül a telefon zárolásának feloldásával. A rendszer visszaállítja a telefont, és ezzel a rajta lévő összes adat törlődik."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"<xliff:g id="NUMBER_0">%1$d</xliff:g> alkalommal próbálkozott sikertelenül a táblagép zárolásának feloldásával. További <xliff:g id="NUMBER_1">%2$d</xliff:g> sikertelen kísérlet után a rendszer eltávolítja a felhasználót, és ezzel a felhasználó összes adata törlődik majd."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"<xliff:g id="NUMBER_0">%1$d</xliff:g> alkalommal próbálkozott sikertelenül a telefon zárolásának feloldásával. További <xliff:g id="NUMBER_1">%2$d</xliff:g> sikertelen kísérlet után a rendszer eltávolítja a felhasználót, és ezzel a felhasználó összes adata törlődik majd."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"<xliff:g id="NUMBER">%d</xliff:g> alkalommal próbálkozott sikertelenül a táblagép zárolásának feloldásával. A rendszer eltávolítja a felhasználót, és ezzel a felhasználó összes adata törlődik."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"<xliff:g id="NUMBER">%d</xliff:g> alkalommal próbálkozott sikertelenül a telefon zárolásának feloldásával. A rendszer eltávolítja a felhasználót, és ezzel a felhasználó összes adata törlődik."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"<xliff:g id="NUMBER_0">%1$d</xliff:g> alkalommal próbálkozott sikertelenül a táblagép zárolásának feloldásával. További <xliff:g id="NUMBER_1">%2$d</xliff:g> sikertelen kísérlet után a rendszer eltávolítja a munkaprofilt, és ezzel a profil összes adata törlődik majd."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"<xliff:g id="NUMBER_0">%1$d</xliff:g> alkalommal próbálkozott sikertelenül a telefon zárolásának feloldásával. További <xliff:g id="NUMBER_1">%2$d</xliff:g> sikertelen kísérlet után a rendszer eltávolítja a munkaprofilt, és ezzel a profil összes adata törlődik majd."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"<xliff:g id="NUMBER">%d</xliff:g> alkalommal próbálkozott sikertelenül a táblagép zárolásának feloldásával. A rendszer eltávolítja a munkaprofilt, és ezzel a profil összes adata törlődik."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"<xliff:g id="NUMBER">%d</xliff:g> alkalommal próbálkozott sikertelenül a telefon zárolásának feloldásával. A rendszer eltávolítja a munkaprofilt, és ezzel a profil összes adata törlődik."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"<xliff:g id="NUMBER_0">%1$d</xliff:g> alkalommal helytelenül rajzolta le a feloldási mintát. További <xliff:g id="NUMBER_1">%2$d</xliff:g> sikertelen kísérlet után e-mail-fiók használatával kell feloldania táblagépét.\n\nPróbálja újra <xliff:g id="NUMBER_2">%3$d</xliff:g> másodperc múlva."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"<xliff:g id="NUMBER_0">%1$d</xliff:g> alkalommal helytelenül rajzolta le a feloldási mintát. További <xliff:g id="NUMBER_1">%2$d</xliff:g> sikertelen kísérlet után e-mail-fiók használatával kell feloldania telefonját.\n\nPróbálja újra <xliff:g id="NUMBER_2">%3$d</xliff:g> másodperc múlva."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-hy/strings.xml b/packages/SystemUI/res-product/values-hy/strings.xml
index 008ac7efc89a..9f5fa601ce21 100644
--- a/packages/SystemUI/res-product/values-hy/strings.xml
+++ b/packages/SystemUI/res-product/values-hy/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"Պլանշետում SIM քարտ չկա:"</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"Հեռախոսում SIM քարտ չկա:"</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"PIN կոդերը չեն համընկնում"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Դուք կատարել եք պլանշետն ապակողպելու <xliff:g id="NUMBER_0">%1$d</xliff:g> անհաջող փորձ: Եվս <xliff:g id="NUMBER_1">%2$d</xliff:g> անհաջող փորձից հետո այս պլանշետը կվերակայվի և բոլոր տվյալները կջնջվեն:"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Դուք կատարել եք հեռախոսն ապակողպելու <xliff:g id="NUMBER_0">%1$d</xliff:g> անհաջող փորձ: Եվս <xliff:g id="NUMBER_1">%2$d</xliff:g> անհաջող փորձից հետո այս հեռախոսը կվերակայվի և բոլոր տվյալները կջնջվեն:"</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Դուք կատարել եք պլանշետն ապակողպելու <xliff:g id="NUMBER">%d</xliff:g> անհաջող փորձ: Այս պլանշետը կվերակայվի և բոլոր տվյալները կջնջվեն:"</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Դուք կատարել եք հեռախոսն ապակողպելու <xliff:g id="NUMBER">%d</xliff:g> անհաջող փորձ: Այս հեռախոսը կվերակայվի և բոլոր տվյալները կջնջվեն:"</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Դուք կատարել եք պլանշետն ապակողպելու <xliff:g id="NUMBER_0">%1$d</xliff:g> անհաջող փորձ: Եվս <xliff:g id="NUMBER_1">%2$d</xliff:g> անհաջող փորձից հետո այս օգտվողը կհեռացվի և օգտվողի բոլոր տվյալները կջնջվեն:"</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Դուք կատարել եք հեռախոսն ապակողպելու <xliff:g id="NUMBER_0">%1$d</xliff:g> անհաջող փորձ: Եվս <xliff:g id="NUMBER_1">%2$d</xliff:g> անհաջող փորձից հետո այս օգտվողը կհեռացվի և օգտվողի բոլոր տվյալները կջնջվեն:"</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Android TV սարքը շուտով կանջատվի: Սեղմեք որևէ կոճակ՝ միացրած թողնելու համար:"</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Սարքը շուտով կանջատվի: Սեղմեք՝ միացրած թողնելու համար:"</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Դուք կատարել եք պլանշետն ապակողպելու <xliff:g id="NUMBER">%d</xliff:g> անհաջող փորձ: Աշխատանքային պրոֆիլը կհեռացվի և պրոֆիլի բոլոր տվյալները կջնջվեն:"</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Դուք կատարել եք հեռախոսն ապակողպելու <xliff:g id="NUMBER">%d</xliff:g> անհաջող փորձ: Աշխատանքային պրոֆիլը կհեռացվի և պրոֆիլի բոլոր տվյալները կջնջվեն:"</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Դուք կատարել եք ապակողպման նախշը մուտքագրելու <xliff:g id="NUMBER_0">%1$d</xliff:g> անհաջող փորձ: Եվս <xliff:g id="NUMBER_1">%2$d</xliff:g> անհաջող փորձից հետո ձեզանից կպահանջվի ապակողպել պլանշետը էլփոստի հաշվի միջոցով։\n\n Խնդրում ենք փորձել կրկին <xliff:g id="NUMBER_2">%3$d</xliff:g> վայրկյանից:"</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Դուք կատարել եք ապակողպման նախշը մուտքագրելու <xliff:g id="NUMBER_0">%1$d</xliff:g> անհաջող փորձ: Եվս <xliff:g id="NUMBER_1">%2$d</xliff:g> անհաջող փորձից հետո ձեզանից կպահանջվի ապակողպել հեռախոսը էլփոստի հաշվի միջոցով։\n\n Խնդրում ենք փորձել կրկին <xliff:g id="NUMBER_2">%3$d</xliff:g> վայրկյանից:"</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Կարգավորեք հեռախոսը՝ ավելի արագ լիցքավորելու համար"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Կարգավորեք հեռախոսը` առանց լարի լիցքավորելու համար"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Android TV սարքը շուտով կանջատվի: Սեղմեք որևէ կոճակ՝ միացրած թողնելու համար:"</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Սարքը շուտով կանջատվի: Սեղմեք՝ միացրած թողնելու համար:"</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Պլանշետում SIM քարտ չկա:"</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Հեռախոսում SIM քարտ չկա:"</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"PIN կոդերը չեն համընկնում"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Դուք կատարել եք պլանշետն ապակողպելու <xliff:g id="NUMBER_0">%1$d</xliff:g> անհաջող փորձ: Եվս <xliff:g id="NUMBER_1">%2$d</xliff:g> անհաջող փորձից հետո այս պլանշետը կվերակայվի և բոլոր տվյալները կջնջվեն:"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Դուք կատարել եք հեռախոսն ապակողպելու <xliff:g id="NUMBER_0">%1$d</xliff:g> անհաջող փորձ: Եվս <xliff:g id="NUMBER_1">%2$d</xliff:g> անհաջող փորձից հետո այս հեռախոսի կարգավորումները կզրոյացվեն, և բոլոր տվյալները կջնջվեն:"</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Դուք կատարել եք պլանշետն ապակողպելու <xliff:g id="NUMBER">%d</xliff:g> անհաջող փորձ: Պլանշետի կարգավորումները կզրոյացվեն, և բոլոր տվյալները կջնջվեն:"</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Դուք կատարել եք հեռախոսն ապակողպելու <xliff:g id="NUMBER">%d</xliff:g> անհաջող փորձ: Հեռախոսի կարգավորումները կզրոյացվեն, և բոլոր տվյալները կջնջվեն:"</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Դուք կատարել եք պլանշետն ապակողպելու <xliff:g id="NUMBER_0">%1$d</xliff:g> անհաջող փորձ: Եվս <xliff:g id="NUMBER_1">%2$d</xliff:g> անհաջող փորձից հետո այս օգտատերը կհեռացվի, և նրա բոլոր տվյալները կջնջվեն:"</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Դուք կատարել եք հեռախոսն ապակողպելու <xliff:g id="NUMBER_0">%1$d</xliff:g> անհաջող փորձ: Եվս <xliff:g id="NUMBER_1">%2$d</xliff:g> անհաջող փորձից հետո այս օգտատերը կհեռացվի, և նրա բոլոր տվյալները կջնջվեն:"</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Դուք կատարել եք պլանշետն ապակողպելու <xliff:g id="NUMBER">%d</xliff:g> անհաջող փորձ: Օգտատերը կհեռացվի, և նրա բոլոր տվյալները կջնջվեն:"</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Դուք կատարել եք հեռախոսն ապակողպելու <xliff:g id="NUMBER">%d</xliff:g> անհաջող փորձ: Օգտատերը կհեռացվի, և նրա բոլոր տվյալները կջնջվեն:"</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Դուք կատարել եք պլանշետն ապակողպելու <xliff:g id="NUMBER_0">%1$d</xliff:g> անհաջող փորձ: Եվս <xliff:g id="NUMBER_1">%2$d</xliff:g> անհաջող փորձից հետո աշխատանքային պրոֆիլը կհեռացվի, և պրոֆիլի բոլոր տվյալները կջնջվեն:"</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Դուք կատարել եք հեռախոսն ապակողպելու <xliff:g id="NUMBER_0">%1$d</xliff:g> անհաջող փորձ: Եվս <xliff:g id="NUMBER_1">%2$d</xliff:g> անհաջող փորձից հետո աշխատանքային պրոֆիլը կհեռացվի, և պրոֆիլի բոլոր տվյալները կջնջվեն:"</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Դուք կատարել եք պլանշետն ապակողպելու <xliff:g id="NUMBER">%d</xliff:g> անհաջող փորձ: Աշխատանքային պրոֆիլը կհեռացվի, և պրոֆիլի բոլոր տվյալները կջնջվեն:"</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Դուք կատարել եք հեռախոսն ապակողպելու <xliff:g id="NUMBER">%d</xliff:g> անհաջող փորձ: Աշխատանքային պրոֆիլը կհեռացվի, և պրոֆիլի բոլոր տվյալները կջնջվեն:"</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Դուք կատարել եք ապակողպման նախշը մուտքագրելու <xliff:g id="NUMBER_0">%1$d</xliff:g> անհաջող փորձ: Եվս <xliff:g id="NUMBER_1">%2$d</xliff:g> անհաջող փորձից հետո ձեզանից կպահանջվի ապակողպել պլանշետը էլփոստի հաշվի միջոցով։\n\n Խնդրում ենք կրկին փորձել <xliff:g id="NUMBER_2">%3$d</xliff:g> վայրկյանից:"</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Դուք <xliff:g id="NUMBER_0">%1$d</xliff:g> անգամ սխալ եք հավաքել ձեր ապակողպման նմուշը: Եվս <xliff:g id="NUMBER_1">%2$d</xliff:g> անհաջող փորձից հետո ձեզ կառաջարկվի ապակողպել հեռախոսը` օգտագործելով էլփոստի հաշիվ:\n\n Կրկին փորձեք <xliff:g id="NUMBER_2">%3$d</xliff:g> վայրկյանից:"</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-in/strings.xml b/packages/SystemUI/res-product/values-in/strings.xml
index e87aab3edbc5..369d5734411f 100644
--- a/packages/SystemUI/res-product/values-in/strings.xml
+++ b/packages/SystemUI/res-product/values-in/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"Tidak ada kartu SIM dalam tablet."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"Tidak ada Kartu SIM di dalam ponsel."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"Kode PIN tidak cocok"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Sudah <xliff:g id="NUMBER_0">%1$d</xliff:g> kali Anda berupaya membuka kunci tablet dengan tidak benar. Setelah <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi upaya yang tidak berhasil, tablet ini akan disetel ulang, sehingga semua datanya akan dihapus."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Sudah <xliff:g id="NUMBER_0">%1$d</xliff:g> kali Anda berupaya membuka kunci ponsel dengan tidak benar. Setelah <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi upaya yang tidak berhasil, ponsel ini akan disetel ulang, sehingga semua datanya akan dihapus."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Sudah <xliff:g id="NUMBER">%d</xliff:g> kali Anda berupaya membuka kunci tablet dengan tidak benar. Tablet ini akan disetel ulang, sehingga menghapus semua datanya."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Sudah <xliff:g id="NUMBER">%d</xliff:g> kali Anda berupaya membuka kunci ponsel dengan tidak benar. Ponsel ini akan disetel ulang, sehingga menghapus semua datanya."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Sudah <xliff:g id="NUMBER_0">%1$d</xliff:g> kali Anda berupaya membuka kunci tablet dengan tidak benar. Setelah <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi upaya yang tidak berhasil, pengguna ini akan dihapus, sehingga semua data pengguna akan dihapus."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Sudah <xliff:g id="NUMBER_0">%1$d</xliff:g> kali Anda berupaya membuka kunci ponsel dengan tidak benar. Setelah <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi upaya yang tidak berhasil, pengguna ini akan dihapus, sehingga semua data pengguna akan dihapus."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Perangkat Android TV akan segera dinonaktifkan; tekan tombol untuk terus menyalakannya."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Perangkat akan segera dinonaktifkan, tekan untuk terus menyalakannya."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Sudah <xliff:g id="NUMBER">%d</xliff:g> kali Anda berupaya membuka kunci tablet dengan tidak benar. Profil kerja akan dihapus, sehingga menghapus semua data profil."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Sudah <xliff:g id="NUMBER">%d</xliff:g> kali Anda berupaya membuka kunci ponsel dengan tidak benar. Profil kerja akan dihapus, sehingga menghapus semua data profil."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Anda telah <xliff:g id="NUMBER_0">%1$d</xliff:g> kali salah menggambar pola pembuka. Setelah gagal <xliff:g id="NUMBER_1">%2$d</xliff:g> kali lagi, Anda akan diminta membuka kunci tablet menggunakan akun email.\n\n Coba lagi dalam <xliff:g id="NUMBER_2">%3$d</xliff:g> detik."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Anda telah <xliff:g id="NUMBER_0">%1$d</xliff:g> kali salah menggambar pola pembuka. Setelah gagal <xliff:g id="NUMBER_1">%2$d</xliff:g> kali lagi, Anda akan diminta membuka kunci ponsel menggunakan akun email.\n\n Coba lagi dalam <xliff:g id="NUMBER_2">%3$d</xliff:g> detik."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Sejajarkan ulang ponsel untuk mengisi daya lebih cepat"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Sejajarkan ulang ponsel untuk mengisi daya secara nirkabel"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Perangkat Android TV akan segera dimatikan; tekan tombol untuk terus menyalakannya."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Perangkat akan segera dimatikan, tekan untuk terus menyalakannya."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Tidak ada kartu SIM dalam tablet."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Tidak ada kartu SIM dalam ponsel."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"Kode PIN tidak cocok"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Anda telah <xliff:g id="NUMBER_0">%1$d</xliff:g> kali berupaya membuka kunci tablet dengan tidak benar. Setelah <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi upaya yang tidak berhasil, tablet ini akan disetel ulang, sehingga semua datanya akan dihapus."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Anda telah <xliff:g id="NUMBER_0">%1$d</xliff:g> kali berupaya membuka kunci ponsel dengan tidak benar. Setelah <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi upaya yang tidak berhasil, ponsel ini akan disetel ulang, sehingga semua datanya akan dihapus."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Anda telah <xliff:g id="NUMBER">%d</xliff:g> kali berupaya membuka kunci tablet dengan tidak benar. Tablet ini akan disetel ulang, sehingga semua datanya akan dihapus."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Anda telah <xliff:g id="NUMBER">%d</xliff:g> kali berupaya membuka kunci ponsel dengan tidak benar. Ponsel ini akan disetel ulang, sehingga semua datanya akan dihapus."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Anda telah <xliff:g id="NUMBER_0">%1$d</xliff:g> kali berupaya membuka kunci tablet dengan tidak benar. Setelah <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi upaya yang tidak berhasil, pengguna ini akan dihapus, sehingga semua data pengguna akan dihapus."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Anda telah <xliff:g id="NUMBER_0">%1$d</xliff:g> kali berupaya membuka kunci ponsel dengan tidak benar. Setelah <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi upaya yang tidak berhasil, pengguna ini akan dihapus, sehingga semua data pengguna akan dihapus."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Anda telah <xliff:g id="NUMBER">%d</xliff:g> kali berupaya membuka kunci tablet dengan tidak benar. Pengguna ini akan dihapus, sehingga semua data pengguna akan dihapus."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Anda telah <xliff:g id="NUMBER">%d</xliff:g> kali berupaya membuka kunci ponsel dengan tidak benar. Pengguna ini akan dihapus, sehingga semua data pengguna akan dihapus."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Anda telah <xliff:g id="NUMBER_0">%1$d</xliff:g> kali berupaya membuka kunci tablet dengan tidak benar. Setelah <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi upaya yang tidak berhasil, profil kerja akan dihapus, sehingga semua data profil akan dihapus."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Anda telah <xliff:g id="NUMBER_0">%1$d</xliff:g> kali berupaya membuka kunci ponsel dengan tidak benar. Setelah <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi upaya yang tidak berhasil, profil kerja akan dihapus, sehingga semua data profil akan dihapus."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Anda telah <xliff:g id="NUMBER">%d</xliff:g> kali berupaya membuka kunci tablet dengan tidak benar. Profil kerja akan dihapus, sehingga semua data profil akan dihapus."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Anda telah <xliff:g id="NUMBER">%d</xliff:g> kali berupaya membuka kunci ponsel dengan tidak benar. Profil kerja akan dihapus, sehingga semua data profil akan dihapus."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Anda telah <xliff:g id="NUMBER_0">%1$d</xliff:g> kali salah menggambar pola pembuka kunci. Setelah <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi upaya yang tidak berhasil, Anda akan diminta membuka kunci tablet menggunakan akun email.\n\n Coba lagi dalam <xliff:g id="NUMBER_2">%3$d</xliff:g> detik."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Anda telah <xliff:g id="NUMBER_0">%1$d</xliff:g> kali salah menggambar pola pembuka kunci. Setelah <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi upaya yang tidak berhasil, Anda akan diminta membuka kunci ponsel menggunakan akun email.\n\n Coba lagi dalam <xliff:g id="NUMBER_2">%3$d</xliff:g> detik."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-is/strings.xml b/packages/SystemUI/res-product/values-is/strings.xml
index 38c651a05d8c..f533bb818828 100644
--- a/packages/SystemUI/res-product/values-is/strings.xml
+++ b/packages/SystemUI/res-product/values-is/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"Ekkert SIM-kort í spjaldtölvunni."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"Ekkert SIM-kort í símanum."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"PIN-númerin stemma ekki"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Þú hefur gert <xliff:g id="NUMBER_0">%1$d</xliff:g> árangurslausar tilraunir til að opna spjaldtölvuna. Eftir <xliff:g id="NUMBER_1">%2$d</xliff:g> árangurslausar tilraunir í viðbót verður spjaldtölvan endurstillt, með þeim afleiðingum að öllum gögnum hennar verður eytt."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Þú hefur gert <xliff:g id="NUMBER_0">%1$d</xliff:g> árangurslausar tilraunir til að opna símann. Eftir <xliff:g id="NUMBER_1">%2$d</xliff:g> árangurslausar tilraunir í viðbót verður síminn endurstilltur, með þeim afleiðingum að öllum gögnum hans verður eytt."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Þú hefur gert <xliff:g id="NUMBER">%d</xliff:g> árangurslausar tilraunir til að opna spjaldtölvuna. Spjaldtölvan verður endurstillt, með þeim afleiðingum að öllum gögnum hennar verður eytt."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Þú hefur gert <xliff:g id="NUMBER">%d</xliff:g> árangurslausar tilraunir til að opna símann. Síminn verður endurstilltur, með þeim afleiðingum að öllum gögnum hans verður eytt."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Þú hefur gert <xliff:g id="NUMBER_0">%1$d</xliff:g> árangurslausar tilraunir til að opna spjaldtölvuna. Eftir <xliff:g id="NUMBER_1">%2$d</xliff:g> árangurslausar tilraunir í viðbót verður notandinn fjarlægður með þeim afleiðingum að öllum notandagögnum verður eytt."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Þú hefur gert <xliff:g id="NUMBER_0">%1$d</xliff:g> árangurslausar tilraunir til að opna símann. Eftir <xliff:g id="NUMBER_1">%2$d</xliff:g> árangurslausar tilraunir í viðbót verður notandinn fjarlægður með þeim afleiðingum að öllum notandagögnum verður eytt."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Android TV tækið slekkur á sér fljótlega. Ýttu á takka til að það slokkni ekki á því."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Tækið slekkur á sér fljótlega. Ýttu á takka til að það slokkni ekki á því."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Þú hefur gert <xliff:g id="NUMBER">%d</xliff:g> árangurslausar tilraunir til að opna spjaldtölvuna. Vinnusniðið verður fjarlægt, með þeim afleiðingum að öllum gögnum þess verður eytt."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Þú hefur gert <xliff:g id="NUMBER">%d</xliff:g> árangurslausar tilraunir til að opna símann. Vinnusniðið verður fjarlægt, með þeim afleiðingum að öllum gögnum þess verður eytt."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Þú hefur teiknað rangt opnunarmynstur <xliff:g id="NUMBER_0">%1$d</xliff:g> sinnum. Eftir <xliff:g id="NUMBER_1">%2$d</xliff:g> árangurslausar tilraunir í viðbót verður þú beðin(n) um að opna spjaldtölvuna með tölvupóstreikningi.\n\n Reyndu aftur eftir <xliff:g id="NUMBER_2">%3$d</xliff:g> sekúndur."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Þú hefur teiknað rangt opnunarmynstur <xliff:g id="NUMBER_0">%1$d</xliff:g> sinnum. Eftir <xliff:g id="NUMBER_1">%2$d</xliff:g> árangurslausar tilraunir í viðbót verðurðu beðin(n) um að opna símann með tölvupóstreikningi.\n\n Reyndu aftur eftir <xliff:g id="NUMBER_2">%3$d</xliff:g> sekúndur."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Færðu símann til að fá hraðari hleðslu"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Færðu símann til að hlaða þráðlaust"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Android TV tækið slekkur á sér fljótlega. Ýttu á takka til að það slokkni ekki á því."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Tækið slekkur á sér fljótlega. Ýttu á takka til að það slokkni ekki á því."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Ekkert SIM-kort í spjaldtölvunni."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Ekkert SIM-kort í símanum."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"PIN-númerin stemma ekki"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Þú hefur gert <xliff:g id="NUMBER_0">%1$d</xliff:g> árangurslausar tilraunir til að opna spjaldtölvuna. Eftir <xliff:g id="NUMBER_1">%2$d</xliff:g> árangurslausar tilraunir í viðbót verður spjaldtölvan endurstillt, með þeim afleiðingum að öllum gögnum hennar verður eytt."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Þú hefur gert <xliff:g id="NUMBER_0">%1$d</xliff:g> árangurslausar tilraunir til að opna símann. Eftir <xliff:g id="NUMBER_1">%2$d</xliff:g> árangurslausar tilraunir í viðbót verður síminn endurstilltur, með þeim afleiðingum að öllum gögnum hans verður eytt."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Þú hefur gert <xliff:g id="NUMBER">%d</xliff:g> árangurslausar tilraunir til að opna spjaldtölvuna. Spjaldtölvan verður endurstillt, með þeim afleiðingum að öllum gögnum hennar verður eytt."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Þú hefur gert <xliff:g id="NUMBER">%d</xliff:g> árangurslausar tilraunir til að opna símann. Síminn verður endurstilltur, með þeim afleiðingum að öllum gögnum hans verður eytt."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Þú hefur gert <xliff:g id="NUMBER_0">%1$d</xliff:g> árangurslausar tilraunir til að opna spjaldtölvuna. Eftir <xliff:g id="NUMBER_1">%2$d</xliff:g> árangurslausar tilraunir í viðbót verður notandinn fjarlægður með þeim afleiðingum að öllum notandagögnum verður eytt."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Þú hefur gert <xliff:g id="NUMBER_0">%1$d</xliff:g> árangurslausar tilraunir til að opna símann. Eftir <xliff:g id="NUMBER_1">%2$d</xliff:g> árangurslausar tilraunir í viðbót verður notandinn fjarlægður með þeim afleiðingum að öllum notandagögnum verður eytt."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Þú hefur gert <xliff:g id="NUMBER">%d</xliff:g> árangurslausar tilraunir til að opna spjaldtölvuna. Notandinn verður fjarlægður, með þeim afleiðingum að öllum notandagögnum verður eytt."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Þú hefur gert <xliff:g id="NUMBER">%d</xliff:g> árangurslausar tilraunir til að opna símann. Notandinn verður fjarlægður, með þeim afleiðingum að öllum notandagögnum verður eytt."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Þú hefur gert <xliff:g id="NUMBER_0">%1$d</xliff:g> árangurslausar tilraunir til að opna spjaldtölvuna. Eftir <xliff:g id="NUMBER_1">%2$d</xliff:g> árangurslausar tilraunir í viðbót verður vinnusniðið fjarlægt með þeim afleiðingum að öllum gögnum þess verður eytt."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Þú hefur gert <xliff:g id="NUMBER_0">%1$d</xliff:g> árangurslausar tilraunir til að opna símann. Eftir <xliff:g id="NUMBER_1">%2$d</xliff:g> árangurslausar tilraunir í viðbót verður vinnusniðið fjarlægt með þeim afleiðingum að öllum gögnum þess verður eytt."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Þú hefur gert <xliff:g id="NUMBER">%d</xliff:g> árangurslausar tilraunir til að opna spjaldtölvuna. Vinnusniðið verður fjarlægt, með þeim afleiðingum að öllum gögnum þess verður eytt."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Þú hefur gert <xliff:g id="NUMBER">%d</xliff:g> árangurslausar tilraunir til að opna símann. Vinnusniðið verður fjarlægt, með þeim afleiðingum að öllum gögnum þess verður eytt."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Þú hefur teiknað rangt opnunarmynstur <xliff:g id="NUMBER_0">%1$d</xliff:g> sinnum. Eftir <xliff:g id="NUMBER_1">%2$d</xliff:g> árangurslausar tilraunir í viðbót verðurðu beðin(n) um að opna spjaldtölvuna með tölvupóstreikningi.\n\n Reyndu aftur eftir <xliff:g id="NUMBER_2">%3$d</xliff:g> sekúndur."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Þú hefur teiknað rangt opnunarmynstur <xliff:g id="NUMBER_0">%1$d</xliff:g> sinnum. Eftir <xliff:g id="NUMBER_1">%2$d</xliff:g> árangurslausar tilraunir í viðbót verðurðu beðin(n) um að opna símann með tölvupóstreikningi.\n\n Reyndu aftur eftir <xliff:g id="NUMBER_2">%3$d</xliff:g> sekúndur."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-it/strings.xml b/packages/SystemUI/res-product/values-it/strings.xml
index 1ca5706d2004..5adff23d8898 100644
--- a/packages/SystemUI/res-product/values-it/strings.xml
+++ b/packages/SystemUI/res-product/values-it/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"Nessuna scheda SIM presente nel tablet."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"Nessuna scheda SIM presente nel telefono."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"I codici PIN non corrispondono"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Hai tentato di sbloccare il tablet senza riuscirci per <xliff:g id="NUMBER_0">%1$d</xliff:g> volte. Dopo altri <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativi falliti, il tablet verrà ripristinato e verranno quindi eliminati tutti i relativi dati."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Hai tentato di sbloccare il telefono senza riuscirci per <xliff:g id="NUMBER_0">%1$d</xliff:g> volte. Dopo altri <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativi falliti, il telefono verrà ripristinato e verranno quindi eliminati tutti i relativi dati."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Hai tentato di sbloccare il tablet senza riuscirci per <xliff:g id="NUMBER">%d</xliff:g> volte. Il tablet verrà ripristinato e verranno quindi eliminati tutti i relativi dati."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Hai tentato di sbloccare il telefono senza riuscirci per <xliff:g id="NUMBER">%d</xliff:g> volte. Il telefono verrà ripristinato e verranno quindi eliminati tutti i relativi dati."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Hai tentato di sbloccare il tablet senza riuscirci per <xliff:g id="NUMBER_0">%1$d</xliff:g> volte. Dopo altri <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativi falliti, questo utente verrà rimosso e verranno quindi eliminati tutti i dati associati."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Hai tentato di sbloccare il telefono senza riuscirci per <xliff:g id="NUMBER_0">%1$d</xliff:g> volte. Dopo altri <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativi falliti, questo utente verrà rimosso e verranno quindi eliminati tutti i dati associati."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"A breve il dispositivo Android TV si spegnerà. Premi un pulsante per tenerlo acceso."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"A breve il dispositivo si spegnerà. Premi per tenerlo acceso."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Hai tentato di sbloccare il tablet senza riuscirci per <xliff:g id="NUMBER">%d</xliff:g> volte. Il profilo di lavoro verrà rimosso e verranno quindi eliminati tutti i dati associati."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Hai tentato di sbloccare il telefono senza riuscirci per <xliff:g id="NUMBER">%d</xliff:g> volte. Il profilo di lavoro verrà rimosso e verranno quindi eliminati tutti i dati associati."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"<xliff:g id="NUMBER_0">%1$d</xliff:g> tentativi errati di inserimento della sequenza di sblocco. Dopo altri <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativi falliti, ti verrà chiesto di sbloccare il tablet con un account email.\n\n Riprova tra <xliff:g id="NUMBER_2">%3$d</xliff:g> secondi."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"<xliff:g id="NUMBER_0">%1$d</xliff:g> tentativi errati di inserimento della sequenza di sblocco. Dopo altri <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativi falliti, ti verrà chiesto di sbloccare il telefono con un account email.\n\n Riprova tra <xliff:g id="NUMBER_2">%3$d</xliff:g> secondi."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Riallinea il telefono per ricaricarlo più velocemente"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Riallinea il telefono per caricarlo in modalità wireless"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Presto il dispositivo Android TV si spegnerà. Premi un pulsante per tenerlo acceso."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Presto il dispositivo si spegnerà. Premi per tenerlo acceso."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Nessuna scheda SIM presente nel tablet."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Nessuna scheda SIM presente nel telefono."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"I codici PIN non corrispondono"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Hai tentato di sbloccare il tablet senza riuscirci per <xliff:g id="NUMBER_0">%1$d</xliff:g> volte. Dopo altri <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativi falliti, il tablet verrà ripristinato e verranno quindi eliminati tutti i relativi dati."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Hai tentato di sbloccare il telefono senza riuscirci per <xliff:g id="NUMBER_0">%1$d</xliff:g> volte. Dopo altri <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativi falliti, il telefono verrà ripristinato e verranno quindi eliminati tutti i relativi dati."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Hai tentato di sbloccare il tablet senza riuscirci per <xliff:g id="NUMBER">%d</xliff:g> volte. Il tablet verrà ripristinato e verranno quindi eliminati tutti i relativi dati."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Hai tentato di sbloccare il telefono senza riuscirci per <xliff:g id="NUMBER">%d</xliff:g> volte. Il telefono verrà ripristinato e verranno quindi eliminati tutti i relativi dati."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Hai tentato di sbloccare il tablet senza riuscirci per <xliff:g id="NUMBER_0">%1$d</xliff:g> volte. Dopo altri <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativi falliti, questo utente verrà rimosso e verranno quindi eliminati tutti i dati associati."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Hai tentato di sbloccare il telefono senza riuscirci per <xliff:g id="NUMBER_0">%1$d</xliff:g> volte. Dopo altri <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativi falliti, questo utente verrà rimosso e verranno quindi eliminati tutti i dati associati."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Hai tentato di sbloccare il tablet senza riuscirci per <xliff:g id="NUMBER">%d</xliff:g> volte. Questo utente verrà rimosso e verranno quindi eliminati tutti i dati associati."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Hai tentato di sbloccare il telefono senza riuscirci per <xliff:g id="NUMBER">%d</xliff:g> volte. Questo utente verrà rimosso e verranno quindi eliminati tutti i dati associati."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Hai tentato di sbloccare il tablet senza riuscirci per <xliff:g id="NUMBER_0">%1$d</xliff:g> volte. Dopo altri <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativi falliti, il profilo di lavoro verrà rimosso e verranno quindi eliminati tutti i dati associati."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Hai tentato di sbloccare il telefono senza riuscirci per <xliff:g id="NUMBER_0">%1$d</xliff:g> volte. Dopo altri <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativi falliti, il profilo di lavoro verrà rimosso e verranno quindi eliminati tutti i dati associati."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Hai tentato di sbloccare il tablet senza riuscirci per <xliff:g id="NUMBER">%d</xliff:g> volte. Il profilo di lavoro verrà rimosso e verranno quindi eliminati tutti i dati associati."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Hai tentato di sbloccare il telefono senza riuscirci per <xliff:g id="NUMBER">%d</xliff:g> volte. Il profilo di lavoro verrà rimosso e verranno quindi eliminati tutti i dati associati."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"<xliff:g id="NUMBER_0">%1$d</xliff:g> tentativi errati di inserimento della sequenza di sblocco. Dopo altri <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativi falliti, ti verrà chiesto di sbloccare il tablet con un account email.\n\n Riprova tra <xliff:g id="NUMBER_2">%3$d</xliff:g> secondi."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"<xliff:g id="NUMBER_0">%1$d</xliff:g> tentativi errati di inserimento della sequenza di sblocco. Dopo altri <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativi falliti, ti verrà chiesto di sbloccare il telefono con un account email.\n\n Riprova tra <xliff:g id="NUMBER_2">%3$d</xliff:g> secondi."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-iw/strings.xml b/packages/SystemUI/res-product/values-iw/strings.xml
index 3a6f6f130b35..cd9836552eb1 100644
--- a/packages/SystemUI/res-product/values-iw/strings.xml
+++ b/packages/SystemUI/res-product/values-iw/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"‏אין כרטיס SIM בטאבלט."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"‏אין כרטיס SIM בטלפון."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"קודי הגישה אינם תואמים"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"ניסית לבטל את נעילת הטאבלט <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, טאבלט זה יאופס וכל הנתונים שבו יימחקו."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"ניסית לבטל את נעילת הטלפון <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, טלפון זה יאופס וכל הנתונים שבו יימחקו."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"ניסית לבטל את נעילת הטאבלט <xliff:g id="NUMBER">%d</xliff:g> פעמים. הטאבלט יאופס וכל הנתונים שלו יימחקו."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"ניסית לבטל את נעילת הטלפון <xliff:g id="NUMBER">%d</xliff:g> פעמים. הטלפון יאופס וכל הנתונים שבו יימחקו."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"ניסית לבטל את נעילת הטאבלט <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, משתמש זה יוסר וכל נתוני המשתמש יימחקו."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"ניסית לבטל את נעילת הטלפון <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, משתמש זה יוסר וכל נתוני המשתמש יימחקו."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"‏מכשיר Android TV ייכבה בקרוב. יש ללחוץ על לחצן כלשהו כדי שהוא ימשיך לפעול."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"המכשיר ייכבה בקרוב, יש ללחוץ כדי שהוא ימשיך לפעול."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"ניסית לבטל את נעילת הטאבלט <xliff:g id="NUMBER">%d</xliff:g> פעמים. פרופיל העבודה יוסר וכל נתוני הפרופיל יימחקו."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"ניסית לבטל את נעילת הטלפון <xliff:g id="NUMBER">%d</xliff:g> פעמים. פרופיל העבודה יוסר וכל נתוני הפרופיל יימחקו."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"שרטטת קו ביטול נעילה שגוי <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, תתבקש לבטל את נעילת הטאבלט באמצעות חשבון אימייל‏.\n\nנסה שוב בעוד <xliff:g id="NUMBER_2">%3$d</xliff:g> שניות."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"שרטטת קו ביטול נעילה שגוי <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, תתבקש לבטל את נעילת הטלפון באמצעות חשבון אימייל‏.\n\n נסה שוב בעוד <xliff:g id="NUMBER_2">%3$d</xliff:g> שניות."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"צריך ליישר את הטלפון כדי לטעון אותו במהירות"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"צריך ליישר את הטלפון כדי לטעון אותו באופן אלחוטי"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"‏מכשיר Android TV ייכבה בקרוב. יש ללחוץ על לחצן כלשהו כדי שהוא ימשיך לפעול."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"המכשיר ייכבה בקרוב, יש ללחוץ כדי שהוא ימשיך לפעול."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"‏אין כרטיס SIM בטאבלט."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"‏אין כרטיס SIM בטלפון."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"קודי האימות אינם תואמים"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"ניסית לבטל את נעילת הטאבלט <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, טאבלט זה יאופס וכל הנתונים שבו יימחקו."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"ניסית לבטל את נעילת הטלפון <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, טלפון זה יאופס וכל הנתונים שבו יימחקו."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"ניסית לבטל את נעילת הטאבלט <xliff:g id="NUMBER">%d</xliff:g> פעמים. הטאבלט יאופס וכל הנתונים שלו יימחקו."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"ניסית לבטל את נעילת הטלפון <xliff:g id="NUMBER">%d</xliff:g> פעמים. הטלפון יאופס וכל הנתונים שבו יימחקו."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"ניסית לבטל את נעילת הטאבלט <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, משתמש זה יוסר וכל נתוני המשתמש יימחקו."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"ניסית לבטל את נעילת הטלפון <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, משתמש זה יוסר וכל נתוני המשתמש יימחקו."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"ניסית לבטל את נעילת הטאבלט <xliff:g id="NUMBER">%d</xliff:g> פעמים באופן שגוי. משתמש זה יוסר וכל נתוני המשתמש יימחקו."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"ניסית לבטל את נעילת הטלפון <xliff:g id="NUMBER">%d</xliff:g> פעמים. משתמש זה יוסר וכל נתוני המשתמש יימחקו."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"ניסית לבטל את נעילת הטאבלט <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, פרופיל העבודה יוסר וכל נתוני הפרופיל יימחקו."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"ניסית לבטל את נעילת הטלפון <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, פרופיל העבודה יוסר וכל נתוני הפרופיל יימחקו."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"ניסית לבטל את נעילת הטאבלט <xliff:g id="NUMBER">%d</xliff:g> פעמים. פרופיל העבודה יוסר וכל נתוני הפרופיל יימחקו."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"ניסית לבטל את נעילת הטלפון <xliff:g id="NUMBER">%d</xliff:g> פעמים. פרופיל העבודה יוסר וכל נתוני הפרופיל יימחקו."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"שרטטת קו ביטול נעילה שגוי <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, ,תישלח אליך בקשה לבטל את נעילת הטאבלט באמצעות חשבון אימייל‏.\n\n יש לנסות שוב בעוד <xliff:g id="NUMBER_2">%3$d</xliff:g> שניות."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"שרטטת קו ביטול נעילה שגוי <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, תשילח אליך בקשה לבטל את נעילת הטלפון באמצעות חשבון אימייל‏.\n\n יש לנסות שוב בעוד <xliff:g id="NUMBER_2">%3$d</xliff:g> שניות."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-ja/strings.xml b/packages/SystemUI/res-product/values-ja/strings.xml
index b0ea11c58698..d5634fa50ae4 100644
--- a/packages/SystemUI/res-product/values-ja/strings.xml
+++ b/packages/SystemUI/res-product/values-ja/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"タブレットに SIM カードが挿入されていません。"</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"スマートフォンに SIM カードが挿入されていません。"</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"PIN コードが一致しません"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"タブレットのロック解除に <xliff:g id="NUMBER_0">%1$d</xliff:g> 回失敗しました。あと <xliff:g id="NUMBER_1">%2$d</xliff:g> 回失敗すると、このタブレットはリセットされ、データはすべて消去されます。"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"スマートフォンのロック解除に <xliff:g id="NUMBER_0">%1$d</xliff:g> 回失敗しました。あと <xliff:g id="NUMBER_1">%2$d</xliff:g> 回失敗すると、このスマートフォンはリセットされ、データはすべて消去されます。"</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"タブレットのロック解除に <xliff:g id="NUMBER">%d</xliff:g> 回失敗しました。このタブレットはリセットされ、データはすべて消去されます。"</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"スマートフォンのロック解除に <xliff:g id="NUMBER">%d</xliff:g> 回失敗しました。このスマートフォンはリセットされ、データはすべて消去されます。"</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"タブレットのロック解除に <xliff:g id="NUMBER_0">%1$d</xliff:g> 回失敗しました。あと <xliff:g id="NUMBER_1">%2$d</xliff:g> 回失敗すると、このユーザーは削除され、ユーザー データはすべて消去されます。"</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"スマートフォンのロック解除に <xliff:g id="NUMBER_0">%1$d</xliff:g> 回失敗しました。あと <xliff:g id="NUMBER_1">%2$d</xliff:g> 回失敗すると、このユーザーは削除され、ユーザー データはすべて消去されます。"</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Android TV デバイスはまもなく OFF になります。ON 状態を維持するには、ボタンを押してください。"</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"このデバイスはまもなく OFF になります。ON 状態を維持するには、ボタンを押してください。"</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"タブレットのロック解除に <xliff:g id="NUMBER">%d</xliff:g> 回失敗しました。仕事用プロファイルは削除され、プロファイルのデータはすべて消去されます。"</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"スマートフォンのロック解除に <xliff:g id="NUMBER">%d</xliff:g> 回失敗しました。仕事用プロファイルは削除され、プロファイルのデータはすべて消去されます。"</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"ロック解除パターンの入力を <xliff:g id="NUMBER_0">%1$d</xliff:g> 回間違えました。あと <xliff:g id="NUMBER_1">%2$d</xliff:g> 回間違えると、タブレットのロック解除にメール アカウントが必要になります。\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> 秒後にもう一度お試しください。"</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"ロック解除パターンの入力を <xliff:g id="NUMBER_0">%1$d</xliff:g> 回間違えました。あと <xliff:g id="NUMBER_1">%2$d</xliff:g> 回間違えると、スマートフォンのロック解除にメール アカウントが必要になります。\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> 秒後にもう一度お試しください。"</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"急速充電するにはスマートフォンの位置を調整してください"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"ワイヤレス充電するにはスマートフォンの位置を調整してください"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Android TV デバイスはまもなく OFF になります。ON 状態を維持するには、ボタンを押してください。"</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"このデバイスはまもなく OFF になります。ON 状態を維持するには、ボタンを押してください。"</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"タブレットに SIM カードが挿入されていません。"</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"スマートフォンに SIM カードが挿入されていません。"</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"PIN コードが一致しません"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"タブレットのロック解除に <xliff:g id="NUMBER_0">%1$d</xliff:g> 回失敗しました。あと <xliff:g id="NUMBER_1">%2$d</xliff:g> 回失敗すると、このタブレットはリセットされ、データはすべて消去されます。"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"スマートフォンのロック解除に <xliff:g id="NUMBER_0">%1$d</xliff:g> 回失敗しました。あと <xliff:g id="NUMBER_1">%2$d</xliff:g> 回失敗すると、このスマートフォンはリセットされ、データはすべて消去されます。"</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"タブレットのロック解除に <xliff:g id="NUMBER">%d</xliff:g> 回失敗しました。このタブレットはリセットされ、データはすべて消去されます。"</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"スマートフォンのロック解除に <xliff:g id="NUMBER">%d</xliff:g> 回失敗しました。このスマートフォンはリセットされ、データはすべて消去されます。"</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"タブレットのロック解除に <xliff:g id="NUMBER_0">%1$d</xliff:g> 回失敗しました。あと <xliff:g id="NUMBER_1">%2$d</xliff:g> 回失敗すると、このユーザーは削除され、ユーザー データはすべて消去されます。"</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"スマートフォンのロック解除に <xliff:g id="NUMBER_0">%1$d</xliff:g> 回失敗しました。あと <xliff:g id="NUMBER_1">%2$d</xliff:g> 回失敗すると、このユーザーは削除され、ユーザー データはすべて消去されます。"</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"タブレットのロック解除に <xliff:g id="NUMBER">%d</xliff:g> 回失敗しました。このユーザーは削除され、ユーザー データはすべて消去されます。"</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"スマートフォンのロック解除に <xliff:g id="NUMBER">%d</xliff:g> 回失敗しました。このユーザーは削除され、ユーザー データはすべて消去されます。"</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"タブレットのロック解除に <xliff:g id="NUMBER_0">%1$d</xliff:g> 回失敗しました。あと <xliff:g id="NUMBER_1">%2$d</xliff:g> 回失敗すると、仕事用プロファイルは削除され、プロファイルのデータはすべて消去されます。"</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"スマートフォンのロック解除に <xliff:g id="NUMBER_0">%1$d</xliff:g> 回失敗しました。あと <xliff:g id="NUMBER_1">%2$d</xliff:g> 回失敗すると、仕事用プロファイルは削除され、プロファイルのデータはすべて消去されます。"</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"タブレットのロック解除に <xliff:g id="NUMBER">%d</xliff:g> 回失敗しました。仕事用プロファイルは削除され、プロファイルのデータはすべて消去されます。"</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"スマートフォンのロック解除に <xliff:g id="NUMBER">%d</xliff:g> 回失敗しました。仕事用プロファイルは削除され、プロファイルのデータはすべて消去されます。"</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"ロック解除パターンの入力を <xliff:g id="NUMBER_0">%1$d</xliff:g> 回間違えました。あと <xliff:g id="NUMBER_1">%2$d</xliff:g> 回間違えると、タブレットのロック解除にメール アカウントが必要になります。\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> 秒後にもう一度お試しください。"</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"ロック解除パターンの入力を <xliff:g id="NUMBER_0">%1$d</xliff:g> 回間違えました。あと <xliff:g id="NUMBER_1">%2$d</xliff:g> 回間違えると、スマートフォンのロック解除にメール アカウントが必要になります。\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> 秒後にもう一度お試しください。"</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-ka/strings.xml b/packages/SystemUI/res-product/values-ka/strings.xml
index 1f5a20229ebb..772e3f4e2f79 100644
--- a/packages/SystemUI/res-product/values-ka/strings.xml
+++ b/packages/SystemUI/res-product/values-ka/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"ტაბლეტში არ არის SIM ბარათი."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"ტელეფონში არ არის SIM ბარათი."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"PIN-კოდები არ ემთხვევა"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"თქვენ არასწორად ცადეთ ტაბლეტის განბლოკვა <xliff:g id="NUMBER_0">%1$d</xliff:g>-ჯერ. კიდევ <xliff:g id="NUMBER_1">%2$d</xliff:g> წარუმატებელი მცდელობის შემდეგ, ამ ტაბლეტის გადაყენება განხორციელდება, რაც მისი მონაცემების მთლიანად წაშლას გამოიწვევს."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"თქვენ არასწორად ცადეთ ტელეფონის განბლოკვა <xliff:g id="NUMBER_0">%1$d</xliff:g>-ჯერ. კიდევ <xliff:g id="NUMBER_1">%2$d</xliff:g> წარუმატებელი მცდელობის შემდეგ, ამ ტელეფონის გადაყენება განხორციელდება, რაც მისი მონაცემების მთლიანად წაშლას გამოიწვევს."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"თქვენ არასწორად ცადეთ ტაბლეტის განბლოკვა <xliff:g id="NUMBER">%d</xliff:g>-ჯერ. ამის გამო, ამ ტაბლეტის გადაყენება განხორციელდება, რაც მისი მონაცემების მთლიანად წაშლას გამოიწვევს."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"თქვენ არასწორად ცადეთ ტელეფონის განბლოკვა <xliff:g id="NUMBER">%d</xliff:g>-ჯერ. ამის გამო, ამ ტელეფონის გადაყენება განხორციელდება, რაც მისი მონაცემების მთლიანად წაშლას გამოიწვევს."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"თქვენ არასწორად ცადეთ ტაბლეტის განბლოკვა <xliff:g id="NUMBER_0">%1$d</xliff:g>-ჯერ. კიდევ <xliff:g id="NUMBER_1">%2$d</xliff:g> წარუმატებელი მცდელობის შემდეგ, ეს მომხმარებელი ამოიშლება, რაც მომხმარებლის ყველა მონაცემის წაშლას გამოიწვევს."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"თქვენ არასწორად ცადეთ ტელეფონის განბლოკვა <xliff:g id="NUMBER_0">%1$d</xliff:g>-ჯერ. კიდევ <xliff:g id="NUMBER_1">%2$d</xliff:g> წარუმატებელი მცდელობის შემდეგ, ეს მომხმარებელი ამოიშლება, რაც მომხმარებლის ყველა მონაცემის წაშლას გამოიწვევს."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Android TV მოწყობილობა მალე გამოირთვება, დააჭირეთ ღილაკს, რომ ჩართული დარჩეს."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"მოწყობილობა მალე გამოირთვება, დააჭირეთ, რომ ჩართული დარჩეს."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"თქვენ არასწორად ცადეთ ტაბლეტის განბლოკვა <xliff:g id="NUMBER">%d</xliff:g>-ჯერ. ამის გამო, სამსახურის პროფილი ამოიშლება, რაც პროფილის ყველა მონაცემის წაშლას გამოიწვევს."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"თქვენ არასწორად ცადეთ ტელეფონის განბლოკვა <xliff:g id="NUMBER">%d</xliff:g>-ჯერ. ამის გამო, სამსახურის პროფილი ამოიშლება, რაც პროფილის ყველა მონაცემის წაშლას გამოიწვევს."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"თქვენ არასწორად დახატეთ თქვენი განბლოკვის ნიმუში <xliff:g id="NUMBER_0">%1$d</xliff:g>-ჯერ. კიდევ <xliff:g id="NUMBER_1">%2$d</xliff:g> წარუმატებელი მცდელობის შემდეგ, ტაბლეტის განბლოკვა თქვენი ელფოსტის ანგარიშის მეშვეობით მოგიწევთ.\n\n ცადეთ ხელახლა <xliff:g id="NUMBER_2">%3$d</xliff:g> წამში."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"თქვენ არასწორად დახატეთ თქვენი განბლოკვის ნიმუში <xliff:g id="NUMBER_0">%1$d</xliff:g>-ჯერ. კიდევ <xliff:g id="NUMBER_1">%2$d</xliff:g> წარუმატებელი მცდელობის შემდეგ, ტელეფონის განბლოკვა თქვენი ელფოსტის ანგარიშის მეშვეობით მოგიწევთ.\n\n ცადეთ ხელახლა <xliff:g id="NUMBER_2">%3$d</xliff:g> წამში."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"ზუსტად მოათავსეთ ტელეფონი სწრაფად დასატენად"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"ხელახლა შეუერთეთ ტელეფონი უსადენოდ დასამუხტად"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Android TV მოწყობილობა მალე გამოირთვება, დააჭირეთ ღილაკს, რომ ჩართული დარჩეს."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"მოწყობილობა მალე გამოირთვება, დააჭირეთ, რომ ჩართული დარჩეს."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"ტაბლეტში არ არის SIM ბარათი."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"ტელეფონში არ არის SIM ბარათი."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"PIN-კოდები არ ემთხვევა"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"თქვენ არასწორად ცადეთ ტაბლეტის განბლოკვა <xliff:g id="NUMBER_0">%1$d</xliff:g>-ჯერ. კიდევ <xliff:g id="NUMBER_1">%2$d</xliff:g> წარუმატებელი მცდელობის შემდეგ, ეს ტაბლეტი გადაყენდება, რაც მისი მონაცემების მთლიანად წაშლას გამოიწვევს."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"თქვენ არასწორად ცადეთ ტელეფონის განბლოკვა <xliff:g id="NUMBER_0">%1$d</xliff:g>-ჯერ. კიდევ <xliff:g id="NUMBER_1">%2$d</xliff:g> წარუმატებელი მცდელობის შემდეგ, ეს ტელეფონი გადაყენდება, რაც მისი მონაცემების მთლიანად წაშლას გამოიწვევს."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"თქვენ არასწორად ცადეთ ტაბლეტის განბლოკვა <xliff:g id="NUMBER">%d</xliff:g>-ჯერ. ამის გამო, ეს ტაბლეტი გადაყენდება, რაც მისი მონაცემების მთლიანად წაშლას გამოიწვევს."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"თქვენ არასწორად ცადეთ ტელეფონის განბლოკვა <xliff:g id="NUMBER">%d</xliff:g>-ჯერ. ამის გამო, ეს ტელეფონის გადაყენდება, რაც მისი მონაცემების მთლიანად წაშლას გამოიწვევს."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"თქვენ არასწორად ცადეთ ტაბლეტის განბლოკვა <xliff:g id="NUMBER_0">%1$d</xliff:g>-ჯერ. კიდევ <xliff:g id="NUMBER_1">%2$d</xliff:g> წარუმატებელი მცდელობის შემდეგ, ეს მომხმარებელი ამოიშლება, რაც მომხმარებლის ყველა მონაცემის წაშლას გამოიწვევს."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"თქვენ არასწორად ცადეთ ტელეფონის განბლოკვა <xliff:g id="NUMBER_0">%1$d</xliff:g>-ჯერ. კიდევ <xliff:g id="NUMBER_1">%2$d</xliff:g> წარუმატებელი მცდელობის შემდეგ, ეს მომხმარებელი ამოიშლება, რაც მომხმარებლის ყველა მონაცემის წაშლას გამოიწვევს."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"თქვენ არასწორად ცადეთ ტაბლეტის განბლოკვა <xliff:g id="NUMBER">%d</xliff:g>-ჯერ. ამის გამო, ეს მომხმარებელი ამოიშლება, რაც მომხმარებლის ყველა მონაცემის წაშლას გამოიწვევს."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"თქვენ არასწორად ცადეთ ტელეფონის განბლოკვა <xliff:g id="NUMBER">%d</xliff:g>-ჯერ. ამის გამო, ეს მომხმარებელი ამოიშლება, რაც მომხმარებლის ყველა მონაცემის წაშლას გამოიწვევს."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"თქვენ არასწორად ცადეთ ტაბლეტის განბლოკვა <xliff:g id="NUMBER_0">%1$d</xliff:g>-ჯერ. კიდევ <xliff:g id="NUMBER_1">%2$d</xliff:g> წარუმატებელი მცდელობის შემდეგ, სამსახურის პროფილი ამოიშლება, რაც პროფილის ყველა მონაცემის წაშლას გამოიწვევს."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"თქვენ არასწორად ცადეთ ტელეფონის განბლოკვა <xliff:g id="NUMBER_0">%1$d</xliff:g>-ჯერ. კიდევ <xliff:g id="NUMBER_1">%2$d</xliff:g> წარუმატებელი მცდელობის შემდეგ, სამსახურის პროფილი ამოიშლება, რაც პროფილის ყველა მონაცემის წაშლას გამოიწვევს."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"თქვენ არასწორად ცადეთ ტაბლეტის განბლოკვა <xliff:g id="NUMBER">%d</xliff:g>-ჯერ. ამის გამო, სამსახურის პროფილი ამოიშლება, რაც პროფილის ყველა მონაცემის წაშლას გამოიწვევს."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"თქვენ არასწორად ცადეთ ტელეფონის განბლოკვა <xliff:g id="NUMBER">%d</xliff:g>-ჯერ. ამის გამო, სამსახურის პროფილი ამოიშლება, რაც პროფილის ყველა მონაცემის წაშლას გამოიწვევს."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"თქვენ არასწორად დახატეთ თქვენი განბლოკვის ნიმუში <xliff:g id="NUMBER_0">%1$d</xliff:g>-ჯერ. კიდევ <xliff:g id="NUMBER_1">%2$d</xliff:g> წარუმატებელი მცდელობის შემდეგ მოგთხოვთ, ტაბლეტი თქვენი ელფოსტის ანგარიშის მეშვეობით განბლოკოთ.\n\n ცადეთ ხელახლა <xliff:g id="NUMBER_2">%3$d</xliff:g> წამში."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"თქვენ არასწორად დახატეთ თქვენი განბლოკვის ნიმუში <xliff:g id="NUMBER_0">%1$d</xliff:g>-ჯერ. კიდევ <xliff:g id="NUMBER_1">%2$d</xliff:g> წარუმატებელი მცდელობის შემდეგ მოგთხოვთ, ტელეფონი თქვენი ელფოსტის ანგარიშის მეშვეობით განბლოკოთ.\n\n ცადეთ ხელახლა <xliff:g id="NUMBER_2">%3$d</xliff:g> წამში."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-kk/strings.xml b/packages/SystemUI/res-product/values-kk/strings.xml
index 8185a1630711..f20baf910f72 100644
--- a/packages/SystemUI/res-product/values-kk/strings.xml
+++ b/packages/SystemUI/res-product/values-kk/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"Планшетте SIM картасы жоқ."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"Телефонда SIM картасы жоқ."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"PIN коды сәйкес келмейді"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Планшет құлпын ашуға <xliff:g id="NUMBER_0">%1$d</xliff:g> рет сәтсіз әрекет жасалды. <xliff:g id="NUMBER_1">%2$d</xliff:g> әрекет қалды. Одан кейін осы планшет бастапқы күйіне қайтарылып, оның бүкіл деректері жойылады."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Телефон құлпын ашуға <xliff:g id="NUMBER_0">%1$d</xliff:g> рет сәтсіз әрекет жасалды. <xliff:g id="NUMBER_1">%2$d</xliff:g> әрекет қалды. Одан кейін осы телефон бастапқы күйіне қайтарылып, оның бүкіл деректері жойылады."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Планшет құлпын ашуға <xliff:g id="NUMBER">%d</xliff:g> рет сәтсіз әрекет жасалды. Осы планшет бастапқы күйіне қайтарылып, оның бүкіл деректері жойылады."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Телефон құлпын ашуға <xliff:g id="NUMBER">%d</xliff:g> рет сәтсіз әрекет жасалды. Осы телефон бастапқы күйіне қайтарылып, оның бүкіл деректері жойылады."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Планшет құлпын ашуға <xliff:g id="NUMBER_0">%1$d</xliff:g> рет сәтсіз әрекет жасалды. <xliff:g id="NUMBER_1">%2$d</xliff:g> әрекет қалды. Одан кейін пайдаланушы өшіріліп, оның бүкіл деректері жойылады."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Телефон құлпын ашуға <xliff:g id="NUMBER_0">%1$d</xliff:g> рет сәтсіз әрекет жасалды. <xliff:g id="NUMBER_1">%2$d</xliff:g> әрекет қалды. Одан кейін пайдаланушы өшіріліп, оның бүкіл деректері жойылады."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Android TV құрылғысы жақын арада өшеді. Оны қосулы қалдыру үшін басыңыз."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Құрылғы жақын арада өшеді. Оны қосулы қалдыру үшін басыңыз."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Планшет құлпын ашуға <xliff:g id="NUMBER">%d</xliff:g> рет сәтсіз әрекет жасалды. Жұмыс профилі өшіріліп, оның бүкіл деректері жойылады."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Телефон құлпын ашуға <xliff:g id="NUMBER">%d</xliff:g> рет сәтсіз әрекет жасалды. Жұмыс профилі өшіріліп, оның бүкіл деректері жойылады."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Құлыпты ашу өрнегі <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате енгізілді. <xliff:g id="NUMBER_1">%2$d</xliff:g> әрекет қалды. Одан кейін планшетті есептік жазба арқылы ашу сұралады. \n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундтан кейін әрекетті қайталаңыз."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Құлыпты ашу өрнегі <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате енгізілді. <xliff:g id="NUMBER_1">%2$d</xliff:g> әрекет қалды. Одан кейін телефонды есептік жазба арқылы ашу сұралады. \n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундтан кейін әрекетті қайталаңыз."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Жылдам зарядтау үшін телефонды қайта туралаңыз."</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Сымсыз зарядтау үшін телефонды қайта туралаңыз."</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Android TV құрылғысы жақын арада өшеді. Оны қосулы ұстау үшін басыңыз."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Құрылғы жақын арада өшеді. Оны қосулы ұстау үшін басыңыз."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Планшетте SIM картасы жоқ."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Телефонда SIM картасы жоқ."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"PIN коды сәйкес келмейді"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Планшет құлпын ашуға <xliff:g id="NUMBER_0">%1$d</xliff:g> рет сәтсіз әрекет жасалды. <xliff:g id="NUMBER_1">%2$d</xliff:g> әрекет қалды. Одан кейін осы планшет бастапқы күйіне қайтарылып, оның бүкіл деректері жойылады."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Телефон құлпын ашуға <xliff:g id="NUMBER_0">%1$d</xliff:g> рет сәтсіз әрекет жасалды. <xliff:g id="NUMBER_1">%2$d</xliff:g> әрекет қалды. Одан кейін осы телефон бастапқы күйіне қайтарылып, оның бүкіл деректері жойылады."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Планшет құлпын ашуға <xliff:g id="NUMBER">%d</xliff:g> рет сәтсіз әрекет жасалды. Осы планшет бастапқы күйіне қайтарылып, оның бүкіл деректері жойылады."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Телефон құлпын ашуға <xliff:g id="NUMBER">%d</xliff:g> рет сәтсіз әрекет жасалды. Осы телефон бастапқы күйіне қайтарылып, оның бүкіл деректері жойылады."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Планшет құлпын ашуға <xliff:g id="NUMBER_0">%1$d</xliff:g> рет сәтсіз әрекет жасалды. <xliff:g id="NUMBER_1">%2$d</xliff:g> әрекет қалды. Одан кейін пайдаланушы өшіріліп, оның бүкіл деректері жойылады."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Телефон құлпын ашуға <xliff:g id="NUMBER_0">%1$d</xliff:g> рет сәтсіз әрекет жасалды. <xliff:g id="NUMBER_1">%2$d</xliff:g> әрекет қалды. Одан кейін пайдаланушы өшіріліп, оның бүкіл деректері жойылады."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Планшет құлпын ашуға <xliff:g id="NUMBER">%d</xliff:g> рет сәтсіз әрекет жасалды. Бұл пайдаланушы өшіріліп, оның бүкіл деректері жойылады."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Телефон құлпын ашуға <xliff:g id="NUMBER">%d</xliff:g> рет сәтсіз әрекет жасалды. Бұл пайдаланушы өшіріліп, оның бүкіл деректері жойылады."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Планшет құлпын ашуға <xliff:g id="NUMBER_0">%1$d</xliff:g> рет сәтсіз әрекет жасалды. <xliff:g id="NUMBER_1">%2$d</xliff:g> әрекет қалды. Одан кейін жұмыс профилі өшіріліп, оның бүкіл деректері жойылады."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Телефон құлпын ашуға <xliff:g id="NUMBER_0">%1$d</xliff:g> рет сәтсіз әрекет жасалды. <xliff:g id="NUMBER_1">%2$d</xliff:g> әрекет қалды. Одан кейін жұмыс профилі өшіріліп, оның бүкіл деректері жойылады."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Планшет құлпын ашуға <xliff:g id="NUMBER">%d</xliff:g> рет сәтсіз әрекет жасалды. Жұмыс профилі өшіріліп, оның бүкіл деректері жойылады."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Телефон құлпын ашуға <xliff:g id="NUMBER">%d</xliff:g> рет сәтсіз әрекет жасалды. Жұмыс профилі өшіріліп, оның бүкіл деректері жойылады."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Құлыпты ашу өрнегі <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате енгізілді. <xliff:g id="NUMBER_1">%2$d</xliff:g> әрекет қалды. Одан кейін планшетті есептік жазба арқылы ашу сұралады. \n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундтан кейін әрекетті қайталаңыз."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Құлыпты ашу өрнегі <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате енгізілді. <xliff:g id="NUMBER_1">%2$d</xliff:g> әрекет қалды. Одан кейін телефонды есептік жазба арқылы ашу сұралады. \n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундтан кейін әрекетті қайталаңыз."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-km/strings.xml b/packages/SystemUI/res-product/values-km/strings.xml
index 1c3c7f4cf3cc..338b4c186f5b 100644
--- a/packages/SystemUI/res-product/values-km/strings.xml
+++ b/packages/SystemUI/res-product/values-km/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"គ្មាន​ស៊ីម​កាត​នៅ​ក្នុង​ថេប្លេត​ទេ។"</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"គ្មាន​ស៊ីមកាត​នៅ​ក្នុង​ទូរសព្ទ​ទេ។"</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"កូដ PIN មិន​ត្រូវ​គ្នា​ទេ"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"អ្នក​បាន​ព្យាយាម​ដោះសោ​ថេប្លេត​នេះ​មិន​ត្រឹមត្រូវ​ចំនួន <xliff:g id="NUMBER_0">%1$d</xliff:g> ដង​ហើយ។ ប្រសិន​បើ​ការ​ព្យាយាម​ដោះ​សោ​ចំនួន <xliff:g id="NUMBER_1">%2$d</xliff:g> ដងទៀត​មិន​ទទួល​បាន​ជោគជ័យទេ ថេប្លេត​នេះ​នឹង​ត្រូវ​បាន​កំណត់​ឡើងវិញ ហើយ​វា​នឹង​លុប​ទិន្នន័យ​របស់វា​ទាំងអស់។"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"អ្នក​បាន​ព្យាយាម​ដោះសោ​ទូរសព្ទ​នេះ​មិន​ត្រឹមត្រូវ​ចំនួន <xliff:g id="NUMBER_0">%1$d</xliff:g> ដង​ហើយ។ ប្រសិន​បើ​ការ​ព្យាយាម​ដោះ​សោ​ចំនួន <xliff:g id="NUMBER_1">%2$d</xliff:g> ដងទៀត​មិន​ទទួល​បាន​ជោគជ័យទេ ទូរសព្ទ​នេះ​នឹង​ត្រូវ​បាន​កំណត់​ឡើងវិញ ហើយ​វា​នឹង​លុប​ទិន្នន័យ​របស់វា​ទាំងអស់។"</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"អ្នក​បាន​ព្យាយាម​ដោះសោ​ថេប្លេត​នេះ​មិន​ត្រឹមត្រូវ​ចំនួន <xliff:g id="NUMBER">%d</xliff:g> ដង។ ថេប្លេត​នេះ​នឹង​ត្រូវ​បាន​កំណត់​ឡើងវិញ ហើយ​វា​នឹង​លុប​ទិន្នន័យ​ទាំងអស់​របស់​វា។"</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"អ្នក​បាន​ព្យាយាម​ដោះសោ​ទូរសព្ទ​នេះ​មិន​ត្រឹមត្រូវ​ចំនួន <xliff:g id="NUMBER">%d</xliff:g> ដង​ហើយ។ ទូរសព្ទ​នេះ​នឹង​ត្រូវ​បាន​កំណត់​ឡើងវិញ ហើយ​វា​នឹង​លុប​ទិន្នន័យ​ទាំងអស់​របស់​វា។"</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"អ្នក​បាន​ព្យាយាម​ដោះ​សោ​ថេប្លេត​នេះ​មិន​ត្រឹមត្រូវ​ចំនួន <xliff:g id="NUMBER_0">%1$d</xliff:g> ដង​ហើយ។ ប្រសិន​បើ​ការ​ព្យាយាម​ដោះ​សោ​ចំនួន <xliff:g id="NUMBER_1">%2$d</xliff:g> ដងទៀត​មិន​ទទួល​បាន​ជោគជ័យទេ អ្នក​ប្រើប្រាស់​នេះនឹង​ត្រូវ​បាន​លុប ហើយ​វា​នឹង​លុប​ទិន្នន័យ​របស់​អ្នក​ប្រើប្រាស់​ទាំងអស់។"</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"អ្នក​បាន​ព្យាយាម​ដោះ​សោ​ទូរសព្ទ​នេះ​មិន​ត្រឹមត្រូវ​ចំនួន <xliff:g id="NUMBER_0">%1$d</xliff:g> ដង​ហើយ។ ប្រសិន​បើ​ការ​ព្យាយាមដោះសោ​ចំនួន <xliff:g id="NUMBER_1">%2$d</xliff:g> ដងទៀត​មិន​ទទួល​បាន​ជោគជ័យទេ អ្នក​ប្រើប្រាស់​នេះនឹង​ត្រូវ​បាន​លុប ហើយ​វា​នឹង​លុប​ទិន្នន័យ​របស់​អ្នក​ប្រើប្រាស់​ទាំងអស់។"</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"ឧបករណ៍ Android TV នឹង​បិទ​ក្នុងពេល​ឆាប់ៗនេះ សូមចុច​ប៊ូតុង​ដើម្បី​បន្ត​បើក​ឧបករណ៍។"</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"ឧបករណ៍​នឹង​បិទ​ក្នុងពេល​ឆាប់ៗនេះ សូមចុច​ដើម្បី​បន្ត​បើក​ឧបករណ៍។"</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"អ្នក​បាន​ព្យាយាម​ដោះសោ​ថេប្លេត​នេះ​មិន​ត្រឹមត្រូវ​ចំនួន <xliff:g id="NUMBER">%d</xliff:g> ដង​ហើយ។ កម្រង​ព័ត៌មាន​ការងារ​នេះ​នឹង​ត្រូវ​បាន​លុប ហើយ​វា​នឹង​លុប​ទិន្នន័យ​កម្រង​ព័ត៌មាន​ទាំងអស់។"</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"អ្នក​បាន​ព្យាយាម​ដោះសោ​ទូរសព្ទ​នេះ​មិន​ត្រឹមត្រូវ​ចំនួន <xliff:g id="NUMBER">%d</xliff:g> ដង​ហើយ។ កម្រង​ព័ត៌មាន​ការងារ​នេះ​នឹង​ត្រូវ​បាន​លុប ហើយ​វា​នឹង​លុប​ទិន្នន័យ​កម្រង​ព័ត៌មាន​ទាំងអស់។"</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"អ្នក​បាន​គូរ​លំនាំ​ដោះ​សោ​របស់​អ្នក​មិន​ត្រឹមត្រូវ​ចំនួន <xliff:g id="NUMBER_0">%1$d</xliff:g> ដង​ហើយ។ ប្រសិន​បើ​ការ​ព្យាយាម​ដោះ​សោ​ចំនួន <xliff:g id="NUMBER_1">%2$d</xliff:g> ដងទៀត​មិន​ទទួល​បាន​ជោគជ័យទេ អ្នក​នឹង​ត្រូវ​បាន​ស្នើ​ឲ្យ​ដោះ​សោ​ថេប្លេត​របស់​អ្នក​ ដោយ​ប្រើ​គណនី​អ៊ីមែល។\n\n សូមព្យាយាម​ម្ដង​ទៀត​ក្នុង​រយៈ​ពេល <xliff:g id="NUMBER_2">%3$d</xliff:g> វិនាទី​ទៀត។"</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"អ្នក​បាន​គូរ​លំនាំ​ដោះ​សោ​របស់​អ្នក​មិន​ត្រឹមត្រូវ​ចំនួន <xliff:g id="NUMBER_0">%1$d</xliff:g> ដង​ហើយ។ ប្រសិន​បើ​ការ​ព្យាយាម​ដោះ​សោ​ចំនួន <xliff:g id="NUMBER_1">%2$d</xliff:g> ដងទៀត​មិន​ទទួល​បាន​ជោគជ័យទេ អ្នក​នឹង​ត្រូវ​បាន​ស្នើ​ឲ្យ​ដោះ​សោ​ទូរសព្ទ​របស់​អ្នក​ ដោយ​ប្រើ​គណនី​អ៊ីមែល។\n\n សូម​ព្យាយាម​ម្ដង​ទៀត​ក្នុង​រយៈ​ពេល <xliff:g id="NUMBER_2">%3$d</xliff:g> វិនាទី​ទៀត។"</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"ដាក់ទូរសព្ទ​ឱ្យត្រូវកន្លែង ដើម្បីសាកថ្ម​រហ័សជាងមុន"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"ដាក់ទូរសព្ទ​ឱ្យត្រូវកន្លែង ដើម្បីសាកថ្មដោយឥតប្រើខ្សែ"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"ឧបករណ៍ Android TV នឹង​បិទ​ក្នុងពេល​ឆាប់ៗនេះ សូមចុច​ប៊ូតុង​ដើម្បី​បន្ត​បើក​ឧបករណ៍។"</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"ឧបករណ៍​នឹង​បិទ​ក្នុងពេល​ឆាប់ៗនេះ សូមចុច​ដើម្បី​បន្ត​បើក​ឧបករណ៍។"</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"គ្មាន​ស៊ីម​កាត​នៅ​ក្នុង​ថេប្លេត​ទេ។"</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"គ្មាន​ស៊ីមកាត​នៅ​ក្នុង​ទូរសព្ទ​ទេ។"</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"កូដ PIN មិន​ត្រូវ​គ្នា​ទេ"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"អ្នក​បាន​ព្យាយាម​ដោះសោ​ថេប្លេត​នេះ​មិន​ត្រឹមត្រូវ​ចំនួន <xliff:g id="NUMBER_0">%1$d</xliff:g> ដង​ហើយ។ បន្ទាប់ពីមាន​ការព្យាយាម​ដោះសោ​ចំនួន <xliff:g id="NUMBER_1">%2$d</xliff:g> ដងទៀត​មិន​ទទួល​បាន​ជោគជ័យ ថេប្លេត​នេះ​នឹង​ត្រូវ​បាន​កំណត់​ឡើងវិញ ហើយ​វា​នឹង​លុប​ទិន្នន័យ​ទាំងអស់​របស់ថេប្លេត​នេះ។"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"អ្នក​បាន​ព្យាយាម​ដោះសោ​ទូរសព្ទ​នេះ​មិន​ត្រឹមត្រូវ​ចំនួន <xliff:g id="NUMBER_0">%1$d</xliff:g> ដង​ហើយ។ បន្ទាប់ពីមាន​ការ​ព្យាយាម​ដោះ​សោ​ចំនួន <xliff:g id="NUMBER_1">%2$d</xliff:g> ដងទៀត​មិន​ទទួល​បាន​ជោគជ័យ ទូរសព្ទ​នេះ​នឹង​ត្រូវ​បាន​កំណត់​ឡើងវិញ ហើយ​វា​នឹង​លុប​ទិន្នន័យ​ទាំងអស់​របស់ទូរសព្ទនេះ។"</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"អ្នក​បាន​ព្យាយាម​ដោះសោ​ថេប្លេត​នេះ​មិន​ត្រឹមត្រូវ​ចំនួន <xliff:g id="NUMBER">%d</xliff:g> ដងហើយ។ ថេប្លេត​នេះ​នឹង​ត្រូវ​បាន​កំណត់​ឡើងវិញ ហើយ​វា​នឹង​លុប​ទិន្នន័យ​ទាំងអស់​របស់ថេប្លេតនេះ។"</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"អ្នក​បាន​ព្យាយាម​ដោះសោ​ទូរសព្ទ​នេះ​មិន​ត្រឹមត្រូវ​ចំនួន <xliff:g id="NUMBER">%d</xliff:g> ដង​ហើយ។ ទូរសព្ទ​នេះ​នឹង​ត្រូវ​បាន​កំណត់​ឡើងវិញ ហើយ​វា​នឹង​លុប​ទិន្នន័យ​ទាំងអស់​របស់ទូរសព្ទនេះ។"</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"អ្នក​បាន​ព្យាយាម​ដោះ​សោ​ថេប្លេត​នេះ​មិន​ត្រឹមត្រូវ​ចំនួន <xliff:g id="NUMBER_0">%1$d</xliff:g> ដង​ហើយ។ បន្ទាប់ពីមាន​ការ​ព្យាយាម​ដោះ​សោ​ចំនួន <xliff:g id="NUMBER_1">%2$d</xliff:g> ដងទៀត​មិន​ទទួល​បាន​ជោគជ័យ អ្នក​ប្រើប្រាស់​នេះនឹង​ត្រូវ​បាន​លុប ហើយ​វា​នឹង​លុប​ទិន្នន័យទាំងអស់​របស់អ្នក​ប្រើប្រាស់នេះ។"</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"អ្នក​បាន​ព្យាយាម​ដោះ​សោ​ទូរសព្ទ​នេះ​មិន​ត្រឹមត្រូវ​ចំនួន <xliff:g id="NUMBER_0">%1$d</xliff:g> ដង​ហើយ។ បន្ទាប់ពីមាន​ការព្យាយាមដោះសោ​ចំនួន <xliff:g id="NUMBER_1">%2$d</xliff:g> ដងទៀត​មិន​ទទួល​បាន​ជោគជ័យ អ្នក​ប្រើប្រាស់​នេះនឹង​ត្រូវ​បាន​លុប ហើយ​វា​នឹង​លុប​ទិន្នន័យទាំងអស់​របស់​អ្នក​ប្រើប្រាស់​នេះ។"</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"អ្នក​បាន​ព្យាយាម​ដោះសោ​ថេប្លេត​នេះ​មិន​ត្រឹមត្រូវ​ចំនួន <xliff:g id="NUMBER">%d</xliff:g> ដង​ហើយ។ អ្នក​ប្រើប្រាស់​នេះ​នឹង​ត្រូវ​បាន​លុប ហើយ​វា​នឹង​លុប​ទិន្នន័យ​ទាំងអស់​របស់​អ្នក​ប្រើប្រាស់​នេះ។"</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"អ្នក​បាន​ព្យាយាម​ដោះសោ​ទូរសព្ទ​នេះ​មិន​ត្រឹមត្រូវ​ចំនួន <xliff:g id="NUMBER">%d</xliff:g> ដង​ហើយ។ អ្នក​ប្រើប្រាស់​នេះ​នឹង​ត្រូវ​បាន​លុប ហើយ​វា​នឹង​លុប​ទិន្នន័យ​ទាំងអស់​របស់អ្នកប្រើប្រាស់​នេះ។"</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"អ្នក​បាន​ព្យាយាម​ដោះ​សោ​ថេប្លេត​នេះ​មិន​ត្រឹមត្រូវ​ចំនួន <xliff:g id="NUMBER_0">%1$d</xliff:g> ដង​ហើយ។ បន្ទាប់ពីមានការ​ព្យាយាមដោះសោ​ចំនួន <xliff:g id="NUMBER_1">%2$d</xliff:g> ដងទៀត​មិន​ទទួល​បាន​ជោគជ័យ កម្រង​ព័ត៌មាន​ការងារ​នេះ​នឹង​ត្រូវ​បាន​លុប ហើយ​វា​នឹង​លុប​ទិន្នន័យ​កម្រងព័ត៌មាន​ទាំងអស់។"</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"អ្នក​បាន​ព្យាយាម​ដោះ​សោ​ទូរសព្ទ​នេះ​មិន​ត្រឹមត្រូវ​ចំនួន <xliff:g id="NUMBER_0">%1$d</xliff:g> ដង​ហើយ។ បន្ទាប់ពីមានការ​ព្យាយាមដោះសោ​ចំនួន <xliff:g id="NUMBER_1">%2$d</xliff:g> ដងទៀត​មិន​ទទួល​បាន​ជោគជ័យ កម្រង​ព័ត៌មាន​ការងារ​នេះ​នឹង​ត្រូវ​បាន​លុប ហើយ​វា​នឹង​លុប​ទិន្នន័យ​កម្រងព័ត៌មាន​ទាំងអស់។"</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"អ្នក​បាន​ព្យាយាម​ដោះសោ​ថេប្លេត​នេះ​មិន​ត្រឹមត្រូវ​ចំនួន <xliff:g id="NUMBER">%d</xliff:g> ដង​ហើយ។ កម្រង​ព័ត៌មាន​ការងារ​នេះ​នឹង​ត្រូវ​បាន​លុប ហើយ​វា​នឹង​លុប​ទិន្នន័យ​កម្រង​ព័ត៌មាន​ទាំងអស់។"</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"អ្នក​បាន​ព្យាយាម​ដោះសោ​ទូរសព្ទ​នេះ​មិន​ត្រឹមត្រូវ​ចំនួន <xliff:g id="NUMBER">%d</xliff:g> ដង​ហើយ។ កម្រង​ព័ត៌មាន​ការងារ​នេះ​នឹង​ត្រូវ​បាន​លុប ហើយ​វា​នឹង​លុប​ទិន្នន័យ​កម្រង​ព័ត៌មាន​ទាំងអស់។"</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"អ្នក​បាន​គូរ​លំនាំ​ដោះ​សោ​របស់​អ្នក​មិន​ត្រឹមត្រូវ​ចំនួន <xliff:g id="NUMBER_0">%1$d</xliff:g> ដង​ហើយ។ បន្ទាប់ពីមានការ​ព្យាយាម​ដោះ​សោ​ចំនួន <xliff:g id="NUMBER_1">%2$d</xliff:g> ដងទៀត​មិន​ទទួល​បាន​ជោគជ័យ អ្នក​នឹង​ត្រូវ​បាន​ស្នើ​ឱ្យ​ដោះ​សោ​ថេប្លេត​របស់​អ្នក​ ដោយ​ប្រើ​គណនី​អ៊ីមែល។\n\n សូមព្យាយាម​ម្ដង​ទៀត​ក្នុង​រយៈ​ពេល <xliff:g id="NUMBER_2">%3$d</xliff:g> វិនាទី​ទៀត។"</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"អ្នកបានគូរលំនាំ​ដោះសោ​របស់អ្នក​មិន​ត្រឹមត្រូវចំនួន <xliff:g id="NUMBER_0">%1$d</xliff:g> ដងហើយ។ បន្ទាប់ពីមាន​ការព្យាយាម​ដោះសោចំនួន <xliff:g id="NUMBER_1">%2$d</xliff:g> ដងទៀតមិនទទួលបាន​ជោគជ័យ អ្នកនឹង​ត្រូវបាន​ស្នើឱ្យ​ដោះសោ​ទូរសព្ទ​របស់​អ្នកដោយ​ប្រើគណនី​អ៊ីមែល។\n\n សូមព្យាយាម​ម្ដងទៀតក្នុង​រយៈពេល <xliff:g id="NUMBER_2">%3$d</xliff:g> វិនាទីទៀត។"</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-kn/strings.xml b/packages/SystemUI/res-product/values-kn/strings.xml
index 06644f46ea1a..c10d5dc59f16 100644
--- a/packages/SystemUI/res-product/values-kn/strings.xml
+++ b/packages/SystemUI/res-product/values-kn/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"ಟ್ಯಾಬ್ಲೆಟ್‌ನಲ್ಲಿ ಸಿಮ್‌ ಕಾರ್ಡ್ ಇಲ್ಲ."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"ಪೋನ್‌ನಲ್ಲಿ ಯಾವುದೇ ಸಿಮ್‌ ಕಾರ್ಡ್ ಇಲ್ಲ."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"ಪಿನ್‌ ಕೋಡ್‍ಗಳು ಹೊಂದಾಣಿಕೆಯಾಗುತ್ತಿಲ್ಲ"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"ಟ್ಯಾಬ್ಲೆಟ್ ಅನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡಲು ನೀವು <xliff:g id="NUMBER_0">%1$d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಪ್ರಯತ್ನಿಸಿದ್ದೀರಿ. <xliff:g id="NUMBER_1">%2$d</xliff:g> ಕ್ಕೂ ಹೆಚ್ಚಿನ ವಿಫಲ ಪ್ರಯತ್ನಗಳ ನಂತರ, ಈ ಟ್ಯಾಬ್ಲೆಟ್ ಅನ್ನು ಮರುಹೊಂದಿಸಲಾಗುತ್ತದೆ, ಇದು ಎಲ್ಲ ಡೇಟಾವನ್ನು ಅಳಿಸುತ್ತದೆ."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"ಫೋನ್ ಅನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡಲು ನೀವು <xliff:g id="NUMBER_0">%1$d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಪ್ರಯತ್ನಿಸಿದ್ದೀರಿ. <xliff:g id="NUMBER_1">%2$d</xliff:g> ಕ್ಕೂ ಹೆಚ್ಚಿನ ವಿಫಲ ಪ್ರಯತ್ನಗಳ ನಂತರ, ಈ ಫೋನ್ ಅನ್ನು ಮರುಹೊಂದಿಸಲಾಗುತ್ತದೆ, ಇದು ಎಲ್ಲ ಡೇಟಾವನ್ನು ಅಳಿಸುತ್ತದೆ."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"ಟ್ಯಾಬ್ಲೆಟ್ ಅನ್‌ಲಾಕ್ ಮಾಡಲು ನೀವು <xliff:g id="NUMBER">%d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಪ್ರಯತ್ನಿಸಿದ್ದೀರಿ. ಈ ಟ್ಯಾಬ್ಲೆಟ್ ಅನ್ನು ಮರುಹೊಂದಿಸಲಾಗುತ್ತದೆ, ಇದು ಅದರ ಎಲ್ಲ ಡೇಟಾವನ್ನು ಅಳಿಸುತ್ತದೆ."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"ಫೋನ್ ಅನ್‌ಲಾಕ್ ಮಾಡಲು ನೀವು <xliff:g id="NUMBER">%d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಪ್ರಯತ್ನಿಸಿದ್ದೀರಿ. ಈ ಫೋನ್ ಅನ್ನು ಮರುಹೊಂದಿಸಲಾಗುತ್ತದೆ, ಇದು ಅದರ ಎಲ್ಲ ಡೇಟಾವನ್ನು ಅಳಿಸುತ್ತದೆ."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"ಟ್ಯಾಬ್ಲೆಟ್ ಅನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡಲು ನೀವು <xliff:g id="NUMBER_0">%1$d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಪ್ರಯತ್ನಿಸಿದ್ದೀರಿ. <xliff:g id="NUMBER_1">%2$d</xliff:g> ಕ್ಕೂ ಹೆಚ್ಚಿನ ವಿಫಲ ಪ್ರಯತ್ನಗಳ ನಂತರ, ಈ ಬಳಕೆದಾರರನ್ನು ತೆಗೆದುಹಾಕಲಾಗುತ್ತದೆ, ಇದು ಬಳಕೆದಾರರ ಎಲ್ಲ ಡೇಟಾವನ್ನು ಅಳಿಸುತ್ತದೆ."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"ಫೋನ್ ಅನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡಲು ನೀವು <xliff:g id="NUMBER_0">%1$d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಪ್ರಯತ್ನಿಸಿದ್ದೀರಿ. <xliff:g id="NUMBER_1">%2$d</xliff:g> ಕ್ಕೂ ಹೆಚ್ಚಿನ ವಿಫಲ ಪ್ರಯತ್ನಗಳ ನಂತರ, ಈ ಬಳಕೆದಾರರನ್ನು ತೆಗೆದುಹಾಕಲಾಗುತ್ತದೆ, ಇದು ಬಳಕೆದಾರರ ಎಲ್ಲ ಡೇಟಾವನ್ನು ಅಳಿಸುತ್ತದೆ."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"ಈ Android TV ಸಾಧನವು ಶೀಘ್ರವೇ ಆಫ್ ಆಗುತ್ತದೆ; ಇದನ್ನು ಆನ್‌ನಲ್ಲಿಡಲು ಬಟನ್ ಅನ್ನು ಒತ್ತಿರಿ."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"ಈ ಸಾಧನವು ಶೀಘ್ರವೇ ಆಫ್ ಆಗುತ್ತದೆ; ಇದನ್ನು ಆನ್‌ನಲ್ಲಿಡಲು ಒತ್ತಿರಿ."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"ಟ್ಯಾಬ್ಲೆಟ್ ಅನ್‌ಲಾಕ್ ಮಾಡಲು ನೀವು <xliff:g id="NUMBER">%d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಪ್ರಯತ್ನಿಸಿದ್ದೀರಿ. ಕೆಲಸದ ಪ್ರೊಫೈಲ್ ಅನ್ನು ತೆಗೆದುಹಾಕಲಾಗುತ್ತದೆ, ಇದು ಎಲ್ಲ ಪ್ರೊಫೈಲ್ ಡೇಟಾವನ್ನು ಅಳಿಸುತ್ತದೆ."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"ಫೋನ್ ಅನ್‌ಲಾಕ್ ಮಾಡಲು ನೀವು <xliff:g id="NUMBER">%d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಪ್ರಯತ್ನಿಸಿದ್ದೀರಿ. ಕೆಲಸದ ಪ್ರೊಫೈಲ್ ಅನ್ನು ತೆಗೆದುಹಾಕಲಾಗುತ್ತದೆ, ಇದು ಎಲ್ಲ ಪ್ರೊಫೈಲ್ ಡೇಟಾವನ್ನು ಅಳಿಸುತ್ತದೆ."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"ನಿಮ್ಮ ಅನ್‍‍ಲಾಕ್ ಪ್ಯಾಟರ್ನ್ ಅನ್ನು ನೀವು <xliff:g id="NUMBER_0">%1$d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಎಳೆದಿದ್ದೀರಿ. <xliff:g id="NUMBER_1">%2$d</xliff:g> ಕ್ಕೂ ಹೆಚ್ಚಿನ ವಿಫಲ ಪ್ರಯತ್ನಗಳ ಬಳಿಕ, ನಿಮ್ಮ ಇಮೇಲ್ ಖಾತೆಯನ್ನು ಬಳಸಿ ಟ್ಯಾಬ್ಲೆಟ್ ಅನ್‌ಲಾಕ್ ಮಾಡುವಂತೆ ನಿಮ್ಮಲ್ಲಿ ಕೇಳಿಕೊಳ್ಳಲಾಗುತ್ತದೆ.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ಸೆಕೆಂಡುಗಳಲ್ಲಿ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"ನಿಮ್ಮ ಅನ್‍‍ಲಾಕ್ ಪ್ಯಾಟರ್ನ್ ಅನ್ನು ನೀವು <xliff:g id="NUMBER_0">%1$d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಎಳೆದಿದ್ದೀರಿ. <xliff:g id="NUMBER_1">%2$d</xliff:g> ಕ್ಕೂ ಹೆಚ್ಚಿನ ವಿಫಲ ಪ್ರಯತ್ನಗಳ ಬಳಿಕ, ನಿಮ್ಮ ಇಮೇಲ್ ಖಾತೆಯನ್ನು ಬಳಸಿ ಫೋನ್ ಅನ್‌ಲಾಕ್ ಮಾಡುವಂತೆ ನಿಮ್ಮಲ್ಲಿ ಕೇಳಿಕೊಳ್ಳಲಾಗುತ್ತದೆ.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ಸೆಕೆಂಡುಗಳಲ್ಲಿ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"ವೇಗವಾಗಿ ಚಾರ್ಜ್ ಮಾಡಲು, ನಿಮ್ಮ ಫೋನ್‌‌ನ ಸ್ಥಾನವನ್ನು ಮರುಹೊಂದಿಸಿ"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"ವೈರ್‌ಲೆಸ್ ಆಗಿ ಚಾರ್ಜ್ ಮಾಡಲು, ನಿಮ್ಮ ಫೋನ್ ಸ್ಥಾನವನ್ನು ಮರುಹೊಂದಿಸಿ"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Android TV ಸಾಧನವು ಶೀಘ್ರವೇ ಆಫ್ ಆಗುತ್ತದೆ; ಇದನ್ನು ಆನ್‌ನಲ್ಲಿಡಲು ಬಟನ್ ಅನ್ನು ಒತ್ತಿರಿ."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"ಸಾಧನವು ಶೀಘ್ರವೇ ಆಫ್ ಆಗುತ್ತದೆ; ಇದನ್ನು ಆನ್‌ನಲ್ಲಿಡಲು ಒತ್ತಿರಿ."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"ಟ್ಯಾಬ್ಲೆಟ್‌ನಲ್ಲಿ ಸಿಮ್‌ ಕಾರ್ಡ್ ಇಲ್ಲ."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"ಪೋನ್‌ನಲ್ಲಿ ಸಿಮ್‌ ಕಾರ್ಡ್ ಇಲ್ಲ."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"ಪಿನ್‌ ಕೋಡ್‍ಗಳು ಹೊಂದಾಣಿಕೆಯಾಗುತ್ತಿಲ್ಲ"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"ಟ್ಯಾಬ್ಲೆಟ್ ಅನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡಲು ನೀವು <xliff:g id="NUMBER_0">%1$d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಪ್ರಯತ್ನಿಸಿದ್ದೀರಿ. <xliff:g id="NUMBER_1">%2$d</xliff:g> ಕ್ಕೂ ಹೆಚ್ಚಿನ ವಿಫಲ ಪ್ರಯತ್ನಗಳ ನಂತರ, ಈ ಟ್ಯಾಬ್ಲೆಟ್ ಅನ್ನು ಮರುಹೊಂದಿಸಲಾಗುತ್ತದೆ, ಇದು ಅದಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಎಲ್ಲಾ ಡೇಟಾವನ್ನು ಅಳಿಸುತ್ತದೆ."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"ಫೋನ್ ಅನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡಲು ನೀವು <xliff:g id="NUMBER_0">%1$d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಪ್ರಯತ್ನಿಸಿದ್ದೀರಿ. <xliff:g id="NUMBER_1">%2$d</xliff:g> ಕ್ಕೂ ಹೆಚ್ಚಿನ ವಿಫಲ ಪ್ರಯತ್ನಗಳ ನಂತರ, ಈ ಫೋನ್ ಅನ್ನು ಮರುಹೊಂದಿಸಲಾಗುತ್ತದೆ, ಇದು ಅದಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಎಲ್ಲಾ ಡೇಟಾವನ್ನು ಅಳಿಸುತ್ತದೆ."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"ಟ್ಯಾಬ್ಲೆಟ್ ಅನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡಲು ನೀವು <xliff:g id="NUMBER">%d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಪ್ರಯತ್ನಿಸಿದ್ದೀರಿ. ಈ ಟ್ಯಾಬ್ಲೆಟ್ ಅನ್ನು ಮರುಹೊಂದಿಸಲಾಗುತ್ತದೆ, ಇದು ಅದಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಎಲ್ಲಾ ಡೇಟಾವನ್ನು ಅಳಿಸುತ್ತದೆ."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"ಫೋನ್ ಅನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡಲು ನೀವು <xliff:g id="NUMBER">%d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಪ್ರಯತ್ನಿಸಿದ್ದೀರಿ. ಈ ಫೋನ್ ಅನ್ನು ಮರುಹೊಂದಿಸಲಾಗುತ್ತದೆ, ಇದು ಅದಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಎಲ್ಲಾ ಡೇಟಾವನ್ನು ಅಳಿಸುತ್ತದೆ."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"ಟ್ಯಾಬ್ಲೆಟ್ ಅನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡಲು ನೀವು <xliff:g id="NUMBER_0">%1$d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಪ್ರಯತ್ನಿಸಿದ್ದೀರಿ. <xliff:g id="NUMBER_1">%2$d</xliff:g> ಕ್ಕೂ ಹೆಚ್ಚಿನ ವಿಫಲ ಪ್ರಯತ್ನಗಳ ನಂತರ, ಈ ಬಳಕೆದಾರರನ್ನು ತೆಗೆದುಹಾಕಲಾಗುತ್ತದೆ, ಇದು ಬಳಕೆದಾರರ ಎಲ್ಲಾ ಡೇಟಾವನ್ನು ಅಳಿಸುತ್ತದೆ."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"ಫೋನ್ ಅನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡಲು ನೀವು <xliff:g id="NUMBER_0">%1$d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಪ್ರಯತ್ನಿಸಿದ್ದೀರಿ. <xliff:g id="NUMBER_1">%2$d</xliff:g> ಕ್ಕೂ ಹೆಚ್ಚಿನ ವಿಫಲ ಪ್ರಯತ್ನಗಳ ನಂತರ, ಈ ಬಳಕೆದಾರರನ್ನು ತೆಗೆದುಹಾಕಲಾಗುತ್ತದೆ, ಇದು ಬಳಕೆದಾರರ ಎಲ್ಲಾ ಡೇಟಾವನ್ನು ಅಳಿಸುತ್ತದೆ."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"ಟ್ಯಾಬ್ಲೆಟ್ ಅನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡಲು ನೀವು <xliff:g id="NUMBER">%d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಪ್ರಯತ್ನಿಸಿದ್ದೀರಿ. ಈ ಬಳಕೆದಾರರನ್ನು ತೆಗೆದುಹಾಕಲಾಗುತ್ತದೆ, ಇದು ಬಳಕೆದಾರರ ಎಲ್ಲಾ ಡೇಟಾವನ್ನು ಅಳಿಸುತ್ತದೆ."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"ಫೋನ್ ಅನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡಲು ನೀವು <xliff:g id="NUMBER">%d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಪ್ರಯತ್ನಿಸಿದ್ದೀರಿ. ಈ ಬಳಕೆದಾರರನ್ನು ತೆಗೆದುಹಾಕಲಾಗುತ್ತದೆ, ಇದು ಬಳಕೆದಾರರ ಎಲ್ಲಾ ಡೇಟಾವನ್ನು ಅಳಿಸುತ್ತದೆ."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"ಟ್ಯಾಬ್ಲೆಟ್ ಅನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡಲು ನೀವು <xliff:g id="NUMBER_0">%1$d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಪ್ರಯತ್ನಿಸಿದ್ದೀರಿ. <xliff:g id="NUMBER_1">%2$d</xliff:g> ಕ್ಕೂ ಹೆಚ್ಚಿನ ವಿಫಲ ಪ್ರಯತ್ನಗಳ ನಂತರ, ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್ ಅನ್ನು ತೆಗೆದುಹಾಕಲಾಗುತ್ತದೆ, ಇದು ಪ್ರೊಫೈಲ್‌ನ ಎಲ್ಲಾ ಡೇಟಾವನ್ನು ಅಳಿಸುತ್ತದೆ."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"ಫೋನ್ ಅನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡಲು ನೀವು <xliff:g id="NUMBER_0">%1$d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಪ್ರಯತ್ನಿಸಿದ್ದೀರಿ. <xliff:g id="NUMBER_1">%2$d</xliff:g> ಕ್ಕೂ ಹೆಚ್ಚಿನ ವಿಫಲ ಪ್ರಯತ್ನಗಳ ನಂತರ, ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್ ಅನ್ನು ತೆಗೆದುಹಾಕಲಾಗುತ್ತದೆ, ಇದು ಪ್ರೊಫೈಲ್‌ನ ಎಲ್ಲಾ ಡೇಟಾವನ್ನು ಅಳಿಸುತ್ತದೆ."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"ಟ್ಯಾಬ್ಲೆಟ್ ಅನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡಲು ನೀವು <xliff:g id="NUMBER">%d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಪ್ರಯತ್ನಿಸಿದ್ದೀರಿ. ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್ ಅನ್ನು ತೆಗೆದುಹಾಕಲಾಗುತ್ತದೆ, ಇದು ಎಲ್ಲಾ ಪ್ರೊಫೈಲ್ ಡೇಟಾವನ್ನು ಅಳಿಸುತ್ತದೆ."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"ಫೋನ್ ಅನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡಲು ನೀವು <xliff:g id="NUMBER">%d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಪ್ರಯತ್ನಿಸಿದ್ದೀರಿ. ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್ ಅನ್ನು ತೆಗೆದುಹಾಕಲಾಗುತ್ತದೆ, ಇದು ಪ್ರೊಫೈಲ್‌ನ ಎಲ್ಲಾ ಡೇಟಾವನ್ನು ಅಳಿಸುತ್ತದೆ."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"ನಿಮ್ಮ ಅನ್‍‍ಲಾಕ್ ಪ್ಯಾಟರ್ನ್ ಅನ್ನು ನೀವು <xliff:g id="NUMBER_0">%1$d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಡ್ರಾ ಮಾಡಿರುವಿರಿ. <xliff:g id="NUMBER_1">%2$d</xliff:g> ಕ್ಕೂ ಹೆಚ್ಚಿನ ವಿಫಲ ಪ್ರಯತ್ನಗಳ ಬಳಿಕ, ನಿಮ್ಮ ಇಮೇಲ್ ಖಾತೆಯನ್ನು ಬಳಸಿ ಟ್ಯಾಬ್ಲೆಟ್ ಅನ್‌ಲಾಕ್ ಮಾಡಲು ನಿಮ್ಮನ್ನು ಕೇಳಲಾಗುತ್ತದೆ.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ಸೆಕೆಂಡ್‌ಗಳಲ್ಲಿ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"ನಿಮ್ಮ ಅನ್‍‍ಲಾಕ್ ಪ್ಯಾಟರ್ನ್ ಅನ್ನು ನೀವು <xliff:g id="NUMBER_0">%1$d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಡ್ರಾ ಮಾಡಿರುವಿರಿ. <xliff:g id="NUMBER_1">%2$d</xliff:g> ಕ್ಕೂ ಹೆಚ್ಚಿನ ವಿಫಲ ಪ್ರಯತ್ನಗಳ ಬಳಿಕ, ಇಮೇಲ್ ಖಾತೆಯನ್ನು ಬಳಸಿ ನಿಮ್ಮ ಫೋನ್ ಅನ್‌ಲಾಕ್ ಮಾಡಲು ನಿಮ್ಮನ್ನು ಕೇಳಲಾಗುತ್ತದೆ.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ಸೆಕೆಂಡ್‌ಗಳಲ್ಲಿ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-ko/strings.xml b/packages/SystemUI/res-product/values-ko/strings.xml
index 1d5152e98bca..c9b9dd40b067 100644
--- a/packages/SystemUI/res-product/values-ko/strings.xml
+++ b/packages/SystemUI/res-product/values-ko/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"태블릿에 SIM 카드가 없습니다."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"휴대전화에 SIM 카드가 없습니다."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"PIN 코드가 일치하지 않음"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"태블릿 잠금 해제에 <xliff:g id="NUMBER_0">%1$d</xliff:g>번 실패했습니다. <xliff:g id="NUMBER_1">%2$d</xliff:g>번 더 실패하면 태블릿이 재설정되며 모든 데이터가 삭제됩니다."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"휴대전화 잠금 해제에 <xliff:g id="NUMBER_0">%1$d</xliff:g>번 실패했습니다. <xliff:g id="NUMBER_1">%2$d</xliff:g>번 더 실패하면 휴대전화가 재설정되며 모든 데이터가 삭제됩니다."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"태블릿 잠금 해제에 <xliff:g id="NUMBER">%d</xliff:g>번 실패했습니다. 태블릿이 재설정되며 모든 데이터가 삭제됩니다."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"휴대전화 잠금 해제에 <xliff:g id="NUMBER">%d</xliff:g>번 실패했습니다. 휴대전화가 재설정되며 모든 데이터가 삭제됩니다."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"태블릿 잠금 해제에 <xliff:g id="NUMBER_0">%1$d</xliff:g>번 실패했습니다. <xliff:g id="NUMBER_1">%2$d</xliff:g>번 더 실패하면 이 사용자와 모든 사용자 데이터가 삭제됩니다."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"휴대전화 잠금 해제에 <xliff:g id="NUMBER_0">%1$d</xliff:g>번 실패했습니다. <xliff:g id="NUMBER_1">%2$d</xliff:g>번 더 실패하면 이 사용자와 모든 사용자 데이터가 삭제됩니다."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Android TV가 곧 꺼집니다. 계속 켜 두려면 버튼을 누르세요."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"기기가 곧 꺼집니다. 계속 켜 두려면 누르세요."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"태블릿 잠금 해제에 <xliff:g id="NUMBER">%d</xliff:g>번 실패했습니다. 직장 프로필과 모든 프로필 데이터가 삭제됩니다."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"휴대전화 잠금 해제에 <xliff:g id="NUMBER">%d</xliff:g>번 실패했습니다. 직장 프로필과 모든 프로필 데이터가 삭제됩니다."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"잠금해제 패턴을 <xliff:g id="NUMBER_0">%1$d</xliff:g>번 잘못 그렸습니다. <xliff:g id="NUMBER_1">%2$d</xliff:g>번 더 실패하면 이메일 계정을 사용하여 태블릿을 잠금 해제해야 합니다.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g>초 후에 다시 시도해 주세요."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"잠금해제 패턴을 <xliff:g id="NUMBER_0">%1$d</xliff:g>번 잘못 그렸습니다. <xliff:g id="NUMBER_1">%2$d</xliff:g>번 더 실패하면 이메일 계정을 사용하여 휴대전화를 잠금 해제해야 합니다.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g>초 후에 다시 시도해 주세요."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"더 빠르게 충전하려면 스마트폰을 다시 배치하세요."</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"무선으로 충전하려면 스마트폰을 다시 배치하세요."</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Android TV가 곧 꺼집니다. 계속 켜 두려면 버튼을 누르세요."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"기기가 곧 꺼집니다. 계속 켜 두려면 누르세요."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"태블릿에 SIM 카드가 없습니다."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"휴대전화에 SIM 카드가 없습니다."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"PIN 코드가 일치하지 않음"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"태블릿 잠금 해제에 <xliff:g id="NUMBER_0">%1$d</xliff:g>번 실패했습니다. <xliff:g id="NUMBER_1">%2$d</xliff:g>번 더 실패하면 태블릿이 초기화되며 모든 데이터가 삭제됩니다."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"휴대전화 잠금 해제에 <xliff:g id="NUMBER_0">%1$d</xliff:g>번 실패했습니다. <xliff:g id="NUMBER_1">%2$d</xliff:g>번 더 실패하면 휴대전화가 초기화되며 모든 데이터가 삭제됩니다."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"태블릿 잠금 해제에 <xliff:g id="NUMBER">%d</xliff:g>번 실패했습니다. 태블릿이 재설정되며 모든 데이터가 삭제됩니다."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"휴대전화 잠금 해제에 <xliff:g id="NUMBER">%d</xliff:g>번 실패했습니다. 휴대전화가 초기화되며 모든 데이터가 삭제됩니다."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"태블릿 잠금 해제에 <xliff:g id="NUMBER_0">%1$d</xliff:g>번 실패했습니다. <xliff:g id="NUMBER_1">%2$d</xliff:g>번 더 실패하면 이 사용자와 모든 사용자 데이터가 삭제됩니다."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"휴대전화 잠금 해제에 <xliff:g id="NUMBER_0">%1$d</xliff:g>번 실패했습니다. <xliff:g id="NUMBER_1">%2$d</xliff:g>번 더 실패하면 이 사용자와 모든 사용자 데이터가 삭제됩니다."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"태블릿 잠금 해제에 <xliff:g id="NUMBER">%d</xliff:g>번 실패했습니다. 이 사용자와 모든 사용자 데이터가 삭제됩니다."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"휴대전화 잠금 해제에 <xliff:g id="NUMBER">%d</xliff:g>번 실패했습니다. 이 사용자와 모든 사용자 데이터가 삭제됩니다."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"태블릿 잠금 해제에 <xliff:g id="NUMBER_0">%1$d</xliff:g>번 실패했습니다. <xliff:g id="NUMBER_1">%2$d</xliff:g>번 더 실패하면 직장 프로필과 모든 프로필 데이터가 삭제됩니다."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"휴대전화 잠금 해제에 <xliff:g id="NUMBER_0">%1$d</xliff:g>번 실패했습니다. <xliff:g id="NUMBER_1">%2$d</xliff:g>번 더 실패하면 직장 프로필과 모든 프로필 데이터가 삭제됩니다."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"태블릿 잠금 해제에 <xliff:g id="NUMBER">%d</xliff:g>번 실패했습니다. 직장 프로필과 모든 프로필 데이터가 삭제됩니다."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"휴대전화 잠금 해제에 <xliff:g id="NUMBER">%d</xliff:g>번 실패했습니다. 직장 프로필과 모든 프로필 데이터가 삭제됩니다."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"잠금 해제 패턴을 <xliff:g id="NUMBER_0">%1$d</xliff:g>회 잘못 그렸습니다. <xliff:g id="NUMBER_1">%2$d</xliff:g>회 더 실패하면 이메일 계정을 사용하여 태블릿을 잠금 해제해야 합니다.\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g>초 후에 다시 시도해 주세요."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"잠금 해제 패턴을 <xliff:g id="NUMBER_0">%1$d</xliff:g>회 잘못 그렸습니다. <xliff:g id="NUMBER_1">%2$d</xliff:g>회 더 실패하면 이메일 계정을 사용하여 휴대전화를 잠금 해제해야 합니다.\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g>초 후에 다시 시도해 주세요."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-ky/strings.xml b/packages/SystemUI/res-product/values-ky/strings.xml
index bc4ffa0ea523..8d96cb26bf30 100644
--- a/packages/SystemUI/res-product/values-ky/strings.xml
+++ b/packages/SystemUI/res-product/values-ky/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"Планшетте SIM-карта жок."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"Телефондо SIM-карта жок."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"PIN-коддор дал келген жок"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Планшеттин кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, бул планшет баштапкы абалга келтирилип, андагы бардык дайындар жок болот."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Телефондун кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, бул телефон баштапкы абалга келтирилип, андагы бардык дайындар жок болот."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Планшеттин кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Бул планшет баштапкы абалга келтирилип, андагы бардык дайындар жок болот."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Телефондун кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес аракет жасадыңыз. Бул телефон баштапкы абалга келтирилип, андагы бардык дайындар жок болот."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Планшеттин кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, бул колдонуучу чыгарылып салынып, колдонуучунун бардык дайындары жок болот."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Телефондун кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, бул колдонуучу чыгарылып салынып, колдонуучунун бардык дайындары жок болот."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Android TV түзмөгү жакында өчүрүлөт, аны күйүк боюнча калтыруу үчүн баскычты басыңыз."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Түзмөк жакында өчүрүлөт, күйүк боюнча калтыруу үчүн басып коюңуз."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Планшеттин кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Жумуш профили чыгарылып салынып, андагы бардык дайындар жок болот."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Телефондун кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Жумуш профили чыгарылып салынып, андагы бардык дайындар жок болот."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Сиз графикалык ачкычты <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тарттыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> ийгиликсиз аракеттен кийин планшетиңизди бөгөттөн электрондук почтаңыз аркылуу чыгарышыңыз талап кылынат.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секунддан кийин кайра аракеттениңиз."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Сиз графикалык ачкычты <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тарттыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> ийгиликсиз аракеттен кийин телефонуңузду бөгөттөн электрондук почтаңыз аркылуу чыгаруу талап кылынат.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секунддан кийин кайра аракеттениңиз."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Телефонду ыкчам кубаттоо үчүн туура коюңуз"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Телефонду зымсыз кубаттоо үчүн туура коюңуз"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Android TV түзмөгү жакында өчүрүлөт, аны күйүк боюнча калтыруу үчүн баскычты басыңыз."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Түзмөк жакында өчүрүлөт, күйүк боюнча калтыруу үчүн басып коюңуз."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Планшетте SIM-карта жок."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Телефондо SIM-карта жок."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"PIN-коддор дал келген жок"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Планшеттин кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, бул планшет баштапкы абалга келтирилип, андагы бардык маалымат жок кылынат."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Телефондун кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, бул телефон баштапкы абалга келтирилип, андагы бардык маалымат жок кылынат."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Планшеттин кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Бул планшет баштапкы абалга келтирилип, андагы бардык маалымат жок кылынат."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Телефондун кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес аракет жасадыңыз. Бул телефон баштапкы абалга келтирилип, андагы бардык маалымат жок кылынат."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Планшеттин кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, бул колдонуучу өчүрүлүп, колдонуучунун бардык маалыматы жок кылынат."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Телефондун кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, бул колдонуучу өчүрүлүп, колдонуучунун бардык маалыматы жок кылынат."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Планшеттин кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Бул колдонуучу өчүрүлүп, колдонуучунун бардык маалыматы жок кылынат."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Телефондун кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Бул колдонуучу өчүрүлүп, колдонуучунун бардык маалыматы жок кылынат."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Планшетиңиздин кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, жумуш профилиңиз өчүрүлүп, профилдеги бардык маалымат жок кылынат."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Телефондун кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, жумуш профилиңиз өчүрүлүп, профилдеги бардык маалымат жок кылынат."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Планшеттин кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Жумуш профили өчүрүлүп, андагы бардык маалымат жок кылынат."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Телефондун кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Жумуш профили өчүрүлүп, андагы бардык маалымат жок кылынат."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Графикалык ачкычты <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тарттыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> ийгиликсиз аракеттен кийин планшетиңизди бөгөттөн электрондук почтаңыз аркылуу чыгаруу талап кылынат.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секунддан кийин кайра аракеттениңиз."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Графикалык ачкычты <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тарттыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> ийгиликсиз аракеттен кийин телефонуңузду бөгөттөн электрондук почтаңыз аркылуу чыгаруу талап кылынат.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секунддан кийин кайра аракеттениңиз."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-lo/strings.xml b/packages/SystemUI/res-product/values-lo/strings.xml
index 8d2e0f3d65e7..bc2d00f6dd77 100644
--- a/packages/SystemUI/res-product/values-lo/strings.xml
+++ b/packages/SystemUI/res-product/values-lo/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"ບໍ່ມີຊິມກາດໃນແທັບເລັດ."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"ບໍ່ມີ SIM card ໃນໂທລະສັບ."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"ລະຫັດ PIN ບໍ່ກົງກັນ"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"ທ່ານພະຍາຍາມປົດລັອກແທັບເລັດບໍ່ຖືກຕ້ອງ <xliff:g id="NUMBER_0">%1$d</xliff:g> ຄັ້ງ. ຫຼັງຈາກລອງບໍ່ສຳເລັດອີກ <xliff:g id="NUMBER_1">%2$d</xliff:g> ຄັ້ງ, ແທັບເລັດນີ້ຈະຖືກຕັ້ງຄ່າໃໝ່, ເຊິ່ງຈະລຶບທຸກຂໍ້ມູນຂອງມັນ."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"ທ່ານພະຍາຍາມປົດລັອກໂທລະສັບບໍ່ຖືກຕ້ອງ <xliff:g id="NUMBER_0">%1$d</xliff:g> ຄັ້ງ. ຫຼັງຈາກລອງບໍ່ສຳເລັດອີກ <xliff:g id="NUMBER_1">%2$d</xliff:g> ຄັ້ງ, ໂທລະສັບນີ້ຈະຖືກຕັ້ງຄ່າໃໝ່, ເຊິ່ງຈະລຶບທຸກຂໍ້ມູນຂອງມັນ."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"ທ່ານພະຍາຍາມປົດລັອກແທັບເລັດບໍ່ຖືກຕ້ອງ <xliff:g id="NUMBER">%d</xliff:g> ຄັ້ງ. ແທັບເລັດນີ້ຈະຖືກຕັ້ງຄ່າໃໝ່, ເຊິ່ງຈະລຶບທຸກຂໍ້ມູນຂອງມັນ."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"ທ່ານພະຍາຍາມປົດລັອກໂທລະສັບບໍ່ຖືກຕ້ອງ <xliff:g id="NUMBER">%d</xliff:g> ຄັ້ງ. ໂທລະສັບນີ້ຈະຖືກຕັ້ງຄ່າໃໝ່, ເຊິ່ງຈະລຶບທຸກຂໍ້ມູນຂອງມັນ."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"ທ່ານພະຍາຍາມປົດລັອກແທັບເລັດບໍ່ຖືກຕ້ອງ <xliff:g id="NUMBER_0">%1$d</xliff:g> ຄັ້ງ. ຫຼັງຈາກລອງບໍ່ສຳເລັດອີກ <xliff:g id="NUMBER_1">%2$d</xliff:g>ຄັ້ງ, ຜູ້ໃຊ້ນີ້ຈະຖືກເອົາອອກໄປ, ເຊິ່ງຈະລຶບທຸກຂໍ້ມູນຜູ້ໃຊ້."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"ທ່ານພະຍາຍາມປົດລັອກໂທລະສັບບໍ່ຖືກຕ້ອງ <xliff:g id="NUMBER_0">%1$d</xliff:g> ຄັ້ງ. ຫຼັງຈາກລອງບໍ່ສຳເລັດອີກ <xliff:g id="NUMBER_1">%2$d</xliff:g> ຄັ້ງ, ຜູ້ໃຊ້ນີ້ຈະຖືກເອົາອອກໄປ, ເຊິ່ງຈະລຶບທຸກຂໍ້ມູນຜູ້ໃຊ້."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"ອຸປະກອນ Android TV ຈະປິດໃນອີກບໍ່ດົນ, ກົດປຸ່ມໃດໜຶ່ງເພື່ອເປີດມັນໄວ້ຕໍ່."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"ອຸປະກອນຈະປິດໃນອີກບໍ່ດົນ, ກົດເພື່ອເປີດມັນໄວ້ຕໍ່."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"ທ່ານພະຍາຍາມປົດລັອກແທັບເລັດບໍ່ຖືກຕ້ອງ <xliff:g id="NUMBER">%d</xliff:g> ຄັ້ງ. ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກຈະຖືກເອົາອອກໄປ, ເຊິ່ງຈະລຶບທຸກຂໍ້ມູນໂປຣໄຟລ໌."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"ທ່ານພະຍາຍາມປົດລັອກໂທລະສັບບໍ່ຖືກຕ້ອງ <xliff:g id="NUMBER">%d</xliff:g> ຄັ້ງ. ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກຈະຖືກເອົາອອກໄປ, ເຊິ່ງຈະລຶບທຸກຂໍ້ມູນໂປຣໄຟລ໌."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"ທ່ານແຕ້ມຮູບແບບປົດລັອກຜິດ <xliff:g id="NUMBER_0">%1$d</xliff:g> ເທື່ອແລ້ວ. ຫຼັງຈາກແຕ້ມຜິດອີກ <xliff:g id="NUMBER_1">%2$d</xliff:g> ເທື່ອ, ທ່ານຈະຖືກຖາມໃຫ້ປົດລັອກແທັບເລັດຂອງທ່ານ ດ້ວຍການເຂົ້າສູ່ລະບົບໂດຍໃຊ້ອີເມວຂອງທ່ານ.\n\n ກະລຸນາລອງໃໝ່ອີກຄັ້ງໃນອີກ <xliff:g id="NUMBER_2">%3$d</xliff:g> ວິນາທີ."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"ທ່ານແຕ້ມຮູບແບບປົດລັອກຂອງທ່ານຜິດ <xliff:g id="NUMBER_0">%1$d</xliff:g> ເທື່ອແລ້ວ. ຫຼັງຈາກຄວາມພະຍາຍາມອີກ <xliff:g id="NUMBER_1">%2$d</xliff:g> ເທື່ອ ທ່ານຈະຖືກຖາມໃຫ້ປົດລັອກໂທລະສັບຂອງທ່ານດ້ວຍບັນຊີອີເມວ.\n\n ລອງໃໝ່ອີກຄັ້ງໃນ <xliff:g id="NUMBER_2">%3$d</xliff:g> ວິນາທີ."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"ຈັດວາງໂທລະສັບຄືນໃໝ່ເພື່ອສາກໃຫ້ໄວຂຶ້ນ"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"ຈັດວາງໂທລະສັບໃໝ່ເພື່ອສາກແບບໄຮ້ສາຍ"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"ອຸປະກອນ Android TV ຈະປິດໃນອີກບໍ່ດົນ, ກົດປຸ່ມໃດໜຶ່ງເພື່ອເປີດມັນໄວ້ຕໍ່."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"ອຸປະກອນຈະປິດໃນອີກບໍ່ດົນ, ກົດເພື່ອເປີດມັນໄວ້ຕໍ່."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"ບໍ່ມີຊິມກາດໃນແທັບເລັດ."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"ບໍ່ມີຊິມກາດໃນໂທລະສັບ."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"ລະຫັດ PIN ບໍ່ກົງກັນ"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"ທ່ານພະຍາຍາມປົດລັອກແທັບເລັດຜິດ <xliff:g id="NUMBER_0">%1$d</xliff:g> ເທື່ອແລ້ວ. ຫຼັງຈາກລອງບໍ່ສຳເລັດອີກ <xliff:g id="NUMBER_1">%2$d</xliff:g> ເທື່ອ, ແທັບເລັດນີ້ຈະຖືກຣີເຊັດ, ເຊິ່ງຈະລຶບຂໍ້ມູນທັງໝົດຂອງມັນອອກນຳ."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"ທ່ານພະຍາຍາມປົດລັອກໂທລະສັບຜິດ <xliff:g id="NUMBER_0">%1$d</xliff:g> ເທື່ອແລ້ວ. ຫຼັງຈາກລອງບໍ່ສຳເລັດອີກ <xliff:g id="NUMBER_1">%2$d</xliff:g> ເທື່ອ, ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກຈະຖືກຣີເຊັດ, ເຊິ່ງຈະລຶບຂໍ້ມູນທັງໝົດຂອງມັນອອກນຳ."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"ທ່ານພະຍາຍາມປົດລັອກແທັບເລັດຜິດ <xliff:g id="NUMBER">%d</xliff:g> ເທື່ອແລ້ວ. ແທັບເລັດນີ້ຈະຖືກຣີເຊັດ, ເຊິ່ງຈະລຶບຂໍ້ມູນທັງໝົດຂອງມັນອອກ."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"ທ່ານພະຍາຍາມປົດລັອກໂທລະສັບຜິດ <xliff:g id="NUMBER">%d</xliff:g> ເທື່ອແລ້ວ. ໂທລະສັບນີ້ຈະຖືກຣີເຊັດ, ເຊິ່ງຈະລຶບຂໍ້ມູນທັງໝົດຂອງມັນອອກນຳ."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"ທ່ານພະຍາຍາມປົດລັອກແທັບເລັດຜິດ <xliff:g id="NUMBER_0">%1$d</xliff:g> ເທື່ອແລ້ວ. ຫຼັງຈາກລອງບໍ່ສຳເລັດອີກ <xliff:g id="NUMBER_1">%2$d</xliff:g>ເທື່ອ, ຜູ້ໃຊ້ນີ້ຈະຖືກລຶບອອກ, ເຊິ່ງຈະລຶບຂໍ້ມູນຜູ້ໃຊ້ທັງໝົດອອກນຳ."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"ທ່ານພະຍາຍາມປົດລັອກໂທລະສັບຜິດ <xliff:g id="NUMBER_0">%1$d</xliff:g> ເທື່ອແລ້ວ. ຫຼັງຈາກລອງບໍ່ສຳເລັດອີກ <xliff:g id="NUMBER_1">%2$d</xliff:g> ເທື່ອ, ຜູ້ໃຊ້ນີ້ຈະຖືກລຶບອອກ, ເຊິ່ງຈະລຶບຂໍ້ມູນຜູ້ໃຊ້ທັງໝົດອອກນຳ."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"ທ່ານພະຍາຍາມປົດລັອກແທັບເລັດຜິດ <xliff:g id="NUMBER">%d</xliff:g> ເທື່ອແລ້ວ. ຜູ້ໃຊ້ນີ້ຈະຖືກລຶບອອກ, ເຊິ່ງຈະລຶບຂໍ້ມູນຜູ້ໃຊ້ທັງໝົດອອກນຳ."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"ທ່ານພະຍາຍາມປົດລັອກໂທລະສັບຜິດ <xliff:g id="NUMBER">%d</xliff:g> ເທື່ອແລ້ວ. ຜູ້ໃຊ້ນີ້ຈະຖືກລຶບອອກ, ເຊິ່ງຈະລຶບຂໍ້ມູນຜູ້ໃຊ້ທັງໝົດອອກນຳ."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"ທ່ານພະຍາຍາມປົດລັອກແທັບເລັດຜິດ <xliff:g id="NUMBER_0">%1$d</xliff:g> ເທື່ອແລ້ວ. ຫຼັງຈາກລອງບໍ່ສຳເລັດອີກ <xliff:g id="NUMBER_1">%2$d</xliff:g> ເທື່ອ, ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກຈະຖືກລຶບອອກ, ເຊິ່ງຈະລຶບຂໍ້ມູນທັງໝົດໂປຣໄຟລ໌ທັງໝົດອອກນຳ."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"ທ່ານພະຍາຍາມປົດລັອກໂທລະສັບຜິດ <xliff:g id="NUMBER_0">%1$d</xliff:g> ເທື່ອແລ້ວ. ຫຼັງຈາກລອງບໍ່ສຳເລັດອີກ <xliff:g id="NUMBER_1">%2$d</xliff:g> ເທື່ອ, ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກຈະຖືກລຶບອອກ, ເຊິ່ງຈະລຶບຂໍ້ມູນໂປຣໄຟລ໌ທັງໝົດອອກນຳ."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"ທ່ານພະຍາຍາມປົດລັອກແທັບເລັດຜິດ <xliff:g id="NUMBER">%d</xliff:g> ເທື່ອແລ້ວ. ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກຈະຖືກລຶບອອກ, ເຊິ່ງຈະລຶບຂໍ້ມູນໂປຣໄຟລ໌ທັງໝົດອອກນຳ."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"ທ່ານພະຍາຍາມປົດລັອກໂທລະສັບຜິດ <xliff:g id="NUMBER">%d</xliff:g> ເທື່ອແລ້ວ. ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກຈະຖືກລຶບອອກ, ເຊິ່ງຈະລຶບຂໍ້ມູນໂປຣໄຟລ໌ທັງໝົດອອກນຳ."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"ທ່ານແຕ້ມຮູບແບບປົດລັອກຜິດ <xliff:g id="NUMBER_0">%1$d</xliff:g> ເທື່ອແລ້ວ. ຫຼັງຈາກແຕ້ມຜິດອີກ <xliff:g id="NUMBER_1">%2$d</xliff:g> ເທື່ອ, ທ່ານຈະຖືກຖາມໃຫ້ປົດລັອກແທັບເລັດຂອງທ່ານດ້ວຍການເຂົ້າສູ່ລະບົບໂດຍໃຊ້ອີເມວຂອງທ່ານ.\n\n ກະລຸນາລອງໃໝ່ໃນອີກ <xliff:g id="NUMBER_2">%3$d</xliff:g> ວິນາທີ."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"ທ່ານແຕ້ມຮູບແບບປົດລັອກຜິດ <xliff:g id="NUMBER_0">%1$d</xliff:g> ເທື່ອແລ້ວ. ຫຼັງຈາກແຕ້ມຜິດອີກ <xliff:g id="NUMBER_1">%2$d</xliff:g> ເທື່ອ, ທ່ານຈະຖືກຖາມໃຫ້ປົດໂທລະສັບຂອງທ່ານດ້ວຍການເຂົ້າສູ່ລະບົບໂດຍໃຊ້ບັນຊີອີເມວ.\n\n ກະລຸນາລອງໃໝ່ໃນອີກ <xliff:g id="NUMBER_2">%3$d</xliff:g> ວິນາທີ."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-lt/strings.xml b/packages/SystemUI/res-product/values-lt/strings.xml
index f29168194f30..26bac3b71b02 100644
--- a/packages/SystemUI/res-product/values-lt/strings.xml
+++ b/packages/SystemUI/res-product/values-lt/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"Planšetiniame kompiuteryje nėra SIM kortelės."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"Telefone nėra SIM kortelės."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"PIN kodai nesutampa"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"<xliff:g id="NUMBER_0">%1$d</xliff:g> kart. nesėkmingai bandėte atrakinti planšetinį kompiuterį. Po dar <xliff:g id="NUMBER_1">%2$d</xliff:g> nesėkm. band. šis planšetinis kompiuteris bus nustatytas iš naujo ir visi jo duomenys bus ištrinti."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"<xliff:g id="NUMBER_0">%1$d</xliff:g> kart. nesėkmingai bandėte atrakinti telefoną. Po dar <xliff:g id="NUMBER_1">%2$d</xliff:g> nesėkm. band. šis telefonas bus nustatytas iš naujo ir visi jo duomenys bus ištrinti."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"<xliff:g id="NUMBER">%d</xliff:g> kart. nesėkmingai bandėte atrakinti planšetinį kompiuterį. Šis planšetinis kompiuteris bus nustatytas iš naujo ir visi jo duomenys bus ištrinti."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"<xliff:g id="NUMBER">%d</xliff:g> kart. nesėkmingai bandėte atrakinti telefoną. Šis telefonas bus nustatytas iš naujo ir visi jo duomenys bus ištrinti."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"<xliff:g id="NUMBER_0">%1$d</xliff:g> kart. nesėkmingai bandėte atrakinti planšetinį kompiuterį. Po dar <xliff:g id="NUMBER_1">%2$d</xliff:g> nesėkm. band. šis naudotojas bus pašalintas ir visi naudotojo duomenys bus ištrinti."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"<xliff:g id="NUMBER_0">%1$d</xliff:g> kart. nesėkmingai bandėte atrakinti telefoną. Po dar <xliff:g id="NUMBER_1">%2$d</xliff:g> nesėkm. band. šis naudotojas bus pašalintas ir visi naudotojo duomenys bus ištrinti."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"„Android TV“ įrenginys netrukus išsijungs. Paspauskite mygtuką, kad jis liktų įjungtas."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Įrenginys netrukus išsijungs. Paspauskite, kad jis liktų įjungtas."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"<xliff:g id="NUMBER">%d</xliff:g> kart. nesėkmingai bandėte atrakinti planšetinį kompiuterį. Darbo profilis bus pašalintas ir visi profilio duomenys bus ištrinti."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"<xliff:g id="NUMBER">%d</xliff:g> kart. nesėkmingai bandėte atrakinti telefoną. Darbo profilis bus pašalintas ir visi profilio duomenys bus ištrinti."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"<xliff:g id="NUMBER_0">%1$d</xliff:g> kart. netinkamai nupiešėte atrakinimo piešinį. Po dar <xliff:g id="NUMBER_1">%2$d</xliff:g> nesėkm. band. būsite paprašyti atrakinti planšetinį kompiuterį naudodami el. pašto paskyrą.\n\n Bandykite dar kartą po <xliff:g id="NUMBER_2">%3$d</xliff:g> sek."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"<xliff:g id="NUMBER_0">%1$d</xliff:g> kart. netinkamai nupiešėte atrakinimo piešinį. Po dar <xliff:g id="NUMBER_1">%2$d</xliff:g> nesėkm. band. būsite paprašyti atrakinti telefoną naudodami el. pašto paskyrą.\n\n Bandykite dar kartą po <xliff:g id="NUMBER_2">%3$d</xliff:g> sek."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Sulygiuokite telefoną iš naujo, kad gal. sparčiau įkrauti"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Sulygiuokite telefoną iš naujo, kad gal. įkrauti be laidų"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"„Android TV“ įrenginys netrukus išsijungs. Paspauskite mygtuką, kad jis liktų įjungtas."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Įrenginys netrukus išsijungs. Paspauskite, kad jis liktų įjungtas."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Planšetiniame kompiuteryje nėra SIM kortelės."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Telefone nėra SIM kortelės."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"PIN kodai nesutampa"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"<xliff:g id="NUMBER_0">%1$d</xliff:g> kart. nesėkmingai bandėte atrakinti planšetinį kompiuterį. Po dar <xliff:g id="NUMBER_1">%2$d</xliff:g> nesėkm. band. šis planšetinis kompiuteris bus nustatytas iš naujo ir visi jo duomenys bus ištrinti."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"<xliff:g id="NUMBER_0">%1$d</xliff:g> kart. nesėkmingai bandėte atrakinti telefoną. Po dar <xliff:g id="NUMBER_1">%2$d</xliff:g> nesėkm. band. šis telefonas bus nustatytas iš naujo ir visi jo duomenys bus ištrinti."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"<xliff:g id="NUMBER">%d</xliff:g> kart. nesėkmingai bandėte atrakinti planšetinį kompiuterį. Šis planšetinis kompiuteris bus nustatytas iš naujo ir visi jo duomenys bus ištrinti."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"<xliff:g id="NUMBER">%d</xliff:g> kart. nesėkmingai bandėte atrakinti telefoną. Šis telefonas bus nustatytas iš naujo ir visi jo duomenys bus ištrinti."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"<xliff:g id="NUMBER_0">%1$d</xliff:g> kart. nesėkmingai bandėte atrakinti planšetinį kompiuterį. Po dar <xliff:g id="NUMBER_1">%2$d</xliff:g> nesėkm. band. šis naudotojas bus pašalintas ir visi naudotojo duomenys bus ištrinti."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"<xliff:g id="NUMBER_0">%1$d</xliff:g> kart. nesėkmingai bandėte atrakinti telefoną. Po dar <xliff:g id="NUMBER_1">%2$d</xliff:g> nesėkm. band. šis naudotojas bus pašalintas ir visi naudotojo duomenys bus ištrinti."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"<xliff:g id="NUMBER">%d</xliff:g> kart. nesėkmingai bandėte atrakinti planšetinį kompiuterį. Šis naudotojas bus pašalintas ir visi naudotojo duomenys bus ištrinti."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"<xliff:g id="NUMBER">%d</xliff:g> kart. nesėkmingai bandėte atrakinti telefoną. Šis naudotojas bus pašalintas ir visi naudotojo duomenys bus ištrinti."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"<xliff:g id="NUMBER_0">%1$d</xliff:g> kart. nesėkmingai bandėte atrakinti planšetinį kompiuterį. Po dar <xliff:g id="NUMBER_1">%2$d</xliff:g> nesėkm. band. darbo profilis bus pašalintas ir visi profilio duomenys bus ištrinti."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"<xliff:g id="NUMBER_0">%1$d</xliff:g> kart. nesėkmingai bandėte atrakinti telefoną. Po dar <xliff:g id="NUMBER_1">%2$d</xliff:g> nesėkm. band. darbo profilis bus pašalintas ir visi profilio duomenys bus ištrinti."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"<xliff:g id="NUMBER">%d</xliff:g> kart. nesėkmingai bandėte atrakinti planšetinį kompiuterį. Darbo profilis bus pašalintas ir visi profilio duomenys bus ištrinti."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"<xliff:g id="NUMBER">%d</xliff:g> kart. nesėkmingai bandėte atrakinti telefoną. Darbo profilis bus pašalintas ir visi profilio duomenys bus ištrinti."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"<xliff:g id="NUMBER_0">%1$d</xliff:g> kart. netinkamai nupiešėte atrakinimo piešinį. Po dar <xliff:g id="NUMBER_1">%2$d</xliff:g> nesėkm. band. būsite paprašyti atrakinti planšetinį kompiuterį naudodami el. pašto paskyrą.\n\n Bandykite dar kartą po <xliff:g id="NUMBER_2">%3$d</xliff:g> sek."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"<xliff:g id="NUMBER_0">%1$d</xliff:g> kart. netinkamai nupiešėte atrakinimo piešinį. Po dar <xliff:g id="NUMBER_1">%2$d</xliff:g> nesėkm. band. būsite paprašyti atrakinti telefoną naudodami el. pašto paskyrą.\n\n Bandykite dar kartą po <xliff:g id="NUMBER_2">%3$d</xliff:g> sek."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-lv/strings.xml b/packages/SystemUI/res-product/values-lv/strings.xml
index 6459e257653c..0b12841421b1 100644
--- a/packages/SystemUI/res-product/values-lv/strings.xml
+++ b/packages/SystemUI/res-product/values-lv/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"Planšetdatorā nav SIM kartes."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"Tālrunī nav SIM kartes."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"PIN kodi neatbilst."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Jūs <xliff:g id="NUMBER_0">%1$d</xliff:g> reizi(-es) nesekmīgi mēģinājāt atbloķēt planšetdatoru. Pēc vēl <xliff:g id="NUMBER_1">%2$d</xliff:g> nesekmīga(-iem) mēģinājuma(-iem) šis planšetdators tiks atiestatīts, kā arī visi planšetdatora dati tiks dzēsti."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Jūs <xliff:g id="NUMBER_0">%1$d</xliff:g> reizi(-es) nesekmīgi mēģinājāt atbloķēt tālruni. Pēc vēl <xliff:g id="NUMBER_1">%2$d</xliff:g> nesekmīga(-iem) mēģinājuma(-iem) šis tālrunis tiks atiestatīts, kā arī visi tālruņa dati tiks dzēsti."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Jūs <xliff:g id="NUMBER">%d</xliff:g> reizi(-es) nesekmīgi mēģinājāt atbloķēt planšetdatoru. Šis planšetdators tiks atiestatīts, kā arī visi planšetdatora dati tiks dzēsti."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Jūs <xliff:g id="NUMBER">%d</xliff:g> reizi(-es) nesekmīgi mēģinājāt atbloķēt tālruni. Šis tālrunis tiks atiestatīts, kā arī visi tālruņa dati tiks dzēsti."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Jūs <xliff:g id="NUMBER_0">%1$d</xliff:g> reizi(-es) nesekmīgi mēģinājāt atbloķēt planšetdatoru. Pēc vēl <xliff:g id="NUMBER_1">%2$d</xliff:g> nesekmīga(-iem) mēģinājuma(-iem) šis lietotājs tiks noņemts, kā arī visi lietotāja dati tiks dzēsti."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Jūs <xliff:g id="NUMBER_0">%1$d</xliff:g> reizi(-es) nesekmīgi mēģinājāt atbloķēt tālruni. Pēc vēl <xliff:g id="NUMBER_1">%2$d</xliff:g> nesekmīga(-iem) mēģinājuma(-iem) šis lietotājs tiks noņemts, kā arī visi lietotāja dati tiks dzēsti."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Android TV ierīce drīz izslēgsies. Nospiediet pogu, lai tā paliktu ieslēgta."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Ierīce drīz izslēgsies. Nospiediet, lai tā paliktu ieslēgta."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Jūs <xliff:g id="NUMBER">%d</xliff:g> reizi(-es) nesekmīgi mēģinājāt atbloķēt planšetdatoru. Darba profils tiks noņemts, kā arī visi profila dati tiks dzēsti."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Jūs <xliff:g id="NUMBER">%d</xliff:g> reizi(-es) nesekmīgi mēģinājāt atbloķēt tālruni. Darba profils tiks noņemts, kā arī visi profila dati tiks dzēsti."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Jūs <xliff:g id="NUMBER_0">%1$d</xliff:g> reizi(-es) nepareizi norādījāt atbloķēšanas kombināciju. Pēc vēl <xliff:g id="NUMBER_1">%2$d</xliff:g> nesekmīga(-iem) mēģinājuma(-iem) planšetdators būs jāatbloķē, izmantojot e-pasta kontu.\n\nMēģiniet vēlreiz pēc <xliff:g id="NUMBER_2">%3$d</xliff:g> sekundes(-ēm)."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Jūs <xliff:g id="NUMBER_0">%1$d</xliff:g> reizi(-es) nepareizi norādījāt atbloķēšanas kombināciju. Pēc vēl <xliff:g id="NUMBER_1">%2$d</xliff:g> nesekmīga(-iem) mēģinājuma(-iem) tālrunis būs jāatbloķē, izmantojot e-pasta kontu.\n\nMēģiniet vēlreiz pēc <xliff:g id="NUMBER_2">%3$d</xliff:g> sekundes(-ēm)."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Pārvietojiet tālruni citā vietā, lai uzlāde notiktu ātrāk."</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Pārvietojiet tālruni citā vietā, lai veiktu bezvadu uzlādi."</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Android TV ierīce drīz izslēgsies. Nospiediet pogu, lai ierīce paliktu ieslēgta."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Ierīce drīz izslēgsies. Nospiediet pogu, lai ierīce paliktu ieslēgta."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Planšetdatorā nav SIM kartes."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Tālrunī nav SIM kartes."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"PIN kodi neatbilst."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Jūs <xliff:g id="NUMBER_0">%1$d</xliff:g> reizi(-es) nesekmīgi mēģinājāt atbloķēt planšetdatoru. Pēc vēl <xliff:g id="NUMBER_1">%2$d</xliff:g> nesekmīga(-iem) mēģinājuma(-iem) šis planšetdators tiks atiestatīts, kā arī visi planšetdatora dati tiks dzēsti."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Jūs <xliff:g id="NUMBER_0">%1$d</xliff:g> reizi(-es) nesekmīgi mēģinājāt atbloķēt tālruni. Pēc vēl <xliff:g id="NUMBER_1">%2$d</xliff:g> nesekmīga(-iem) mēģinājuma(-iem) šis tālrunis tiks atiestatīts, kā arī visi tālruņa dati tiks dzēsti."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Jūs <xliff:g id="NUMBER">%d</xliff:g> reizi(-es) nesekmīgi mēģinājāt atbloķēt planšetdatoru. Šis planšetdators tiks atiestatīts, kā arī visi planšetdatora dati tiks dzēsti."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Jūs <xliff:g id="NUMBER">%d</xliff:g> reizi(-es) nesekmīgi mēģinājāt atbloķēt tālruni. Šis tālrunis tiks atiestatīts, kā arī visi tālruņa dati tiks dzēsti."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Jūs <xliff:g id="NUMBER_0">%1$d</xliff:g> reizi(-es) nesekmīgi mēģinājāt atbloķēt planšetdatoru. Pēc vēl <xliff:g id="NUMBER_1">%2$d</xliff:g> nesekmīga(-iem) mēģinājuma(-iem) šis lietotājs tiks noņemts, kā arī visi lietotāja dati tiks dzēsti."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Jūs <xliff:g id="NUMBER_0">%1$d</xliff:g> reizi(-es) nesekmīgi mēģinājāt atbloķēt tālruni. Pēc vēl <xliff:g id="NUMBER_1">%2$d</xliff:g> nesekmīga(-iem) mēģinājuma(-iem) šis lietotājs tiks noņemts, kā arī visi lietotāja dati tiks dzēsti."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Jūs <xliff:g id="NUMBER">%d</xliff:g> reizi(-es) nesekmīgi mēģinājāt atbloķēt planšetdatoru. Šis lietotājs tiks noņemts, kā arī visi lietotāja dati tiks dzēsti."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Jūs <xliff:g id="NUMBER">%d</xliff:g> reizi(-es) nesekmīgi mēģinājāt atbloķēt tālruni. Šis lietotājs tiks noņemts, kā arī visi lietotāja dati tiks dzēsti."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Jūs <xliff:g id="NUMBER_0">%1$d</xliff:g> reizi(-es) nesekmīgi mēģinājāt atbloķēt planšetdatoru. Pēc vēl <xliff:g id="NUMBER_1">%2$d</xliff:g> nesekmīga(-iem) mēģinājuma(-iem) darba profils tiks noņemts, kā arī visi profila dati tiks dzēsti."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Jūs <xliff:g id="NUMBER_0">%1$d</xliff:g> reizi(-es) nesekmīgi mēģinājāt atbloķēt tālruni. Pēc vēl <xliff:g id="NUMBER_1">%2$d</xliff:g> nesekmīga(-iem) mēģinājuma(-iem) darba profils tiks noņemts, kā arī visi profila dati tiks dzēsti."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Jūs <xliff:g id="NUMBER">%d</xliff:g> reizi(-es) nesekmīgi mēģinājāt atbloķēt planšetdatoru. Darba profils tiks noņemts, kā arī visi profila dati tiks dzēsti."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Jūs <xliff:g id="NUMBER">%d</xliff:g> reizi(-es) nesekmīgi mēģinājāt atbloķēt tālruni. Darba profils tiks noņemts, kā arī visi profila dati tiks dzēsti."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Jūs <xliff:g id="NUMBER_0">%1$d</xliff:g> reizi(-es) nepareizi norādījāt atbloķēšanas kombināciju. Pēc vēl <xliff:g id="NUMBER_1">%2$d</xliff:g> neveiksmīga(-iem) mēģinājuma(-iem) planšetdators būs jāatbloķē, izmantojot e-pasta kontu.\n\nMēģiniet vēlreiz pēc <xliff:g id="NUMBER_2">%3$d</xliff:g> sekundes(-ēm)."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Jūs <xliff:g id="NUMBER_0">%1$d</xliff:g> reizi(-es) nepareizi norādījāt atbloķēšanas kombināciju. Pēc vēl <xliff:g id="NUMBER_1">%2$d</xliff:g> nesekmīga(-iem) mēģinājuma(-iem) tālrunis būs jāatbloķē, izmantojot e-pasta kontu.\n\nMēģiniet vēlreiz pēc <xliff:g id="NUMBER_2">%3$d</xliff:g> sekundes(-ēm)."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-mk/strings.xml b/packages/SystemUI/res-product/values-mk/strings.xml
index 21fde4d6d815..4478695eb8f4 100644
--- a/packages/SystemUI/res-product/values-mk/strings.xml
+++ b/packages/SystemUI/res-product/values-mk/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"Во таблетот нема SIM-картичка."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"Во телефонот нема SIM-картичка."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"PIN-кодовите не се совпаѓаат"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Неправилно се обидовте да го отклучите таблетот <xliff:g id="NUMBER_0">%1$d</xliff:g> пати. По уште <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешни обиди, таблетот ќе се ресетира, со што ќе се избришат сите негови податоци."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Неправилно се обидовте да го отклучите телефонот <xliff:g id="NUMBER_0">%1$d</xliff:g> пати. По уште <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешни обиди, телефонот ќе се ресетира, со што ќе се избришат сите негови податоци."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Неправилно се обидовте да го отклучите таблетот <xliff:g id="NUMBER">%d</xliff:g> пати. Овој таблет ќе се ресетира, со што ќе се избришат сите негови податоци."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Неправилно се обидовте да го отклучите телефонот <xliff:g id="NUMBER">%d</xliff:g> пати. Овој телефон ќе се ресетира, со што ќе се избришат сите негови податоци."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Неправилно се обидовте да го отклучите таблетот <xliff:g id="NUMBER_0">%1$d</xliff:g> пати. По уште <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешни обиди, корисникот ќе се отстрани, со што ќе се избришат сите негови податоци."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Неправилно се обидовте да го отклучите телефонот <xliff:g id="NUMBER_0">%1$d</xliff:g> пати. По уште <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешни обиди, корисникот ќе се отстрани, со што ќе се избришат сите податоци на корисникот."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Уредот со Android TV наскоро ќе се исклучи, притиснете копче за да остане вклучен."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Уредот наскоро ќе се исклучи, притиснете за да остане вклучен."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Неправилно се обидовте да го отклучите таблетот <xliff:g id="NUMBER">%d</xliff:g> пати. Работниот профил ќе се отстрани, со што ќе се избришат сите податоци на профилот."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Неправилно се обидовте да го отклучите телефонот <xliff:g id="NUMBER">%d</xliff:g> пати. Работниот профил ќе се отстрани, со што ќе се избришат сите податоци на профилот."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Погрешно сте ја употребиле вашата шема на отклучување <xliff:g id="NUMBER_0">%1$d</xliff:g> пати. По <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешни обиди, ќе побараме да го отклучите таблетот со сметка на е-пошта.\n\n Обидете се повторно за <xliff:g id="NUMBER_2">%3$d</xliff:g> секунди."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Погрешно сте ја употребиле вашата шема на отклучување <xliff:g id="NUMBER_0">%1$d</xliff:g> пати. По <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешни обиди, ќе побараме да го отклучите телефонот со сметка на е-пошта.\n\n Обидете се повторно за <xliff:g id="NUMBER_2">%3$d</xliff:g> секунди."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Повторно порамнете го телефонот за побрзо полнење"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Повторно порамнете го телефонот за да се полни безжично"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Уредот Android TV наскоро ќе се исклучи. Притиснете копче за да остане вклучен."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Уредот наскоро ќе се исклучи. Притиснете за да остане вклучен."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Во таблетот нема SIM-картичка."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Во телефонот нема SIM-картичка."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"PIN-кодовите не се совпаѓаат"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Погрешно се обидовте да го отклучите таблетот <xliff:g id="NUMBER_0">%1$d</xliff:g> пати. По уште <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешни обиди, таблетов ќе се ресетира, со што ќе се избришат сите негови податоци."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Погрешно се обидовте да го отклучите телефонот <xliff:g id="NUMBER_0">%1$d</xliff:g> пати. По уште <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешни обиди, телефонот ќе се ресетира, со што ќе се избришат сите негови податоци."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Погрешно се обидовте да го отклучите таблетот <xliff:g id="NUMBER">%d</xliff:g> пати. Таблетов ќе се ресетира, со што ќе се избришат сите негови податоци."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Погрешно се обидовте да го отклучите телефонот <xliff:g id="NUMBER">%d</xliff:g> пати. Телефонов ќе се ресетира, со што ќе се избришат сите негови податоци."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Погрешно се обидовте да го отклучите таблетот <xliff:g id="NUMBER_0">%1$d</xliff:g> пати. По уште <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешни обиди, овој корисник ќе се отстрани, со што ќе се избришат сите негови податоци."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Погрешно се обидовте да го отклучите телефонот <xliff:g id="NUMBER_0">%1$d</xliff:g> пати. По уште <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешни обиди, овој корисник ќе се отстрани, со што ќе се избришат сите негови податоци."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Погрешно се обидовте да го отклучите таблетот <xliff:g id="NUMBER">%d</xliff:g> пати. Овој корисник ќе се отстрани, со што ќе се избришат сите негови податоци."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Погрешно се обидовте да го отклучите телефонот <xliff:g id="NUMBER">%d</xliff:g> пати. Овој корисник ќе се отстрани, со што ќе се избришат сите негови податоци."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Погрешно се обидовте да го отклучите таблетот <xliff:g id="NUMBER_0">%1$d</xliff:g> пати. По уште <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешни обиди, работниот профил ќе се отстрани, со што ќе се избришат сите податоци на профилот."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Погрешно се обидовте да го отклучите телефонот <xliff:g id="NUMBER_0">%1$d</xliff:g> пати. По уште <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешни обиди, работниот профил ќе се отстрани, со што ќе се избришат сите податоци на профилот."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Погрешно се обидовте да го отклучите таблетот <xliff:g id="NUMBER">%d</xliff:g> пати. Работниот профил ќе се отстрани, со што ќе се избришат сите податоци на профилот."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Погрешно се обидовте да го отклучите телефонот <xliff:g id="NUMBER">%d</xliff:g> пати. Работниот профил ќе се отстрани, со што ќе се избришат сите податоци на профилот."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Погрешно ја употребивте вашата шема на отклучување <xliff:g id="NUMBER_0">%1$d</xliff:g> пати. По уште <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешни обиди, ќе побараме да го отклучите таблетот со сметка на е-пошта.\n\n Обидете се повторно за <xliff:g id="NUMBER_2">%3$d</xliff:g> секунди."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Погрешно ја употребивте вашата шема на отклучување <xliff:g id="NUMBER_0">%1$d</xliff:g> пати. По уште <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешни обиди, ќе побараме да го отклучите телефонот со сметка на е-пошта.\n\n Обидете се повторно за <xliff:g id="NUMBER_2">%3$d</xliff:g> секунди."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-ml/strings.xml b/packages/SystemUI/res-product/values-ml/strings.xml
index c39cce179f47..7e60dfda14fc 100644
--- a/packages/SystemUI/res-product/values-ml/strings.xml
+++ b/packages/SystemUI/res-product/values-ml/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,46 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"ടാബ്‌ലെറ്റിൽ സിം കാർഡൊന്നുമില്ല."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"ഫോണിൽ സിം കാർഡൊന്നുമില്ല."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"പിൻ കോഡുകൾ പൊരുത്തപ്പെടുന്നില്ല"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"നിങ്ങൾ <xliff:g id="NUMBER_0">%1$d</xliff:g> തവണ തെറ്റായി ടാബ്‌ലെറ്റ് അൺലോക്കുചെയ്യാൻ ശ്രമിച്ചു. <xliff:g id="NUMBER_1">%2$d</xliff:g> ശ്രമങ്ങൾ കൂടി പരാജയപ്പെട്ടാൽ, ഈ ടാബ്‌ലെറ്റ് ‌റീസെറ്റുചെയ്യപ്പെടുകയും, അതുവഴി അതിലെ എല്ലാ ‌ഡാറ്റയും ഇല്ലാതാകുകയും ചെയ്യും."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"നിങ്ങൾ <xliff:g id="NUMBER_0">%1$d</xliff:g> തവണ തെറ്റായി ഫോൺ അൺലോക്കുചെയ്യാൻ ശ്രമിച്ചു. <xliff:g id="NUMBER_1">%2$d</xliff:g> ശ്രമങ്ങൾ കൂടി പരാജയപ്പെട്ടാൽ ഈ ഫോൺ റീസെറ്റുചെയ്യപ്പെടുകയും, അതുവഴി അതിലെ എല്ലാ ‌ഡാറ്റയും ഇല്ലാതാകുകയും ചെയ്യും."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"നിങ്ങൾ <xliff:g id="NUMBER">%d</xliff:g> തവണ തെറ്റായി ടാബ്‌ലെറ്റ് അൺലോക്കുചെയ്യാൻ ശ്രമിച്ചു. ഈ ഫോൺ റീസെറ്റുചെയ്യപ്പെടുകയും, അതുവഴി അതിലെ എല്ലാ ‌ഡാറ്റയും ഇല്ലാതാകുകയും ചെയ്യും."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"നിങ്ങൾ <xliff:g id="NUMBER">%d</xliff:g> തവണ തെറ്റായി ഫോൺ അൺലോക്കുചെയ്യാൻ ശ്രമിച്ചു. ഈ ഫോൺ റീസെറ്റുചെയ്യപ്പെടുകയും, അതുവഴി അതിലെ എല്ലാ ‌ഡാറ്റയും ഇല്ലാതാകുകയും ചെയ്യും."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"നിങ്ങൾ <xliff:g id="NUMBER_0">%1$d</xliff:g> തവണ തെറ്റായി ടാബ്‌ലെറ്റ് അൺലോക്കുചെയ്യാൻ ശ്രമിച്ചു. <xliff:g id="NUMBER_1">%2$d</xliff:g> ശ്രമങ്ങൾ കൂടി പരാജയപ്പെട്ടാൽ ഈ ഉപയോക്താവിനെ ‌നീക്കം ചെയ്യുകയും, അതുവഴി ‌ഉപയോക്താവിന്റെ എല്ലാ ‌ഡാറ്റയും ഇല്ലാതാകുകയും ചെയ്യും."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"നിങ്ങൾ <xliff:g id="NUMBER_0">%1$d</xliff:g> തവണ തെറ്റായി ഫോൺ അൺലോക്കുചെയ്യാൻ ശ്രമിച്ചു. <xliff:g id="NUMBER_1">%2$d</xliff:g> ശ്രമങ്ങൾ കൂടി പരാജയപ്പെട്ടാൽ ഈ ഉപയോക്താവിനെ ‌നീക്കം ചെയ്യുകയും, അതുവഴി ‌ഉപയോക്താവിന്റെ എല്ലാ ‌ഡാറ്റയും ഇല്ലാതാകുകയും ചെയ്യും."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for notification_bubble_title (8330481035191903164) -->
- <skip/>
- <!-- no translation found for notification_channel_summary_bubble (7235935211580860537) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Android ടിവി ഉടൻ ഓഫാകും, ഓണാക്കി നിർത്താൻ ഒരു ബട്ടൺ അമർത്തുക."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"ഉപകരണം ഉടൻ ഓഫാകും, ഓണാക്കി നിർത്താൻ അമർത്തുക."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"നിങ്ങൾ <xliff:g id="NUMBER">%d</xliff:g> തവണ തെറ്റായി ടാബ്‌ലെറ്റ് അൺലോക്കുചെയ്യാൻ ശ്രമിച്ചു. ഔദ്യോഗിക പ്രൊഫൈൽ നീക്കംചെയ്യപ്പെടുകയും, അതുവഴി എല്ലാ പ്രൊഫൈൽ ഡാറ്റയും ഇല്ലാതാകുകയും ചെയ്യും."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"നിങ്ങൾ <xliff:g id="NUMBER">%d</xliff:g> തവണ തെറ്റായി ഫോൺ അൺലോക്കുചെയ്യാൻ ശ്രമിച്ചു. ഔദ്യോഗിക പ്രൊഫൈൽ നീക്കംചെയ്യപ്പെടുകയും, അതുവഴി എല്ലാ പ്രൊഫൈൽ ഡാറ്റയും ഇല്ലാതാകുകയും ചെയ്യും."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"നിങ്ങൾ <xliff:g id="NUMBER_0">%1$d</xliff:g> തവണ തെറ്റായി അൺലോക്ക് പാറ്റേൺ വരച്ചു. <xliff:g id="NUMBER_1">%2$d</xliff:g> ശ്രമങ്ങൾ കൂടി പരാജയപ്പെട്ടാൽ, ഒരു ഇമെയിൽ അക്കൗണ്ടുപയോഗിച്ച് ടാബ്‌ലെറ്റ് അൺലോക്കുചെയ്യാൻ നിങ്ങളോട് ആവശ്യപ്പെടും.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> സെക്കന്റ് കഴിഞ്ഞ് വീണ്ടും ‌ശ്രമിക്കുക."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"നിങ്ങൾ <xliff:g id="NUMBER_0">%1$d</xliff:g> തവണ തെറ്റായി അൺലോക്ക് പാറ്റേൺ വരച്ചു. <xliff:g id="NUMBER_1">%2$d</xliff:g> ശ്രമങ്ങൾ കൂടി പരാജയപ്പെട്ടാൽ, ഒരു ഇമെയിൽ അക്കൗണ്ടുപയോഗിച്ച് ഫോൺ അൺലോക്കുചെയ്യാൻ നിങ്ങളോട് ആവശ്യപ്പെടും.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> സെക്കന്റ് കഴിഞ്ഞ് വീണ്ടും ‌ശ്രമിക്കുക."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"അതിവേഗം ചാർജ് ചെയ്യാൻ ഫോണിന്റെ സ്ഥാനം പുനഃക്രമീകരിക്കുക"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"വയർലെസായി ചാർജ് ചെയ്യാൻ ഫോണിന്റെ സ്ഥാനം പുനഃക്രമീകരിക്കുക"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Android ടിവി ഉടൻ ഓഫാകും, ഓണാക്കി നിർത്താൻ ഒരു ബട്ടൺ അമർത്തുക."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"ഉപകരണം ഉടൻ ഓഫാകും; ഓണാക്കി നിർത്താൻ അമർത്തുക."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"ടാബ്‌ലെറ്റിൽ സിം കാർഡൊന്നുമില്ല."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"ഫോണിൽ സിം കാർഡൊന്നുമില്ല."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"പിൻ കോഡുകൾ പൊരുത്തപ്പെടുന്നില്ല"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"നിങ്ങൾ <xliff:g id="NUMBER_0">%1$d</xliff:g> തവണ തെറ്റായ രീതിയിൽ ടാബ്‌ലെറ്റ് അൺലോക്ക് ചെയ്യാൻ ശ്രമിച്ചു. <xliff:g id="NUMBER_1">%2$d</xliff:g> ശ്രമങ്ങൾ കൂടി പരാജയപ്പെട്ടാൽ, ഈ ടാബ്‌ലെറ്റ് റീസെറ്റ് ചെയ്യപ്പെടുകയും, അതുവഴി അതിലെ എല്ലാ ഡാറ്റയും ഇല്ലാതാകുകയും ചെയ്യും."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"നിങ്ങൾ <xliff:g id="NUMBER_0">%1$d</xliff:g> തവണ തെറ്റായ രീതിയിൽ ഫോൺ അൺലോക്ക് ചെയ്യാൻ ശ്രമിച്ചു. <xliff:g id="NUMBER_1">%2$d</xliff:g> ശ്രമങ്ങൾ കൂടി പരാജയപ്പെട്ടാൽ ഈ ഫോൺ റീസെറ്റ് ചെയ്യപ്പെടുകയും, അതുവഴി അതിലെ എല്ലാ ഡാറ്റയും ഇല്ലാതാകുകയും ചെയ്യും."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"നിങ്ങൾ <xliff:g id="NUMBER">%d</xliff:g> തവണ തെറ്റായ രീതിയിൽ ടാബ്‌ലെറ്റ് അൺലോക്ക് ചെയ്യാൻ ശ്രമിച്ചു. ഈ ഫോൺ റീസെറ്റ് ചെയ്യപ്പെടുകയും, അതുവഴി അതിലെ എല്ലാ ഡാറ്റയും ഇല്ലാതാകുകയും ചെയ്യും."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"നിങ്ങൾ <xliff:g id="NUMBER">%d</xliff:g> തവണ തെറ്റായ രീതിയിൽ ഫോൺ അൺലോക്ക് ചെയ്യാൻ ശ്രമിച്ചു. ഈ ഫോൺ റീസെറ്റ് ചെയ്യപ്പെടുകയും, അതുവഴി അതിലെ എല്ലാ ഡാറ്റയും ഇല്ലാതാകുകയും ചെയ്യും."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"നിങ്ങൾ <xliff:g id="NUMBER_0">%1$d</xliff:g> തവണ തെറ്റായ രീതിയിൽ ടാബ്‌ലെറ്റ് അൺലോക്ക് ചെയ്യാൻ ശ്രമിച്ചു. <xliff:g id="NUMBER_1">%2$d</xliff:g> ശ്രമങ്ങൾ കൂടി പരാജയപ്പെട്ടാൽ ഈ ഉപയോക്താവിനെ നീക്കം ചെയ്യുകയും, അതുവഴി ഉപയോക്താവിന്റെ എല്ലാ ഡാറ്റയും ഇല്ലാതാകുകയും ചെയ്യും."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"നിങ്ങൾ <xliff:g id="NUMBER_0">%1$d</xliff:g> തവണ തെറ്റായ രീതിയിൽ ഫോൺ അൺലോക്ക് ചെയ്യാൻ ശ്രമിച്ചു. <xliff:g id="NUMBER_1">%2$d</xliff:g> ശ്രമങ്ങൾ കൂടി പരാജയപ്പെട്ടാൽ ഈ ഉപയോക്താവിനെ ‌നീക്കം ചെയ്യുകയും, അതുവഴി ഉപയോക്താവിന്റെ എല്ലാ ഡാറ്റയും ഇല്ലാതാകുകയും ചെയ്യും."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"നിങ്ങൾ <xliff:g id="NUMBER">%d</xliff:g> തവണ തെറ്റായ രീതിയിൽ ടാബ്‌ലെറ്റ് അൺലോക്ക് ചെയ്യാൻ ശ്രമിച്ചു. ഈ ഉപയോക്താവിനെ നീക്കം ചെയ്യുകയും, അതുവഴി ഉപയോക്താവിന്റെ എല്ലാ ഡാറ്റയും ഇല്ലാതാകുകയും ചെയ്യും."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"നിങ്ങൾ <xliff:g id="NUMBER">%d</xliff:g> തവണ തെറ്റായ രീതിയിൽ ഫോൺ അൺലോക്ക് ചെയ്യാൻ ശ്രമിച്ചു. ഈ ഉപയോക്താവിനെ ‌നീക്കം ചെയ്യുകയും, അതുവഴി ഉപയോക്താവിന്റെ എല്ലാ ഡാറ്റയും ഇല്ലാതാകുകയും ചെയ്യും."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"നിങ്ങൾ <xliff:g id="NUMBER_0">%1$d</xliff:g> തവണ തെറ്റായ രീതിയിൽ ടാബ്‌ലെറ്റ് അൺലോക്ക് ചെയ്യാൻ ശ്രമിച്ചു. <xliff:g id="NUMBER_1">%2$d</xliff:g> ശ്രമങ്ങൾ കൂടി പരാജയപ്പെട്ടാൽ ഔദ്യോഗിക പ്രൊഫൈൽ നീക്കം ചെയ്യപ്പെടുകയും, അതുവഴി എല്ലാ പ്രൊഫൈൽ ഡാറ്റയും ഇല്ലാതാകുകയും ചെയ്യും."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"നിങ്ങൾ <xliff:g id="NUMBER_0">%1$d</xliff:g> തവണ തെറ്റായ രീതിയിൽ ഫോൺ അൺലോക്ക് ചെയ്യാൻ ശ്രമിച്ചു. <xliff:g id="NUMBER_1">%2$d</xliff:g> ശ്രമങ്ങൾ കൂടി പരാജയപ്പെട്ടാൽ ഔദ്യോഗിക പ്രൊഫൈൽ നീക്കം ചെയ്യപ്പെടുകയും, അതുവഴി എല്ലാ പ്രൊഫൈൽ ഡാറ്റയും ഇല്ലാതാകുകയും ചെയ്യും."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"നിങ്ങൾ <xliff:g id="NUMBER">%d</xliff:g> തവണ തെറ്റായ രീതിയിൽ ടാബ്‌ലെറ്റ് അൺലോക്ക് ചെയ്യാൻ ശ്രമിച്ചു. ഔദ്യോഗിക പ്രൊഫൈൽ നീക്കം ചെയ്യപ്പെടുകയും, അതുവഴി എല്ലാ പ്രൊഫൈൽ ഡാറ്റയും ഇല്ലാതാകുകയും ചെയ്യും."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"നിങ്ങൾ <xliff:g id="NUMBER">%d</xliff:g> തവണ തെറ്റായ രീതിയിൽ ഫോൺ അൺലോക്ക് ചെയ്യാൻ ശ്രമിച്ചു. ഔദ്യോഗിക പ്രൊഫൈൽ നീക്കം ചെയ്യപ്പെടുകയും, അതുവഴി എല്ലാ പ്രൊഫൈൽ ഡാറ്റയും ഇല്ലാതാകുകയും ചെയ്യും."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"നിങ്ങൾ <xliff:g id="NUMBER_0">%1$d</xliff:g> തവണ തെറ്റായ രീതിയിൽ അൺലോക്ക് പാറ്റേൺ വരച്ചു. <xliff:g id="NUMBER_1">%2$d</xliff:g> ശ്രമങ്ങൾ കൂടി പരാജയപ്പെട്ടാൽ, ഒരു ഇമെയിൽ അക്കൗണ്ടുപയോഗിച്ച് ടാബ്‌ലെറ്റ് അൺലോക്ക് ചെയ്യാൻ നിങ്ങളോട് ആവശ്യപ്പെടും.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> സെക്കന്റ് കഴിഞ്ഞ് വീണ്ടും ശ്രമിക്കുക."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"നിങ്ങൾ <xliff:g id="NUMBER_0">%1$d</xliff:g> തവണ തെറ്റായ രീതിയിൽ അൺലോക്ക് പാറ്റേൺ വരച്ചു. <xliff:g id="NUMBER_1">%2$d</xliff:g> ശ്രമങ്ങൾ കൂടി പരാജയപ്പെട്ടാൽ, ഒരു ഇമെയിൽ അക്കൗണ്ടുപയോഗിച്ച് ഫോൺ അൺലോക്ക് ചെയ്യാൻ നിങ്ങളോട് ആവശ്യപ്പെടും.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> സെക്കന്റ് കഴിഞ്ഞ് വീണ്ടും ശ്രമിക്കുക."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-mn/strings.xml b/packages/SystemUI/res-product/values-mn/strings.xml
index 32f3bf9c4633..7f4c52b408f4 100644
--- a/packages/SystemUI/res-product/values-mn/strings.xml
+++ b/packages/SystemUI/res-product/values-mn/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"Таблетад SIM карт алга."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"Утсанд SIM карт алга."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"ПИН код тохирохгүй байна"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Та таблетын түгжээг тайлах оролдлогыг <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу хийлээ. Хэрэв та дахин <xliff:g id="NUMBER_1">%2$d</xliff:g> удаа буруу оруулсан тохиолдолд энэ таблетыг шинэчлэх бөгөөд бүх өгөгдөл нь устах болно."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Та утасны түгжээг тайлах оролдлогыг <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу хийлээ.Хэрэв та дахин <xliff:g id="NUMBER_1">%2$d</xliff:g> удаа буруу оруулсан тохиолдолд энэ утсыг шинэчлэх бөгөөд бүх өгөгдөл нь устах болно."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Та таблетын түгжээг тайлах оролдлогыг <xliff:g id="NUMBER">%d</xliff:g> удаа буруу хийлээ. Энэ таблетыг шинэчлэх бөгөөд ингэснээр бүх өгөгдөл нь устах болно."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Та утасны түгжээг тайлах оролдлогыг <xliff:g id="NUMBER">%d</xliff:g> удаа буруу хийлээ. Энэ утсыг шинэчлэх бөгөөд ингэснээр бүх өгөгдөл нь устах болно."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Та таблетын түгжээг тайлах оролдлогыг <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу хийсэн байна. Хэрэв та дахин <xliff:g id="NUMBER_1">%2$d</xliff:g> удаа буруу оруулсан тохиолдолд энэ хэрэглэгчийг устгах бөгөөд ингэснээр хэрэглэгчийн бүх өгөгдөл устах болно."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Та утасны түгжээг тайлах оролдлогыг <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу хийсэн байна. Хэрэв та дахин <xliff:g id="NUMBER_1">%2$d</xliff:g> удаа буруу оруулсан тохиолдолд энэ хэрэглэгчийг устгах бөгөөд ингэснээр хэрэглэгчийн бүх өгөгдөл устах болно."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Андройд ТВ төхөөрөмж удахгүй унтрах тул асаалттай хэвээр байлгахын тулд товчлуур дээр дарна уу."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Төхөөрөмж удахгүй унтрах тул асаалттай хэвээр байлгахын тулд дарна уу."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Та таблетын түгжээг тайлах оролдогыг <xliff:g id="NUMBER">%d</xliff:g> удаа буруу хийсэн байна. Ажлын профайлыг устгах бөгөөд ингэснээр профайлын бүх өгөгдөл устах болно."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Та утасны түгжээг тайлах оролдлогыг <xliff:g id="NUMBER">%d</xliff:g> удаа буруу хийлээ. Ажлын профайлыг устгах бөгөөд ингэснээр профайлын бүх өгөгдлийг устгах болно."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Та түгжээ тайлах загварыг <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу орууллаа. Хэрэв та дахин <xliff:g id="NUMBER_1">%2$d</xliff:g> удаа буруу оруулсан тохиолдолд таблетынхаа түгжээг имэйл бүртгэлээрээ тайлах шаардлагатай болно.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундын дараа дахин оролдоно уу."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Та түгжээ тайлах загварыг <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу орууллаа. Хэрэв та дахин <xliff:g id="NUMBER_1">%2$d</xliff:g> удаа буруу оруулсан тохиолдолд утасныхаа түгжээг имэйл бүртгэлээрээ тайлах шаардлагатай болно.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундын дараа дахин оролдоно уу."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Илүү хурдан цэнэглэхийн тулд утсыг дахин байрлуулна уу"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Утасгүйгээр цэнэглэхийн тулд утсыг дахин байрлуулна уу"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Android TВ төхөөрөмж удахгүй унтрах тул асаалттай хэвээр байлгахын тулд товчлуурыг дарна уу."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Төхөөрөмж удахгүй унтрах тул асаалттай хэвээр байлгахын тулд дарна уу."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Таблетад SIM карт алга байна."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Утсанд SIM карт алга байна."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"ПИН код тохирохгүй байна"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Та таблетын түгжээг тайлах оролдлогыг <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу хийсэн байна. Дахин <xliff:g id="NUMBER_1">%2$d</xliff:g> удаа буруу хийсний дараа энэ таблетыг шинэчлэх бөгөөд ингэснээр бүх өгөгдлийг нь устгах болно."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Та утасны түгжээг тайлах оролдлогыг <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу хийсэн байна. Дахин <xliff:g id="NUMBER_1">%2$d</xliff:g> удаа буруу хийсний дараа энэ утсыг шинэчлэх бөгөөд ингэснээр бүх өгөгдлийг нь устгах болно."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Та таблетын түгжээг тайлах оролдлогыг <xliff:g id="NUMBER">%d</xliff:g> удаа буруу хийсэн байна. Энэ таблетыг шинэчлэх бөгөөд ингэснээр бүх өгөгдлийг нь устгах болно."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Та утасны түгжээг тайлах оролдлогыг <xliff:g id="NUMBER">%d</xliff:g> удаа буруу хийсэн байна. Энэ утсыг шинэчлэх бөгөөд ингэснээр бүх өгөгдлийг нь устгах болно."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Та таблетын түгжээг тайлах оролдлогыг <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу хийсэн байна. Дахин <xliff:g id="NUMBER_1">%2$d</xliff:g> удаа буруу хийсний дараа энэ хэрэглэгчийг устгах бөгөөд ингэснээр хэрэглэгчийн бүх өгөгдлийг устгах болно."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Та утасны түгжээг тайлах оролдлогыг <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу хийсэн байна. Дахин <xliff:g id="NUMBER_1">%2$d</xliff:g> удаа буруу хийсний дараа энэ хэрэглэгчийг устгах бөгөөд ингэснээр хэрэглэгчийн бүх өгөгдлийг устгах болно."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Та таблетын түгжээг тайлах оролдлогыг <xliff:g id="NUMBER">%d</xliff:g> удаа буруу хийсэн байна. Энэ хэрэглэгчийг устгах бөгөөд ингэснээр хэрэглэгчийн бүх өгөгдлийг устгах болно."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Та утасны түгжээг тайлах оролдлогыг <xliff:g id="NUMBER">%d</xliff:g> удаа буруу хийсэн байна. Энэ хэрэглэгчийг устгах бөгөөд ингэснээр хэрэглэгчийн бүх өгөгдлийг устгах болно."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Та таблетын түгжээг тайлах оролдлогыг <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу хийсэн байна. Дахин <xliff:g id="NUMBER_1">%2$d</xliff:g> удаа буруу хийсний дараа ажлын профайлыг устгах бөгөөд ингэснээр профайлын бүх өгөгдлийг устгах болно."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Та утасны түгжээг тайлах оролдлогыг <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу хийсэн байна. Дахин <xliff:g id="NUMBER_1">%2$d</xliff:g> удаа буруу хийсний ажлын профайлыг устгах бөгөөд ингэснээр профайлын бүх өгөгдлийг устгах болно."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Та таблетын түгжээг тайлах оролдлогыг <xliff:g id="NUMBER">%d</xliff:g> удаа буруу хийсэн байна. Ажлын профайлыг устгах бөгөөд ингэснээр профайлын бүх өгөгдлийг устгах болно."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Та утасны түгжээг тайлах оролдлогыг <xliff:g id="NUMBER">%d</xliff:g> удаа буруу хийсэн байна. Ажлын профайлыг устгах бөгөөд ингэснээр профайлын бүх өгөгдлийг устгах болно."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Та тайлах хээгээ <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу зурсан байна. Дахин <xliff:g id="NUMBER_1">%2$d</xliff:g> удаа буруу зурсны дараа та имэйл бүртгэл ашиглан таблетынхаа түгжээг тайлах шаардлагатай болно.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундийн дараа дахин оролдоно уу."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Та тайлах хээгээ <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу зурсан байна. Дахин <xliff:g id="NUMBER_1">%2$d</xliff:g> удаа буруу зурсны дараа та имэйл бүртгэл ашиглан утасныхаа түгжээг тайлах шаардлагатай болно.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундийн дараа дахин оролдоно уу."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-mr/strings.xml b/packages/SystemUI/res-product/values-mr/strings.xml
index 8ef190e128ef..4a96d839b090 100644
--- a/packages/SystemUI/res-product/values-mr/strings.xml
+++ b/packages/SystemUI/res-product/values-mr/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"टॅबलेटमध्ये सिम कार्ड नाही."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"फोनमध्ये सिम कार्ड नाही."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"पिन कोड जुळत नाहीत"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"तुम्ही टॅबलेट अनलॉक करण्याचा <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा चुकीच्या पद्धतीने प्रयत्न केला आहे. आणखी <xliff:g id="NUMBER_1">%2$d</xliff:g> अयशस्वी प्रयत्नांनंतर, हे टॅबलेट रीसेट केला जाईल, जे त्याचा सर्व डेटा हटवेल."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"तुम्ही फोन अनलॉक करण्याचा <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा चुकीच्या पद्धतीने प्रयत्न केला आहे. आणखी <xliff:g id="NUMBER_1">%2$d</xliff:g> अयशस्वी प्रयत्नांनंतर, हा फोन रीसेट केला जाईल, जे त्याचा सर्व डेटा हटवेल."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"तुम्ही टॅबलेट अनलॉक करण्याचा <xliff:g id="NUMBER">%d</xliff:g> वेळा चुकीच्या पद्धतीने प्रयत्न केला आहे. हे टॅबलेट रीसेट केले जाईल, जे त्याचा सर्व डेटा हटवेल."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"तुम्ही फोन अनलॉक करण्याचा <xliff:g id="NUMBER">%d</xliff:g> वेळा चुकीच्या पद्धतीने प्रयत्न केला आहे. हा फोन रीसेट केला जाईल, जे त्याचा सर्व डेटा हटवेल."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"तुम्ही टॅबलेट अनलॉक करण्याचा <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा चुकीच्या पद्धतीने प्रयत्न केला आहे. आणखी <xliff:g id="NUMBER_1">%2$d</xliff:g> अयशस्वी प्रयत्नांनंतर, या वापरकर्त्याला काढले जाईल, जे सर्व वापरकर्ता डेटा हटवेल."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"तुम्ही फोन अनलॉक करण्याचा <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा चुकीच्या पद्धतीने प्रयत्न केला आहे. आणखी <xliff:g id="NUMBER_1">%2$d</xliff:g> अयशस्वी प्रयत्नांनंतर, या वापरकर्त्याला काढले जाईल, जे सर्व वापरकर्ता डेटा हटवेल."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Android TV डिव्हाइस लवकरच बंद होणार आहे; सुरू ठेवण्यासाठी बटण दाबा."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"डिव्हाइस लवकरच बंद होणार आहे; सुरू ठेवण्यासाठी स्क्रीनवर किंवा बटण दाबा."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"तुम्ही टॅबलेट अनलॉक करण्याचा <xliff:g id="NUMBER">%d</xliff:g> वेळा चुकीच्या पद्धतीने प्रयत्न केला आहे. कार्य प्रोफाइल काढली जाईल, जे सर्व प्रोफाइल डेटा हटवेल."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"तुम्ही फोन अनलॉक करण्याचा <xliff:g id="NUMBER">%d</xliff:g> वेळा चुकीच्या पद्धतीने प्रयत्न केला आहे. कार्य प्रोफाइल काढली जाईल, जे सर्व प्रोफाइल डेटा हटवेल."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"तुम्ही तुमचा अनलॉक पॅटर्न <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा अयोग्यपणे काढला आहे. आणखी <xliff:g id="NUMBER_1">%2$d</xliff:g> अयशस्वी प्रयत्नांनंतर, तुम्हाला ईमेल खाते वापरून तुमचा टॅब्लेट अनलॉक करण्यास सांगितले जाईल.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"तुम्ही तुमचा अनलॉक पॅटर्न <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा अयोग्यपणे काढला आहे. आणखी <xliff:g id="NUMBER_1">%2$d</xliff:g> अयशस्वी प्रयत्नांनंतर, तुम्हाला ईमेल खाते वापरून तुमचा फोन अनलॉक करण्यास सांगितले जाईल.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"फास्ट चार्ज करण्यासाठी फोन पुन्हा अलाइन करा"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"वायरलेस पद्धतीने चार्ज करण्यासाठी फोन पुन्हा अलाइन करा"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Android TV डिव्हाइस लवकरच बंद होणार आहे; सुरू ठेवण्यासाठी बटण दाबा."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"डिव्हाइस लवकरच बंद होणार आहे; ते सुरू ठेवण्यासाठी दाबा."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"टॅबलेटमध्ये सिम कार्ड नाही."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"फोनमध्ये सिम कार्ड नाही."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"पिन कोड जुळत नाहीत"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"तुम्ही टॅबलेट अनलॉक करण्याचा <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा चुकीच्या पद्धतीने प्रयत्न केला आहे. आणखी <xliff:g id="NUMBER_1">%2$d</xliff:g> अयशस्वी प्रयत्नांनंतर, हे टॅबलेट रीसेट केला जाईल, त्यामुळे त्याचा सर्व डेटा हटवला जाईल."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"तुम्ही फोन अनलॉक करण्याचा <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा चुकीच्या पद्धतीने प्रयत्न केला आहे. आणखी <xliff:g id="NUMBER_1">%2$d</xliff:g> अयशस्वी प्रयत्नांनंतर, हा फोन रीसेट केला जाईल, त्यामुळे त्याचा सर्व डेटा हटवला जाईल."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"तुम्ही टॅबलेट अनलॉक करण्याचा <xliff:g id="NUMBER">%d</xliff:g> वेळा चुकीच्या पद्धतीने प्रयत्न केला आहे. हे टॅबलेट रीसेट केले जाईल, त्यामुळे त्याचा सर्व डेटा हटवला जाईल."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"तुम्ही फोन अनलॉक करण्याचा <xliff:g id="NUMBER">%d</xliff:g> वेळा चुकीच्या पद्धतीने प्रयत्न केला आहे. हा फोन रीसेट केला जाईल, त्यामुळे त्याचा सर्व डेटा हटवला जाईल."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"तुम्ही टॅबलेट अनलॉक करण्याचा <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा चुकीच्या पद्धतीने प्रयत्न केला आहे. आणखी <xliff:g id="NUMBER_1">%2$d</xliff:g> अयशस्वी प्रयत्नांनंतर, हा वापरकर्ता काढला जाईल, त्यामुळे सर्व वापरकर्ता डेटा हटवला जाईल."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"तुम्ही फोन अनलॉक करण्याचा <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा चुकीच्या पद्धतीने प्रयत्न केला आहे. आणखी <xliff:g id="NUMBER_1">%2$d</xliff:g> अयशस्वी प्रयत्नांनंतर, हा वापरकर्ता काढला जाईल, त्यामुळे सर्व वापरकर्ता डेटा हटवला जाईल."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"तुम्ही टॅबलेट अनलॉक करण्याचा <xliff:g id="NUMBER">%d</xliff:g> वेळा चुकीच्या पद्धतीने प्रयत्न केला आहे. हा वापरकर्ता काढला जाईल, त्यामुळे सर्व वापरकर्ता डेटा हटवला जाईल."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"तुम्ही फोन अनलॉक करण्याचा <xliff:g id="NUMBER">%d</xliff:g> वेळा चुकीच्या पद्धतीने प्रयत्न केला आहे. या वापरकर्त्याला काढले जाईल, त्यामुळे सर्व वापरकर्ता डेटा हटवला जाईल."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"तुम्ही टॅबलेट अनलॉक करण्याचा <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा चुकीच्या पद्धतीने प्रयत्न केला आहे. आणखी <xliff:g id="NUMBER_1">%2$d</xliff:g> अयशस्वी प्रयत्नांनंतर, ही कार्य प्रोफाइल काढली जाईल, ज्यामुळे सर्व प्रोफाइल डेटा हटवला जाईल."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"तुम्ही फोन अनलॉक करण्याचा <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा चुकीच्या पद्धतीने प्रयत्न केला आहे. आणखी <xliff:g id="NUMBER_1">%2$d</xliff:g> अयशस्वी प्रयत्नांनंतर, कार्य प्रोफाइल काढले जाईल, त्यामुळे सर्व प्रोफाइल डेटा हटवला जाईल."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"तुम्ही टॅबलेट अनलॉक करण्याचा <xliff:g id="NUMBER">%d</xliff:g> वेळा चुकीच्या पद्धतीने प्रयत्न केला आहे. कार्य प्रोफाइल काढली जाईल, त्यामुळे सर्व प्रोफाइल डेटा हटवला जाईल."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"तुम्ही फोन अनलॉक करण्याचा <xliff:g id="NUMBER">%d</xliff:g> वेळा चुकीच्या पद्धतीने प्रयत्न केला आहे. कार्य प्रोफाइल काढली जाईल, त्यामुळे सर्व प्रोफाइल डेटा हटवला जाईल."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"तुम्ही तुमचा अनलॉक पॅटर्न <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा चुकीच्या पद्धतीने काढला आहे. आणखी <xliff:g id="NUMBER_1">%2$d</xliff:g> अयशस्वी प्रयत्नांनंतर, तुम्हाला ईमेल खाते वापरून तुमचा टॅबलेट अनलॉक करण्यास सांगितले जाईल.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"तुम्ही तुमचा अनलॉक पॅटर्न <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा चुकीच्या पद्धतीने काढला आहे. आणखी <xliff:g id="NUMBER_1">%2$d</xliff:g> अयशस्वी प्रयत्नांनंतर, तुम्हाला ईमेल खाते वापरून तुमचा फोन अनलॉक करण्यास सांगितले जाईल.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-ms/strings.xml b/packages/SystemUI/res-product/values-ms/strings.xml
index 5443a543ead5..2aa55b72aaf4 100644
--- a/packages/SystemUI/res-product/values-ms/strings.xml
+++ b/packages/SystemUI/res-product/values-ms/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"Tiada kad SIM dalam tablet."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"Tiada kad SIM dalam telefon."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"Kod PIN tidak sepadan"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Anda telah salah membuka kunci tablet sebanyak <xliff:g id="NUMBER_0">%1$d</xliff:g> kali. Selepas <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi percubaan yang gagal, tablet ini akan ditetapkan semula sekali gus memadamkan semua data."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Anda telah salah membuka kunci telefon sebanyak <xliff:g id="NUMBER_0">%1$d</xliff:g> kali. Selepas <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi percubaan yang gagal, telefon ini akan ditetapkan semula sekali gus memadamkan semua data."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Anda telah salah membuka kunci tablet sebanyak <xliff:g id="NUMBER">%d</xliff:g> kali. Tablet ini akan ditetapkan semula sekali gus memadamkan semua data."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Anda telah salah membuka kunci telefon sebanyak <xliff:g id="NUMBER">%d</xliff:g> kali. Telefon ini akan ditetapkan semula sekali gus memadamkan semua data."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Anda telah salah membuka kunci tablet sebanyak <xliff:g id="NUMBER_0">%1$d</xliff:g> kali. Selepas <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi percubaan yang gagal, pengguna ini akan dialih keluar sekali gus memadamkan semua data pengguna."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Anda telah salah membuka kunci telefon sebanyak <xliff:g id="NUMBER_0">%1$d</xliff:g> kali. Selepas <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi percubaan yang gagal, pengguna ini akan dialih keluar sekali gus memadamkan semua data pengguna."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Peranti Android TV akan mati tidak lama lagi; tekan butang untuk memastikan peranti terus hidup."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Peranti akan mati tidak lama lagi; tekan untuk memastikan peranti terus hidup."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Anda telah salah membuka kunci tablet sebanyak <xliff:g id="NUMBER">%d</xliff:g> kali. Profil kerja ini akan dialih keluar sekali gus memadamkan semua data profil."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Anda telah salah membuka kunci telefon sebanyak <xliff:g id="NUMBER">%d</xliff:g> kali. Profil kerja ini akan dialih keluar sekali gus memadamkan semua data profil."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Anda telah tersilap melukis corak buka kunci sebanyak <xliff:g id="NUMBER_0">%1$d</xliff:g> kali. Selepas <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi percubaan yang gagal, anda akan diminta membuka kunci tablet anda menggunakan akaun e-mel.\n\n Cuba lagi dalam <xliff:g id="NUMBER_2">%3$d</xliff:g> saat."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Anda telah tersilap lukis corak buka kunci sebanyak <xliff:g id="NUMBER_0">%1$d</xliff:g> kali. Selepas <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi percubaan yang gagal, anda akan diminta membuka kunci telefon anda menggunakan akaun e-mel.\n\n Cuba lagi dalam <xliff:g id="NUMBER_2">%3$d</xliff:g> saat."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Jajarkan semula telefon untuk mengecas dengan lebih pantas"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Jajarkan semula telefon untuk mengecas secara wayarles"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Peranti Android TV akan mati tidak lama lagi; tekan butang untuk memastikan peranti terus hidup."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Peranti akan mati tidak lama lagi; tekan untuk memastikan peranti terus hidup."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Tiada kad SIM dalam tablet."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Tiada kad SIM dalam telefon."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"Kod PIN tidak sepadan"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Anda telah salah membuka kunci tablet sebanyak <xliff:g id="NUMBER_0">%1$d</xliff:g> kali. Selepas <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi percubaan yang gagal, tablet ini akan ditetapkan semula sekali gus memadamkan semua data."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Anda telah salah membuka kunci telefon sebanyak <xliff:g id="NUMBER_0">%1$d</xliff:g> kali. Selepas <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi percubaan yang gagal, telefon ini akan ditetapkan semula sekali gus memadamkan semua data."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Anda telah salah membuka kunci tablet sebanyak <xliff:g id="NUMBER">%d</xliff:g> kali. Tablet ini akan ditetapkan semula sekali gus memadamkan semua data."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Anda telah salah membuka kunci telefon sebanyak <xliff:g id="NUMBER">%d</xliff:g> kali. Telefon ini akan ditetapkan semula sekali gus memadamkan semua data."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Anda telah salah membuka kunci tablet sebanyak <xliff:g id="NUMBER_0">%1$d</xliff:g> kali. Selepas <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi percubaan yang gagal, pengguna ini akan dialih keluar sekali gus memadamkan semua data pengguna."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Anda telah salah membuka kunci telefon sebanyak <xliff:g id="NUMBER_0">%1$d</xliff:g> kali. Selepas <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi percubaan yang gagal, pengguna ini akan dialih keluar sekali gus memadamkan semua data pengguna."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Anda telah salah membuka kunci tablet sebanyak <xliff:g id="NUMBER">%d</xliff:g> kali. Pengguna ini akan dialih keluar sekali gus memadamkan semua data pengguna."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Anda telah salah membuka kunci telefon sebanyak <xliff:g id="NUMBER">%d</xliff:g> kali. Pengguna ini akan dialih keluar sekali gus memadamkan semua data pengguna."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Anda telah salah membuka kunci tablet sebanyak <xliff:g id="NUMBER_0">%1$d</xliff:g> kali. Selepas <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi percubaan yang gagal, profil kerja anda akan dialih keluar sekali gus memadamkan semua data profil."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Anda telah salah membuka kunci telefon sebanyak <xliff:g id="NUMBER_0">%1$d</xliff:g> kali. Selepas <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi percubaan yang gagal, profil kerja ini akan dialih keluar sekali gus memadamkan semua data profil."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Anda telah salah membuka kunci tablet sebanyak <xliff:g id="NUMBER">%d</xliff:g> kali. Profil kerja ini akan dialih keluar sekali gus memadamkan semua data profil."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Anda telah salah membuka kunci telefon sebanyak <xliff:g id="NUMBER">%d</xliff:g> kali. Profil kerja ini akan dialih keluar sekali gus memadamkan semua data profil."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Anda telah tersilap lukis corak buka kunci sebanyak <xliff:g id="NUMBER_0">%1$d</xliff:g> kali. Selepas <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi percubaan yang gagal, anda akan diminta membuka kunci tablet anda menggunakan akaun e-mel.\n\n Cuba lagi dalam <xliff:g id="NUMBER_2">%3$d</xliff:g> saat."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Anda telah tersilap lukis corak buka kunci sebanyak <xliff:g id="NUMBER_0">%1$d</xliff:g> kali. Selepas <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi percubaan yang gagal, anda akan diminta membuka kunci telefon anda menggunakan akaun e-mel.\n\n Cuba lagi dalam <xliff:g id="NUMBER_2">%3$d</xliff:g> saat."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-my/strings.xml b/packages/SystemUI/res-product/values-my/strings.xml
index 3f2891df815c..c3d5688c6340 100644
--- a/packages/SystemUI/res-product/values-my/strings.xml
+++ b/packages/SystemUI/res-product/values-my/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"တက်ဘလက်ထဲတွင် ဆင်းမ်ကဒ် မရှိပါ။"</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"ဖုန်းထဲတွင် ဆင်းမ်ကဒ် မရှိပါ။"</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"ပင်နံပါတ် ကိုက်ညီမှုမရှိပါ"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"တက်ဘလက်ကို <xliff:g id="NUMBER_0">%1$d</xliff:g> ကြိမ် မှားယွင်းစွာ လော့ခ်ဖွင့်ရန် ကြိုးစားခဲ့ပါသည်။ <xliff:g id="NUMBER_1">%2$d</xliff:g> ကြိမ် ထပ်မံမှားယွင်းခဲ့လျှင် ဤတက်ဘလက်ကို ပြင်ဆင်သတ်မှတ်လိုက်မည် ဖြစ်ပြီး ၎င်းအတွင်းရှိ ဒေတာများအားလုံးကိုလည်း ဖျက်လိုက်ပါမည်။"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"ဖုန်းကို <xliff:g id="NUMBER_0">%1$d</xliff:g> ကြိမ် မှားယွင်းစွာ လော့ခ်ဖွင့်ရန် ကြိုးစားခဲ့ပါသည်။ <xliff:g id="NUMBER_1">%2$d</xliff:g> ကြိမ် ထပ်မံမှားယွင်းခဲ့လျှင် ဤဖုန်းကို ပြင်ဆင်သတ်မှတ်လိုက်မည် ဖြစ်ပြီး ၎င်းအတွင်းရှိ ဒေတာများအားလုံးကိုလည်း ဖျက်လိုက်ပါမည်။"</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"တက်ဘလက်ကို <xliff:g id="NUMBER">%d</xliff:g> ကြိမ် မှားယွင်းစွာ လော့ခ်ဖွင့်ရန် ကြိုးစားခဲ့ပါသည်။ ဤတက်ဘလက်ကို ပြင်ဆင်သတ်မှတ်လိုက်မည် ဖြစ်ပြီး ၎င်းအတွင်းရှိ ဒေတာများအားလုံးကိုလည်း ဖျက်လိုက်ပါမည်။"</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"ဖုန်းကို <xliff:g id="NUMBER">%d</xliff:g> ကြိမ် မှားယွင်းစွာ လော့ခ်ဖွင့်ရန် ကြိုးစားခဲ့ပါသည်။ ဤဖုန်းကို ပြင်ဆင်သတ်မှတ်လိုက်မည် ဖြစ်ပြီး ၎င်းအတွင်းရှိ ဒေတာများအားလုံးကိုလည်း ဖျက်လိုက်ပါမည်။"</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"တက်ဘလက်ကို <xliff:g id="NUMBER_0">%1$d</xliff:g> ကြိမ် မှားယွင်းစွာ လော့ခ်ဖွင့်ရန် ကြိုးစားခဲ့ပါသည်။ <xliff:g id="NUMBER_1">%2$d</xliff:g> ကြိမ် ထပ်မံမှားယွင်းခဲ့လျှင် ဤအသုံးပြုသူကို ဖယ်ရှားလိုက်မည်ဖြစ်ပြီး အသုံးပြုသူဒေတာများ အားလုံးကိုလည်း ဖျက်လိုက်ပါမည်။"</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"ဖုန်းကို <xliff:g id="NUMBER_0">%1$d</xliff:g> ကြိမ် မှားယွင်းစွာ လော့ခ်ဖွင့်ရန် ကြိုးစားခဲ့ပါသည်။ <xliff:g id="NUMBER_1">%2$d</xliff:g> ကြိမ် ထပ်မံမှားယွင်းသွားလျှင် ဤအသုံးပြုသူကို ဖယ်ရှားလိုက်မည်ဖြစ်ပြီး အသုံးပြုသူဒေတာများ အားလုံးကိုလည်း ဖျက်လိုက်ပါမည်။"</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Android TV စက်သည် မကြာမီ ပိတ်သွားပါမည်၊ ဆက်ဖွင့်ထားရန် ခလုတ်တစ်ခုနှိပ်ပါ။"</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"စက်သည် မကြာမီ ပိတ်သွားပါမည်၊ ဆက်ဖွင့်ထားပါ။"</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"တက်ဘလက်ကို <xliff:g id="NUMBER">%d</xliff:g> ကြိမ် မှားယွင်းစွာ လော့ခ်ဖွင့်ရန် ကြိုးစားခဲ့ပါသည်။ အလုပ်ပရိုဖိုင်ကို ဖယ်ရှားလိုက်မည်ဖြစ်ပြီး ပရိုဖိုင်ဒေတာများ အားလုံးကိုလည်း ဖျက်လိုက်ပါမည်။"</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"ဖုန်းကို <xliff:g id="NUMBER">%d</xliff:g> ကြိမ် မှားယွင်းစွာ လော့ခ်ဖွင့်ရန် ကြိုးစားခဲ့ပါသည်။ အလုပ်ပရိုဖိုင်ကို ဖယ်ရှားလိုက်မည်ဖြစ်ပြီး ပရိုဖိုင်ဒေတာများ အားလုံးကိုလည်း ဖျက်လိုက်ပါမည်။"</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"သင်သည် သင်၏ လော့ခ်ဖွင့်ခြင်းပုံစံကို <xliff:g id="NUMBER_0">%1$d</xliff:g> ကြိမ် မှားယွင်းစွာ ဆွဲခဲ့ပါသည်။ <xliff:g id="NUMBER_1">%2$d</xliff:g> ကြိမ် ထပ်မံမှားယွင်းပြီးသည့်နောက်တွင် သင့်အီးမေးလ်အကောင့်အား အသုံးပြု၍ တက်ဘလက်ကို လော့ခ်ဖွင့်ရန် တောင်းဆိုသွားပါမည်။\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> စက္ကန့်အကြာတွင် ထပ်စမ်းကြည့်ပါ။"</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"သင်သည် သင်၏ လော့ခ်ဖွင့်ခြင်းပုံစံကို <xliff:g id="NUMBER_0">%1$d</xliff:g> ကြိမ် မှားယွင်းစွာ ဆွဲခဲ့ပါသည်။ <xliff:g id="NUMBER_1">%2$d</xliff:g> ကြိမ် ထပ်မံမှားယွင်းပြီးသည့်နောက်တွင် သင့်အီးမေးလ်အကောင့်အား အသုံးပြု၍ ဖုန်းကို လော့ခ်ဖွင့်ရန် တောင်းဆိုသွားပါမည်။\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> စက္ကန့်အကြာတွင် ထပ်စမ်းကြည့်ပါ။"</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"ဖုန်းကို မြန်ဆန်စွာ အားသွင်းနိုင်ရန် ပြန်၍ချိန်ပါ"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"ကြိုးမဲ့အားသွင်းရန် ဖုန်းကို ပြန်၍ချိန်ပါ"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Android TV စက်သည် မကြာမီ ပိတ်သွားပါမည်၊ ဆက်ဖွင့်ထားရန် ခလုတ်တစ်ခုကို နှိပ်ပါ။"</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"စက်သည် မကြာမီ ပိတ်သွားပါမည်၊ ဆက်ဖွင့်ထားရန် နှိပ်ပါ။"</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"တက်ဘလက်ထဲတွင် ဆင်းမ်ကတ် မရှိပါ။"</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"ဖုန်းထဲတွင် ဆင်းမ်ကတ် မရှိပါ။"</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"ပင်နံပါတ် ကိုက်ညီမှု မရှိပါ"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"တက်ဘလက်ကို <xliff:g id="NUMBER_0">%1$d</xliff:g> ကြိမ် မှားယွင်းစွာ လော့ခ်ဖွင့်ရန် ကြိုးစားခဲ့ပါသည်။ <xliff:g id="NUMBER_1">%2$d</xliff:g> ကြိမ် ထပ်မံမှားယွင်းခဲ့လျှင် ဤတက်ဘလက်ကို ပြင်ဆင်သတ်မှတ်လိုက်မည် ဖြစ်ပြီး ၎င်းအတွင်းရှိ ဒေတာအားလုံးကိုလည်း ဖျက်လိုက်ပါမည်။"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"ဖုန်းကို <xliff:g id="NUMBER_0">%1$d</xliff:g> ကြိမ် မှားယွင်းစွာ လော့ခ်ဖွင့်ရန် ကြိုးစားခဲ့ပါသည်။ <xliff:g id="NUMBER_1">%2$d</xliff:g> ကြိမ် ထပ်မံမှားယွင်းခဲ့လျှင် ဤဖုန်းကို ပြင်ဆင်သတ်မှတ်လိုက်မည် ဖြစ်ပြီး ၎င်းအတွင်းရှိ ဒေတာအားလုံးကိုလည်း ဖျက်လိုက်ပါမည်။"</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"တက်ဘလက်ကို <xliff:g id="NUMBER">%d</xliff:g> ကြိမ် မှားယွင်းစွာ လော့ခ်ဖွင့်ရန် ကြိုးစားခဲ့ပါသည်။ ဤတက်ဘလက်ကို ပြင်ဆင်သတ်မှတ်လိုက်မည် ဖြစ်ပြီး ၎င်းအတွင်းရှိ ဒေတာအားလုံးကိုလည်း ဖျက်လိုက်ပါမည်။"</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"ဖုန်းကို <xliff:g id="NUMBER">%d</xliff:g> ကြိမ် မှားယွင်းစွာ လော့ခ်ဖွင့်ရန် ကြိုးစားခဲ့ပါသည်။ ဤဖုန်းကို ပြင်ဆင်သတ်မှတ်လိုက်မည် ဖြစ်ပြီး ၎င်းအတွင်းရှိ ဒေတာအားလုံးကိုလည်း ဖျက်လိုက်ပါမည်။"</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"တက်ဘလက်ကို <xliff:g id="NUMBER_0">%1$d</xliff:g> ကြိမ် မှားယွင်းစွာ လော့ခ်ဖွင့်ရန် ကြိုးစားခဲ့ပါသည်။ <xliff:g id="NUMBER_1">%2$d</xliff:g> ကြိမ် ထပ်မံမှားယွင်းခဲ့လျှင် ဤအသုံးပြုသူကို ဖယ်ရှားလိုက်မည်ဖြစ်ပြီး အသုံးပြုသူဒေတာအားလုံးကိုလည်း ဖျက်လိုက်ပါမည်။"</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"ဖုန်းကို <xliff:g id="NUMBER_0">%1$d</xliff:g> ကြိမ် မှားယွင်းစွာ လော့ခ်ဖွင့်ရန် ကြိုးစားခဲ့ပါသည်။ <xliff:g id="NUMBER_1">%2$d</xliff:g> ကြိမ် ထပ်မံမှားယွင်းသွားလျှင် ဤအသုံးပြုသူကို ဖယ်ရှားလိုက်မည်ဖြစ်ပြီး အသုံးပြုသူဒေတာအားလုံးကိုလည်း ဖျက်လိုက်ပါမည်။"</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"တက်ဘလက်ကို <xliff:g id="NUMBER">%d</xliff:g> ကြိမ် မှားယွင်းစွာ လော့ခ်ဖွင့်ရန် ကြိုးစားခဲ့ပါသည်။ ဤအသုံးပြုသူကို ဖယ်ရှားလိုက်မည်ဖြစ်ပြီး အသုံးပြုသူဒေတာအားလုံးကိုလည်း ဖျက်လိုက်ပါမည်။"</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"ဖုန်းကို <xliff:g id="NUMBER">%d</xliff:g> ကြိမ် မှားယွင်းစွာ လော့ခ်ဖွင့်ရန် ကြိုးစားခဲ့ပါသည်။ ဤအသုံးပြုသူကို ဖယ်ရှားလိုက်မည်ဖြစ်ပြီး အသုံးပြုသူဒေတာအားလုံးကိုလည်း ဖျက်လိုက်ပါမည်။"</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"တက်ဘလက်ကို <xliff:g id="NUMBER_0">%1$d</xliff:g> ကြိမ် မှားယွင်းစွာ လော့ခ်ဖွင့်ရန် ကြိုးစားခဲ့ပါသည်။ <xliff:g id="NUMBER_1">%2$d</xliff:g> ကြိမ် ထပ်မံ မှားယွင်းသွားလျှင် အလုပ်ပရိုဖိုင်ကို ဖယ်ရှားလိုက်မည်ဖြစ်ပြီး ပရိုဖိုင်ဒေတာအားလုံးကိုလည်း ဖျက်လိုက်ပါမည်။"</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"ဖုန်းကို <xliff:g id="NUMBER_0">%1$d</xliff:g> ကြိမ် မှားယွင်းစွာ လော့ခ်ဖွင့်ရန် ကြိုးစားခဲ့ပါသည်။ <xliff:g id="NUMBER_1">%2$d</xliff:g> ကြိမ် ထပ်မံမှားယွင်းသွားလျှင် အလုပ်ပရိုဖိုင်ကို ဖယ်ရှားလိုက်မည်ဖြစ်ပြီး ပရိုဖိုင်ဒေတာ အားလုံးကိုလည်း ဖျက်လိုက်ပါမည်။"</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"တက်ဘလက်ကို <xliff:g id="NUMBER">%d</xliff:g> ကြိမ် မှားယွင်းစွာ လော့ခ်ဖွင့်ရန် ကြိုးစားခဲ့ပါသည်။ အလုပ်ပရိုဖိုင်ကို ဖယ်ရှားလိုက်မည်ဖြစ်ပြီး ပရိုဖိုင်ဒေတာအားလုံးကိုလည်း ဖျက်လိုက်ပါမည်။"</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"ဖုန်းကို <xliff:g id="NUMBER">%d</xliff:g> ကြိမ် မှားယွင်းစွာ လော့ခ်ဖွင့်ရန် ကြိုးစားခဲ့ပါသည်။ အလုပ်ပရိုဖိုင်ကို ဖယ်ရှားလိုက်မည်ဖြစ်ပြီး ပရိုဖိုင်ဒေတာ အားလုံးကိုလည်း ဖျက်လိုက်ပါမည်။"</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"သင်သည် သင်၏ လော့ခ်ဖွင့်ခြင်းပုံစံကို <xliff:g id="NUMBER_0">%1$d</xliff:g> ကြိမ် မှားယွင်းစွာ ဆွဲခဲ့ပါသည်။ <xliff:g id="NUMBER_1">%2$d</xliff:g> ကြိမ် ထပ်မံမှားယွင်းပြီးသည့်နောက်တွင် သင့်အီးမေးလ်အကောင့်အား အသုံးပြု၍ တက်ဘလက်ကို လော့ခ်ဖွင့်ရန် တောင်းဆိုသွားပါမည်။\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> စက္ကန့်အကြာတွင် ထပ်စမ်းကြည့်ပါ။"</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"သင်သည် သင်၏ လော့ခ်ဖွင့်ခြင်းပုံစံကို <xliff:g id="NUMBER_0">%1$d</xliff:g> ကြိမ် မှားယွင်းစွာ ဆွဲခဲ့ပါသည်။ <xliff:g id="NUMBER_1">%2$d</xliff:g> ကြိမ် ထပ်မံမှားယွင်းပြီးသည့်နောက်တွင် သင့်အီးမေးလ်အကောင့်အား အသုံးပြု၍ ဖုန်းကို လော့ခ်ဖွင့်ရန် တောင်းဆိုသွားပါမည်။\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> စက္ကန့်အကြာတွင် ထပ်စမ်းကြည့်ပါ။"</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-nb/strings.xml b/packages/SystemUI/res-product/values-nb/strings.xml
index 6608b25af1d5..021bac9bff7b 100644
--- a/packages/SystemUI/res-product/values-nb/strings.xml
+++ b/packages/SystemUI/res-product/values-nb/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"Nettbrettet mangler SIM-kort."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"Telefonen mangler SIM-kort."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"PIN-kodene stemmer ikke overens"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Du har gjort feil i forsøket på å låse opp nettbrettet <xliff:g id="NUMBER_0">%1$d</xliff:g> ganger. Nettbrettet tilbakestilles etter <xliff:g id="NUMBER_1">%2$d</xliff:g> nye mislykkede forsøk, noe som sletter alle dataene på nettbrettet."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Du har gjort feil i forsøket på å låse opp telefonen <xliff:g id="NUMBER_0">%1$d</xliff:g> ganger. Telefonen tilbakestilles etter <xliff:g id="NUMBER_1">%2$d</xliff:g> nye mislykkede forsøk, noe som sletter alle dataene på telefonen."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Du har gjort feil i forsøket på å låse opp nettbrettet <xliff:g id="NUMBER">%d</xliff:g> ganger. Dette nettbrettet blir tilbakestilt, og alle dataene blir slettet."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Du har gjort feil i forsøket på å låse opp telefonen <xliff:g id="NUMBER">%d</xliff:g> ganger. Denne telefonen blir tilbakestilt, og alle dataene blir slettet."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Du har gjort feil i forsøket på å låse opp nettbrettet <xliff:g id="NUMBER_0">%1$d</xliff:g> ganger. Brukeren fjernes etter <xliff:g id="NUMBER_1">%2$d</xliff:g> nye mislykkede forsøk, noe som sletter alle brukerdataene."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Du har gjort feil i forsøket på å låse opp telefonen <xliff:g id="NUMBER_0">%1$d</xliff:g> ganger. Brukeren fjernes etter <xliff:g id="NUMBER_1">%2$d</xliff:g> nye mislykkede forsøk, noe som sletter alle brukerdataene."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Android TV-enheten slås snart av. Trykk på en knapp for å holde den på."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Enheten slås snart av. Trykk for å holde den på."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Du har gjort feil i forsøket på å låse opp nettbrettet <xliff:g id="NUMBER">%d</xliff:g> ganger. Jobbprofilen blir fjernet, og alle profildataene blir slettet."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Du har gjort feil i forsøket på å låse opp telefonen <xliff:g id="NUMBER">%d</xliff:g> ganger. Jobbprofilen blir fjernet, og alle profildataene blir slettet."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Du har tegnet opplåsingsmønsteret feil <xliff:g id="NUMBER_0">%1$d</xliff:g> ganger. Etter ytterligere <xliff:g id="NUMBER_1">%2$d</xliff:g> feil forsøk blir du bedt om å låse opp nettbrettet via en e-postkonto.\n\n Prøv på nytt om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Du har tegnet opplåsingsmønsteret feil <xliff:g id="NUMBER_0">%1$d</xliff:g> ganger. Etter ytterligere <xliff:g id="NUMBER_1">%2$d</xliff:g> feil forsøk blir du bedt om å låse opp telefonen via en e-postkonto.\n\n Prøv på nytt om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Juster telefonen for å lade raskere"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Juster telefonen for å lade trådløst"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Android TV-enheten slås snart av. Trykk på en knapp for å holde den på."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Enheten slås snart av. Trykk for å holde den på."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Nettbrettet mangler SIM-kort."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Telefonen mangler SIM-kort."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"PIN-kodene stemmer ikke overens"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Du har gjort feil i forsøket på å låse opp nettbrettet <xliff:g id="NUMBER_0">%1$d</xliff:g> ganger. Nettbrettet tilbakestilles etter <xliff:g id="NUMBER_1">%2$d</xliff:g> nye mislykkede forsøk, noe som sletter alle dataene på nettbrettet."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Du har gjort feil i forsøket på å låse opp telefonen <xliff:g id="NUMBER_0">%1$d</xliff:g> ganger. Telefonen tilbakestilles etter <xliff:g id="NUMBER_1">%2$d</xliff:g> nye mislykkede forsøk, noe som sletter alle dataene på telefonen."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Du har gjort feil i forsøket på å låse opp nettbrettet <xliff:g id="NUMBER">%d</xliff:g> ganger. Dette nettbrettet blir tilbakestilt, og alle dataene blir slettet."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Du har gjort feil i forsøket på å låse opp telefonen <xliff:g id="NUMBER">%d</xliff:g> ganger. Denne telefonen blir tilbakestilt, og alle dataene blir slettet."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Du har gjort feil i forsøket på å låse opp nettbrettet <xliff:g id="NUMBER_0">%1$d</xliff:g> ganger. Brukeren fjernes etter <xliff:g id="NUMBER_1">%2$d</xliff:g> nye mislykkede forsøk, noe som sletter alle brukerdataene."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Du har gjort feil i forsøket på å låse opp telefonen <xliff:g id="NUMBER_0">%1$d</xliff:g> ganger. Brukeren fjernes etter <xliff:g id="NUMBER_1">%2$d</xliff:g> nye mislykkede forsøk, noe som sletter alle brukerdataene."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Du har gjort feil i forsøket på å låse opp nettbrettet <xliff:g id="NUMBER">%d</xliff:g> ganger. Denne brukeren blir fjernet, og alle brukerdataene blir slettet."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Du har gjort feil i forsøket på å låse opp telefonen <xliff:g id="NUMBER">%d</xliff:g> ganger. Denne brukeren blir fjernet, og alle brukerdataene blir slettet."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Du har gjort feil i forsøket på å låse opp nettbrettet <xliff:g id="NUMBER_0">%1$d</xliff:g> ganger. Jobbprofilen fjernes etter <xliff:g id="NUMBER_1">%2$d</xliff:g> nye mislykkede forsøk, noe som sletter alle profildataene."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Du har gjort feil i forsøket på å låse opp telefonen <xliff:g id="NUMBER_0">%1$d</xliff:g> ganger. Jobbprofilen fjernes etter <xliff:g id="NUMBER_1">%2$d</xliff:g> nye mislykkede forsøk, noe som sletter alle profildataene."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Du har gjort feil i forsøket på å låse opp nettbrettet <xliff:g id="NUMBER">%d</xliff:g> ganger. Jobbprofilen blir fjernet, og alle profildataene blir slettet."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Du har gjort feil i forsøket på å låse opp telefonen <xliff:g id="NUMBER">%d</xliff:g> ganger. Jobbprofilen blir fjernet, og alle profildataene blir slettet."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Du har tegnet opplåsingsmønsteret feil <xliff:g id="NUMBER_0">%1$d</xliff:g> ganger. Etter ytterligere <xliff:g id="NUMBER_1">%2$d</xliff:g> nye mislykkede forsøk blir du bedt om å låse opp nettbrettet via en e-postkonto.\n\n Prøv på nytt om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Du har tegnet opplåsingsmønsteret feil <xliff:g id="NUMBER_0">%1$d</xliff:g> ganger. Etter ytterligere <xliff:g id="NUMBER_1">%2$d</xliff:g> nye mislykkede forsøk blir du bedt om å låse opp telefonen via en e-postkonto.\n\n Prøv på nytt om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-ne/strings.xml b/packages/SystemUI/res-product/values-ne/strings.xml
index 2361ac9b2bac..463e29d602bc 100644
--- a/packages/SystemUI/res-product/values-ne/strings.xml
+++ b/packages/SystemUI/res-product/values-ne/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"ट्याब्लेटमा SIM कार्ड छैन।"</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"फोनमा SIM कार्ड छैन।"</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"PIN कोडहरू मिलेनन्"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"तपाईंले <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक गलत तरिकाले ट्याब्लेट अनलक गर्ने प्रयास गर्नुभएको छ। थप <xliff:g id="NUMBER_1">%2$d</xliff:g> असफल प्रयासहरूपछि, यो ट्याब्लेट यसमा भएका सबै डेटा मेटिने गरी रिसेट हुनेछ।"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"तपाईंले <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक गलत तरिकाले फोन अनलक गर्ने प्रयास गर्नुभएको छ। थप <xliff:g id="NUMBER_1">%2$d</xliff:g> असफल प्रयासहरूपछि, यो फोन यसमा भएका सबै डेटा मेटिने गरी रिसेट हुनेछ।"</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"तपाईंले <xliff:g id="NUMBER">%d</xliff:g> पटक गलत तरिकाले ट्याब्लेट अनलक गर्ने प्रयास गर्नुभएको छ। यो ट्याब्लेट यसमा भएका सबै डेटा मेटिने गरी रिसेट हुनेछ।"</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"तपाईंले <xliff:g id="NUMBER">%d</xliff:g> पटक गलत तरिकाले फोन अनलक गर्ने प्रयास गर्नुभएको छ। यो फोन यसमा भएका सबै डेटा मेटिने गरी रिसेट हुनेछ।"</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"तपाईंले <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक गलत तरिकाले ट्याब्लेट अनलक गर्ने प्रयास गर्नुभएको छ। थप <xliff:g id="NUMBER_1">%2$d</xliff:g> असफल प्रयासहरूपछि, यस प्रयोगकर्तालाई यसका सबै डेटा मेटिने गरी हटाइने छ।"</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"तपाईंले <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक गलत तरिकाले फोन अनलक गर्ने प्रयास गर्नुभएको छ। थप <xliff:g id="NUMBER_1">%2$d</xliff:g> असफल प्रयासहरूपछि, यस प्रयोगकर्तालाई यसका सबै डेटा मेटिने गरी हटाइने छ।"</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Android TV यन्त्र चाँडै निष्क्रिय हुने छ; सक्रिय राख्न कुनै बटन थिच्नुहोस्।"</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"यो यन्त्र चाँडै निष्क्रिय हुने छ; सक्रिय राख्न थिच्नुहोस्।"</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"तपाईं <xliff:g id="NUMBER">%d</xliff:g> पटक गलत तरिकाले ट्याब्लेट अनलक गर्ने प्रयास गर्नुभएको छ। कार्य प्रोफाइललाई यसका सबै डेटा मेटिने गरी हटाइने छ।"</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"तपाईंले <xliff:g id="NUMBER">%d</xliff:g> पटक गलत तरिकाले फोन अनलक गर्ने प्रयास गर्नुभएको छ। कार्य प्रोफाइललाई यसका सबै डेटा मेटिने गरी हटाइने छ।"</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"तपाईंले <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक आफ्नो अनलक गर्ने ढाँचा गलत रूपमा कोर्नुभयो। थप <xliff:g id="NUMBER_1">%2$d</xliff:g> असफल प्रयासहरूपछि, तपाईंलाई एउटा इमेल खाता प्रयोग गरेर आफ्नो ट्याब्लेट अनलक गर्न आग्रह गरिनेछ।\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> सेकेन्डमा फेरि प्रयास गर्नुहोस्।"</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"तपाईंले <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक आफ्नो अनलक गर्ने ढाँचा गलत रूपमा कोर्नुभयो। थप <xliff:g id="NUMBER_1">%2$d</xliff:g> असफल प्रयासहरूपछि, तपाईंलाई एउटा इमेल खाता प्रयोग गरेर आफ्नो फोन अनलक गर्न आग्रह गरिनेछ।\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> सेकेन्डमा फेरि प्रयास गर्नुहोस्।"</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"अझ छिटो चार्ज गर्न फोनलाई फेरि मिलाउनुहोस्"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"तारविनै चार्ज गर्न फोनलाई फेरि मिलाउनुहोस्"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Android TV यन्त्र चाँडै निष्क्रिय हुने छ; सक्रिय राख्न कुनै बटन थिच्नुहोस्।"</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"यो यन्त्र चाँडै निष्क्रिय हुने छ; सक्रिय राख्न थिच्नुहोस्।"</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"ट्याब्लेटमा SIM कार्ड छैन।"</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"फोनमा SIM कार्ड छैन।"</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"PIN कोडहरू मिलेनन्"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"तपाईंले <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक गलत तरिकाले ट्याब्लेट अनलक गर्ने प्रयास गर्नुभएको छ। थप <xliff:g id="NUMBER_1">%2$d</xliff:g> पटक असफल प्रयास गरेपछि, यो ट्याब्लेट यसमा भएका सबै डेटा मेटिने गरी रिसेट गरिने छ।"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"तपाईंले <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक गलत तरिकाले फोन अनलक गर्ने प्रयास गर्नुभएको छ। थप <xliff:g id="NUMBER_1">%2$d</xliff:g> पटक असफल प्रयास गरेपछि, यो फोन यसमा भएका सबै डेटा मेटिने गरी रिसेट गरिने छ।"</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"तपाईंले <xliff:g id="NUMBER">%d</xliff:g> पटक गलत तरिकाले ट्याब्लेट अनलक गर्ने प्रयास गर्नुभएको छ। यो ट्याब्लेट यसमा भएका सबै डेटा मेटिने गरी रिसेट गरिने छ।"</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"तपाईंले <xliff:g id="NUMBER">%d</xliff:g> पटक गलत तरिकाले फोन अनलक गर्ने प्रयास गर्नुभएको छ। यो फोन यसमा भएका सबै डेटा मेटिने गरी रिसेट गरिने छ।"</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"तपाईंले <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक गलत तरिकाले ट्याब्लेट अनलक गर्ने प्रयास गर्नुभएको छ। थप <xliff:g id="NUMBER_1">%2$d</xliff:g> पटक असफल प्रयास गरेपछि, यस प्रयोगकर्तालाई यसका सबै डेटा मेटिने गरी हटाइने छ।"</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"तपाईंले <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक गलत तरिकाले फोन अनलक गर्ने प्रयास गर्नुभएको छ। थप <xliff:g id="NUMBER_1">%2$d</xliff:g> पटक असफल प्रयास गरेपछि, यस प्रयोगकर्तालाई यसका सबै डेटा मेटिने गरी हटाइने छ।"</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"तपाईंले <xliff:g id="NUMBER">%d</xliff:g> पटक गलत तरिकाले ट्याब्लेट अनलक गर्ने प्रयास गर्नुभएको छ। यो प्रयोगकर्तालाई यसका सबै डेटा मेटिने गरी हटाइने छ।"</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"तपाईंले <xliff:g id="NUMBER">%d</xliff:g> पटक गलत तरिकाले फोन अनलक गर्ने प्रयास गर्नुभएको छ। यस प्रयोगकर्तालाई यसका सबै डेटा मेटिने गरी हटाइने छ।"</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"तपाईंले <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक गलत तरिकाले ट्याब्लेट अनलक गर्ने प्रयास गर्नुभएको छ। थप <xliff:g id="NUMBER_1">%2$d</xliff:g> पटक असफल प्रयास गरेपछि, कार्य प्रोफाइललाई यसको सबै डेटा मेटिने गरी हटाइने छ।"</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"तपाईंले <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक गलत तरिकाले फोन अनलक गर्ने प्रयास गर्नुभएको छ। थप <xliff:g id="NUMBER_1">%2$d</xliff:g> पटक असफल प्रयास गरेपछि, कार्य प्रोफाइललाई यसको सबै डेटा मेटिने गरी हटाइने छ।"</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"तपाईं <xliff:g id="NUMBER">%d</xliff:g> पटक गलत तरिकाले ट्याब्लेट अनलक गर्ने प्रयास गर्नुभएको छ। कार्य प्रोफाइललाई यसका सबै डेटा मेटिने गरी हटाइने छ।"</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"तपाईंले <xliff:g id="NUMBER">%d</xliff:g> पटक गलत तरिकाले फोन अनलक गर्ने प्रयास गर्नुभएको छ। कार्य प्रोफाइललाई यसका सबै डेटा मेटिने गरी हटाइने छ।"</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"तपाईंले <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक आफ्नो अनलक गर्ने ढाँचा गलत रूपमा कोर्नुभयो। थप <xliff:g id="NUMBER_1">%2$d</xliff:g> पटक असफल प्रयास गरेपछि, तपाईंलाई एउटा इमेल खाता प्रयोग गरेर आफ्नो ट्याब्लेट अनलक गर्न आग्रह गरिने छ।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकेन्डमा फेरि प्रयास गर्नुहोस्।"</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"तपाईंले <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक आफ्नो अनलक गर्ने ढाँचा गलत रूपमा कोर्नुभयो। थप <xliff:g id="NUMBER_1">%2$d</xliff:g> पटक असफल प्रयास गरेपछि, तपाईंलाई एउटा इमेल खाता प्रयोग गरेर आफ्नो फोन अनलक गर्न आग्रह गरिने छ।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकेन्डमा फेरि प्रयास गर्नुहोस्।"</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-nl/strings.xml b/packages/SystemUI/res-product/values-nl/strings.xml
index 6f71d987fc1a..3be686c1c1fa 100644
--- a/packages/SystemUI/res-product/values-nl/strings.xml
+++ b/packages/SystemUI/res-product/values-nl/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"Geen simkaart in tablet."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"Geen simkaart in telefoon."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"Pincodes komen niet overeen"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Je hebt <xliff:g id="NUMBER_0">%1$d</xliff:g> mislukte pogingen ondernomen om de tablet te ontgrendelen. Na nog eens <xliff:g id="NUMBER_1">%2$d</xliff:g> mislukte pogingen wordt deze tablet gereset, waardoor alle gegevens worden verwijderd."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Je hebt <xliff:g id="NUMBER_0">%1$d</xliff:g> mislukte pogingen ondernomen om de telefoon te ontgrendelen. Na nog eens <xliff:g id="NUMBER_1">%2$d</xliff:g> mislukte pogingen wordt deze telefoon gereset, waardoor alle gegevens worden verwijderd."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Je hebt <xliff:g id="NUMBER">%d</xliff:g> mislukte pogingen ondernomen om de tablet te ontgrendelen. Deze tablet wordt gereset, waardoor alle gegevens worden verwijderd."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Je hebt <xliff:g id="NUMBER">%d</xliff:g> mislukte pogingen ondernomen om de telefoon te ontgrendelen. Deze telefoon wordt gereset, waardoor alle gegevens worden verwijderd."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Je hebt <xliff:g id="NUMBER_0">%1$d</xliff:g> mislukte pogingen ondernomen om de tablet te ontgrendelen. Na nog eens <xliff:g id="NUMBER_1">%2$d</xliff:g> mislukte pogingen wordt deze gebruiker verwijderd, waardoor alle gebruikersgegevens worden verwijderd."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Je hebt <xliff:g id="NUMBER_0">%1$d</xliff:g> mislukte pogingen ondernomen om de telefoon te ontgrendelen. Na nog eens <xliff:g id="NUMBER_1">%2$d</xliff:g> mislukte pogingen wordt deze gebruiker verwijderd, waardoor alle gebruikersgegevens worden verwijderd."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Het Android TV-apparaat wordt binnenkort uitgeschakeld. Druk op een knop om het ingeschakeld te houden."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Het apparaat wordt binnenkort uitgeschakeld. Druk om het ingeschakeld te houden."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Je hebt <xliff:g id="NUMBER">%d</xliff:g> mislukte pogingen ondernomen om de tablet te ontgrendelen. Het werkprofiel wordt verwijderd, waardoor alle profielgegevens worden verwijderd."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Je hebt <xliff:g id="NUMBER">%d</xliff:g> mislukte pogingen ondernomen om de telefoon te ontgrendelen. Het werkprofiel wordt verwijderd, waardoor alle profielgegevens worden verwijderd."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Je hebt je ontgrendelingspatroon <xliff:g id="NUMBER_0">%1$d</xliff:g> keer onjuist getekend. Na nog eens <xliff:g id="NUMBER_1">%2$d</xliff:g> mislukte pogingen wordt je gevraagd je tablet te ontgrendelen via een e-mailaccount.\n\n Probeer het over <xliff:g id="NUMBER_2">%3$d</xliff:g> seconden opnieuw."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Je hebt je ontgrendelingspatroon <xliff:g id="NUMBER_0">%1$d</xliff:g> keer onjuist getekend. Na nog eens <xliff:g id="NUMBER_1">%2$d</xliff:g> mislukte pogingen wordt je gevraagd je telefoon te ontgrendelen via een e-mailaccount.\n\n Probeer het over <xliff:g id="NUMBER_2">%3$d</xliff:g> seconden opnieuw."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Lijn de telefoon opnieuw uit om sneller op te laden"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Lijn de telefoon opnieuw uit om draadloos op te laden"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Het Android TV-apparaat wordt binnenkort uitgeschakeld. Druk op een knop om het ingeschakeld te houden."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Het apparaat wordt binnenkort uitgeschakeld. Druk om het ingeschakeld te houden."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Geen simkaart in tablet."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Geen simkaart in telefoon."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"Pincodes komen niet overeen"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Je hebt <xliff:g id="NUMBER_0">%1$d</xliff:g> mislukte pogingen ondernomen om de tablet te ontgrendelen. Na nog eens <xliff:g id="NUMBER_1">%2$d</xliff:g> mislukte pogingen wordt deze tablet gereset, waardoor alle gegevens worden verwijderd."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Je hebt <xliff:g id="NUMBER_0">%1$d</xliff:g> mislukte pogingen ondernomen om de telefoon te ontgrendelen. Na nog eens <xliff:g id="NUMBER_1">%2$d</xliff:g> mislukte pogingen wordt deze telefoon gereset, waardoor alle gegevens worden verwijderd."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Je hebt <xliff:g id="NUMBER">%d</xliff:g> mislukte pogingen ondernomen om de tablet te ontgrendelen. Deze tablet wordt gereset, waardoor alle gegevens worden verwijderd."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Je hebt <xliff:g id="NUMBER">%d</xliff:g> mislukte pogingen ondernomen om de telefoon te ontgrendelen. Deze telefoon wordt gereset, waardoor alle gegevens worden verwijderd."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Je hebt <xliff:g id="NUMBER_0">%1$d</xliff:g> mislukte pogingen ondernomen om de tablet te ontgrendelen. Na nog eens <xliff:g id="NUMBER_1">%2$d</xliff:g> mislukte pogingen wordt deze gebruiker verwijderd, waardoor alle gebruikersgegevens worden verwijderd."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Je hebt <xliff:g id="NUMBER_0">%1$d</xliff:g> mislukte pogingen ondernomen om de telefoon te ontgrendelen. Na nog eens <xliff:g id="NUMBER_1">%2$d</xliff:g> mislukte pogingen wordt deze gebruiker verwijderd, waardoor alle gebruikersgegevens worden verwijderd."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Je hebt <xliff:g id="NUMBER">%d</xliff:g> mislukte pogingen ondernomen om de tablet te ontgrendelen. Deze gebruiker wordt verwijderd, waardoor alle gebruikersgegevens worden verwijderd."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Je hebt <xliff:g id="NUMBER">%d</xliff:g> mislukte pogingen ondernomen om de telefoon te ontgrendelen. Deze gebruiker wordt verwijderd, waardoor alle gebruikersgegevens worden verwijderd."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Je hebt <xliff:g id="NUMBER_0">%1$d</xliff:g> mislukte pogingen ondernomen om de tablet te ontgrendelen. Na nog eens <xliff:g id="NUMBER_1">%2$d</xliff:g> mislukte pogingen wordt het werkprofiel verwijderd, waardoor alle profielgegevens worden verwijderd."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Je hebt <xliff:g id="NUMBER_0">%1$d</xliff:g> mislukte pogingen ondernomen om de telefoon te ontgrendelen. Na nog eens <xliff:g id="NUMBER_1">%2$d</xliff:g> mislukte pogingen wordt het werkprofiel verwijderd, waardoor alle profielgegevens worden verwijderd."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Je hebt <xliff:g id="NUMBER">%d</xliff:g> mislukte pogingen ondernomen om de tablet te ontgrendelen. Het werkprofiel wordt verwijderd, waardoor alle profielgegevens worden verwijderd."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Je hebt <xliff:g id="NUMBER">%d</xliff:g> mislukte pogingen ondernomen om de telefoon te ontgrendelen. Het werkprofiel wordt verwijderd, waardoor alle profielgegevens worden verwijderd."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Je hebt je ontgrendelingspatroon <xliff:g id="NUMBER_0">%1$d</xliff:g> keer onjuist getekend. Na nog eens <xliff:g id="NUMBER_1">%2$d</xliff:g> mislukte pogingen wordt je gevraagd je tablet te ontgrendelen via een e-mailaccount.\n\n Probeer het over <xliff:g id="NUMBER_2">%3$d</xliff:g> seconden opnieuw."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Je hebt je ontgrendelingspatroon <xliff:g id="NUMBER_0">%1$d</xliff:g> keer onjuist getekend. Na nog eens <xliff:g id="NUMBER_1">%2$d</xliff:g> mislukte pogingen wordt je gevraagd je telefoon te ontgrendelen via een e-mailaccount.\n\n Probeer het over <xliff:g id="NUMBER_2">%3$d</xliff:g> seconden opnieuw."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-or/strings.xml b/packages/SystemUI/res-product/values-or/strings.xml
index a6190fcb90c0..aee54f4b246e 100644
--- a/packages/SystemUI/res-product/values-or/strings.xml
+++ b/packages/SystemUI/res-product/values-or/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,46 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"ଟାବଲେଟ୍‌ରେ କୌଣସି SIM‍ କାର୍ଡ ନାହିଁ।"</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"ଫୋନରେ କୌଣସି SIM କାର୍ଡ ନାହିଁ।"</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"PIN କୋଡ୍‍ ମେଳ ହେଉନାହିଁ"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"ଆପଣ ଟାବଲେଟକୁ <xliff:g id="NUMBER_0">%1$d</xliff:g> ଭୁଲ ଭାବେ ପ୍ରୟାସ କରିଛନ୍ତି। ଆଉ <xliff:g id="NUMBER_1">%2$d</xliff:g>ଟି ଭୁଲ୍‍ ପ୍ରୟାସ ପରେ, ଏହି ଟାବଲେଟଟି ରିସେଟ୍‍ ହୋଇଯିବ, ଯାହାଦ୍ୱାରା ଏହାର ସମସ୍ତ ଡାଟା ଲିଟ୍‍ ହୋଇଯିବ।"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"ଆପଣ ଫୋନକୁ ଅନଲକ୍‍ କରିବାକୁ <xliff:g id="NUMBER_0">%1$d</xliff:g> ଭୁଲ ଭାବେ ପ୍ରୟାସ କରିଛନ୍ତି। ଆଉ <xliff:g id="NUMBER_1">%2$d</xliff:g>ଟି ଭୁଲ୍‍ ପ୍ରୟାସ ପରେ, ଏହି ଫୋନଟି ରିସେଟ୍‍ ହୋଇଯିବ, ଯାହାଦ୍ୱାରା ଏହାର ସମସ୍ତ ଡାଟା ଲିଟ୍‍ ହୋଇଯିବ।"</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"ଆପଣ ଟାବଲେଟକୁ ଅନଲକ୍‍ କରିବାକୁ <xliff:g id="NUMBER">%d</xliff:g> ଥର ଭୁଲ୍‍ ଭାବେ ପ୍ରୟାସ କରିଛନ୍ତି। ଏହି ଟାବଲେଟକୁ ରିସେଟ୍‍ କରାଯିବ, ଯାହାଦ୍ୱାରା ଏହାର ସମସ୍ତ ଡାଟା ଡିଲିଟ୍‍ ହୋଇଯିବ।"</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"ଆପଣ ଫୋନଟି ଅନଲକ୍‍ କରିବାକୁ <xliff:g id="NUMBER">%d</xliff:g>ଥର ଭୁଲ୍‍ ଭାବେ ପ୍ରୟାସ କରିଛନ୍ତି। ଏହି ଫୋନ୍‍ ରିସେଟ୍‍ କରାଯିବ, ଯାହା ଦ୍ୱାରା ଏହାର ସମସ୍ତ ଡାଟା ଡିଲିଟ୍‍ ହୋଇଯିବ।"</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"ଆପଣ ଟାବଲେଟ୍‌ଟିକୁ ଅନଲକ୍‍ କରିବା ପାଇଁ <xliff:g id="NUMBER_0">%1$d</xliff:g> ଥର ଭୁଲ ଭାବେ ଚେଷ୍ଟା କରିଛନ୍ତି। ଆଉ <xliff:g id="NUMBER_1">%2$d</xliff:g> ଟି ଭୁଲ୍‍ ପ୍ରୟାସ ପରେ, ୱାର୍କ ପ୍ରୋଫାଇଲ୍‍କୁ ବାହାର କରିଦିଆଯିବ ଏବଂ ଏହା ଦ୍ୱାରା ସମସ୍ତ ପ୍ରୋଫାଇଲ୍‍ ଡାଟା ଡିଲିଟ୍‍ ହୋଇଯିବ।"</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"ଆପଣ ଫୋନଟି ଅନଲକ୍‍ କରିବାକୁ <xliff:g id="NUMBER_0">%1$d</xliff:g>ଥର ଭୁଲ ଭାବେ ପ୍ରୟାସ କରିଛନ୍ତି। ଆଉ <xliff:g id="NUMBER_1">%2$d</xliff:g>ଟି ଭୁଲ୍‍ ପ୍ରୟାସ ପରେ, ଏହି ୟୁଜରଙ୍କୁ ବାହାର କରିଦିଆଯିବ ଏବଂ ଏହାଦ୍ୱାରା ସମସ୍ତ ୟୁଜର୍‍ ଡାଟା ଡିଲିଟ୍‍ ହୋଇଯିବ।"</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for notification_bubble_title (8330481035191903164) -->
- <skip/>
- <!-- no translation found for notification_channel_summary_bubble (7235935211580860537) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Android ଟିଭି ଡିଭାଇସ୍ ଶୀଘ୍ର ବନ୍ଦ ହୋଇଯିବ; ଏହା ଚାଲୁ ରଖିବା ପାଇଁ ଏକ ବଟନ୍ ଦବାନ୍ତୁ।"</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"ଡିଭାଇସ୍ ଶୀଘ୍ର ବନ୍ଦ ହୋଇଯିବ; ଚାଲୁ ରଖିବା ପାଇଁ ଦବାନ୍ତୁ।"</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"ଆପଣ ଟାବଲେଟକୁ ଅନଲକ୍‍ କରିବାକୁ <xliff:g id="NUMBER">%d</xliff:g> ଭୁଲ୍‍ ଭାବେ ପ୍ରୟାସ କରିଛନ୍ତି। କାର୍ଯ୍ୟ ପ୍ରୋଫାଇଲ୍‍ ବାହାର କରିଦିଆଯିବ, ଯାହାଦ୍ୱାରା ସମସ୍ତ ପ୍ରୋଫାଇଲ୍‍ ଡାଟା ଡିଲିଟ୍‍ ହୋଇଯିବ।"</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"ଆପଣ ଫୋନଟି ଅନଲକ୍‍ କରିବାକୁ <xliff:g id="NUMBER">%d</xliff:g>ଥର ଭୁଲ୍‍ ଭାବେ ପ୍ରୟାସ କରିଛନ୍ତି। ୱର୍କ ପ୍ରୋଫାଇଲ୍‍ ବାହାର କରିଦିଆଯିବ, ଯାହା ଦ୍ୱାରା ସମସ୍ତ ପ୍ରୋଫାଇଲ୍‍ ଡାଟା ଡିଲିଟ୍‍ ହୋଇଯିବ।"</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"ଆପଣଙ୍କ ଅନଲକ୍‍ ପାଟର୍ନକୁ ଆପଣ <xliff:g id="NUMBER_0">%1$d</xliff:g> ଥର ଭୁଲ ଭାବେ ଅଙ୍କନ କରିଛନ୍ତି। ଆଉ <xliff:g id="NUMBER_1">%2$d</xliff:g> ଟି ଭୁଲ ପ୍ରୟାସ ପରେ ଏକ ଇମେଲ୍‍ ଆକାଉଣ୍ଟ ବ୍ୟବହାର କରି ନିଜ ଟାବଲେଟକୁ ଅନଲକ୍‌ କରିବା ପାଇଁ କୁହାଯିବ।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ସେକେଣ୍ଡ ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"ଆପଣଙ୍କ ଅନଲକ୍‍ ପାଟର୍ନକୁ ଆପଣ <xliff:g id="NUMBER_0">%1$d</xliff:g> ଥର ଭୁଲ ଭାବେ ଅଙ୍କନ କରିଛନ୍ତି। ଆଉ <xliff:g id="NUMBER_1">%2$d</xliff:g> ଟି ଭୁଲ ପ୍ରୟାସ ପରେ ଏକ ଇମେଲ୍‍ ଆକାଉଣ୍ଟ ବ୍ୟବହାର କରି ନିଜ ଫୋନକୁ ଅନଲକ୍‌ କରିବା ପାଇଁ କୁହାଯିବ।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ସେକେଣ୍ଡ ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"ଶୀଘ୍ର ଚାର୍ଜିଂ ପାଇଁ ଫୋନ୍‌କୁ ଠିକ୍ ଭାବରେ ରଖନ୍ତୁ"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"ୱାୟାର୍‌ଲେସ୍ ଭାବେ ଚାର୍ଜ କରିବାକୁ ଫୋନ୍‌କୁ ଠିକ୍ ଭାବରେ ରଖନ୍ତୁ"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Android TV ଡିଭାଇସ୍ ଶୀଘ୍ର ବନ୍ଦ ହୋଇଯିବ; ଏହା ଚାଲୁ ରଖିବା ପାଇଁ ଏକ ବଟନ୍ ଦବାନ୍ତୁ।"</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"ଡିଭାଇସ୍‌ଟି ଶୀଘ୍ର ବନ୍ଦ ହୋଇଯିବ; ଏହାକୁ ଚାଲୁ ରଖିବା ପାଇଁ ଦବାନ୍ତୁ।"</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"ଟାବ୍‌ଲେଟ୍‌ରେ କୌଣସି SIM କାର୍ଡ ନାହିଁ।"</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"ଫୋନ୍‌ରେ କୌଣସି SIM କାର୍ଡ ନାହିଁ।"</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"PIN କୋଡ୍‌ଗୁଡ଼ିକ ମେଳ ଖାଉନାହିଁ"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"ଆପଣ ଟାବ୍‌ଲେଟ୍‌କୁ ଅନ୍‌ଲକ୍ କରିବାକୁ <xliff:g id="NUMBER_0">%1$d</xliff:g>ଥର ଭୁଲ ପ୍ରୟାସ କରିଛନ୍ତି। ଆଉ <xliff:g id="NUMBER_1">%2$d</xliff:g>ଟି ଭୁଲ୍ ପ୍ରୟାସ ପରେ, ଏହି ଟାବ୍‌ଲେଟ୍‌କୁ ରିସେଟ୍ କରିଦିଆଯିବ, ଯାହାଦ୍ୱାରା ଏହାର ସମସ୍ତ ଡାଟା ଡିଲିଟ୍ ହେବ।"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"ଆପଣ ଫୋନ୍‌କୁ ଅନ୍‌ଲକ୍ କରିବାକୁ <xliff:g id="NUMBER_0">%1$d</xliff:g>ଥର ଭୁଲ ପ୍ରୟାସ କରିଛନ୍ତି। ଆଉ <xliff:g id="NUMBER_1">%2$d</xliff:g>ଟି ଭୁଲ୍ ପ୍ରୟାସ ପରେ, ଏହି ଫୋନ୍‌କୁ ରିସେଟ୍ କରିଦିଆଯିବ, ଯାହାଦ୍ୱାରା ଏହାର ସମସ୍ତ ଡାଟା ଡିଲିଟ୍ ହେବ।"</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"ଆପଣ ଟାବ୍‌ଲେଟ୍‌କୁ ଅନ୍‌ଲକ୍ କରିବାକୁ <xliff:g id="NUMBER">%d</xliff:g>ଥର ଭୁଲ ପ୍ରୟାସ କରିଛନ୍ତି। ଏହି ଟାବ୍‌ଲେଟ୍‌ଟି ରିସେଟ୍ କରିଦିଆଯିବ, ଫଳରେ ଏହାର ସମସ୍ତ ଡାଟା ଡିଲିଟ୍ ହେବ।"</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"ଆପଣ ଫୋନ୍‌କୁ ଅନ୍‌ଲକ୍ କରିବାକୁ <xliff:g id="NUMBER">%d</xliff:g>ଥର ଭୁଲ ପ୍ରୟାସ କରିଛନ୍ତି। ଏହି ଫୋନ୍‌ଟି ରିସେଟ୍ କରିଦିଆଯିବ, ଫଳରେ ଏହାର ସମସ୍ତ ଡାଟା ଡିଲିଟ୍ ହେବ।"</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"ଆପଣ ଟାବ୍‌ଲେଟ୍‌କୁ ଅନ୍‌ଲକ୍ କରିବାକୁ <xliff:g id="NUMBER_0">%1$d</xliff:g>ଥର ଭୁଲ ପ୍ରୟାସ କରିଛନ୍ତି। ଆଉ <xliff:g id="NUMBER_1">%2$d</xliff:g>ଟି ଭୁଲ୍ ପ୍ରୟାସ ପରେ, ଏହି ଉପଯୋଗକର୍ତ୍ତା ପ୍ରୋଫାଇଲ୍‌କୁ କାଢ଼ିଦିଆଯିବ, ଯାହା ଫଳରେ ସମସ୍ତ ଉପଯୋଗକର୍ତ୍ତା ଡାଟା ଡିଲିଟ୍ ହେବ।"</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"ଆପଣ ଫୋନ୍‌କୁ ଅନ୍‌ଲକ୍ କରିବାକୁ <xliff:g id="NUMBER_0">%1$d</xliff:g>ଥର ଭୁଲ ପ୍ରୟାସ କରିଛନ୍ତି। ଆଉ <xliff:g id="NUMBER_1">%2$d</xliff:g>ଟି ଭୁଲ୍ ପ୍ରୟାସ ପରେ, ଏହି ଉପଯୋଗକର୍ତ୍ତା ପ୍ରୋଫାଇଲ୍‌କୁ କାଢ଼ିଦିଆଯିବ, ଯାହା ଫଳରେ ସମସ୍ତ ଉପଯୋଗକର୍ତ୍ତା ଡାଟା ଡିଲିଟ୍ ହେବ।"</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"ଆପଣ ଟାବ୍‌ଲେଟ୍‌କୁ ଅନ୍‌ଲକ୍ କରିବାକୁ <xliff:g id="NUMBER">%d</xliff:g>ଥର ଭୁଲ ପ୍ରୟାସ କରିଛନ୍ତି। ଏହି ଉପଯୋଗକର୍ତ୍ତାଙ୍କୁ ବାହାର କରିଦିଆଯିବ, ଯାହାଦ୍ୱାରା ସମସ୍ତ ଉପଯୋଗକର୍ତ୍ତା ଡାଟା ଡିଲିଟ୍ ହେବ।"</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"ଆପଣ ଫୋନ୍‌କୁ ଅନ୍‌ଲକ୍ କରିବାକୁ <xliff:g id="NUMBER">%d</xliff:g>ଥର ଭୁଲ୍ ପ୍ରୟାସ କରିଛନ୍ତି। ଏହି ଉପଯୋଗକର୍ତ୍ତାଙ୍କୁ ବାହାର କରିଦିଆଯିବ, ଯାହାଦ୍ୱାରା ସମସ୍ତ ଉପଯୋଗକର୍ତ୍ତା ଡାଟା ଡିଲିଟ୍ ହେବ।"</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"ଆପଣ ଟାବ୍‌ଲେଟ୍‌କୁ ଅନ୍‌ଲକ୍ କରିବାକୁ <xliff:g id="NUMBER_0">%1$d</xliff:g>ଥର ଭୁଲ ପ୍ରୟାସ କରିଛନ୍ତି। ଆଉ <xliff:g id="NUMBER_1">%2$d</xliff:g>ଟି ଭୁଲ୍ ପ୍ରୟାସ ପରେ, ୱାର୍କ ପ୍ରୋଫାଇଲ୍‌କୁ ବାହାର କରିଦିଆଯିବ, ଯାହା ଫଳରେ ସମସ୍ତ ପ୍ରୋଫାଇଲ୍ ଡାଟା ଡିଲିଟ୍ ହେବ।"</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"ଆପଣ ଫୋନ୍‌କୁ ଅନ୍‌ଲକ୍ କରିବାକୁ <xliff:g id="NUMBER_0">%1$d</xliff:g>ଥର ଭୁଲ ପ୍ରୟାସ କରିଛନ୍ତି। ଆଉ <xliff:g id="NUMBER_1">%2$d</xliff:g>ଟି ଭୁଲ୍ ପ୍ରୟାସ ପରେ, ୱାର୍କ ପ୍ରୋଫାଇଲ୍‌କୁ ବାହାର କରିଦିଆଯିବ, ଯାହା ଫଳରେ ସମସ୍ତ ପ୍ରୋଫାଇଲ୍ ଡାଟା ଡିଲିଟ୍ ହେବ।"</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"ଆପଣ ଟାବ୍‌ଲେଟ୍‌କୁ ଅନ୍‌ଲକ୍ କରିବାକୁ<xliff:g id="NUMBER">%d</xliff:g>ଥର ଭୁଲ ପ୍ରୟାସ କରିଛନ୍ତି। କାର୍ଯ୍ୟ ପ୍ରୋଫାଇଲ୍ ବାହାର କରିଦିଆଯିବ, ଯାହା ଫଳରେ ସମସ୍ତ ପ୍ରୋଫାଇଲ୍ ଡାଟା ଡିଲିଟ୍ ହେବ।"</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"ଆପଣ ଫୋନ୍‌କୁ ଅନ୍‌ଲକ୍ କରିବାକୁ<xliff:g id="NUMBER">%d</xliff:g>ଥର ଭୁଲ ପ୍ରୟାସ କରିଛନ୍ତି। କାର୍ଯ୍ୟ ପ୍ରୋଫାଇଲ୍ ବାହାର କରିଦିଆଯିବ, ଯାହା ଫଳରେ ସମସ୍ତ ପ୍ରୋଫାଇଲ୍ ଡାଟା ଡିଲିଟ୍ ହେବ।"</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"ଆପଣ ଆପଣଙ୍କ ଅନ୍‌ଲକ୍ ପାଟର୍ନକୁ <xliff:g id="NUMBER_0">%1$d</xliff:g>ଥର ଭୁଲ ଭାବେ ଡ୍ର କରିଛନ୍ତି। ଆଉ <xliff:g id="NUMBER_1">%2$d</xliff:g>ଟି ଭୁଲ ପ୍ରୟାସ ପରେ ଆପଣଙ୍କୁ ଏକ ଇମେଲ୍ ଆକାଉଣ୍ଟ ବ୍ୟବହାର କରି ଆପଣଙ୍କ ଟାବ୍‌ଲୋଟ୍‌କୁ ଅନ୍‌ଲକ୍ କରିବା ପାଇଁ କୁହାଯିବ।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ସେକେଣ୍ଡ ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"ଆପଣ ଆପଣଙ୍କ ଅନ୍‌ଲକ୍ ପାଟର୍ନକୁ <xliff:g id="NUMBER_0">%1$d</xliff:g>ଥର ଭୁଲ ଭାବେ ଡ୍ର କରିଛନ୍ତି। ଆଉ <xliff:g id="NUMBER_1">%2$d</xliff:g>ଟି ଭୁଲ ପ୍ରୟାସ ପରେ ଆପଣଙ୍କୁ ଏକ ଇମେଲ୍ ଆକାଉଣ୍ଟ ବ୍ୟବହାର କରି ଆପଣଙ୍କ ଫୋନ୍‌କୁ ଅନ୍‌ଲକ୍‌ କରିବା ପାଇଁ କୁହାଯିବ।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ସେକେଣ୍ଡ ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-pa/strings.xml b/packages/SystemUI/res-product/values-pa/strings.xml
index bc16b5ad7a5a..483d91c60888 100644
--- a/packages/SystemUI/res-product/values-pa/strings.xml
+++ b/packages/SystemUI/res-product/values-pa/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,46 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"ਟੈਬਲੈੱਟ ਵਿੱਚ ਕੋਈ ਸਿਮ ਕਾਰਡ ਮੌਜੂਦ ਨਹੀਂ।"</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"ਫ਼ੋਨ ਵਿੱਚ ਕੋਈ ਸਿਮ ਕਾਰਡ ਮੌਜੂਦ ਨਹੀਂ।"</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"ਪਿੰਨ ਕੋਡ ਮੇਲ ਨਹੀਂ ਖਾਂਦੇ"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟੈਬਲੈੱਟ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਇਹ ਟੈਬਲੈੱਟ ਰੀਸੈੱਟ ਕੀਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਇਸਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਫ਼ੋਨ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਇਹ ਫ਼ੋਨ ਰੀਸੈੱਟ ਕੀਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਇਸਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"ਤੁਸੀਂ <xliff:g id="NUMBER">%d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟੈਬਲੈੱਟ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। ਇਹ ਟੈਬਲੈੱਟ ਰੀਸੈੱਟ ਕੀਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਇਸਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"ਤੁਸੀਂ <xliff:g id="NUMBER">%d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਫ਼ੋਨ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। ਇਹ ਫ਼ੋਨ ਰੀਸੈੱਟ ਕੀਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਇਸਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟੈਬਲੈੱਟ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਇਸ ਵਰਤੋਂਕਾਰ ਨੂੰ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਸਾਰਾ ਵਰਤੋਂਕਾਰ ਡਾਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਫ਼ੋਨ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਇਸ ਵਰਤੋਂਕਾਰ ਨੂੰ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਸਾਰਾ ਵਰਤੋਂਕਾਰ ਡਾਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for notification_bubble_title (8330481035191903164) -->
- <skip/>
- <!-- no translation found for notification_channel_summary_bubble (7235935211580860537) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Android TV ਡੀਵਾਈਸ ਜਲਦ ਹੀ ਬੰਦ ਹੋ ਜਾਵੇਗਾ; ਇਸਨੂੰ ਚਾਲੂ ਰੱਖਣ ਲਈ ਕੋਈ ਬਟਨ ਦਬਾਓ।"</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"ਡੀਵਾਈਸ ਜਲਦ ਹੀ ਬੰਦ ਹੋ ਜਾਵੇਗਾ, ਇਸਨੂੰ ਚਾਲੂ ਰੱਖਣ ਲਈ ਦਬਾਓ।"</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"ਤੁਸੀਂ <xliff:g id="NUMBER">%d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟੈਬਲੈੱਟ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਸਾਰਾ ਪ੍ਰੋਫਾਈਲ ਡਾਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"ਤੁਸੀਂ <xliff:g id="NUMBER">%d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਫ਼ੋਨ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਸਾਰਾ ਪ੍ਰੋਫਾਈਲ ਡਾਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਅਣਲਾਕ ਪੈਟਰਨ ਗਲਤ ਢੰਗ ਨਾਲ ਉਲੀਕਿਆ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਤੁਹਾਨੂੰ ਇੱਕ ਈਮੇਲ ਖਾਤਾ ਵਰਤਦੇ ਹੋਏ ਆਪਣੇ ਟੈਬਲੈੱਟ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਲਈ ਕਿਹਾ ਜਾਵੇਗਾ।\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਅਣਲਾਕ ਪੈਟਰਨ ਗਲਤ ਢੰਗ ਨਾਲ ਡ੍ਰਾ ਕੀਤਾ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਤੁਹਾਨੂੰ ਇੱਕ ਈਮੇਲ ਖਾਤਾ ਵਰਤਦੇ ਹੋਏ ਆਪਣਾ ਫ਼ੋਨ ਅਣਲਾਕ ਕਰਨ ਲਈ ਕਿਹਾ ਜਾਏਗਾ।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"ਫ਼ੋਨ ਨੂੰ ਤੇਜ਼ੀ ਨਾਲ ਚਾਰਜ ਕਰਨ ਲਈ ਡੌਕ \'ਤੇ ਸਹੀ ਕਰਕੇ ਰੱਖੋ"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"ਫ਼ੋਨ ਨੂੰ ਬਿਨਾਂ ਤਾਰ ਤੋਂ ਚਾਰਜ ਕਰਨ ਲਈ ਡੌਕ \'ਤੇ ਸਹੀ ਕਰਕੇ ਰੱਖੋ"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Android TV ਡੀਵਾਈਸ ਜਲਦ ਹੀ ਬੰਦ ਹੋ ਜਾਵੇਗਾ; ਇਸਨੂੰ ਚਾਲੂ ਰੱਖਣ ਲਈ ਕੋਈ ਬਟਨ ਦਬਾਓ।"</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"ਡੀਵਾਈਸ ਜਲਦ ਹੀ ਬੰਦ ਹੋ ਜਾਵੇਗਾ; ਇਸਨੂੰ ਚਾਲੂ ਰੱਖਣ ਲਈ ਦਬਾਓ।"</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"ਟੈਬਲੈੱਟ ਵਿੱਚ ਕੋਈ ਸਿਮ ਕਾਰਡ ਮੌਜੂਦ ਨਹੀਂ।"</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"ਫ਼ੋਨ ਵਿੱਚ ਕੋਈ ਸਿਮ ਕਾਰਡ ਮੌਜੂਦ ਨਹੀਂ।"</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"ਪਿੰਨ ਕੋਡ ਮੇਲ ਨਹੀਂ ਖਾਂਦੇ"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟੈਬਲੈੱਟ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਇਹ ਟੈਬਲੈੱਟ ਰੀਸੈੱਟ ਕੀਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਇਸਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਫ਼ੋਨ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਇਹ ਫ਼ੋਨ ਰੀਸੈੱਟ ਕੀਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਇਸਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"ਤੁਸੀਂ <xliff:g id="NUMBER">%d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟੈਬਲੈੱਟ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। ਇਹ ਟੈਬਲੈੱਟ ਰੀਸੈੱਟ ਕੀਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਇਸਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"ਤੁਸੀਂ <xliff:g id="NUMBER">%d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਫ਼ੋਨ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। ਇਹ ਫ਼ੋਨ ਰੀਸੈੱਟ ਕੀਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਇਸਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟੈਬਲੈੱਟ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਇਸ ਵਰਤੋਂਕਾਰ ਨੂੰ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਸਾਰਾ ਵਰਤੋਂਕਾਰ ਡਾਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਫ਼ੋਨ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਇਸ ਵਰਤੋਂਕਾਰ ਨੂੰ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਸਾਰਾ ਵਰਤੋਂਕਾਰ ਡਾਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"ਤੁਸੀਂ <xliff:g id="NUMBER">%d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟੈਬਲੈੱਟ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। ਇਸ ਵਰਤੋਂਕਾਰ ਨੂੰ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਸਾਰਾ ਵਰਤੋਂਕਾਰ ਡਾਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"ਤੁਸੀਂ <xliff:g id="NUMBER">%d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਫ਼ੋਨ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। ਇਸ ਵਰਤੋਂਕਾਰ ਨੂੰ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਸਾਰਾ ਵਰਤੋਂਕਾਰ ਡਾਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟੈਬਲੈੱਟ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਪ੍ਰੋਫਾਈਲ ਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਫ਼ੋਨ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਪ੍ਰੋਫਾਈਲ ਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"ਤੁਸੀਂ <xliff:g id="NUMBER">%d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟੈਬਲੈੱਟ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਸਾਰਾ ਪ੍ਰੋਫਾਈਲ ਡਾਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"ਤੁਸੀਂ <xliff:g id="NUMBER">%d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਫ਼ੋਨ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਸਾਰਾ ਪ੍ਰੋਫਾਈਲ ਡਾਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਅਣਲਾਕ ਪੈਟਰਨ ਗਲਤ ਢੰਗ ਨਾਲ ਉਲੀਕਿਆ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਤੁਹਾਨੂੰ ਇੱਕ ਈਮੇਲ ਖਾਤਾ ਵਰਤਦੇ ਹੋਏ ਆਪਣੇ ਟੈਬਲੈੱਟ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਲਈ ਕਿਹਾ ਜਾਵੇਗਾ।\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਅਣਲਾਕ ਪੈਟਰਨ ਗਲਤ ਢੰਗ ਨਾਲ ਡ੍ਰਾ ਕੀਤਾ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਤੁਹਾਨੂੰ ਇੱਕ ਈਮੇਲ ਖਾਤਾ ਵਰਤਦੇ ਹੋਏ ਆਪਣਾ ਫ਼ੋਨ ਅਣਲਾਕ ਕਰਨ ਲਈ ਕਿਹਾ ਜਾਏਗਾ।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-pl/strings.xml b/packages/SystemUI/res-product/values-pl/strings.xml
index 9ba9b6521e3c..d38c127ea7de 100644
--- a/packages/SystemUI/res-product/values-pl/strings.xml
+++ b/packages/SystemUI/res-product/values-pl/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"Brak karty SIM w tablecie."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"Brak karty SIM w telefonie."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"Kody PIN nie pasują"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> próbowałeś nieprawidłowo odblokować tablet. Po kolejnych <xliff:g id="NUMBER_1">%2$d</xliff:g> nieudanych próbach tablet zostanie zresetowany, co spowoduje skasowanie wszystkich jego danych."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> próbowałeś nieprawidłowo odblokować telefon. Po kolejnych <xliff:g id="NUMBER_1">%2$d</xliff:g> nieudanych próbach telefon zostanie zresetowany, co spowoduje skasowanie wszystkich jego danych."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Po raz <xliff:g id="NUMBER">%d</xliff:g> próbowałeś nieprawidłowo odblokować tablet. Tablet zostanie zresetowany, co spowoduje skasowanie wszystkich jego danych."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Po raz <xliff:g id="NUMBER">%d</xliff:g> próbowałeś nieprawidłowo odblokować telefon. Telefon zostanie zresetowany, co spowoduje skasowanie wszystkich jego danych."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> próbowałeś nieprawidłowo odblokować tablet. Po kolejnych <xliff:g id="NUMBER_1">%2$d</xliff:g> nieudanych próbach użytkownik zostanie usunięty, co spowoduje skasowanie wszystkich danych użytkownika."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> próbowałeś nieprawidłowo odblokować telefon. Po kolejnych <xliff:g id="NUMBER_1">%2$d</xliff:g> nieudanych próbach użytkownik zostanie usunięty, co spowoduje skasowanie wszystkich danych użytkownika."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Urządzenie z Androidem TV za chwilę się wyłączy. Naciśnij przycisk, by pozostało włączone."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Urządzenie za chwilę się wyłączy. Naciśnij, by pozostało włączone."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Po raz <xliff:g id="NUMBER">%d</xliff:g> próbowałeś nieprawidłowo odblokować tablet. Profil służbowy zostanie usunięty, co spowoduje skasowanie wszystkich danych tego profilu."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Po raz <xliff:g id="NUMBER">%d</xliff:g> próbowałeś nieprawidłowo odblokować telefon. Profil służbowy zostanie usunięty, co spowoduje skasowanie wszystkich danych tego profilu."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> nieprawidłowo narysowałeś wzór odblokowania. Po kolejnych <xliff:g id="NUMBER_1">%2$d</xliff:g> nieudanych próbach konieczne będzie odblokowanie tabletu przy użyciu konta e-mail.\n\n Spróbuj ponownie za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> nieprawidłowo narysowałeś wzór odblokowania. Po kolejnych <xliff:g id="NUMBER_1">%2$d</xliff:g> nieudanych próbach konieczne będzie odblokowanie telefonu przy użyciu konta e-mail.\n\n Spróbuj ponownie za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Popraw ustawienie telefonu, by naładować go szybciej"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Popraw ustawienie telefonu, by naładować go bezprzewodowo"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Urządzenie z Androidem TV za chwilę się wyłączy. Naciśnij przycisk, by pozostało włączone."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Urządzenie za chwilę się wyłączy. Naciśnij, by pozostało włączone."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Brak karty SIM w tablecie."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Brak karty SIM w telefonie."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"Kody PIN nie pasują"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> próbowano nieprawidłowo odblokować tablet. Po kolejnych <xliff:g id="NUMBER_1">%2$d</xliff:g> nieudanych próbach tablet zostanie zresetowany, co spowoduje skasowanie wszystkich jego danych."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> próbowano nieprawidłowo odblokować telefon. Po kolejnych <xliff:g id="NUMBER_1">%2$d</xliff:g> nieudanych próbach telefon zostanie zresetowany, co spowoduje skasowanie wszystkich jego danych."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Po raz <xliff:g id="NUMBER">%d</xliff:g> próbowano nieprawidłowo odblokować tablet. Tablet zostanie zresetowany, co spowoduje skasowanie wszystkich jego danych."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Po raz <xliff:g id="NUMBER">%d</xliff:g> próbowano nieprawidłowo odblokować telefon. Telefon zostanie zresetowany, co spowoduje skasowanie wszystkich jego danych."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> próbowano nieprawidłowo odblokować tablet. Po kolejnych <xliff:g id="NUMBER_1">%2$d</xliff:g> nieudanych próbach użytkownik zostanie usunięty, co spowoduje skasowanie wszystkich jego danych."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> próbowano nieprawidłowo odblokować telefon. Po kolejnych <xliff:g id="NUMBER_1">%2$d</xliff:g> nieudanych próbach użytkownik zostanie usunięty, co spowoduje skasowanie wszystkich jego danych."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Po raz <xliff:g id="NUMBER">%d</xliff:g> próbowano nieprawidłowo odblokować tablet. Użytkownik zostanie usunięty, co spowoduje skasowanie wszystkich jego danych."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Po raz <xliff:g id="NUMBER">%d</xliff:g> próbowano nieprawidłowo odblokować telefon. Użytkownik zostanie usunięty, co spowoduje skasowanie wszystkich jego danych."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> próbowano nieprawidłowo odblokować tablet. Po kolejnych <xliff:g id="NUMBER_1">%2$d</xliff:g> nieudanych próbach profil do pracy zostanie usunięty, co spowoduje skasowanie wszystkich jego danych."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> próbowano nieprawidłowo odblokować telefon. Po kolejnych <xliff:g id="NUMBER_1">%2$d</xliff:g> nieudanych próbach profil do pracy zostanie usunięty, co spowoduje skasowanie wszystkich jego danych."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Po raz <xliff:g id="NUMBER">%d</xliff:g> próbowano nieprawidłowo odblokować tablet. Profil do pracy zostanie usunięty, co spowoduje skasowanie wszystkich jego danych."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Po raz <xliff:g id="NUMBER">%d</xliff:g> próbowano nieprawidłowo odblokować telefon. Profil do pracy zostanie usunięty, co spowoduje skasowanie wszystkich jego danych."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> nieprawidłowo narysowano wzór odblokowania. Po kolejnych <xliff:g id="NUMBER_1">%2$d</xliff:g> nieudanych próbach konieczne będzie odblokowanie tabletu przy użyciu konta e-mail.\n\n Spróbuj ponownie za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> nieprawidłowo narysowano wzór odblokowania. Po kolejnych <xliff:g id="NUMBER_1">%2$d</xliff:g> nieudanych próbach konieczne będzie odblokowanie telefonu przy użyciu konta e-mail.\n\n Spróbuj ponownie za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-pt-rBR/strings.xml b/packages/SystemUI/res-product/values-pt-rBR/strings.xml
index 73a0983f54b6..eb65508c8809 100644
--- a/packages/SystemUI/res-product/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res-product/values-pt-rBR/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"Não há um chip no tablet."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"Não há um chip no smartphone."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"Os códigos PIN não coincidem"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Você tentou desbloquear o tablet incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, este smartphone será redefinido, o que excluirá todos os dados dele."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Você tentou desbloquear o smartphone incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, este smartphone será redefinido, o que excluirá todos os dados dele."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Você tentou desbloquear o tablet incorretamente <xliff:g id="NUMBER">%d</xliff:g> vezes. Este tablet será redefinido, o que excluirá todos os dados dele."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Você tentou desbloquear o smartphone incorretamente <xliff:g id="NUMBER">%d</xliff:g> vezes. Este smartphone será redefinido, o que excluirá todos os dados dele."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Você tentou desbloquear o tablet incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, este usuário será removido, o que excluirá todos os dados do usuário."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Você tentou desbloquear o smartphone incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, este usuário será removido, o que excluirá todos os dados do usuário."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"O dispositivo Android TV entrará no modo de espera em breve. Pressione um botão para mantê-lo ativado."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"O dispositivo entrará no modo de espera em breve. Pressione para mantê-lo ativado."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Você tentou desbloquear o tablet incorretamente <xliff:g id="NUMBER">%d</xliff:g> vezes. O perfil de trabalho será removido, o que excluirá todos os dados do perfil."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Você tentou desbloquear o smartphone incorretamente <xliff:g id="NUMBER">%d</xliff:g> vezes. O perfil de trabalho será removido, o que excluirá todos os dados do perfil."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Você desenhou sua sequência de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, será solicitado que você use o login do Google para desbloquear seu tablet.\n\n Tente novamente em <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Você desenhou sua sequência de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, será solicitado que você use o login do Google para desbloquear.\n\n Tente novamente em <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Realinhe o smartphone para carregar mais rapidamente"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Realinhe o smartphone para carregar sem usar fios"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"O dispositivo Android TV entrará no modo de espera em breve. Pressione um botão para mantê-lo ativado."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"O dispositivo entrará no modo de espera em breve. Pressione para mantê-lo ativado."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Nenhum chip no tablet."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Nenhum chip no smartphone."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"Os códigos PIN não coincidem"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Você tentou desbloquear o tablet incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, este tablet será redefinido, o que excluirá todos os dados dele."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Você tentou desbloquear o smartphone incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, este smartphone será redefinido, o que excluirá todos os dados dele."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Você tentou desbloquear o tablet incorretamente <xliff:g id="NUMBER">%d</xliff:g> vezes. Este tablet será redefinido, o que excluirá todos os dados dele."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Você tentou desbloquear o smartphone incorretamente <xliff:g id="NUMBER">%d</xliff:g> vezes. Este smartphone será redefinido, o que excluirá todos os dados dele."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Você tentou desbloquear o tablet incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, este usuário será removido, o que excluirá todos os dados dele."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Você tentou desbloquear o smartphone incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, este usuário será removido, o que excluirá todos os dados dele."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Você tentou desbloquear o tablet incorretamente <xliff:g id="NUMBER">%d</xliff:g> vezes. Este usuário será removido, o que excluirá todos os dados dele."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Você tentou desbloquear o smartphone incorretamente <xliff:g id="NUMBER">%d</xliff:g> vezes. Este usuário será removido, o que excluirá todos os dados do usuário."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Você tentou desbloquear o tablet incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, o perfil de trabalho será removido, o que excluirá todos os dados do perfil."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Você tentou desbloquear o smartphone incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, o perfil de trabalho será removido, o que excluirá todos os dados do perfil."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Você tentou desbloquear o tablet incorretamente <xliff:g id="NUMBER">%d</xliff:g> vezes. O perfil de trabalho será removido, o que excluirá todos os dados do perfil."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Você tentou desbloquear o smartphone incorretamente <xliff:g id="NUMBER">%d</xliff:g> vezes. O perfil de trabalho será removido, o que excluirá todos os dados do perfil."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Você desenhou seu padrão de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, será solicitado que você use uma conta de e-mail para desbloquear o tablet.\n\n Tente novamente em <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Você desenhou seu padrão de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, será solicitado que você use uma conta de e-mail para desbloquear o smartphone.\n\n Tente novamente em <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-pt-rPT/strings.xml b/packages/SystemUI/res-product/values-pt-rPT/strings.xml
index e324686e026f..d5ace307ff55 100644
--- a/packages/SystemUI/res-product/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res-product/values-pt-rPT/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"Nenhum cartão SIM no tablet."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"Nenhum cartão SIM no telemóvel."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"Os códigos PIN não coincidem"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Tentou desbloquear incorretamente o tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Após mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas sem êxito, este tablet será reposto, o que eliminará todos os dados do mesmo."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Tentou desbloquear incorretamente o telemóvel <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Após mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas sem êxito, este telemóvel será reposto, o que eliminará todos os dados do mesmo."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Tentou desbloquear incorretamente o tablet <xliff:g id="NUMBER">%d</xliff:g> vezes. Este tablet será reposto, o que eliminará todos os dados do mesmo."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Tentou desbloquear incorretamente o telemóvel <xliff:g id="NUMBER">%d</xliff:g> vezes. Este telemóvel será reposto, o que eliminará todos os dados do mesmo."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Tentou desbloquear incorretamente o tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Após mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas sem êxito, este utilizador será removido, o que eliminará todos os dados do mesmo."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Tentou desbloquear incorretamente o telemóvel <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Após mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas sem êxito, este utilizador será removido, o que eliminará todos os dados do mesmo."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"O dispositivo Android TV irá desligar-se brevemente. Prima um botão para o manter ligado."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"O dispositivo irá desligar-se brevemente. Prima para o manter ligado."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Tentou desbloquear incorretamente o tablet <xliff:g id="NUMBER">%d</xliff:g> vezes. O perfil de trabalho será removido, o que eliminará todos os dados do mesmo."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Tentou desbloquear incorretamente o telemóvel <xliff:g id="NUMBER">%d</xliff:g> vezes. O perfil de trabalho será removido, o que eliminará todos os dados do mesmo."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Desenhou o padrão de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Após mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas sem êxito, ser-lhe-á pedido para desbloquear o tablet através de uma conta de email.\n\n Tente novamente dentro de <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Desenhou o padrão de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Após mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas sem êxito, ser-lhe-á pedido para desbloquear o telemóvel através de uma conta de email.\n\n Tente novamente dentro de <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Realinhe o telemóvel para um carregamento mais rápido."</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Realinhe o telemóvel para carregar sem fios."</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"O dispositivo Android TV irá desligar-se brevemente. Prima um botão para o manter ligado."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"O dispositivo irá desligar-se brevemente. Prima para o manter ligado."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Nenhum cartão SIM no tablet."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Nenhum cartão SIM no telemóvel."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"Os códigos PIN não coincidem."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Tentou desbloquear incorretamente o tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Após mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas sem êxito, este tablet será reposto, o que eliminará todos os dados do mesmo."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Tentou desbloquear incorretamente o telemóvel <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Após mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas sem êxito, este telemóvel será reposto, o que eliminará todos os dados do mesmo."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Tentou desbloquear incorretamente o tablet <xliff:g id="NUMBER">%d</xliff:g> vezes. Este tablet será reposto, o que eliminará todos os dados do mesmo."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Tentou desbloquear incorretamente o telemóvel <xliff:g id="NUMBER">%d</xliff:g> vezes. Este telemóvel será reposto, o que eliminará todos os dados do mesmo."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Tentou desbloquear incorretamente o tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Após mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas sem êxito, este utilizador será removido, o que eliminará todos os dados do mesmo."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Tentou desbloquear incorretamente o telemóvel <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Após mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas sem êxito, este utilizador será removido, o que eliminará todos os dados do mesmo."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Tentou desbloquear incorretamente o tablet <xliff:g id="NUMBER">%d</xliff:g> vezes. Este utilizador será removido, o que eliminará todos os dados do mesmo."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Tentou desbloquear incorretamente o telemóvel <xliff:g id="NUMBER">%d</xliff:g> vezes. Este utilizador será removido, o que eliminará todos os dados do mesmo."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Tentou desbloquear incorretamente o tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Após mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas sem êxito, o perfil de trabalho será removido, o que eliminará todos os dados do mesmo."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Tentou desbloquear incorretamente o telemóvel <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Após mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas sem êxito, o perfil de trabalho será removido, o que eliminará todos os dados do mesmo."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Tentou desbloquear incorretamente o tablet <xliff:g id="NUMBER">%d</xliff:g> vezes. O perfil de trabalho será removido, o que eliminará todos os dados do mesmo."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Tentou desbloquear incorretamente o telemóvel <xliff:g id="NUMBER">%d</xliff:g> vezes. O perfil de trabalho será removido, o que eliminará todos os dados do mesmo."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Desenhou o padrão de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Após mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas sem êxito, ser-lhe-á pedido para desbloquear o tablet através de uma conta de email.\n\n Tente novamente dentro de <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Desenhou o padrão de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Após mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas sem êxito, ser-lhe-á pedido para desbloquear o telemóvel através de uma conta de email.\n\n Tente novamente dentro de <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-pt/strings.xml b/packages/SystemUI/res-product/values-pt/strings.xml
index 73a0983f54b6..eb65508c8809 100644
--- a/packages/SystemUI/res-product/values-pt/strings.xml
+++ b/packages/SystemUI/res-product/values-pt/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"Não há um chip no tablet."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"Não há um chip no smartphone."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"Os códigos PIN não coincidem"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Você tentou desbloquear o tablet incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, este smartphone será redefinido, o que excluirá todos os dados dele."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Você tentou desbloquear o smartphone incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, este smartphone será redefinido, o que excluirá todos os dados dele."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Você tentou desbloquear o tablet incorretamente <xliff:g id="NUMBER">%d</xliff:g> vezes. Este tablet será redefinido, o que excluirá todos os dados dele."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Você tentou desbloquear o smartphone incorretamente <xliff:g id="NUMBER">%d</xliff:g> vezes. Este smartphone será redefinido, o que excluirá todos os dados dele."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Você tentou desbloquear o tablet incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, este usuário será removido, o que excluirá todos os dados do usuário."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Você tentou desbloquear o smartphone incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, este usuário será removido, o que excluirá todos os dados do usuário."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"O dispositivo Android TV entrará no modo de espera em breve. Pressione um botão para mantê-lo ativado."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"O dispositivo entrará no modo de espera em breve. Pressione para mantê-lo ativado."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Você tentou desbloquear o tablet incorretamente <xliff:g id="NUMBER">%d</xliff:g> vezes. O perfil de trabalho será removido, o que excluirá todos os dados do perfil."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Você tentou desbloquear o smartphone incorretamente <xliff:g id="NUMBER">%d</xliff:g> vezes. O perfil de trabalho será removido, o que excluirá todos os dados do perfil."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Você desenhou sua sequência de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, será solicitado que você use o login do Google para desbloquear seu tablet.\n\n Tente novamente em <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Você desenhou sua sequência de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, será solicitado que você use o login do Google para desbloquear.\n\n Tente novamente em <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Realinhe o smartphone para carregar mais rapidamente"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Realinhe o smartphone para carregar sem usar fios"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"O dispositivo Android TV entrará no modo de espera em breve. Pressione um botão para mantê-lo ativado."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"O dispositivo entrará no modo de espera em breve. Pressione para mantê-lo ativado."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Nenhum chip no tablet."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Nenhum chip no smartphone."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"Os códigos PIN não coincidem"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Você tentou desbloquear o tablet incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, este tablet será redefinido, o que excluirá todos os dados dele."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Você tentou desbloquear o smartphone incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, este smartphone será redefinido, o que excluirá todos os dados dele."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Você tentou desbloquear o tablet incorretamente <xliff:g id="NUMBER">%d</xliff:g> vezes. Este tablet será redefinido, o que excluirá todos os dados dele."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Você tentou desbloquear o smartphone incorretamente <xliff:g id="NUMBER">%d</xliff:g> vezes. Este smartphone será redefinido, o que excluirá todos os dados dele."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Você tentou desbloquear o tablet incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, este usuário será removido, o que excluirá todos os dados dele."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Você tentou desbloquear o smartphone incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, este usuário será removido, o que excluirá todos os dados dele."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Você tentou desbloquear o tablet incorretamente <xliff:g id="NUMBER">%d</xliff:g> vezes. Este usuário será removido, o que excluirá todos os dados dele."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Você tentou desbloquear o smartphone incorretamente <xliff:g id="NUMBER">%d</xliff:g> vezes. Este usuário será removido, o que excluirá todos os dados do usuário."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Você tentou desbloquear o tablet incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, o perfil de trabalho será removido, o que excluirá todos os dados do perfil."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Você tentou desbloquear o smartphone incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, o perfil de trabalho será removido, o que excluirá todos os dados do perfil."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Você tentou desbloquear o tablet incorretamente <xliff:g id="NUMBER">%d</xliff:g> vezes. O perfil de trabalho será removido, o que excluirá todos os dados do perfil."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Você tentou desbloquear o smartphone incorretamente <xliff:g id="NUMBER">%d</xliff:g> vezes. O perfil de trabalho será removido, o que excluirá todos os dados do perfil."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Você desenhou seu padrão de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, será solicitado que você use uma conta de e-mail para desbloquear o tablet.\n\n Tente novamente em <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Você desenhou seu padrão de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, será solicitado que você use uma conta de e-mail para desbloquear o smartphone.\n\n Tente novamente em <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-ro/strings.xml b/packages/SystemUI/res-product/values-ro/strings.xml
index 536d7d923858..12dc17c32e7b 100644
--- a/packages/SystemUI/res-product/values-ro/strings.xml
+++ b/packages/SystemUI/res-product/values-ro/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"Nu există card SIM în tabletă."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"Nu există card SIM în telefon."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"Codurile PIN nu coincid"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Ați efectuat <xliff:g id="NUMBER_0">%1$d</xliff:g> încercări incorecte de deblocare a tabletei. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereușite, această tabletă va fi resetată, iar toate datele acesteia vor fi șterse."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Ați efectuat <xliff:g id="NUMBER_0">%1$d</xliff:g> încercări incorecte de deblocare a telefonului. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereușite, acest telefon va fi resetat, iar toate datele acestuia vor fi șterse."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Ați efectuat <xliff:g id="NUMBER">%d</xliff:g> încercări incorecte de deblocare a tabletei. Această tabletă va fi resetată, iar toate datele acesteia vor fi șterse."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Ați efectuat <xliff:g id="NUMBER">%d</xliff:g> încercări incorecte de deblocare a telefonului. Acest telefon va fi resetat, iar toate datele acestuia vor fi șterse."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Ați efectuat <xliff:g id="NUMBER_0">%1$d</xliff:g> încercări incorecte de deblocare a tabletei. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereușite, acest utilizator va fi eliminat, iar toate datele utilizatorului vor fi șterse."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Ați efectuat <xliff:g id="NUMBER_0">%1$d</xliff:g> încercări incorecte de deblocare a telefonului. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereușite, acest utilizator va fi eliminat, iar toate datele utilizatorului vor fi șterse."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Dispozitivul Android TV se va opri în curând. Apăsați un buton pentru a-l menține pornit."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Dispozitivul se va opri în curând. Apăsați pentru a-l menține pornit."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Ați efectuat <xliff:g id="NUMBER">%d</xliff:g> încercări incorecte de deblocare a tabletei. Profilul de serviciu va fi eliminat, iar toate datele profilului vor fi șterse."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Ați efectuat <xliff:g id="NUMBER">%d</xliff:g> încercări incorecte de deblocare a telefonului. Profilul de serviciu va fi eliminat, iar toate datele profilului vor fi șterse."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Ați desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereușite, vi se va solicita să deblocați tableta cu ajutorul unui cont de e-mail.\n\n Încercați din nou peste <xliff:g id="NUMBER_2">%3$d</xliff:g> secunde."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Ați desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereușite, vi se va solicita să deblocați telefonul cu ajutorul unui cont de e-mail.\n\n Încercați din nou peste <xliff:g id="NUMBER_2">%3$d</xliff:g> secunde."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Repoziționați telefonul pentru încărcare mai rapidă"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Repoziționați telefonul pentru încărcarea wireless"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Dispozitivul Android TV se va opri în curând. Apăsați un buton pentru a-l menține pornit."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Dispozitivul se va opri în curând. Apăsați pentru a-l menține pornit."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Nu există card SIM în tabletă."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Nu există card SIM în telefon."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"Codurile PIN nu coincid"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Ați efectuat <xliff:g id="NUMBER_0">%1$d</xliff:g> încercări incorecte de deblocare a tabletei. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereușite, această tabletă va fi resetată, iar toate datele acesteia vor fi șterse."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Ați efectuat <xliff:g id="NUMBER_0">%1$d</xliff:g> încercări incorecte de deblocare a telefonului. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereușite, acest telefon va fi resetat, iar toate datele acestuia vor fi șterse."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Ați efectuat <xliff:g id="NUMBER">%d</xliff:g> încercări incorecte de deblocare a tabletei. Această tabletă va fi resetată, iar toate datele acesteia vor fi șterse."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Ați efectuat <xliff:g id="NUMBER">%d</xliff:g> încercări incorecte de deblocare a telefonului. Acest telefon va fi resetat, iar toate datele acestuia vor fi șterse."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Ați efectuat <xliff:g id="NUMBER_0">%1$d</xliff:g> încercări incorecte de deblocare a tabletei. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereușite, acest utilizator va fi eliminat, iar toate datele utilizatorului vor fi șterse."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Ați efectuat <xliff:g id="NUMBER_0">%1$d</xliff:g> încercări incorecte de deblocare a telefonului. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereușite, acest utilizator va fi eliminat, iar toate datele utilizatorului vor fi șterse."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Ați efectuat <xliff:g id="NUMBER">%d</xliff:g> încercări incorecte de deblocare a tabletei. Acest utilizator va fi eliminat, iar toate datele utilizatorului vor fi șterse."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Ați efectuat <xliff:g id="NUMBER">%d</xliff:g> încercări incorecte de deblocare a telefonului. Acest utilizator va fi eliminat, iar toate datele utilizatorului vor fi șterse."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Ați efectuat <xliff:g id="NUMBER_0">%1$d</xliff:g> încercări incorecte de deblocare a tabletei. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereușite, profilul de serviciu va fi eliminat, iar toate datele profilului vor fi șterse."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Ați efectuat <xliff:g id="NUMBER_0">%1$d</xliff:g> încercări incorecte de deblocare a telefonului. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereușite, profilul de serviciu va fi eliminat, iar toate datele profilului vor fi șterse."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Ați efectuat <xliff:g id="NUMBER">%d</xliff:g> încercări incorecte de deblocare a tabletei. Profilul de serviciu va fi eliminat, iar toate datele profilului vor fi șterse."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Ați efectuat <xliff:g id="NUMBER">%d</xliff:g> încercări incorecte de deblocare a telefonului. Profilul de serviciu va fi eliminat, iar toate datele profilului vor fi șterse."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Ați desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereușite, vi se va solicita să deblocați tableta cu ajutorul unui cont de e-mail.\n\n Încercați din nou peste <xliff:g id="NUMBER_2">%3$d</xliff:g> secunde."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Ați desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereușite, vi se va solicita să deblocați telefonul cu ajutorul unui cont de e-mail.\n\n Încercați din nou peste <xliff:g id="NUMBER_2">%3$d</xliff:g> secunde."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-ru/strings.xml b/packages/SystemUI/res-product/values-ru/strings.xml
index a8707747cb92..e4cb70d2b215 100644
--- a/packages/SystemUI/res-product/values-ru/strings.xml
+++ b/packages/SystemUI/res-product/values-ru/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"Нет SIM-карты."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"Нет SIM-карты."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"PIN-коды не совпадают."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Вы пытались разблокировать планшет несколько раз (<xliff:g id="NUMBER_0">%1$d</xliff:g>). Осталось попыток: <xliff:g id="NUMBER_1">%2$d</xliff:g>. В случае неудачи произойдет сброс настроек и все данные на устройстве будут удалены."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Вы пытались разблокировать телефон несколько раз (<xliff:g id="NUMBER_0">%1$d</xliff:g>). Осталось попыток: <xliff:g id="NUMBER_1">%2$d</xliff:g>. В случае неудачи произойдет сброс настроек и все данные на устройстве будут удалены."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Достигнуто максимальное количество неудачных попыток разблокировать планшет (<xliff:g id="NUMBER">%d</xliff:g>). Настройки устройства будут сброшены, а все его данные – удалены."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Достигнуто максимальное количество неудачных попыток разблокировать телефон (<xliff:g id="NUMBER">%d</xliff:g>). Настройки устройства будут сброшены, а все его данные – удалены."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Вы пытались разблокировать планшет несколько раз (<xliff:g id="NUMBER_0">%1$d</xliff:g>). Осталось попыток: <xliff:g id="NUMBER_1">%2$d</xliff:g>. В случае неудачи профиль пользователя и все его данные будут удалены."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Вы пытались разблокировать телефон несколько раз (<xliff:g id="NUMBER_0">%1$d</xliff:g>). Осталось попыток: <xliff:g id="NUMBER_1">%2$d</xliff:g>. В случае неудачи профиль пользователя и все его данные будут удалены."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Устройство Android TV скоро выключится. Чтобы этого не произошло, нажмите любую кнопку."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Устройство скоро выключится. Чтобы этого не произошло, нажмите любую кнопку или коснитесь экрана."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Достигнуто максимальное количество неудачных попыток разблокировать планшет (<xliff:g id="NUMBER">%d</xliff:g>). Рабочий профиль и все его данные будут удалены."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Достигнуто максимальное количество неудачных попыток разблокировать телефон (<xliff:g id="NUMBER">%d</xliff:g>). Рабочий профиль и все его данные будут удалены."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Вы ввели неверный графический ключ несколько раз (<xliff:g id="NUMBER_0">%1$d</xliff:g>). Осталось попыток: <xliff:g id="NUMBER_1">%2$d</xliff:g>. В случае неудачи вам будет предложено разблокировать планшет с помощью аккаунта электронной почты.\n\nПовторите попытку через <xliff:g id="NUMBER_2">%3$d</xliff:g> сек."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Вы ввели неверный графический ключ несколько раз (<xliff:g id="NUMBER_0">%1$d</xliff:g>). Осталось попыток: <xliff:g id="NUMBER_1">%2$d</xliff:g>. В случае неудачи вам будет предложено разблокировать телефон с помощью аккаунта электронной почты.\n\nПовторите попытку через <xliff:g id="NUMBER_2">%3$d</xliff:g> сек."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Чтобы ускорить зарядку, поставьте телефон на док-станцию"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Чтобы телефон заряжался, поставьте его на док-станцию"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Устройство Android TV скоро выключится. Чтобы этого не произошло, нажмите любую кнопку."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Устройство скоро выключится. Чтобы этого не произошло, нажмите любую кнопку или коснитесь экрана."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"SIM-карта не установлена."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"SIM-карта не установлена."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"PIN-коды не совпадают"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Вы несколько раз (<xliff:g id="NUMBER_0">%1$d</xliff:g>) не смогли разблокировать планшет. Осталось попыток: <xliff:g id="NUMBER_1">%2$d</xliff:g>. В случае неудачи произойдет сброс настроек и все данные на устройстве будут удалены."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Вы несколько раз (<xliff:g id="NUMBER_0">%1$d</xliff:g>) не смогли разблокировать телефон. Осталось попыток: <xliff:g id="NUMBER_1">%2$d</xliff:g>. В случае неудачи произойдет сброс настроек и все данные на устройстве будут удалены."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Вы несколько раз (<xliff:g id="NUMBER">%d</xliff:g>) не смогли разблокировать планшет. Настройки устройства будут сброшены, а все его данные – удалены."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Вы несколько раз (<xliff:g id="NUMBER">%d</xliff:g>) не смогли разблокировать телефон. Настройки устройства будут сброшены, а все его данные – удалены."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Вы несколько раз (<xliff:g id="NUMBER_0">%1$d</xliff:g>) не смогли разблокировать планшет. Осталось попыток: <xliff:g id="NUMBER_1">%2$d</xliff:g>. В случае неудачи профиль пользователя и все его данные будут удалены."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Вы несколько раз (<xliff:g id="NUMBER_0">%1$d</xliff:g>) не смогли разблокировать телефон. Осталось попыток: <xliff:g id="NUMBER_1">%2$d</xliff:g>. В случае неудачи профиль пользователя и все его данные будут удалены."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Вы несколько раз (<xliff:g id="NUMBER">%d</xliff:g>) не смогли разблокировать планшет. Профиль пользователя и все его данные будут удалены."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Вы несколько раз (<xliff:g id="NUMBER">%d</xliff:g>) не смогли разблокировать телефон. Профиль пользователя и все его данные будут удалены."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Вы несколько раз (<xliff:g id="NUMBER_0">%1$d</xliff:g>) не смогли разблокировать планшет. Осталось попыток: <xliff:g id="NUMBER_1">%2$d</xliff:g>. В случае неудачи рабочий профиль и все его данные будут удалены."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Вы несколько раз (<xliff:g id="NUMBER_0">%1$d</xliff:g>) не смогли разблокировать телефон. Осталось попыток: <xliff:g id="NUMBER_1">%2$d</xliff:g>. В случае неудачи рабочий профиль и все его данные будут удалены."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Вы несколько раз (<xliff:g id="NUMBER">%d</xliff:g>) не смогли разблокировать планшет. Рабочий профиль и все его данные будут удалены."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Вы несколько раз (<xliff:g id="NUMBER">%d</xliff:g>) не смогли разблокировать телефон. Рабочий профиль и все его данные будут удалены."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Вы несколько раз (<xliff:g id="NUMBER_0">%1$d</xliff:g>) ввели неверный графический ключ. Осталось попыток: <xliff:g id="NUMBER_1">%2$d</xliff:g>. В случае неудачи вам будет предложено разблокировать планшет с помощью аккаунта электронной почты.\n\nПовторите попытку через <xliff:g id="NUMBER_2">%3$d</xliff:g> сек."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Вы несколько раз (<xliff:g id="NUMBER_0">%1$d</xliff:g>) ввели неверный графический ключ. Осталось попыток: <xliff:g id="NUMBER_1">%2$d</xliff:g>. В случае неудачи вам будет предложено разблокировать телефон с помощью аккаунта электронной почты.\n\nПовторите попытку через <xliff:g id="NUMBER_2">%3$d</xliff:g> сек."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-si/strings.xml b/packages/SystemUI/res-product/values-si/strings.xml
index 2d02d1f66370..dcdbe319b4ec 100644
--- a/packages/SystemUI/res-product/values-si/strings.xml
+++ b/packages/SystemUI/res-product/values-si/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"ටැබ්ලටයේ SIM පත නොමැත."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"දුරකථනය තුල SIM පතක් නැත."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"PIN කේත නොගැළපේ."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"ඔබ ටැබ්ලට් පරිගණකය අගුළු හැරීමට <xliff:g id="NUMBER_0">%1$d</xliff:g> වරක් වැරදියට උත්සාහ කර ඇත. තවත් අසාර්ථක උත්සාහයන් <xliff:g id="NUMBER_1">%2$d</xliff:g>කින් පසුව, මෙම ටැබ්ලට් පරිගණකය යළි සකසනු ඇති අතර, එය එහි සියලු දත්ත මකනු ඇත."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"ඔබ දුරකථනය අගුළු හැරීමට <xliff:g id="NUMBER_0">%1$d</xliff:g> වරක් වැරදියට උත්සාහ කර ඇත. තවත් අසාර්ථක උත්සාහයන් <xliff:g id="NUMBER_1">%2$d</xliff:g>කින් පසුව, මෙම දුරකථනය යළි සකසනු ඇති අතර, එය එහි සියලු දත්ත මකනු ඇත."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"ඔබ ටැබ්ලට් පරිගණකය අගුළු හැරීමට <xliff:g id="NUMBER">%d</xliff:g> වරක් වැරදියට උත්සාහ කර ඇත. මෙම ටැබ්ලට් පරිගණකය යළි සකසනු ඇති අතර, එය එහි සියලු පදත්ත මකනු ඇත."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"ඔබ දුරකථනය අගුළු හැරීමට <xliff:g id="NUMBER">%d</xliff:g> වරක් වැරදියට උත්සාහ කර ඇත. මෙම දුරකථනය යළි සකසනු ඇති අතර, එය එහි සියලු පදත්ත මකනු ඇත."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"ඔබ ටැබ්ලට් පරිගණකය අගුළු හැරීමට <xliff:g id="NUMBER_0">%1$d</xliff:g> වරක් වැරදියට උත්සාහ කර ඇත. තවත් අසාර්ථක උත්සාහයන් <xliff:g id="NUMBER_1">%2$d</xliff:g>කින් පසුව, මෙම පරිශීලකයා ඉවත් කරනු ඇති අතර, එය සියලු පරිශීලක දත්ත මකනු ඇත."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"ඔබ දුරකථනය අගුළු හැරීමට <xliff:g id="NUMBER_0">%1$d</xliff:g> වරක් වැරදියට උත්සාහ කර ඇත. තවත් අසාර්ථක උත්සාහයන් <xliff:g id="NUMBER_1">%2$d</xliff:g>කින් පසුව, මෙම පරිශීලකයා ඉවත් කරනු ඇති අතර, එය සියලු පරිශීලක දත්ත මකනු ඇත."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Android TV උපාංගය ඉක්මනින් ක්‍රියා විරහිත වනු ඇත; එය දිගටම ක්‍රියාත්මක කර තැබීමට බොත්තමක් ඔබන්න."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"උපාංගය ඉක්මනින් ක්‍රියා විරහිත වනු ඇත; එය දිගටම ක්‍රියාත්මක කර තැබීමට ඔබන්න."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"ඔබ ටැබ්ලට් පරිගණකය අගුළු හැරීමට <xliff:g id="NUMBER">%d</xliff:g> වරක් වැරදියට උත්සාහ කර ඇත. කාර්යාල පැතිකඩ ඉවත් කරනු ඇති අතර, එය සියලු පැතිකඩ දත්ත මකනු ඇත."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"ඔබ දුරකථනය අගුළු හැරීමට <xliff:g id="NUMBER">%d</xliff:g> වරක් වැරදියට උත්සාහ කර ඇත. කාර්යාල පැතිකඩ ඉවත් කරනු ඇති අතර, එය සියලු පැතිකඩ දත්ත මකනු ඇත."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"ඔබ අගුළු ඇරිමේ රටාව <xliff:g id="NUMBER_0">%1$d</xliff:g> වතාවක් වැරදියට ඇඳ ඇත. තවත් අසාර්ථක උත්සාහ <xliff:g id="NUMBER_1">%2$d</xliff:g> කින් පසුව, ඊ-තැපැල් ගිණුම භාවිතා කරමින් ඔබගේ ටැබ්ලටයේ අගුළු ඇරීමට ඔබට පවසනු ඇත.\n\n නැවත තත්පර <xliff:g id="NUMBER_2">%3$d</xliff:g> කින් උත්සාහ කරන්න."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"ඔබ වැරදියට <xliff:g id="NUMBER_0">%1$d</xliff:g> වතාවක් ඔබගේ අගුළු හැරීමේ රටාව ඇඳ ඇත. අසාර්ථක උත්සහ කිරීම් <xliff:g id="NUMBER_1">%2$d</xliff:g> න් පසුව, ඔබගේ ඊ-තැපැල් ලිපිනය භාවිතයෙන් ඔබගේ දුරකථනය අගුළු හැරීමට ඔබගෙන් අසයි.\n\n තත්පර <xliff:g id="NUMBER_2">%3$d</xliff:g> න් පසුව නැවත උත්සහ කරන්න."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"වඩා වේගවත් ආරෝපණය සඳහා දුරකථනය යළි සකසන්න"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"නොරැහැන්ව ආරෝපණය කිරීමට දුරකථනය යළි සකසන්න"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Android TV උපාංගය ඉක්මනින් ක්‍රියා විරහිත වනු ඇත; එය දිගටම ක්‍රියාත්මක කර තැබීමට බොත්තමක් ඔබන්න."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"උපාංගය ඉක්මනින් ක්‍රියා විරහිත වනු ඇත; එය දිගටම ක්‍රියාත්මක කර තැබීමට ඔබන්න."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"ටැබ්ලට් පරිගණකයේ SIM පත නොමැත."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"දුරකථනයේ SIM පතක් නැත."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"PIN කේත නොගැළපේ."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"ඔබ ටැබ්ලට් පරිගණකය අගුළු හැරීමට <xliff:g id="NUMBER_0">%1$d</xliff:g> වරක් වැරදියට උත්සාහ කර ඇත. තවත් අසාර්ථක උත්සාහයන් <xliff:g id="NUMBER_1">%2$d</xliff:g>කින් පසුව, මෙම ටැබ්ලට් පරිගණකය යළි සකසනු ඇති අතර, එය එහි සියලු දත්ත මකනු ඇත."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"ඔබ දුරකථනය අගුළු හැරීමට <xliff:g id="NUMBER_0">%1$d</xliff:g> වරක් වැරදියට උත්සාහ කර ඇත. තවත් අසාර්ථක උත්සාහයන් <xliff:g id="NUMBER_1">%2$d</xliff:g>කින් පසුව, මෙම දුරකථනය යළි සකසනු ඇති අතර, එය එහි සියලු දත්ත මකනු ඇත."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"ඔබ ටැබ්ලට් පරිගණකය අගුළු හැරීමට <xliff:g id="NUMBER">%d</xliff:g> වරක් වැරදියට උත්සාහ කර ඇත. මෙම ටැබ්ලට් පරිගණකය යළි සකසනු ඇති අතර, එය එහි සියලු පදත්ත මකනු ඇත."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"ඔබ දුරකථනය අගුළු හැරීමට <xliff:g id="NUMBER">%d</xliff:g> වරක් වැරදියට උත්සාහ කර ඇත. මෙම දුරකථනය යළි සකසනු ඇති අතර, එය එහි සියලු පදත්ත මකනු ඇත."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"ඔබ ටැබ්ලට් පරිගණකය අගුළු හැරීමට <xliff:g id="NUMBER_0">%1$d</xliff:g> වරක් වැරදියට උත්සාහ කර ඇත. තවත් අසාර්ථක උත්සාහයන් <xliff:g id="NUMBER_1">%2$d</xliff:g>කින් පසුව, මෙම පරිශීලකයා ඉවත් කරනු ඇති අතර, එය සියලු පරිශීලක දත්ත මකනු ඇත."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"ඔබ දුරකථනය අගුළු හැරීමට <xliff:g id="NUMBER_0">%1$d</xliff:g> වරක් වැරදියට උත්සාහ කර ඇත. තවත් අසාර්ථක උත්සාහයන් <xliff:g id="NUMBER_1">%2$d</xliff:g>කින් පසුව, මෙම පරිශීලකයා ඉවත් කරනු ඇති අතර, එය සියලු පරිශීලක දත්ත මකනු ඇත."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"ඔබ ටැබ්ලට් පරිගණකය අගුළු හැරීමට <xliff:g id="NUMBER">%d</xliff:g> වරක් වැරදියට උත්සාහ කර ඇත. මෙම පරිශීලකයා ඉවත් කරනු ඇති අතර, එය සියලු පරිශීලක දත්ත මකනු ඇත."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"ඔබ දුරකථනය අගුළු හැරීමට <xliff:g id="NUMBER">%d</xliff:g> වරක් වැරදියට උත්සාහ කර ඇත. මෙම පරිශීලකයා ඉවත් කරනු ඇති අතර, එය සියලු පරිශීලක දත්ත මකනු ඇත."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"ඔබ ටැබ්ලට් පරිගණකය අගුළු හැරීමට <xliff:g id="NUMBER_0">%1$d</xliff:g> වරක් වැරදියට උත්සාහ කර ඇත. තවත් අසාර්ථක උත්සාහයන් <xliff:g id="NUMBER_1">%2$d</xliff:g>කින් පසුව, කාර්යාල පැතිකඩ ඉවත් කරනු ඇති අතර, එය සියලු පැතිකඩ දත්ත මකනු ඇත."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"ඔබ දුරකථනය අගුළු හැරීමට <xliff:g id="NUMBER_0">%1$d</xliff:g> වරක් වැරදියට උත්සාහ කර ඇත. තවත් අසාර්ථක උත්සාහයන් <xliff:g id="NUMBER_1">%2$d</xliff:g>කින් පසුව, කාර්යාල පැතිකඩ ඉවත් කරනු ඇති අතර, එය සියලු පැතිකඩ දත්ත මකනු ඇත."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"ඔබ ටැබ්ලට් පරිගණකය අගුළු හැරීමට <xliff:g id="NUMBER">%d</xliff:g> වරක් වැරදියට උත්සාහ කර ඇත. කාර්යාල පැතිකඩ ඉවත් කරනු ඇති අතර, එය සියලු පැතිකඩ දත්ත මකනු ඇත."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"ඔබ දුරකථනය අගුළු හැරීමට <xliff:g id="NUMBER">%d</xliff:g> වරක් වැරදියට උත්සාහ කර ඇත. කාර්යාල පැතිකඩ ඉවත් කරනු ඇති අතර, එය සියලු පැතිකඩ දත්ත මකනු ඇත."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"ඔබ අගුළු ඇරිමේ රටාව <xliff:g id="NUMBER_0">%1$d</xliff:g> වතාවක් වැරදියට ඇඳ ඇත. තවත් අසාර්ථක උත්සාහ <xliff:g id="NUMBER_1">%2$d</xliff:g> කින් පසුව, ඊ-තැපැල් ගිණුම භාවිතා කරමින් ඔබගේ ටැබ්ලටයේ අගුළු ඇරීමට ඔබට පවසනු ඇත.\n\n නැවත තත්පර <xliff:g id="NUMBER_2">%3$d</xliff:g> කින් උත්සාහ කරන්න."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"ඔබ වැරදියට <xliff:g id="NUMBER_0">%1$d</xliff:g> වතාවක් ඔබගේ අගුළු හැරීමේ රටාව ඇඳ ඇත. අසාර්ථක උත්සහ කිරීම් <xliff:g id="NUMBER_1">%2$d</xliff:g> න් පසුව, ඔබගේ ඊ-තැපැල් ලිපිනය භාවිතයෙන් ඔබගේ දුරකථනය අගුළු හැරීමට ඔබගෙන් අසයි.\n\n තත්පර <xliff:g id="NUMBER_2">%3$d</xliff:g> න් පසුව නැවත උත්සහ කරන්න."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-sk/strings.xml b/packages/SystemUI/res-product/values-sk/strings.xml
index b57ecf9d77a9..bcb73178ec5b 100644
--- a/packages/SystemUI/res-product/values-sk/strings.xml
+++ b/packages/SystemUI/res-product/values-sk/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"V tablete nie je žiadna SIM karta."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"V telefóne nie je žiadna SIM karta."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"Kódy PIN sa nezhodujú"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Tablet ste sa pokúsili <xliff:g id="NUMBER_0">%1$d</xliff:g>-krát nesprávne odomknúť. Po ďalších neúspešných pokusoch (počet: <xliff:g id="NUMBER_1">%2$d</xliff:g>) bude tento tablet obnovený a všetky údaje, ktoré sú v ňom uložené, budú odstránené."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Telefón ste sa pokúsili <xliff:g id="NUMBER_0">%1$d</xliff:g>-krát nesprávne odomknúť. Po ďalších neúspešných pokusoch (počet: <xliff:g id="NUMBER_1">%2$d</xliff:g>) bude tento telefón obnovený a všetky údaje, ktoré sú v ňom uložené, budú odstránené."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Tablet ste sa pokúsili <xliff:g id="NUMBER">%d</xliff:g>-krát nesprávne odomknúť. Tablet bude obnovený a všetky údaje, ktoré sú v ňom uložené, budú odstránené."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Telefón ste sa pokúsili <xliff:g id="NUMBER">%d</xliff:g>-krát nesprávne odomknúť. Telefón bude obnovený a všetky údaje, ktoré sú v ňom uložené, budú odstránené."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Tablet ste sa pokúsili <xliff:g id="NUMBER_0">%1$d</xliff:g>-krát nesprávne odomknúť. Po ďalších neúspešných pokusoch (počet: <xliff:g id="NUMBER_1">%2$d</xliff:g>) bude tento používateľ odstránený a spolu s ním všetky jeho údaje."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Telefón ste sa pokúsili <xliff:g id="NUMBER_0">%1$d</xliff:g>-krát nesprávne odomknúť. Po ďalších neúspešných pokusoch (počet: <xliff:g id="NUMBER_1">%2$d</xliff:g>) bude tento používateľ odstránený a spolu s ním všetky jeho údaje."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Zariadenie Android TV sa čoskoro vypne. Ak ho chcete ponechať zapnuté, stlačte ľubovoľné tlačidlo."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Zariadenie sa čoskoro vypne. Ak ho chcete ponechať zapnuté, stlačte ľubovoľné tlačidlo."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Tablet ste sa pokúsili <xliff:g id="NUMBER">%d</xliff:g>-krát nesprávne odomknúť. Pracovný profil bude odstránený spolu so všetkými údajmi."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Telefón ste sa pokúsili <xliff:g id="NUMBER">%d</xliff:g>-krát nesprávne odomknúť. Pracovný profil bude odstránený spolu so všetkými údajmi."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Už ste <xliff:g id="NUMBER_0">%1$d</xliff:g>-krát nesprávne nakreslili svoj bezpečnostný vzor. Po ďalších <xliff:g id="NUMBER_1">%2$d</xliff:g> neúspešných pokusoch sa zobrazí výzva na odomknutie tabletu pomocou e-mailového účtu.\n\n Skúste to znova o <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Už ste <xliff:g id="NUMBER_0">%1$d</xliff:g>-krát nesprávne nakreslili svoj bezpečnostný vzor. Po <xliff:g id="NUMBER_1">%2$d</xliff:g> ďalších neúspešných pokusoch sa zobrazí výzva na odomknutie telefónu pomocou e-mailového účtu.\n\n Skúste to znova o <xliff:g id="NUMBER_2">%3$d</xliff:g>} s."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Znova vložte telefón, aby sa rýchlejšie nabil"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Znova vložte telefón, aby sa bezdrôtovo nabil"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Zariadenie Android TV sa čoskoro vypne. Ak ho chcete ponechať zapnuté, stlačte ľubovoľné tlačidlo."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Zariadenie sa čoskoro vypne. Ak ho chcete ponechať zapnuté, stlačte ľubovoľné tlačidlo."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"V tablete nie je žiadna SIM karta."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"V telefóne nie je žiadna SIM karta."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"Kódy PIN sa nezhodujú"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Tablet ste sa pokúsili <xliff:g id="NUMBER_0">%1$d</xliff:g>‑krát nesprávne odomknúť. Po <xliff:g id="NUMBER_1">%2$d</xliff:g> ďalších neúspešných pokusoch bude tento tablet obnovený a všetky údaje, ktoré sú v ňom uložené, budú odstránené."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Telefón ste sa pokúsili <xliff:g id="NUMBER_0">%1$d</xliff:g>‑krát nesprávne odomknúť. Po <xliff:g id="NUMBER_1">%2$d</xliff:g> ďalších neúspešných pokusoch bude tento telefón obnovený a všetky údaje, ktoré sú v ňom uložené, budú odstránené."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Tablet ste sa pokúsili <xliff:g id="NUMBER">%d</xliff:g>‑krát nesprávne odomknúť. Tablet bude obnovený a všetky údaje, ktoré sú v ňom uložené, budú odstránené."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Telefón ste sa pokúsili <xliff:g id="NUMBER">%d</xliff:g>‑krát nesprávne odomknúť. Telefón bude obnovený a všetky údaje, ktoré sú v ňom uložené, budú odstránené."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Tablet ste sa pokúsili <xliff:g id="NUMBER_0">%1$d</xliff:g>‑krát nesprávne odomknúť. Po <xliff:g id="NUMBER_1">%2$d</xliff:g> ďalších neúspešných pokusoch bude tento používateľ odstránený a spolu s ním všetky jeho údaje."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Telefón ste sa pokúsili <xliff:g id="NUMBER_0">%1$d</xliff:g>‑krát nesprávne odomknúť. Po <xliff:g id="NUMBER_1">%2$d</xliff:g> ďalších neúspešných pokusoch bude tento používateľ odstránený a spolu s ním všetky jeho údaje."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Tablet ste sa pokúsili <xliff:g id="NUMBER">%d</xliff:g>‑krát nesprávne odomknúť. Používateľ bude odstránený a spolu s ním všetky jeho údaje."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Telefón ste sa pokúsili <xliff:g id="NUMBER">%d</xliff:g>‑krát nesprávne odomknúť. Používateľ bude odstránený a spolu s ním všetky jeho údaje."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Tablet ste sa pokúsili <xliff:g id="NUMBER_0">%1$d</xliff:g>‑krát nesprávne odomknúť. Po <xliff:g id="NUMBER_1">%2$d</xliff:g> ďalších neúspešných pokusoch bude pracovný profil odstránený a spolu s ním všetky údaje profilu."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Telefón ste sa pokúsili <xliff:g id="NUMBER_0">%1$d</xliff:g>‑krát nesprávne odomknúť. Po <xliff:g id="NUMBER_1">%2$d</xliff:g> ďalších neúspešných pokusoch bude pracovný profil odstránený a spolu s ním všetky údaje profilu."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Tablet ste sa pokúsili <xliff:g id="NUMBER">%d</xliff:g>‑krát nesprávne odomknúť. Pracovný profil bude odstránený spolu so všetkými údajmi."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Telefón ste sa pokúsili <xliff:g id="NUMBER">%d</xliff:g>‑krát nesprávne odomknúť. Pracovný profil bude odstránený spolu so všetkými údajmi."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"<xliff:g id="NUMBER_0">%1$d</xliff:g>‑krát ste nesprávne nakreslili svoj bezpečnostný vzor. Po <xliff:g id="NUMBER_1">%2$d</xliff:g> ďalších neúspešných pokusoch sa zobrazí výzva na odomknutie tabletu pomocou e‑mailového účtu.\n\n Skúste to znova o <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Už ste <xliff:g id="NUMBER_0">%1$d</xliff:g>‑krát nesprávne nakreslili svoj bezpečnostný vzor. Po <xliff:g id="NUMBER_1">%2$d</xliff:g> ďalších neúspešných pokusoch sa zobrazí výzva na odomknutie telefónu pomocou e‑mailového účtu.\n\n Skúste to znova o <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-sl/strings.xml b/packages/SystemUI/res-product/values-sl/strings.xml
index 99cb111dc8c3..53249e16e436 100644
--- a/packages/SystemUI/res-product/values-sl/strings.xml
+++ b/packages/SystemUI/res-product/values-sl/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"V tabličnem računalniku ni kartice SIM."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"V telefonu ni kartice SIM."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"Kodi PIN se ne ujemata"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Tablični računalnik ste neuspešno poskusili odkleniti <xliff:g id="NUMBER_0">%1$d</xliff:g>-krat. Če ga neuspešno poskusite odkleniti še <xliff:g id="NUMBER_1">%2$d</xliff:g>-krat, bo ponastavljen in vsi podatki v njem bodo izbrisani."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Telefon ste neuspešno poskusili odkleniti <xliff:g id="NUMBER_0">%1$d</xliff:g>-krat. Če ga neuspešno poskusite odkleniti še <xliff:g id="NUMBER_1">%2$d</xliff:g>-krat, bo ponastavljen in vsi podatki v njem bodo izbrisani."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Tablični računalnik ste neuspešno poskusili odkleniti <xliff:g id="NUMBER">%d</xliff:g>-krat, zato bo ponastavljen, vsi podatki v njem pa bodo izbrisani."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Telefon ste neuspešno poskusili odkleniti <xliff:g id="NUMBER">%d</xliff:g>-krat, zato bo ponastavljen, vsi podatki v njem pa bodo izbrisani."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Tablični računalnik ste neuspešno poskusili odkleniti <xliff:g id="NUMBER_0">%1$d</xliff:g>-krat. Če ga neuspešno poskusite odkleniti še <xliff:g id="NUMBER_1">%2$d</xliff:g>-krat, bo ta uporabnik odstranjen in vsi podatki uporabnika bodo izbrisani."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Telefon ste neuspešno poskusili odkleniti <xliff:g id="NUMBER_0">%1$d</xliff:g>-krat. Če ga neuspešno poskusite odkleniti še <xliff:g id="NUMBER_1">%2$d</xliff:g>-krat, bo ta uporabnik odstranjen in vsi podatki uporabnika bodo izbrisani."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Naprava Android TV se bo kmalu izklopila. Če tega ne želite, pritisnite poljuben gumb."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Naprava se bo kmalu izklopila. Če tega ne želite, pritisnite poljuben gumb."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Tablični računalnik ste neuspešno poskusili odkleniti <xliff:g id="NUMBER">%d</xliff:g>-krat. Delovni profil bo odstranjen in vsi podatki profila bodo izbrisani."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Telefon ste neuspešno poskusili odkleniti <xliff:g id="NUMBER">%d</xliff:g>-krat. Delovni profil bo odstranjen in vsi podatki profila bodo izbrisani."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Vzorec za odklepanje ste <xliff:g id="NUMBER_0">%1$d</xliff:g>-krat napačno vnesli. Če ga neuspešno poskusite vnesti še <xliff:g id="NUMBER_1">%2$d</xliff:g>-krat, boste pozvani, da tablični računalnik odklenete z e-poštnim računom.\n\n Poskusite znova čez <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Vzorec za odklepanje ste <xliff:g id="NUMBER_0">%1$d</xliff:g>-krat napačno vnesli. Če ga neuspešno poskusite vnesti še <xliff:g id="NUMBER_1">%2$d</xliff:g>-krat, boste pozvani, da telefon odklenete z Googlovimi podatki za prijavo.\n\nPoskusite znova čez <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Za hitrejše polnjenje poravnajte telefon z nosilcem"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Za brezžično polnjenje poravnajte telefon z nosilcem"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Naprava Android TV se bo kmalu izklopila. Če tega ne želite, pritisnite poljuben gumb."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Naprava se bo kmalu izklopila. Če tega ne želite, pritisnite."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"V tabličnem računalniku ni kartice SIM."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"V telefonu ni kartice SIM."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"Kodi PIN se ne ujemata"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Tablični računalnik ste neuspešno poskusili odkleniti <xliff:g id="NUMBER_0">%1$d</xliff:g>-krat. Če ga neuspešno poskusite odkleniti še <xliff:g id="NUMBER_1">%2$d</xliff:g>-krat, bo ponastavljen in vsi podatki v njem bodo izbrisani."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Telefon ste neuspešno poskusili odkleniti <xliff:g id="NUMBER_0">%1$d</xliff:g>-krat. Če ga neuspešno poskusite odkleniti še <xliff:g id="NUMBER_1">%2$d</xliff:g>-krat, bo ponastavljen in vsi podatki v njem bodo izbrisani."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Tablični računalnik ste neuspešno poskusili odkleniti <xliff:g id="NUMBER">%d</xliff:g>-krat, zato bo ponastavljen, vsi podatki v njem pa bodo izbrisani."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Telefon ste neuspešno poskusili odkleniti <xliff:g id="NUMBER">%d</xliff:g>-krat, zato bo ponastavljen, vsi podatki v njem pa bodo izbrisani."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Tablični računalnik ste neuspešno poskusili odkleniti <xliff:g id="NUMBER_0">%1$d</xliff:g>-krat. Če ga neuspešno poskusite odkleniti še <xliff:g id="NUMBER_1">%2$d</xliff:g>-krat, bo ta uporabnik odstranjen in vsi podatki uporabnika bodo izbrisani."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Telefon ste neuspešno poskusili odkleniti <xliff:g id="NUMBER_0">%1$d</xliff:g>-krat. Če ga neuspešno poskusite odkleniti še <xliff:g id="NUMBER_1">%2$d</xliff:g>-krat, bo ta uporabnik odstranjen in vsi podatki uporabnika bodo izbrisani."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Tablični računalnik ste neuspešno poskusili odkleniti <xliff:g id="NUMBER">%d</xliff:g>-krat. Ta uporabnik bo odstranjen in vsi podatki uporabnika bodo izbrisani."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Telefon ste neuspešno poskusili odkleniti <xliff:g id="NUMBER">%d</xliff:g>-krat. Ta uporabnik bo odstranjen in vsi podatki uporabnika bodo izbrisani."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Tablični računalnik ste neuspešno poskusili odkleniti <xliff:g id="NUMBER_0">%1$d</xliff:g>-krat. Če ga neuspešno poskusite odkleniti še <xliff:g id="NUMBER_1">%2$d</xliff:g>-krat, bo delovni profil odstranjen in vsi podatki profila bodo izbrisani."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Telefon ste neuspešno poskusili odkleniti <xliff:g id="NUMBER_0">%1$d</xliff:g>-krat. Če ga neuspešno poskusite odkleniti še <xliff:g id="NUMBER_1">%2$d</xliff:g>-krat, bo delovni profil odstranjen in vsi podatki profila bodo izbrisani."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Tablični računalnik ste neuspešno poskusili odkleniti <xliff:g id="NUMBER">%d</xliff:g>-krat. Delovni profil bo odstranjen in vsi podatki profila bodo izbrisani."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Telefon ste neuspešno poskusili odkleniti <xliff:g id="NUMBER">%d</xliff:g>-krat. Delovni profil bo odstranjen in vsi podatki profila bodo izbrisani."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Vzorec za odklepanje ste <xliff:g id="NUMBER_0">%1$d</xliff:g>-krat napačno vnesli. Če ga neuspešno poskusite vnesti še <xliff:g id="NUMBER_1">%2$d</xliff:g>-krat, boste pozvani, da tablični računalnik odklenete z e-poštnim računom.\n\nPoskusite znova čez <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Vzorec za odklepanje ste <xliff:g id="NUMBER_0">%1$d</xliff:g>-krat napačno vnesli. Če ga neuspešno poskusite vnesti še <xliff:g id="NUMBER_1">%2$d</xliff:g>-krat, boste pozvani, da telefon odklenete z e-poštnim računom.\n\nPoskusite znova čez <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-sq/strings.xml b/packages/SystemUI/res-product/values-sq/strings.xml
index 723c4757e71f..a7508e3ea20a 100644
--- a/packages/SystemUI/res-product/values-sq/strings.xml
+++ b/packages/SystemUI/res-product/values-sq/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"Nuk ka kartë SIM në tablet."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"Në telefon nuk ka kartë SIM."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"Kodet PIN nuk përputhen"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Ke tentuar <xliff:g id="NUMBER_0">%1$d</xliff:g> herë gabimisht për ta shkyçur tabletin. Pas <xliff:g id="NUMBER_1">%2$d</xliff:g> përpjekjeve të tjera të pasuksesshme, tableti do të rivendoset, gjë që do të rivendosë të gjitha të dhënat e tij."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Ke tentuar <xliff:g id="NUMBER_0">%1$d</xliff:g> herë gabimisht për ta shkyçur telefonin. Pas <xliff:g id="NUMBER_1">%2$d</xliff:g> përpjekjeve të tjera të pasuksesshme, telefoni do të rivendoset, gjë që do të fshijë të gjitha të dhënat e tij."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Ke tentuar <xliff:g id="NUMBER">%d</xliff:g> herë pa sukses për ta shkyçur tabletin. Ky tablet do të rivendoset, gjë që do të fshijë të gjitha të dhënat e tij."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Ke tentuar <xliff:g id="NUMBER">%d</xliff:g> herë pa sukses për ta shkyçur telefonin. Ky telefon do të rivendoset, gjë që do të fshijë të gjitha të dhënat e tij."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Ke tentuar <xliff:g id="NUMBER_0">%1$d</xliff:g> herë pa sukses për ta shkyçur telefonin. Pas <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativave të tjera të pasuksesshme, përdoruesi do të hiqet dhe të gjitha të dhënat e përdoruesit në të, do të fshihen."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Ke tentuar <xliff:g id="NUMBER_0">%1$d</xliff:g> herë pa sukses për ta shkyçur telefonin. Pas <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativave të tjera të pasuksesshme, përdoruesi do të hiqet dhe të gjitha të dhënat e përdoruesit në të, do të fshihen."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Pajisja Android TV do të fiket së shpejti. Shtyp një buton për ta mbajtur të ndezur."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Pajisja do të fiket së shpejti. Shtype për ta mbajtur të ndezur."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Ke tentuar <xliff:g id="NUMBER">%d</xliff:g> herë pa sukses për ta shkyçur tabletin. Profili i punës do të hiqet, gjë që do të fshijë të gjitha të dhënat e profilit."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Ke tentuar <xliff:g id="NUMBER">%d</xliff:g> herë pa sukses për ta shkyçur telefonin. Profili i punës do të hiqet, gjë që do të fshijë të gjitha të dhënat e profilit."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Ke vizatuar <xliff:g id="NUMBER_0">%1$d</xliff:g> herë pa sukses motivin tënd të shkyçjes. Pas <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativave të tjera të pasuksesshme, do të të duhet ta shkyçësh tabletin duke përdorur një llogari mail-i.\n\n Provo sërish për <xliff:g id="NUMBER_2">%3$d</xliff:g> sekonda."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Ke vizatuar <xliff:g id="NUMBER_0">%1$d</xliff:g> herë pa sukses motivin tënd të shkyçjes. Pas <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativave të tjera të pasuksesshme, do të të duhet ta shkyçësh telefonin duke përdorur një llogari mail-i.\n\n Provo sërish për <xliff:g id="NUMBER_2">%3$d</xliff:g> sekonda."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Drejtvendose përsëri telefonin për karikim më të shpejtë"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Drejtvendose përsëri telefonin për ta karikuar me valë"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Pajisja Android TV së shpejti do të fiket. Shtyp një buton për ta mbajtur të ndezur."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Pajisja së shpejti do të fiket. Shtype për ta mbajtur të ndezur."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Nuk ka kartë SIM në tablet."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Në telefon nuk ka kartë SIM."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"Kodet PIN nuk përputhen"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Ke tentuar <xliff:g id="NUMBER_0">%1$d</xliff:g> herë gabimisht për ta shkyçur tabletin. Pas <xliff:g id="NUMBER_1">%2$d</xliff:g> përpjekjeve të tjera të pasuksesshme, tableti do të rivendoset, gjë që do të rivendosë të gjitha të dhënat e tij."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Ke tentuar <xliff:g id="NUMBER_0">%1$d</xliff:g> herë gabimisht për ta shkyçur telefonin. Pas <xliff:g id="NUMBER_1">%2$d</xliff:g> përpjekjeve të tjera të pasuksesshme, telefoni do të rivendoset, gjë që do të fshijë të gjitha të dhënat e tij."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Ke tentuar <xliff:g id="NUMBER">%d</xliff:g> herë pa sukses për ta shkyçur tabletin. Ky tablet do të rivendoset, gjë që do të fshijë të gjitha të dhënat e tij."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Ke tentuar <xliff:g id="NUMBER">%d</xliff:g> herë pa sukses për ta shkyçur telefonin. Ky telefon do të rivendoset, gjë që do të fshijë të gjitha të dhënat e tij."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Ke tentuar <xliff:g id="NUMBER_0">%1$d</xliff:g> herë pa sukses për ta shkyçur telefonin. Pas <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativave të tjera të pasuksesshme, përdoruesi do të hiqet dhe të gjitha të dhënat e përdoruesit në të, do të fshihen."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Ke tentuar <xliff:g id="NUMBER_0">%1$d</xliff:g> herë pa sukses për ta shkyçur telefonin. Pas <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativave të tjera të pasuksesshme, përdoruesi do të hiqet dhe të gjitha të dhënat e përdoruesit në të, do të fshihen."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Ke tentuar <xliff:g id="NUMBER">%d</xliff:g> herë pa sukses për ta shkyçur tabletin. Përdoruesi do të hiqet, gjë që do të fshijë të gjitha të dhënat e përdoruesit."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Ke tentuar <xliff:g id="NUMBER">%d</xliff:g> herë pa sukses për ta shkyçur telefonin. Përdoruesi do të hiqet, gjë që do të fshijë të gjitha të dhënat e përdoruesit."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Ke tentuar <xliff:g id="NUMBER_0">%1$d</xliff:g> herë pa sukses për ta shkyçur tabletin. Pas <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativave të tjera të pasuksesshme, profili i punës do të hiqet dhe të gjitha të dhënat në të do të fshihen."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Ke tentuar <xliff:g id="NUMBER_0">%1$d</xliff:g> herë pa sukses për ta shkyçur telefonin. Pas <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativave të tjera të pasuksesshme, profili i punës do të hiqet dhe të gjitha të dhënat në të do të fshihen."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Ke tentuar <xliff:g id="NUMBER">%d</xliff:g> herë pa sukses për ta shkyçur tabletin. Profili i punës do të hiqet, gjë që do të fshijë të gjitha të dhënat e profilit."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Ke tentuar <xliff:g id="NUMBER">%d</xliff:g> herë pa sukses për ta shkyçur telefonin. Profili i punës do të hiqet, gjë që do të fshijë të gjitha të dhënat e profilit."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Ke vizatuar <xliff:g id="NUMBER_0">%1$d</xliff:g> herë pa sukses motivin tënd të shkyçjes. Pas <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativave të tjera të pasuksesshme, do të të duhet ta shkyçësh tabletin duke përdorur një llogari email-i.\n\n Provo sërish për <xliff:g id="NUMBER_2">%3$d</xliff:g> sekonda."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Ke vizatuar <xliff:g id="NUMBER_0">%1$d</xliff:g> herë pa sukses motivin tënd. Pas <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativave të tjera të pasuksesshme, do të të duhet ta shkyçësh telefonin duke përdorur një llogari email-i.\n\n Provo sërish për <xliff:g id="NUMBER_2">%3$d</xliff:g> sekonda."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-sr/strings.xml b/packages/SystemUI/res-product/values-sr/strings.xml
index 0e6106e9d1ee..d43f0a3e382a 100644
--- a/packages/SystemUI/res-product/values-sr/strings.xml
+++ b/packages/SystemUI/res-product/values-sr/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"У таблету нема SIM картице."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"У телефону нема SIM картице."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"PIN кодови се не подударају"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Погрешно сте покушали да откључате таблет <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. Ако погрешно покушате још <xliff:g id="NUMBER_1">%2$d</xliff:g> пута, овај таблет ће се ресетовати, чиме се бришу сви подаци корисника."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Погрешно сте покушали да откључате телефон <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. Ако погрешно покушате још <xliff:g id="NUMBER_1">%2$d</xliff:g> пута, овај телефон ће се ресетовати, чиме се бришу сви подаци корисника."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Погрешно сте покушали да откључате таблет <xliff:g id="NUMBER">%d</xliff:g> пута. Овај таблет ће се ресетовати, чиме се бришу сви подаци."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Погрешно сте покушали да откључате телефон <xliff:g id="NUMBER">%d</xliff:g> пута. Овај телефон ће се ресетовати, чиме се бришу сви подаци."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Погрешно сте покушали да откључате таблет <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. Ако погрешно покушате још <xliff:g id="NUMBER_1">%2$d</xliff:g> пута, уклонићемо овог корисника, чиме се бришу сви подаци корисника."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Погрешно сте покушали да откључате телефон <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. Ако погрешно покушате још <xliff:g id="NUMBER_1">%2$d</xliff:g> пута, уклонићемо овог корисника, чиме се бришу сви подаци корисника."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Android TV ће се ускоро искључити. Притисните дугме да би остао укључен."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Уређај ће се ускоро искључити. Притисните да би остао укључен."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Погрешно сте покушали да откључате таблет <xliff:g id="NUMBER">%d</xliff:g> пута. Уклонићемо профил за Work, чиме се бришу сви подаци са профила."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Погрешно сте покушали да откључате телефон <xliff:g id="NUMBER">%d</xliff:g> пута. Уклонићемо профил за Work, чиме се бришу сви подаци са профила."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Нетачно сте нацртали шаблон за откључавање <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. Ако погрешно покушате још <xliff:g id="NUMBER_1">%2$d</xliff:g> пута, затражићемо да откључате таблет помоћу имејл налога.\n\n Пробајте поново за <xliff:g id="NUMBER_2">%3$d</xliff:g> сек."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Нетачно сте нацртали шаблон за откључавање <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. Ако погрешно покушате још <xliff:g id="NUMBER_1">%2$d</xliff:g> пута, затражићемо да откључате телефон помоћу имејл налога.\n\n Пробајте поново за <xliff:g id="NUMBER_2">%3$d</xliff:g> сек."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Поново поставите телефон ради бржег пуњења"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Поново поставите телефон ради бежичног пуњења"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Android TV ће се ускоро искључити. Притисните дугме да би остао укључен."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Уређај ће се ускоро искључити. Притисните да би остао укључен."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"У таблету нема SIM картице."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"У телефону нема SIM картице."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"PIN кодови се не подударају"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Погрешно сте покушали да откључате таблет <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. Ако погрешно покушате још <xliff:g id="NUMBER_1">%2$d</xliff:g> пута, овај таблет ће се ресетовати, чиме се бришу сви подаци корисника."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Погрешно сте покушали да откључате телефон <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. Ако погрешно покушате још <xliff:g id="NUMBER_1">%2$d</xliff:g> пута, овај телефон ће се ресетовати, чиме се бришу сви подаци корисника."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Погрешно сте покушали да откључате таблет <xliff:g id="NUMBER">%d</xliff:g> пута. Овај таблет ће се ресетовати, чиме се бришу сви подаци."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Погрешно сте покушали да откључате телефон <xliff:g id="NUMBER">%d</xliff:g> пута. Овај телефон ће се ресетовати, чиме се бришу сви подаци."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Погрешно сте покушали да откључате таблет <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. Ако погрешно покушате још <xliff:g id="NUMBER_1">%2$d</xliff:g> пута, уклонићемо овог корисника, чиме се бришу сви подаци корисника."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Погрешно сте покушали да откључате телефон <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. Ако погрешно покушате још <xliff:g id="NUMBER_1">%2$d</xliff:g> пута, уклонићемо овог корисника, чиме се бришу сви подаци корисника."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Погрешно сте покушали да откључате таблет <xliff:g id="NUMBER">%d</xliff:g> пута. Уклонићемо овог корисника, чиме се бришу сви подаци корисника."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Погрешно сте покушали да откључате телефон <xliff:g id="NUMBER">%d</xliff:g> пута. Уклонићемо овог корисника, чиме се бришу сви подаци корисника."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Погрешно сте покушали да откључате таблет <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. Ако погрешно покушате још <xliff:g id="NUMBER_1">%2$d</xliff:g> пута, уклонићемо профил за Work, чиме се бришу сви подаци са профила."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Погрешно сте покушали да откључате телефон <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. Ако погрешно покушате још <xliff:g id="NUMBER_1">%2$d</xliff:g> пута, уклонићемо профил за Work, чиме се бришу сви подаци са профила."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Погрешно сте покушали да откључате таблет <xliff:g id="NUMBER">%d</xliff:g> пута. Уклонићемо профил за Work, чиме се бришу сви подаци са профила."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Погрешно сте покушали да откључате телефон <xliff:g id="NUMBER">%d</xliff:g> пута. Уклонићемо профил за Work, чиме се бришу сви подаци са профила."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Нетачно сте нацртали шаблон за откључавање <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. Ако погрешно покушате још <xliff:g id="NUMBER_1">%2$d</xliff:g> пута, затражићемо да откључате таблет помоћу имејл налога.\n\n Пробајте поново за <xliff:g id="NUMBER_2">%3$d</xliff:g> сек."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Нетачно сте нацртали шаблон за откључавање <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. Ако погрешно покушате још <xliff:g id="NUMBER_1">%2$d</xliff:g> пута, затражићемо да откључате телефон помоћу имејл налога.\n\n Пробајте поново за <xliff:g id="NUMBER_2">%3$d</xliff:g> сек."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-sv/strings.xml b/packages/SystemUI/res-product/values-sv/strings.xml
index 05de9eb5d4a7..e52a0cc02731 100644
--- a/packages/SystemUI/res-product/values-sv/strings.xml
+++ b/packages/SystemUI/res-product/values-sv/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"Inget SIM-kort i surfplattan."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"Inget SIM-kort i mobilen."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"Pinkoderna stämmer inte överens"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Du har försökt låsa upp surfplattan på ett felaktigt sätt <xliff:g id="NUMBER_0">%1$d</xliff:g> gånger. Efter ytterligare <xliff:g id="NUMBER_1">%2$d</xliff:g> försök återställs surfplattan och all data raderas."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Du har försökt låsa upp mobilen på ett felaktigt sätt <xliff:g id="NUMBER_0">%1$d</xliff:g> gånger. Efter ytterligare <xliff:g id="NUMBER_1">%2$d</xliff:g> försök återställs mobilen och all data raderas."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Du har försökt låsa upp surfplattan på ett felaktigt sätt <xliff:g id="NUMBER">%d</xliff:g> gånger. Surfplattan återställs och all data raderas."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Du har försökt låsa upp mobilen på ett felaktigt sätt <xliff:g id="NUMBER">%d</xliff:g> gånger. Mobilen återställs och all data raderas."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Du har försökt låsa upp surfplattan på ett felaktigt sätt <xliff:g id="NUMBER_0">%1$d</xliff:g> gånger. Efter ytterligare <xliff:g id="NUMBER_1">%2$d</xliff:g> försök tas användaren bort och all användardata raderas."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Du har försökt låsa upp mobilen på ett felaktigt sätt <xliff:g id="NUMBER_0">%1$d</xliff:g> gånger. Efter ytterligare <xliff:g id="NUMBER_1">%2$d</xliff:g> försök tas användaren bort och all användardata raderas."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Android TV-enheten stängs snart av. Tryck på en knapp för att behålla den på."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Enheten stängs snart av. Tryck för att behålla den på."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Du har försökt låsa upp surfplattan på ett felaktigt sätt <xliff:g id="NUMBER">%d</xliff:g> gånger. Jobbprofilen tas bort och all profildata raderas."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Du har försökt låsa upp mobilen på ett felaktigt sätt <xliff:g id="NUMBER">%d</xliff:g> gånger. Jobbprofilen tas bort och all profildata raderas."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Du har ritat ditt grafiska lösenord fel <xliff:g id="NUMBER_0">%1$d</xliff:g> gånger. Efter ytterligare <xliff:g id="NUMBER_1">%2$d</xliff:g> försök måste du låsa upp surfplattan med hjälp av ett e-postkonto.\n\n Försök igen om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Du har ritat ditt grafiska lösenord fel <xliff:g id="NUMBER_0">%1$d</xliff:g> gånger. Efter ytterligare <xliff:g id="NUMBER_1">%2$d</xliff:g> försök måste du låsa upp mobilen med hjälp av ett e-postkonto.\n\n Försök igen om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Räta upp telefonen för att ladda snabbare"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Räta upp telefonen för att ladda trådlöst"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Android TV-enheten stängs snart av. Tryck på en knapp för att behålla den på."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Enheten stängs snart av. Tryck för att behålla den på."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Inget SIM-kort i surfplattan."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Inget SIM-kort i telefonen."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"Pinkoderna stämmer inte överens"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Du har försökt låsa upp surfplattan på ett felaktigt sätt <xliff:g id="NUMBER_0">%1$d</xliff:g> gånger. Efter ytterligare <xliff:g id="NUMBER_1">%2$d</xliff:g> försök återställs surfplattan och all data raderas."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Du har försökt låsa upp telefonen på ett felaktigt sätt <xliff:g id="NUMBER_0">%1$d</xliff:g> gånger. Efter ytterligare <xliff:g id="NUMBER_1">%2$d</xliff:g> försök återställs telefonen och all data raderas."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Du har försökt låsa upp surfplattan på ett felaktigt sätt <xliff:g id="NUMBER">%d</xliff:g> gånger. Surfplattan återställs och all data raderas."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Du har försökt låsa upp telefonen på ett felaktigt sätt <xliff:g id="NUMBER">%d</xliff:g> gånger. Telefonen återställs och all data raderas."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Du har försökt låsa upp surfplattan på ett felaktigt sätt <xliff:g id="NUMBER_0">%1$d</xliff:g> gånger. Efter ytterligare <xliff:g id="NUMBER_1">%2$d</xliff:g> försök tas användaren bort och all användardata raderas."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Du har försökt låsa upp telefonen på ett felaktigt sätt <xliff:g id="NUMBER_0">%1$d</xliff:g> gånger. Efter ytterligare <xliff:g id="NUMBER_1">%2$d</xliff:g> försök tas användaren bort och all användardata raderas."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Du har försökt låsa upp surfplattan på ett felaktigt sätt <xliff:g id="NUMBER">%d</xliff:g> gånger. Användaren tas bort och all användardata raderas."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Du har försökt låsa upp telefonen på ett felaktigt sätt <xliff:g id="NUMBER">%d</xliff:g> gånger. Användaren tas bort och all användardata raderas."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Du har försökt låsa upp surfplattan på ett felaktigt sätt <xliff:g id="NUMBER_0">%1$d</xliff:g> gånger. Efter ytterligare <xliff:g id="NUMBER_1">%2$d</xliff:g> försök tas jobbprofilen bort och all profildata raderas."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Du har försökt låsa upp telefonen på ett felaktigt sätt <xliff:g id="NUMBER_0">%1$d</xliff:g> gånger. Efter ytterligare <xliff:g id="NUMBER_1">%2$d</xliff:g> försök tas jobbprofilen bort och all profildata raderas."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Du har försökt låsa upp surfplattan på ett felaktigt sätt <xliff:g id="NUMBER">%d</xliff:g> gånger. Jobbprofilen tas bort och all profildata raderas."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Du har försökt låsa upp telefonen på ett felaktigt sätt <xliff:g id="NUMBER">%d</xliff:g> gånger. Jobbprofilen tas bort och all profildata raderas."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Du har ritat ditt grafiska lösenord fel <xliff:g id="NUMBER_0">%1$d</xliff:g> gånger. Efter ytterligare <xliff:g id="NUMBER_1">%2$d</xliff:g> försök måste du låsa upp surfplattan med hjälp av ett e-postkonto.\n\n Försök igen om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Du har ritat ditt grafiska lösenord fel <xliff:g id="NUMBER_0">%1$d</xliff:g> gånger. Efter ytterligare <xliff:g id="NUMBER_1">%2$d</xliff:g> försök måste du låsa upp telefonen med hjälp av ett e-postkonto.\n\n Försök igen om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-sw/strings.xml b/packages/SystemUI/res-product/values-sw/strings.xml
index 09eb0b2b34b2..c3cc758e82c9 100644
--- a/packages/SystemUI/res-product/values-sw/strings.xml
+++ b/packages/SystemUI/res-product/values-sw/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"Hakuna SIM kadi katika kompyuta kibao."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"Hakuna SIM kadi kwenye simu."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"Nambari za PIN hazifanani"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Umejaribu kufungua kompyuta kibao mara <xliff:g id="NUMBER_0">%1$d</xliff:g> bila mafanikio. Ukikosea mara nyingine <xliff:g id="NUMBER_1">%2$d</xliff:g>, kompyuta hii kibao itarejeshwa katika hali iliyotoka nayo kiwandani, hatua itakayofuta data yake yote."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Umejaribu kufungua simu mara <xliff:g id="NUMBER_0">%1$d</xliff:g> bila mafanikio. Ukikosea mara nyingine <xliff:g id="NUMBER_1">%2$d</xliff:g>, simu hii itarejeshwa katika hali iliyotoka nayo kiwandani, hatua itakayofuta data yake yote."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Umejaribu kufungua simu mara <xliff:g id="NUMBER">%d</xliff:g> bila mafanikio. Kompyuta hii kibao itarejeshwa katika hali iliyotoka nayo kiwandani, hatua itakayofuta data yake yote."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Umejaribu kufungua simu mara <xliff:g id="NUMBER">%d</xliff:g> bila mafanikio. Simu hii itarejeshwa katika hali iliyotoka nayo kiwandani, hatua itakayofuta data yake yote."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Umejaribu kufungua kompyuta kibao mara <xliff:g id="NUMBER_0">%1$d</xliff:g> bila mafanikio. Ukikosea mara nyingine <xliff:g id="NUMBER_1">%2$d</xliff:g>, mtumiaji huyu ataondolewa, hatua itakayofuta data yake yote."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Umejaribu kufungua simu mara <xliff:g id="NUMBER_0">%1$d</xliff:g> bila mafanikio. Ukikosea mara nyingine <xliff:g id="NUMBER_1">%2$d</xliff:g>, mtumiaji huyu ataondolewa, hatua itakayofuta data yake yote."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Kifaa cha Android TV kitazima hivi karibuni; bonyeza kitufe ili kisizime."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Kifaa kitazima hivi karibuni; bonyeza ili kisizime."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Umejaribu kufungua kompyuta kibao mara <xliff:g id="NUMBER">%d</xliff:g> bila mafanikio. Wasifu wa kazini utaondolewa, hatua itakayofuta data yote ya wasifu."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Umejaribu kufungua simu mara <xliff:g id="NUMBER">%d</xliff:g> bila mafanikio. Wasifu wa kazini utaondolewa, hatua itakayofuta data yote ya wasifu."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Umekosea kuchora mchoro wako wa kufungua mara <xliff:g id="NUMBER_0">%1$d</xliff:g>. Ukikosea mara nyingine <xliff:g id="NUMBER_1">%2$d</xliff:g>, utaombwa kufungua kompyuta yako kibao kwa kutumia akaunti yako ya barua pepe.\n\n Jaribu tena baada ya sekunde <xliff:g id="NUMBER_2">%3$d</xliff:g>."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Umekosea kuchora mchoro wako wa kufungua mara <xliff:g id="NUMBER_0">%1$d</xliff:g>. Ukikosea mara nyingine <xliff:g id="NUMBER_1">%2$d</xliff:g>, utaombwa kufungua simu yako kwa kutumia akaunti ya barua pepe.\n\n Jaribu tena baada ya sekunde <xliff:g id="NUMBER_2">%3$d</xliff:g>."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Pangilia tena simu ili ichaji kwa kasi"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Pangilia tena simu ili ichaji bila kutumia waya"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Kifaa cha Android TV kitazima hivi karibuni; bonyeza kitufe ili kisizime."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Kifaa kitazima hivi karibuni; bonyeza ili kisizime."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Hakuna SIM kadi katika kompyuta kibao."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Hakuna SIM kadi kwenye simu."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"Misimbo ya PIN haifanani"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Umejaribu kufungua kompyuta kibao mara <xliff:g id="NUMBER_0">%1$d</xliff:g> bila mafanikio. Ukikosea mara nyingine <xliff:g id="NUMBER_1">%2$d</xliff:g>, kompyuta hii kibao itarejeshwa katika hali iliyotoka nayo kiwandani, hatua itakayofuta data yake yote."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Umejaribu kufungua simu mara <xliff:g id="NUMBER_0">%1$d</xliff:g> bila mafanikio. Ukikosea mara nyingine <xliff:g id="NUMBER_1">%2$d</xliff:g>, simu hii itarejeshwa katika hali iliyotoka nayo kiwandani, hatua itakayofuta data yake yote."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Umejaribu kufungua simu mara <xliff:g id="NUMBER">%d</xliff:g> bila mafanikio. Kompyuta hii kibao itarejeshwa katika hali iliyotoka nayo kiwandani, hatua itakayofuta data yake yote."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Umejaribu kufungua simu mara <xliff:g id="NUMBER">%d</xliff:g> bila mafanikio. Simu hii itarejeshwa katika hali iliyotoka nayo kiwandani, hatua itakayofuta data yake yote."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Umejaribu kufungua kompyuta kibao mara <xliff:g id="NUMBER_0">%1$d</xliff:g> bila mafanikio. Ukikosea mara nyingine <xliff:g id="NUMBER_1">%2$d</xliff:g>, mtumiaji huyu ataondolewa, hatua itakayofuta data yote ya mtumiaji."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Umejaribu kufungua simu mara <xliff:g id="NUMBER_0">%1$d</xliff:g> bila mafanikio. Ukikosea mara nyingine <xliff:g id="NUMBER_1">%2$d</xliff:g>, mtumiaji huyu ataondolewa, hatua itakayofuta data yote ya mtumiaji."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Umejaribu kufungua kompyuta kibao mara <xliff:g id="NUMBER">%d</xliff:g> bila mafanikio. Mtumiaji huyu ataondolewa, hatua itakayofuta data yote ya mtumiaji."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Umejaribu kufungua simu mara <xliff:g id="NUMBER">%d</xliff:g> bila mafanikio. Mtumiaji huyu ataondolewa, hatua itakayofuta data yote ya mtumiaji."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Umejaribu kufungua kompyuta kibao mara <xliff:g id="NUMBER_0">%1$d</xliff:g> bila mafanikio. Ukikosea mara nyingine <xliff:g id="NUMBER_1">%2$d</xliff:g>, wasifu wa kazini utaondolewa, hatua itakayofuta data yote ya wasifu."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Umejaribu kufungua simu mara <xliff:g id="NUMBER_0">%1$d</xliff:g> bila mafanikio. Ukikosea mara nyingine <xliff:g id="NUMBER_1">%2$d</xliff:g>, wasifu wa kazini utaondolewa, hatua itakayofuta data yote ya wasifu."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Umejaribu kufungua kompyuta kibao mara <xliff:g id="NUMBER">%d</xliff:g> bila mafanikio. Wasifu wa kazini utaondolewa, hatua itakayofuta data yote ya wasifu."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Umejaribu kufungua simu mara <xliff:g id="NUMBER">%d</xliff:g> bila mafanikio. Wasifu wa kazini utaondolewa, hatua itakayofuta data yote ya wasifu."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Umeweka mchoro usio sahihi wa kufungua skrini mara <xliff:g id="NUMBER_0">%1$d</xliff:g>. Baada ya majaribio <xliff:g id="NUMBER_1">%2$d</xliff:g> zaidi bila mafanikio, utaombwa ufungue kompyuta yako kibao kwa kutumia akaunti ya barua pepe.\n\n Jaribu tena baada ya sekunde <xliff:g id="NUMBER_2">%3$d</xliff:g>."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Umeweka mchoro usio sahihi wa kufungua skrini mara <xliff:g id="NUMBER_0">%1$d</xliff:g>. Ukikosea mara nyingine <xliff:g id="NUMBER_1">%2$d</xliff:g>, utaombwa ufungue simu yako kwa kutumia akaunti ya barua pepe.\n\n Jaribu tena baada ya sekunde <xliff:g id="NUMBER_2">%3$d</xliff:g>."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-ta/strings.xml b/packages/SystemUI/res-product/values-ta/strings.xml
index 35e3f8255e93..7678e9f03b1a 100644
--- a/packages/SystemUI/res-product/values-ta/strings.xml
+++ b/packages/SystemUI/res-product/values-ta/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"டேப்லெட்டில் சிம் கார்டு இல்லை."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"மொபைலில் சிம் கார்டு இல்லை."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"பின் குறியீடுகள் பொருந்தவில்லை"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"டேப்லெட்டைத் திறக்க, <xliff:g id="NUMBER_0">%1$d</xliff:g> முறை தவறாக முயன்றுவிட்டீர்கள். இன்னும் <xliff:g id="NUMBER_1">%2$d</xliff:g> முறை தவறாக முயன்றால், இந்த டேப்லெட் மீட்டமைக்கப்பட்டு, அதன் எல்லாத் தரவும் நீக்கப்படும்."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"மொபைலைத் திறக்க, <xliff:g id="NUMBER_0">%1$d</xliff:g> முறை தவறாக முயன்றுவிட்டீர்கள். இன்னும் <xliff:g id="NUMBER_1">%2$d</xliff:g> முறை தவறாக முயன்றால், இந்த மொபைல் மீட்டமைக்கப்பட்டு, அதன் எல்லாத் தரவும் நீக்கப்படும்."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"டேப்லெட்டைத் திறக்க, <xliff:g id="NUMBER">%d</xliff:g> முறை தவறாக முயன்றுவிட்டீர்கள். இந்த டேப்லெட் மீட்டமைக்கப்பட்டு, அதன் எல்லாத் தரவும் நீக்கப்படும்."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"மொபைலைத் திறக்க, <xliff:g id="NUMBER">%d</xliff:g> முறை தவறாக முயன்றுவிட்டீர்கள். இந்த மொபைல் மீட்டமைக்கப்பட்டு, அதன் எல்லாத் தரவும் நீக்கப்படும்."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"டேப்லெட்டைத் திறக்க, <xliff:g id="NUMBER_0">%1$d</xliff:g> முறை தவறாக முயன்றுவிட்டீர்கள். இன்னும் <xliff:g id="NUMBER_1">%2$d</xliff:g> முறை தவறாக முயன்றால், இந்தப் பயனர் அகற்றப்பட்டு, எல்லாப் பயனர் தரவும் நீக்கப்படும்."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"மொபைலைத் திறக்க, <xliff:g id="NUMBER_0">%1$d</xliff:g> முறை தவறாக முயன்றுவிட்டீர்கள். இன்னும் <xliff:g id="NUMBER_1">%2$d</xliff:g> முறை தவறாக முயன்றால், இந்தப் பயனர் அகற்றப்பட்டு, எல்லாப் பயனர் தரவும் நீக்கப்படும்."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Android TV விரைவில் ஆஃப் ஆகலாம். இதைத் தொடர்ந்து ஆனில் வைக்க ஒரு பட்டனைத் தட்டவும்."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"இந்தச் சாதனம் விரைவில் ஆஃப் ஆகலாம், இதைத் தொடர்ந்து ஆனில் வைக்கத் தட்டவும்."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"டேப்லெட்டைத் திறக்க, <xliff:g id="NUMBER">%d</xliff:g> முறை தவறாக முயன்றுவிட்டீர்கள். பணிக் கணக்கு அகற்றப்பட்டு, எல்லாச் சுயவிவரத் தரவும் நீக்கப்படும்."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"மொபைலைத் திறக்க, <xliff:g id="NUMBER">%d</xliff:g> முறை தவறாக முயன்றுவிட்டீர்கள். பணிக் கணக்கு அகற்றப்பட்டு, எல்லாச் சுயவிவரத் தரவும் நீக்கப்படும்."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"திறப்பதற்கான பேட்டர்னை, <xliff:g id="NUMBER_0">%1$d</xliff:g> முறை தவறாக வரைந்துவிட்டீர்கள். இன்னும் <xliff:g id="NUMBER_1">%2$d</xliff:g> முறை தவறாக வரைந்தால், மின்னஞ்சல் கணக்கைப் பயன்படுத்தி டேப்லெட்டைத் திறக்கும்படி கேட்கப்படுவீர்கள்.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> வினாடிகளில் மீண்டும் முயலவும்."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"திறப்பதற்கான பேட்டர்னை, <xliff:g id="NUMBER_0">%1$d</xliff:g> முறை தவறாக வரைந்துவிட்டீர்கள். இன்னும் <xliff:g id="NUMBER_1">%2$d</xliff:g> முறை தவறாக வரைந்தால், மின்னஞ்சல் கணக்கைப் பயன்படுத்தி மொபைலைத் திறக்கும்படி கேட்கப்படுவீர்கள்.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> வினாடிகளில் மீண்டும் முயலவும்."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"வேகமாகச் சார்ஜ் செய்ய மொபைலை சரியாக வைக்கவும்"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"மொபைலை வயர்லெஸ்ஸாகச் சார்ஜ் செய்ய அதை சரியாக வைக்கவும்"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Android TV விரைவில் ஆஃப் ஆகும். இதைத் தொடர்ந்து ஆனில் வைக்க ஒரு பட்டனைத் தட்டவும்."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"இந்தச் சாதனம் விரைவில் ஆஃப் ஆகும். இதைத் தொடர்ந்து ஆனில் வைக்கத் தட்டவும்."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"டேப்லெட்டில் சிம் கார்டு இல்லை."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"மொபைலில் சிம் கார்டு இல்லை."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"பின் குறியீடுகள் பொருந்தவில்லை"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"டேப்லெட்டைத் திறக்க, <xliff:g id="NUMBER_0">%1$d</xliff:g> முறை தவறாக முயன்றுவிட்டீர்கள். இன்னும் <xliff:g id="NUMBER_1">%2$d</xliff:g> முறை தவறாக முயன்றால், இந்த டேப்லெட் மீட்டமைக்கப்படும். இதனால் அதிலுள்ள அனைத்துத் தரவும் நீக்கப்படும்."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"மொபைலைத் திறக்க <xliff:g id="NUMBER_0">%1$d</xliff:g> முறை தவறாக முயன்றுவிட்டீர்கள். இன்னும் <xliff:g id="NUMBER_1">%2$d</xliff:g> முறை தவறாக முயன்றால், இந்த மொபைல் மீட்டமைக்கப்படும். இதனால் அதிலுள்ள அனைத்துத் தரவும் நீக்கப்படும்."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"டேப்லெட்டைத் திறக்க <xliff:g id="NUMBER">%d</xliff:g> முறை தவறாக முயன்றுவிட்டீர்கள். இந்த டேப்லெட் மீட்டமைக்கப்படும் இதனால் அதிலுள்ள அனைத்துத் தரவும் நீக்கப்படும்."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"மொபைலைத் திறக்க, <xliff:g id="NUMBER">%d</xliff:g> முறை தவறாக முயன்றுவிட்டதனால் இந்த மொபைல் மீட்டமைக்கப்படும். இதனால் அதிலுள்ள அனைத்துத் தரவும் நீக்கப்படும்."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"டேப்லெட்டைத் திறக்க, <xliff:g id="NUMBER_0">%1$d</xliff:g> முறை தவறாக முயன்றுவிட்டீர்கள். இன்னும் <xliff:g id="NUMBER_1">%2$d</xliff:g> முறை தவறாக முயன்றால், இந்தப் பயனர் அகற்றப்படும். இதனால் அதிலுள்ள அனைத்துப் பயனர் தரவும் நீக்கப்படும்."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"மொபைலைத் திறக்க <xliff:g id="NUMBER_0">%1$d</xliff:g> முறை தவறாக முயன்றுவிட்டீர்கள். இன்னும் <xliff:g id="NUMBER_1">%2$d</xliff:g> முறை தவறாக முயன்றால், இந்தப் பயனர் அகற்றப்படும். இதனால் அதிலுள்ள அனைத்துப் பயனர் தரவும் நீக்கப்படும்."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"டேப்லெட்டைத் திறக்க, <xliff:g id="NUMBER">%d</xliff:g> முறை தவறாக முயன்றுவிட்டீர்கள். இந்தப் பயனர் அகற்றப்படும் இதனால் அதிலுள்ள அனைத்துப் பயனர் தரவும் நீக்கப்படும்."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"மொபைலைத் திறக்க <xliff:g id="NUMBER">%d</xliff:g> முறை தவறாக முயன்றுவிட்டதனால் இந்தப் பயனர் அகற்றப்படும். இதனால் அதிலுள்ள அனைத்துப் பயனர் தரவும் நீக்கப்படும்."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"டேப்லெட்டைத் திறக்க, <xliff:g id="NUMBER_0">%1$d</xliff:g> முறை தவறாக முயன்றுவிட்டீர்கள். இன்னும் <xliff:g id="NUMBER_1">%2$d</xliff:g> முறை தவறாக முயன்றால், பணிக் கணக்கு அகற்றப்படும். இதனால் அதிலுள்ள அனைத்து சுயவிவரத் தரவும் நீக்கப்படும்."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"மொபைலைத் திறக்க, <xliff:g id="NUMBER_0">%1$d</xliff:g> முறை தவறாக முயன்றுவிட்டீர்கள். இன்னும் <xliff:g id="NUMBER_1">%2$d</xliff:g> முறை தவறாக முயன்றால், பணிக் கணக்கு அகற்றப்படும். இதனால் அதிலுள்ள அனைத்துச் சுயவிவரத் தரவும் நீக்கப்படும்."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"டேப்லெட்டைத் திறக்க <xliff:g id="NUMBER">%d</xliff:g> முறை தவறாக முயன்றுவிட்டதனால் பணிக் கணக்கு அகற்றப்படும். இதனால் அதிலுள்ள அனைத்துச் சுயவிவரத் தரவும் நீக்கப்படும்."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"மொபைலைத் திறக்க, <xliff:g id="NUMBER">%d</xliff:g> முறை தவறாக முயன்றுவிட்டதனால் பணிக் கணக்கு அகற்றப்படும். இதனால் அதிலுள்ள அனைத்துச் சுயவிவரத் தரவும் நீக்கப்படும்."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"திறப்பதற்கான பேட்டர்னை, <xliff:g id="NUMBER_0">%1$d</xliff:g> முறை தவறாக வரைந்துவிட்டீர்கள். இன்னும் <xliff:g id="NUMBER_1">%2$d</xliff:g> முறை தவறாக வரைந்தால், மின்னஞ்சல் கணக்கைப் பயன்படுத்தி டேப்லெட்டைத் திறக்கும்படி கேட்கப்படுவீர்கள்.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> வினாடிகளில் மீண்டும் முயலவும்."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"திறப்பதற்கான பேட்டர்னை, <xliff:g id="NUMBER_0">%1$d</xliff:g> முறை தவறாக வரைந்துவிட்டீர்கள். இன்னும் <xliff:g id="NUMBER_1">%2$d</xliff:g> முறை தவறாக வரைந்தால், மின்னஞ்சல் கணக்கைப் பயன்படுத்தி மொபைலைத் திறக்கும்படி கேட்கப்படுவீர்கள்.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> வினாடிகளில் மீண்டும் முயலவும்."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-te/strings.xml b/packages/SystemUI/res-product/values-te/strings.xml
index 6f172eee730f..8e7b11f41677 100644
--- a/packages/SystemUI/res-product/values-te/strings.xml
+++ b/packages/SystemUI/res-product/values-te/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"టాబ్లెట్‌లో SIM కార్డ్ లేదు."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"ఫోన్‌లో SIM కార్డ్ లేదు."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"పిన్ కోడ్‌లు సరిపోలలేదు"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"మీరు టాబ్లెట్‌ను అన్‌లాక్ చేయడానికి <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు చెల్లని ప్రయత్నాలు చేసారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> విఫల ప్రయత్నాల తర్వాత, ఈ టాబ్లెట్ రీసెట్ చేయబడుతుంది, తద్వారా ఇందులోని మొత్తం డేటా తొలగించబడుతుంది."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"మీరు ఫోన్‌ను అన్‌లాక్ చేయడానికి <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు చెల్లని ప్రయత్నాలు చేసారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> విఫల ప్రయత్నాల తర్వాత, ఈ ఫోన్ రీసెట్ చేయబడుతుంది, తద్వారా ఇందులోని మొత్తం డేటా తొలగించబడుతుంది."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"మీరు టాబ్లెట్‌ను అన్‌లాక్ చేయడానికి <xliff:g id="NUMBER">%d</xliff:g> సార్లు చెల్లని ప్రయత్నాలు చేసారు. ఈ టాబ్లెట్ రీసెట్ చేయబడుతుంది, తద్వారా ఇందులోని మొత్తం డేటా తొలగించబడుతుంది."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"మీరు ఫోన్‌ను అన్‌లాక్ చేయడానికి <xliff:g id="NUMBER">%d</xliff:g> సార్లు చెల్లని ప్రయత్నాలు చేసారు. ఈ ఫోన్ రీసెట్ చేయబడుతుంది, తద్వారా ఇందులోని మొత్తం డేటా తొలగించబడుతుంది."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"మీరు టాబ్లెట్‌ను అన్‌లాక్ చేయడానికి <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు చెల్లని ప్రయత్నాలు చేసారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> విఫల ప్రయత్నాల తర్వాత, ఈ వినియోగదారు తీసివేయబడతారు, తద్వారా వినియోగదారు డేటా మొత్తం తొలగించబడుతుంది."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"మీరు ఫోన్‌ని అన్‌లాక్ చేయడానికి <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు చెల్లని ప్రయత్నాలు చేసారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> విఫల ప్రయత్నాల తర్వాత, ఈ వినియోగదారు తీసివేయబడతారు, తద్వారా వినియోగదారు డేటా మొత్తం తొలగించబడుతుంది."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Android TV పరికరం త్వరలో ఆఫ్ అయిపోతుంది; దాన్ని ఆన్‌లో ఉంచడానికి బటన్‌ను నొక్కండి."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"పరికరం త్వరలో ఆఫ్ అయిపోతుంది; దీన్ని ఆన్‌లో ఉంచడానికి నొక్కండి."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"మీరు టాబ్లెట్‌ను అన్‌లాక్ చేయడానికి <xliff:g id="NUMBER">%d</xliff:g> సార్లు చెల్లని ప్రయత్నాలు చేసారు. కార్యాలయ ప్రొఫైల్ తీసివేయబడుతుంది, తద్వారా ప్రొఫైల్ డేటా మొత్తం తొలగించబడుతుంది."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"మీరు ఫోన్‌ని అన్‌లాక్ చేయడానికి <xliff:g id="NUMBER">%d</xliff:g> సార్లు చెల్లని ప్రయత్నాలు చేసారు. కార్యాలయ ప్రొఫైల్ తీసివేయబడుతుంది, తద్వారా ప్రొఫైల్ డేటా మొత్తం తొలగించబడుతుంది."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"మీరు మీ అన్‌లాక్ నమూనాను <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా గీసారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> విఫల ప్రయత్నాల తర్వాత, మీరు ఇమెయిల్ ఖాతాను ఉపయోగించి మీ టాబ్లెట్‌ను అన్‌లాక్ చేయాల్సి వస్తుంది.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"మీరు మీ అన్‌లాక్ నమూనాను <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా గీసారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> విఫల ప్రయత్నాల తర్వాత, మీరు ఇమెయిల్ ఖాతాను ఉపయోగించి మీ ఫోన్‌ను అన్‌లాక్ చేయాల్సి వస్తుంది.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"మరింత ఫాస్ట్ ఛార్జింగ్ కోసం ఫోన్‌ను సరిగ్గా అమర్చండి"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"వైర్‌లెస్‌లో ఛార్జ్ కావడానికి ఫోన్‌ను సరిగ్గా అమర్చండి"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Android TV పరికరం త్వరలో ఆఫ్ అయిపోతుంది; దీన్ని ఆన్‌లో ఉంచడానికి బటన్‌ను నొక్కండి."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"పరికరం త్వరలో ఆఫ్ అయిపోతుంది; దీన్ని ఆన్‌లో ఉంచడానికి నొక్కండి."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"టాబ్లెట్‌లో SIM కార్డ్ లేదు."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"ఫోన్‌లో SIM కార్డ్ లేదు."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"పిన్ కోడ్‌లు సరిపోలలేదు"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"మీరు టాబ్లెట్‌ను అన్‌లాక్ చేయడానికి <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పు ప్రయత్నాలు చేశారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> ప్రయత్నాలలో విఫలమైతే, ఈ టాబ్లెట్ రీసెట్ చేయబడుతుంది, దీని వలన ఇందులోని మొత్తం డేటా తొలగించబడుతుంది."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"మీరు ఫోన్‌ను అన్‌లాక్ చేయడానికి <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా ప్రయత్నించారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> ప్రయత్నాలలో విఫలమైతే, ఈ ఫోన్ రీసెట్ చేయబడుతుంది, దీని వలన ఇందులోని మొత్తం డేటా తొలగించబడుతుంది."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"మీరు టాబ్లెట్‌ను అన్‌లాక్ చేయడానికి <xliff:g id="NUMBER">%d</xliff:g> సార్లు తప్పు ప్రయత్నాలు చేశారు. ఈ టాబ్లెట్ రీసెట్ చేయబడుతుంది, దీని వలన ఇందులోని మొత్తం డేటా తొలగించబడుతుంది."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"మీరు ఫోన్‌ను అన్‌లాక్ చేయడానికి <xliff:g id="NUMBER">%d</xliff:g> సార్లు తప్పు ప్రయత్నాలు చేశారు. ఈ ఫోన్ రీసెట్ చేయబడుతుంది, దీని వలన ఇందులోని మొత్తం డేటా తొలగించబడుతుంది."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"మీరు టాబ్లెట్‌ను అన్‌లాక్ చేయడానికి <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పు ప్రయత్నాలు చేశారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> ప్రయత్నాలలో విఫలమైతే, ఈ వినియోగదారు తీసివేయబడతారు, దీని వలన వినియోగదారు డేటా మొత్తం తొలగించబడుతుంది."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"మీరు ఫోన్‌ను అన్‌లాక్ చేయడానికి <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పు ప్రయత్నాలు చేశారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> ప్రయత్నాలలో విఫలమైతే, ఈ వినియోగదారు తీసివేయబడతారు. దీని వలన వినియోగదారు డేటా మొత్తం తొలగించబడుతుంది."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"మీరు టాబ్లెట్‌ను అన్‌లాక్ చేయడానికి <xliff:g id="NUMBER">%d</xliff:g> సార్లు తప్పు ప్రయత్నాలు చేశారు. ఈ వినియోగదారు తీసివేయబడతారు, దీని వలన వినియోగదారు డేటా మొత్తం తొలగించబడుతుంది."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"మీరు ఫోన్‌ను అన్‌లాక్ చేయడానికి <xliff:g id="NUMBER">%d</xliff:g> సార్లు తప్పు ప్రయత్నాలు చేశారు. ఈ వినియోగదారు తీసివేయబడతారు, దీని వలన వినియోగదారు డేటా మొత్తం తొలగించబడుతుంది."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"మీరు టాబ్లెట్‌ను అన్‌లాక్ చేయడానికి <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పు ప్రయత్నాలు చేశారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> ప్రయత్నాలలో విఫలమైతే, కార్యాలయ ప్రొఫైల్ తీసివేయబడుతుంది, దీని వలన ప్రొఫైల్ డేటా మొత్తం తొలగించబడుతుంది."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"మీరు ఫోన్‌ను అన్‌లాక్ చేయడానికి <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పు ప్రయత్నాలు చేశారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> ప్రయత్నాలలో విఫలమైతే, కార్యాలయ ప్రొఫైల్ తీసివేయబడుతుంది, దీని వలన ప్రొఫైల్ డేటా మొత్తం తొలగించబడుతుంది."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"మీరు టాబ్లెట్‌ను అన్‌లాక్ చేయడానికి <xliff:g id="NUMBER">%d</xliff:g> సార్లు తప్పు ప్రయత్నాలు చేశారు. కార్యాలయ ప్రొఫైల్ తీసివేయబడుతుంది, దీని వలన ప్రొఫైల్ డేటా మొత్తం తొలగించబడుతుంది."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"మీరు ఫోన్‌ను అన్‌లాక్ చేయడానికి <xliff:g id="NUMBER">%d</xliff:g> సార్లు తప్పు ప్రయత్నాలు చేశారు. కార్యాలయ ప్రొఫైల్ తీసివేయబడుతుంది, దీని వలన ప్రొఫైల్ డేటా మొత్తం తొలగించబడుతుంది."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"మీరు మీ అన్‌లాక్ నమూనాను <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా గీసారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> ప్రయత్నాలలో విఫలమైతే, మీరు ఇమెయిల్ ఖాతాను ఉపయోగించి మీ టాబ్లెట్‌ను అన్‌లాక్ చేయాల్సి వస్తుంది.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"మీరు మీ అన్‌లాక్ నమూనాను <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా గీసారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> ప్రయత్నాలలో విఫలమైతే, మీరు ఇమెయిల్ ఖాతాను ఉపయోగించి మీ ఫోన్‌ను అన్‌లాక్ చేయాల్సి వస్తుంది.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-th/strings.xml b/packages/SystemUI/res-product/values-th/strings.xml
index 8c9e72a8fffd..b9f44cd69868 100644
--- a/packages/SystemUI/res-product/values-th/strings.xml
+++ b/packages/SystemUI/res-product/values-th/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"ไม่มีซิมการ์ดในแท็บเล็ต"</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"ไม่มีซิมการ์ดในโทรศัพท์"</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"รหัส PIN ไม่ตรง"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"คุณปลดล็อกแท็บเล็ตไม่ถูกต้อง <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้ง หากพยายามไม่สำเร็จอีก <xliff:g id="NUMBER_1">%2$d</xliff:g> ครั้ง ระบบจะรีเซ็ตแท็บเล็ตเครื่องนี้ ซึ่งจะเป็นการลบข้อมูลทั้งหมดในเครื่อง"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"คุณปลดล็อกโทรศัพท์ไม่ถูกต้อง <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้ง หากพยายามไม่สำเร็จอีก <xliff:g id="NUMBER_1">%2$d</xliff:g> ครั้ง ระบบจะรีเซ็ตโทรศัพท์เครื่องนี้ ซึ่งจะเป็นการลบข้อมูลทั้งหมดในเครื่อง"</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"คุณปลดล็อกแท็บเล็ตไม่ถูกต้อง <xliff:g id="NUMBER">%d</xliff:g> ครั้ง ระบบจะรีเซ็ตแท็บเล็ตเครื่องนี้ ซึ่งจะเป็นการลบข้อมูลทั้งหมดในเครื่อง"</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"คุณปลดล็อกโทรศัพท์ไม่ถูกต้อง <xliff:g id="NUMBER">%d</xliff:g> ครั้ง ระบบจะรีเซ็ตโทรศัพท์เครื่องนี้ ซึ่งจะเป็นการลบข้อมูลทั้งหมดในเครื่อง"</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"คุณปลดล็อกแท็บเล็ตไม่ถูกต้อง <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้ง หากพยายามไม่สำเร็จอีก <xliff:g id="NUMBER_1">%2$d</xliff:g> ครั้ง ระบบจะนำผู้ใช้รายนี้ออก ซึ่งจะเป็นการลบข้อมูลทั้งหมดของผู้ใช้"</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"คุณปลดล็อกโทรศัพท์ไม่ถูกต้อง <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้ง หากพยายามไม่สำเร็จอีก <xliff:g id="NUMBER_1">%2$d</xliff:g> ครั้ง ระบบจะนำผู้ใช้รายนี้ออก ซึ่งจะเป็นการลบข้อมูลทั้งหมดของผู้ใช้"</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"อุปกรณ์ Android TV จะปิดเครื่องในอีกไม่ช้า กดปุ่มเพื่อเปิดอุปกรณ์ต่อไป"</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"อุปกรณ์จะปิดเครื่องในอีกไม่ช้า กดเพื่อเปิดอุปกรณ์ต่อไป"</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"คุณปลดล็อกแท็บเล็ตไม่ถูกต้อง <xliff:g id="NUMBER">%d</xliff:g> ครั้ง ระบบจะนำโปรไฟล์งานออก ซึ่งจะเป็นการลบข้อมูลโปรไฟล์ทั้งหมด"</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"คุณปลดล็อกโทรศัพท์ไม่ถูกต้อง <xliff:g id="NUMBER">%d</xliff:g> ครั้ง ระบบจะนำโปรไฟล์งานออก ซึ่งจะเป็นการลบข้อมูลโปรไฟล์ทั้งหมด"</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"คุณวาดรูปแบบการปลดล็อกไม่ถูกต้อง <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้ง หากพยายามไม่สำเร็จอีก <xliff:g id="NUMBER_1">%2$d</xliff:g> ครั้ง ระบบจะขอให้คุณปลดล็อกแท็บเล็ตโดยใช้บัญชีอีเมล\n\n โปรดลองอีกครั้งในอีก <xliff:g id="NUMBER_2">%3$d</xliff:g> วินาที"</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"คุณวาดรูปแบบการปลดล็อกไม่ถูกต้อง <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้ง หากพยายามไม่สำเร็จอีก <xliff:g id="NUMBER_1">%2$d</xliff:g> ครั้ง ระบบจะขอให้คุณปลดล็อกโทรศัพท์โดยใช้บัญชีอีเมล\n\n โปรดลองอีกครั้งในอีก <xliff:g id="NUMBER_2">%3$d</xliff:g> วินาที"</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"จัดวางโทรศัพท์ใหม่เพื่อให้ชาร์จได้เร็วขึ้น"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"จัดวางโทรศัพท์ใหม่เพื่อชาร์จแบบไร้สาย"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"อุปกรณ์ Android TV จะปิดเครื่องในอีกไม่ช้า กดปุ่มเพื่อเปิดอุปกรณ์ต่อไป"</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"อุปกรณ์จะปิดเครื่องในอีกไม่ช้า กดเพื่อเปิดอุปกรณ์ต่อไป"</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"ไม่มีซิมการ์ดในแท็บเล็ต"</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"ไม่มีซิมการ์ดในโทรศัพท์"</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"รหัส PIN ไม่ตรง"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"คุณปลดล็อกแท็บเล็ตไม่ถูกต้อง <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้งแล้ว หากทำไม่สำเร็จอีก <xliff:g id="NUMBER_1">%2$d</xliff:g> ครั้ง ระบบจะรีเซ็ตแท็บเล็ตเครื่องนี้ ซึ่งจะเป็นการลบข้อมูลทั้งหมดในเครื่อง"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"คุณปลดล็อกโทรศัพท์ไม่ถูกต้อง <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้งแล้ว หากทำไม่สำเร็จอีก <xliff:g id="NUMBER_1">%2$d</xliff:g> ครั้ง ระบบจะรีเซ็ตโทรศัพท์เครื่องนี้ ซึ่งจะเป็นการลบข้อมูลทั้งหมดในเครื่อง"</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"คุณปลดล็อกแท็บเล็ตไม่ถูกต้อง <xliff:g id="NUMBER">%d</xliff:g> ครั้งแล้ว ระบบจะรีเซ็ตแท็บเล็ตเครื่องนี้ ซึ่งจะเป็นการลบข้อมูลทั้งหมดในเครื่อง"</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"คุณปลดล็อกโทรศัพท์ไม่ถูกต้อง <xliff:g id="NUMBER">%d</xliff:g> ครั้งแล้ว ระบบจะรีเซ็ตโทรศัพท์เครื่องนี้ ซึ่งจะเป็นการลบข้อมูลทั้งหมดในเครื่อง"</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"คุณปลดล็อกแท็บเล็ตไม่ถูกต้อง <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้งแล้ว หากทำไม่สำเร็จอีก <xliff:g id="NUMBER_1">%2$d</xliff:g> ครั้ง ระบบจะนำผู้ใช้รายนี้ออก ซึ่งจะเป็นการลบข้อมูลทั้งหมดของผู้ใช้"</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"คุณปลดล็อกโทรศัพท์ไม่ถูกต้อง <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้งแล้ว หากทำไม่สำเร็จอีก <xliff:g id="NUMBER_1">%2$d</xliff:g> ครั้ง ระบบจะนำผู้ใช้รายนี้ออก ซึ่งจะเป็นการลบข้อมูลทั้งหมดของผู้ใช้"</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"คุณปลดล็อกแท็บเล็ตไม่ถูกต้อง <xliff:g id="NUMBER">%d</xliff:g> ครั้งแล้ว ระบบจะนำผู้ใช้รายนี้ออก ซึ่งจะเป็นการลบข้อมูลทั้งหมดของผู้ใช้"</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"คุณปลดล็อกโทรศัพท์ไม่ถูกต้อง <xliff:g id="NUMBER">%d</xliff:g> ครั้งแล้ว ระบบจะนำผู้ใช้รายนี้ออก ซึ่งจะเป็นการลบข้อมูลทั้งหมดของผู้ใช้"</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"คุณปลดล็อกแท็บเล็ตไม่ถูกต้อง <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้งแล้ว หากทำไม่สำเร็จอีก <xliff:g id="NUMBER_1">%2$d</xliff:g> ครั้ง ระบบจะนำโปรไฟล์งานออก ซึ่งจะเป็นการลบข้อมูลทั้งหมดในโปรไฟล์"</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"คุณปลดล็อกโทรศัพท์ไม่ถูกต้อง <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้งแล้ว หากทำไม่สำเร็จอีก <xliff:g id="NUMBER_1">%2$d</xliff:g> ครั้ง ระบบจะนำโปรไฟล์งานออก ซึ่งจะเป็นการลบข้อมูลทั้งหมดในโปรไฟล์"</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"คุณปลดล็อกแท็บเล็ตไม่ถูกต้อง <xliff:g id="NUMBER">%d</xliff:g> ครั้งแล้ว ระบบจะนำโปรไฟล์งานออก ซึ่งจะเป็นการลบข้อมูลทั้งหมดในโปรไฟล์"</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"คุณปลดล็อกโทรศัพท์ไม่ถูกต้อง <xliff:g id="NUMBER">%d</xliff:g> ครั้งแล้ว ระบบจะนำโปรไฟล์งานออก ซึ่งจะเป็นการลบข้อมูลทั้งหมดในโปรไฟล์"</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"คุณวาดรูปแบบการปลดล็อกไม่ถูกต้อง <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้งแล้ว หากทำไม่สำเร็จอีก <xliff:g id="NUMBER_1">%2$d</xliff:g> ครั้ง ระบบจะขอให้คุณปลดล็อกแท็บเล็ตโดยใช้บัญชีอีเมล\n\n โปรดลองอีกครั้งใน <xliff:g id="NUMBER_2">%3$d</xliff:g> วินาที"</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"คุณวาดรูปแบบการปลดล็อกไม่ถูกต้อง <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้งแล้ว หากทำไม่สำเร็จอีก <xliff:g id="NUMBER_1">%2$d</xliff:g> ครั้ง ระบบจะขอให้คุณปลดล็อกโทรศัพท์โดยใช้บัญชีอีเมล\n\n โปรดลองอีกครั้งในอีก <xliff:g id="NUMBER_2">%3$d</xliff:g> วินาที"</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-tl/strings.xml b/packages/SystemUI/res-product/values-tl/strings.xml
index d3901ee29d7a..4a291c1b6716 100644
--- a/packages/SystemUI/res-product/values-tl/strings.xml
+++ b/packages/SystemUI/res-product/values-tl/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"Walang SIM card sa tablet."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"Walang SIM card sa telepono."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"Hindi nagtutugma ang mga PIN code"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"<xliff:g id="NUMBER_0">%1$d</xliff:g> (na) beses mo nang sinubukang i-unlock ang tablet gamit ang maling password. Pagkatapos ng <xliff:g id="NUMBER_1">%2$d</xliff:g> pang hindi matagumpay na pagsubok, ire-reset ang tablet na ito, na magiging dahilan upang ma-delete ang lahat ng data nito."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"<xliff:g id="NUMBER_0">%1$d</xliff:g> (na) beses mo nang sinubukang i-unlock ang telepono gamit ang maling password. Pagkatapos ng <xliff:g id="NUMBER_1">%2$d</xliff:g> pang hindi matagumpay na pagsubok, ire-reset ang teleponong ito, na magiging dahilan upang ma-delete ang lahat ng data nito."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"<xliff:g id="NUMBER">%d</xliff:g> (na) beses mo nang sinubukang i-unlock ang tablet gamit ang maling password. Ire-reset ang tablet na ito, na magiging dahilan upang ma-delete ang lahat ng data nito."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"<xliff:g id="NUMBER">%d</xliff:g> (na) beses mo nang sinubukang i-unlock ang telepono gamit ang maling password. Ire-reset ang teleponong ito, na magiging dahilan upang ma-delete ang lahat ng data nito."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"<xliff:g id="NUMBER_0">%1$d</xliff:g> (na) beses mo nang sinubukang i-unlock ang tablet gamit ang maling password. Pagkatapos ng <xliff:g id="NUMBER_1">%2$d</xliff:g> pang hindi matagumpay na pagsubok, aalisin ang user na ito, na magiging dahilan upang ma-delete ang lahat ng data ng user."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"<xliff:g id="NUMBER_0">%1$d</xliff:g> (na) beses mo nang sinubukang i-unlock ang telepono gamit ang maling password. Pagkatapos ng <xliff:g id="NUMBER_1">%2$d</xliff:g> pang hindi matagumpay na pagsubok, aalisin ang user na ito, na magiging dahilan upang ma-delete ang lahat ng data ng user."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Mao-off na ang Android TV device; pumindot ng button para panatilihin itong naka-on."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Mao-off na ang device; pumindot para panatilihin itong naka-on."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"<xliff:g id="NUMBER">%d</xliff:g> (na) beses mo nang sinubukang i-unlock ang tablet gamit ang maling password. Aalisin ang profile sa trabaho, na magiging dahilan upang ma-delete ang lahat ng data sa profile."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"<xliff:g id="NUMBER">%d</xliff:g> (na) beses mo nang sinubukang i-unlock ang telepono gamit ang maling password. Aalisin ang profile sa trabaho, na magiging dahilan upang ma-delete ang lahat ng data sa profile."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Naguhit mo nang hindi tama ang iyong pattern sa pag-unlock nang <xliff:g id="NUMBER_0">%1$d</xliff:g> (na) beses. Pagkatapos ng <xliff:g id="NUMBER_1">%2$d</xliff:g> pang hindi matagumpay na pagsubok, hihilingin sa iyong i-unlock ang tablet mo gamit ang isang email account.\n\n Subukang muli sa loob ng <xliff:g id="NUMBER_2">%3$d</xliff:g> (na) segundo."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Naguhit mo nang hindi tama ang iyong pattern sa pag-unlock nang <xliff:g id="NUMBER_0">%1$d</xliff:g> (na) beses. Pagkatapos ng <xliff:g id="NUMBER_1">%2$d</xliff:g> pang hindi matagumpay na pagsubok, hihilingin sa iyong i-unlock ang telepono mo gamit ang isang email account.\n\n Subukang muli sa loob ng <xliff:g id="NUMBER_2">%3$d</xliff:g> (na) segundo."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"I-align ulit ang telepono para sa mas mabilis na pag-charge"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"I-align ulit ang telepono para i-charge nang wireless"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Mag-o-off na ang Android TV device; pumindot ng button para panatilihin itong naka-on."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Mag-o-off na ang device; pumindot para panatilihin itong naka-on."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Walang SIM card sa tablet."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Walang SIM card sa telepono."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"Hindi nagtutugma ang mga PIN code"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"<xliff:g id="NUMBER_0">%1$d</xliff:g> (na) beses mo nang sinubukang i-unlock ang tablet gamit ang maling password. Pagkatapos ng <xliff:g id="NUMBER_1">%2$d</xliff:g> pang hindi matagumpay na pagsubok, ire-reset ang tablet na ito, na magiging dahilan para ma-delete ang lahat ng data nito."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"<xliff:g id="NUMBER_0">%1$d</xliff:g> (na) beses mo nang sinubukang i-unlock ang telepono gamit ang maling password. Pagkatapos ng <xliff:g id="NUMBER_1">%2$d</xliff:g> pang hindi matagumpay na pagsubok, ire-reset ang teleponong ito, na magiging dahilan para ma-delete ang lahat ng data nito."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"<xliff:g id="NUMBER">%d</xliff:g> (na) beses mo nang sinubukang i-unlock ang tablet gamit ang maling password. Ire-reset ang tablet na ito, na magiging dahilan para ma-delete ang lahat ng data nito."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"<xliff:g id="NUMBER">%d</xliff:g> (na) beses mo nang sinubukang i-unlock ang telepono gamit ang maling password. Ire-reset ang teleponong ito, na magiging dahilan para ma-delete ang lahat ng data nito."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"<xliff:g id="NUMBER_0">%1$d</xliff:g> (na) beses mo nang sinubukang i-unlock ang tablet gamit ang maling password. Pagkatapos ng <xliff:g id="NUMBER_1">%2$d</xliff:g> pang hindi matagumpay na pagsubok, aalisin ang user na ito, na magiging dahilan para ma-delete ang lahat ng data ng user."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"<xliff:g id="NUMBER_0">%1$d</xliff:g> (na) beses mo nang sinubukang i-unlock ang telepono gamit ang maling password. Pagkatapos ng <xliff:g id="NUMBER_1">%2$d</xliff:g> pang hindi matagumpay na pagsubok, aalisin ang user na ito, na magiging dahilan para ma-delete ang lahat ng data ng user."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"<xliff:g id="NUMBER">%d</xliff:g> (na) beses mo nang sinubukang i-unlock ang tablet gamit ang maling password. Aalisin ang user na ito, na magiging dahilan para ma-delete ang lahat ng data ng user."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"<xliff:g id="NUMBER">%d</xliff:g> (na) beses mo nang sinubukang i-unlock ang telepono gamit ang maling password. Aalisin ang user na ito, na magiging dahilan para ma-delete ang lahat ng data ng user."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"<xliff:g id="NUMBER_0">%1$d</xliff:g> (na) beses mo nang sinubukang i-unlock ang tablet gamit ang maling password. Pagkatapos ng <xliff:g id="NUMBER_1">%2$d</xliff:g> pang hindi matagumpay na pagsubok, aalisin ang profile sa trabaho, na magiging dahilan para ma-delete ang lahat ng data sa profile."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"<xliff:g id="NUMBER_0">%1$d</xliff:g> (na) beses mo nang sinubukang i-unlock ang telepono gamit ang maling password. Pagkatapos ng <xliff:g id="NUMBER_1">%2$d</xliff:g> pang hindi matagumpay na pagsubok, aalisin ang profile sa trabaho, na magiging dahilan para ma-delete ang lahat ng data sa profile."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"<xliff:g id="NUMBER">%d</xliff:g> (na) beses mo nang sinubukang i-unlock ang tablet gamit ang maling password. Aalisin ang profile sa trabaho, na magiging dahilan para ma-delete ang lahat ng data sa profile."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"<xliff:g id="NUMBER">%d</xliff:g> (na) beses mo nang sinubukang i-unlock ang telepono gamit ang maling password. Aalisin ang profile sa trabaho, na magiging dahilan para ma-delete ang lahat ng data sa profile."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"<xliff:g id="NUMBER_0">%1$d</xliff:g> (na) beses kang nagkamali sa pagguhit ng iyong pattern sa pag-unlock. Pagkatapos ng <xliff:g id="NUMBER_1">%2$d</xliff:g> pang hindi matagumpay na pagsubok, hihilingin sa iyong i-unlock ang tablet mo gamit ang isang email account.\n\n Subukan ulit sa loob ng <xliff:g id="NUMBER_2">%3$d</xliff:g> (na) segundo."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"<xliff:g id="NUMBER_0">%1$d</xliff:g> (na) beses kang nagkamali sa pagguhit ng iyong pattern sa pag-unlock. Pagkatapos ng <xliff:g id="NUMBER_1">%2$d</xliff:g> pang hindi matagumpay na pagsubok, hihilingin sa iyong i-unlock ang telepono mo gamit ang isang email account.\n\n Subukan ulit sa loob ng <xliff:g id="NUMBER_2">%3$d</xliff:g> (na) segundo."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-tr/strings.xml b/packages/SystemUI/res-product/values-tr/strings.xml
index d6e0c39ee24b..2791adad744c 100644
--- a/packages/SystemUI/res-product/values-tr/strings.xml
+++ b/packages/SystemUI/res-product/values-tr/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"Tablette SIM kart yok."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"Telefonda SIM kart yok."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"PIN kodları eşleşmiyor"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Tabletin kilidini <xliff:g id="NUMBER_0">%1$d</xliff:g> kez hatalı bir şekilde açmayı denediniz. <xliff:g id="NUMBER_1">%2$d</xliff:g> başarısız deneme daha yaparsanız bu tablet sıfırlanacak ve tüm verileri silinecektir."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Telefonun kilidini <xliff:g id="NUMBER_0">%1$d</xliff:g> kez hatalı bir şekilde açmayı denediniz. <xliff:g id="NUMBER_1">%2$d</xliff:g> başarısız deneme daha yaparsanız bu telefon sıfırlanacak ve tüm verileri silinecektir."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Tabletin kilidini <xliff:g id="NUMBER">%d</xliff:g> kez hatalı bir şekilde açmayı denediniz. Bu tablet sıfırlanacak ve tüm verileri silinecektir."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Telefonun kilidini <xliff:g id="NUMBER">%d</xliff:g> kez hatalı bir şekilde açmayı denediniz. Bu telefon sıfırlanacak ve tüm verileri silinecektir."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Tabletin kilidini <xliff:g id="NUMBER_0">%1$d</xliff:g> kez hatalı bir şekilde açmayı denediniz. <xliff:g id="NUMBER_1">%2$d</xliff:g> başarısız deneme daha yaparsanız bu kullanıcı kaldırılacak ve tüm kullanıcı verileri silinecektir."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Telefonun kilidini <xliff:g id="NUMBER_0">%1$d</xliff:g> kez hatalı bir şekilde açmayı denediniz. <xliff:g id="NUMBER_1">%2$d</xliff:g> başarısız deneme daha yaparsanız bu kullanıcı kaldırılacak ve tüm kullanıcı verileri silinecektir."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Android TV cihazı kısa süre içinde kapanacak. Cihazınızı açık tutmak için bir düğmeye basın."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Cihaz kısa süre içinde kapanacak. Cihazı açık tutmak için düğmeye basın."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Tabletin kilidini <xliff:g id="NUMBER">%d</xliff:g> kez hatalı bir şekilde açmayı denediniz. İş profili kaldırılacak ve tüm profil verileri silinecektir."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Telefonun kilidini <xliff:g id="NUMBER">%d</xliff:g> kez hatalı bir şekilde açmayı denediniz. İş profili kaldırılacak ve tüm profil verileri silinecektir."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Kilit açma deseninizi <xliff:g id="NUMBER_0">%1$d</xliff:g> defa yanlış çizdiniz. <xliff:g id="NUMBER_1">%2$d</xliff:g> başarısız denemeden sonra, tabletinizin kilidini bir e-posta hesabı kullanarak açmanız istenir.\n<xliff:g id="NUMBER_2">%3$d</xliff:g>\n saniye içinde tekrar deneyin."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Kilit açma deseninizi <xliff:g id="NUMBER_0">%1$d</xliff:g> kez yanlış çizdiniz. <xliff:g id="NUMBER_1">%2$d</xliff:g> başarısız denemeden sonra telefonunuzun kilidini bir e-posta hesabı kullanarak açmanız istenir.\n<xliff:g id="NUMBER_2">%3$d</xliff:g>\n saniye içinde tekrar deneyin."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Daha hızlı şarj olması için telefonun yerini ayarlayın"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Telefonu kablosuz olarak şarj etmek için yerini ayarlayın"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Android TV cihazı kısa süre içinde kapanacak. Açık tutmak için bir düğmeye basın."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Cihaz kısa süre içinde kapanacak. Açık tutmak için düğmeye basın."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Tablette SIM kart yok."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Telefonda SIM kart yok."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"PIN kodları eşleşmiyor"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Tabletin kilidini <xliff:g id="NUMBER_0">%1$d</xliff:g> kez hatalı bir şekilde açmayı denediniz. <xliff:g id="NUMBER_1">%2$d</xliff:g> başarısız deneme daha yaparsanız bu tablet sıfırlanacak ve tüm verileri silinecektir."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Telefonun kilidini <xliff:g id="NUMBER_0">%1$d</xliff:g> kez hatalı bir şekilde açmayı denediniz. <xliff:g id="NUMBER_1">%2$d</xliff:g> başarısız deneme daha yaparsanız bu telefon sıfırlanacak ve tüm verileri silinecektir."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Tabletin kilidini <xliff:g id="NUMBER">%d</xliff:g> kez hatalı bir şekilde açmayı denediniz. Bu tablet sıfırlanacak ve tüm verileri silinecektir."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Telefonun kilidini <xliff:g id="NUMBER">%d</xliff:g> kez hatalı bir şekilde açmayı denediniz. Bu telefon sıfırlanacak ve tüm verileri silinecektir."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Tabletin kilidini <xliff:g id="NUMBER_0">%1$d</xliff:g> kez hatalı bir şekilde açmayı denediniz. <xliff:g id="NUMBER_1">%2$d</xliff:g> başarısız deneme daha yaparsanız bu kullanıcı kaldırılacak ve tüm kullanıcı verileri silinecektir."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Telefonun kilidini <xliff:g id="NUMBER_0">%1$d</xliff:g> kez hatalı bir şekilde açmayı denediniz. <xliff:g id="NUMBER_1">%2$d</xliff:g> başarısız deneme daha yaparsanız bu kullanıcı kaldırılacak ve tüm kullanıcı verileri silinecektir."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Tabletin kilidini <xliff:g id="NUMBER">%d</xliff:g> kez hatalı bir şekilde açmayı denediniz. Bu kullanıcı kaldırılacak ve tüm kullanıcı verileri silinecektir."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Telefonun kilidini <xliff:g id="NUMBER">%d</xliff:g> kez hatalı bir şekilde açmayı denediniz. Bu kullanıcı kaldırılacak ve tüm kullanıcı verileri silinecektir."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Tabletin kilidini <xliff:g id="NUMBER_0">%1$d</xliff:g> kez hatalı bir şekilde açmayı denediniz. <xliff:g id="NUMBER_1">%2$d</xliff:g> başarısız deneme daha yaparsanız iş profili kaldırılacak ve tüm profil verileri silinecektir."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Telefonun kilidini <xliff:g id="NUMBER_0">%1$d</xliff:g> kez hatalı bir şekilde açmayı denediniz. <xliff:g id="NUMBER_1">%2$d</xliff:g> başarısız deneme daha yaparsanız iş profili kaldırılacak ve tüm profil verileri silinecektir."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Tabletin kilidini <xliff:g id="NUMBER">%d</xliff:g> kez hatalı bir şekilde açmayı denediniz. İş profili kaldırılacak ve tüm profil verileri silinecektir."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Telefonun kilidini <xliff:g id="NUMBER">%d</xliff:g> kez hatalı bir şekilde açmayı denediniz. İş profili kaldırılacak ve tüm profil verileri silinecektir."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Kilit açma deseninizi <xliff:g id="NUMBER_0">%1$d</xliff:g> kez hatalı çizdiniz. <xliff:g id="NUMBER_1">%2$d</xliff:g> başarısız deneme daha yaparsanız tabletinizin kilidini bir e-posta hesabı kullanarak açmanız istenir.\n<xliff:g id="NUMBER_2">%3$d</xliff:g>\n saniye içinde tekrar deneyin."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Kilit açma deseninizi <xliff:g id="NUMBER_0">%1$d</xliff:g> kez yanlış çizdiniz. <xliff:g id="NUMBER_1">%2$d</xliff:g> başarısız deneme daha yaparsanız telefonunuzu bir e-posta hesabı kullanarak açmanız istenir.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> saniye içinde tekrar deneyin."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-uk/strings.xml b/packages/SystemUI/res-product/values-uk/strings.xml
index a53043c621bc..9647c4507753 100644
--- a/packages/SystemUI/res-product/values-uk/strings.xml
+++ b/packages/SystemUI/res-product/values-uk/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"У пристрої немає SIM-карти."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"У телефоні немає SIM-карти."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"PIN-коди не збігаються"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Кількість невдалих спроб розблокувати планшет: <xliff:g id="NUMBER_0">%1$d</xliff:g>. Залишилося спроб: <xliff:g id="NUMBER_1">%2$d</xliff:g>. У разі невдачі буде скинуто налаштування планшета й видалено всі його дані."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Кількість невдалих спроб розблокувати телефон: <xliff:g id="NUMBER_0">%1$d</xliff:g>. Залишилося спроб: <xliff:g id="NUMBER_1">%2$d</xliff:g>. У разі невдачі буде скинуто налаштування телефона й видалено всі його дані."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Кількість невдалих спроб розблокувати планшет: <xliff:g id="NUMBER">%d</xliff:g>. Буде скинуто налаштування цього планшета й видалено всі його дані."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Кількість невдалих спроб розблокувати телефон: <xliff:g id="NUMBER">%d</xliff:g>. Буде скинуто налаштування цього телефона й видалено всі його дані."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Кількість невдалих спроб розблокувати планшет: <xliff:g id="NUMBER_0">%1$d</xliff:g>. Залишилося спроб: <xliff:g id="NUMBER_1">%2$d</xliff:g>. У разі невдачі буде видалено цього користувача й усі його дані."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Кількість невдалих спроб розблокувати телефон: <xliff:g id="NUMBER_0">%1$d</xliff:g>. Залишилося спроб: <xliff:g id="NUMBER_1">%2$d</xliff:g>. У разі невдачі буде видалено цього користувача й усі його дані."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Незабаром пристрій Android TV буде вимкнено. Натисніть кнопку, щоб цього не сталося."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Незабаром пристрій буде вимкнено. Натисніть, щоб цього не сталося."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Кількість невдалих спроб розблокувати планшет: <xliff:g id="NUMBER">%d</xliff:g>. Буде видалено робочий профіль і всі його дані."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Кількість невдалих спроб розблокувати телефон: <xliff:g id="NUMBER">%d</xliff:g>. Буде видалено робочий профіль і всі його дані."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Ключ розблокування неправильно намальовано стільки разів: <xliff:g id="NUMBER_0">%1$d</xliff:g>. У вас є ще стільки спроб: <xliff:g id="NUMBER_1">%2$d</xliff:g>. У разі невдачі з’явиться запит розблокувати планшет за допомогою облікового запису електронної пошти.\n\n Повторіть спробу через <xliff:g id="NUMBER_2">%3$d</xliff:g> с."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Ключ розблокування неправильно намальовано стільки разів: <xliff:g id="NUMBER_0">%1$d</xliff:g>. У вас є ще стільки спроб: <xliff:g id="NUMBER_1">%2$d</xliff:g>. У разі невдачі з’явиться запит розблокувати телефон за допомогою облікового запису електронної пошти.\n\n Повторіть спробу через <xliff:g id="NUMBER_2">%3$d</xliff:g> с."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Поправте телефон, щоб активувати швидке заряджання"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Поправте телефон, щоб активувати бездротове заряджання"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Незабаром пристрій Android TV буде вимкнено. Натисніть кнопку, щоб цього не сталося."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Незабаром пристрій буде вимкнено. Натисніть, щоб цього не сталося."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"У планшеті немає SIM-карти."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"У телефоні немає SIM-карти."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"PIN-коди не збігаються"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Кількість невдалих спроб розблокувати планшет: <xliff:g id="NUMBER_0">%1$d</xliff:g>. Залишилося спроб: <xliff:g id="NUMBER_1">%2$d</xliff:g>. У разі невдачі буде скинуто налаштування планшета й видалено всі його дані."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Кількість невдалих спроб розблокувати телефон: <xliff:g id="NUMBER_0">%1$d</xliff:g>. Залишилося спроб: <xliff:g id="NUMBER_1">%2$d</xliff:g>. У разі невдачі буде скинуто налаштування телефона й видалено всі його дані."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Кількість невдалих спроб розблокувати планшет: <xliff:g id="NUMBER">%d</xliff:g>. Буде скинуто налаштування цього планшета й видалено всі його дані."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Кількість невдалих спроб розблокувати телефон: <xliff:g id="NUMBER">%d</xliff:g>. Буде скинуто налаштування цього телефона й видалено всі його дані."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Кількість невдалих спроб розблокувати планшет: <xliff:g id="NUMBER_0">%1$d</xliff:g>. Залишилося спроб: <xliff:g id="NUMBER_1">%2$d</xliff:g>. У разі невдачі буде видалено цього користувача й усі його дані."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Кількість невдалих спроб розблокувати телефон: <xliff:g id="NUMBER_0">%1$d</xliff:g>. Залишилося спроб: <xliff:g id="NUMBER_1">%2$d</xliff:g>. У разі невдачі буде видалено цього користувача й усі його дані."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Кількість невдалих спроб розблокувати планшет: <xliff:g id="NUMBER">%d</xliff:g>. Буде видалено цього користувача й усі його дані."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Кількість невдалих спроб розблокувати телефон: <xliff:g id="NUMBER">%d</xliff:g>. Буде видалено цього користувача й усі його дані."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Кількість невдалих спроб розблокувати планшет: <xliff:g id="NUMBER_0">%1$d</xliff:g>. Залишилося спроб: <xliff:g id="NUMBER_1">%2$d</xliff:g>. У разі невдачі буде видалено робочий профіль і всі його дані."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Кількість невдалих спроб розблокувати телефон: <xliff:g id="NUMBER_0">%1$d</xliff:g>. Залишилося спроб: <xliff:g id="NUMBER_1">%2$d</xliff:g>. У разі невдачі буде видалено робочий профіль і всі його дані."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Кількість невдалих спроб розблокувати планшет: <xliff:g id="NUMBER">%d</xliff:g>. Буде видалено робочий профіль і всі його дані."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Кількість невдалих спроб розблокувати телефон: <xliff:g id="NUMBER">%d</xliff:g>. Буде видалено робочий профіль і всі його дані."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Ключ розблокування неправильно намальовано стільки разів: <xliff:g id="NUMBER_0">%1$d</xliff:g>. Залишилося спроб: <xliff:g id="NUMBER_1">%2$d</xliff:g>. У разі невдачі з\'явиться запит розблокувати планшет за допомогою облікового запису електронної пошти.\n\n Повторіть спробу за <xliff:g id="NUMBER_2">%3$d</xliff:g> с."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Ключ розблокування неправильно намальовано стільки разів: <xliff:g id="NUMBER_0">%1$d</xliff:g>. Залишилося спроб: <xliff:g id="NUMBER_1">%2$d</xliff:g>. У разі невдачі з\'явиться запит розблокувати телефон за допомогою облікового запису електронної пошти.\n\n Повторіть спробу за <xliff:g id="NUMBER_2">%3$d</xliff:g> с."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-ur/strings.xml b/packages/SystemUI/res-product/values-ur/strings.xml
index 4569ee3a2967..83f262f92522 100644
--- a/packages/SystemUI/res-product/values-ur/strings.xml
+++ b/packages/SystemUI/res-product/values-ur/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"‏ٹیبلیٹ میں کوئی SIM کارڈ نہیں ہے۔"</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"‏فون میں کوئی SIM کارڈ نہيں ہے۔"</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"‏PIN کوڈز مماثل نہیں ہیں"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"آپ نے ٹیبلیٹ کو غیر مقفل کرنے کیلئے <xliff:g id="NUMBER_0">%1$d</xliff:g> بار غلط طریقے سے کوشش کی ہے۔ <xliff:g id="NUMBER_1">%2$d</xliff:g> مزید ناکام کوششوں کے بعد، اس ٹیبلیٹ کو دوبارہ ترتیب دے دیا جائے گا، جس سے اس کا سبھی ڈیٹا حذف ہو جائے گا۔"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"آپ نے فون کو غیر مقفل کرنے کیلئے <xliff:g id="NUMBER_0">%1$d</xliff:g> بار غلط طریقے سے کوشش کی ہے۔ <xliff:g id="NUMBER_1">%2$d</xliff:g> مزید ناکام کوششوں کے بعد، اس فون کو دوبارہ ترتیب دے دیا جائے گا، جس سے اس کا سبھی ڈیٹا حذف ہو جائے گا۔"</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"آپ نے ٹیبلیٹ کو غیر مقفل کرنے کیلئے <xliff:g id="NUMBER">%d</xliff:g> بار غلط طریقے سے کوشش کی ہے۔ اس ٹیبلیٹ کو دوبارہ ترتیب دے دیا جائے گا، جس سے اس کا سبھی ڈیٹا حذف ہو جائے گا۔"</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"آپ نے فون کو غیر مقفل کرنے کیلئے <xliff:g id="NUMBER">%d</xliff:g> بار غلط طریقے سے کوشش کی ہے۔ اس فون کو دوبارہ ترتیب دے دیا جائے گا، جس سے اس کا سبھی ڈیٹا حذف ہو جائے گا۔"</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"آپ نے ٹیبلیٹ کو غیر مقفل کرنے کیلئے <xliff:g id="NUMBER_0">%1$d</xliff:g> بار غلط طریقے سے کوشش کی ہے۔ <xliff:g id="NUMBER_1">%2$d</xliff:g> مزید ناکام کوششوں کے بعد، اس صارف کو ہٹا دیا جائے گا، جس سے صارف کا سبھی ڈیٹا حذف ہو جائے گا۔"</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"آپ نے فون کو غیر مقفل کرنے کیلئے <xliff:g id="NUMBER_0">%1$d</xliff:g> بار غلط طریقے سے کوشش کی ہے۔ <xliff:g id="NUMBER_1">%2$d</xliff:g> مزید ناکام کوششوں کے بعد، اس صارف کو ہٹا دیا جائے گا، جس سے صارف کا سبھی ڈیٹا حذف ہو جائے گا۔"</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"‏Android TV آلہ جلد ہی بند ہوجائے گا آن رکھنے کے ليے بٹن دبائیں۔"</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"آلہ جلد ہی بند ہوجائے گا اسے آن رکھنے کے ليے دبائیں۔"</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"آپ نے ٹیبلیٹ کو غیر مقفل کرنے کیلئے <xliff:g id="NUMBER">%d</xliff:g> بار غلط طریقے سے کوشش کی ہے۔ دفتری پروفائل ہٹا دیا جائے گا، جس سے پروفائل کا سبھی ڈیٹا حذف ہو جائے گا۔"</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"آپ نے فون کو غیر مقفل کرنے کیلئے <xliff:g id="NUMBER">%d</xliff:g> بار غلط طریقے سے کوشش کی ہے۔ دفتری پروفائل ہٹا دیا جائے گا، جس سے پروفائل کا سبھی ڈیٹا حذف ہو جائے گا۔"</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"آپ نے اپنا غیر مقفل کرنے کا پیٹرن <xliff:g id="NUMBER_0">%1$d</xliff:g> بار غلط طریقے سے ڈرا کیا ہے۔ <xliff:g id="NUMBER_1">%2$d</xliff:g> مزید ناکام کوششوں کے بعد، آپ سے ایک ای میل اکاؤنٹ استعمال کرکے اپنا ٹیبلیٹ غیر مقفل کرنے کو کہا جائے گا۔\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> سیکنڈ میں دوبارہ کوشش کریں۔"</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"آپ نے اپنا غیر مقفل کرنے کا پیٹرن <xliff:g id="NUMBER_0">%1$d</xliff:g> بار غلط طریقے سے ڈرا کیا ہے۔ <xliff:g id="NUMBER_1">%2$d</xliff:g> مزید ناکام کوششوں کے بعد، آپ سے ایک ای میل اکاؤنٹ استعمال کرکے اپنا فون غیر مقفل کرنے کو کہا جائے گا۔\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> سیکنڈ میں دوبارہ کوشش کریں۔"</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"فاسٹ چارجنگ کے لیے فون کو دوبارہ موافق بنائیں"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"وائرلیس چارج کرنے کے ليے فون کو دوبارہ موافق بنائيں"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"‏Android TV آلہ جلد ہی بند ہوجائے گا؛ اسے آن رکھنے کے ليے بٹن دبائیں۔"</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"آلہ جلد ہی بند ہوجائے گا اسے آن رکھنے کے ليے دبائیں۔"</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"‏ٹیبلیٹ میں کوئی SIM کارڈ نہیں ہے۔"</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"‏فون میں کوئی SIM کارڈ نہيں ہے۔"</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"‏PIN کوڈز مماثل نہیں ہیں"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"آپ نے ٹیبلیٹ کو غیر مقفل کرنے کیلئے <xliff:g id="NUMBER_0">%1$d</xliff:g> بار غلط طریقے سے کوشش کی ہے۔ <xliff:g id="NUMBER_1">%2$d</xliff:g> مزید ناکام کوششوں کے بعد، اس ٹیبلیٹ کو ری سیٹ کر دیا جائے گا، جس سے اس کا سبھی ڈیٹا حذف ہو جائے گا۔"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"آپ نے فون کو غیر مقفل کرنے کیلئے <xliff:g id="NUMBER_0">%1$d</xliff:g> بار غلط طریقے سے کوشش کی ہے۔ <xliff:g id="NUMBER_1">%2$d</xliff:g> مزید ناکام کوششوں کے بعد، اس فون کو ری سیٹ کر دیا جائے گا، جس سے اس کا سبھی ڈیٹا حذف ہو جائے گا۔"</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"آپ نے ٹیبلیٹ کو غیر مقفل کرنے کیلئے <xliff:g id="NUMBER">%d</xliff:g> بار غلط طریقے سے کوشش کی ہے۔ اس ٹیبلیٹ کو ری سیٹ کر دیا جائے گا، جس سے اس کا سبھی ڈیٹا حذف ہو جائے گا۔"</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"آپ نے فون کو غیر مقفل کرنے کیلئے <xliff:g id="NUMBER">%d</xliff:g> بار غلط طریقے سے کوشش کی ہے۔ اس فون کو ری سیٹ کر دیا جائے گا، جس سے اس کا سبھی ڈیٹا حذف ہو جائے گا۔"</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"آپ نے ٹیبلیٹ کو غیر مقفل کرنے کیلئے <xliff:g id="NUMBER_0">%1$d</xliff:g> بار غلط طریقے سے کوشش کی ہے۔ <xliff:g id="NUMBER_1">%2$d</xliff:g> مزید ناکام کوششوں کے بعد، اس صارف کو ہٹا دیا جائے گا، جس سے صارف کا سبھی ڈیٹا حذف ہو جائے گا۔"</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"آپ نے فون کو غیر مقفل کرنے کیلئے <xliff:g id="NUMBER_0">%1$d</xliff:g> بار غلط طریقے سے کوشش کی ہے۔ <xliff:g id="NUMBER_1">%2$d</xliff:g> مزید ناکام کوششوں کے بعد، اس صارف کو ہٹا دیا جائے گا، جس سے صارف کا سبھی ڈیٹا حذف ہو جائے گا۔"</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"آپ نے ٹیبلیٹ کو غیر مقفل کرنے کیلئے <xliff:g id="NUMBER">%d</xliff:g> بار غلط طریقے سے کوشش کی ہے۔ اس صارف کو ہٹا دیا جائے گا، جس سے صارف کا سبھی ڈیٹا حذف ہو جائے گا۔"</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"آپ نے فون کو غیر مقفل کرنے کیلئے <xliff:g id="NUMBER">%d</xliff:g> بار غلط طریقے سے کوشش کی ہے۔ اس صارف کو ہٹا دیا جائے گا، جس سے صارف کا سبھی ڈیٹا حذف ہو جائے گا۔"</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"آپ نے ٹیبلیٹ کو غیر مقفل کرنے کیلئے <xliff:g id="NUMBER_0">%1$d</xliff:g> بار غلط طریقے سے کوشش کی ہے۔ <xliff:g id="NUMBER_1">%2$d</xliff:g> مزید ناکام کوششوں کے بعد، دفتری پروفائل ہٹا دیا جائے گا، جس سے پروفائل کا سبھی ڈیٹا حذف ہو جائے گا۔"</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"آپ نے فون کو غیر مقفل کرنے کیلئے <xliff:g id="NUMBER_0">%1$d</xliff:g> بار غلط طریقے سے کوشش کی ہے۔ <xliff:g id="NUMBER_1">%2$d</xliff:g> مزید ناکام کوششوں کے بعد، دفتری پروفائل ہٹا دی جائے گی، جس سے پروفائل کا سبھی ڈیٹا حذف ہو جائے گا۔"</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"آپ نے ٹیبلیٹ کو غیر مقفل کرنے کیلئے <xliff:g id="NUMBER">%d</xliff:g> بار غلط طریقے سے کوشش کی ہے۔ دفتری پروفائل ہٹا دی جائے گی، جس سے پروفائل کا سبھی ڈیٹا حذف ہو جائے گا۔"</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"آپ نے فون کو غیر مقفل کرنے کیلئے <xliff:g id="NUMBER">%d</xliff:g> بار غلط طریقے سے کوشش کی ہے۔ دفتری پروفائل ہٹا دی جائے گی، جس سے پروفائل کا سبھی ڈیٹا حذف ہو جائے گا۔"</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"آپ نے اپنا غیر مقفل کرنے کا پیٹرن <xliff:g id="NUMBER_0">%1$d</xliff:g> بار غلط طریقے سے ڈرا کیا ہے۔ <xliff:g id="NUMBER_1">%2$d</xliff:g> مزید ناکام کوششوں کے بعد، آپ سے ایک ای میل اکاؤنٹ استعمال کر کے اپنا ٹیبلیٹ غیر مقفل کرنے کو کہا جائے گا۔\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> سیکنڈ میں دوبارہ کوشش کریں۔"</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"آپ نے اپنا غیر مقفل کرنے کا پیٹرن <xliff:g id="NUMBER_0">%1$d</xliff:g> بار غلط طریقے سے ڈرا کیا ہے۔ <xliff:g id="NUMBER_1">%2$d</xliff:g> مزید ناکام کوششوں کے بعد، آپ سے ایک ای میل اکاؤنٹ استعمال کر کے اپنا فون غیر مقفل کرنے کو کہا جائے گا۔\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> سیکنڈ میں دوبارہ کوشش کریں۔"</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-uz/strings.xml b/packages/SystemUI/res-product/values-uz/strings.xml
index 105ae9dd08e7..c3e3a3a59e90 100644
--- a/packages/SystemUI/res-product/values-uz/strings.xml
+++ b/packages/SystemUI/res-product/values-uz/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"Planshetingizda SIM karta yo‘q."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"Telefoningizda SIM karta yo‘q."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"PIN kod mos kelmadi"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Siz planshetni qulfdan chiqarish uchun <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri urinish qildingiz. Agar yana <xliff:g id="NUMBER_1">%2$d</xliff:g> marta muvaffaqiyatsiz urinish qilsangiz, ushbu planshetda zavod sozlamalari qayta tiklanadi va undagi barcha ma’lumotlar ham o‘chib ketadi."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Siz telefonni qulfdan chiqarish uchun <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri urinish qildingiz. Agar yana <xliff:g id="NUMBER_1">%2$d</xliff:g> marta muvaffaqiyatsiz urinish qilsangiz, ushbu telefonda zavod sozlamalari qayta tiklanadi va undagi barcha ma’lumotlar ham o‘chib ketadi."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Siz planshetni qulfdan chiqarish uchun <xliff:g id="NUMBER">%d</xliff:g> marta noto‘g‘ri urinish qildingiz. Endi, ushbu planshetda zavod sozlamalari qayta tiklanadi va undagi barcha ma’lumotlar ham o‘chib ketadi."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Siz telefonni qulfdan chiqarish uchun <xliff:g id="NUMBER">%d</xliff:g> marta noto‘g‘ri urinish qildingiz. Endi, ushbu telefonda zavod sozlamalari qayta tiklanadi va undagi barcha ma’lumotlar ham o‘chib ketadi."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Siz planshetni qulfdan chiqarish uchun <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri urinish qildingiz. Agar yana <xliff:g id="NUMBER_1">%2$d</xliff:g> marta muvaffaqiyatsiz urinish qilsangiz, ushbu foydalanuvchi o‘chirib tashlanadi va undagi barcha foydalanuvchi ma’lumotlari ham o‘chib ketadi."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Siz telefonni qulfdan chiqarish uchun <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri urinish qildingiz. Agar yana <xliff:g id="NUMBER_1">%2$d</xliff:g> marta muvaffaqiyatsiz urinish qilsangiz, ushbu foydalanuvchi o‘chirib tashlanadi va undagi barcha foydalanuvchi ma’lumotlari ham o‘chib ketadi."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Android TV qurilmasi oʻchish arafasida, yoniq qolishi uchun istalgan tugmani bosing."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Qurilma oʻchish arafasida, yoniq qolishi uchun istalgan tugmani bosing."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Siz planshetni qulfdan chiqarish uchun <xliff:g id="NUMBER">%d</xliff:g> marta noto‘g‘ri urinish qildingiz. Endi, ishchi profil o‘chirib tashlanadi va undagi barcha ma’lumotlar ham o‘chib ketadi."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Siz telefonni qulfdan chiqarish uchun <xliff:g id="NUMBER">%d</xliff:g> marta noto‘g‘ri urinish qildingiz. Endi, ishchi profil o‘chirib tashlanadi va undagi barcha ma’lumotlar ham o‘chib ketadi."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Grafik kalit <xliff:g id="NUMBER_0">%1$d</xliff:g> marta xato chizildi. <xliff:g id="NUMBER_1">%2$d</xliff:g> marta muvaffaqiyatsiz urinishdan keyin, sizdan e-pochtangizdan foydalanib, planshet qulfini ochishingiz so‘raladi.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> soniyadan keyin yana urinib ko‘ring."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Grafik kalit <xliff:g id="NUMBER_0">%1$d</xliff:g> marta xato chizildi. <xliff:g id="NUMBER_1">%2$d</xliff:g> marta muvaffaqiyatsiz urinishdan keyin, sizdan e-pochtangizdan foydalanib, telefon qulfini ochishingiz so‘raladi.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> soniyadan keyin qayta urinib ko‘ring."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Tezkor quvvatlanishi uchun telefonni dok-stansiyaga joylang"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Telefon quvvat olishi uchun uni dok-stansiyaga joylang"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Android TV qurilmasi oʻchish arafasida, yoniq qolishi uchun istalgan tugmani bosing."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Qurilma oʻchish arafasida, yoniq qolishi uchun istalgan tugmani bosing"</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Planshetingizda SIM karta yoʻq."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Telefoningizda SIM karta yoʻq."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"PIN kod mos kelmadi"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Siz planshetni qulfdan chiqarish uchun <xliff:g id="NUMBER_0">%1$d</xliff:g> marta xato urinish qildingiz. Agar yana <xliff:g id="NUMBER_1">%2$d</xliff:g> marta muvaffaqiyatsiz urinish qilsangiz, ushbu planshetda zavod sozlamalari qayta tiklanadi va undagi barcha maʼlumotlar ham oʻchib ketadi."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Siz telefonni qulfdan chiqarish uchun <xliff:g id="NUMBER_0">%1$d</xliff:g> marta xato urinish qildingiz. Agar yana <xliff:g id="NUMBER_1">%2$d</xliff:g> marta muvaffaqiyatsiz urinish qilsangiz, ushbu telefonda zavod sozlamalari qayta tiklanadi va undagi barcha maʼlumotlar ham oʻchib ketadi."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Siz planshetni qulfdan chiqarish uchun <xliff:g id="NUMBER">%d</xliff:g> marta xato urinish qildingiz. Endi, ushbu planshetda zavod sozlamalari qayta tiklanadi va undagi barcha maʼlumotlar ham oʻchib ketadi."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Siz telefonni qulfdan chiqarish uchun <xliff:g id="NUMBER">%d</xliff:g> marta xato urinish qildingiz. Endi ushbu telefonda zavod sozlamalari qayta tiklanadi va undagi barcha maʼlumotlar ham oʻchib ketadi."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Siz planshetni qulfdan chiqarish uchun <xliff:g id="NUMBER_0">%1$d</xliff:g> marta xato urinish qildingiz. Agar yana <xliff:g id="NUMBER_1">%2$d</xliff:g> marta muvaffaqiyatsiz urinish qilsangiz, ushbu foydalanuvchi oʻchirib tashlanadi va undagi barcha foydalanuvchi maʼlumotlari ham oʻchib ketadi."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Siz telefonni qulfdan chiqarish uchun <xliff:g id="NUMBER_0">%1$d</xliff:g> marta xato urinish qildingiz. Agar yana <xliff:g id="NUMBER_1">%2$d</xliff:g> marta muvaffaqiyatsiz urinish qilsangiz, ushbu foydalanuvchi oʻchirib tashlanadi va undagi barcha foydalanuvchi maʼlumotlari ham oʻchib ketadi."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Siz planshetni qulfdan chiqarish uchun <xliff:g id="NUMBER">%d</xliff:g> marta xato urinish qildingiz. Endi ushbu foydalanuvchi oʻchirib tashlanadi va undagi barcha foydalanuvchi maʼlumotlari ham oʻchib ketadi."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Siz telefonni qulfdan chiqarish uchun <xliff:g id="NUMBER">%d</xliff:g> marta xato urinish qildingiz. Endi ushbu foydalanuvchi oʻchirib tashlanadi va undagi barcha foydalanuvchi maʼlumotlari ham oʻchib ketadi."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Siz planshetni qulfdan chiqarish uchun <xliff:g id="NUMBER_0">%1$d</xliff:g> marta xato urinish qildingiz. Agar yana <xliff:g id="NUMBER_1">%2$d</xliff:g> marta muvaffaqiyatsiz urinish qilsangiz, ish profili oʻchirib tashlanadi va undagi barcha profil maʼlumotlari ham oʻchib ketadi."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Siz telefonni qulfdan chiqarish uchun <xliff:g id="NUMBER_0">%1$d</xliff:g> marta xato urinish qildingiz. Agar yana <xliff:g id="NUMBER_1">%2$d</xliff:g> marta muvaffaqiyatsiz urinish qilsangiz, ish profili oʻchirib tashlanadi va undagi barcha profil maʼlumotlari ham oʻchib ketadi."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Siz planshetni qulfdan chiqarish uchun <xliff:g id="NUMBER">%d</xliff:g> marta xato urinish qildingiz. Endi ishchi profil oʻchirib tashlanadi va undagi barcha maʼlumotlar ham oʻchib ketadi."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Siz telefonni qulfdan chiqarish uchun <xliff:g id="NUMBER">%d</xliff:g> marta xato urinish qildingiz. Endi ish profili oʻchirib tashlanadi va undagi barcha maʼlumotlar ham oʻchib ketadi."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Grafik kalit <xliff:g id="NUMBER_0">%1$d</xliff:g> marta xato chizildi. <xliff:g id="NUMBER_1">%2$d</xliff:g> marta muvaffaqiyatsiz urinishdan keyin sizdan emailingizdan foydalanib, planshet qulfini ochishingiz soʻraladi.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> soniyadan keyin yana urinib koʻring."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Grafik kalit <xliff:g id="NUMBER_0">%1$d</xliff:g> marta xato chizildi. <xliff:g id="NUMBER_1">%2$d</xliff:g> marta muvaffaqiyatsiz urinishdan keyin sizdan emailngizdan foydalanib, telefon qulfini ochishingiz soʻraladi.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> soniyadan keyin qayta urinib koʻring."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-vi/strings.xml b/packages/SystemUI/res-product/values-vi/strings.xml
index c9022eea2af2..8e9c2da55a50 100644
--- a/packages/SystemUI/res-product/values-vi/strings.xml
+++ b/packages/SystemUI/res-product/values-vi/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,46 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"Không có thẻ SIM nào trong máy tính bảng."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"Không có thẻ SIM nào trong điện thoại."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"Mã PIN không khớp"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Bạn đã mở khóa máy tính bảng sai <xliff:g id="NUMBER_0">%1$d</xliff:g> lần. Sau <xliff:g id="NUMBER_1">%2$d</xliff:g> lần mở khóa không thành công nữa, máy tính bảng này sẽ được đặt lại, tức là tất cả dữ liệu của máy tính bảng sẽ bị xóa."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Bạn đã mở khóa điện thoại sai <xliff:g id="NUMBER_0">%1$d</xliff:g> lần. Sau <xliff:g id="NUMBER_1">%2$d</xliff:g> lần mở khóa không thành công nữa, điện thoại này sẽ được đặt lại, tức là tất cả dữ liệu của điện thoại sẽ bị xóa."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Bạn đã mở khóa máy tính bảng sai <xliff:g id="NUMBER">%d</xliff:g> lần. Máy tính bảng này sẽ được đặt lại, tức là tất cả dữ liệu của máy tính bảng sẽ bị xóa."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Bạn đã mở khóa điện thoại sai <xliff:g id="NUMBER">%d</xliff:g> lần. Điện thoại này sẽ được đặt lại, tức là tất cả dữ liệu của điện thoại sẽ bị xóa."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Bạn đã mở khóa máy tính bảng sai <xliff:g id="NUMBER_0">%1$d</xliff:g> lần. Sau <xliff:g id="NUMBER_1">%2$d</xliff:g> lần mở khóa không thành công nữa, người dùng này sẽ bị xóa, tức là tất cả dữ liệu người dùng sẽ bị xóa."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Bạn đã mở khóa điện thoại sai <xliff:g id="NUMBER_0">%1$d</xliff:g> lần. Sau <xliff:g id="NUMBER_1">%2$d</xliff:g> lần mở khóa không thành công nữa, người dùng này sẽ bị xóa, tức là tất cả dữ liệu người dùng sẽ bị xóa."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for notification_bubble_title (8330481035191903164) -->
- <skip/>
- <!-- no translation found for notification_channel_summary_bubble (7235935211580860537) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Thiết bị Android TV sẽ sớm tắt. Hãy nhấn vào một nút để thiết bị vẫn bật."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Thiết bị sẽ sớm tắt. Hãy nhấn vào một nút để thiết bị vẫn bật."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Bạn đã mở khóa máy tính bảng sai <xliff:g id="NUMBER">%d</xliff:g> lần. Hồ sơ công việc sẽ bị xóa, tức là tất cả dữ liệu hồ sơ sẽ bị xóa."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Bạn đã mở khóa điện thoại sai <xliff:g id="NUMBER">%d</xliff:g> lần. Hồ sơ công việc sẽ bị xóa, tức là tất cả dữ liệu hồ sơ sẽ bị xóa."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Bạn đã vẽ không chính xác hình mở khóa <xliff:g id="NUMBER_0">%1$d</xliff:g> lần. Sau <xliff:g id="NUMBER_1">%2$d</xliff:g> lần thử không thành công nữa, bạn sẽ được yêu cầu mở khóa máy tính bảng bằng tài khoản email.\n\n Hãy thử lại sau <xliff:g id="NUMBER_2">%3$d</xliff:g> giây."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Bạn đã vẽ không chính xác hình mở khóa <xliff:g id="NUMBER_0">%1$d</xliff:g> lần. Sau <xliff:g id="NUMBER_1">%2$d</xliff:g> lần thử không thành công nữa, bạn sẽ được yêu cầu mở khóa điện thoại bằng tài khoản email.\n\n Hãy thử lại sau <xliff:g id="NUMBER_2">%3$d</xliff:g> giây."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Điều chỉnh lại vị trí điện thoại để sạc nhanh hơn"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Điều chỉnh lại vị trí điện thoại để sạc không dây"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Thiết bị Android TV sắp tắt. Hãy nhấn vào một nút để duy trì trạng thái bật."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Thiết bị sắp tắt. Hãy nhấn vào một nút để duy trì trạng thái bật."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Không có thẻ SIM nào trong máy tính bảng."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Không có thẻ SIM nào trong điện thoại."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"Mã PIN không khớp"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Bạn đã mở khóa máy tính bảng sai <xliff:g id="NUMBER_0">%1$d</xliff:g> lần. Sau <xliff:g id="NUMBER_1">%2$d</xliff:g> lần mở khóa không thành công nữa, máy tính bảng này sẽ được đặt lại, tức là tất cả dữ liệu của máy tính bảng sẽ bị xóa."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Bạn đã mở khóa điện thoại sai <xliff:g id="NUMBER_0">%1$d</xliff:g> lần. Sau <xliff:g id="NUMBER_1">%2$d</xliff:g> lần mở khóa không thành công nữa, điện thoại này sẽ được đặt lại, tức là tất cả dữ liệu của điện thoại sẽ bị xóa."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Bạn đã mở khóa máy tính bảng sai <xliff:g id="NUMBER">%d</xliff:g> lần. Máy tính bảng này sẽ được đặt lại, tức là tất cả dữ liệu của máy tính bảng sẽ bị xóa."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Bạn đã mở khóa điện thoại sai <xliff:g id="NUMBER">%d</xliff:g> lần. Điện thoại này sẽ được đặt lại, tức là tất cả dữ liệu của điện thoại sẽ bị xóa."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Bạn đã mở khóa máy tính bảng sai <xliff:g id="NUMBER_0">%1$d</xliff:g> lần. Sau <xliff:g id="NUMBER_1">%2$d</xliff:g> lần mở khóa không thành công nữa, người dùng này sẽ bị xóa, tức là tất cả dữ liệu người dùng sẽ bị xóa."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Bạn đã mở khóa điện thoại sai <xliff:g id="NUMBER_0">%1$d</xliff:g> lần. Sau <xliff:g id="NUMBER_1">%2$d</xliff:g> lần mở khóa không thành công nữa, người dùng này sẽ bị xóa, tức là tất cả dữ liệu người dùng sẽ bị xóa."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Bạn đã mở khóa máy tính bảng sai <xliff:g id="NUMBER">%d</xliff:g> lần. Người dùng này sẽ bị xóa, tức là tất cả dữ liệu người dùng sẽ bị xóa."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Bạn đã mở khóa điện thoại sai <xliff:g id="NUMBER">%d</xliff:g> lần. Người dùng này sẽ bị xóa, tức là tất cả dữ liệu người dùng sẽ bị xóa."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Bạn đã mở khóa máy tính bảng sai <xliff:g id="NUMBER_0">%1$d</xliff:g> lần. Sau <xliff:g id="NUMBER_1">%2$d</xliff:g> lần mở khóa không thành công nữa, hồ sơ công việc sẽ bị xóa, tức là tất cả dữ liệu hồ sơ sẽ bị xóa."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Bạn đã mở khóa điện thoại sai <xliff:g id="NUMBER_0">%1$d</xliff:g> lần. Sau <xliff:g id="NUMBER_1">%2$d</xliff:g> lần mở khóa không thành công nữa, hồ sơ công việc sẽ bị xóa, tức là tất cả dữ liệu hồ sơ sẽ bị xóa."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Bạn đã mở khóa máy tính bảng sai <xliff:g id="NUMBER">%d</xliff:g> lần. Hồ sơ công việc sẽ bị xóa, tức là tất cả dữ liệu hồ sơ sẽ bị xóa."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Bạn đã mở khóa điện thoại sai <xliff:g id="NUMBER">%d</xliff:g> lần. Hồ sơ công việc sẽ bị xóa, tức là tất cả dữ liệu hồ sơ sẽ bị xóa."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Bạn đã vẽ không chính xác hình mở khóa <xliff:g id="NUMBER_0">%1$d</xliff:g> lần. Sau <xliff:g id="NUMBER_1">%2$d</xliff:g> lần thử không thành công nữa, bạn sẽ được yêu cầu mở khóa máy tính bảng bằng tài khoản email.\n\n Hãy thử lại sau <xliff:g id="NUMBER_2">%3$d</xliff:g> giây."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Bạn đã vẽ không chính xác hình mở khóa <xliff:g id="NUMBER_0">%1$d</xliff:g> lần. Sau <xliff:g id="NUMBER_1">%2$d</xliff:g> lần thử không thành công nữa, bạn sẽ được yêu cầu mở khóa điện thoại bằng tài khoản email.\n\n Hãy thử lại sau <xliff:g id="NUMBER_2">%3$d</xliff:g> giây."</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-zh-rCN/strings.xml b/packages/SystemUI/res-product/values-zh-rCN/strings.xml
index 7109c9990bee..56c461c7d28c 100644
--- a/packages/SystemUI/res-product/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res-product/values-zh-rCN/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"平板电脑中没有 SIM 卡。"</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"手机中没有 SIM 卡。"</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"PIN 码不匹配"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"您尝试解锁平板电脑后失败的次数已达 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次。如果再尝试 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次后仍不成功,平板电脑将会被重置,而这将删除其中的所有数据。"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"您尝试解锁手机后失败的次数已达 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次。如果再尝试 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次后仍不成功,手机将会被重置,而这将删除其中的所有数据。"</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"您尝试解锁平板电脑后失败的次数已达 <xliff:g id="NUMBER">%d</xliff:g> 次。这部平板电脑将会被重置,而这将删除其中的所有数据。"</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"您尝试解锁手机后失败的次数已达 <xliff:g id="NUMBER">%d</xliff:g> 次。这部手机将会被重置,而这将删除其中的所有数据。"</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"您尝试解锁平板电脑后失败的次数已达 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次。如果再尝试 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次后仍不成功,系统将移除此用户,而这将删除所有的用户数据。"</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"您尝试解锁手机后失败的次数已达 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次。如果再尝试 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次后仍不成功,系统将移除此用户,而这将删除所有的用户数据。"</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Android TV 设备即将关闭;按一下相应的按钮即可让设备保持开启状态。"</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"设备即将关闭;按一下即可让设备保持开启状态。"</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"您尝试解锁平板电脑后失败的次数已达 <xliff:g id="NUMBER">%d</xliff:g> 次。系统将移除此工作资料,而这将删除所有的工作资料数据。"</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"您尝试解锁手机后失败的次数已达 <xliff:g id="NUMBER">%d</xliff:g> 次。系统将移除此工作资料,而这将删除所有的工作资料数据。"</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"您已 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次画错解锁图案。如果再尝试 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次后仍不成功,系统就会要求您使用自己的电子邮件帐号解锁平板电脑。\n\n请在 <xliff:g id="NUMBER_2">%3$d</xliff:g> 秒后重试。"</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"您已 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次画错解锁图案。如果再尝试 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次后仍不成功,系统就会要求您使用自己的电子邮件帐号解锁手机。\n\n请在 <xliff:g id="NUMBER_2">%3$d</xliff:g> 秒后重试。"</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"请重新调整手机位置以便更快速地充电"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"请重新调整手机位置以便进行无线充电"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Android TV 设备即将关闭;按一下相应的按钮即可让设备保持开启状态。"</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"设备即将关闭;按一下即可让设备保持开启状态。"</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"平板电脑中没有 SIM 卡。"</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"手机中没有 SIM 卡。"</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"PIN 码不匹配"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"您尝试解锁平板电脑后失败的次数已达 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次。如果再尝试 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次后仍不成功,平板电脑将会被重置,而这将删除其中的所有数据。"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"您尝试解锁手机后失败的次数已达 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次。如果再尝试 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次后仍不成功,手机将会被重置,而这将删除其中的所有数据。"</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"您尝试解锁平板电脑后失败的次数已达 <xliff:g id="NUMBER">%d</xliff:g> 次。这部平板电脑将会被重置,而这将删除其中的所有数据。"</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"您尝试解锁手机后失败的次数已达 <xliff:g id="NUMBER">%d</xliff:g> 次。这部手机将会被重置,而这将删除其中的所有数据。"</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"您尝试解锁平板电脑后失败的次数已达 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次。如果再尝试 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次后仍不成功,系统将移除此用户,而这将删除所有的用户数据。"</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"您尝试解锁手机后失败的次数已达 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次。如果再尝试 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次后仍不成功,系统将移除此用户,而这将删除所有的用户数据。"</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"您尝试解锁平板电脑后失败的次数已达 <xliff:g id="NUMBER">%d</xliff:g> 次。系统将移除此用户,而这将删除所有的用户数据。"</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"您尝试解锁手机后失败的次数已达 <xliff:g id="NUMBER">%d</xliff:g> 次。系统将移除此用户,而这将删除所有的用户数据。"</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"您尝试解锁平板电脑后失败的次数已达 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次。如果再尝试 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次后仍不成功,系统将移除此工作资料,而这将删除所有的工作资料数据。"</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"您尝试解锁手机后失败的次数已达 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次。如果再尝试 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次后仍不成功,系统将移除此工作资料,而这将删除所有的工作资料数据。"</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"您尝试解锁平板电脑后失败的次数已达 <xliff:g id="NUMBER">%d</xliff:g> 次。系统将移除此工作资料,而这将删除所有的工作资料数据。"</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"您尝试解锁手机后失败的次数已达 <xliff:g id="NUMBER">%d</xliff:g> 次。系统将移除此工作资料,而这将删除所有的工作资料数据。"</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"您已 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次画错解锁图案。如果再尝试 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次后仍不成功,系统就会要求您使用自己的电子邮件帐号解锁平板电脑。\n\n请在 <xliff:g id="NUMBER_2">%3$d</xliff:g> 秒后重试。"</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"您已 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次画错解锁图案。如果再尝试 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次后仍不成功,系统就会要求您使用自己的电子邮件帐号解锁手机。\n\n请在 <xliff:g id="NUMBER_2">%3$d</xliff:g> 秒后重试。"</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-zh-rHK/strings.xml b/packages/SystemUI/res-product/values-zh-rHK/strings.xml
index 233b2454ea7a..0f78f5e21203 100644
--- a/packages/SystemUI/res-product/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res-product/values-zh-rHK/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"平板電腦中沒有 SIM 卡。"</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"手機中沒有 SIM 卡。"</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"PIN 碼不符"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"您嘗試解鎖平板電腦已失敗 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次。如果之後再嘗試 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次仍未成功,系統將重設此平板電腦,而平板電腦的所有資料亦會一併刪除。"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"您嘗試解鎖手機已失敗 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次。如果之後再嘗試 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次仍未成功,系統將重設此手機,而手機的所有資料亦會一併刪除。"</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"您嘗試解鎖平板電腦已失敗 <xliff:g id="NUMBER">%d</xliff:g> 次。系統將重設此平板電腦,而平板電腦的所有資料亦會一併刪除。"</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"您嘗試解鎖手機已失敗 <xliff:g id="NUMBER">%d</xliff:g> 次。系統將重設此手機,而手機的所有資料亦會一併刪除。"</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"您嘗試解鎖平板電腦已失敗 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次。如果之後再嘗試 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次仍未成功,系統將移除此使用者,而所有使用者資料亦會一併刪除。"</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"您嘗試解鎖手機已失敗 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次。如果之後再嘗試 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次仍未成功,系統將移除此使用者,而所有使用者資料亦會一併刪除。"</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Android TV 裝置即將關閉,按下按鈕即可保持開啟。"</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"裝置即將關閉,輕按即可保持開啟。"</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"您嘗試解鎖平板電腦已失敗 <xliff:g id="NUMBER">%d</xliff:g> 次。系統將移除此工作設定檔,而所有設定檔資料亦會一併刪除。"</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"您嘗試解鎖手機已失敗 <xliff:g id="NUMBER">%d</xliff:g> 次。系統將移除此工作設定檔,而所有設定檔資料亦會一併刪除。"</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"您已畫錯解鎖圖案 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次。如果之後再嘗試 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次仍未成功,系統會要求您透過電郵帳戶解鎖平板電腦。\n\n請在 <xliff:g id="NUMBER_2">%3$d</xliff:g> 秒後再試一次。"</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"您已畫錯解鎖圖案 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次。如果之後再嘗試 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次仍未成功,系統會要求您透過電郵帳戶解鎖手機。\n\n請在 <xliff:g id="NUMBER_2">%3$d</xliff:g> 秒後再試一次。"</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"請重新調整手機位置以使用快速充電"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"請重新調整手機位置以使用無線充電"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Android TV 裝置即將關閉,按下按鈕即可保持開啟。"</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"裝置即將關閉,輕按即可保持開啟。"</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"平板電腦中沒有 SIM 卡。"</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"手機中沒有 SIM 卡。"</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"PIN 碼不符"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"您嘗試解鎖平板電腦已失敗 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次。如果之後再嘗試 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次仍未成功,系統將重設此平板電腦,而所有平板電腦資料亦會一併刪除。"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"您嘗試解鎖手機已失敗 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次。如果之後再嘗試 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次仍未成功,系統將重設此手機,而所有手機資料亦會一併刪除。"</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"您嘗試解鎖平板電腦已失敗 <xliff:g id="NUMBER">%d</xliff:g> 次。系統將重設此平板電腦,而所有平板電腦資料亦會一併刪除。"</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"您嘗試解鎖手機已失敗 <xliff:g id="NUMBER">%d</xliff:g> 次。系統將重設此手機,而所有手機資料亦會一併刪除。"</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"您嘗試解鎖平板電腦已失敗 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次。如果之後再嘗試 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次仍未成功,系統將移除此使用者,而所有使用者資料亦會一併刪除。"</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"您嘗試解鎖手機已失敗 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次。如果之後再嘗試 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次仍未成功,系統將移除此使用者,而所有使用者資料亦會一併刪除。"</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"您嘗試解鎖平板電腦已失敗 <xliff:g id="NUMBER">%d</xliff:g> 次。系統將移除此使用者,而所有使用者資料亦會一併刪除。"</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"您嘗試解鎖手機已失敗 <xliff:g id="NUMBER">%d</xliff:g> 次。系統將移除此使用者,而所有使用者資料亦會一併刪除。"</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"您嘗試解鎖平板電腦已失敗 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次。如果之後再嘗試 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次仍未成功,系統將移除此工作設定檔,而所有設定檔資料亦會一併刪除。"</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"您嘗試解鎖手機已失敗 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次。如果之後再嘗試 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次仍未成功,系統將移除此工作設定檔,而所有設定檔資料亦會一併刪除。"</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"您嘗試解鎖平板電腦已失敗 <xliff:g id="NUMBER">%d</xliff:g> 次。系統將移除此工作設定檔,而所有設定檔資料亦會一併刪除。"</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"您嘗試解鎖手機已失敗 <xliff:g id="NUMBER">%d</xliff:g> 次。系統將移除此工作設定檔,而所有設定檔資料亦會一併刪除。"</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"您已畫錯解鎖圖案 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次。如果之後再嘗試 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次仍未成功,系統會要求您透過電郵帳戶解鎖平板電腦。\n\n請在 <xliff:g id="NUMBER_2">%3$d</xliff:g> 秒後再試一次。"</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"您已畫錯解鎖圖案 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次。如果之後再嘗試 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次仍未成功,系統會要求您透過電郵帳戶解鎖手機。\n\n請在 <xliff:g id="NUMBER_2">%3$d</xliff:g> 秒後再試一次。"</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-zh-rTW/strings.xml b/packages/SystemUI/res-product/values-zh-rTW/strings.xml
index 87e7dc430ed9..8b3b1213b0b8 100644
--- a/packages/SystemUI/res-product/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res-product/values-zh-rTW/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"平板電腦中沒有 SIM 卡。"</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"手機中沒有 SIM 卡。"</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"PIN 碼不符"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"你嘗試解鎖平板電腦已失敗 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次,目前還剩 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次機會。如果失敗次數超過限制,系統會重設這台平板電腦,其中的所有資料也會一併遭到刪除。"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"你嘗試解鎖手機已失敗 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次,目前還剩 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次機會。如果失敗次數超過限制,系統會重設這支手機,其中的所有資料也會一併遭到刪除。"</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"你嘗試解鎖平板電腦已失敗 <xliff:g id="NUMBER">%d</xliff:g> 次。系統會重設這台平板電腦,其中的所有資料也會一併遭到刪除。"</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"你嘗試解鎖手機已失敗 <xliff:g id="NUMBER">%d</xliff:g> 次。系統會重設這支手機,其中的所有資料也會一併遭到刪除。"</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"你嘗試解鎖平板電腦已失敗 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次,目前還剩 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次機會。如果失敗次數超過限制,這位使用者將遭到移除,所有相關的使用者資料也會一併遭到刪除。"</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"你嘗試解鎖手機已失敗 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次,目前還剩 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次機會。如果失敗次數超過限制,這位使用者將遭到移除,所有相關的使用者資料也會一併遭到刪除。"</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Android TV 裝置即將進入待機模式。如要讓裝置保持開啟狀態,請按下任一按鈕。"</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"裝置即將進入待機模式。如要讓裝置保持開啟狀態,請輕觸螢幕或按下按鈕。"</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"你嘗試解鎖平板電腦已失敗 <xliff:g id="NUMBER">%d</xliff:g> 次。你的工作資料夾將遭到移除,所有設定檔資料也會一併遭到刪除。"</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"你嘗試解鎖手機已失敗 <xliff:g id="NUMBER">%d</xliff:g> 次。你的工作資料夾將遭到移除,所有設定檔資料也會一併遭到刪除。"</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"你的解鎖圖案已畫錯 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次,目前還剩 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次機會。如果失敗次數超過限制,系統就會要求你透過電子郵件帳戶解鎖平板電腦。\n\n請在 <xliff:g id="NUMBER_2">%3$d</xliff:g> 秒後再試一次。"</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"你的解鎖圖案已畫錯 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次,目前還剩 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次機會。如果失敗次數超過限制,系統就會要求你透過電子郵件帳戶解鎖手機。\n\n請在 <xliff:g id="NUMBER_2">%3$d</xliff:g> 秒後再試一次。"</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"請調整手機的位置,以便提高充電效率"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"請調整手機的位置,以便進行無線充電"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Android TV 裝置即將關閉。如要讓裝置保持開啟狀態,請按下任一按鈕。"</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"裝置即將關閉。如要讓裝置保持開啟狀態,請輕觸螢幕或按下任一按鈕。"</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"平板電腦中沒有 SIM 卡。"</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"手機中沒有 SIM 卡。"</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"PIN 碼不符"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"你嘗試解鎖平板電腦已失敗 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次,目前還剩 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次機會。如果失敗次數超過限制,系統會將這部平板電腦恢復原廠設定,其中的所有資料也會一併遭到刪除。"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"你嘗試解鎖手機已失敗 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次,目前還剩 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次機會。如果失敗次數超過限制,系統會將這支手機恢復原廠設定,其中的所有資料也會一併遭到刪除。"</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"你嘗試解鎖平板電腦已失敗 <xliff:g id="NUMBER">%d</xliff:g> 次。系統會將這部平板電腦恢復原廠設定,其中的所有資料也會一併遭到刪除。"</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"你嘗試解鎖手機已失敗 <xliff:g id="NUMBER">%d</xliff:g> 次。系統會將這支手機恢復原廠設定,其中的所有資料也會一併遭到刪除。"</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"你嘗試解鎖平板電腦已失敗 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次,目前還剩 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次機會。如果失敗次數超過限制,這位使用者將遭到移除,所有相關的使用者資料也會一併遭到刪除。"</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"你嘗試解鎖手機已失敗 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次,目前還剩 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次機會。如果失敗次數超過限制,這位使用者將遭到移除,所有相關的使用者資料也會一併遭到刪除。"</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"你嘗試解鎖平板電腦已失敗 <xliff:g id="NUMBER">%d</xliff:g> 次。這位使用者將遭到移除,所有相關的使用者資料也會一併遭到刪除。"</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"你嘗試解鎖手機已失敗 <xliff:g id="NUMBER">%d</xliff:g> 次。這位使用者將遭到移除,所有相關的使用者資料也會一併遭到刪除。"</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"你嘗試解鎖平板電腦已失敗 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次,目前還剩 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次機會。如果失敗次數超過限制,你的工作資料夾將遭到移除,所有設定檔資料也會一併遭到刪除。"</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"你嘗試解鎖手機已失敗 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次,目前還剩 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次機會。如果失敗次數超過限制,你的工作資料夾將遭到移除,所有設定檔資料也會一併遭到刪除。"</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"你嘗試解鎖平板電腦已失敗 <xliff:g id="NUMBER">%d</xliff:g> 次。你的工作資料夾將遭到移除,所有設定檔資料也會一併遭到刪除。"</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"你嘗試解鎖手機已失敗 <xliff:g id="NUMBER">%d</xliff:g> 次。你的工作資料夾將遭到移除,所有設定檔資料也會一併遭到刪除。"</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"你的解鎖圖案已畫錯 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次,目前還剩 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次機會。如果失敗次數超過限制,系統會要求你透過電子郵件帳戶將平板電腦解鎖。\n\n請在 <xliff:g id="NUMBER_2">%3$d</xliff:g> 秒後再試一次。"</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"你的解鎖圖案已畫錯 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次,目前還剩 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次機會。如果失敗次數超過限制,系統會要求你透過電子郵件帳戶將手機解鎖。\n\n請在 <xliff:g id="NUMBER_2">%3$d</xliff:g> 秒後再試一次。"</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-zu/strings.xml b/packages/SystemUI/res-product/values-zu/strings.xml
index 2c8728b6370a..b80ec5a17d21 100644
--- a/packages/SystemUI/res-product/values-zu/strings.xml
+++ b/packages/SystemUI/res-product/values-zu/strings.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?><!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
@@ -15,42 +16,28 @@
* limitations under the License.
*/
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <string name="keyguard_missing_sim_message" product="tablet" msgid="3088787847082615459">"Alikho ikhadi le-SIM efonini."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="5124049236681993063">"Alikho ikhadi le-SIM efonini."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="1500814146841660886">"Iphinikhodi ayifani"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="2445671146665131857">"Uzame ngokungalungile ukuvula ithebulethi izikhathi ezingu-<xliff:g id="NUMBER_0">%1$d</xliff:g>. Ngemuva kwemizamo engaphezulu kwengu-<xliff:g id="NUMBER_1">%2$d</xliff:g> engaphumelelanga, le thebulethi izosethwa kabusha, okuzosusa yonke idatha yayo."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4738318327984389472">"Uzame ngokungalungile ukuvula ifoni izikhathi ezingu-<xliff:g id="NUMBER_0">%1$d</xliff:g>. Ngemuva kwemizamo engaphezulu kwengu-<xliff:g id="NUMBER_1">%2$d</xliff:g> engaphumelelanga, le foni izosethwa kabusha, okuzosusa yonke idatha yayo."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="6974065787881197466">"Uzame ngokungalungile ukuvula ithebulethi izikhathi ezingu-<xliff:g id="NUMBER">%d</xliff:g>. Le thebulethi izosethwa kabusha, okuzosusa yonke idatha yayo."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="4645797157486540692">"Uzame ngokungalungile ukuvula ifoni izikhathi ezingu-<xliff:g id="NUMBER">%d</xliff:g>. Le foni izosethwa kabusha, okuzosusa yonke idatha yayo."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="2444432908572039632">"Uzame ngokungalungile ukuvula ithebulethi izikhathi ezingu-<xliff:g id="NUMBER_0">%1$d</xliff:g>. Ngemuva kwemizamo engaphezulu kwengu-<xliff:g id="NUMBER_1">%2$d</xliff:g> engaphumelelanga, lo msebenzisi uzosuswa, okuzosusa yonke idatha yomsebenzisi."</string>
- <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="3230300995829296824">"Uzame ngokungalungile ukuvula ifoni izikhathi ezingu-<xliff:g id="NUMBER_0">%1$d</xliff:g>. Ngemuva kwemizamo engaphezulu kwengu-<xliff:g id="NUMBER_1">%2$d</xliff:g> engaphumelelanga, lo msebenzisi uzosuswa, okuzosusa yonke idatha yomsebenzisi."</string>
- <!-- no translation found for kg_failed_attempts_now_erasing_user (9046628517316763961) -->
- <skip/>
- <!-- no translation found for cancel (1089011503403416730) -->
- <!-- no translation found for kg_failed_attempts_now_erasing_user (3588779327358321092) -->
- <skip/>
- <!-- no translation found for accessibility_casting (8708751252897282313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (6114158710353725041) -->
- <skip/>
- <!-- no translation found for accessibility_work_mode (1280025758672376313) -->
- <!-- no translation found for kg_failed_attempts_almost_at_erase_profile (8345451368768804892) -->
- <skip/>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip/>
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip/>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip/>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip/>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip/>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6017523991455860482">"Idivayisi ye-Android TV maduze izovalwa, cindezela inkinobho ukuze uyigcine ivuliwe."</string>
- <string name="inattentive_sleep_warning_message" product="default" msgid="4866963937818527643">"Idivayisi maduze izovalwa, cindezela ukuze uyigcine ivuliwe."</string>
-<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="9063715142119087685">"Uzame ngokungalungile ukuvula ithebulethi izikhathi ezingu-<xliff:g id="NUMBER">%d</xliff:g>. Iphrofayela yomsebenzi izosuswa, okuzosusa yonke idatha yephrofayela."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="105463960684230996">"Uzame ngokungalungile ukuvula ifoni izikhathi ezingu-<xliff:g id="NUMBER">%d</xliff:g>. Iphrofayela yomsebenzi izosuswa, okuzosusa yonke idatha yephrofayela."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="5123792377735688284">"Udwebe ngokungalungile iphethini yakho yokuvula ngezikhathi ezingu-<xliff:g id="NUMBER_0">%1$d</xliff:g>. Ngemuva kwemizamo engaphumelelanga kaningi engu-<xliff:g id="NUMBER_1">%2$d</xliff:g>, uzocelwa ukuthi uvule ithebulethi yakho usebenzisa i-akhawunti ye-imeyili.\n\nZama futhi kumasekhondi angu-<xliff:g id="NUMBER_2">%3$d</xliff:g>."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="3307854957632348753">"Ukulayisha ungenisa iphathini yakho yokuvula ngendlela engalungile izikhathi ezi-<xliff:g id="NUMBER_0">%1$d</xliff:g> Emva kweminye imizamo engu-<xliff:g id="NUMBER_1">%2$d</xliff:g>, uzocelwa ukuvula ifoni yakho usebenzisa ukungena ngemvume ku-Google\n\n Zame futhi emumva kwengu- <xliff:g id="NUMBER_2">%3$d</xliff:g> imizuzwana."</string>
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Ukwenza ifoni ishaje ngokushesha"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Ukwenza ifoni ishaje ngokungaxhunyiwe"</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Idivayisi ye-Android TV maduze izovalwa, cindezela inkinobho ukuze uyigcine ivuliwe."</string>
+ <string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Idivayisi maduze izovalwa, cindezela ukuze uyigcine ivuliwe."</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Alikho ikhadi le-SIM efonini."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Alikho ikhadi le-SIM efonini."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"Iphinikhodi ayifani"</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Uzame ngokungalungile ukuvula ithebulethi izikhathi ezingu-<xliff:g id="NUMBER_0">%1$d</xliff:g>. Ngemuva kwemizamo engaphezulu kwengu-<xliff:g id="NUMBER_1">%2$d</xliff:g> engaphumelelanga, le thebulethi izosethwa kabusha, okuzosusa yonke idatha yayo."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Uzame ngokungalungile ukuvula ifoni izikhathi ezingu-<xliff:g id="NUMBER_0">%1$d</xliff:g>. Ngemuva kwemizamo engaphezulu kwengu-<xliff:g id="NUMBER_1">%2$d</xliff:g> engaphumelelanga, le foni izosethwa kabusha, okuzosusa yonke idatha yayo."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Uzame ngokungalungile ukuvula ithebulethi izikhathi ezingu-<xliff:g id="NUMBER">%d</xliff:g>. Le thebulethi izosethwa kabusha, okuzosusa yonke idatha yayo."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Uzame ngokungalungile ukuvula ifoni izikhathi ezingu-<xliff:g id="NUMBER">%d</xliff:g>. Le foni izosethwa kabusha, okuzosusa yonke idatha yayo."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Uzame ngokungalungile ukuvula ithebulethi izikhathi ezingu-<xliff:g id="NUMBER_0">%1$d</xliff:g>. Ngemuva kwemizamo engaphezulu kwengu-<xliff:g id="NUMBER_1">%2$d</xliff:g> engaphumelelanga, lo msebenzisi uzosuswa, okuzosusa yonke idatha yomsebenzisi."</string>
+ <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Uzame ngokungalungile ukuvula ifoni izikhathi ezingu-<xliff:g id="NUMBER_0">%1$d</xliff:g>. Ngemuva kwemizamo engaphezulu kwengu-<xliff:g id="NUMBER_1">%2$d</xliff:g> engaphumelelanga, lo msebenzisi uzosuswa, okuzosusa yonke idatha yomsebenzisi."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Uzame ngokungalungile ukuvula ithebulethi izikhathi ezingu-<xliff:g id="NUMBER">%d</xliff:g>. Lo msebenzisi uzosuswa, okuzosusa yonke idatha yomsebenzisi."</string>
+ <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Uzame ngokungalungile ukuvula ifoni izikhathi ezingu-<xliff:g id="NUMBER">%d</xliff:g>. Lo msebenzisi uzosuswa, okuzosusa yonke idatha yomsebenzisi."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Uzame ngokungalungile ukuvula ithebulethi izikhathi ezingu-<xliff:g id="NUMBER_0">%1$d</xliff:g>. Ngemuva kwemizamo engaphezulu kwengu-<xliff:g id="NUMBER_1">%2$d</xliff:g> engaphumelelanga, iphrofayela yomsebenzi izosuswa, okuzosusa yonke idatha yephrofayela."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Uzame ngokungalungile ukuvula ifoni izikhathi ezingu-<xliff:g id="NUMBER_0">%1$d</xliff:g>. Ngemuva kwemizamo engaphezulu kwengu-<xliff:g id="NUMBER_1">%2$d</xliff:g> engaphumelelanga, iphrofayela yomsebenzi, izosuswa, okuzosusa yonke idatha yephrofayela."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Uzame ngokungalungile ukuvula ithebulethi izikhathi ezingu-<xliff:g id="NUMBER">%d</xliff:g>. Iphrofayela yomsebenzi izosuswa, okuzosusa yonke idatha yephrofayela."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Uzame ngokungalungile ukuvula ifoni izikhathi ezingu-<xliff:g id="NUMBER">%d</xliff:g>. Iphrofayela yomsebenzi izosuswa, okuzosusa yonke idatha yephrofayela."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Udwebe ngokungalungile iphethini yakho yokuvula ngezikhathi ezingu-<xliff:g id="NUMBER_0">%1$d</xliff:g>. Ngemuva kwemizamo engaphumelelanga kaningi engu-<xliff:g id="NUMBER_1">%2$d</xliff:g>, uzocelwa ukuthi uvule ithebulethi yakho usebenzisa i-akhawunti ye-imeyili.\n\nZama futhi kumasekhondi angu-<xliff:g id="NUMBER_2">%3$d</xliff:g>."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Ukulayisha ungenisa iphathini yakho yokuvula ngendlela engalungile izikhathi ezi-<xliff:g id="NUMBER_0">%1$d</xliff:g> Emva kweminye imizamo engu-<xliff:g id="NUMBER_1">%2$d</xliff:g>, uzocelwa ukuvula ifoni yakho usebenzisa ukungena ngemvume ku-Google\n\n Zame futhi emumva kwengu- <xliff:g id="NUMBER_2">%3$d</xliff:g> imizuzwana."</string>
</resources>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 8f64aab3eca6..08be42a74637 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Kom meer te wete"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Zoem om skerm te vul"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Strek om skerm te vul"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Skermkiekie"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Stoor tans skermkiekie..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Stoor tans skermkiekie..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Skermkiekie is gestoor"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"maak foon oop"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"maak stembystand oop"</string>
<string name="camera_label" msgid="8253821920931143699">"maak kamera oop"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Kanselleer"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Bevestig"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Probeer weer"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Tik om stawing te kanselleer"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Aan om <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Tot <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Donker-tema"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Donker-tema\nBatterybespaarder"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Batterybespaarder"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Aan met sonsondergang"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Tot sonsopkoms"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC is gedeaktiveer"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC is geaktiveer"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Tik weer om oop te maak"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Swiep op om oop te maak"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Swiep op om weer te probeer"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Jou organisasie bestuur hierdie toestel"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Hierdie toestel word deur <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> bestuur"</string>
<string name="phone_hint" msgid="6682125338461375925">"Swiep vanaf ikoon vir foon"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Batterybespaarder is aan"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Verminder werkverrigting en agtergronddata"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Skakel Batterybespaarder af"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Terwyl dit opneem of uitsaai, kan <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> enige sensitiewe inligting vasvang wat op jou skerm gewys word of op jou toestel gespeel word, insluitend sensitiewe inligting soos oudio, wagwoorde, betaalinligting, foto\'s en boodskappe."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Terwyl dit opneem of uitsaai, kan die diens wat hierdie taak uitvoer enige sensitiewe inligting vasvang wat op jou skerm gewys word of op jou toestel gespeel word, insluitend sensitiewe inligting soos oudio, wagwoorde, betaalinligting, foto\'s en boodskappe."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Bekendmaking van sensitiewe inligting tydens uitsending/opname"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> sal toegang hê tot al die inligting wat op jou skerm sigbaar is of wat op jou toestel gespeel word terwyl dit opneem of uitsaai. Dit sluit in inligting soos wagwoorde, betalingbesonderhede, foto\'s, boodskappe en oudio wat jy speel."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Die diens wat hierdie funksie verskaf, sal toegang hê tot al die inligting wat op jou skerm sigbaar is of wat op jou toestel gespeel word terwyl dit opneem of uitsaai. Dit sluit in inligting soos wagwoorde, betalingbesonderhede, foto\'s, boodskappe en oudio wat jy speel."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Begin opneem of uitsaai met <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Moenie weer wys nie"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Vee alles uit"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Bestuur"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Sleutelbordwisselaar"</string>
<string name="save" msgid="3392754183673848006">"Stoor"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Stel terug"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Verstel knoppiebreedte"</string>
<string name="clipboard" msgid="8517342737534284617">"Knipbord"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Gepasmaakte navigasieknoppie"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Regs"</string>
<string name="tuner_menu" msgid="363690665924769420">"Kieslys"</string>
<string name="tuner_app" msgid="6949280415826686972">"<xliff:g id="APP">%1$s</xliff:g>-program"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Opletberigte"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Battery"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Skermkiekies"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Algemene boodskappe"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> loop tans"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Program is oopgemaak sonder dat dit geïnstalleer is."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Program is oopgemaak sonder dat dit geïnstalleer is. Tik om meer te wete te kom."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Programinligting"</string>
<string name="go_to_web" msgid="636673528981366511">"Gaan na blaaier"</string>
<string name="mobile_data" msgid="4564407557775397216">"Mobiele data"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Instellings"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Het dit"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Stort SysUI-hoop"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> gebruik tans jou <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Programme gebruik tans jou <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" en "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"ligging"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofoon"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensors is af"</string>
<string name="device_services" msgid="1549944177856658705">"Toesteldienste"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Titelloos"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Stelselnavigasie is opgedateer. Gaan na Instellings toe om veranderinge te maak."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Gaan na Instellings toe om stelselnavigasie op te dateer"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Bystandmodus"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Vergrotingoorleggervenster"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Vergrotingvenster"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Vergrotingvensterkontroles"</string>
</resources>
diff --git a/packages/SystemUI/res/values-af/strings_tv.xml b/packages/SystemUI/res/values-af/strings_tv.xml
index 5e078a2393b8..2ea6c60ab1b8 100644
--- a/packages/SystemUI/res/values-af/strings_tv.xml
+++ b/packages/SystemUI/res/values-af/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Titellose program)"</string>
<string name="pip_close" msgid="5775212044472849930">"Maak PIP toe"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Volskerm"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Mikrofoon aktief"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s het toegang tot jou mikrofoon"</string>
</resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index d73c0ed17f3c..18a4a7a6737f 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"የበለጠ መረዳት"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"ማያ እንዲሞላ አጉላ"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"ማያ ለመሙለት ሳብ"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"ቅጽበታዊ ገጽ እይታ"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"ቅጽበታዊ ገጽ እይታ በማስቀመጥ ላይ..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"ቅጽበታዊ ገጽ እይታ በማስቀመጥ ላይ..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"ቅጽበታዊ ገጽ እይታ ተቀምጧል"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"ስልክ ክፈት"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"የድምጽ ረዳትን ክፈት"</string>
<string name="camera_label" msgid="8253821920931143699">"ካሜራ ክፈት"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"ይቅር"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"አረጋግጥ"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"እንደገና ይሞክሩ"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"ማረጋገጥን ለመሰረዝ መታ ያድርጉ"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"<xliff:g id="TIME">%s</xliff:g> ላይ ይበራል"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"እስከ <xliff:g id="TIME">%s</xliff:g> ድረስ"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"ጨለማ ገጽታ"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"ጨለም ያለ ገጽታ\nየባትሪ ቆጣቢ"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"ባትሪ ቆጣቢ"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"ጸሐይ ስትጠልቅ ይበራል"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"ጸሐይ እስክትወጣ ድረስ"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"ኤንኤፍሲ"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"ኤንኤፍሲ ተሰናክሏል"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"ኤንኤፍሲ ነቅቷል"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"ለመክፈት ዳግም መታ ያድርጉ"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"ለመክፈት በጣት ወደ ላይ ጠረግ ያድርጉ"</string>
<string name="keyguard_retry" msgid="886802522584053523">"እንደገና ለመሞከር ወደ ላይ ይጥረጉ"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"ይህ መሣሪያ በእርስዎ ድርጅት የሚተዳደር ነው"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"ይህ መሣሪያ በ<xliff:g id="ORGANIZATION_NAME">%s</xliff:g> የሚተዳደር ነው"</string>
<string name="phone_hint" msgid="6682125338461375925">"ለስልክ ከአዶ ላይ ጠረግ ያድርጉ"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"ባትሪ ቆጣቢ በርቷል"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"አፈጻጸምን እና የጀርባ ውሂብ ይቀንሳል"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"ባትሪ ቆጣቢን አጥፋ"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"እየቀረጸ ወይም cast እያደረገ ሳለ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> እንደ ኦዲዮ፣ የይለፍ ቃላት፣ የክፍያ መረጃ፣ ፎቶዎች እና መልዕክቶች ያለ ሚስጥራዊነት ያለው መረጃ ጨምሮ በማያ ገጽዎ ላይ የሚታይ ወይም ከመሣሪያዎ የተጫወተ ማንኛውም ሚስጥራዊነት ያለው መረጃ ሊይዝ ይችላል።"</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"እየቀረጸ ወይም cast እያደረገ ሳለ ይህን ተግባር የሚያቀርበው አገልግሎት እንደ ኦዲዮ፣ የይለፍ ቃላት፣ የክፍያ መረጃ፣ ፎቶዎች እና መልዕክቶች ያለ ሚስጥራዊነት ያለው መረጃ ጨምሮ በማያ ገጽዎ ላይ የሚታይ ወይም ከመሣሪያዎ የተጫወተ ማንኛውም ሚስጥራዊነት ያለው መረጃ ሊይዝ ይችላል።"</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"በመውሰድ/ ቀረጻ ላይ አደገኛ መረጃን አጋልጦ በመስጠት ላይ"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> በእርስዎ ማያ ገጽ ላይ ያለን ወይም በእርስዎ መሣሪያ ላይ በመጫወት ላይ ያለን ሁሉንም መረጃ በቀረጻ ወይም casting ላይ እያለ መዳረሻ ይኖረዋል። ይህ እንደ የይለፍ ቃላት፣ የክፍያ ዝርዝሮች፣ ፎቶዎች፣ መልዕክቶች እና እርስዎ የሚጫውቱት ኦዲዮን የመሳሰለ መረጃን ያካትታል።"</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"ይህን ተግባር የሚያቀርበው አገልግሎት በእርስዎ ማያ ገጽ ላይ ያለን ወይም በእርስዎ መሣሪያ ላይ በመጫወት ላይ ያለን ሁሉንም መረጃ በቀረጻ ወይም casting ላይ እያለ መዳረሻ ይኖረዋል። ይህ እንደ የይለፍ ቃላት፣ የክፍያ ዝርዝሮች፣ ፎቶዎች፣ መልዕክቶች እና እርስዎ የሚጫውቱት ኦዲዮን የመሳሰለ መረጃን ያካትታል።"</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"ከ<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ጋር ቀረጻ ወይም casting ይጀምር?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"ዳግመኛ አታሳይ"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"ሁሉንም አጽዳ"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"ያቀናብሩ"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"የቁልፍ ሰሌዳ መቀየሪያ"</string>
<string name="save" msgid="3392754183673848006">"አስቀምጥ"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"ዳግም አስጀምር"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"የአዝራር ስፋት አስተካክል"</string>
<string name="clipboard" msgid="8517342737534284617">"የቅንጥብ ሰሌዳ"</string>
<string name="accessibility_key" msgid="3471162841552818281">"ብጁ የአሰሳ አዝራር"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"ቀኝ"</string>
<string name="tuner_menu" msgid="363690665924769420">"ምናሌ"</string>
<string name="tuner_app" msgid="6949280415826686972">"የ<xliff:g id="APP">%1$s</xliff:g> መተግበሪያ"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"ማንቂያዎች"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"ባትሪ"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"ቅጽበታዊ ገጽ እይታዎች"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"አጠቃላይ መልዕክቶች"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> አሂድ"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"መተግበሪያ ሳይጫን ተከፍቷል።"</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"መተግበሪያ ሳይጫን ተከፍቷል። ተጨማሪ ለማወቅ መታ ያድርጉ።"</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"የመተግበሪያ መረጃ"</string>
<string name="go_to_web" msgid="636673528981366511">"ወደ አሳሽ ሂድ"</string>
<string name="mobile_data" msgid="4564407557775397216">"የተንቀሳቃሽ ስልክ ውሂብ"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g>— <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"ቅንብሮች"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"ገባኝ"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"SysUI Heap አራግፍ"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> የእርስዎን <xliff:g id="TYPES_LIST">%2$s</xliff:g> እየተጠቀመ ነው።"</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"መተግበሪያዎች የእርስዎን <xliff:g id="TYPES_LIST">%s</xliff:g> እየተጠቀሙ ነው።"</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">"፣ "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" እና "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"ካሜራ"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"አካባቢ"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"ማይክሮፎን"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"ዳሳሾች ጠፍተዋል"</string>
<string name="device_services" msgid="1549944177856658705">"የመሣሪያ አገልግሎቶች"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"ርዕስ የለም"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"የስርዓት ዳሰሳ ተዘምኗል። ለውጦችን ለማድረግ ወደ ቅንብሮች ይሂዱ።"</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"የስርዓት ዳሰሳን ለማዘመን ወደ ቅንብሮች ይሂዱ"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"ተጠባባቂ"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"የማጉያ ንብርብር መስኮት"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"የማጉያ መስኮት"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"የማጉያ መስኮት መቆጣጠሪያዎች"</string>
</resources>
diff --git a/packages/SystemUI/res/values-am/strings_tv.xml b/packages/SystemUI/res/values-am/strings_tv.xml
index 591032344bc0..83e3fd9f539f 100644
--- a/packages/SystemUI/res/values-am/strings_tv.xml
+++ b/packages/SystemUI/res/values-am/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(ርዕስ የሌለው ፕሮግራም)"</string>
<string name="pip_close" msgid="5775212044472849930">"PIPን ዝጋ"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"ሙሉ ማያ ገጽ"</string>
+ <string name="mic_active" msgid="5766614241012047024">"ማይክራፎን ንቁ ነው"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s የእርስዎን ማይክራፎን ደርሶበታል"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 68fe91ce4ed3..07be692b5a23 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"مزيد من المعلومات"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"تكبير/تصغير لملء الشاشة"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"توسيع بملء الشاشة"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"لقطة شاشة"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"جارٍ حفظ لقطة الشاشة..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"جارٍ حفظ لقطة الشاشة..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"تم حفظ لقطة الشاشة."</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"فتح الهاتف"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"فتح المساعد الصوتي"</string>
<string name="camera_label" msgid="8253821920931143699">"فتح الكاميرا"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"إلغاء"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"تأكيد"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"إعادة المحاولة"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"انقر لإلغاء المصادقة."</string>
@@ -395,7 +393,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"تفعيل الإعداد في <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"حتى <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"مظهر داكن"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"مظهر داكن\nتوفير شحن البطارية"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"توفير شحن البطارية"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"تفعيل عند غروب الشمس"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"حتى شروق الشمس"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"‏الاتصالات قصيرة المدى (NFC)"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"تم إيقاف الاتصال القريب المدى"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"تم تفعيل الاتصال القريب المدى"</string>
@@ -420,10 +420,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"انقر مرة أخرى للفتح"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"يمكنك الفتح بالتمرير سريعًا لأعلى."</string>
<string name="keyguard_retry" msgid="886802522584053523">"مرِّر سريعًا للأعلى لإعادة المحاولة."</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"تتولى مؤسستك إدارة هذا الجهاز."</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"تتم إدارة هذا الجهاز بواسطة <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"يمكنك التمرير سريعًا من الرمز لتشغيل الهاتف"</string>
@@ -479,9 +475,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"تم تفعيل ميزة توفير شحن البطارية"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"لخفض مستوى الأداء وبيانات الخلفية"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"إيقاف ميزة توفير شحن البطارية"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"أثناء التسجيل أو البث، يمكن لتطبيق <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> تسجيل أي معلومات حسّاسة يتم عرضها على الشاشة أو تشغيلها من جهازك، بما فيها المعلومات الحسّاسة مثل المقاطع الصوتية وكلمات المرور ومعلومات الدفع والصور والرسائل."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"أثناء التسجيل أو الإرسال، يمكن للخدمة التي تقدّم هذه الوظيفة تسجيل أي معلومات حساسة يتم عرضها على الشاشة أو تشغيلها من جهازك، بما فيها المعلومات الحساسة مثل الصوت الذي تشغّله وكلمات المرور ومعلومات الدفع والصور والرسائل."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"عرض معلومات حسّاسة أثناء الإرسال/التسجيل"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"سيتمكن تطبيق <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> من الوصول إلى كل المعلومات المرئية لك على الشاشة أو التي يتم تشغيلها على جهازك أثناء التسجيل أو الإرسال. ويشمل ذلك معلومات مثل كلمات المرور وتفاصيل الدفع والصور والرسائل والمقاطع الصوتية التي تشغِّلها."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"ستتمكن الخدمة التي تقدّم هذه الوظيفة من الوصول إلى كل المعلومات المرئية لك على الشاشة أو التي يتم تشغيلها على جهازك أثناء التسجيل أو الإرسال. ويشمل ذلك معلومات مثل كلمات المرور وتفاصيل الدفع والصور والرسائل والمقاطع الصوتية التي تشغِّلها."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"هل تريد بدء التسجيل أو الإرسال باستخدام <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>؟"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"عدم الإظهار مرة أخرى"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"محو الكل"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"إدارة"</string>
@@ -806,8 +804,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"مفتاح تبديل لوحة المفاتيح"</string>
<string name="save" msgid="3392754183673848006">"حفظ"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"إعادة الضبط"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"ضبط عرض الزر"</string>
<string name="clipboard" msgid="8517342737534284617">"الحافظة"</string>
<string name="accessibility_key" msgid="3471162841552818281">"زر التنقل المخصص"</string>
@@ -903,8 +900,7 @@
<string name="tuner_right" msgid="8247571132790812149">"يمين"</string>
<string name="tuner_menu" msgid="363690665924769420">"القائمة"</string>
<string name="tuner_app" msgid="6949280415826686972">"تطبيق <xliff:g id="APP">%1$s</xliff:g>"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"التنبيهات"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"البطارية"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"لقطات الشاشة"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"رسائل عامة"</string>
@@ -914,8 +910,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"التطبيق <xliff:g id="APP">%1$s</xliff:g> قيد التشغيل"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"تمّ فتح التطبيق بدون تثبيته."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"تمّ فتح التطبيق بدون تثبيته. انقر لمعرفة مزيد من المعلومات."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"معلومات التطبيق"</string>
<string name="go_to_web" msgid="636673528981366511">"الانتقال إلى المتصفح"</string>
<string name="mobile_data" msgid="4564407557775397216">"بيانات الجوّال"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -949,13 +944,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"الإعدادات"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"حسنًا"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"‏تفريغ ذاكرة SysUI"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"التطبيق <xliff:g id="APP">%1$s</xliff:g> يستخدم <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"تستخدم التطبيقات <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">"، "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" و "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"الكاميرا"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"الموقع"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"الميكروفون"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"إيقاف أجهزة الاستشعار"</string>
<string name="device_services" msgid="1549944177856658705">"خدمات الأجهزة"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"بلا عنوان"</string>
@@ -978,4 +966,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"تم تحديث التنقل داخل النظام. لإجراء التغييرات، يُرجى الانتقال إلى \"الإعدادات\"."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"الانتقال إلى \"الإعدادات\" لتعديل التنقل داخل النظام"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"وضع الاستعداد"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"نافذة تراكب التكبير"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"نافذة التكبير"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"عناصر التحكم في نافذة التكبير"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ar/strings_tv.xml b/packages/SystemUI/res/values-ar/strings_tv.xml
index aeb1e437606e..4b5005539c93 100644
--- a/packages/SystemUI/res/values-ar/strings_tv.xml
+++ b/packages/SystemUI/res/values-ar/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(ليس هناك عنوان للبرنامج)"</string>
<string name="pip_close" msgid="5775212044472849930">"‏إغلاق PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"ملء الشاشة"</string>
+ <string name="mic_active" msgid="5766614241012047024">"الميكروفون نشط"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"‏تمكن %1$s من الوصول إلى الميكروفون الخاص بك."</string>
</resources>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index b55f4197f6a5..d8a7b26a4aff 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"অধিক জানক"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"স্ক্ৰীণ পূর্ণ কৰিবলৈ জুম কৰক"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"স্ক্ৰীণ পূর্ণ কৰিবলৈ প্ৰসাৰিত কৰক"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"স্ক্ৰীনশ্বট"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"স্ক্ৰীণশ্বট ছেভ কৰি থকা হৈছে…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"স্ক্ৰীণশ্বট ছেভ কৰি থকা হৈছে…"</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"স্ক্ৰীণশ্বট ছেভ কৰা হ’ল"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"ফ\'ন খোলক"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"কণ্ঠধ্বনিৰে সহায় খোলক"</string>
<string name="camera_label" msgid="8253821920931143699">"কেমেৰা খোলক"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"বাতিল কৰক"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"নিশ্চিত কৰক"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"আকৌ চেষ্টা কৰক"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"বিশ্বাসযোগ্যতা প্ৰমাণীকৰণ বাতিল কৰিবলৈ টিপক"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"<xliff:g id="TIME">%s</xliff:g>ত অন কৰক"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g> পৰ্যন্ত"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"গাঢ় ৰঙৰ থীম"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"গাঢ় ৰঙৰ থীম\nবেটাৰী সঞ্চয়কাৰী"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"বেটাৰী সঞ্চয়কাৰী"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"সূৰ্যাস্তত অন হয়"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"সূৰ্যোদয়লৈকে"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC নিষ্ক্ৰিয় হৈ আছে"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC সক্ষম হৈ আছে"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"খুলিবলৈ পুনৰাই টিপক"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"খুলিবলৈ ওপৰলৈ ছোৱাইপ কৰক"</string>
<string name="keyguard_retry" msgid="886802522584053523">"পুনৰ চেষ্টা কৰিবলৈ ওপৰলৈ ছোৱাইপ কৰক"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"আপোনাৰ প্ৰতিষ্ঠানে এই ডিভাইচটো পৰিচালনা কৰে"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"এই ডিভাইচটো <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>ৰ দ্বাৰা পৰিচালিত।"</string>
<string name="phone_hint" msgid="6682125338461375925">"ফ\'নৰ বাবে আইকনৰপৰা ছোৱাইপ কৰক"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"বেটাৰি সঞ্চয়কাৰী অন হৈ আছে"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"কাৰ্যদক্ষতা আৰু নেপথ্য ডেটা হ্ৰাস কৰে"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"বেটাৰি সঞ্চয়কাৰী অফ কৰক"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"ৰেকৰ্ড বা কাষ্ট কৰি থাকোঁতে <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>এ অডিঅ’, পাছৱৰ্ডসমূহ, পৰিশোধৰ তথ্য, ফট’সমূহ আৰু বাৰ্তাসমূহকে ধৰি আপোনাৰ স্ক্রীণত দেখুওৱা বা আপোনাৰ ডিভাইচৰ পৰা প্লে’ কৰা যিকোনো সংবেনদশীল তথ্য কেপচ্চাৰ কৰিব পাৰে।"</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"ৰেকৰ্ড বা কাষ্ট কৰি থাকোঁতে এই কাৰ্যকাৰিতাটো প্ৰদান কৰি থকা সেৱাটোৱে অডিঅ’, পাছৱৰ্ডসমূহ, পৰিশোধৰ তথ্য, ফট’সমূহ আৰু বাৰ্তাসমূহকে ধৰি আপোনাৰ স্ক্রীণত দেখুওৱা বা আপোনাৰ ডিভাইচৰ পৰা প্লে’ কৰা যিকোনো সংবেনদশীল তথ্য কেপচ্চাৰ কৰিব পাৰে।"</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"কাষ্টিং/ৰেকৰ্ডিঙৰ সময়ত স্পৰ্শকাতৰ তথ্য দেখুওৱা হৈছে"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>এ আপোনাৰ স্ক্ৰীনত দৃশ্যমান হোৱা অথবা ৰেকর্ডিং অথবা কাষ্টিংৰ সময়ত আপোনাৰ ডিভাইচত প্লে\' কৰা সকলো তথ্যলৈ এক্সেছ পাব। এইটোত পাছৱর্ড, পৰিশোধৰ সবিশেষ, ফট\', বার্তাসমূহ আৰু আপুনি প্লে\' কৰা অডিঅ\'ৰ দৰে তথ্য অন্তর্ভুক্ত হয়।"</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"এই সুবিধাটো প্ৰদান কৰা সেৱাটোৱে আপোনাৰ স্ক্ৰীনত দৃশ্যমান হোৱা অথবা ৰেকর্ডিং অথবা কাষ্টিংৰ সময়ত আপোনাৰ ডিভাইচত প্লে\' কৰা সকলো তথ্যলৈ এক্সেছ পাব। এইটোত পাছৱর্ড, পৰিশোধৰ সবিশেষ, ফট\', বার্তাসমূহ আৰু আপুনি প্লে\' কৰা অডিঅ\'ৰ দৰে তথ্য অন্তর্ভুক্ত হয়।"</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>ৰ জৰিয়তে ৰেকর্ডিং অথবা কাষ্টিং আৰম্ভ কৰিবনে ?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"পুনৰাই নেদেখুৱাব"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"সকলো মচক"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"পৰিচালনা"</string>
@@ -667,12 +665,10 @@
<string name="inline_keep_showing_app" msgid="4393429060390649757">"এই এপটোৰ জাননী দেখুওৱাই থাকিব লাগিবনে?"</string>
<string name="notification_silence_title" msgid="8608090968400832335">"নীৰৱ"</string>
<string name="notification_alert_title" msgid="7629202599338071971">"সতৰ্ক কৰক"</string>
- <!-- no translation found for notification_bubble_title (8330481035191903164) -->
- <skip />
+ <string name="notification_bubble_title" msgid="8330481035191903164">"বাবল"</string>
<string name="notification_channel_summary_low" msgid="7300447764759926720">"কোনো ধ্বনি অথবা কম্পন অবিহনে আপোনাক মনোযোগ দিয়াত সহায় কৰে।"</string>
<string name="notification_channel_summary_default" msgid="3539949463907902037">"ধ্বনি অথবা কম্পনৰ জৰিয়তে আপোনাৰ মনোযোগ আকৰ্ষণ কৰে।"</string>
- <!-- no translation found for notification_channel_summary_bubble (7235935211580860537) -->
- <skip />
+ <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"উপঙি থকা এটা শ্বৰ্টকাটৰ জৰিয়তে এই সমলখিনিৰ প্ৰতি আপোনাক মনোযোগী কৰি ৰাখে।"</string>
<string name="notification_unblockable_desc" msgid="2073030886006190804">"এই জাননীসমূহ সংশোধন কৰিব নোৱাৰি।"</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"এই ধৰণৰ জাননীবোৰ ইয়াত কনফিগাৰ কৰিব পৰা নাযায়"</string>
<string name="notification_delegate_header" msgid="1264510071031479920">"প্ৰক্সি হিচাপে পঠিওৱা জাননী"</string>
@@ -788,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"কীব\'ৰ্ড সলনি কৰাৰ সুবিধা"</string>
<string name="save" msgid="3392754183673848006">"ছেভ কৰক"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"ৰিছেট কৰক"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"বুটামৰ প্ৰস্থ খাপ খুৱাওক"</string>
<string name="clipboard" msgid="8517342737534284617">"ক্লিপব\'ৰ্ড"</string>
<string name="accessibility_key" msgid="3471162841552818281">"উপযোগিতা অনুসৰি তৈয়াৰ কৰা নেভিগেশ্বনৰ বুটাম"</string>
@@ -885,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"সোঁ"</string>
<string name="tuner_menu" msgid="363690665924769420">"মেনু"</string>
<string name="tuner_app" msgid="6949280415826686972">"<xliff:g id="APP">%1$s</xliff:g> এপ্"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"সতৰ্কবার্তাসমূহ"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"বেটাৰি"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"স্ক্ৰীণশ্বটসমূহ"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"সাধাৰণ বার্তাসমূহ"</string>
@@ -896,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> চলি আছে"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"ইনষ্ট\'ল নকৰাকৈয়েই এপটো খোলা হৈছে।"</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"ইনষ্ট\'ল নকৰাকৈয়েই এপটো খোলা হৈছে। অধিক জানিবলৈ টিপক।"</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"এপৰ তথ্য"</string>
<string name="go_to_web" msgid="636673528981366511">"ব্ৰাউজাৰলৈ যাওক"</string>
<string name="mobile_data" msgid="4564407557775397216">"ম’বাইল ডেটা"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -931,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"ছেটিংবোৰ"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"বুজি পালোঁ"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"SysUI হীপ ডাম্প কৰক"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g>এ আপোনাৰ <xliff:g id="TYPES_LIST">%2$s</xliff:g> ব্যৱহাৰ কৰি আছে।"</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"এপ্লিকেশ্বনসমূহে আপোনাৰ <xliff:g id="TYPES_LIST">%s</xliff:g> ব্যৱহাৰ কৰি আছে।"</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" আৰু "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"কেমেৰা"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"অৱস্থান"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"মাইক্ৰ\'ফ\'ন"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"ছেন্সৰ অফ হৈ আছে"</string>
<string name="device_services" msgid="1549944177856658705">"ডিভাইচ সেৱা"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"কোনো শিৰোনাম নাই"</string>
@@ -960,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"ছিষ্টেম নেভিগেশ্বন আপডে’ট কৰা হ’ল। সলনি কৰিবলৈ ছেটিংসমূহ-লৈ যাওক।"</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"ছিষ্টেম নেভিগেশ্বন আপডে’ট কৰিবলৈ ছেটিংসমূহ-লৈ যাওক"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"ষ্টেণ্ডবাই"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"বিবৰ্ধন অ’ভাৰলে’ৰ ৱিণ্ড’"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"বিবৰ্ধন ৱিণ্ড’"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"বিবৰ্ধন ৱিণ্ড’ৰ নিয়ন্ত্ৰণসমূহ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-as/strings_tv.xml b/packages/SystemUI/res/values-as/strings_tv.xml
index 0cca6fdf93c3..2076c99bf901 100644
--- a/packages/SystemUI/res/values-as/strings_tv.xml
+++ b/packages/SystemUI/res/values-as/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(শিৰোনামবিহীন কাৰ্যক্ৰম)"</string>
<string name="pip_close" msgid="5775212044472849930">"পিপ বন্ধ কৰক"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"সম্পূৰ্ণ স্ক্ৰীণ"</string>
+ <string name="mic_active" msgid="5766614241012047024">"মাইক্ৰ’ফ’ন সক্ৰিয় কৰা আছে"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$sএ আপোনাৰ মাইক্ৰ’ফ’ন এক্সেছ কৰিছে"</string>
</resources>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 95da98134a08..7511a7f0ee9a 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Ətraflı məlumat"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Ekranı doldurmaq üçün yaxınlaşdır"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Ekranı doldurmaq üçün uzat"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Ekran şəkli"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Skrinşot yadda saxlanılır..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Skrinşot yadda saxlanır..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Skrinşot yadda saxlandı"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"telefonu açın"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"səs yardımçısını açın"</string>
<string name="camera_label" msgid="8253821920931143699">"kemaranı açın"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Ləğv edin"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Təsdiq"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Yenidən cəhd edin"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Doğrulanmanı ləğv etmək üçün toxunun"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"<xliff:g id="TIME">%s</xliff:g> olduqda aktiv ediləcək"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g> vaxtına qədər"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Tünd tema"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Tünd tema\nEnerjiyə Qənaət"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Enerjiyə qənaət"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Qürubda aktiv olacaq"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Şəfəq vaxtına qədər"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC deaktiv edilib"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC aktiv edilib"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Açmaq üçün yenidən tıklayın"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Açmaq üçün yuxarı sürüşdürün"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Yenidən cəhd etmək üçün yuxarı sürüşdürün"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Bu cihaz təşkilatınız tərəfindən idarə olunur"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Bu cihaz <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> tərəfindən idarə olunur"</string>
<string name="phone_hint" msgid="6682125338461375925">"Telefon üçün ikonadan sürüşdürün"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Batareya Qənaəti aktivdir"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Performansı azaldır və arxa fon datasını məhdudlaşdırır"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Batareya Qənaətini deaktiv edin"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Qeydə alarkən və ya yayımlayarkən <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> audio, parollar, ödəniş məlumatı, foto və mesajlar daxil olmaqla ekranda göstərilən və ya cihazdan oxudulan həssas məlumatıı əldə edə bilər."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Qeydə alarkən və ya yayımlayarkən bu funksiyanı təmin edən xidmət audio, parollar, ödəniş məlumatı, foto və mesajlar daxil olmaqla ekranda göstərilən və ya cihazdan oxudulan həssas məlumatıı əldə edə bilər."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Yayım/qeydə alma zamanı həssas məlumatın paylaşılması"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> tətbiqinin yazma və ya yayım zamanı ekranda görünən və ya cihazdan oxudulan bütün məlumatlara girişi olacaq. Bura parollar, ödəniş detalları, fotolar, mesajlar və oxudulan audio kimi məlumatlar daxildir."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Bu funksiyanı təmin edən xidmətin yazma və ya yayım zamanı ekranda görünən və ya cihazdan oxudulan bütün məlumatlara girişi olacaq. Bura parollar, ödəniş detalları, fotolar, mesajlar və oxudulan audio kimi məlumatlar daxildir."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ilə yazma və ya yayımlama başladılsın?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Daha göstərmə"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Hamısını silin"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"İdarə edin"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Klaviatura dəyişdirici"</string>
<string name="save" msgid="3392754183673848006">"Saxlayın"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Sıfırlayın"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Düymənin enini nizamlayın"</string>
<string name="clipboard" msgid="8517342737534284617">"Pano"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Fərdi naviqasiya düyməsi"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Sağ"</string>
<string name="tuner_menu" msgid="363690665924769420">"Menyu"</string>
<string name="tuner_app" msgid="6949280415826686972">"<xliff:g id="APP">%1$s</xliff:g> tətbiqi"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Xəbərdarlıqlar"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Batareya"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Skrinşotlar"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Ümumi Mesajlar"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> işləyir"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Quraşdırılmadan açılan tətbiq."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Quraşdırılmadan açılan tətbiq. Ətraflı məlumat üçün klikləyin."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Tətbiq haqqında"</string>
<string name="go_to_web" msgid="636673528981366511">"Brauzerə daxil edin"</string>
<string name="mobile_data" msgid="4564407557775397216">"Mobil data"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Ayarlar"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Anladım"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="TYPES_LIST">%2$s</xliff:g> tətbiqlərindən istifadə edir."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Tətbiqlər <xliff:g id="TYPES_LIST">%s</xliff:g> istifadə edir."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" və "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"məkan"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensorlar deaktivdir"</string>
<string name="device_services" msgid="1549944177856658705">"Cihaz Xidmətləri"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Başlıq yoxdur"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Sistem naviqasiyası yeniləndi. Dəyişiklik etmək üçün Ayarlara daxil olun."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Sistem naviqasiyasını yeniləmək üçün Ayarlara keçin"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Gözləmə rejimi"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Böyütmə Üst-üstə Düşən Pəncərəsi"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Böyütmə Pəncərəsi"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Böyütmə Pəncərəsi Kontrolları"</string>
</resources>
diff --git a/packages/SystemUI/res/values-az/strings_tv.xml b/packages/SystemUI/res/values-az/strings_tv.xml
index c0c419ce5e50..e4e8880df847 100644
--- a/packages/SystemUI/res/values-az/strings_tv.xml
+++ b/packages/SystemUI/res/values-az/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Başlıqsız proqram)"</string>
<string name="pip_close" msgid="5775212044472849930">"PIP bağlayın"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Tam ekran"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Mikrofon Aktivdir"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s mikrofona daxil olub"</string>
</resources>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 7b909cf311bf..14f5e7f8ccee 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Saznajte više"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Zumiraj na celom ekranu"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Razvuci na ceo ekran"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Snimak ekrana"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Čuvanje snimka ekrana..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Čuvanje snimka ekrana..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Snimak ekrana je sačuvan"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"otvori telefon"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"otvori glasovnu pomoć"</string>
<string name="camera_label" msgid="8253821920931143699">"otvori kameru"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Otkaži"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Potvrdi"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Probaj ponovo"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Dodirnite da biste otkazali potvrdu identiteta"</string>
@@ -389,7 +387,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Uključuje se u <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Tamna tema"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Tamna tema\nUšteda baterije"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Ušteda baterije"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Uključuje se po zalasku sunca"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Do izlaska sunca"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC je onemogućen"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC je omogućen"</string>
@@ -414,10 +414,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Dodirnite ponovo da biste otvorili"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Prevucite nagore da biste otvorili"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Prevucite nagore da biste probali ponovo"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Ovim uređajem upravlja organizacija"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Ovim uređajem upravlja <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Prevucite od ikone za telefon"</string>
@@ -470,9 +466,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Ušteda baterije je uključena"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Smanjuje performanse i pozadinske podatke"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Isključi Uštedu baterije"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Kada snimate ili prebacujete, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> može da čuva osetljive informacije koje se prikazuju na ekranu ili reprodukuju sa uređaja, uključujući osetljive informacije kao što su zvuk, lozinke, informacije o plaćanju, slike i poruke."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Kada snimate ili prebacujete, usluga koja pruža ovu funkciju može da čuva osetljive informacije koje se prikazuju na ekranu ili reprodukuju sa uređaja, uključujući osetljive informacije kao što su zvuk, lozinke, informacije o plaćanju, slike i poruke."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Otkrivanje osetljivih informacija tokom prebacivanja/snimanja"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> će imati pristup svim informacijama koje se prikazuju na ekranu ili reprodukuju sa uređaja tokom snimanja ili prebacivanja. To obuhvata informacije poput lozinki, informacija o plaćanju, slika, poruka i zvuka koji puštate."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Usluga koja pruža ovu funkciju će imati pristup svim informacijama koje se prikazuju na ekranu ili reprodukuju sa uređaja tokom snimanja ili prebacivanja. To obuhvata informacije poput lozinki, informacija o plaćanju, slika, poruka i zvuka koji puštate."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Želite da počnete snimanje ili prebacivanje pomoću aplikacije <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Ne prikazuj ponovo"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Obriši sve"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Upravljajte"</string>
@@ -791,8 +789,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Prebacivač za tastaturu"</string>
<string name="save" msgid="3392754183673848006">"Sačuvaj"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Resetuj"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Prilagodi širinu dugmeta"</string>
<string name="clipboard" msgid="8517342737534284617">"Privremena memorija"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Prilagođeno dugme za navigaciju"</string>
@@ -888,8 +885,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Strelica udesno"</string>
<string name="tuner_menu" msgid="363690665924769420">"Meni"</string>
<string name="tuner_app" msgid="6949280415826686972">"Aplikacija <xliff:g id="APP">%1$s</xliff:g>"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Obaveštenja"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Baterija"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Snimci ekrana"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Opšte poruke"</string>
@@ -899,8 +895,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"Aplikacija <xliff:g id="APP">%1$s</xliff:g> je pokrenuta"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Aplikacija se otvorila bez instaliranja."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Aplikacija se otvorila bez instaliranja. Dodirnite da biste saznali više."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Informacije o aplikaciji"</string>
<string name="go_to_web" msgid="636673528981366511">"Idi na pregledač"</string>
<string name="mobile_data" msgid="4564407557775397216">"Mobilni podaci"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -934,13 +929,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Podešavanja"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Važi"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Izdvoji SysUI mem."</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> koristi <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplikacije koriste <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" i "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"kameru"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"lokaciju"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Senzori su isključeni"</string>
<string name="device_services" msgid="1549944177856658705">"Usluge za uređaje"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Bez naslova"</string>
@@ -963,4 +951,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Navigacija sistema je ažurirana. Da biste uneli izmene, idite u Podešavanja."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Idite u Podešavanja da biste ažurirali navigaciju sistema"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Stanje pripravnosti"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Preklopni prozor za uvećanje"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Prozor za uvećanje"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Kontrole prozora za uvećanje"</string>
</resources>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml b/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml
index 705166c27811..4e2d610da4c5 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Program bez naslova)"</string>
<string name="pip_close" msgid="5775212044472849930">"Zatvori PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Ceo ekran"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Mikrofon je aktivan"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"Aplikacija %1$s je pristupila mikrofonu"</string>
</resources>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 412fcb7430c6..35b0ddb00424 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Даведацца больш"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Павял. на ўвесь экран"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Расцягн. на ўвесь экран"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Здымак экрана"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Захаванне скрыншота..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Захаванне скрыншота..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Здымак экрана захаваны"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"адкрыць тэлефон"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"адкрыць галасавую дапамогу"</string>
<string name="camera_label" msgid="8253821920931143699">"адкрыць камеру"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Скасаваць"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Пацвердзіць"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Паўтарыць спробу"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Націсніце, каб скасаваць аўтэнтыфікацыю"</string>
@@ -393,7 +391,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Уключыць у <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Да <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Цёмная тэма"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Цёмная тэма\nЭканомія зараду"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Эканомія зараду"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Уключана ўвечары"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Да ўсходу сонца"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC адключаны"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC уключаны"</string>
@@ -418,10 +418,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Дакраніцеся яшчэ раз, каб адкрыць"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Каб адкрыць, прагарніце ўверх"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Прагартайце ўверх, каб паўтарыць спробу"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Гэта прылада знаходзіцца пад кіраваннем вашай арганізацыі"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Гэта прылада знаходзіцца пад кіраваннем <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Тэлефон: правядзіце пальцам ад значка"</string>
@@ -475,9 +471,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Рэжым эканоміі зараду ўключаны"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Памяншае прадукцыйнасць і фонавую перадачу даных"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Адключыць рэжым эканоміі зараду"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Падчас запісу ці трансляцыі <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> можа збіраць канфідэнцыяльную інфармацыю, адлюстраваную на экране вашай прылады, ці тую, якая прайграецца праз вашу прыладу, напрыклад аўдыяданыя, паролі, фота, паведамленні і звесткі пра аплату."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Падчас запісу ці трансляцыі служба, якая забяспечвае работу гэтай функцыі, можа збіраць канфідэнцыяльную інфармацыю, адлюстраваную на экране вашай прылады, ці тую, якая прайграецца праз вашу прыладу, напрыклад аўдыяданыя, паролі, фота, паведамленні і звесткі пра аплату."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Выкарыстанне асабістай інфармацыі падчас трансляцыі і запісу"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"Падчас запісу ці трансляцыі праграма \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\" будзе мець доступ да ўсёй інфармацыі, адлюстраванай на экране вашай прылады, ці той, якая праз яе прайграецца. Гэта інфармацыя ўключае паролі, звесткі пра аплату, фота, паведамленні і аўдыя, якое вы прайграяце."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Падчас запісу ці трансляцыі служба, якая забяспечвае работу гэтай функцыі, будзе мець доступ да ўсёй інфармацыі, адлюстраванай на экране вашай прылады, ці той, якая праз яе прайграецца. Гэта інфармацыя ўключае паролі, звесткі пра аплату, фота, паведамленні і аўдыя, якое вы прайграяце."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Пачаць запіс або трансляцыю з дапамогай праграмы \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\"?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Не паказваць зноў"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Ачысціць усё"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Кіраваць"</string>
@@ -798,8 +796,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Пераключальнік клавіятуры"</string>
<string name="save" msgid="3392754183673848006">"Захаваць"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Скінуць"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Адрэгуляваць шырыню кнопкі"</string>
<string name="clipboard" msgid="8517342737534284617">"Буфер абмену"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Кнопка карыстальніцкай навігацыі"</string>
@@ -895,8 +892,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Управа"</string>
<string name="tuner_menu" msgid="363690665924769420">"Меню"</string>
<string name="tuner_app" msgid="6949280415826686972">"Праграма <xliff:g id="APP">%1$s</xliff:g>"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Абвесткі"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Акумулятар"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Здымкі экрана"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Агульныя паведамленні"</string>
@@ -906,8 +902,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"Праграма \"<xliff:g id="APP">%1$s</xliff:g>\" запушчана"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Праграма адкрыта без усталёўкі."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Праграма адкрыта без усталёўкі. Націсніце, каб даведацца больш."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Звесткі пра праграму"</string>
<string name="go_to_web" msgid="636673528981366511">"Перайсці ў браўзер"</string>
<string name="mobile_data" msgid="4564407557775397216">"Маб. перадача даных"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -941,13 +936,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Налады"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Зразумела"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"Праграма \"<xliff:g id="APP">%1$s</xliff:g>\" выкарыстоўвае: <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Праграмы выкарыстоўваюць: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" і "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"камера"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"геалакацыя"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"мікрафон"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Датчыкі выкл."</string>
<string name="device_services" msgid="1549944177856658705">"Сэрвісы прылады"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Без назвы"</string>
@@ -970,4 +958,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Навігацыя ў сістэме абноўлена. Каб унесці змяненні, перайдзіце ў Налады."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Перайдзіце ў Налады, каб абнавіць параметры навігацыі ў сістэме"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Рэжым чакання"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Акно-накладка з павелічэннем"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Акно павелічэння"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Налады акна павелічэння"</string>
</resources>
diff --git a/packages/SystemUI/res/values-be/strings_tv.xml b/packages/SystemUI/res/values-be/strings_tv.xml
index 317d748d13b3..c75a49236e04 100644
--- a/packages/SystemUI/res/values-be/strings_tv.xml
+++ b/packages/SystemUI/res/values-be/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Праграма без назвы)"</string>
<string name="pip_close" msgid="5775212044472849930">"Закрыць PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Ва ўвесь экран"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Мікрафон актыўны"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"Праграма \"%1$s\" атрымала доступ да мікрафона"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index e9bf3c7a45ff..9b7b62a333ab 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Научете повече"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Мащаб – запълва екрана"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Разпъване – запълва екрана"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Екранна снимка"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Екранната снимка се запазва..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Екранната снимка се запазва..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Екранната снимка е запазена"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"отваряне на телефона"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"отваряне на гласовата помощ"</string>
<string name="camera_label" msgid="8253821920931143699">"отваряне на камерата"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Отказ"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Потвърждаване"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Нов опит"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Докоснете, за да анулирате удостоверяването"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Ще се включи в <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"До <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Тъмна тема"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Тъмна тема\nЗапазване на батерията: Режим"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Запазв. на батерията"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Ще се вкл. по залез"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"До изгрев"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"КБП"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"КБП е деактивирана"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"КБП е активирана"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Докоснете отново, за да отворите"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Прекарайте пръст нагоре, за да отключите"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Плъзнете бързо нагоре, за да опитате отново"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Това устройство се управлява от организацията ви"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Това устройство се управлява от <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Плъзнете с пръст от иконата, за да използвате телефона"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Режимът за запазване на батерията е включен"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Намалява ефективността и данните на заден план"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Изключване на режима за запазване на батерията"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Докато записва или предава, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> може да прихване поверителна информация, която е показана на екрана ви или възпроизвеждана от устройството ви, включително поверителна информация, като например аудиозапис, пароли, данни за плащане, снимки и съобщения."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Докато записва или предава, услугата, предоставяща тази функция, може да прихване поверителна информация, която е показана на екрана ви или възпроизвеждана от устройството ви, включително поверителна информация, като например аудиозапис, пароли, данни за плащане, снимки и съобщения."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Разкриване на поверителна информация по време на предаване/записване"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ще има достъп до цялата информация, която е видима на екрана или възпроизвеждана от устройството ви по време на записване или предаване. Това включва различна информация, като например пароли, данни за плащане, снимки, съобщения и възпроизвеждано аудио."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Услугата, предоставяща тази функция, ще има достъп до цялата информация, която е видима на екрана или възпроизвеждана от устройството ви по време на записване или предаване. Това включва различна информация, като например пароли, данни за плащане, снимки, съобщения и възпроизвеждано аудио."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Да се стартира ли записване или предаване чрез <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Да не се показва отново"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Изчистване на всички"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Управление"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Превключвател на клавиатурата"</string>
<string name="save" msgid="3392754183673848006">"Запазване"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Повторно задаване"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Коригиране на ширината на бутона"</string>
<string name="clipboard" msgid="8517342737534284617">"Буферна памет"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Персонализиран бутон за навигация"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Стрелка за надясно"</string>
<string name="tuner_menu" msgid="363690665924769420">"Меню"</string>
<string name="tuner_app" msgid="6949280415826686972">"Приложение <xliff:g id="APP">%1$s</xliff:g>"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Сигнали"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Батерия"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Екранни снимки"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Общи съобщения"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> работи"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Приложението се отвори, без да бъде инсталирано."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Приложението се отвори, без да бъде инсталирано. Докоснете, за да научите повече."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Информация"</string>
<string name="go_to_web" msgid="636673528981366511">"Към браузъра"</string>
<string name="mobile_data" msgid="4564407557775397216">"Мобилни данни"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Настройки"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Разбрах"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> използва <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Някои приложения използват <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" и "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"камерата"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"местополож."</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"микрофона"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Сензорите са изключени"</string>
<string name="device_services" msgid="1549944177856658705">"Услуги за устройството"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Няма заглавие"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Режимът за навигиране в системата е актуализиран. За да извършите промени, отворете настройките."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Отворете настройките, за да актуализирате режима за навигиране в системата"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Режим на готовност"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Прозорец с наслагване за ниво на мащаба"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Прозорец за ниво на мащаба"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Контроли за прозореца за ниво на мащаба"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bg/strings_tv.xml b/packages/SystemUI/res/values-bg/strings_tv.xml
index 26d1f61e0c57..6d2b842117f1 100644
--- a/packages/SystemUI/res/values-bg/strings_tv.xml
+++ b/packages/SystemUI/res/values-bg/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Програма без заглавие)"</string>
<string name="pip_close" msgid="5775212044472849930">"Затваряне на PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Цял екран"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Микрофонът е активен"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s осъществи достъп до микрофона ви"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 60b23d7b5e9a..e17905a06d14 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"আরও জানুন"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"স্ক্রীণ পূরণ করতে জুম করুন"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"ফুল স্ক্রিন করুন"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"স্ক্রিনশট"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"স্ক্রিনশট সেভ করা হচ্ছে..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"স্ক্রিনশট সেভ করা হচ্ছে..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"স্ক্রিনশট সেভ করা হয়েছে"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"ফোন খুলুন"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"ভয়েস সহায়তা খুলুন"</string>
<string name="camera_label" msgid="8253821920931143699">"ক্যামেরা খুলুন"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"বাতিল করুন"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"কনফার্ম করুন"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"আবার চেষ্টা করুন"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"যাচাইকরণ বাতিল করতে ট্যাপ করুন"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"<xliff:g id="TIME">%s</xliff:g> এ চালু হবে"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g> পর্যন্ত"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"গাঢ় থিম"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"গাঢ় থিম\nব্যাটারি সেভার"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"ব্যাটারি সেভার"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"সূর্যাস্তে চালু হবে"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"সূর্যোদয় পর্যন্ত"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC অক্ষম করা আছে"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC সক্ষম করা আছে"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"খোলার জন্য আবার আলতো চাপুন"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"খোলার জন্য উপরে সোয়াইপ করুন"</string>
<string name="keyguard_retry" msgid="886802522584053523">"আবার চেষ্টা করতে উপরের দিকে সোয়াইপ করুন"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"আপনার সংস্থা এই ডিভাইসটি পরিচালনা করছে"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"এই ডিভাইসটি <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> এর দ্বারা পরিচালিত"</string>
<string name="phone_hint" msgid="6682125338461375925">"ফোনের জন্য আইকন থেকে সোয়াইপ করুন"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"ব্যাটারি সেভার চালু আছে"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"কার্য-সম্পাদনা ও পশ্চাদপট ডেটাকে কমিয়ে দেয়"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"ব্যাটারি সেভার বন্ধ করুন"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"রেকর্ডিং বা কাস্টিংয়ের সময়, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> আপনার স্ক্রিনে প্রদর্শিত বা ডিভাইস থেকে অডিও, পাসওয়ার্ড, পেমেন্টের তথ্য, ফটো এবং মেসেজের মতো যেকোনও সংবেদনশীল তথ্য ক্যাপচার করতে পারে।"</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"রেকর্ডিং বা কাস্টিংয়ের সময়, এই ফাংশন সরবরাহকারী পরিষেবা আপনার স্ক্রিনে প্রদর্শিত বা ডিভাইস থেকে অডিও, পাসওয়ার্ড, পেমেন্টের তথ্য, ফটো এবং মেসেজের মতো যেকোনও সংবেদনশীল তথ্য ক্যাপচার করতে পারে।"</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"কাস্ট/রেকর্ড করার সময় সংবেদনশীল তথ্য প্রকাশ করে"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"রেকর্ড করা বা কাস্টিং করার সময় স্ক্রিনে দেখানো বা ডিভাইসে দেখানো সমস্ত তথ্যের অ্যাক্সেস <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>-এর থাকবে। এর মধ্যে আপনার পাসওয়ার্ড, পেমেন্টের বিবরণ, ফটো, মেসেজ এবং যে অডিও আপনি চালান সেগুলি সম্পর্কিত তথ্য রয়েছে।"</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"রেকর্ড করা বা কাস্টিং করার সময় আপনার স্ক্রিনে দেখানো বা ডিভাইসে চালানো হয়েছে এমন সমস্ত তথ্যের অ্যাক্সেস এই ফাংশন প্রদানকারী পরিষেবার কাছে থাকবে। এর মধ্যে আপনার পাসওয়ার্ড, পেমেন্টের বিবরণ, ফটো, মেসেজ এবং যে অডিও আপনি চালান সেগুলি সম্পর্কিত তথ্য রয়েছে।"</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> দিয়ে রেকর্ড করা বা কাস্টিং শুরু করবেন?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"আর দেখাবেন না"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"সবকিছু সাফ করুন"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"পরিচালনা করুন"</string>
@@ -667,12 +665,10 @@
<string name="inline_keep_showing_app" msgid="4393429060390649757">"এই অ্যাপের বিজ্ঞপ্তি পরেও দেখে যেতে চান?"</string>
<string name="notification_silence_title" msgid="8608090968400832335">"সাইলেন্ট"</string>
<string name="notification_alert_title" msgid="7629202599338071971">"সতর্ক করুন"</string>
- <!-- no translation found for notification_bubble_title (8330481035191903164) -->
- <skip />
+ <string name="notification_bubble_title" msgid="8330481035191903164">"বাবল"</string>
<string name="notification_channel_summary_low" msgid="7300447764759926720">"সাউন্ড বা ভাইব্রেশন ছাড়া ফোকাস করতে আপনাকে সাহায্য করে।"</string>
<string name="notification_channel_summary_default" msgid="3539949463907902037">"সাউন্ড বা ভাইব্রেশনের সাহায্যে দৃষ্টি আকর্ষণ করে।"</string>
- <!-- no translation found for notification_channel_summary_bubble (7235935211580860537) -->
- <skip />
+ <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ফ্লোটিং শর্টকাট ব্যবহার করে এই কন্টেন্টে আপনার দৃষ্টি আকর্ষণ করে রাখে।"</string>
<string name="notification_unblockable_desc" msgid="2073030886006190804">"এই বিজ্ঞপ্তিগুলি পরিবর্তন করা যাবে না।"</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"এই সমস্ত বিজ্ঞপ্তিকে এখানে কনফিগার করা যাবে না"</string>
<string name="notification_delegate_header" msgid="1264510071031479920">"প্রক্সি করা বিজ্ঞপ্তি"</string>
@@ -788,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"কিবোর্ড স্যুইচার"</string>
<string name="save" msgid="3392754183673848006">"সেভ করুন"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"রিসেট করুন"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"বোতামের প্রস্থ সিঙ্ক করুন"</string>
<string name="clipboard" msgid="8517342737534284617">"ক্লিপবোর্ড"</string>
<string name="accessibility_key" msgid="3471162841552818281">"কাস্টম নেভিগেশন বোতাম"</string>
@@ -885,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"ডান"</string>
<string name="tuner_menu" msgid="363690665924769420">"মেনু"</string>
<string name="tuner_app" msgid="6949280415826686972">"<xliff:g id="APP">%1$s</xliff:g> অ্যাপ"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"সতর্কতা"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"ব্যাটারি"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"স্ক্রীনশটস"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"সাধারণ বার্তাগুলি"</string>
@@ -896,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> চলছে"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"অ্যাপটি ইনস্টল না করে চালু করা হয়েছে।"</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"অ্যাপটি ইনস্টল না করে চালু করা হয়েছে। আরও জানতে ট্যাপ করুন।"</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"অ্যাপের তথ্য"</string>
<string name="go_to_web" msgid="636673528981366511">"ব্রাউজারে যান"</string>
<string name="mobile_data" msgid="4564407557775397216">"মোবাইল ডেটা"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -931,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"সেটিংস"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"বুঝেছি"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> আপনার <xliff:g id="TYPES_LIST">%2$s</xliff:g> ব্যবহার করছে।"</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"অ্যাপ্লিকেশনগুলি আপনার <xliff:g id="TYPES_LIST">%s</xliff:g> ব্যবহার করছে।"</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" এবং "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"ক্যামেরা"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"লোকেশন"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"মাইক্রোফোন"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"সেন্সর বন্ধ"</string>
<string name="device_services" msgid="1549944177856658705">"ডিভাইস সংক্রান্ত পরিষেবা"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"কোনও শীর্ষক নেই"</string>
@@ -960,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"সিস্টেম নেভিগেশন আপডেট হয়েছে। পরিবর্তন করার জন্য সেটিংসে যান।"</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"সিস্টেম নেভিগেশন আপডেট করতে সেটিংসে যান"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"স্ট্যান্ডবাই"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"ওভারলে উইন্ডো বড় করে দেখা"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"উইন্ডো বড় করে দেখা"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"উইন্ডো কন্ট্রোল বড় করে দেখা"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bn/strings_tv.xml b/packages/SystemUI/res/values-bn/strings_tv.xml
index 132447568024..795314c4b15c 100644
--- a/packages/SystemUI/res/values-bn/strings_tv.xml
+++ b/packages/SystemUI/res/values-bn/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(শিরোনামহীন প্রোগ্রাম)"</string>
<string name="pip_close" msgid="5775212044472849930">"PIP বন্ধ করুন"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"পূর্ণ স্ক্রিন"</string>
+ <string name="mic_active" msgid="5766614241012047024">"মাইক্রোফোন চালু আছে"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s আপনার ডিভাইসের মাইক্রোফোন অ্যাক্সেস করেছে"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 40f2d7c5e764..6e2285e1c92d 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Saznajte više"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Uvećaj prikaz na ekran"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Razvuci prikaz na ekran"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Snimak ekrana"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Spašavanje snimka ekrana..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Spašavanje snimka ekrana..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Snimak ekrana je sačuvan"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"otvori telefon"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"otvori glasovnu pomoć"</string>
<string name="camera_label" msgid="8253821920931143699">"otvori kameru"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Otkaži"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Potvrdite"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Pokušaj ponovo"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Dodirnite da otkažete autentifikaciju"</string>
@@ -384,12 +382,14 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"Upozorenje <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Radni profil"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"Noćno svjetlo"</string>
- <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Uključuje se u suton"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Uključuje se u sumrak"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Do svitanja"</string>
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Uključuje se u <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Tamna tema"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Tamna tema\nUšteda baterije"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Ušteda baterije"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Uključuje se u sumrak"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Do svitanja"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC je onemogućen"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC je omogućen"</string>
@@ -414,10 +414,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Dodirnite ponovo da otvorite"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Prevucite da otvorite"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Prevucite prema gore da pokušate ponovo"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Ovim uređajem upravlja vaša organizacija"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Ovim uređajem upravlja <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Prevucite preko ikone da otvorite telefon"</string>
@@ -470,9 +466,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Uključena je Ušteda baterije"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Minimizira rad i prijenos podataka u pozadini"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Isključi Uštedu baterije"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Prilikom snimanja ili emitiranja aplikacija <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> može snimiti sve osjetljive podatke koji se prikazuju na vašem ekranu ili koji se reproduciraju s vašeg uređaja, uključujući i osjetljive podatke kao što su zvuk, lozinke, podaci za plaćanje, fotografije i poruke."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Prilikom snimanja ili emitiranja usluga koja pruža ovu funkciju može snimati osjetljive podatke koji se prikazuju na vašem ekranu ili koji se reproduciraju s vašeg uređaja, uključujući i osjetljive podatke kao što su zvuk, lozinke, podaci za plaćanje, fotografije i poruke."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Izlaganje osjetljivih podataka za vrijeme emitiranja/snimanja"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"Aplikacija <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> će imati pristup svim informacijama koje se prikazuju na ekranu ili koje se reproduciraju s vašeg uređaja za vrijeme snimanja ili emitiranja. To obuhvata informacije kao što su lozinke, detalji o plaćanju, fotografije, poruke i zvuk koji reproducirate."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Usluga koja pruža ovu funkciju će imati pristup svim informacijama koje se prikazuju na ekranu ili koje se reproduciraju s vašeg uređaja za vrijeme snimanja ili emitiranja. To obuhvata informacije kao što su lozinke, detalji o plaćanju, fotografije, poruke i zvuk koji reproducirate."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Započeti snimanje ili emitiranje s aplikacijom <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Ne prikazuj opet"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Očisti sve"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Upravljajte"</string>
@@ -793,8 +791,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Prebacivač tastatura"</string>
<string name="save" msgid="3392754183673848006">"Sačuvaj"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Vrati na zadano"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Podesite širinu dugmeta"</string>
<string name="clipboard" msgid="8517342737534284617">"Međumemorija"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Prilagođeno dugme za navigaciju"</string>
@@ -890,8 +887,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Desno"</string>
<string name="tuner_menu" msgid="363690665924769420">"Meni"</string>
<string name="tuner_app" msgid="6949280415826686972">"Aplikacija <xliff:g id="APP">%1$s</xliff:g>"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Obavještenja"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Baterija"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Snimci ekrana"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Opće poruke"</string>
@@ -901,8 +897,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"Pokrenuta je aplikacija <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Aplikacija je otvorena bez prethodne instalacije."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Aplikacija je otvorena bez prethodne instalacije. Dodirnite da saznate više."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Info. o aplikaciji"</string>
<string name="go_to_web" msgid="636673528981366511">"Idi na preglednik"</string>
<string name="mobile_data" msgid="4564407557775397216">"Prijenos podataka"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -936,13 +931,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Postavke"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Razumijem"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Izdvoji SysUI mem."</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> koristi <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplikacije koriste <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" i "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"kameru"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"lokaciju"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Senzori su isključeni"</string>
<string name="device_services" msgid="1549944177856658705">"Usluge uređaja"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Bez naslova"</string>
@@ -965,4 +953,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Navigiranje sistemom je ažurirano. Da izvršite promjene, idite u Postavke."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Idite u Postavke da ažurirate navigiranje sistemom"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Stanje mirovanja"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Preklopni prozor za uvećavanje"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Prozor za uvećavanje"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Kontrole prozora za uvećavanje"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bs/strings_tv.xml b/packages/SystemUI/res/values-bs/strings_tv.xml
index 9bdc8cb3a78f..1dd803516841 100644
--- a/packages/SystemUI/res/values-bs/strings_tv.xml
+++ b/packages/SystemUI/res/values-bs/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Program bez naslova)"</string>
<string name="pip_close" msgid="5775212044472849930">"Zatvori PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Cijeli ekran"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Mikrofon je aktivan"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"Aplikacija %1$s je pristupila vašem mikrofonu"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 8e64a2e0674d..4909e10e87e2 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Més informació"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Zoom per omplir pantalla"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Estira per omplir pant."</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Captura de pantalla"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"S\'està desant captura de pantalla..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"S\'està desant la captura de pantalla..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"S\'ha desat la captura de pantalla"</string>
@@ -80,7 +79,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Prova de tornar a fer una captura de pantalla"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"La captura de pantalla no es pot desar perquè no hi ha prou espai d\'emmagatzematge"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"L\'aplicació o la teva organització no permeten fer captures de pantalla"</string>
- <string name="screenrecord_name" msgid="6286499308042305686">"Gravació de la pantalla"</string>
+ <string name="screenrecord_name" msgid="6286499308042305686">"Gravació de pantalla"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificació en curs d\'una sessió de gravació de la pantalla"</string>
<string name="screenrecord_start_label" msgid="1539048263178882562">"Inicia la gravació"</string>
<string name="screenrecord_mic_label" msgid="6134198080740031632">"Grava la veu en off"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"obre el telèfon"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"obre l\'assistència per veu"</string>
<string name="camera_label" msgid="8253821920931143699">"obre la càmera"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Cancel·la"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Confirma"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Torna-ho a provar"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Toca per cancel·lar l\'autenticació"</string>
@@ -255,15 +253,15 @@
<string name="accessibility_quick_settings_location_on" msgid="6869947200325467243">"Informes d\'ubicació activats"</string>
<string name="accessibility_quick_settings_location_changed_off" msgid="5132776369388699133">"Els informes d\'ubicació estan desactivats."</string>
<string name="accessibility_quick_settings_location_changed_on" msgid="7159115433070112154">"Els informes d\'ubicació estan activats."</string>
- <string name="accessibility_quick_settings_alarm" msgid="558094529584082090">"Alarma establerta a les <xliff:g id="TIME">%s</xliff:g>."</string>
+ <string name="accessibility_quick_settings_alarm" msgid="558094529584082090">"S\'ha configurat l\'alarma (<xliff:g id="TIME">%s</xliff:g>)."</string>
<string name="accessibility_quick_settings_close" msgid="2974895537860082341">"Tanca el tauler."</string>
<string name="accessibility_quick_settings_more_time" msgid="7646479831704665284">"Més temps"</string>
<string name="accessibility_quick_settings_less_time" msgid="9110364286464977870">"Menys temps"</string>
- <string name="accessibility_quick_settings_flashlight_off" msgid="7606563260714825190">"Llanterna desactivada"</string>
+ <string name="accessibility_quick_settings_flashlight_off" msgid="7606563260714825190">"Llanterna apagada."</string>
<string name="accessibility_quick_settings_flashlight_unavailable" msgid="7458591827288347635">"La llanterna no està disponible."</string>
- <string name="accessibility_quick_settings_flashlight_on" msgid="3785616827729850766">"Llanterna activada"</string>
- <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3782375441381402599">"Llanterna desactivada."</string>
- <string name="accessibility_quick_settings_flashlight_changed_on" msgid="4747870681508334200">"Llanterna activada."</string>
+ <string name="accessibility_quick_settings_flashlight_on" msgid="3785616827729850766">"Llanterna encesa."</string>
+ <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3782375441381402599">"Llanterna apagada."</string>
+ <string name="accessibility_quick_settings_flashlight_changed_on" msgid="4747870681508334200">"Llanterna encesa."</string>
<string name="accessibility_quick_settings_color_inversion_changed_off" msgid="7548045840282925393">"La inversió dels colors està desactivada."</string>
<string name="accessibility_quick_settings_color_inversion_changed_on" msgid="4711141858364404084">"La inversió dels colors està activada."</string>
<string name="accessibility_quick_settings_hotspot_changed_off" msgid="7002061268910095176">"El punt d\'accés mòbil està desactivat."</string>
@@ -382,12 +380,14 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"Advertiment: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Perfil professional"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"Llum nocturna"</string>
- <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"A la posta de sol"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Al vespre"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Fins a l\'alba"</string>
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"S\'activarà a les <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Fins a les <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Tema fosc"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Tema fosc\nEstalvi de bateria"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Estalvi de bateria"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Al vespre"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Fins a l\'alba"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"L\'NFC està desactivada"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"L\'NFC està activada"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Torna a tocar per obrir-la."</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Llisca cap amunt per obrir"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Llisca cap a dalt per tornar-ho a provar"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"La teva organització gestiona aquest dispositiu"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"<xliff:g id="ORGANIZATION_NAME">%s</xliff:g> gestiona aquest dispositiu"</string>
<string name="phone_hint" msgid="6682125338461375925">"Llisca des de la icona per obrir el telèfon"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"S\'ha activat l\'estalvi de bateria"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Redueix el rendiment i l\'ús de les dades en segon pla."</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Desactiva l\'estalvi de bateria"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Quan graves o emets contingut, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> pot capturar la informació sensible que es mostri a la pantalla o que es reprodueixi al dispositiu, com ara àudio, contrasenyes, informació de pagament, fotos i missatges."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Quan graves o emets contingut, el servei que ofereix aquesta funció pot capturar informació sensible que es mostri a la pantalla o que es reprodueixi al dispositiu, com ara àudio, contrasenyes, informació de pagament, fotos i missatges."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Es mostra informació sensible durant l\'emissió o la gravació"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> tindrà accés a tota la informació que es veu en pantalla o que es reprodueix al dispositiu mentre graves o emets contingut, com ara contrasenyes, detalls dels pagaments, fotos, missatges i àudio."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"El servei que ofereix aquesta funció tindrà accés a tota la informació que es veu en pantalla o que es reprodueix al dispositiu mentre graves o emets contingut, com ara contrasenyes, detalls dels pagaments, fotos, missatges i àudio."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Vols començar a gravar o emetre contingut amb <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"No ho tornis a mostrar"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Esborra-ho tot"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Gestiona"</string>
@@ -515,7 +513,7 @@
<string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Estàs connectat a <xliff:g id="VPN_APP_0">%1$s</xliff:g> i <xliff:g id="VPN_APP_1">%2$s</xliff:g>, que poden supervisar la teva activitat a la xarxa, com ara els correus electrònics, les aplicacions i els llocs web."</string>
<string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"El teu perfil professional està connectat a <xliff:g id="VPN_APP">%1$s</xliff:g>, que pot supervisar la teva activitat a la xarxa, com ara els correus electrònics, les aplicacions i els llocs web."</string>
<string name="monitoring_description_personal_profile_named_vpn" msgid="8179722332380953673">"El teu perfil personal està connectat a <xliff:g id="VPN_APP">%1$s</xliff:g>,que pot supervisar la teva activitat a la xarxa, com ara els correus electrònics, les aplicacions i els llocs web."</string>
- <string name="monitoring_description_do_header_generic" msgid="6130190408164834986">"<xliff:g id="DEVICE_OWNER_APP">%1$s</xliff:g> gestiona el teu dispositiu."</string>
+ <string name="monitoring_description_do_header_generic" msgid="6130190408164834986">"El teu dispositiu està gestionat per <xliff:g id="DEVICE_OWNER_APP">%1$s</xliff:g>."</string>
<string name="monitoring_description_do_header_with_name" msgid="2696255132542779511">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> utilitza <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> per gestionar el teu dispositiu."</string>
<string name="monitoring_description_do_body" msgid="7700878065625769970">"L\'administrador pot supervisar i gestionar la configuració, l\'accés corporatiu, les aplicacions, la ubicació i les dades del dispositiu."</string>
<string name="monitoring_description_do_learn_more_separator" msgid="1467280496376492558">" "</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Commutador del teclat"</string>
<string name="save" msgid="3392754183673848006">"Desa"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Restableix"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Ajusta l\'amplada del botó"</string>
<string name="clipboard" msgid="8517342737534284617">"Porta-retalls"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Botó de navegació personalitzat"</string>
@@ -797,7 +794,7 @@
<string name="right_icon" msgid="1103955040645237425">"Icona de la dreta"</string>
<string name="drag_to_add_tiles" msgid="8933270127508303672">"Mantén premut i arrossega per afegir mosaics"</string>
<string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"Mantén premut i arrossega per reorganitzar els mosaics"</string>
- <string name="drag_to_remove_tiles" msgid="4682194717573850385">"Arrossega aquí per suprimir una funció"</string>
+ <string name="drag_to_remove_tiles" msgid="4682194717573850385">"Arrossega aquí per suprimir"</string>
<string name="drag_to_remove_disabled" msgid="933046987838658850">"Necessites com a mínim <xliff:g id="MIN_NUM_TILES">%1$d</xliff:g> mosaics"</string>
<string name="qs_edit" msgid="5583565172803472437">"Edita"</string>
<string name="tuner_time" msgid="2450785840990529997">"Hora"</string>
@@ -839,7 +836,7 @@
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Obre la configuració."</string>
<string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Obre la configuració ràpida."</string>
<string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Tanca la configuració ràpida."</string>
- <string name="accessibility_quick_settings_alarm_set" msgid="7237918261045099853">"L\'alarma s\'ha definit."</string>
+ <string name="accessibility_quick_settings_alarm_set" msgid="7237918261045099853">"S\'ha configurat l\'alarma."</string>
<string name="accessibility_quick_settings_user" msgid="505821942882668619">"S\'ha iniciat la sessió com a <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="data_connection_no_internet" msgid="691058178914184544">"Sense connexió a Internet"</string>
<string name="accessibility_quick_settings_open_details" msgid="4879279912389052142">"Obre la informació detallada."</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Dreta"</string>
<string name="tuner_menu" msgid="363690665924769420">"Menú"</string>
<string name="tuner_app" msgid="6949280415826686972">"Aplicació <xliff:g id="APP">%1$s</xliff:g>"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Alertes"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Bateria"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Captures de pantalla"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Missatges generals"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"S\'està executant <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"L\'aplicació s\'ha obert sense instal·lar-se."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"L\'aplicació s\'ha obert sense instal·lar-se. Toca per obtenir més informació."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Informació de l\'aplicació"</string>
<string name="go_to_web" msgid="636673528981366511">"Ves al navegador"</string>
<string name="mobile_data" msgid="4564407557775397216">"Dades mòbils"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> - <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Configuració"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Entesos"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Aboca espai de SysUI"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> està fent servir el següent: <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Algunes aplicacions estan fent servir el següent: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" i "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"càmera"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"ubicació"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"micròfon"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensors desactivats"</string>
<string name="device_services" msgid="1549944177856658705">"Serveis per a dispositius"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Sense títol"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"S\'ha actualitzat el sistema de navegació. Per fer canvis, ves a Configuració."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Ves a Configuració per actualitzar el sistema de navegació"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"En espera"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Finestra superposada d\'ampliació"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Finestra d\'ampliació"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Finestra de controls d\'ampliació"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ca/strings_tv.xml b/packages/SystemUI/res/values-ca/strings_tv.xml
index cc9fa41bde48..44cc9410ed0b 100644
--- a/packages/SystemUI/res/values-ca/strings_tv.xml
+++ b/packages/SystemUI/res/values-ca/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Programa sense títol)"</string>
<string name="pip_close" msgid="5775212044472849930">"Tanca PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Pantalla completa"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Micròfon actiu"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s ha accedit al teu micròfon"</string>
</resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 2843bcd44f70..b5b8aa3f8aa5 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Další informace"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Přiblížit na celou obrazovku"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Na celou obrazovku"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Snímek obrazovky"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Ukládání snímku obrazovky..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Ukládání snímku obrazovky..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Snímek obrazovky byl uložen"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"otevřít telefon"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"otevřít hlasovou asistenci"</string>
<string name="camera_label" msgid="8253821920931143699">"spustit fotoaparát"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Zrušit"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Potvrdit"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Zkusit znovu"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Klepnutím zrušíte ověření"</string>
@@ -386,12 +384,14 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"Upozornění při <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Pracovní profil"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"Noční režim"</string>
- <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Zapnout při soumraku"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Při soumraku"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Do svítání"</string>
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Zapnout v <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Tmavý motiv"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Tmavý motiv\nSpořič baterie"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Spořič baterie"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Při soumraku"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Do svítání"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC je vypnuto"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC je zapnuto"</string>
@@ -416,10 +416,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Oznámení otevřete opětovným klepnutím"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Otevřete přejetím prstem nahoru"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Přejetím nahoru to zkusíte znovu"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Toto zařízení spravuje vaše organizace"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Toto zařízení je spravováno organizací <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Telefon otevřete přejetím prstem od ikony"</string>
@@ -473,9 +469,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Spořič baterie je zapnutý"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Omezuje výkon a data na pozadí"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Vypnout spořič baterie"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Při nahrávání nebo odesílání může aplikace <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> zachytit citlivé údaje zobrazené na obrazovce nebo přehrávané ze zařízení, např. zvuky, hesla, platební údaje, fotky a zprávy."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Při nahrávání nebo odesílání může služba poskytující tuto funkci zachytit citlivé údaje zobrazené na obrazovce nebo přehrávané ze zařízení, např. zvuky, hesla, platební údaje, fotky a zprávy."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Zobrazení citlivých údajů při nahrávání/odesílání"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"Aplikace <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> bude mít přístup ke všem informacím, které jsou viditelné na obrazovce nebo které jsou přehrávány ze za řízení při nahrávání nebo odesílání. Týká se to i hesel, údajů o platbě, fotek, zpráv a přehrávaných zvuků."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Služba, která poskytuje tuto funkci, bude mít přístup ke všem informacím, které jsou viditelné na obrazovce nebo které jsou přehrávány ze zařízení při nahrávání nebo odesílání. Týká se to i hesel, údajů o platbě, fotek, zpráv a přehrávaných zvuků."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Začít nahrávat nebo odesílat s aplikací <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Tuto zprávu příště nezobrazovat"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Smazat vše"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Spravovat"</string>
@@ -796,8 +794,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Přepínač klávesnice"</string>
<string name="save" msgid="3392754183673848006">"Uložit"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Resetovat"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Upravit šířku tlačítka"</string>
<string name="clipboard" msgid="8517342737534284617">"Schránka"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Vlastní navigační tlačítko"</string>
@@ -893,8 +890,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Vpravo"</string>
<string name="tuner_menu" msgid="363690665924769420">"Nabídka"</string>
<string name="tuner_app" msgid="6949280415826686972">"Aplikace <xliff:g id="APP">%1$s</xliff:g>"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Upozornění"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Baterie"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Snímky obrazovek"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Všeobecné zprávy"</string>
@@ -904,8 +900,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"Aplikace <xliff:g id="APP">%1$s</xliff:g> je spuštěna"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Aplikace byla otevřena bez instalace."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Aplikace byla otevřena bez instalace. Klepnutím zobrazíte další informace."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"O aplikaci"</string>
<string name="go_to_web" msgid="636673528981366511">"Přejít do prohlížeče"</string>
<string name="mobile_data" msgid="4564407557775397216">"Mobilní data"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -939,13 +934,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Nastavení"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Rozumím"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Výpis haldy SysUI"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"Aplikace <xliff:g id="APP">%1$s</xliff:g> využívá tato oprávnění: <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplikace využívají tato oprávnění: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" a "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"fotoaparát"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"poloha"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Senzory jsou vypnuty"</string>
<string name="device_services" msgid="1549944177856658705">"Služby zařízení"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Bez názvu"</string>
@@ -968,4 +956,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Systémová navigace byla aktualizována. Chcete-li provést změny, přejděte do Nastavení."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Přejděte do Nastavení a aktualizujte systémovou navigaci"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Pohotovostní režim"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Překryvné zvětšovací okno"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Zvětšovací okno"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Ovládací prvky zvětšovacího okna"</string>
</resources>
diff --git a/packages/SystemUI/res/values-cs/strings_tv.xml b/packages/SystemUI/res/values-cs/strings_tv.xml
index 3f7bf9e6a400..0494bc12b469 100644
--- a/packages/SystemUI/res/values-cs/strings_tv.xml
+++ b/packages/SystemUI/res/values-cs/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Bez názvu)"</string>
<string name="pip_close" msgid="5775212044472849930">"Ukončit obraz v obraze (PIP)"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Celá obrazovka"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Mikrofon je aktivní"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"Aplikace %1$s použila mikrofon"</string>
</resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index da62c702d257..80c8d285d359 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -39,7 +39,7 @@
<string name="battery_saver_start_action" msgid="4553256017945469937">"Aktivér batterisparefunktion"</string>
<string name="status_bar_settings_settings_button" msgid="534331565185171556">"Indstillinger"</string>
<string name="status_bar_settings_wifi_button" msgid="7243072479837270946">"Wi-Fi"</string>
- <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Automatisk skærmrotation"</string>
+ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Roter skærm automatisk"</string>
<string name="status_bar_settings_mute_label" msgid="914392730086057522">"LYDLØS"</string>
<string name="status_bar_settings_auto_brightness_label" msgid="2151934479226017725">"AUTO"</string>
<string name="status_bar_settings_notifications" msgid="5285316949980621438">"Notifikationer"</string>
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Få flere oplysninger"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Zoom til fuld skærm"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Stræk til fuld skærm"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Gemmer screenshot..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Gemmer screenshot..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshottet blev gemt"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"åbn telefon"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"åbn taleassistent"</string>
<string name="camera_label" msgid="8253821920931143699">"åbn kamera"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Annuller"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Bekræft"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Prøv igen"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Tryk for at annullere godkendelsen"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Tænd kl. <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Indtil <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Mørkt tema"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Mørkt tema\nBatterisparefunktion"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Batterisparefunktion"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Til ved solnedgang"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Indtil solopgang"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC er deaktiveret"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC er aktiveret"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Tryk igen for at åbne"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Stryg opad for at åbne"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Stryg opad for at prøve igen"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Denne enhed administreres af din organisation"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Denne enhed administreres af <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Stryg fra telefonikonet"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Batterisparefunktion er aktiveret"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Reducerer ydeevne og baggrundsdata"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Deaktiver batterisparefunktion"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Mens der optages eller castes, kan <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> registrere alle følsomme oplysninger, der vises på din skærm eller afspilles på din enhed, f.eks. lyd, adgangskoder, betalingsoplysninger, billeder og beskeder."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Mens der optages eller castes, kan den tjeneste, som leverer funktionen, registrere alle følsomme oplysninger, der vises på din skærm eller afspilles på din enhed, f.eks. lyd, adgangskoder, betalingsoplysninger, billeder og beskeder."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Visning af følsomme oplysninger, mens der castes/optages"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> får adgang til alle de oplysninger, der er synlige på din skærm, eller som afspilles på din enhed, når du optager eller caster. Dette omfatter oplysninger som f.eks. adgangskoder, betalingsoplysninger, billeder, beskeder og afspillet lyd."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Tjenesten, der tilbyder denne funktion, får adgang til alle de oplysninger, der er synlige på din skærm, eller som afspilles på din enhed, når du optager eller caster. Dette omfatter oplysninger som f.eks. adgangskoder, betalingsoplysninger, billeder, beskeder og afspillet lyd."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Vil du begynde at optage eller caste via <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Vis ikke igen"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Ryd alle"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Administrer"</string>
@@ -718,7 +716,7 @@
<string name="keyboard_key_dpad_left" msgid="8329738048908755640">"Venstre"</string>
<string name="keyboard_key_dpad_right" msgid="6282105433822321767">"Højre"</string>
<string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Midtertast"</string>
- <string name="keyboard_key_tab" msgid="4592772350906496730">"Tabulatortast"</string>
+ <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab-tast"</string>
<string name="keyboard_key_space" msgid="6980847564173394012">"Mellemrumstast"</string>
<string name="keyboard_key_enter" msgid="8633362970109751646">"Enter"</string>
<string name="keyboard_key_backspace" msgid="4095278312039628074">"Tilbagetast"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Tastaturskifter"</string>
<string name="save" msgid="3392754183673848006">"Gem"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Nulstil"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Juster knappens bredde"</string>
<string name="clipboard" msgid="8517342737534284617">"Udklipsholder"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Tilpasset navigationsknap"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Højre"</string>
<string name="tuner_menu" msgid="363690665924769420">"Menu"</string>
<string name="tuner_app" msgid="6949280415826686972">"Appen <xliff:g id="APP">%1$s</xliff:g>"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Underretninger"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Batteri"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Screenshots"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Generelle meddelelser"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> kører"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"En app blev åbnet uden at blive installeret."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"En app blev åbnet uden at blive installeret. Tryk for at få flere oplysninger."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Appinfo"</string>
<string name="go_to_web" msgid="636673528981366511">"Gå til en browser"</string>
<string name="mobile_data" msgid="4564407557775397216">"Mobildata"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Indstillinger"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"OK"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Gem SysUI-heap"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> anvender enhedens <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Apps anvender enhedens <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" og "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"placering"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Deaktiver sensorer"</string>
<string name="device_services" msgid="1549944177856658705">"Enhedstjenester"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Ingen titel"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Systemnavigationen blev opdateret. Gå til Indstillinger for at foretage ændringer."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Gå til Indstillinger for at opdatere systemnavigationen"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Standby"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Vindue med overlejret forstørrelse"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Vindue med forstørrelse"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Vindue med forstørrelsesstyring"</string>
</resources>
diff --git a/packages/SystemUI/res/values-da/strings_tv.xml b/packages/SystemUI/res/values-da/strings_tv.xml
index 6093f9391f48..5b8bf6c9c2c4 100644
--- a/packages/SystemUI/res/values-da/strings_tv.xml
+++ b/packages/SystemUI/res/values-da/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Program uden titel)"</string>
<string name="pip_close" msgid="5775212044472849930">"Luk integreret billede"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Fuld skærm"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Mikrofonen er slået til"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s fik adgang til din mikrofon"</string>
</resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 7e54703c151b..7defdc1b8972 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Weitere Informationen"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Zoom auf Bildschirmgröße"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Auf Bildschirmgröße anpassen"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Screenshot wird gespeichert..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Screenshot wird gespeichert..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot gespeichert"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"Telefon öffnen"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"Sprachassistent öffnen"</string>
<string name="camera_label" msgid="8253821920931143699">"Kamera öffnen"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Abbrechen"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Bestätigen"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Noch einmal versuchen"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Zum Abbrechen der Authentifizierung tippen"</string>
@@ -391,7 +389,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"An um <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Bis <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Dunkles Design"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Dunkles Design\nEnergiesparmodus"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Energiesparmodus"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"An bei Sonnenuntergang"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Bis Sonnenaufgang"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC ist deaktiviert"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ist aktiviert"</string>
@@ -416,10 +416,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Erneut tippen, um Benachrichtigung zu öffnen"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Zum Öffnen nach oben wischen"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Zum Wiederholen nach oben wischen"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Dieses Gerät wird von deiner Organisation verwaltet"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Dieses Gerät wird von <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> verwaltet"</string>
<string name="phone_hint" msgid="6682125338461375925">"Zum Öffnen des Telefons vom Symbol wegwischen"</string>
@@ -471,9 +467,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Energiesparmodus ist aktiviert"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Reduzierung der Leistung und Hintergrunddaten"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Energiesparmodus deaktivieren"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Beim Aufnehmen oder Streamen kann <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> vertrauliche Informationen erfassen, die auf deinem Bildschirm angezeigt oder von deinem Gerät wiedergegeben werden. Das können beispielsweise Audioinhalte, deine Passwörter, deine Zahlungsinformationen sowie Fotos und Nachrichten sein."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Beim Aufnehmen oder Streamen kann der Dienst, der diese Funktion zur Verfügung stellt, vertrauliche Informationen erfassen, die auf deinem Bildschirm angezeigt oder von deinem Gerät wiedergegeben werden. Das können beispielsweise Audioinhalte, deine Passwörter, deine Zahlungsinformationen sowie Fotos und Nachrichten sein."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Beim Streamen/Aufzeichnen werden vertrauliche Informationen zugänglich gemacht"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"Die App \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\" erhält Zugriff auf alle Informationen, die auf deinem Bildschirm sichtbar sind oder von deinem Gerät wiedergegeben werden, während du aufnimmst oder streamst. Dazu gehören beispielsweise Passwörter, Zahlungsdetails, Fotos, Nachrichten und Audioinhalte."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Der Anbieter dieser App erhält Zugriff auf alle Informationen, die auf deinem Bildschirm sichtbar sind oder von deinem Gerät wiedergegeben werden, während du aufnimmst oder streamst. Dazu gehören beispielsweise Passwörter, Zahlungsdetails, Fotos, Nachrichten und Audioinhalte."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Aufnehmen oder Streamen mit der App \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\" starten?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Nicht mehr anzeigen"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Alle löschen"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Verwalten"</string>
@@ -790,8 +788,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Tastaturwechsler"</string>
<string name="save" msgid="3392754183673848006">"Speichern"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Zurücksetzen"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Schaltflächenbreite anpassen"</string>
<string name="clipboard" msgid="8517342737534284617">"Zwischenablage"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Benutzerdefinierte Navigationsschaltfläche"</string>
@@ -887,8 +884,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Rechts"</string>
<string name="tuner_menu" msgid="363690665924769420">"Menü"</string>
<string name="tuner_app" msgid="6949280415826686972">"App \"<xliff:g id="APP">%1$s</xliff:g>\""</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Benachrichtigungen"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Akku"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Screenshots"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Nachrichten"</string>
@@ -898,8 +894,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> wird ausgeführt"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"App wurde geöffnet, ohne vorher installiert zu werden."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"App wurde geöffnet, ohne vorher installiert zu werden. Tippe, um weitere Informationen zu erhalten."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"App-Info"</string>
<string name="go_to_web" msgid="636673528981366511">"Browser öffnen"</string>
<string name="mobile_data" msgid="4564407557775397216">"Mobile Daten"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -933,13 +928,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Einstellungen"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Ok"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> verwendet gerade Folgendes: <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Apps verwenden gerade Folgendes: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" und "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"Kamera"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"Standort"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"Mikrofon"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensoren aus"</string>
<string name="device_services" msgid="1549944177856658705">"Gerätedienste"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Kein Titel"</string>
@@ -962,4 +950,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Systemsteuerungseinstellungen wurden angepasst. Änderungen kannst du in den Einstellungen vornehmen."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Gehe zu den Einstellungen, um die Systemsteuerung anzupassen"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Standby"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Overlay-Vergrößerungsfenster"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Vergrößerungsfenster"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Einstellungen für Vergrößerungsfenster"</string>
</resources>
diff --git a/packages/SystemUI/res/values-de/strings_tv.xml b/packages/SystemUI/res/values-de/strings_tv.xml
index fca013a82062..ba2052840c10 100644
--- a/packages/SystemUI/res/values-de/strings_tv.xml
+++ b/packages/SystemUI/res/values-de/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Kein Sendungsname gefunden)"</string>
<string name="pip_close" msgid="5775212044472849930">"PIP schließen"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Vollbild"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Mikrofon aktiv"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s hat auf dein Mikrofon zugegriffen"</string>
</resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index ab7f1e577219..8a71fb27655d 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Μάθετε περισσότερα"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Ζουμ σε πλήρη οθόνη"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Προβoλή σε πλήρη οθ."</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Στιγμιότυπο οθόνης"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Αποθήκ. στιγμιότυπου οθόνης..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Αποθήκευση στιγμιότυπου οθόνης..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Το στιγμιότυπο οθόνης αποθηκεύτηκε"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"άνοιγμα τηλεφώνου"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"άνοιγμα φωνητικής υποβοήθησης"</string>
<string name="camera_label" msgid="8253821920931143699">"άνοιγμα φωτογραφικής μηχανής"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Ακύρωση"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Επιβεβαίωση"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Δοκιμάστε ξανά"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Πατήστε για ακύρωση του ελέγχου ταυτότητας"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Ενεργοποίηση στις <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Έως τις <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Σκούρο θέμα"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Σκούρο θέμα\nΕξοικονόμηση μπαταρίας"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Εξοικονόμ. μπαταρίας"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Κατά τη δύση"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Μέχρι την ανατολή"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"Το NFC είναι απενεργοποιημένο"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"Το NFC είναι ενεργοποιημένο"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Πατήστε ξανά για να ανοίξετε"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Σύρετε προς τα επάνω για άνοιγμα"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Σύρετε προς τα πάνω για να δοκιμάσετε ξανά"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Αυτή η συσκευή είναι διαχειριζόμενη από τον οργανισμό σας"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Τη συσκευή διαχειρίζεται ο οργανισμός <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Σύρετε προς τα έξω για τηλέφωνο"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Η Εξοικονόμηση μπαταρίας είναι ενεργή"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Μειώνει την απόδοση και τα δεδομένα παρασκηνίου"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Απενεργοποίηση Εξοικονόμησης μπαταρίας"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Κατά την εγγραφή ή τη μετάδοση, η εφαρμογή <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> μπορεί να καταγράφει τυχόν ευαίσθητες πληροφορίες που εμφανίζονται στην οθόνη σας ή των οποίων γίνεται αναπαραγωγή από τη συσκευή σας, συμπεριλαμβανομένων ευαίσθητων πληροφοριών όπως ήχος, κωδικοί πρόσβασης, στοιχεία πληρωμής, φωτογραφίες και μηνύματα."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Κατά την εγγραφή ή τη μετάδοση, η υπηρεσία που παρέχει αυτήν τη λειτουργία μπορεί να καταγράφει τυχόν ευαίσθητες πληροφορίες που εμφανίζονται στην οθόνη σας ή των οποίων γίνεται αναπαραγωγή από τη συσκευή σας, συμπεριλαμβανομένων ευαίσθητων πληροφοριών όπως ήχος, κωδικοί πρόσβασης, στοιχεία πληρωμής, φωτογραφίες και μηνύματα."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Έκθεση ευαίσθητων πληροφοριών κατά τη μετάδοση/εγγραφή"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"Η εφαρμογή <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> θα έχει πρόσβαση σε όλες τις πληροφορίες που εμφανίζονται στην οθόνη σας ή που αναπαράγονται από τη συσκευή σας κατά την εγγραφή ή τη μετάδοση. Αυτό περιλαμβάνει πληροφορίες όπως κωδικούς πρόσβασης, στοιχεία πληρωμής, φωτογραφίες, μηνύματα και ήχο που αναπαράγετε."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Η υπηρεσία που παρέχει αυτήν τη λειτουργία θα έχει πρόσβαση σε όλες τις πληροφορίες που εμφανίζονται στην οθόνη σας ή που αναπαράγονται από τη συσκευή σας κατά την εγγραφή ή τη μετάδοση. Αυτό περιλαμβάνει πληροφορίες όπως κωδικούς πρόσβασης, στοιχεία πληρωμής, φωτογραφίες, μηνύματα και ήχο που αναπαράγετε."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Έναρξη εγγραφής ή μετάδοσης με <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>;"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Να μην εμφανιστεί ξανά"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Διαγραφή όλων"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Διαχείριση"</string>
@@ -642,7 +640,7 @@
<string name="do_not_silence" msgid="4982217934250511227">"Χωρίς σίγαση"</string>
<string name="do_not_silence_block" msgid="4361847809775811849">"Χωρίς σίγαση ή αποκλεισμό"</string>
<string name="tuner_full_importance_settings" msgid="1388025816553459059">"Στοιχεία ελέγχου ειδοποίησης ισχύος"</string>
- <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Ενεργή"</string>
+ <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Ενεργό"</string>
<string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Ανενεργή"</string>
<string name="power_notification_controls_description" msgid="1334963837572708952">"Με τα στοιχεία ελέγχου ειδοποίησης ισχύος, μπορείτε να ορίσετε ένα επίπεδο βαρύτητας από 0 έως 5 για τις ειδοποιήσεις μιας εφαρμογής. \n\n"<b>"Επίπεδο 5"</b>" \n- Εμφάνιση στην κορυφή της λίστας ειδοποιήσεων \n- Να επιτρέπεται η διακοπή πλήρους οθόνης \n- Να γίνεται πάντα σύντομη προβολή \n\n"<b>"Επίπεδο 4"</b>" \n- Αποτροπή διακοπής πλήρους οθόνης \n- Να γίνεται πάντα σύντομη προβολή \n\n"<b>"Επίπεδο 3"</b>" \n- Αποτροπή διακοπής πλήρους οθόνης \n- Να μην γίνεται ποτέ σύντομη προβολή \n\n"<b>"Επίπεδο 2"</b>" \n- Αποτροπή διακοπής πλήρους οθόνης \n- Να μην γίνεται ποτέ σύντομη προβολή \n- Να μην χρησιμοποιείται ποτέ ήχος και δόνηση \n\n"<b>"Επίπεδο 1"</b>" \n- Αποτροπή διακοπής πλήρους οθόνης \n- Να μην γίνεται ποτέ σύντομη προβολή \n- Να μην χρησιμοποιείται ποτέ ήχος και δόνηση \n- Απόκρυψη από την οθόνη κλειδώματος και τη γραμμή κατάστασης \n- Εμφάνιση στο κάτω μέρος της λίστας ειδοποιήσεων \n\n"<b>"Επίπεδο 0"</b>" \n- Αποκλεισμός όλων των ειδοποιήσεων από την εφαρμογή"</string>
<string name="notification_header_default_channel" msgid="225454696914642444">"Ειδοποιήσεις"</string>
@@ -765,7 +763,7 @@
<string name="data_saver" msgid="3484013368530820763">"Εξοικονόμηση δεδομένων"</string>
<string name="accessibility_data_saver_on" msgid="5394743820189757731">"Η Εξοικονόμηση δεδομένων είναι ενεργοποιημένη"</string>
<string name="accessibility_data_saver_off" msgid="58339669022107171">"Η Εξοικονόμηση δεδομένων είναι απενεργοποιημένη"</string>
- <string name="switch_bar_on" msgid="1770868129120096114">"Ενεργή"</string>
+ <string name="switch_bar_on" msgid="1770868129120096114">"Ενεργό"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Απενεργοποίηση"</string>
<string name="nav_bar" msgid="4642708685386136807">"Γραμμή πλοήγησης"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Διάταξη"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Εναλλαγή πληκτρολογίων"</string>
<string name="save" msgid="3392754183673848006">"Αποθήκευση"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Επαναφορά"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Προσαρμογή πλάτους κουμπιού"</string>
<string name="clipboard" msgid="8517342737534284617">"Πρόχειρο"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Προσαρμοσμένο κουμπί πλοήγησης"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Δεξιά"</string>
<string name="tuner_menu" msgid="363690665924769420">"Μενού"</string>
<string name="tuner_app" msgid="6949280415826686972">"Εφαρμογή <xliff:g id="APP">%1$s</xliff:g>"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Ειδοποιήσεις"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Μπαταρία"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Στιγμιότυπα οθόνης"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Γενικά μηνύματα"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"Η εφαρμογή <xliff:g id="APP">%1$s</xliff:g> εκτελείται"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Η εφαρμογή άνοιξε χωρίς να έχει εγκατασταθεί."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Η εφαρμογή άνοιξε χωρίς να έχει εγκατασταθεί. Πατήστε για να μάθετε περισσότερα."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Πληροφορ. εφαρμογής"</string>
<string name="go_to_web" msgid="636673528981366511">"Μετάβ. σε πρόγ. περ."</string>
<string name="mobile_data" msgid="4564407557775397216">"Δεδομένα κινητής τηλεφωνίας"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> - <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Ρυθμίσεις"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Το κατάλαβα"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Στιγμ. μνήμης SysUI"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"Η εφαρμογή <xliff:g id="APP">%1$s</xliff:g> χρησιμοποιεί τις λειτουργίες <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Οι εφαρμογές χρησιμοποιούν τις λειτουργίες <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" και "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"κάμερα"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"τοποθεσία"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"μικρόφωνο"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Αισθητήρες ανενεργοί"</string>
<string name="device_services" msgid="1549944177856658705">"Υπηρεσίες συσκευής"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Χωρίς τίτλο"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Η πλοήγηση συστήματος ενημερώθηκε. Για να κάνετε αλλαγές, μεταβείτε στις Ρυθμίσεις."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Μεταβείτε στις Ρυθμίσεις για να ενημερώσετε την πλοήγηση συστήματος"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Κατάσταση αναμονής"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Παράθυρο επικάλυψης μεγέθυνσης"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Παράθυρο μεγέθυνσης"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Στοιχεία ελέγχου παραθύρου μεγέθυνσης"</string>
</resources>
diff --git a/packages/SystemUI/res/values-el/strings_tv.xml b/packages/SystemUI/res/values-el/strings_tv.xml
index 14d071432903..5f93f3246f82 100644
--- a/packages/SystemUI/res/values-el/strings_tv.xml
+++ b/packages/SystemUI/res/values-el/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Δεν υπάρχει τίτλος προγράμματος)"</string>
<string name="pip_close" msgid="5775212044472849930">"Κλείσιμο PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Πλήρης οθόνη"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Ενεργό μικρόφωνο"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"Πραγματοποιήθηκε πρόσβαση στο μικρόφωνό σας από το %1$s"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 35d4b4f5c070..1ffd1b15f02b 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Learn more"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Zoom to fill screen"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Stretch to fill screen"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Saving screenshot…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Saving screenshot…"</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot saved"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"open phone"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"open voice assist"</string>
<string name="camera_label" msgid="8253821920931143699">"open camera"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Cancel"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Confirm"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Try again"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Tap to cancel authentication"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"On at <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Until <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Dark theme"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Dark theme\nBattery Saver"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Battery Saver"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"On at sunset"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Until sunrise"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC is disabled"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC is enabled"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Tap again to open"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Swipe up to open"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Swipe up to try again"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"This device is managed by your organisation"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"This device is managed by <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Swipe from icon for phone"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Battery Saver is on"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Reduces performance and background data"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Turn off Battery Saver"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"While recording or casting, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> can capture any sensitive information that is displayed on your screen or played from your device, including sensitive information such as audio, passwords, payment info, photos and messages."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"While recording or casting, the service providing this function can capture any sensitive information that is displayed on your screen or played from your device, including sensitive information such as audio, passwords, payment info, photos and messages."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Exposing sensitive info during casting/recording"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information, such as passwords, payment details, photos, messages and audio that you play."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"The service providing this function will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information, such as passwords, payment details, photos, messages and audio that you play."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Start recording or casting with <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Don\'t show again"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Clear all"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Manage"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Keyboard switcher"</string>
<string name="save" msgid="3392754183673848006">"Save"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Reset"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Adjust button width"</string>
<string name="clipboard" msgid="8517342737534284617">"Clipboard"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Customised navigation button"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Right"</string>
<string name="tuner_menu" msgid="363690665924769420">"Menu"</string>
<string name="tuner_app" msgid="6949280415826686972">"<xliff:g id="APP">%1$s</xliff:g> app"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Alerts"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Battery"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Screenshots"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"General Messages"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> running"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"App opened without being installed."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"App opened without being installed. Tap to find out more."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"App info"</string>
<string name="go_to_web" msgid="636673528981366511">"Go to browser"</string>
<string name="mobile_data" msgid="4564407557775397216">"Mobile data"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Settings"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"OK"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> is using your <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Applications are using your <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" and "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"camera"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"location"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"microphone"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensors off"</string>
<string name="device_services" msgid="1549944177856658705">"Device Services"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"No title"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"System navigation updated. To make changes, go to Settings."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Go to Settings to update system navigation"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Standby"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Magnification overlay window"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Magnification window"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Magnification window controls"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings_tv.xml b/packages/SystemUI/res/values-en-rAU/strings_tv.xml
index 0ec3ff5b8ce3..efbaa1c42e60 100644
--- a/packages/SystemUI/res/values-en-rAU/strings_tv.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(No title program)"</string>
<string name="pip_close" msgid="5775212044472849930">"Close PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Full screen"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Microphone active"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s accessed your microphone"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 9ac53cd816ad..652353c3d4de 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Learn more"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Zoom to fill screen"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Stretch to fill screen"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Saving screenshot…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Saving screenshot…"</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot saved"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"open phone"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"open voice assist"</string>
<string name="camera_label" msgid="8253821920931143699">"open camera"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Cancel"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Confirm"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Try again"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Tap to cancel authentication"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"On at <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Until <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Dark theme"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Dark theme\nBattery Saver"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Battery Saver"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"On at sunset"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Until sunrise"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC is disabled"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC is enabled"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Tap again to open"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Swipe up to open"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Swipe up to try again"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"This device is managed by your organisation"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"This device is managed by <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Swipe from icon for phone"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Battery Saver is on"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Reduces performance and background data"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Turn off Battery Saver"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"While recording or casting, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> can capture any sensitive information that is displayed on your screen or played from your device, including sensitive information such as audio, passwords, payment info, photos and messages."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"While recording or casting, the service providing this function can capture any sensitive information that is displayed on your screen or played from your device, including sensitive information such as audio, passwords, payment info, photos and messages."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Exposing sensitive info during casting/recording"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information, such as passwords, payment details, photos, messages and audio that you play."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"The service providing this function will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information, such as passwords, payment details, photos, messages and audio that you play."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Start recording or casting with <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Don\'t show again"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Clear all"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Manage"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Keyboard switcher"</string>
<string name="save" msgid="3392754183673848006">"Save"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Reset"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Adjust button width"</string>
<string name="clipboard" msgid="8517342737534284617">"Clipboard"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Customised navigation button"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Right"</string>
<string name="tuner_menu" msgid="363690665924769420">"Menu"</string>
<string name="tuner_app" msgid="6949280415826686972">"<xliff:g id="APP">%1$s</xliff:g> app"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Alerts"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Battery"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Screenshots"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"General Messages"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> running"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"App opened without being installed."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"App opened without being installed. Tap to find out more."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"App info"</string>
<string name="go_to_web" msgid="636673528981366511">"Go to browser"</string>
<string name="mobile_data" msgid="4564407557775397216">"Mobile data"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Settings"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"OK"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> is using your <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Applications are using your <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" and "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"camera"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"location"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"microphone"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensors off"</string>
<string name="device_services" msgid="1549944177856658705">"Device Services"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"No title"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"System navigation updated. To make changes, go to Settings."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Go to Settings to update system navigation"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Standby"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Magnification overlay window"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Magnification window"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Magnification window controls"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rCA/strings_tv.xml b/packages/SystemUI/res/values-en-rCA/strings_tv.xml
index 0ec3ff5b8ce3..efbaa1c42e60 100644
--- a/packages/SystemUI/res/values-en-rCA/strings_tv.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(No title program)"</string>
<string name="pip_close" msgid="5775212044472849930">"Close PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Full screen"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Microphone active"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s accessed your microphone"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 35d4b4f5c070..1ffd1b15f02b 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Learn more"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Zoom to fill screen"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Stretch to fill screen"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Saving screenshot…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Saving screenshot…"</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot saved"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"open phone"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"open voice assist"</string>
<string name="camera_label" msgid="8253821920931143699">"open camera"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Cancel"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Confirm"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Try again"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Tap to cancel authentication"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"On at <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Until <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Dark theme"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Dark theme\nBattery Saver"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Battery Saver"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"On at sunset"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Until sunrise"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC is disabled"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC is enabled"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Tap again to open"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Swipe up to open"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Swipe up to try again"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"This device is managed by your organisation"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"This device is managed by <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Swipe from icon for phone"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Battery Saver is on"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Reduces performance and background data"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Turn off Battery Saver"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"While recording or casting, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> can capture any sensitive information that is displayed on your screen or played from your device, including sensitive information such as audio, passwords, payment info, photos and messages."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"While recording or casting, the service providing this function can capture any sensitive information that is displayed on your screen or played from your device, including sensitive information such as audio, passwords, payment info, photos and messages."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Exposing sensitive info during casting/recording"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information, such as passwords, payment details, photos, messages and audio that you play."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"The service providing this function will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information, such as passwords, payment details, photos, messages and audio that you play."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Start recording or casting with <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Don\'t show again"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Clear all"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Manage"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Keyboard switcher"</string>
<string name="save" msgid="3392754183673848006">"Save"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Reset"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Adjust button width"</string>
<string name="clipboard" msgid="8517342737534284617">"Clipboard"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Customised navigation button"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Right"</string>
<string name="tuner_menu" msgid="363690665924769420">"Menu"</string>
<string name="tuner_app" msgid="6949280415826686972">"<xliff:g id="APP">%1$s</xliff:g> app"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Alerts"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Battery"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Screenshots"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"General Messages"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> running"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"App opened without being installed."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"App opened without being installed. Tap to find out more."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"App info"</string>
<string name="go_to_web" msgid="636673528981366511">"Go to browser"</string>
<string name="mobile_data" msgid="4564407557775397216">"Mobile data"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Settings"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"OK"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> is using your <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Applications are using your <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" and "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"camera"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"location"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"microphone"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensors off"</string>
<string name="device_services" msgid="1549944177856658705">"Device Services"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"No title"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"System navigation updated. To make changes, go to Settings."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Go to Settings to update system navigation"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Standby"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Magnification overlay window"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Magnification window"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Magnification window controls"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings_tv.xml b/packages/SystemUI/res/values-en-rGB/strings_tv.xml
index 0ec3ff5b8ce3..efbaa1c42e60 100644
--- a/packages/SystemUI/res/values-en-rGB/strings_tv.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(No title program)"</string>
<string name="pip_close" msgid="5775212044472849930">"Close PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Full screen"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Microphone active"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s accessed your microphone"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 35d4b4f5c070..1ffd1b15f02b 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Learn more"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Zoom to fill screen"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Stretch to fill screen"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Saving screenshot…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Saving screenshot…"</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot saved"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"open phone"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"open voice assist"</string>
<string name="camera_label" msgid="8253821920931143699">"open camera"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Cancel"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Confirm"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Try again"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Tap to cancel authentication"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"On at <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Until <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Dark theme"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Dark theme\nBattery Saver"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Battery Saver"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"On at sunset"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Until sunrise"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC is disabled"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC is enabled"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Tap again to open"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Swipe up to open"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Swipe up to try again"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"This device is managed by your organisation"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"This device is managed by <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Swipe from icon for phone"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Battery Saver is on"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Reduces performance and background data"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Turn off Battery Saver"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"While recording or casting, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> can capture any sensitive information that is displayed on your screen or played from your device, including sensitive information such as audio, passwords, payment info, photos and messages."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"While recording or casting, the service providing this function can capture any sensitive information that is displayed on your screen or played from your device, including sensitive information such as audio, passwords, payment info, photos and messages."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Exposing sensitive info during casting/recording"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information, such as passwords, payment details, photos, messages and audio that you play."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"The service providing this function will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information, such as passwords, payment details, photos, messages and audio that you play."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Start recording or casting with <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Don\'t show again"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Clear all"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Manage"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Keyboard switcher"</string>
<string name="save" msgid="3392754183673848006">"Save"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Reset"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Adjust button width"</string>
<string name="clipboard" msgid="8517342737534284617">"Clipboard"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Customised navigation button"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Right"</string>
<string name="tuner_menu" msgid="363690665924769420">"Menu"</string>
<string name="tuner_app" msgid="6949280415826686972">"<xliff:g id="APP">%1$s</xliff:g> app"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Alerts"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Battery"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Screenshots"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"General Messages"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> running"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"App opened without being installed."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"App opened without being installed. Tap to find out more."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"App info"</string>
<string name="go_to_web" msgid="636673528981366511">"Go to browser"</string>
<string name="mobile_data" msgid="4564407557775397216">"Mobile data"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Settings"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"OK"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> is using your <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Applications are using your <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" and "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"camera"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"location"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"microphone"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensors off"</string>
<string name="device_services" msgid="1549944177856658705">"Device Services"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"No title"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"System navigation updated. To make changes, go to Settings."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Go to Settings to update system navigation"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Standby"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Magnification overlay window"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Magnification window"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Magnification window controls"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings_tv.xml b/packages/SystemUI/res/values-en-rIN/strings_tv.xml
index 0ec3ff5b8ce3..efbaa1c42e60 100644
--- a/packages/SystemUI/res/values-en-rIN/strings_tv.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(No title program)"</string>
<string name="pip_close" msgid="5775212044472849930">"Close PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Full screen"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Microphone active"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s accessed your microphone"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index f7c937b45c62..cc5ae646e6d2 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -385,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‎‎‏‏‎‎‏‎‏‏‎‏‏‎‎‎‏‎‎‎‏‎‎‎‎‎‏‏‏‎‏‎‏‎‏‏‏‎‏‎‏‎‏‎‏‏‎On at ‎‏‎‎‏‏‎<xliff:g id="TIME">%s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‎‎‏‎‎‏‎‏‎‎‏‏‏‏‏‎‏‏‏‏‏‎‏‎‎‎‏‎‎‏‎‎‎‎‎‎‏‎‏‏‏‏‏‎‏‎‏‎‎‏‎‎‏‏‎‎‎Until ‎‏‎‎‏‏‎<xliff:g id="TIME">%s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‏‎‏‏‎‏‎‎‏‏‏‏‏‏‏‎‏‏‏‎‏‏‎‎‏‏‎‏‎‏‏‎‎‎‎‎‎‎‎‎‏‏‏‎‏‎‎‎‏‎‎‏‏‎‏‏‎‎Dark theme‎‏‎‎‏‎"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‏‎‎‎‏‎‎‎‏‏‎‎‏‏‏‎‎‏‎‎‏‎‏‎‏‏‏‎‏‎‎‎‎‏‏‎‏‏‏‏‎‏‏‎‎‎‎‎‎‎‏‏‏‏‎‏‎Dark theme‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Battery saver‎‏‎‎‏‎"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‏‎‎‎‎‏‎‏‎‎‏‎‎‏‎‏‏‎‎‏‎‏‎‎‏‎‎‎‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‏‎Battery Saver‎‏‎‎‏‎"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‎‎‎‏‎‎‎‎‎‏‏‎‏‎‎‎‎‏‎‎‏‏‎‏‏‎‏‏‏‏‎‎On at sunset‎‏‎‎‏‎"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‎‎‏‎‎‎‎‏‎‏‎‎‏‎‏‏‏‎‏‎‎‎‏‎‎‎‏‎‎‏‎‎‏‎‏‎‎‏‏‎‎‏‎‎‎‎‎‏‏‎‏‏‏‎‎‎‎Until sunrise‎‏‎‎‏‎"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‎‏‎‎‎‎‏‏‎‏‏‎‎‎‎‎‎‎‏‏‎‏‎‏‎‏‎‎‎‏‎‎‏‎‏‏‏‏‎‏‏‎‏‎‎‎‏‏‏‎‏‎‏‎‏‎NFC‎‏‎‎‏‎"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‎‎‎‏‎‏‏‎‎‎‏‎‎‏‏‏‎‎‏‏‎‎‎‏‏‏‏‎‎‎‏‎‏‎‎‎‎‏‎‏‎‎‎‎‎‏‎‏‏‎‎‏‎‏‏‏‎NFC is disabled‎‏‎‎‏‎"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‏‏‏‏‎‎‏‎‎‏‏‎‎‏‎‎‏‏‏‎‎‏‏‏‎‎‏‏‏‏‏‎‎‏‎‏‎‏‏‏‏‎‏‏‏‏‎‎‏‎‏‏‎‏‏‎‎NFC is enabled‎‏‎‎‏‎"</string>
@@ -410,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‎‎‏‎‎‎‏‎‏‎‏‎‎‎‎‏‎‎‏‎‎‏‏‎‎‎‏‏‎‎‎‎‎‎‎‏‏‎‎‏‎‏‏‏‎‎‎‏‎‎‏‎‎‎‎‏‎Tap again to open‎‏‎‎‏‎"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‏‏‎‏‏‏‎‏‎‎‏‏‏‏‎‏‏‎‏‏‏‎‎‏‏‏‏‎‏‎‎‎‎‎‏‏‏‎‏‏‏‎‎‎‏‎‎‏‎‎‎‎‎‏‎Swipe up to open‎‏‎‎‏‎"</string>
<string name="keyguard_retry" msgid="886802522584053523">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‎‎‏‎‎‏‏‏‎‏‎‎‎‏‏‏‎‎‎‏‏‎‎‏‎‎‎‏‎‎‎‎‎‏‎‎‎‏‎‏‎‏‏‏‏‎‏‏‏‎‎‎‏‎‎‏‏‎Swipe up to try again‎‏‎‎‏‎"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‏‎‎‏‎‎‏‎‎‎‎‏‏‎‏‏‏‎‎‎‎‎‏‏‏‎‏‏‏‎‎‏‎‏‏‎‎‎‎‎‎‎‏‎‎‎‎‎‏‎‎‎‎‏‎‎‎‎This device is managed by your organization‎‏‎‎‏‎"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‎‎‎‏‎‏‎‎‎‎‏‏‎‎‏‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‏‎‎‎‏‎‏‎‏‎‏‏‏‏‎‏‏‎‏‏‎This device is managed by ‎‏‎‎‏‏‎<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
<string name="phone_hint" msgid="6682125338461375925">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‎‏‏‏‎‏‏‏‎‏‎‏‏‎‏‏‎‎‏‎‏‏‏‏‎‎‎‎‏‏‏‏‎‏‎‎‎‎‎‏‎‎‎‏‏‎‏‏‎‏‏‎‏‎‏‎Swipe from icon for phone‎‏‎‎‏‎"</string>
@@ -465,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‏‎‏‏‏‎‎‏‏‏‏‏‎‎‏‎‏‎‎‎‏‎‎‎‎‎‎‎‏‏‎‏‏‎‏‎‏‎‏‏‎‏‏‏‏‏‏‎‏‎‎‏‎‎Battery Saver is on‎‏‎‎‏‎"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‎‏‎‏‎‏‎‎‎‏‏‏‎‎‎‏‎‎‎‏‏‎‎‏‎‎‏‏‎‎‏‎‏‏‎‎‎‏‎‏‎‏‎‏‏‏‎‎‎‏‏‏‎‏‏‏‎Reduces performance and background data‎‏‎‎‏‎"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‎‎‏‎‎‏‎‏‏‎‎‎‏‎‎‏‎‏‏‎‎‎‎‎‏‏‎‏‏‏‏‎‎‏‏‏‎‎‎‎‏‎‏‏‎‏‎‏‏‎‎‎‏‏‏‎Turn off Battery Saver‎‏‎‎‏‎"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‎‎‏‏‏‎‏‏‏‎‏‎‎‏‏‎‏‏‏‏‏‏‏‎‎‏‏‏‎‏‏‏‏‎‏‎‎‏‏‏‏‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‏‎While recording or casting, ‎‏‎‎‏‏‎<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>‎‏‎‎‏‏‏‎ can capture any sensitive information that is displayed on your screen or played from your device, including sensitive information such as audio, passwords, payment info, photos and messages.‎‏‎‎‏‎"</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‎‎‎‎‏‏‏‎‎‏‏‏‎‏‏‏‏‏‎‎‏‎‎‎‏‏‏‏‎‏‏‎‏‏‎‏‏‎‎‏‏‏‏‎‏‎‎‎‎‏‎‏‎‎‎‎While recording or casting, the service providing this function can capture any sensitive information that is displayed on your screen or played from your device, including sensitive information such as audio, passwords, payment info, photos and messages.‎‏‎‎‏‎"</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‎‎‎‏‎‎‏‎‎‎‏‎‏‏‎‏‏‎‏‏‏‎‏‎‏‏‏‏‎‎‏‏‎‏‏‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎Exposing sensitive info during casting/recording‎‏‎‎‏‎"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‎‎‏‎‏‏‏‎‏‏‎‎‎‎‏‎‎‏‎‏‎‎‏‎‏‎‎‏‏‏‎‎‏‎‏‎‎‏‎‏‎‏‏‎‎‏‎‏‏‎‏‎‏‎‏‎‎‎‎‏‎‎‏‏‎<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>‎‏‎‎‏‏‏‎ will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information such as passwords, payment details, photos, messages, and audio that you play.‎‏‎‎‏‎"</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‎‏‎‎‏‎‏‏‏‎‎‎‎‎‎‎‏‏‎‏‎‎‏‏‏‎‏‎‎‎‎‎‎‏‎‎‏‏‎‎‏‏‏‏‎‎‏‎‏‏‎‏‎‎‏‏‎The service providing this function will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information such as passwords, payment details, photos, messages, and audio that you play.‎‏‎‎‏‎"</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‎‎‎‎‎‎‏‎‏‎‎‎‎‎‏‏‎‎‏‎‎‏‎‏‏‏‎‎‏‏‏‏‏‎‏‏‎‏‏‏‎‎‏‎‏‎‏‏‎‏‎‎‎‎‏‏‎‎Start recording or casting with ‎‏‎‎‏‏‎<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‎‏‏‎‏‏‎‎‎‏‏‏‏‎‏‎‏‎‏‎‏‏‏‏‏‏‎‏‎‎‎‏‎‏‏‏‎‎‏‏‎‏‎‎‏‎‏‎‎‏‎‎‏‏‏‎Don\'t show again‎‏‎‎‏‎"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‎‏‏‎‏‎‏‎‏‎‏‏‏‎‏‎‎‎‏‎‎‎‎‎‏‎‏‎‏‏‏‏‎‏‏‎‎‏‎‎‏‏‎‎‏‎‎‎‏‏‏‏‏‎‎‏‎‎Clear all‎‏‎‎‏‎"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‎‎‎‏‏‏‎‏‎‏‏‏‎‎‏‏‏‏‏‎‏‎‏‏‎‎‏‎‎‎‏‎‎‎‎‏‏‎‎‏‏‎‏‏‏‏‏‎‏‏‏‏‏‎‎‎Manage‎‏‎‎‏‎"</string>
@@ -924,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‏‎‏‎‎‏‏‎‏‎‏‏‎‏‎‏‏‎‏‏‎‏‎‏‏‏‎‎‎‎‎‎‏‎‏‏‎‎‎‎‏‎‎‏‏‎‏‏‎‏‎‎‏‎‏‏‎‎Settings‎‏‎‎‏‎"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‏‏‎‏‏‏‏‎‏‏‏‏‏‏‎‎‎‎‏‏‏‏‎‏‎‎‏‎‏‏‏‏‎‎‏‏‎‏‎‎‏‎‎‏‎‏‎‎‎‏‏‎‏‎‎Got it‎‏‎‎‏‎"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‎‎‎‏‏‎‎‏‎‏‎‎‎‏‏‏‏‏‎‎‏‏‏‏‎‎‏‎‏‏‏‏‎‏‎‎‎‏‎‏‎‏‎‎‎‎‎‏‎‏‎‎‎‎‏‏‎‎Dump SysUI Heap‎‏‎‎‏‎"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‏‎‎‏‏‎‏‏‎‏‎‏‎‏‏‎‎‎‏‏‏‎‎‎‎‎‎‎‏‏‏‎‎‏‎‏‏‎‎‏‏‎‎‎‎‎‏‏‏‏‎‏‏‎‎‎‏‎‎‏‎‎‏‏‎<xliff:g id="APP">%1$s</xliff:g>‎‏‎‎‏‏‏‎ is using your ‎‏‎‎‏‏‎<xliff:g id="TYPES_LIST">%2$s</xliff:g>‎‏‎‎‏‏‏‎.‎‏‎‎‏‎"</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‎‎‎‎‏‏‏‏‏‎‎‏‏‏‏‎‎‎‏‏‏‎‏‎‏‏‏‎‎‎‏‏‏‏‎‎‏‏‎‎‏‏‎‏‎‎‏‎‏‎‎‏‎‎Applications are using your ‎‏‎‎‏‏‎<xliff:g id="TYPES_LIST">%s</xliff:g>‎‏‎‎‏‏‏‎.‎‏‎‎‏‎"</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‏‏‏‎‎‏‏‎‎‎‏‎‎‏‏‏‎‏‏‏‏‎‎‏‏‏‎‏‎‎‎‎‎‎‎‏‏‏‎‎‏‎‎‎‏‎‎‎‎‏‎‎‏‎‏‏‎, ‎‏‎‎‏‎ "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" ‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‏‏‏‎‏‏‏‏‏‎‎‏‏‎‎‏‏‎‎‏‎‎‏‎‎‏‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‎‏‏‎‏‎‏‎‎‏‎‎‏‏‏‎ and ‎‏‎‎‏‎ "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‏‎‏‎‎‏‏‎‎‎‎‏‎‏‎‏‏‏‏‎‏‏‏‏‎‏‎‏‏‎‏‏‎‎‏‎‎‎‎‎‎‎‎‏‎‏‏‎‏‏‏‏‎‎‎camera‎‏‎‎‏‎"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‏‏‎‎‏‏‏‎‏‏‏‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‎‏‎‎‎‏‏‏‏‏‏‎‎‏‎‏‏‏‎‎‎‏‏‏‏‎location‎‏‎‎‏‎"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‎‎‎‏‎‎‏‏‏‎‎‏‎‏‏‏‎‏‎‏‎‏‎‏‎‏‎‏‎‎‏‎‏‎‎‎‎‎‎‎‏‎‎‏‎‎‏‏‎‎‎microphone‎‏‎‎‏‎"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‏‏‏‎‏‏‏‏‎‏‎‎‏‎‎‏‏‏‎‏‎‎‎‏‎‏‎‎‏‏‎‎‎‏‏‎‏‎‏‎‏‏‎‏‎‏‏‏‎‎‎‏‏‏‎‎‎Sensors off‎‏‎‎‏‎"</string>
<string name="device_services" msgid="1549944177856658705">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‏‎‎‎‎‎‏‎‏‎‎‎‎‎‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‏‏‎‏‏‎‏‎‏‎‎‏‎‏‏‏‏‎‏‎‎‎‏‎‎‎‏‎Device Services‎‏‎‎‏‎"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‏‏‏‎‏‎‎‏‎‎‏‎‏‏‏‏‏‎‎‎‎‎‎‎‏‏‏‎‎‏‎‎‏‏‎‎‎‏‏‏‎‎‏‏‎‏‏‏‎‎‏‏‏‏‎‏‎‎No title‎‏‎‎‏‎"</string>
@@ -953,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‏‏‏‏‎‎‎‎‏‎‏‏‏‏‏‎‎‎‏‏‎‎‏‏‏‏‎‏‏‏‎‏‏‎‎‎‎‎‏‎‎‎‎‏‏‎‏‎‎‎‎‎‎‎‎‎System navigation updated. To make changes, go to Settings.‎‏‎‎‏‎"</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‎‏‏‏‏‏‏‏‏‎‏‏‎‏‏‎‎‎‎‏‏‏‏‏‎‎‎‏‎‏‏‏‎‎‏‎‏‎‎‎‏‏‏‏‏‎‎‎‏‎‏‏‎‎‎‎‎Go to Settings to update system navigation‎‏‎‎‏‎"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‎‎‎‎‎‎‎‎‎‏‏‏‎‏‏‎‏‏‏‎‏‏‎‎‎‎‏‏‎‎‏‎‏‎‎‏‎‏‎‎‎‏‎‏‎‎‏‏‎‏‏‏‎‎‏‎‏‎Standby‎‏‎‎‏‎"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‏‎‏‎‏‏‏‏‏‏‎‏‏‎‏‎‎‎‏‎‎‏‏‏‎‏‎‎‎‎‏‏‏‎‏‏‏‏‎‏‏‏‎‎‏‏‎‏‎‏‎‏‏‎‏‏‎‎Magnification Overlay Window‎‏‎‎‏‎"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‎‎‎‎‎‎‎‎‎‎‏‏‎‎‎‎‏‎‏‎‏‏‏‎‏‎‏‎‎‎‎‎‎‏‏‏‎‎‎‏‏‎‏‎‎‏‎‏‏‎‏‏‏‎‏‎Magnification Window‎‏‎‎‏‎"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‏‏‏‎‏‏‏‎‎‎‏‏‏‏‏‎‏‎‏‏‏‏‎‎‎‎‏‎‎‏‎‎‏‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‏‎Magnification Window Controls‎‏‎‎‏‎"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rXC/strings_tv.xml b/packages/SystemUI/res/values-en-rXC/strings_tv.xml
index 09c4f833bd7a..1ca2385af9c4 100644
--- a/packages/SystemUI/res/values-en-rXC/strings_tv.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‎‎‏‏‏‏‏‏‎‎‎‎‏‎‎‏‏‎‎‏‏‏‎‏‎‏‎‏‏‏‏‎‎‎‏‎‏‎‏‏‎‎‎‎‎‎‎‎‎‎‎‏‏‎‏‏‎(No title program)‎‏‎‎‏‎"</string>
<string name="pip_close" msgid="5775212044472849930">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‎‏‎‎‏‎‏‏‎‏‎‏‏‎‎‏‏‎‎‎‎‎‏‏‎‎‎‏‏‎‏‎‏‎‏‏‏‎‎‏‎‎‏‎‏‏‎‎‎‎‎‏‎‏‎‎Close PIP‎‏‎‎‏‎"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‏‏‎‏‎‎‎‏‎‏‏‎‏‎‏‎‎‎‏‎‏‎‏‏‏‎‏‎‎‏‏‏‏‎‎‎‎‏‏‎‏‏‎‎‏‏‎‏‎‏‏‎‏‏‎‏‎Full screen‎‏‎‎‏‎"</string>
+ <string name="mic_active" msgid="5766614241012047024">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‎‎‎‎‏‏‏‎‎‏‎‎‎‎‏‎‎‎‏‏‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‏‎‏‏‎‏‎‏‏‏‎‎‏‎‏‏‎‎‎‎‎Microphone Active‎‏‎‎‏‎"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‎‎‎‏‏‏‎‎‏‏‎‏‏‎‎‏‎‎‏‎‎‏‎‎‏‎‏‎‏‎‏‎‎‎‏‎‎‏‏‎‏‎‎‏‎‏‏‏‏‎‎‏‏‎‏‎‎‎%1$s accessed your microphone‎‏‎‎‏‎"</string>
</resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 1787643f3e68..713a9966609e 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Más información"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Zoom para ocupar la pantalla"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Estirar p/ ocupar la pantalla"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Captura de pantalla"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Guardando captura de pantalla"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Guardando la captura de pantalla..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Se guardó la captura de pantalla"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"abrir teléfono"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"abrir el asistente de voz"</string>
<string name="camera_label" msgid="8253821920931143699">"abrir cámara"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Cancelar"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Confirmar"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Volver a intentarlo"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Presiona para cancelar la autenticación"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"A la(s) <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Hasta <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Tema oscuro"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Tema oscuro\nAhorro de batería"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Ahorro de batería"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Al atardecer"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Hasta el amanecer"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"La tecnología NFC está inhabilitada"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"La tecnología NFC está habilitada"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Presionar de nuevo para abrir"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Desliza el dedo hacia arriba para abrir"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Desliza el dedo hacia arriba para volver a intentarlo"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Tu organización administra este dispositivo"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"<xliff:g id="ORGANIZATION_NAME">%s</xliff:g> administra este dispositivo"</string>
<string name="phone_hint" msgid="6682125338461375925">"Desliza el dedo para desbloquear el teléfono."</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"El Ahorro de batería está activado"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Reduce el rendimiento y el uso de datos en segundo plano."</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Desactivar el Ahorro de batería"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Durante una grabación o una transmisión, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> podrá capturar cualquier información sensible que se muestre en la pantalla o se reproduzca en tu dispositivo, como audio, contraseñas, información de pago, fotos y mensajes."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Durante una grabación o una transmisión, el servicio que brinda esta función podrá capturar cualquier información sensible que se muestre en la pantalla o se reproduzca en tu dispositivo, como audio, contraseñas, información de pago, fotos y mensajes."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Exposición de información sensible durante la grabación o transmisión"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> tendrá acceso a toda la información que sea visible en la pantalla o que reproduzcas en tu dispositivo durante una grabación o transmisión. Se incluyen las contraseñas, los detalles del pago, las fotos, los mensajes y el audio que reproduzcas."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"El servicio que brinda esta función tendrá acceso a toda la información que sea visible en la pantalla o que reproduzcas en tu dispositivo durante una grabación o transmisión. Se incluyen las contraseñas, los detalles del pago, las fotos, los mensajes y el audio que reproduzcas."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"¿Deseas iniciar una grabación o transmisión con <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"No volver a mostrar"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Borrar todo"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Administrar"</string>
@@ -538,7 +536,7 @@
<string name="keyguard_indication_trust_disabled" msgid="6820793704816727918">"El dispositivo permanecerá bloqueado hasta que lo desbloquees manualmente."</string>
<string name="hidden_notifications_title" msgid="1782412844777612795">"Recibe notificaciones más rápido"</string>
<string name="hidden_notifications_text" msgid="5899627470450792578">"Ver antes de desbloquear"</string>
- <string name="hidden_notifications_cancel" msgid="4805370226181001278">"No"</string>
+ <string name="hidden_notifications_cancel" msgid="4805370226181001278">"No, gracias"</string>
<string name="hidden_notifications_setup" msgid="2064795578526982467">"Configurar"</string>
<string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
<string name="volume_zen_end_now" msgid="5901885672973736563">"Desactivar ahora"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Cambio de teclado"</string>
<string name="save" msgid="3392754183673848006">"Guardar"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Restablecer"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Ajustar ancho del botón"</string>
<string name="clipboard" msgid="8517342737534284617">"Portapapeles"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Botón de navegación personalizado"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Derecha"</string>
<string name="tuner_menu" msgid="363690665924769420">"Menú"</string>
<string name="tuner_app" msgid="6949280415826686972">"App de <xliff:g id="APP">%1$s</xliff:g>"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Alertas"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Batería"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Capturas de pantalla"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Mensajes generales"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> en ejecución"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"La app se abrió sin instalarse."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"La app se abrió sin instalarse. Presiona para obtener más información."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Datos de la app"</string>
<string name="go_to_web" msgid="636673528981366511">"Ir al navegador"</string>
<string name="mobile_data" msgid="4564407557775397216">"Datos móviles"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Configuración"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Entendido"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Volcar pila de SysUI"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> está usando tu <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Hay aplicaciones que están usando tu <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" y "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"cámara"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"ubicación"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"micrófono"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Se desactivaron los sensores"</string>
<string name="device_services" msgid="1549944177856658705">"Servicios del dispositivo"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Sin título"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Se actualizó el sistema de navegación. Para hacer cambios, ve a Configuración."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Ve a Configuración para actualizar la navegación del sistema"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"En espera"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Ventana superpuesta de ampliación"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Ventana de ampliación"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Controles de ampliación de la ventana"</string>
</resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings_tv.xml b/packages/SystemUI/res/values-es-rUS/strings_tv.xml
index 1c0786589832..3921fd822e57 100644
--- a/packages/SystemUI/res/values-es-rUS/strings_tv.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Sin título de programa)"</string>
<string name="pip_close" msgid="5775212044472849930">"Cerrar PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Pantalla completa"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Micrófono activado"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s accedió al micrófono"</string>
</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 9a9f05193aa9..ffcafaec3756 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Más información"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Zoom para ajustar"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Expandir para ajustar"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Captura de pantalla"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Guardando captura..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Guardando captura..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Se ha guardado la captura de pantalla"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"abrir teléfono"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"abrir el asistente de voz"</string>
<string name="camera_label" msgid="8253821920931143699">"abrir cámara"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Cancelar"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Confirmar"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Reintentar"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Toca para cancelar la autenticación"</string>
@@ -357,7 +355,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="2325362583903258677">"AUTO"</string>
<string name="quick_settings_inversion_label" msgid="5078769633069667698">"Invertir colores"</string>
<string name="quick_settings_color_space_label" msgid="537528291083575559">"Modo de corrección de color"</string>
- <string name="quick_settings_more_settings" msgid="2878235926753776694">"Más opciones"</string>
+ <string name="quick_settings_more_settings" msgid="2878235926753776694">"Más ajustes"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Listo"</string>
<string name="quick_settings_connected" msgid="3873605509184830379">"Conectado"</string>
<string name="quick_settings_connected_battery_level" msgid="1322075669498906959">"Conectado (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería)"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Hora: <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Hasta las <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Tema oscuro"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Tema oscuro\nAhorro de batería"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Ahorro de batería"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Al anochecer"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Hasta el amanecer"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"La conexión NFC está inhabilitada"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"La conexión NFC está habilitada"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Toca de nuevo para abrir"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Desliza el dedo hacia arriba para abrir"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Desliza el dedo hacia arriba para volverlo a intentar"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Este dispositivo está administrado por tu organización"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Este dispositivo está administrado por <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Desliza desde el icono para abrir el teléfono"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Ahorro de batería activado"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Reduce el rendimiento y los datos en segundo plano"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Desactivar Ahorro de batería"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Mientras grabas o envías contenido, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> puede capturar información sensible que se muestre en la pantalla o que se reproduzca en el dispositivo, como audio, contraseñas, información de pagos, fotos y mensajes."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Mientras grabas o envías contenido, el servicio que ofrece esta función puede capturar información sensible que se muestre en la pantalla o que se reproduzca en el dispositivo, como audio, contraseñas, información de pagos, fotos y mensajes."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Sobre información sensible durante el envío y la grabación"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> tendrá acceso a toda la información que se muestra en pantalla o se reproduce en el dispositivo mientras grabas o envías contenido, incluyendo contraseñas, detalles de pagos, fotos, mensajes y audios que reproduzcas."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"El servicio que ofrece esta función tendrá acceso a toda la información que se muestra en pantalla o se reproduce en el dispositivo mientras grabas o envías contenido, incluyendo contraseñas, detalles de pagos, fotos, mensajes y audios que reproduzcas."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"¿Quieres iniciar la grabación o el envío de contenido con <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"No volver a mostrar"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Borrar todo"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Gestionar"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Cambio de teclado"</string>
<string name="save" msgid="3392754183673848006">"Guardar"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Restablecer"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Ajustar el ancho del botón"</string>
<string name="clipboard" msgid="8517342737534284617">"Portapapeles"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Botón de navegación personalizada"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Derecha"</string>
<string name="tuner_menu" msgid="363690665924769420">"Menú"</string>
<string name="tuner_app" msgid="6949280415826686972">"Aplicación <xliff:g id="APP">%1$s</xliff:g>"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Alertas"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Batería"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Capturas de pantalla"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Mensajes generales"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> se está ejecutando"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"La aplicación se ha abierto sin instalarse."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"La aplicación se ha abierto sin instalarse. Toca para obtener más información."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Datos de aplicación"</string>
<string name="go_to_web" msgid="636673528981366511">"Ir al navegador"</string>
<string name="mobile_data" msgid="4564407557775397216">"Datos móviles"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> ‑ <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Ajustes"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Entendido"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Volcar pila de SysUI"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> está usando tu <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Hay aplicaciones que usan tu <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" y "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"cámara"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"ubicación"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"micrófono"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensores desactivados"</string>
<string name="device_services" msgid="1549944177856658705">"Servicios del dispositivo"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Sin título"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Se ha actualizado la navegación del sistema. Para hacer cambios, ve a Ajustes."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Ve a Ajustes para actualizar la navegación del sistema"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"En espera"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Ventana de superposición de ampliación"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Ventana de ampliación"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Ventana de controles de ampliación"</string>
</resources>
diff --git a/packages/SystemUI/res/values-es/strings_tv.xml b/packages/SystemUI/res/values-es/strings_tv.xml
index 9fca458e25b2..e18d9b6075bc 100644
--- a/packages/SystemUI/res/values-es/strings_tv.xml
+++ b/packages/SystemUI/res/values-es/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Programa sin título)"</string>
<string name="pip_close" msgid="5775212044472849930">"Cerrar PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Pantalla completa"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Micrófono activado"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s ha accedido a tu micrófono"</string>
</resources>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 31bffa34ce5c..db87961a8a65 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Lisateave"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Suumi ekraani täitmiseks"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Venita ekraani täitmiseks"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Ekraanipilt"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Kuvatõmmise salvestamine ..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Kuvatõmmise salvestamine ..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Ekraanipilt salvestati"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"ava telefon"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"ava häälabi"</string>
<string name="camera_label" msgid="8253821920931143699">"ava kaamera"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Tühista"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Kinnita"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Proovi uuesti"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Puudutage autentimise tühistamiseks"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Sisselülitam. kell <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Kuni <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Tume teema"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Tume teema\nAkusäästja"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Akusäästja"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Sisse päikeselooj."</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Kuni päikesetõusuni"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC on keelatud"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC on lubatud"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Avamiseks puudutage uuesti"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Pühkige avamiseks üles"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Uuesti proovimiseks pühkige üles"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Seda seadet haldab teie organisatsioon"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Seda seadet haldab <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Telefoni kasutamiseks pühkige ikoonilt eemale"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Akusäästja on sisse lülitatud"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Vähendab jõudlust ja taustaandmeid"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Akusäästja väljalülitamine"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> saab salvestamisel või ülekandmisel jäädvustada teie ekraanil kuvatud või teie seadmes esitatud mis tahes tundliku teabe, sh sellise tundliku teabe nagu heli, paroolid, makseteave, fotod ja sõnumid."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Seda funktsiooni pakkuv teenus saab salvestamisel või ülekandmisel jäädvustada teie ekraanil kuvatud või teie seadmes esitatud mis tahes tundliku teabe, sh sellise tundliku teabe nagu heli, paroolid, makseteave, fotod ja sõnumid."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Ülekandmise/salvestamise ajal kuvatakse tundlikku teavet"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"Rakendus <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> saab juurdepääsu kogu teabele, mis on teie ekraanikuval nähtav või mida seadmes salvestamise või ülekande ajal esitatakse. See hõlmab teavet, nagu paroolid, maksete üksikasjad, fotod, sõnumid ja esitatav heli."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Seda funktsiooni pakkuv teenus saab juurdepääsu kogu teabele, mis on teie ekraanikuval nähtav või mida seadmes salvestamise või ülekande ajal esitatakse. See hõlmab teavet, nagu paroolid, maksete üksikasjad, fotod, sõnumid ja esitatav heli."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Kas alustada rakendusega <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> salvestamist või ülekannet?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Ära kuva uuesti"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Tühjenda kõik"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Haldamine"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Klaviatuuri vahetaja"</string>
<string name="save" msgid="3392754183673848006">"Salvesta"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Lähtesta"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Nupu laiuse reguleerimine"</string>
<string name="clipboard" msgid="8517342737534284617">"Lõikelaud"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Kohandatud navigeerimisnupp"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Parem"</string>
<string name="tuner_menu" msgid="363690665924769420">"Menüü"</string>
<string name="tuner_app" msgid="6949280415826686972">"Rakendus <xliff:g id="APP">%1$s</xliff:g>"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Hoiatused"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Aku"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Ekraanipildid"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Üldised sõnumid"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"Rakendus <xliff:g id="APP">%1$s</xliff:g> töötab"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Rakendus avati installimata."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Rakendus avati installimata. Lisateabe saamiseks puudutage."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Rakenduse teave"</string>
<string name="go_to_web" msgid="636673528981366511">"Ava brauser"</string>
<string name="mobile_data" msgid="4564407557775397216">"Mobiilne andmeside"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Seaded"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Selge"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> kasutab järgmisi: <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Rakendused kasutavad järgmisi: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" ja "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"kaamera"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"asukoht"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Andurid on välja lülitatud"</string>
<string name="device_services" msgid="1549944177856658705">"Seadme teenused"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Pealkiri puudub"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Süsteemis navigeerimine on värskendatud. Muutmiseks avage jaotis Seaded."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Süsteemi navigeerimise värskendamiseks avage jaotis Seaded"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Ooterežiim"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Suurendamisakna ülekate"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Suurendamisaken"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Suurendamisakna juhtelemendid"</string>
</resources>
diff --git a/packages/SystemUI/res/values-et/strings_tv.xml b/packages/SystemUI/res/values-et/strings_tv.xml
index 6230d2fb7f15..f36d8ec89eed 100644
--- a/packages/SystemUI/res/values-et/strings_tv.xml
+++ b/packages/SystemUI/res/values-et/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Programmi pealkiri puudub)"</string>
<string name="pip_close" msgid="5775212044472849930">"Sule PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Täisekraan"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Mikrofon on aktiivne"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s pääses teie mikrofonile juurde"</string>
</resources>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index fa243887b648..51e3d2ba28af 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Lortu informazio gehiago"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Handiagotu pantaila betetzeko"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Luzatu pantaila betetzeko"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Pantaila-argazkia"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Pantaila-argazkia gordetzen…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Pantaila-argazkia gordetzen…"</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Gorde da pantaila-argazkia"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"ireki telefonoan"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"ireki ahots-laguntza"</string>
<string name="camera_label" msgid="8253821920931143699">"ireki kamera"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Utzi"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Berretsi"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Saiatu berriro"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Sakatu hau autentifikazioa bertan behera uzteko"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Aktibatze-ordua: <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g> arte"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Gai iluna"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Gai iluna\nBateria-aurrezlea"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Bateria-aurrezlea"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Ilunabarrean aktibatuko da"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Egunsentira arte"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"Desgaituta dago NFC"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"Gaituta dago NFC"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Irekitzeko, ukitu berriro"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Pasatu hatza gora irekitzeko"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Berriro saiatzeko, pasatu hatza gora"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Zure erakundeak kudeatzen du gailua"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"<xliff:g id="ORGANIZATION_NAME">%s</xliff:g> erakundeak kudeatzen du gailu hau"</string>
<string name="phone_hint" msgid="6682125338461375925">"Pasatu hatza ikonotik, telefonoa irekitzeko"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Aktibatuta dago bateria-aurrezlea"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Errendimendua eta atzeko planoko datuak murrizten ditu"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Desaktibatu bateria-aurrezlea"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Edukia grabatzen edo igortzen ari zaren bitartean, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aplikazioak pantailan bistaratzen den edo gailuan erreproduzitzen den kontuzko informazioa bil dezake, hala nola audioak, pasahitzak, ordainketa-informazioa, argazkiak eta mezuak."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Edukia grabatzen edo igortzen ari zaren bitartean, funtzio hau eskaintzen duen zerbitzuak pantailan bistaratzen den edo gailuan erreproduzitzen den kontuzko informazioa bil dezake, hala nola audioak, pasahitzak, ordainketa-informazioa, argazkiak eta mezuak."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Kontuzko informazioa erakutsiko da edukia igorri edo grabatzean"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"Zerbait grabatzen edo igortzen duzunean, pantailan ikus daitekeen edo gailuak erreproduzitzen duen informazio guztia atzitu ahalko du <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aplikazioak. Horrek barne hartzen ditu pasahitzak, ordainketen xehetasunak, argazkiak, mezuak eta erreproduzitzen dituzun audioak."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Zerbait grabatzen edo igortzen duzunean, pantailan ikus daitekeen edo gailuak erreproduzitzen duen informazio guztia atzitu ahalko du funtzio hori eskaintzen duen zerbitzuak. Horrek barne hartzen ditu pasahitzak, ordainketen xehetasunak, argazkiak, mezuak eta erreproduzitzen dituzun audioak."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aplikazioarekin grabatzen edo igortzen hasi nahi duzu?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Ez erakutsi berriro"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Garbitu guztiak"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Kudeatu"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Teklatu-aldatzailea"</string>
<string name="save" msgid="3392754183673848006">"Gorde"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Berrezarri"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Doitu botoiaren zabalera"</string>
<string name="clipboard" msgid="8517342737534284617">"Arbela"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Nabigazio-botoi pertsonalizatua"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Eskuinera"</string>
<string name="tuner_menu" msgid="363690665924769420">"Menua"</string>
<string name="tuner_app" msgid="6949280415826686972">"<xliff:g id="APP">%1$s</xliff:g> aplikazioa"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Alertak"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Bateria"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Pantaila-argazkiak"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Mezu orokorrak"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> abian da"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Ezer instalatu gabe ireki da aplikazioa."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Ezer instalatu gabe ireki da aplikazioa. Sakatu informazio gehiago lortzeko."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Aplikazioari buruzko informazioa"</string>
<string name="go_to_web" msgid="636673528981366511">"Joan arakatzailera"</string>
<string name="mobile_data" msgid="4564407557775397216">"Datu-konexioa"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> - <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Ezarpenak"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Ados"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="TYPES_LIST">%2$s</xliff:g> erabiltzen ari da."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplikazio batzuk <xliff:g id="TYPES_LIST">%s</xliff:g> erabiltzen ari dira."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" eta "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"kokapena"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofonoa"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sentsoreak desaktibatuta daude"</string>
<string name="device_services" msgid="1549944177856658705">"Gailuetarako zerbitzuak"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Ez du izenik"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Eguneratu da sistemaren nabigazioa. Aldaketak egiteko, joan Ezarpenak atalera."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Sistemaren nabigazioa eguneratzeko, joan Ezarpenak atalera"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Egonean"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Lupa-leiho gainjarria"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Lupa-leihoa"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Lupa-leihoaren aukerak"</string>
</resources>
diff --git a/packages/SystemUI/res/values-eu/strings_tv.xml b/packages/SystemUI/res/values-eu/strings_tv.xml
index 9906f96bb5ca..bdd1ffadf652 100644
--- a/packages/SystemUI/res/values-eu/strings_tv.xml
+++ b/packages/SystemUI/res/values-eu/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Programa izengabea)"</string>
<string name="pip_close" msgid="5775212044472849930">"Itxi PIPa"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Pantaila osoa"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Mikrofonoa aktibatuta dago"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s aplikazioak mikrofonoa atzitu du"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 4ce5b27cb129..20b55654d292 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"بیشتر بدانید"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"بزرگ‌نمایی برای پر کردن صفحه"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"گسترده کردن برای پر کردن صفحه"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"عکس صفحه‌نمایش"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"در حال ذخیره عکس صفحه‌نمایش..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"درحال ذخیره عکس صفحه‌نمایش…"</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"عکس صفحه‌نمایش ذخیره شد"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"باز کردن تلفن"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"«دستیار صوتی» را باز کنید"</string>
<string name="camera_label" msgid="8253821920931143699">"باز کردن دوربین"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"لغو"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"تأیید"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"امتحان مجدد"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"برای لغو راستی‌آزمایی ضربه بزنید"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"ساعت <xliff:g id="TIME">%s</xliff:g> روشن می‌شود"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"تا <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"طرح زمینه تیره"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"طرح زمینه تیره\nبهینه‌سازی باتری"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"بهینه‌سازی باتری"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"غروب روشن می‌شود"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"تا طلوع آفتاب"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"‏NFC غیرفعال است"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"‏NFC فعال است"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"دوباره ضربه بزنید تا باز شود"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"برای باز کردن، انگشتتان را تند به بالا بکشید"</string>
<string name="keyguard_retry" msgid="886802522584053523">"برای امتحان مجدد، انگشتتان را تند به بالا بکشید"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"سازمان شما این دستگاه را مدیریت می‌کند"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"این دستگاه توسط <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> مدیریت می‌شود"</string>
<string name="phone_hint" msgid="6682125338461375925">"انگشتتان را از نماد تلفن تند بکشید"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"«بهینه‌سازی باتری» روشن است"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"عملکرد و اطلاعات پس‌زمینه را کاهش می‌دهد"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"«بهینه‌سازی باتری» را خاموش کنید"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"هنگام ضبط یا ارسال محتوا، <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> می‌تواند هرگونه اطلاعات حساس را (مانند صوت، گذرواژه، اطلاعات پرداخت، عکس و پیام) که روی صفحه‌تان نشان داده می‌شود یا از دستگاهتان پخش می‌شود ضبط کند."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"هنگام ضبط یا ارسال محتوا، ارائه‌دهنده خدمات این عملکرد می‌تواند هرگونه اطلاعات حساس (مانند صوت، گذرواژه، اطلاعات پرداخت، عکس و پیام) را که روی صفحه‌تان نشان داده می‌شود یا از دستگاهتان پخش می‌شود ضبط کند."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"افشای اطلاعات حساس درحین ارسال/ضبط محتوا"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> به همه اطلاعاتی که روی صفحه‌نمایش قابل‌مشاهد است و هنگام ضبط کردن یا ارسال محتوا از دستگاهتان پخش می‌شود دسترسی خواهد داشت. این شامل اطلاعاتی مانند گذرواژه‌ها، جزئیات پرداخت، عکس‌ها، پیام‌ها، و صداهایی که پخش می‌کنید می‌شود."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"سرویس ارائه‌دهنده این عملکرد به همه اطلاعاتی که روی صفحه‌نمایش قابل‌مشاهد است و هنگام ضبط کردن یا ارسال محتوا از دستگاهتان پخش می‌شود دسترسی خواهد داشت. این شامل اطلاعاتی مانند گذرواژه‌ها، جزئیات پرداخت، عکس‌ها، پیام‌ها، و صداهایی که پخش می‌کنید می‌شود."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"ضبط یا ارسال محتوا با <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> شروع شود؟"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"دوباره نشان داده نشود"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"پاک کردن همه موارد"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"مدیریت"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"تغییردهنده صفحه‌کلید"</string>
<string name="save" msgid="3392754183673848006">"ذخیره کردن"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"بازنشانی"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"تنظیم پهنای دکمه"</string>
<string name="clipboard" msgid="8517342737534284617">"بریده‌دان"</string>
<string name="accessibility_key" msgid="3471162841552818281">"دکمه پیمایش سفارشی"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"راست"</string>
<string name="tuner_menu" msgid="363690665924769420">"منو"</string>
<string name="tuner_app" msgid="6949280415826686972">"<xliff:g id="APP">%1$s</xliff:g> برنامه"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"هشدارها"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"باتری"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"عکس‌های صفحه‌نمایش"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"پیام‌های عمومی"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> درحال اجرا"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"برنامه بدون نصب شدن باز شد."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"برنامه بدون نصب شدن باز شد. برای اطلاعات بیشتر ضربه بزنید."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"اطلاعات برنامه"</string>
<string name="go_to_web" msgid="636673528981366511">"رفتن به مرورگر"</string>
<string name="mobile_data" msgid="4564407557775397216">"داده تلفن همراه"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"تنظیمات"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"متوجه شدم"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> از <xliff:g id="TYPES_LIST">%2$s</xliff:g> شما استفاده می‌کند."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"برنامه‌ها از <xliff:g id="TYPES_LIST">%s</xliff:g> شما استفاده می‌‌کنند."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">"، "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" و "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"دوربین"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"مکان"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"میکروفون"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"حسگرها خاموش است"</string>
<string name="device_services" msgid="1549944177856658705">"سرویس‌های دستگاه"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"بدون عنوان"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"پیمایش سیستم به‌روزرسانی شد. برای انجام تغییرات به «تنظیمات» بروید."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"برای به‌روزرسانی پیمایش سیستم، به «تنظیمات» بروید"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"آماده‌به‌کار"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"پنجره همپوشانی بزرگ‌نمایی"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"پنجره بزرگ‌نمایی"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"کنترل‌های پنجره بزرگ‌نمایی"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fa/strings_tv.xml b/packages/SystemUI/res/values-fa/strings_tv.xml
index 05b6350f9234..fb6d42c2e3ba 100644
--- a/packages/SystemUI/res/values-fa/strings_tv.xml
+++ b/packages/SystemUI/res/values-fa/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(برنامه بدون عنوان)"</string>
<string name="pip_close" msgid="5775212044472849930">"‏بستن PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"تمام صفحه"</string>
+ <string name="mic_active" msgid="5766614241012047024">"میکروفون فعال است"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"‏%1$s به میکروفون شما دسترسی پیدا کرد"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 8912db8b7440..945e63d99f95 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Lue lisää"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Zoomaa koko näyttöön"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Venytä koko näyttöön"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Kuvakaappaus"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Tallennetaan kuvakaappausta..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Tallennetaan kuvakaappausta..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Kuvakaappaus tallennettu"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"avaa puhelin"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"Avaa ääniapuri"</string>
<string name="camera_label" msgid="8253821920931143699">"avaa kamera"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Peruuta"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Vahvista"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Yritä uudelleen"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Peruuta todennus napauttamalla"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Käyttöön klo <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g> saakka"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Tumma teema"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Tumma teema\nVirransäästö"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Virransäästö"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Auringon laskiessa"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Auringonnousuun"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC on poistettu käytöstä"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC on käytössä"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Avaa napauttamalla uudelleen"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Avaa pyyhkäisemällä ylös"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Yritä uudelleen pyyhkäisemällä ylös"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Organisaatiosi hallinnoi laitetta"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Tätä laitetta hallinnoi <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>."</string>
<string name="phone_hint" msgid="6682125338461375925">"Avaa puhelu pyyhkäisemällä."</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Virransäästö on käytössä"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Rajoittaa suorituskykyä ja taustatiedonsiirtoa"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Poista virransäästö käytöstä"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Tallennuksen tai striimauksen aikana <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> voi tallentaa mitä tahansa näytöllä näkyvää tai laitteen toistamaa arkaluontoista tietoa, kuten ääniä, salasanoja, maksutietoja, kuvia ja viestejä."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Tallennuksen tai striimauksen aikana ominaisuuden tarjoava palvelu voi tallentaa mitä tahansa näytöllä näkyvää tai laitteen toistamaa arkaluontoista tietoa, kuten ääniä, salasanoja, maksutietoja, kuvia ja viestejä."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Arkaluontoiset tiedot saatavilla suoratoiston tai tallennuksen aikana"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> saa pääsyn kaikkiin näytölläsi näkyviin tietoihin ja tietoihin laitteesi toistamasta sisällöstä tallennuksen tai striimauksen aikana. Näitä tietoja ovat esimerkiksi salasanat, maksutiedot, kuvat, viestit ja toistettava audiosisältö."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Ominaisuuden tarjoavalla palvelulla on pääsy kaikkiin näytölläsi näkyviin tietoihin ja tietoihin laitteesi toistamasta sisällöstä tallennuksen tai striimauksen aikana. Näitä tietoja ovat esimerkiksi salasanat, maksutiedot, kuvat, viestit ja toistettava audiosisältö."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Haluatko, että <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aloittaa tallennuksen tai striimauksen?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Älä näytä uudelleen"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Poista kaikki"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Muuta asetuksia"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Näppäimistövalitsin"</string>
<string name="save" msgid="3392754183673848006">"Tallenna"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Nollaa"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Muokkaa painikkeen leveyttä"</string>
<string name="clipboard" msgid="8517342737534284617">"Leikepöytä"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Muokattu navigointipainike"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Oikea"</string>
<string name="tuner_menu" msgid="363690665924769420">"Valikko"</string>
<string name="tuner_app" msgid="6949280415826686972">"<xliff:g id="APP">%1$s</xliff:g> sovellus"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Ilmoitukset"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Akku"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Kuvakaappaukset"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Yleiset viestit"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> on käynnissä"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Sovellus avattiin ilman asennusta."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Sovellus avattiin ilman asennusta. Katso lisätietoja napauttamalla."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Sovelluksen tiedot"</string>
<string name="go_to_web" msgid="636673528981366511">"Siirry selaimeen"</string>
<string name="mobile_data" msgid="4564407557775397216">"Mobiilitiedonsiirto"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Asetukset"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Selvä"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Luo SysUI-keon vedos"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> käyttää ominaisuuksia (<xliff:g id="TYPES_LIST">%2$s</xliff:g>)."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"<xliff:g id="TYPES_LIST">%s</xliff:g> ovat sovellusten käytössä."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" ja "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"sijainti"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofoni"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Anturit pois päältä"</string>
<string name="device_services" msgid="1549944177856658705">"Laitepalvelut"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Ei nimeä"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Järjestelmän navigointitapa vaihdettu. Voit muuttaa sitä asetuksista."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Vaihda järjestelmän navigointitapaa asetuksista"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Virransäästötila"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Suurennuksen peittoikkuna"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Suurennusikkuna"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Suurennusikkunan ohjaimet"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fi/strings_tv.xml b/packages/SystemUI/res/values-fi/strings_tv.xml
index 6e011f3f9ddd..3a80561e702f 100644
--- a/packages/SystemUI/res/values-fi/strings_tv.xml
+++ b/packages/SystemUI/res/values-fi/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Nimetön)"</string>
<string name="pip_close" msgid="5775212044472849930">"Sulje PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Koko näyttö"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Mikrofoni aktiivinen"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s käytti mikrofoniasi"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 2bf724c16c57..ac27ea8f6670 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"En savoir plus"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Zoomer pour remplir l\'écran"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Étirer pour remplir l\'écran"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Capture d\'écran"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Enregistrement capture écran…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Enregistrement capture écran…"</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Capture d\'écran enregistrée"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"Ouvrir le téléphone"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"ouvrir l\'assistance vocale"</string>
<string name="camera_label" msgid="8253821920931143699">"Ouvrir l\'appareil photo"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Annuler"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Confirmer"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Réessayer"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Touchez ici pour annuler l\'authentification"</string>
@@ -383,11 +381,13 @@
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Profil professionnel"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"Éclairage nocturne"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Activé la nuit"</string>
- <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Jusqu\'au lev. soleil"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Jusqu\'à l\'aube"</string>
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Actif à <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Jusqu\'à <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Thème sombre"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Thème sombre\nÉconomiseur de pile"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Économiseur de pile"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Activé la nuit"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Jusqu\'à l\'aube"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC désactivée"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC activée"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Touchez à nouveau pour ouvrir"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Balayez l\'écran vers le haut pour ouvrir"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Balayez l\'écran vers le haut pour réessayer"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Cet appareil est géré par votre organisation"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Cet appareil est géré par <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Balayez à partir de l\'icône pour accéder au téléphone"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"La fonction Économie d\'énergie est activée"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Réduire les performances et de fond"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Désactiver la fonction Économie d\'énergie"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Durant l\'enregistrement ou la diffusion, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> peut capturer de l\'information confidentielle qui s\'affiche sur votre écran ou qui joue sur votre appareil, comme de l\'audio, des mots de passe, des données de paiement, des photos et des messages."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Durant l\'enregistrement ou la diffusion, le service offrant cette fonction peut capturer de l\'information confidentielle qui s\'affiche sur votre écran ou qui joue sur votre appareil, comme de l\'audio, des mots de passe, des données de paiement, des photos et des messages."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Exposer des renseignements sensibles durant la diffusion ou l\'enregistrement"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aura accès à toute l\'information visible sur votre écran ou qui joue sur votre appareil durant l\'enregistrement ou la diffusion. Cela comprend des renseignements comme les mots de passe, les détails du paiement, les photos, les messages et l\'audio que vous faites jouer."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Le service offrant cette fonction aura accès à toute l\'information visible sur votre écran ou qui joue sur votre appareil durant l\'enregistrement ou la diffusion. Cela comprend des renseignements comme les mots de passe, les détails du paiement, les photos, les messages et l\'audio que vous faites jouer."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Commencer à enregistrer ou à diffuser avec <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Ne plus afficher"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Tout effacer"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Gérer"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Sélecteur de clavier"</string>
<string name="save" msgid="3392754183673848006">"Enregistrer"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Réinitialiser"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Ajuster la largeur du bouton"</string>
<string name="clipboard" msgid="8517342737534284617">"Presse-papiers"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Bouton de navigation personnalisé"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Droite"</string>
<string name="tuner_menu" msgid="363690665924769420">"Menu"</string>
<string name="tuner_app" msgid="6949280415826686972">"Application <xliff:g id="APP">%1$s</xliff:g>"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Alertes"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Pile"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Saisies d\'écran"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Messages généraux"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> en cours d\'exécution"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Application ouverte sans avoir été installée."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Application ouverte sans avoir été installée. Touchez ici pour en savoir plus."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Détails de l\'applic."</string>
<string name="go_to_web" msgid="636673528981366511">"Ouvrir le navigateur"</string>
<string name="mobile_data" msgid="4564407557775397216">"Données cellulaires"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> : <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Paramètres"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"OK"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Copier mémoire SysUI"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> utilise votre <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Des applications utilisent votre <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" et "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"appareil photo"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"position"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"microphone"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Capteurs désactivés"</string>
<string name="device_services" msgid="1549944177856658705">"Services de l\'appareil"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Sans titre"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"La navigation système a été mise à jour. Pour apporter des modifications, accédez au menu Paramètres."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Accédez au menu Paramètres pour mettre à jour la navigation système"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Veille"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Fenêtre d\'agrandissement superposée"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Fenêtre d\'agrandissement"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Commandes pour la fenêtre d\'agrandissement"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings_tv.xml b/packages/SystemUI/res/values-fr-rCA/strings_tv.xml
index c20524601077..abf4c1916d29 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings_tv.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Aucun programme de titre)"</string>
<string name="pip_close" msgid="5775212044472849930">"Fermer mode IDI"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Plein écran"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Microphone actif"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s a accédé à votre microphone"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index d2614defd013..d88201d001be 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"En savoir plus"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Zoomer pour remplir l\'écran"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Étirer pour remplir l\'écran"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Capture d\'écran"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Enregistrement capture écran…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Enregistrement de la capture d\'écran…"</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Capture d\'écran enregistrée"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"ouvrir le téléphone"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"ouvrir l\'assistance vocale"</string>
<string name="camera_label" msgid="8253821920931143699">"ouvrir l\'appareil photo"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Annuler"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Confirmer"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Réessayer"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Appuyer pour annuler l\'authentification"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"À partir de <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Jusqu\'à <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Thème sombre"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Thème foncé\nÉconomiseur de batterie"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Économiseur batterie"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Activé la nuit"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Jusqu\'à l\'aube"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"La technologie NFC est désactivée"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"La technologie NFC est activée"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Appuyer à nouveau pour ouvrir"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Balayer vers le haut pour ouvrir"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Balayez l\'écran vers le haut pour réessayer"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Cet appareil est géré par votre entreprise"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Cet appareil est géré par <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Balayer pour téléphoner"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Économiseur de batterie activé"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Limite les performances et les données en arrière-plan."</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Désactiver l\'économiseur de batterie"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Pendant que vous enregistrez ou diffusez du contenu, l\'appli <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> peut capturer des informations sensibles affichées à l\'écran ou lues par votre appareil, y compris des contenus audio, des mots de passe, des informations de paiement, des photos et des messages."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Pendant que vous enregistrez ou diffusez du contenu, le service concerné peut capturer des informations sensibles affichées à l\'écran ou lues par votre appareil, y compris des contenus audio, des mots de passe, des informations de paiement, des photos et des messages."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Présence d\'informations sensibles lors de l\'enregistrement ou de la diffusion de contenu"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aura accès à toutes les informations visibles sur votre écran ou lues depuis votre appareil lors d\'un enregistrement ou d\'une diffusion de contenu. Par exemple, vos mots de passe, vos données de paiement, vos photos, vos messages ou encore vos contenus audio lus."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Le service fournissant cette fonctionnalité aura accès à toutes les informations visibles sur votre écran ou lues depuis votre appareil lors d\'un enregistrement ou d\'une diffusion de contenu. Par exemple, vos mots de passe, vos données de paiement, vos photos, vos messages ou encore vos contenus audio lus."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Démarrer l\'enregistrement ou la diffusion avec <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Ne plus afficher"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Tout effacer"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Gérer"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Sélecteur clavier"</string>
<string name="save" msgid="3392754183673848006">"Enregistrer"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Réinitialiser"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Ajuster la largeur du bouton"</string>
<string name="clipboard" msgid="8517342737534284617">"Presse-papiers"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Bouton de navigation personnalisé"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Droite"</string>
<string name="tuner_menu" msgid="363690665924769420">"Menu"</string>
<string name="tuner_app" msgid="6949280415826686972">"Application <xliff:g id="APP">%1$s</xliff:g>"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Alertes"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Batterie"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Captures d\'écran"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Nouveaux messages"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> en cours d\'exécution"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Vous pouvez ouvrir cette application sans l\'installer."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Vous pouvez ouvrir cette application sans l\'installer. Appuyez pour en savoir plus."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Infos sur l\'appli"</string>
<string name="go_to_web" msgid="636673528981366511">"Accéder au navigateur"</string>
<string name="mobile_data" msgid="4564407557775397216">"Données mobiles"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Paramètres"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"OK"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Copier le tas SysUI"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> utilise votre <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Des applications utilisent votre <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" et "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"appareil photo"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"position"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"micro"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Capteurs désactivés"</string>
<string name="device_services" msgid="1549944177856658705">"Services pour l\'appareil"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Sans titre"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Navigation système mise à jour. Pour apporter des modifications, accédez aux paramètres."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Accédez aux paramètres pour mettre à jour la navigation système"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Mode Veille imminent"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Fenêtre de superposition de l\'agrandissement"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Fenêtre d\'agrandissement"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Fenêtre des commandes d\'agrandissement"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fr/strings_tv.xml b/packages/SystemUI/res/values-fr/strings_tv.xml
index ee894fca4fb7..1fc43a1cff4a 100644
--- a/packages/SystemUI/res/values-fr/strings_tv.xml
+++ b/packages/SystemUI/res/values-fr/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Programme sans titre)"</string>
<string name="pip_close" msgid="5775212044472849930">"Fermer mode PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Plein écran"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Micro actif"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s a accédé à votre micro"</string>
</resources>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index a7a5726c2d81..464684ec0fb8 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Máis información"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Ampliar ata ocupar todo"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Estirar ata ocupar todo"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Crear captura"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Gardando captura de pantalla…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Gardando captura de pantalla…"</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Gardouse a captura de pantalla"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"abrir teléfono"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"abrir asistente de voz"</string>
<string name="camera_label" msgid="8253821920931143699">"abrir cámara"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Cancelar"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Confirmar"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Tentar de novo"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Toca para cancelar a autenticación"</string>
@@ -273,8 +271,8 @@
<string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Modo de traballo activado."</string>
<string name="accessibility_quick_settings_work_mode_changed_off" msgid="6256690740556798683">"Desactivouse o modo de traballo."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Activouse o modo de traballo."</string>
- <string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Desactivouse o Economizador de datos."</string>
- <string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Activouse o Economizador de datos."</string>
+ <string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Desactivouse o aforro de datos."</string>
+ <string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Activouse o aforro de datos."</string>
<string name="accessibility_quick_settings_sensor_privacy_changed_off" msgid="7608378211873807353">"Desactivouse a privacidade dos sensores."</string>
<string name="accessibility_quick_settings_sensor_privacy_changed_on" msgid="4267393685085328801">"Activouse a privacidade dos sensores."</string>
<string name="accessibility_brightness" msgid="5391187016177823721">"Brillo de pantalla"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Desde: <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Ata: <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Tema escuro"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Tema escuro\nAforro de batería"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Aforro de batería"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Activación ao solpor"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Ata o amencer"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"A opción NFC está desactivada"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"A opción NFC está activada"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Toca de novo para abrir"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Pasa o dedo cara arriba para abrir"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Pasa o dedo cara arriba para tentalo de novo"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Este dispositivo está xestionado pola túa organización"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Este dispositivo está xestionado por <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Pasa o dedo desde a icona para acceder ao teléfono"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"A función Aforro de batería está activada"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Reduce o rendemento e os datos en segundo plano"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Desactivar a función Aforro de batería"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Mentres graves ou emitas contido, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> pode captar información confidencial que se mostre na pantalla ou se reproduza no dispositivo, como o audio que reproduzas, os contrasinais, a información de pago, as fotos e as mensaxes."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Mentres graves ou emitas contido, o servizo que ofrece esta función pode captar información confidencial que se mostre na pantalla ou se reproduza no dispositivo, como o audio que reproduzas, os contrasinais, a información de pago, as fotos e as mensaxes."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Revelar información confidencial durante a emisión ou a gravación"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> terá acceso a toda a información visible na pantalla ou reproducida desde o teu dispositivo mentres graves ou emitas contido. Isto inclúe información como contrasinais, detalles de pago, fotos, mensaxes e o audio que reproduzas."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"O servizo que proporciona esta función terá acceso a toda a información visible na pantalla ou reproducida desde o teu dispositivo mentres graves ou emitas contido. Isto inclúe información como contrasinais, detalles de pago, fotos, mensaxes e o audio que reproduzas."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Queres comezar a gravar ou emitir contido con <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Non mostrar outra vez"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Eliminar todas"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Xestionar"</string>
@@ -559,7 +557,7 @@
<string name="screen_pinning_description_recents_invisible_accessible" msgid="2857071808674481986">"A pantalla manterase visible ata que deixes de fixala. Para facelo, mantén premido Inicio."</string>
<string name="screen_pinning_toast" msgid="2083944237147005811">"Para deixar de fixar a pantalla, mantén premidos os botóns Volver e Visión xeral"</string>
<string name="screen_pinning_toast_recents_invisible" msgid="6343770487795352573">"Para deixar de fixar a pantalla, mantén premidos os botóns Atrás e Inicio"</string>
- <string name="screen_pinning_toast_gesture_nav" msgid="2884536903398445645">"Para soltar esta pantalla, pasa o dedo cara arriba e mantena premida"</string>
+ <string name="screen_pinning_toast_gesture_nav" msgid="2884536903398445645">"Para deixar de fixar esta pantalla, pasa o dedo cara arriba e mantena premida"</string>
<string name="screen_pinning_positive" msgid="3285785989665266984">"De acordo"</string>
<string name="screen_pinning_negative" msgid="6882816864569211666">"Non, grazas"</string>
<string name="screen_pinning_start" msgid="5695091877402422575">"Fixouse a pantalla"</string>
@@ -762,9 +760,9 @@
<string name="accessibility_long_click_tile" msgid="210472753156768705">"Abre a configuración"</string>
<string name="accessibility_status_bar_headphones" msgid="1304082414912647414">"Conectáronse os auriculares"</string>
<string name="accessibility_status_bar_headset" msgid="2699275863720926104">"Conectáronse os auriculares"</string>
- <string name="data_saver" msgid="3484013368530820763">"Economizador de datos"</string>
- <string name="accessibility_data_saver_on" msgid="5394743820189757731">"O economizador de datos está activado"</string>
- <string name="accessibility_data_saver_off" msgid="58339669022107171">"O economizador de datos está desactivado"</string>
+ <string name="data_saver" msgid="3484013368530820763">"Aforro de datos"</string>
+ <string name="accessibility_data_saver_on" msgid="5394743820189757731">"O aforro de datos está activado"</string>
+ <string name="accessibility_data_saver_off" msgid="58339669022107171">"O aforro de datos está desactivado"</string>
<string name="switch_bar_on" msgid="1770868129120096114">"Activar"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Desactivar"</string>
<string name="nav_bar" msgid="4642708685386136807">"Barra de navegación"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Conmutador do teclado"</string>
<string name="save" msgid="3392754183673848006">"Gardar"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Restablecer"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Axustar o ancho do botón"</string>
<string name="clipboard" msgid="8517342737534284617">"Portapapeis"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Botón de navegación personalizada"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Dereita"</string>
<string name="tuner_menu" msgid="363690665924769420">"Menú"</string>
<string name="tuner_app" msgid="6949280415826686972">"Aplicación <xliff:g id="APP">%1$s</xliff:g>"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Alertas"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Batería"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Capturas de pantalla"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Mensaxes xerais"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"Estase executando <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Abriuse a aplicación sen ter que instalala."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Abriuse a aplicación sen ter que instalala. Tocar para obter máis información."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Información da aplicación"</string>
<string name="go_to_web" msgid="636673528981366511">"Ir ao navegador"</string>
<string name="mobile_data" msgid="4564407557775397216">"Datos móbiles"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g>-<xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Configuración"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"De acordo"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Baleirado mem. SysUI"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> está utilizando <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Hai aplicacións que están utilizando <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" e "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"a cámara"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"a localiz."</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"o micrófono"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Desactivar sensores"</string>
<string name="device_services" msgid="1549944177856658705">"Servizos do dispositivo"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Sen título"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Actualizouse a navegación do sistema. Para facer cambios, vai a Configuración."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Para actualizar a navegación do sistema, vai a Configuración"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Modo de espera"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Ampliación da ventá de superposición"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Ventá de superposición"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Controis de ampliación da ventá"</string>
</resources>
diff --git a/packages/SystemUI/res/values-gl/strings_tv.xml b/packages/SystemUI/res/values-gl/strings_tv.xml
index d7ca10549c38..9455f956e890 100644
--- a/packages/SystemUI/res/values-gl/strings_tv.xml
+++ b/packages/SystemUI/res/values-gl/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Programa sen título)"</string>
<string name="pip_close" msgid="5775212044472849930">"Pechar PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Pantalla completa"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Micrófono activo"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s accedeu ao teu micrófono"</string>
</resources>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 69c50e134ffa..0cbb0bc8781b 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -39,7 +39,7 @@
<string name="battery_saver_start_action" msgid="4553256017945469937">"બૅટરી સેવર ચાલુ કરો"</string>
<string name="status_bar_settings_settings_button" msgid="534331565185171556">"સેટિંગ્સ"</string>
<string name="status_bar_settings_wifi_button" msgid="7243072479837270946">"વાઇ-ફાઇ"</string>
- <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"સ્ક્રીનને આપમેળે ફેરવો"</string>
+ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"ઑટો રોટેટ સ્ક્રીન"</string>
<string name="status_bar_settings_mute_label" msgid="914392730086057522">"મ્યૂટ કરો"</string>
<string name="status_bar_settings_auto_brightness_label" msgid="2151934479226017725">"સ્વતઃ"</string>
<string name="status_bar_settings_notifications" msgid="5285316949980621438">"નોટિફિકેશનો"</string>
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"વધુ જાણો"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"સ્ક્રીન ભરવા માટે ઝૂમ કરો"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"સ્ક્રીન ભરવા માટે ખેંચો"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"સ્ક્રીનશૉટ"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"સ્ક્રીનશોટ સાચવી રહ્યું છે…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"સ્ક્રીનશોટ સાચવી રહ્યું છે…"</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"સ્ક્રીનશૉટ સાચવ્યો"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"ફોન ખોલો"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"વૉઇસ સહાય ખોલો"</string>
<string name="camera_label" msgid="8253821920931143699">"કૅમેરો ખોલો"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"રદ કરો"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"કન્ફર્મ કરો"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"ફરી પ્રયાસ કરો"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"પ્રમાણીકરણ રદ કરવા માટે ટૅપ કરો"</string>
@@ -324,7 +322,7 @@
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"ચાલુ કરી રહ્યાં છીએ…"</string>
<string name="quick_settings_brightness_label" msgid="680259653088849563">"તેજ"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"ઑટો રોટેટ"</string>
- <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"સ્ક્રીનને આપમેળે ફેરવો"</string>
+ <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"ઑટો રોટેટ સ્ક્રીન"</string>
<string name="accessibility_quick_settings_rotation_value" msgid="2916484894750819251">"<xliff:g id="ID_1">%s</xliff:g> મોડ"</string>
<string name="quick_settings_rotation_locked_label" msgid="4420863550666310319">"પરિભ્રમણ લૉક થયું"</string>
<string name="quick_settings_rotation_locked_portrait_label" msgid="1194988975270484482">"પોર્ટ્રેટ"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"<xliff:g id="TIME">%s</xliff:g> વાગ્યે"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g> સુધી"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"ઘેરી થીમ"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"ઘેરી થીમ\nબૅટરી સેવર"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"બૅટરી સેવર"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"સૂર્યાસ્ત વખતે"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"સૂર્યોદય સુધી"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC અક્ષમ કરેલ છે"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC સક્ષમ કરેલ છે"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"ખોલવા માટે ફરીથી ટૅપ કરો"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"ખોલવા માટે ઉપરની તરફ સ્વાઇપ કરો"</string>
<string name="keyguard_retry" msgid="886802522584053523">"ફરી પ્રયાસ કરવા માટે ઉપરની તરફ સ્વાઇપ કરો"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"આ ઉપકરણ તમારી સંસ્થા દ્વારા સંચાલિત છે"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"આ ઉપકરણ <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> દ્વારા સંચાલિત થાય છે"</string>
<string name="phone_hint" msgid="6682125338461375925">"ફોન માટે આયકનમાંથી સ્વાઇપ કરો"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"બૅટરી સેવર ચાલુ છે"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"પ્રદર્શન અને બૅકગ્રાઉન્ડ ડેટા ઘટાડે છે"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"બૅટરી સેવર બંધ કરો"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"રેકોર્ડ અથવા કાસ્ટ કરતી વખતે, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ઑડિયો, પાસવર્ડ, ચુકવણીની માહિતી, ફોટા અને સંદેશા સહિતની આવી કોઈપણ સંવેદનશીલ માહિતી જે તમારા સ્ક્રીન પર દેખાતી હોય અથવા તમારા ડિવાઇસ પર ચલાવવામાં આવતી હોય, તેને કૅપ્ચર કરી શકે છે."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"રેકોર્ડ અથવા કાસ્ટ કરતી વખતે, આ સેવા આપતી સુવિધા ઑડિયો, પાસવર્ડ, ચુકવણીની માહિતી, ફોટા અને સંદેશા સહિતની આવી કોઈપણ સંવેદનશીલ માહિતી જે તમારા સ્ક્રીન પર દેખાતી હોય અથવા તમારા ડિવાઇસ પર ચલાવવામાં આવતી હોય, તેને કૅપ્ચર કરી શકે છે."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"કાસ્ટિંગ/રેકોર્ડિંગ દરમિયાન સંવેદનશીલ માહિતી દર્શાવવી"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"રેકૉર્ડ અથવા કાસ્ટ કરતી વખતે, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>ને તમારી સ્ક્રીન પર દેખાતી હોય અથવા તમારા ડિવાઇસ પર ચલાવવામાં આવતી હોય તેવી બધી માહિતીનો ઍક્સેસ હશે. આમાં પાસવર્ડ, ચુકવણીની વિગતો, ફોટા, સંદેશા અને તમે ચલાવો છો તે ઑડિયો જેવી માહિતીનો સમાવેશ થાય છે."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"રેકૉર્ડ અથવા કાસ્ટ કરતી વખતે, આ સુવિધા આપતી સેવાને તમારી સ્ક્રીન પર દેખાતી હોય અથવા તમારા ડિવાઇસ પર ચલાવવામાં આવતી હોય તેવી બધી માહિતીનો ઍક્સેસ હશે. આમાં પાસવર્ડ, ચુકવણીની વિગતો, ફોટા, સંદેશા અને તમે ચલાવો છો તે ઑડિયો જેવી માહિતીનો સમાવેશ થાય છે."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> વડે રેકૉર્ડ અથવા કાસ્ટ કરવાનું શરૂ કરીએ?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"ફરીથી બતાવશો નહીં"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"બધુ સાફ કરો"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"મેનેજ કરો"</string>
@@ -667,12 +665,10 @@
<string name="inline_keep_showing_app" msgid="4393429060390649757">"આ ઍપમાંથી નોટિફિકેશન બતાવવાનું ચાલુ રાખીએ?"</string>
<string name="notification_silence_title" msgid="8608090968400832335">"સાઇલન્ટ"</string>
<string name="notification_alert_title" msgid="7629202599338071971">"અલર્ટ કરવાનું ચાલુ રાખો"</string>
- <!-- no translation found for notification_bubble_title (8330481035191903164) -->
- <skip />
+ <string name="notification_bubble_title" msgid="8330481035191903164">"બબલ"</string>
<string name="notification_channel_summary_low" msgid="7300447764759926720">"તમને સાઉન્ડ અથવા વાઇબ્રેશન વિના ફોકસ કરવામાં સહાય કરે છે."</string>
<string name="notification_channel_summary_default" msgid="3539949463907902037">"સાઉન્ડ અથવા વાઇબ્રેશન વિના તમારું ધ્યાન દોરે છે."</string>
- <!-- no translation found for notification_channel_summary_bubble (7235935211580860537) -->
- <skip />
+ <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ફ્લોટિંગ શૉર્ટકટથી આ કન્ટેન્ટ પર તમારું ધ્યાન દોરી રાખે છે."</string>
<string name="notification_unblockable_desc" msgid="2073030886006190804">"આ નોટિફિકેશનમાં કોઈ ફેરફાર થઈ શકશે નહીં."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"નોટિફિકેશનના આ ગ્રૂપની ગોઠવણી અહીં કરી શકાશે નહીં"</string>
<string name="notification_delegate_header" msgid="1264510071031479920">"પ્રૉક્સી નોટિફિકેશન"</string>
@@ -788,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"કીબોર્ડ સ્વિચર"</string>
<string name="save" msgid="3392754183673848006">"સાચવો"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"રીસેટ કરો"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"બટનની પહોળાઈ સમાયોજિત કરો"</string>
<string name="clipboard" msgid="8517342737534284617">"ક્લિપબોર્ડ"</string>
<string name="accessibility_key" msgid="3471162841552818281">"કસ્ટમ નેવિગેશન બટન"</string>
@@ -885,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"જમણે"</string>
<string name="tuner_menu" msgid="363690665924769420">"મેનૂ"</string>
<string name="tuner_app" msgid="6949280415826686972">"<xliff:g id="APP">%1$s</xliff:g> ઍપ્લિકેશન"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"અલર્ટ"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"બૅટરી"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"સ્ક્રીનશૉટ"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"સામાન્ય સંદેશા"</string>
@@ -896,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> ચાલી રહી છે"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"ઍપ ઇન્સ્ટૉલ કર્યા વિના ખુલી જાય છે."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"ઍપ ઇન્સ્ટૉલ કર્યા વિના ખુલી જાય છે. વધુ જાણવા માટે ટૅપ કરો."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"ઍપની માહિતી"</string>
<string name="go_to_web" msgid="636673528981366511">"બ્રાઉઝર પર જાઓ"</string>
<string name="mobile_data" msgid="4564407557775397216">"મોબાઇલ ડેટા"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -931,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"સેટિંગ"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"સમજાઈ ગયું"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> ઍપ તમારા <xliff:g id="TYPES_LIST">%2$s</xliff:g>નો ઉપયોગ કરી રહી છે."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"ઍપ્લિકેશન તમારા <xliff:g id="TYPES_LIST">%s</xliff:g>નો ઉપયોગ કરી રહી છે."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" અને "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"કૅમેરા"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"સ્થાન"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"માઇક્રોફોન"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"સેન્સર બંધ છે"</string>
<string name="device_services" msgid="1549944177856658705">"ડિવાઇસ સેવાઓ"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"કોઈ શીર્ષક નથી"</string>
@@ -960,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"સિસ્ટમ નૅવિગેશન અપડેટ કર્યું. ફેરફારો કરવા માટે, સેટિંગ પર જાઓ."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"સિસ્ટમ નૅવિગેશનને અપડેટ કરવા માટે સેટિંગ પર જાઓ"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"સ્ટૅન્ડબાય"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"વિસ્તૃતીકરણ ઓવરલે વિંડો"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"વિસ્તૃતીકરણ વિંડો"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"વિસ્તૃતીકરણ વિંડોના નિયંત્રણો"</string>
</resources>
diff --git a/packages/SystemUI/res/values-gu/strings_tv.xml b/packages/SystemUI/res/values-gu/strings_tv.xml
index bc9a3dff5c31..3ea64873a856 100644
--- a/packages/SystemUI/res/values-gu/strings_tv.xml
+++ b/packages/SystemUI/res/values-gu/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(કોઈ ટાઇટલ પ્રોગ્રામ નથી)"</string>
<string name="pip_close" msgid="5775212044472849930">"PIP બંધ કરો"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"પૂર્ણ સ્ક્રીન"</string>
+ <string name="mic_active" msgid="5766614241012047024">"માઇક્રોફોન સક્રિય છે"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$sએ તમારો માઇક્રોફોન ઍક્સેસ કર્યો હતો"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 3fc78706d4bd..23a512663c39 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"ज़्यादा जानें"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"स्‍क्रीन भरने के लिए ज़ूम करें"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"स्‍क्रीन भरने के लिए खींचें"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"स्क्रीनशॉट"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"स्क्रीनशॉट सहेजा जा रहा है..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"स्क्रीनशॉट सहेजा जा रहा है..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"स्क्रीनशॉट सेव किया गया"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"फ़ोन खोलें"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"आवाज़ से डिवाइस को इस्तेमाल करें"</string>
<string name="camera_label" msgid="8253821920931143699">"कैमरा खोलें"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"रद्द करें"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"पुष्टि करें"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"फिर से कोशिश करें"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"पुष्टि की प्रक्रिया रद्द करने के लिए टैप करें"</string>
@@ -323,8 +321,8 @@
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"सुनने में मददगार डिवाइस"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"ब्लूटूथ चालू हो रहा है…"</string>
<string name="quick_settings_brightness_label" msgid="680259653088849563">"स्क्रीन की रोशनी"</string>
- <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"अपने आप घूमना"</string>
- <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"स्‍क्रीन अपने आप घूमने की सुविधा चालू करें"</string>
+ <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"अपने-आप घूमना"</string>
+ <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"स्‍क्रीन अपने आप-घूमने की सुविधा चालू करें"</string>
<string name="accessibility_quick_settings_rotation_value" msgid="2916484894750819251">"<xliff:g id="ID_1">%s</xliff:g> मोड"</string>
<string name="quick_settings_rotation_locked_label" msgid="4420863550666310319">"घुमाना लॉक किया गया"</string>
<string name="quick_settings_rotation_locked_portrait_label" msgid="1194988975270484482">"पोर्ट्रेट"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"<xliff:g id="TIME">%s</xliff:g> पर चालू की जाएगी"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g> तक"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"गहरे रंग वाली थीम"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"गहरे रंग वाली थीम\nबैटरी सेवर"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"बैटरी सेवर"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"शाम को चालू होगा"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"सुबह तक चालू रहेगी"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"एनएफ़सी"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC बंद है"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC चालू है"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"खोलने के लिए फिर से टैप करें"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"खोलने के लिए ऊपर स्वाइप करें"</string>
<string name="keyguard_retry" msgid="886802522584053523">"फिर से कोशिश करने के लिए ऊपर की ओर स्वाइप करें"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"इस डिवाइस का प्रबंधन आपका संगठन करता है"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"इस डिवाइस के प्रबंधक <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> हैं"</string>
<string name="phone_hint" msgid="6682125338461375925">"फ़ोन के लिए आइकॉन से स्वाइप करें"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"बैटरी सेवर चालू है"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"निष्‍पादन और पृष्ठभूमि डेटा को कम करता है"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"बैटरी सेवर बंद करें"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"रिकॉर्ड या कास्ट करते समय, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> आपकी स्क्रीन पर दिखाई जा रही या आपके डिवाइस पर चलाई जा रही संवेदनशील जानकारी ऐक्सेस कर सकता है. इस जानकारी में ऑडियो, पासवर्ड, भुगतान की जानकारी, फ़ोटो और मैसेज शामिल हैं."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"रिकॉर्ड या कास्ट करते समय, यह सेवा देने वाला ऐप्लिकेशन आपकी स्क्रीन पर दिखाई जा रही या आपके डिवाइस पर चलाई जा रही संवेदनशील जानकारी ऐक्सेस कर सकता है. इस जानकारी में ऑडियो, पासवर्ड, भुगतान की जानकारी, फ़ोटो और मैसेज शामिल हैं."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"कास्ट करने/रिकॉर्ड करने के दौरान संवेदनशील जानकारी का सबके सामने आ जाना"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"रिकॉर्ड या कास्ट करते समय, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> आपकी स्क्रीन पर दिख रही या आपके डिवाइस पर चलाई जा रही जानकारी ऐक्सेस कर सकता है. इसमें पासवर्ड, पैसे चुकाने का ब्यौरा, फ़ोटो, मैसेज, और चलाए गए ऑडियो जैसी जानकारी शामिल है."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"रिकॉर्ड या कास्ट करते समय, वह सेवा जो यह फ़ंक्शन उपलब्ध कराती है, आपके डिवाइस पर चलाई जा रही या स्क्रीन पर दिख रही जानकारी को ऐक्सेस कर सकती है. इसमें पासवर्ड, पैसे चुकाने का ब्यौरा, फ़ोटो, मैसेज, और चलाए गए ऑडियो जैसी जानकारी शामिल है."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> का इस्तेमाल करके रिकॉर्ड और कास्ट करना शुरू करें?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"फिर से न दिखाएं"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"सभी को हटाएं"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"प्रबंधित करें"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"कीबोर्ड स्विचर"</string>
<string name="save" msgid="3392754183673848006">"सेव करें"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"रीसेट करें"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"बटन की चौड़ाई समायोजित करें"</string>
<string name="clipboard" msgid="8517342737534284617">"क्लिपबोर्ड"</string>
<string name="accessibility_key" msgid="3471162841552818281">"आपके मुताबिक नेविगेट करने के लिए बटन"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"दायां"</string>
<string name="tuner_menu" msgid="363690665924769420">"मेन्यू"</string>
<string name="tuner_app" msgid="6949280415826686972">"<xliff:g id="APP">%1$s</xliff:g> ऐप"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"सूचनाएं"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"बैटरी"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"स्‍क्रीनशॉट"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"सामान्य संदेश"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> चल रहा है"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"ऐप्लिकेशन इंस्टॉल किए बिना ही खुल गया है."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"ऐप्लिकेशन इंस्टॉल किए बिना ही खुल गया है. ज़्यादा जानने के लिए टैप करें."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"ऐप्लिकेशन की जानकारी"</string>
<string name="go_to_web" msgid="636673528981366511">"ब्राउज़र पर जाएं"</string>
<string name="mobile_data" msgid="4564407557775397216">"मोबाइल डेटा"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"सेटिंग"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"ठीक है"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> आपकी <xliff:g id="TYPES_LIST">%2$s</xliff:g> का इस्तेमाल कर रहा है."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"ऐप्लिकेशन आपकी <xliff:g id="TYPES_LIST">%s</xliff:g> का इस्तेमाल कर रहे हैं."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" और "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"कैमरा"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"जगह"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"माइक्रोफ़ोन"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"सेंसर बंद हैं"</string>
<string name="device_services" msgid="1549944177856658705">"डिवाइस सेवाएं"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"कोई शीर्षक नहीं"</string>
@@ -958,4 +946,10 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"सिस्टम नेविगेशन अपडेट हो गया. बदलाव करने के लिए \'सेटिंग\' पर जाएं."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"सिस्टम नेविगेशन अपडेट करने के लिए \'सेटिंग\' में जाएं"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"स्टैंडबाई"</string>
+ <!-- no translation found for magnification_overlay_title (6584179429612427958) -->
+ <skip />
+ <!-- no translation found for magnification_window_title (4863914360847258333) -->
+ <skip />
+ <!-- no translation found for magnification_controls_title (8421106606708891519) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-hi/strings_tv.xml b/packages/SystemUI/res/values-hi/strings_tv.xml
index 30324955646f..e5c6eb2e6e20 100644
--- a/packages/SystemUI/res/values-hi/strings_tv.xml
+++ b/packages/SystemUI/res/values-hi/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(कोई शीर्षक कार्यक्रम नहीं)"</string>
<string name="pip_close" msgid="5775212044472849930">"PIP बंद करें"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"फ़ुल स्‍क्रीन"</string>
+ <string name="mic_active" msgid="5766614241012047024">"माइक्रोफ़ोन चालू है"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s ने आपका माइक्रोफ़ोन ऐक्सेस किया था"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index f19bdf5f95a5..42f0df5098c9 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Saznajte više"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Zumiraj i ispuni zaslon"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Rastegni i ispuni zaslon"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Snimka zaslona"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Spremanje snimke zaslona..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Spremanje snimke zaslona..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Snimka zaslona spremljena"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"otvaranje telefona"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"otvaranje glasovne pomoći"</string>
<string name="camera_label" msgid="8253821920931143699">"otvaranje fotoaparata"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Odustani"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Potvrdi"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Pokušaj ponovo"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Dodirnite da biste otkazali autentifikaciju"</string>
@@ -389,7 +387,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Uključuje se u <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Tamna tema"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Tamna tema\nŠtednja baterije"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Štednja baterije"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Uključuje se u suton"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Do izlaska sunca"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC je onemogućen"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC je omogućen"</string>
@@ -414,10 +414,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Dodirnite opet za otvaranje"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Prijeđite prstom prema gore da biste otvorili"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Prijeđite prstom prema gore za ponovni pokušaj"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Ovim uređajem upravlja vaša organizacija"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Ovim uređajem upravlja <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Prijeđite prstom od ikone za telefon"</string>
@@ -470,9 +466,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Štednja baterije je uključena"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Smanjuje količinu rada i pozadinske podatke"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Isključite Štednju baterije"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Tijekom snimanja ili emitiranja <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> može zabilježiti sve osjetljive podatke koji se prikazuju na zaslonu ili reproduciraju s uređaja, uključujući osjetljive podatke kao što su audiozapisi, lozinke, podaci o plaćanjima, fotografije i poruke."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Tijekom snimanja ili emitiranja usluga u sklopu koje se pruža ova funkcija može zabilježiti sve osjetljive podatke koji se prikazuju na zaslonu ili reproduciraju s uređaja, uključujući osjetljive podatke kao što su audiozapisi, lozinke, podaci o plaćanjima, fotografije i poruke."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Izlaganje osjetljivih podataka tijekom emitiranja/snimanja"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> imat će pristup svim podacima koji su vidljivi na vašem zaslonu ili koji se reproduciraju s vašeg uređaja tijekom snimanja ili emitiranja. To uključuje podatke kao što su zaporke, podaci o plaćanju, fotografije, poruke i audiozapisi koje reproducirate."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Usluga koja pruža ovu funkcionalnost imat će pristup svim podacima koji su vidljivi na vašem zaslonu ili koji se reproduciraju s vašeg uređaja tijekom snimanja ili emitiranja. To uključuje podatke kao što su zaporke, podaci o plaćanju, fotografije, poruke i audiozapisi koje reproducirate."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Započeti snimanje ili emitiranja pomoću aplikacije <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Ne prikazuj ponovo"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Izbriši sve"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Upravljajte"</string>
@@ -791,8 +789,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Izmjena tipkovnice"</string>
<string name="save" msgid="3392754183673848006">"Spremi"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Poništi"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Prilagodite širinu gumba"</string>
<string name="clipboard" msgid="8517342737534284617">"Međuspremnik"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Prilagođeni navigacijski gumb"</string>
@@ -888,8 +885,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Desno"</string>
<string name="tuner_menu" msgid="363690665924769420">"Izbornik"</string>
<string name="tuner_app" msgid="6949280415826686972">"Aplikacija <xliff:g id="APP">%1$s</xliff:g>"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Upozorenja"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Baterija"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Snimke zaslona"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Općenite poruke"</string>
@@ -899,8 +895,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"Izvodi se aplikacija <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Aplikacija je otvorena bez instaliranja."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Aplikacija je otvorena bez instaliranja. Dodirnite da biste saznali više."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Podaci o aplikaciji"</string>
<string name="go_to_web" msgid="636673528981366511">"Otvori preglednik"</string>
<string name="mobile_data" msgid="4564407557775397216">"Mobilni podaci"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -934,13 +929,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Postavke"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Shvaćam"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Izdvoji mem. SysUI-a"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"Aplikacija <xliff:g id="APP">%1$s</xliff:g> upotrebljava <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplikacije upotrebljavaju <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" i "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"fotoaparat"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"lokaciju"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Senzori su isključeni"</string>
<string name="device_services" msgid="1549944177856658705">"Usluge uređaja"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Bez naslova"</string>
@@ -963,4 +951,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Ažurirana je navigacija sustavom. Možete je promijeniti u Postavkama."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Navigaciju sustavom možete ažurirati u Postavkama"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Stanje mirovanja"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Prozor preklapanja povećavanja"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Prozor za povećavanje"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Kontrole prozora za povećavanje"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hr/strings_tv.xml b/packages/SystemUI/res/values-hr/strings_tv.xml
index 8bf334a40880..e226460298b7 100644
--- a/packages/SystemUI/res/values-hr/strings_tv.xml
+++ b/packages/SystemUI/res/values-hr/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Program bez naslova)"</string>
<string name="pip_close" msgid="5775212044472849930">"Zatvori PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Cijeli zaslon"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Mikrofon aktivan"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"Aplikacija %1$s pristupila je mikrofonu"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 8624670ea0dc..7a5eadfec028 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Részletek"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Nagyítás a kitöltéshez"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Nyújtás kitöltéshez"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Képernyőkép"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Képernyőkép mentése..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Képernyőkép mentése..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"A képernyőkép mentése sikerült"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"telefon megnyitása"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"hangsegéd megnyitása"</string>
<string name="camera_label" msgid="8253821920931143699">"kamera megnyitása"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Mégse"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Megerősítés"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Újrapróbálkozás"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Koppintson a hitelesítés visszavonásához"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Bekapcsolás: <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Eddig: <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Sötét téma"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Sötét téma\nAkkumulátorkímélő mód"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Akkumulátorkímélő"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Be: napnyugta"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Napfelkeltéig"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"Az NFC ki van kapcsolva"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"Az NFC be van kapcsolva"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Koppintson ismét a megnyitáshoz"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Csúsztasson felfelé a megnyitáshoz"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Az újrapróbálkozáshoz csúsztassa felfelé az ujját"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Az eszközt az Ön szervezete kezeli"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Az eszközt a(z) <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> felügyeli."</string>
<string name="phone_hint" msgid="6682125338461375925">"A telefonhoz csúsztasson az ikonról"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Akkumulátorkímélő mód bekapcsolva"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Csökkenti a teljesítményt és a háttéradatok használatát"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Akkumulátorkímélő mód kikapcsolása"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Felvétel rögzítésekor és átküldés során a(z) <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> rögzítheti a képernyőn megjelenő és az eszközön lejátszott bizalmas információkat, például hangfelvételeket, jelszavakat, fizetési adatokat, fotókat és üzeneteket."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Felvétel rögzítésekor és átküldés során a funkciót biztosító szolgáltató rögzítheti a képernyőn megjelenő és az eszközön lejátszott bizalmas információkat, például hangfelvételeket, jelszavakat, fizetési adatokat, fotókat és üzeneteket."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Bizalmas adatok feltárása átküldés vagy rögzítés során"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"A(z) <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> hozzáfér majd minden olyan információhoz, amely látható az Ön képernyőjén, vagy amelyet az Ön eszközéről játszanak le rögzítés vagy átküldés során. Ez olyan információkat is tartalmaz, mint a jelszavak, a fizetési részletek, fotók, üzenetek és lejátszott audiotartalmak."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"A funkciót biztosító szolgáltatás hozzáfér majd minden olyan információhoz, amely látható az Ön képernyőjén, illetve amelyet az Ön eszközéről játszanak le rögzítés vagy átküldés közben. Ez olyan információkat is tartalmaz, mint a jelszavak, a fizetési részletek, fotók, üzenetek és lejátszott audiotartalmak."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Elkezdi a rögzítést vagy átküldést a következővel: <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Ne jelenjen meg többé"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Az összes törlése"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Kezelés"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Billentyűzetváltó"</string>
<string name="save" msgid="3392754183673848006">"Mentés"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Visszaállítás"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Gombszélesség beállítása"</string>
<string name="clipboard" msgid="8517342737534284617">"Vágólap"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Személyre szabott navigációs gomb"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Jobb"</string>
<string name="tuner_menu" msgid="363690665924769420">"Menü"</string>
<string name="tuner_app" msgid="6949280415826686972">"<xliff:g id="APP">%1$s</xliff:g> alkalmazás"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Értesítések"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Akkumulátor"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Képernyőképek"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Általános üzenetek"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"A(z) <xliff:g id="APP">%1$s</xliff:g> alkalmazás jelenleg fut"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Az alkalmazás telepítés nélkül lett megnyitva."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Az alkalmazás telepítés nélkül lett megnyitva. Ha további információra van szüksége, koppintson ide."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Alkalmazásadatok"</string>
<string name="go_to_web" msgid="636673528981366511">"Ugrás a böngészőbe"</string>
<string name="mobile_data" msgid="4564407557775397216">"Mobiladatok"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Beállítások"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Értem"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"SysUI-memória-kiírás"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"A(z) <xliff:g id="APP">%1$s</xliff:g> használja a következőket: <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Több alkalmazás használja a következőket: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" és "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"helyadatok"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Érzékelők kikapcsolva"</string>
<string name="device_services" msgid="1549944177856658705">"Eszközszolgáltatások"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Nincs cím"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"A rendszer-navigáció módja megváltozott. Módosításához nyissa meg a Beállításokat."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"A rendszer-navigációs lehetőségeket a Beállításokban módosíthatja"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Készenléti mód"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Nagyítási fedvény ablaka"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Nagyítás ablaka"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Nagyítási vezérlők ablaka"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hu/strings_tv.xml b/packages/SystemUI/res/values-hu/strings_tv.xml
index 90c5a66cb546..f039c0d82238 100644
--- a/packages/SystemUI/res/values-hu/strings_tv.xml
+++ b/packages/SystemUI/res/values-hu/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Cím nélküli program)"</string>
<string name="pip_close" msgid="5775212044472849930">"PIP bezárása"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Teljes képernyő"</string>
+ <string name="mic_active" msgid="5766614241012047024">"A mikrofon aktív"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"A(z) %1$s hozzáfért a mikrofonhoz"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index c02199e5316c..f25f6ae7152d 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Իմանալ ավելին"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Խոշորացնել` էկրանը լցնելու համար"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Ձգել` էկրանը լցնելու համար"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Սքրինշոթ"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Սքրինշոթը պահվում է…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Սքրինշոթը պահվում է..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Սքրինշոթը պահվեց"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"բացել հեռախոսը"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"բացեք ձայնային հուշումը"</string>
<string name="camera_label" msgid="8253821920931143699">"բացել ֆոտոխցիկը"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Չեղարկել"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Հաստատել"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Նորից փորձել"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Հպեք՝ նույնականացումը չեղարկելու համար"</string>
@@ -334,7 +332,7 @@
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Անջատել տեղադրությունը"</string>
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Մեդիա սարք"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
- <string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Միայն արտակարգ իրավիճակների զանգեր"</string>
+ <string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Միայն շտապ կանչեր"</string>
<string name="quick_settings_settings_label" msgid="2214639529565474534">"Կարգավորումներ"</string>
<string name="quick_settings_time_label" msgid="3352680970557509303">"Ժամանակը"</string>
<string name="quick_settings_user_label" msgid="1253515509432672496">"Ես"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Կմիացվի ժամը <xliff:g id="TIME">%s</xliff:g>-ին"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Մինչև <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Մուգ թեմա"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Մուգ թեմա\nՄարտկոցի տնտեսում"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Մարտկոցի տնտեսում"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Կմիացվի մայրամուտին"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Մինչև լուսաբաց"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC-ն անջատված է"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC-ն միացված է"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Կրկին հպեք՝ բացելու համար"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Բացելու համար սահեցրեք վերև"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Սահեցրեք վերև՝ նորից փորձելու համար"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Այս սարքը կառավարում է ձեր կազմակերպությունը"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Այս սարքը կառավարվում է <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>-ի կողմից"</string>
<string name="phone_hint" msgid="6682125338461375925">"Սահահարվածեք հեռախոսի պատկերակից"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Մարտկոցի տնտեսումը միացված է"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Նվազեցնում է ծանրաբեռնվածությունը և ֆոնային տվյալները"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Անջատել մարտկոցի տնտեսումը"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ծառայությունը ձայնագրման և հեռարձակման ընթացքում կարող է պահել ձեր սարքի էկրանին ցուցադրվող տեղեկությունները և ձեր սարքով նվագարկվող նյութերը, որոնք կարող են խիստ անձնական լինել, օրինակ՝ աուդիո նյութերը, գաղտնաբառերը, վճարային տվյալները, լուսանկարները և հաղորդագրությունները:"</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Այս գործառույթը տրամադրող ծառայությունը ձայնագրման և հեռարձակման ընթացքում կարող է պահել ձեր սարքի էկրանին ցուցադրվող տեղեկությունները և ձեր սարքով նվագարկվող նյութերը, որոնք կարող են խիստ անձնական լինել, օրինակ՝ աուդիո նյութերը, գաղտնաբառերը, վճարային տվյալները, լուսանկարները և հաղորդագրությունները:"</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Գաղտնի տեղեկությունների բացահայտում հեռարձակման/ձայնագրման ընթացքում"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"Ձայնագրման և հեռարձակման ընթացքում <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> հավելվածին հասանելի կլինեն ձեր սարքի էկրանին ցուցադրվող տեղեկությունները և ձեր սարքով նվագարկվող նյութերը։ Սա ներառում է այնպիսի տեղեկություններ, ինչպիսիք են, օրինակ, գաղտնաբառերը, վճարային տվյալները, լուսանկարները, հաղորդագրությունները և նվագարկվող աուդիո ֆայլերը։"</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Ձայնագրման և հեռարձակման ընթացքում ծառայությունների մատակարարին հասանելի կլինեն ձեր սարքի էկրանին ցուցադրվող տեղեկությունները և ձեր սարքով նվագարկվող նյութերը։ Սա ներառում է այնպիսի տեղեկություններ, ինչպիսիք են, օրինակ, գաղտնաբառերը, վճարային տվյալները, լուսանկարները, հաղորդագրությունները և նվագարկվող աուդիո ֆայլերը։"</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Սկսե՞լ ձայնագրումը կամ հեռարձակումը <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> հավելվածով"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Այլևս ցույց չտալ"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Մաքրել բոլորը"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Կառավարել"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Ստեղնաշարի փոխարկիչ"</string>
<string name="save" msgid="3392754183673848006">"Պահել"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Վերակայել"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Կարգավորել կոճակի լայնությունը"</string>
<string name="clipboard" msgid="8517342737534284617">"Սեղմատախտակ"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Հատուկ նավարկման կոճակ"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Աջ"</string>
<string name="tuner_menu" msgid="363690665924769420">"Ընտրացանկ"</string>
<string name="tuner_app" msgid="6949280415826686972">"<xliff:g id="APP">%1$s</xliff:g> հավելված"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Ծանուցումներ"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Մարտկոց"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Սքրինշոթներ"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Ընդհանուր հաղորդագրություններ"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> հավելվածն աշխատում է"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Հավելվածը բացվել է առանց տեղադրման։"</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Հավելվածը բացվել է առանց տեղադրման։ Հպեք՝ ավելին իմանալու համար։"</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Հավելվածի մասին"</string>
<string name="go_to_web" msgid="636673528981366511">"Անցնել դիտարկիչ"</string>
<string name="mobile_data" msgid="4564407557775397216">"Բջջային ինտերնետ"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Կարգավորումներ"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Եղավ"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> հավելվածն օգտագործում է ձեր <xliff:g id="TYPES_LIST">%2$s</xliff:g>:"</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Հավելվածներն օգտագործում են ձեր <xliff:g id="TYPES_LIST">%s</xliff:g>:"</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" և "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"տեսախցիկը"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"վայրը"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"խոսափողը"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Տվիչներն անջատած են"</string>
<string name="device_services" msgid="1549944177856658705">"Սարքի ծառայություններ"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Անանուն"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Համակարգի նավիգացիան թարմացվեց: Փոփոխություններ անելու համար անցեք կարգավորումներ:"</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Թարմացրեք համակարգի նավիգացիան կարգավորումներում"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Սպասման ռեժիմ"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Խոշորացման պատուհանի վրադրում"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Խոշորացման պատուհան"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Խոշորացման պատուհանի կառավարման տարրեր"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hy/strings_tv.xml b/packages/SystemUI/res/values-hy/strings_tv.xml
index 40c3bcbe03a4..d5dad69ca1ac 100644
--- a/packages/SystemUI/res/values-hy/strings_tv.xml
+++ b/packages/SystemUI/res/values-hy/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Առանց վերնագրի ծրագիր)"</string>
<string name="pip_close" msgid="5775212044472849930">"Փակել PIP-ն"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Լիէկրան"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Խոսափողն ակտիվացված է"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s հավելվածն օգտագործել է ձեր խոսափողը"</string>
</resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 99fa8454d78f..835725fd940f 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Pelajari lebih lanjut"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Perbesar utk mengisi layar"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Rentangkn utk mngisi layar"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Menyimpan screenshot..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Menyimpan screenshot..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot disimpan"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"buka ponsel"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"buka bantuan suara"</string>
<string name="camera_label" msgid="8253821920931143699">"buka kamera"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Batal"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Konfirmasi"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Coba lagi"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Ketuk untuk membatalkan autentikasi"</string>
@@ -323,7 +321,7 @@
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Alat Bantu Dengar"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Mengaktifkan…"</string>
<string name="quick_settings_brightness_label" msgid="680259653088849563">"Kecerahan"</string>
- <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Rotasi otomatis"</string>
+ <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Rotasi Otomatis"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Putar layar otomatis"</string>
<string name="accessibility_quick_settings_rotation_value" msgid="2916484894750819251">"Mode <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="quick_settings_rotation_locked_label" msgid="4420863550666310319">"Rotasi terkunci"</string>
@@ -371,7 +369,7 @@
<item quantity="one">%d perangkat</item>
</plurals>
<string name="quick_settings_notifications_label" msgid="3379631363952582758">"Notifikasi"</string>
- <string name="quick_settings_flashlight_label" msgid="4904634272006284185">"Lampu senter"</string>
+ <string name="quick_settings_flashlight_label" msgid="4904634272006284185">"Lampu Senter"</string>
<string name="quick_settings_flashlight_camera_in_use" msgid="4820591564526512571">"Kamera sedang digunakan"</string>
<string name="quick_settings_cellular_detail_title" msgid="792977203299358893">"Data seluler"</string>
<string name="quick_settings_cellular_detail_data_usage" msgid="6105969068871138427">"Penggunaan kuota"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Aktif pada <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Hingga <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Tema gelap"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Tema gelap\nPenghemat baterai"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Penghemat Baterai"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Aktif saat malam"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Sampai pagi"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC dinonaktifkan"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC diaktifkan"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Ketuk lagi untuk membuka"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Geser ke atas untuk membuka"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Geser ke atas untuk mencoba lagi"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Perangkat ini dikelola oleh organisasi"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Perangkat ini dikelola oleh <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Geser dari ikon untuk telepon"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Penghemat Baterai aktif"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Mengurangi kinerja dan data latar belakang"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Nonaktifkan Penghemat Baterai"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Saat merekam atau melakukan transmisi, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> dapat mengambil informasi sensitif apa pun yang ditampilkan di layar atau diputar dari perangkat Anda, termasuk informasi sensitif seperti audio, sandi, info pembayaran, foto, dan pesan."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Saat merekam atau melakukan transmisi, layanan yang memberikan fungsi ini dapat mengambil informasi sensitif apa pun yang ditampilkan di layar atau diputar dari perangkat Anda, termasuk informasi sensitif seperti audio, sandi, info pembayaran, foto, dan pesan."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Menampakkan informasi sensitif saat melakukan transmisi/merekam"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> akan memiliki akses ke semua informasi yang terlihat di layar atau diputar dari perangkat saat merekam atau melakukan transmisi. Ini mencakup informasi seperti sandi, detail pembayaran, foto, pesan, dan audio yang Anda putar."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Layanan yang menyediakan fungsi ini akan memiliki akses ke semua informasi yang terlihat di layar atau diputar dari perangkat saat merekam atau melakukan transmisi. Ini mencakup informasi seperti sandi, detail pembayaran, foto, pesan, dan audio yang Anda putar."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Mulai merekam atau melakukan transmisi dengan <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Jangan tampilkan lagi"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Hapus semua"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Kelola"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Pengalih keyboard"</string>
<string name="save" msgid="3392754183673848006">"Simpan"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Setel ulang"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Sesuaikan lebar tombol"</string>
<string name="clipboard" msgid="8517342737534284617">"Papan klip"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Tombol navigasi khusus"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Kanan"</string>
<string name="tuner_menu" msgid="363690665924769420">"Menu"</string>
<string name="tuner_app" msgid="6949280415826686972">"Aplikasi <xliff:g id="APP">%1$s</xliff:g>"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Notifikasi"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Baterai"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Screenshot"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Pesan Umum"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> berjalan"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Aplikasi dapat dibuka tanpa perlu diinstal."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Aplikasi dapat dibuka tanpa perlu diinstal. Ketuk untuk mempelajari lebih lanjut."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Info aplikasi"</string>
<string name="go_to_web" msgid="636673528981366511">"Buka browser"</string>
<string name="mobile_data" msgid="4564407557775397216">"Data seluler"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Setelan"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Oke"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Hapus Heap SysUI"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> menggunakan <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplikasi menggunakan <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" dan "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"lokasi"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensor nonaktif"</string>
<string name="device_services" msgid="1549944177856658705">"Layanan Perangkat"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Tanpa judul"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Navigasi sistem diupdate. Untuk melakukan perubahan, buka Setelan."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Buka Setelan untuk mengupdate navigasi sistem"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Siaga"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Jendela Overlay Pembesaran"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Jendela Pembesaran"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Kontrol Jendela Pembesaran"</string>
</resources>
diff --git a/packages/SystemUI/res/values-in/strings_tv.xml b/packages/SystemUI/res/values-in/strings_tv.xml
index 3c7a6fc54db4..5c4212358c65 100644
--- a/packages/SystemUI/res/values-in/strings_tv.xml
+++ b/packages/SystemUI/res/values-in/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Program tanpa judul)"</string>
<string name="pip_close" msgid="5775212044472849930">"Tutup PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Layar penuh"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Mikrofon Aktif"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s mengakses mikrofon"</string>
</resources>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index cd23616c4d7d..9f24d747ed87 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Frekari upplýsingar"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Fylla skjá með aðdrætti"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Teygja yfir allan skjáinn"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Skjámynd"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Vistar skjámynd…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Vistar skjámynd…"</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Skjámynd vistuð"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"opna síma"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"opna raddaðstoð"</string>
<string name="camera_label" msgid="8253821920931143699">"opna myndavél"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Hætta við"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Staðfesta"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Reyna aftur"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Ýttu til að hætta við auðkenningu"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Kveikt klukkan <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Til klukkan <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Dökkt þema"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Dökkt þema\nRafhlöðusparnaður"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Rafhlöðusparnaður"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Kveikt við sólsetur"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Til sólarupprásar"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"Slökkt á NFC"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"Kveikt á NFC"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Ýttu aftur til að opna"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Strjúktu upp til að opna"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Strjúktu upp til að reyna aftur"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Þessu tæki er stýrt af fyrirtækinu þínu"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Þessu tæki er stýrt af <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Strjúktu frá tákninu fyrir síma"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Kveikt er á rafhlöðusparnaði"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Dregur úr afköstum og bakgrunnsgögnum"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Slökkva á rafhlöðusparnaði"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Á meðan þú ert að taka upp eða senda út getur <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> fangað viðkvæmar upplýsingar sem birtast á skjánum eða eru spilaðar í tækinu, svo sem hljóð, aðgangsorð, greiðsluupplýsingar, myndir og skilaboð."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Á meðan þú ert að taka upp eða senda út getur þjónustan sem veitir þessar aðgerðir fangað viðkvæmar upplýsingar sem birtast á skjánum eða eru spilaðar í tækinu, svo sem hljóð, aðgangsorð, greiðsluupplýsingar, myndir og skilaboð."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Sýnir viðkvæmar upplýsingar við útsendingu/upptöku"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> mun hafa aðgang að öllum upplýsingum sem sjást á skjánum eða eru spilaðar í tækinu á meðan upptaka eða útsending er í gangi. Þar á meðal eru upplýsingar á borð við aðgangsorð, greiðsluupplýsingar, myndir, skilaboð og hljóð sem þú spilar."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Þjónustan sem býður upp á þennan eiginleika mun hafa aðgang að öllum upplýsingum sem sjást á skjánum eða eru spilaðar í tækinu á meðan upptaka eða útsending er í gangi. Þar á meðal eru upplýsingar á borð við aðgangsorð, greiðsluupplýsingar, myndir, skilaboð og hljóð sem þú spilar."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Viltu hefja upptöku eða útsendingu með <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Ekki sýna þetta aftur"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Hreinsa allt"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Stjórna"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Lyklaborðsval"</string>
<string name="save" msgid="3392754183673848006">"Vista"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Endurstilla"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Breyta breidd hnapps"</string>
<string name="clipboard" msgid="8517342737534284617">"Klippiborð"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Sérsniðinn flettingahnappur"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Hægri"</string>
<string name="tuner_menu" msgid="363690665924769420">"Valmynd"</string>
<string name="tuner_app" msgid="6949280415826686972">"Forritið <xliff:g id="APP">%1$s</xliff:g>"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Tilkynningar"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Rafhlaða"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Skjámyndir"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Almenn skilaboð"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> er í gangi"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Forrit opnað án þess að vera uppsett."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Forrit opnað án þess að vera uppsett. Ýttu til að fá frekari upplýsingar."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Forritsupplýsingar"</string>
<string name="go_to_web" msgid="636673528981366511">"Opna vafra"</string>
<string name="mobile_data" msgid="4564407557775397216">"Farsímagögn"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Stillingar"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Ég skil"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Vista SysUI-gögn"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> er að nota <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Forrit eru að nota <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" og "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"myndavél"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"staðsetning"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"hljóðnemi"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Slökkt á skynjurum"</string>
<string name="device_services" msgid="1549944177856658705">"Tækjaþjónusta"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Enginn titill"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Kerfisstjórnun uppfærð. Þú getur breytt þessu í stillingunum."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Farðu í stillingar til að uppfæra kerfisstjórnun"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Biðstaða"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Stækkun yfirglugga"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Stækkunargluggi"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Stækkunarstillingar glugga"</string>
</resources>
diff --git a/packages/SystemUI/res/values-is/strings_tv.xml b/packages/SystemUI/res/values-is/strings_tv.xml
index 91735a3537fe..d3a2bec324ee 100644
--- a/packages/SystemUI/res/values-is/strings_tv.xml
+++ b/packages/SystemUI/res/values-is/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Efni án titils)"</string>
<string name="pip_close" msgid="5775212044472849930">"Loka mynd í mynd"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Allur skjárinn"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Hljóðnemi virkur"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s fékk aðgang að hljóðnemanum þínum"</string>
</resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 9429c04de8f8..9b2faa5da748 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Ulteriori informazioni"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Zoom per riempire schermo"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Estendi per riemp. schermo"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Salvataggio screenshot..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Salvataggio screenshot..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot salvato"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"apri telefono"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"apri Voice Assist"</string>
<string name="camera_label" msgid="8253821920931143699">"apri fotocamera"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Annulla"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Conferma"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Riprova"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Tocca per annullare l\'autenticazione"</string>
@@ -199,7 +197,7 @@
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Dati mobili attivati"</string>
<string name="cell_data_off_content_description" msgid="9165555931499878044">"Dati mobili disattivati"</string>
<string name="not_default_data_content_description" msgid="6757881730711522517">"Non impostato per l\'utilizzo dei dati"</string>
- <string name="cell_data_off" msgid="4886198950247099526">"Off"</string>
+ <string name="cell_data_off" msgid="4886198950247099526">"OFF"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Tethering Bluetooth."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Modalità aereo."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN attiva."</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Dalle <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Fino alle <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Tema scuro"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Tema scuro\nRisparmio energetico"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Risparmio energetico"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Attivato al tramonto"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Fino all\'alba"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC non attiva"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC attiva"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Tocca ancora per aprire"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Scorri verso l\'alto per aprire"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Scorri verso l\'alto per riprovare"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Questo dispositivo è gestito dalla tua organizzazione"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Questo dispositivo è gestito da <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Scorri per accedere al telefono"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Risparmio energetico attivo"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Riduce le prestazioni e i dati in background"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Disattiva Risparmio energetico"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Mentre registri o trasmetti, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> può acquisire tutti i dati sensibili che vengono mostrati sul tuo schermo o riprodotti dal tuo dispositivo, incluse informazioni sensibili quali contenuti audio, password, informazioni di pagamento, foto e messaggi."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Mentre registri o trasmetti, il servizio che offre questa funzionalità può acquisire tutti i dati sensibili che vengono mostrati sul tuo schermo o riprodotti dal tuo dispositivo, incluse informazioni sensibili quali contenuti audio, password, informazioni di pagamento, foto e messaggi."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Esposizione di informazioni sensibili durante la trasmissione/registrazione"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> avrà accesso a tutte le informazioni visibili sul tuo schermo o riprodotte dal tuo dispositivo durante la registrazione o la trasmissione. Sono incluse informazioni quali password, dettagli sui pagamenti, foto, messaggi e audio riprodotto."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Il servizio che offre questa funzione avrà accesso a tutte le informazioni visibili sul tuo schermo o riprodotte dal tuo dispositivo durante la registrazione o la trasmissione. Sono incluse informazioni quali password, dettagli sui pagamenti, foto, messaggi e audio riprodotto."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Vuoi avviare la registrazione o la trasmissione con <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Non mostrare più"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Cancella tutto"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Gestisci"</string>
@@ -643,7 +641,7 @@
<string name="do_not_silence_block" msgid="4361847809775811849">"Non silenziare e non bloccare"</string>
<string name="tuner_full_importance_settings" msgid="1388025816553459059">"Controlli di gestione delle notifiche"</string>
<string name="tuner_full_importance_settings_on" msgid="917981436602311547">"On"</string>
- <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Off"</string>
+ <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"OFF"</string>
<string name="power_notification_controls_description" msgid="1334963837572708952">"I controlli di gestione delle notifiche ti consentono di impostare un livello di importanza compreso tra 0 e 5 per le notifiche di un\'app. \n\n"<b>"Livello 5"</b>" \n- Mostra in cima all\'elenco di notifiche \n- Consenti l\'interruzione a schermo intero \n- Visualizza sempre \n\n"<b>"Livello 4"</b>" \n- Impedisci l\'interruzione a schermo intero \n- Visualizza sempre \n\n"<b>"Livello 3"</b>" \n- Impedisci l\'interruzione a schermo intero \n- Non visualizzare mai \n\n"<b>"Livello 2"</b>" \n- Impedisci l\'interruzione a schermo intero \n- Non visualizzare mai \n- Non emettere mai suoni e vibrazioni \n\n"<b>"Livello 1"</b>" \n- Impedisci l\'interruzione a schermo intero \n- Non visualizzare mai \n- Non emettere mai suoni e vibrazioni \n- Nascondi da schermata di blocco e barra di stato \n- Mostra in fondo all\'elenco di notifiche \n\n"<b>"Livello 0"</b>" \n- Blocca tutte le notifiche dell\'app"</string>
<string name="notification_header_default_channel" msgid="225454696914642444">"Notifiche"</string>
<string name="notification_channel_disabled" msgid="928065923928416337">"Non vedrai più queste notifiche"</string>
@@ -766,7 +764,7 @@
<string name="accessibility_data_saver_on" msgid="5394743820189757731">"Risparmio dati attivo"</string>
<string name="accessibility_data_saver_off" msgid="58339669022107171">"Risparmio dati disattivato"</string>
<string name="switch_bar_on" msgid="1770868129120096114">"On"</string>
- <string name="switch_bar_off" msgid="5669805115416379556">"Off"</string>
+ <string name="switch_bar_off" msgid="5669805115416379556">"OFF"</string>
<string name="nav_bar" msgid="4642708685386136807">"Barra di navigazione"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Layout"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Tipo di pulsante extra sinistra"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Selettore tastiera"</string>
<string name="save" msgid="3392754183673848006">"Salva"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Reimposta"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Modifica la larghezza del pulsante"</string>
<string name="clipboard" msgid="8517342737534284617">"Appunti"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Pulsante di navigazione personalizzato"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Destra"</string>
<string name="tuner_menu" msgid="363690665924769420">"Menu"</string>
<string name="tuner_app" msgid="6949280415826686972">"App <xliff:g id="APP">%1$s</xliff:g>"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Avvisi"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Batteria"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Screenshot"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Messaggi generali"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"App <xliff:g id="APP">%1$s</xliff:g> in esecuzione"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"App aperta senza essere stata installata."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"App aperta senza essere stata installata. Tocca per avere ulteriori informazioni."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Informazioni app"</string>
<string name="go_to_web" msgid="636673528981366511">"Vai al browser"</string>
<string name="mobile_data" msgid="4564407557775397216">"Dati mobili"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> - <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Impostazioni"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"OK"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Esegui dump heap SysUI"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"L\'app <xliff:g id="APP">%1$s</xliff:g> sta usando <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Le app stanno usando <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" e "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"Fotocamera"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"luogo"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"un microfono"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensori disattivati"</string>
<string name="device_services" msgid="1549944177856658705">"Servizi del dispositivo"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Senza titolo"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Navigazione del sistema aggiornata. Per apportare modifiche, usa le Impostazioni."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Usa le Impostazioni per aggiornare la navigazione del sistema"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Standby"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Finestra overlay ingrandimento"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Finestra ingrandimento"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Finestra controlli di ingrandimento"</string>
</resources>
diff --git a/packages/SystemUI/res/values-it/strings_tv.xml b/packages/SystemUI/res/values-it/strings_tv.xml
index 074118fdbbad..782b959a134a 100644
--- a/packages/SystemUI/res/values-it/strings_tv.xml
+++ b/packages/SystemUI/res/values-it/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Programma senza titolo)"</string>
<string name="pip_close" msgid="5775212044472849930">"Chiudi PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Schermo intero"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Microfono attivo"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s ha avuto accesso al tuo microfono"</string>
</resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index b2da88a99f05..474327d67da9 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"מידע נוסף"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"הגדל תצוגה כדי למלא את המסך"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"מתח כדי למלא את המסך"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"צילום מסך"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"שומר צילום מסך..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"שומר צילום מסך..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"צילום המסך נשמר"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"פתח את הטלפון"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"פתח את המסייע הקולי"</string>
<string name="camera_label" msgid="8253821920931143699">"פתח את המצלמה"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"ביטול"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"אישור"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"ניסיון נוסף"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"יש להקיש כדי לבטל את האימות"</string>
@@ -391,7 +389,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"מופעל בשעה <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"עד <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"עיצוב כהה"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"עיצוב כהה\nחיסכון בסוללה"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"חיסכון בסוללה"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"מופעל בשקיעה"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"עד הזריחה"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"‏NFC מושבת"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"‏NFC מופעל"</string>
@@ -416,10 +416,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"הקש שוב כדי לפתוח"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"צריך להחליק כדי לפתוח"</string>
<string name="keyguard_retry" msgid="886802522584053523">"יש להחליק למעלה כדי לנסות שוב"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"מכשיר זה מנוהל על ידי הארגון שלך"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"המכשיר הזה מנוהל על ידי <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"החלק מהסמל כדי להפעיל את הטלפון"</string>
@@ -473,9 +469,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"תכונת החיסכון בסוללה פועלת"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"מפחית את הביצועים ונתונים ברקע"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"כיבוי תכונת החיסכון בסוללה"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"בזמן הקלטה או העברה, האפליקציה <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> יכולה לקלוט מידע רגיש שמוצג במסך או מופעל מהמכשיר שלך, כולל מידע רגיש כמו אודיו, סיסמאות, פרטי תשלום, תמונות והודעות."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"בזמן הקלטה או העברה, השירות שמספק את הפונקציה הזו יכול לקלוט מידע רגיש שמוצג במסך או מופעל מהמכשיר שלך, כולל מידע רגיש כמו אודיו, סיסמאות, פרטי תשלום, תמונות והודעות."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"חשיפת מידע רגיש בזמן העברה/הקלטה"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"‏לאפליקציה <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> תהיה גישה לכל הפרטים שגלויים במסך שלך או מופעלים מהמכשיר שלך בזמן הקלטה או העברה (cast). זה כולל פרטים כמו סיסמאות, פרטי תשלום, תמונות, הודעות ואודיו שמושמע מהמכשיר."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"‏לשירות שמספק את הפונקציה הזו תהיה גישה לכל הפרטים שגלויים במסך שלך או מופעלים מהמכשיר שלך בזמן הקלטה או העברה (cast). זה כולל פרטים כמו סיסמאות, פרטי תשלום, תמונות, הודעות ואודיו שמושמע מהמכשיר."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"‏להתחיל להקליט או להעביר (cast) באמצעות <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"אל תציג שוב"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"ניקוי הכל"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"ניהול"</string>
@@ -796,8 +794,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"מחליף מקלדת"</string>
<string name="save" msgid="3392754183673848006">"שמירה"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"איפוס"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"שינוי של רוחב לחצן"</string>
<string name="clipboard" msgid="8517342737534284617">"לוח"</string>
<string name="accessibility_key" msgid="3471162841552818281">"לחצן לניווט מותאם אישית"</string>
@@ -893,8 +890,7 @@
<string name="tuner_right" msgid="8247571132790812149">"ימינה"</string>
<string name="tuner_menu" msgid="363690665924769420">"תפריט"</string>
<string name="tuner_app" msgid="6949280415826686972">"האפליקציה <xliff:g id="APP">%1$s</xliff:g>"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"התראות"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"סוללה"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"צילומי מסך"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"הודעות כלליות"</string>
@@ -904,8 +900,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> פועלת"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"האפליקציה נפתחת בלי התקנה."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"האפליקציה נפתחת בלי התקנה. אפשר להקיש כדי לקבל מידע נוסף."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"פרטי האפליקציה"</string>
<string name="go_to_web" msgid="636673528981366511">"מעבר אל הדפדפן"</string>
<string name="mobile_data" msgid="4564407557775397216">"נתונים סלולריים"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> ‏— <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -939,13 +934,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"הגדרות"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"הבנתי"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"‏ערימת Dump SysUI"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> משתמשת ב<xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"אפליקציות משתמשות ב<xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" וגם "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"מצלמה"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"מיקום"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"מיקרופון"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"החיישנים כבויים"</string>
<string name="device_services" msgid="1549944177856658705">"שירותים למכשיר"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"ללא שם"</string>
@@ -968,4 +956,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"הניווט במערכת עודכן. אפשר לערוך שינויים דרך ההגדרות."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"יש לעבור להגדרות כדי לעדכן את הניווט במערכת"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"המתנה"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"חלון ליצירת שכבת-על להגדלה"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"חלון הגדלה"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"בקרות של חלון ההגדלה"</string>
</resources>
diff --git a/packages/SystemUI/res/values-iw/strings_tv.xml b/packages/SystemUI/res/values-iw/strings_tv.xml
index 88d691262911..1e5fc91ecff1 100644
--- a/packages/SystemUI/res/values-iw/strings_tv.xml
+++ b/packages/SystemUI/res/values-iw/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(תוכנית ללא כותרת)"</string>
<string name="pip_close" msgid="5775212044472849930">"‏סגור PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"מסך מלא"</string>
+ <string name="mic_active" msgid="5766614241012047024">"המיקרופון פעיל"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"‏%1$s קיבלה גישה למיקרופון שלך"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 94dce862e742..2f1ad0922597 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -70,12 +70,11 @@
<string name="learn_more" msgid="4690632085667273811">"詳細"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"画面サイズに合わせて拡大"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"画面サイズに合わせて拡大"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"スクリーンショット"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"スクリーンショットを保存中..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"スクリーンショットを保存しています..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"スクリーンショットを保存しました"</string>
- <string name="screenshot_saved_text" msgid="7778833104901642442">"タップするとスクリーンショットが表示されます"</string>
+ <string name="screenshot_saved_text" msgid="7778833104901642442">"タップしてスクリーンショットを表示します"</string>
<string name="screenshot_failed_title" msgid="3259148215671936891">"スクリーンショット保存エラー"</string>
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"スクリーンショットを撮り直してください"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"空き容量が足りないため、スクリーンショットを保存できません"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"電話を起動"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"音声アシストを開く"</string>
<string name="camera_label" msgid="8253821920931143699">"カメラを起動"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"キャンセル"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"確認"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"再試行"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"タップすると認証をキャンセルします"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"<xliff:g id="TIME">%s</xliff:g> に ON"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g> まで"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"ダークテーマ"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"ダークテーマ\nバッテリー セーバー"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"バッテリー セーバー"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"日の入りに ON"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"日の出まで"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC は無効です"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC は有効です"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"開くにはもう一度タップしてください"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"開くには上にスワイプします"</string>
<string name="keyguard_retry" msgid="886802522584053523">"上にスワイプしてもう一度お試しください"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"このデバイスは組織によって管理されています"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"このデバイスは <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> が管理しています"</string>
<string name="phone_hint" msgid="6682125338461375925">"右にスワイプして通話"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"バッテリー セーバー ON"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"パフォーマンスとバックグラウンドデータを制限します"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"バッテリー セーバーを OFF"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"記録中やキャスト中に、<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>は、画面上に表示またはデバイスから再生されている個人的な情報(音声、パスワード、お支払い情報、写真、メッセージなど)を取得する可能性があります。"</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"記録中やキャスト中に、この機能を提供するサービスは、画面上に表示またはデバイスから再生されている個人的な情報(音声、パスワード、お支払い情報、写真、メッセージなど)を取得する可能性があります。"</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"キャスト中や記録中にプライベート情報が公開されます"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>は、記録中やキャスト中に画面上に表示またはデバイスから再生されるすべての情報にアクセスできます。これには、パスワード、お支払いの詳細、写真、メッセージ、再生される音声などの情報が含まれます。"</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"この機能を提供するサービスは、記録中やキャスト中に画面上に表示またはデバイスから再生されるすべての情報にアクセスできます。これには、パスワード、お支払いの詳細、写真、メッセージ、再生される音声などの情報が含まれます。"</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>で記録やキャストを開始しますか?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"次回から表示しない"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"すべて消去"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"管理"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"キーボードを切り替え"</string>
<string name="save" msgid="3392754183673848006">"保存"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"リセット"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"ボタンの幅の調整"</string>
<string name="clipboard" msgid="8517342737534284617">"クリップボード"</string>
<string name="accessibility_key" msgid="3471162841552818281">"カスタム ナビゲーション ボタン"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"右"</string>
<string name="tuner_menu" msgid="363690665924769420">"メニュー"</string>
<string name="tuner_app" msgid="6949280415826686972">"<xliff:g id="APP">%1$s</xliff:g> アプリ"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"アラート"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"電池"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"スクリーンショット"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"一般メッセージ"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> を実行中"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"アプリをインストールせずに開きました。"</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"アプリをインストールせずに開きました。詳細を見るにはタップしてください。"</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"アプリ情報"</string>
<string name="go_to_web" msgid="636673528981366511">"ブラウザに移動"</string>
<string name="mobile_data" msgid="4564407557775397216">"モバイルデータ"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"設定"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"OK"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"SysUI ヒープのダンプ"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g>は<xliff:g id="TYPES_LIST">%2$s</xliff:g>を使用しています。"</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"アプリは<xliff:g id="TYPES_LIST">%s</xliff:g>を使用しています。"</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">"、 "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" 、 "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"カメラ"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"現在地情報"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"マイク"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"センサー OFF"</string>
<string name="device_services" msgid="1549944177856658705">"デバイス サービス"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"タイトルなし"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"システム ナビゲーションを更新しました。変更するには [設定] に移動してください。"</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"システム ナビゲーションを更新するには [設定] に移動してください"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"スタンバイ"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"拡大オーバーレイ ウィンドウ"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"拡大ウィンドウ"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"拡大ウィンドウ コントロール"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ja/strings_tv.xml b/packages/SystemUI/res/values-ja/strings_tv.xml
index 5506b8e78a57..32f30d388320 100644
--- a/packages/SystemUI/res/values-ja/strings_tv.xml
+++ b/packages/SystemUI/res/values-ja/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(無題の番組)"</string>
<string name="pip_close" msgid="5775212044472849930">"PIP を閉じる"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"全画面表示"</string>
+ <string name="mic_active" msgid="5766614241012047024">"マイク: 有効"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s がマイクにアクセスしました"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index d1e37a4810cb..7754572578da 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"შეიტყვეთ მეტი"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"მასშტაბი შეცვალეთ ეკრანის შესავსებად."</string>
<string name="compat_mode_off" msgid="7682459748279487945">"გაწიეთ ეკრანის შესავსებად."</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"ეკრანის ანაბეჭდი"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"სკრინშოტის შენახვა…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"ეკრანის სურათის შენახვა…"</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"ეკრანის ანაბეჭდი შენახულია"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"ტელეფონის გახსნა"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"ხმოვანი დახმარების გახსნა"</string>
<string name="camera_label" msgid="8253821920931143699">"კამერის გახსნა"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"გაუქმება"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"დადასტურება"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"ხელახლა ცდა"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"შეეხეთ ავტორიზაციის გასაუქმებლად"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"ჩაირთოს <xliff:g id="TIME">%s</xliff:g>-ზე"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g>-მდე"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"მუქი თემა"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"მუქი თემა\nბატარეის დამზოგი"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"ბატარეის დამზოგი"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"ჩაირთოს მზის ჩასვლისას"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"მზის ამოსვლამდე"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC გათიშულია"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ჩართულია"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"შეეხეთ ისევ გასახსნელად"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"გასახსნელად გადაფურცლეთ ზემოთ"</string>
<string name="keyguard_retry" msgid="886802522584053523">"ხელახლა საცდელად გადაფურცლეთ ზემოთ"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"ამ მოწყობილობას მართავს თქვენი ორგანიზაცია"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"ამ მოწყობილობას მართავს <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"ტელეფონისთვის გადაფურცლეთ ხატულადან"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"ბატარეის დამზოგი ჩართულია"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"ამცირებს წარმადობას და უკანა ფონის მონაცემებს"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"ბატარეის დამზოგის გამორთვა"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"ჩაწერის ან ტრანსლირების განმავლობაში, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>-ს შეუძლია აღბეჭდოს ნებისმიერი სენსიტიური ინფორმაცია, რომელიც თქვენს ეკრანზეა ნაჩვენები ან თქვენი მოწყობილობიდან იკვრება, მათ შორის ისეთი, როგორიც არის აუდიო, პაროლები, გადახდის ინფორმაცია, ფოტოები და შეტყობინებები."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"ჩაწერის ან ტრანსლირების განმავლობაში, ამ ფუნქციის მომწოდებელ სერვისს შეუძლია აღბეჭდოს ნებისმიერი სენსიტიური ინფორმაცია, რომელიც თქვენს ეკრანზეა ნაჩვენები ან თქვენი მოწყობილობიდან იკვრება, მათ შორის ისეთი, როგორიც არის აუდიო, პაროლები, გადახდის ინფორმაცია, ფოტოები და შეტყობინებები."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"ტრანსლირების/ჩაწერის განმავლობაში მჟღავნდება სენსიტიური ინფორმაცია"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>-ს ექნება წვდომა ყველა ინფორმაციაზე, რომელიც თქვენს ეკრანზე გამოჩნდება ან თქვენს მოწყობილობაზე დაიკვრება ჩაწერის ან ტრანსლირების განმავლობაში. აღნიშნული მოიცავს ისეთ ინფორმაციას, როგორიც არის პაროლები, გადახდის დეტალები, ფოტოები, შეტყობინებები და თქვენ მიერ დაკრული აუდიო."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"ამ ფუნქციის მომწოდებელ სერვისს ექნება წვდომა ყველა ინფორმაციაზე, რომელიც თქვენს ეკრანზე გამოჩნდება ან თქვენს მოწყობილობაზე დაიკვრება ჩაწერის ან ტრანსლირების განმავლობაში. აღნიშნული მოიცავს ისეთ ინფორმაციას, როგორიც არის პაროლები, გადახდის დეტალები, ფოტოები, შეტყობინებები და თქვენ მიერ დაკრული აუდიო."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"დაიწყოს ჩაწერა ან ტრანსლირება <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>-ით?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"აღარ მაჩვენო"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"ყველას გასუფთავება"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"მართვა"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"კლავიატურის გადამრთველი"</string>
<string name="save" msgid="3392754183673848006">"შენახვა"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"გადაყენება"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"ღილაკის სიგანის კორექტირება"</string>
<string name="clipboard" msgid="8517342737534284617">"გაცვლის ბუფერი"</string>
<string name="accessibility_key" msgid="3471162841552818281">"ნავიგაციის მორგებული ღილაკი"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"მარჯვენა"</string>
<string name="tuner_menu" msgid="363690665924769420">"მენიუ"</string>
<string name="tuner_app" msgid="6949280415826686972">"<xliff:g id="APP">%1$s</xliff:g> აპი"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"გაფრთხილებები"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"ბატარეა"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"ეკრანის ანაბეჭდები"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"ზოგადი შეტყობინებები"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> გაშვებულია"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"აპი გაიხსნა ინსტალაციის გარეშე."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"აპი გაიხსნა ინსტალაციის გარეშე. შეეხეთ მეტის გასაგებად."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"აპის ინფორმაცია"</string>
<string name="go_to_web" msgid="636673528981366511">"ბრაუზერზე გადასვლა"</string>
<string name="mobile_data" msgid="4564407557775397216">"მობილური ინტერნეტი"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"პარამეტრები"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"გასაგებია"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"SysUI გროვის გამოტანა"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g>-ის მიერ გამოიყენება თქვენი <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"აპლიკაციების მიერ გამოიყენება თქვენი <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" და "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"კამერა"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"მდებარეობა"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"მიკროფონი"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"სენსორების გამორთვა"</string>
<string name="device_services" msgid="1549944177856658705">"მოწყობილობის სერვისები"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"უსათაურო"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"სისტემური ნავიგაცია განახლდა. ცვლილებების შესატანად გადადით პარამეტრებზე."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"სისტემური ნავიგაციის გასაახლებლად გადადით პარამეტრებზე"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"მოლოდინის რეჟიმი"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"გადიდების გადაფარვის ფანჯარა"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"გადიდების ფანჯარა"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"გადიდების კონტროლის ფანჯარა"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ka/strings_tv.xml b/packages/SystemUI/res/values-ka/strings_tv.xml
index e7b31224f808..b0ed30a4f218 100644
--- a/packages/SystemUI/res/values-ka/strings_tv.xml
+++ b/packages/SystemUI/res/values-ka/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(პროგრამის სათაურის გარეშე)"</string>
<string name="pip_close" msgid="5775212044472849930">"PIP-ის დახურვა"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"სრულ ეკრანზე"</string>
+ <string name="mic_active" msgid="5766614241012047024">"მიკროფონი აქტიურია"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s-მა გამოიყენა თქვენი მიკროფონი"</string>
</resources>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index c77a07566224..f60aeaf37ac0 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Толығырақ"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Экранды толтыру үшін ұлғайту"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Экранды толтыру үшін созу"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Скриншот"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Скриншотты сақтауда…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Скриншотты сақтауда…"</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Скриншот сақталды"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"телефонды ашу"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"ашық дауыс көмекшісі"</string>
<string name="camera_label" msgid="8253821920931143699">"камераны ашу"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Бас тарту"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Растау"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Қайталап көріңіз"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Аутентификациядан бас тарту үшін түртіңіз."</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Қосылу уақыты: <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g> дейін"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Қараңғы тақырып"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Қараңғы тақырып\nBattery saver"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Battery Saver"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Күн батқанда қосу"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Күн шыққанға дейін"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC өшірулі"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC қосулы"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Ашу үшін қайта түртіңіз"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Ашу үшін жоғары қарай сырғытыңыз."</string>
<string name="keyguard_retry" msgid="886802522584053523">"Әрекетті қайталау үшін жоғары сырғытыңыз."</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Бұл құрылғыны ұйым басқарады"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Бұл құрылғыны <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> басқарады"</string>
<string name="phone_hint" msgid="6682125338461375925">"Телефонды ашу үшін белгішеден әрі қарай сырғытыңыз"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Battery saver қосулы"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Өнімділікті және фондық деректерді азайтады"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Battery saver функциясын өшіру"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Жазу немесе трансляциялау кезінде, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> экранда көрсетілген немесе құрылғыңызда ойнатылған құпия ақпараттың барлығын (мысалы, аудио, құпия сөздер, төлем туралы ақпарат, фотосуреттер және хабарлар) тіркеп отырады."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Жазу немесе трансляциялау кезінде, осы функцияны ұсынатын қызмет экранда көрсетілген немесе құрылғыңызда ойнатылған құпия ақпараттың барлығын (мысалы, аудио, құпия сөздер, төлем туралы ақпарат, фотосуреттер және хабарлар) тіркеп отырады."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Трансляциялау/жазу кезінде құпия ақпаратты көрсету"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> экранда көрсетілетін немесе жазу не трансляциялау кезінде құрылғыда ойнатылған барлық ақпаратты пайдалана алады. Бұған құпия сөздер, төлем туралы мәліметтер, суреттер, хабарлар және ойнатылатын аудио сияқты ақпарат кіреді."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Осы функцияны ұсынатын қызмет экранда көрсетілетін немесе жазу не трансляциялау кезінде құрылғыда ойнатылған барлық ақпаратты пайдалана алады. Бұған құпия сөздер, төлем туралы мәліметтер, суреттер, хабарлар және ойнатылатын аудио сияқты ақпарат кіреді."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> арқылы жазу немесе трансляциялау басталсын ба?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Қайта көрсетпеу"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Барлығын тазалау"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Басқару"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Пернетақта ауыстырғышы"</string>
<string name="save" msgid="3392754183673848006">"Сақтау"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Бастапқы күйге қайтару"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Түйме енін реттеу"</string>
<string name="clipboard" msgid="8517342737534284617">"Буфер"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Арнаулы шарлау түймесі"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Оң жақ"</string>
<string name="tuner_menu" msgid="363690665924769420">"Mәзір"</string>
<string name="tuner_app" msgid="6949280415826686972">"<xliff:g id="APP">%1$s</xliff:g> қолданбасы"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Ескертулер"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Батарея"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Скриншоттар"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Жалпы хабарлар"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> іске қосулы"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Қолданба орнатылмай-ақ ашылды."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Қолданба орнатылмай-ақ ашылды. Толығырақ мәлімет алу үшін түртіңіз."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Қолданба ақпараты"</string>
<string name="go_to_web" msgid="636673528981366511">"Браузерге өту"</string>
<string name="mobile_data" msgid="4564407557775397216">"Мобильдік интернет"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Параметрлер"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Түсінікті"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> қолданбасында <xliff:g id="TYPES_LIST">%2$s</xliff:g> пайдалануда."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Қолданбаларда <xliff:g id="TYPES_LIST">%s</xliff:g> пайдаланылуда."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" және "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"камера"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"геодерек"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"микрофон"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Датчиктер өшірулі"</string>
<string name="device_services" msgid="1549944177856658705">"Құрылғы қызметтері"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Атауы жоқ"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Жүйе навигациясы жаңартылды. Өзгерту енгізу үшін \"Параметрлер\" бөліміне өтіңіз."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Жүйе навигациясын жаңарту үшін \"Параметрлер\" бөліміне өтіңіз."</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Күту режимі"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Ұлғайту терезесін қабаттастыру"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Ұлғайту терезесі"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Ұлғайту терезесінің басқару элементтері"</string>
</resources>
diff --git a/packages/SystemUI/res/values-kk/strings_tv.xml b/packages/SystemUI/res/values-kk/strings_tv.xml
index 47ad21bf9c78..323c5e6c0bc7 100644
--- a/packages/SystemUI/res/values-kk/strings_tv.xml
+++ b/packages/SystemUI/res/values-kk/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Атаусыз бағдарлама)"</string>
<string name="pip_close" msgid="5775212044472849930">"PIP жабу"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Толық экран"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Микрофон қосулы"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s микрофоныңызды пайдаланды."</string>
</resources>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 0cb691092a59..0550adefe547 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"ស្វែងយល់​បន្ថែម"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"ពង្រីក​​ដើម្បី​ឲ្យ​ពេញ​អេក្រង់"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"ទាញ​ដើម្បី​ឲ្យ​ពេញ​អេក្រង់"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"រូបថតអេក្រង់"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"កំពុង​រក្សាទុក​រូបថត​អេក្រង់…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"កំពុង​រក្សាទុក​រូបថត​អេក្រង់..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"បានរក្សាទុក​រូបថតអេក្រង់"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"បើក​ទូរស័ព្ទ"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"បើកជំនួយសំឡេង"</string>
<string name="camera_label" msgid="8253821920931143699">"បើក​ម៉ាស៊ីន​ថត"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"បោះបង់"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"បញ្ជាក់"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"ព្យាយាម​ម្ដង​ទៀត"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"ចុចដើម្បីបោះបង់​ការផ្ទៀងផ្ទាត់"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"បើក​នៅម៉ោង <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"រហូតដល់​ម៉ោង <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"រចនាប័ទ្ម​ងងឹត"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"រចនាប័ទ្មងងឹត\nកម្មវិធីសន្សំថ្ម"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"កម្មវិធីសន្សំថ្ម"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"បើក​នៅពេល​ថ្ងៃលិច"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"រហូត​ដល់​ពេល​ថ្ងៃរះ"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"បាន​បិទ NFC"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"បាន​បើក NFC"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"ប៉ះ​ម្ដង​ទៀត ដើម្បី​បើក"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"អូសឡើងលើ​ដើម្បីបើក"</string>
<string name="keyguard_retry" msgid="886802522584053523">"អូសឡើងលើ ដើម្បី​ព្យាយាម​ម្ដងទៀត"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"ឧបករណ៍​នេះ​ស្ថិត​ក្រោម​ការ​គ្រប់គ្រង​​របស់ស្ថាប័ន​​អ្នក"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"ឧបករណ៍នេះស្ថិតក្រោមការគ្រប់គ្រងរបស់ <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"អូសចេញពីរូបតំណាងដើម្បីប្រើទូរស័ព្ទ"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"កម្មវិធីសន្សំថ្មបានបើក"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"ការ​បន្ថយ​ការ​ប្រតិបត្តិ និង​ទិន្នន័យ​ផ្ទៃ​ខាងក្រោយ"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"បិទ​កម្មវិធី​សន្សំ​ថ្ម"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"នៅពេល​កំពុងថត ឬភ្ជាប់ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> អាច​ថតព័ត៌មាន​រសើប​ទាំងឡាយ​ដែលបង្ហាញ​នៅលើ​អេក្រង់​របស់អ្នក ឬដែលចាក់ពី​ឧបករណ៍​របស់អ្នក រួមទាំង​ព័ត៌មាន​រសើប​ដូចជា សំឡេង ពាក្យ​សម្ងាត់ ព័ត៌មាន​បង់ប្រាក់ រូបថត និងសារ​ជាដើម។"</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"នៅពេល​កំពុងថត ឬបញ្ជូន សេវាកម្មដែល​ផ្ដល់មុខងារនេះ​អាចថតព័ត៌មាន​រសើប​ទាំងឡាយ​ដែលបង្ហាញ​នៅលើ​អេក្រង់​របស់អ្នក ឬដែលចាក់​ពីឧបករណ៍​របស់អ្នក រួមទាំង​ព័ត៌មាន​រសើប​ដូចជា សំឡេង ពាក្យ​សម្ងាត់ ព័ត៌មាន​បង់ប្រាក់​ រូបថត និងសារ​ជាដើម។"</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"ការបង្ហាញព័ត៌មានរសើប​ អំឡុងពេលភ្ជាប់/ថត"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> នឹងមានសិទ្ធិ​ចូលប្រើ​ព័ត៌មាន​ទាំងអស់​ដែលអាច​មើលឃើញ​នៅលើ​អេក្រង់​របស់អ្នក ឬដែលចាក់​ពីឧបករណ៍​របស់អ្នក នៅពេល​កំពុង​ថត ឬបញ្ជូន។ ព័ត៌មាន​នេះមាន​ដូចជា ពាក្យសម្ងាត់ ព័ត៌មាន​លម្អិត​អំពីការទូទាត់​ប្រាក់ រូបថត សារ និង​សំឡេង​ដែល​អ្នកចាក់​ជាដើម។"</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"សេវាកម្មដែល​ផ្ដល់​មុខងារ​នេះ​នឹងមាន​សិទ្ធិ​ចូលប្រើ​ព័ត៌មាន​ទាំងអស់​ដែល​អាច​មើលឃើញ​នៅលើ​អេក្រង់​របស់អ្នក ឬ​ដែលចាក់​ពីឧបករណ៍​របស់អ្នក នៅពេល​កំពុង​ថត ឬបញ្ជូន។ ព័ត៌មាន​នេះមាន​ដូចជា ពាក្យសម្ងាត់ ព័ត៌មាន​លម្អិត​អំពីការទូទាត់​ប្រាក់ រូបថត សារ និង​សំឡេង​ដែល​អ្នកចាក់​ជាដើម។"</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"ចាប់ផ្ដើម​ថត ឬបញ្ជូន​ដោយប្រើ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ឬ?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"កុំ​បង្ហាញ​ម្ដងទៀត"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"សម្អាត​ទាំងអស់"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"គ្រប់គ្រង"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"កម្មវិធី​ប្តូរក្តារ​ចុច"</string>
<string name="save" msgid="3392754183673848006">"រក្សាទុក"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"កំណត់​ឡើងវិញ"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"កែសម្រួលទទឹងប៊ូតុង"</string>
<string name="clipboard" msgid="8517342737534284617">"ក្ដារ​តម្បៀត​ខ្ទាស់"</string>
<string name="accessibility_key" msgid="3471162841552818281">"ប៊ូតុងរុករកផ្ទាល់ខ្លួន"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"ស្ដាំ"</string>
<string name="tuner_menu" msgid="363690665924769420">"ម៉ឺនុយ"</string>
<string name="tuner_app" msgid="6949280415826686972">"កម្មវិធី <xliff:g id="APP">%1$s</xliff:g>"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"ការជូនដំណឹង"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"ថ្ម"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"រូបថត​អេក្រង់"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"សារ​ទូទៅ"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> កំពុង​ដំណើរការ"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"កម្មវិធីត្រូវ​បាន​បើក​ដោយ​មិនចាំបាច់ដំឡើង។"</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"កម្មវិធីត្រូវ​បាន​បើក​ដោយ​មិនចាំបាច់ដំឡើង។ ចុច​ដើម្បី​ស្វែងយល់បន្ថែម។"</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"ព័ត៌មាន​អំពីកម្មវិធី"</string>
<string name="go_to_web" msgid="636673528981366511">"ចូល​ទៅ​កម្មវិធី​រុករក​តាម​អ៊ីនធឺណិត"</string>
<string name="mobile_data" msgid="4564407557775397216">"ទិន្នន័យ​ទូរសព្ទចល័ត"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"ការកំណត់"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"យល់ហើយ"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"ចម្លង SysUI Heap"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> កំពុងប្រើ <xliff:g id="TYPES_LIST">%2$s</xliff:g> របស់អ្នក។"</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"កម្មវិធី​កំពុងប្រើ <xliff:g id="TYPES_LIST">%s</xliff:g> របស់អ្នក។"</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" និង "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"កាមេរ៉ា"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"ទីតាំង"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"មីក្រូហ្វូន"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"បិទឧបករណ៍​ចាប់សញ្ញា"</string>
<string name="device_services" msgid="1549944177856658705">"សេវាកម្មឧបករណ៍"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"គ្មាន​ចំណងជើង"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"បានធ្វើ​បច្ចុប្បន្នភាព​ការរុករកក្នុង​ប្រព័ន្ធ។ ដើម្បីធ្វើការផ្លាស់ប្ដូរ សូមចូលទៅ​កាន់ការកំណត់។"</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"ចូល​ទៅកាន់​ការកំណត់ ដើម្បី​ធ្វើបច្ចុប្បន្នភាព​ការរុករក​ក្នុង​ប្រព័ន្ធ"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"ផ្អាក​ដំណើរការ"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"វិនដូ​ត្រួតគ្នា​លើ​ការពង្រីក"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"វិនដូ​ការពង្រីក"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"វិនដូគ្រប់គ្រង​​ការពង្រីក"</string>
</resources>
diff --git a/packages/SystemUI/res/values-km/strings_tv.xml b/packages/SystemUI/res/values-km/strings_tv.xml
index 159847e4607d..f905f49f695b 100644
--- a/packages/SystemUI/res/values-km/strings_tv.xml
+++ b/packages/SystemUI/res/values-km/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(កម្មវិធី​គ្មានចំណងជើង)"</string>
<string name="pip_close" msgid="5775212044472849930">"បិទ PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"ពេញអេក្រង់"</string>
+ <string name="mic_active" msgid="5766614241012047024">"មីក្រូហ្វូន​កំពុង​ដំណើរការ"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s បានចូលប្រើ​មីក្រូហ្វូន​របស់អ្នក"</string>
</resources>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index c736240a3104..154f13b3a9c3 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"ಪರದೆ ತುಂಬಿಸಲು ಝೂಮ್ ಮಾಡು"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"ಪರದೆ ತುಂಬಿಸಲು ವಿಸ್ತಾರಗೊಳಿಸು"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಉಳಿಸಲಾಗುತ್ತಿದೆ…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಉಳಿಸಲಾಗುತ್ತಿದೆ…"</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್‌ ಅನ್ನು ಉಳಿಸಲಾಗಿದೆ"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"ಫೋನ್ ತೆರೆಯಿರಿ"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"ಧ್ವನಿ ಸಹಾಯಕವನ್ನು ತೆರೆ"</string>
<string name="camera_label" msgid="8253821920931143699">"ಕ್ಯಾಮರಾ ತೆರೆಯಿರಿ"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"ರದ್ದುಮಾಡಿ"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"ದೃಢೀಕರಿಸಿ"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"ದೃಢೀಕರಣವನ್ನು ರದ್ದುಗೊಳಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
@@ -383,11 +381,13 @@
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"ಕೆಲಸದ ಪ್ರೊಫೈಲ್"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"ನೈಟ್ ಲೈಟ್"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"ಸೂರ್ಯಾಸ್ತದಲ್ಲಿ"</string>
- <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"ಸೂರ್ಯೋದಯದ ತನಕ"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"ಸೂರ್ಯೋದಯದವರೆಗೆ"</string>
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"<xliff:g id="TIME">%s</xliff:g> ಸಮಯದಲ್ಲಿ"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g> ವರೆಗೂ"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"ಡಾರ್ಕ್ ಥೀಮ್"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"ಡಾರ್ಕ್ ಥೀಮ್\nಬ್ಯಾಟರಿ ಸೇವರ್"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"ಬ್ಯಾಟರಿ ಸೇವರ್"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"ಸೂರ್ಯಾಸ್ತ ಸಮಯದಲ್ಲಿ"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"ಸೂರ್ಯೋದಯದವರೆಗೆ"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC ನಿಷ್ಕ್ರಿಯಗೊಂಡಿದೆ"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ಸಕ್ರಿಯಗೊಂಡಿದೆ"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"ತೆರೆಯಲು ಮತ್ತೆ ಟ್ಯಾಪ್‌ ಮಾಡಿ"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"ತೆರೆಯಲು ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ"</string>
<string name="keyguard_retry" msgid="886802522584053523">"ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಲು ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"ಈ ಸಾಧನವನ್ನು ನಿಮ್ಮ ಸಂಸ್ಥೆ ನಿರ್ವಹಿಸುತ್ತಿದೆ"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"ಈ ಸಾಧನವನ್ನು <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> ರಿಂದ ನಿರ್ವಹಿಸಲಾಗಿದೆ"</string>
<string name="phone_hint" msgid="6682125338461375925">"ಫೋನ್‌ಗಾಗಿ ಐಕಾನ್‌ನಿಂದ ಸ್ವೈಪ್ ಮಾಡಿ"</string>
@@ -467,11 +463,13 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"ಬ್ಯಾಟರಿ ಸೇವರ್ ಆನ್ ಆಗಿದೆ"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"ಕಾರ್ಯಕ್ಷಮತೆ ಮತ್ತು ಹಿನ್ನೆಲೆ ಡೇಟಾವನ್ನು ಕಡಿಮೆ ಮಾಡುತ್ತದೆ"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"ಬ್ಯಾಟರಿ ಸೇವರ್‌ ಆಫ್ ಮಾಡಿ"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"ರೆಕಾರ್ಡ್ ಮಾಡುವಾಗ ಅಥವಾ ಕ್ಯಾಸ್ಟಿಂಗ್ ಮಾಡುವಾಗ, ಸೂಕ್ಷ್ಮ ಮಾಹಿತಿಯಂತಹ ಆಡಿಯೋ, ಪಾಸ್‌ವರ್ಡ್‌ಗಳು, ಪಾವತಿ ಮಾಹಿತಿ, ಫೋಟೋಗಳು ಮತ್ತು ಸಂದೇಶಗಳನ್ನು ಒಳಗೊಂಡಂತೆ ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ ಮೇಲೆ ಡಿಸ್‌ಪ್ಲೇ ಮಾಡಿದ ಅಥವಾ ನಿಮ್ಮ ಸಾಧನದಿಂದ ಪ್ಲೇ ಮಾಡಿದ ಯಾವುದೇ ಸೂಕ್ಷ್ಮ ಮಾಹಿತಿಯನ್ನು <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ಕ್ಯಾಪ್ಚರ್ ಮಾಡಬಹುದು."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"ರೆಕಾರ್ಡ್ ಮಾಡುವಾಗ ಅಥವಾ ಕ್ಯಾಸ್ಟಿಂಗ್ ಮಾಡುವಾಗ, ಸೂಕ್ಷ್ಮ ಮಾಹಿತಿಯಂತಹ ಆಡಿಯೋ, ಪಾಸ್‌ವರ್ಡ್‌ಗಳು, ಪಾವತಿ ಮಾಹಿತಿ, ಫೋಟೋಗಳು ಮತ್ತು ಸಂದೇಶಗಳನ್ನು ಒಳಗೊಂಡಂತೆ ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ ಮೇಲೆ ಡಿಸ್‌ಪ್ಲೇ ಮಾಡಿದ ಅಥವಾ ನಿಮ್ಮ ಸಾಧನದಿಂದ ಪ್ಲೇ ಮಾಡಿದ ಯಾವುದೇ ಸೂಕ್ಷ್ಮ ಮಾಹಿತಿಯನ್ನು ಸೇವೆ ಒದಗಿಸುವ ಈ ಫಂಕ್ಷನ್ ಕ್ಯಾಪ್ಚರ್ ಮಾಡಬಹುದು."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"ಕ್ಯಾಸ್ಟಿಂಗ್/ರೆಕಾರ್ಡಿಂಗ್ ಸಮಯದಲ್ಲಿ ಸೂಕ್ಷ್ಮ ಮಾಹಿತಿಯನ್ನು ಬಹಿರಂಗಪಡಿಸುವುದು"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>, ಸ್ಕ್ರೀನ್ ಮೇಲೆ ಗೋಚರಿಸುವ ಅಥವಾ ರೆಕಾರ್ಡಿಂಗ್ ಅಥವಾ ಬಿತ್ತರಿಸುವಾಗ ಸಾಧನದಲ್ಲಿ ಪ್ಲೇ ಆಗುವ ಎಲ್ಲಾ ಮಾಹಿತಿಗಳಿಗೆ ಪ್ರವೇಶವನ್ನು ಹೊಂದಿರುತ್ತವೆ. ಪಾಸ್‌ವರ್ಡ್‌ಗಳು, ಪಾವತಿ ವಿವರಗಳು, ಫೋಟೋಗಳು, ಸಂದೇಶಗಳು ಮತ್ತು ಆಡಿಯೊ ಪ್ಲೇಬ್ಯಾಕ್‌ನಂತಹ ಮಾಹಿತಿಯನ್ನು ಇದು ಒಳಗೊಂಡಿದೆ."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"ಈ ವೈಶಿಷ್ಟ್ಯವು ಒದಗಿಸುವ ಸೇವೆಗಳು, ಸ್ಕ್ರೀನ್ ಮೇಲೆ ಗೋಚರಿಸುವ ಅಥವಾ ರೆಕಾರ್ಡಿಂಗ್ ಅಥವಾ ಬಿತ್ತರಿಸುವಾಗ ಸಾಧನದಲ್ಲಿ ಪ್ಲೇ ಆಗುವ ಎಲ್ಲಾ ಮಾಹಿತಿಗಳಿಗೆ ಪ್ರವೇಶವನ್ನು ಹೊಂದಿರುತ್ತವೆ. ಪಾಸ್‌ವರ್ಡ್‌ಗಳು, ಪಾವತಿ ವಿವರಗಳು, ಫೋಟೋಗಳು, ಸಂದೇಶಗಳು ಮತ್ತು ಆಡಿಯೊ ಪ್ಲೇಬ್ಯಾಕ್‌ನಂತಹ ಮಾಹಿತಿಯನ್ನು ಇದು ಒಳಗೊಂಡಿದೆ."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ಬಳಸಿಕೊಂಡು ರೆಕಾರ್ಡಿಂಗ್ ಅಥವಾ ಬಿತ್ತರಿಸುವುದನ್ನು ಪ್ರಾರಂಭಿಸುವುದೇ?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"ಮತ್ತೊಮ್ಮೆ ತೋರಿಸದಿರು"</string>
- <string name="clear_all_notifications_text" msgid="348312370303046130">"ಎಲ್ಲವನ್ನೂ ತೆರವುಗೊಳಿಸು"</string>
+ <string name="clear_all_notifications_text" msgid="348312370303046130">"ಎಲ್ಲವನ್ನೂ ತೆರವುಗೊಳಿಸಿ"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"ನಿರ್ವಹಿಸಿ"</string>
<string name="notification_section_header_gentle" msgid="3044910806569985386">"ನಿಶ್ಶಬ್ಧ ಅಧಿಸೂಚನೆಗಳು"</string>
<string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"ಎಲ್ಲಾ ನಿಶ್ಶಬ್ಧ ಅಧಿಸೂಚನೆಗಳನ್ನು ತೆರವುಗೊಳಿಸಿ"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"ಕೀಬೋರ್ಡ್ ಬದಲಾಯಿಸುವಿಕೆ"</string>
<string name="save" msgid="3392754183673848006">"ಉಳಿಸಿ"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"ಮರುಹೊಂದಿಸಿ"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"ಬಟನ್ ಅಳತೆ ಹೊಂದಿಸು"</string>
<string name="clipboard" msgid="8517342737534284617">"ಕ್ಲಿಪ್‌ಬೋರ್ಡ್"</string>
<string name="accessibility_key" msgid="3471162841552818281">"ಕಸ್ಟಮ್ ನ್ಯಾವಿಗೇಷನ್ ಬಟನ್"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"ಬಲ"</string>
<string name="tuner_menu" msgid="363690665924769420">"ಮೆನು"</string>
<string name="tuner_app" msgid="6949280415826686972">"<xliff:g id="APP">%1$s</xliff:g> ಅಪ್ಲಿಕೇಶನ್"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"ಅಲರ್ಟ್‌ಗಳು"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"ಬ್ಯಾಟರಿ"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್‌ಗಳು"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"ಸಾಮಾನ್ಯ ಸಂದೇಶಗಳು"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> ರನ್ ಆಗುತ್ತಿದೆ"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"ಇನ್‌ಸ್ಟಾಲ್‌ ಮಾಡದೆ ಆ್ಯಪ್‌ ತೆರೆಯಲಾಗಿದೆ."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"ಇನ್‌ಸ್ಟಾಲ್‌ ಮಾಡದೆ ಆ್ಯಪ್‌ ತೆರೆಯಲಾಗಿದೆ. ಇನ್ನಷ್ಟು ತಿಳಿಯಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"ಆ್ಯಪ್‌ ಮಾಹಿತಿ"</string>
<string name="go_to_web" msgid="636673528981366511">"ಬ್ರೌಸರ್‌ಗೆ ಹೋಗಿ"</string>
<string name="mobile_data" msgid="4564407557775397216">"ಮೊಬೈಲ್ ಡೇಟಾ"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"ಅರ್ಥವಾಯಿತು"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"SysUI ಹೀಪ್ ಡಂಪ್ ಮಾಡಿ"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"ನಿಮ್ಮ <xliff:g id="TYPES_LIST">%2$s</xliff:g> ಅನ್ನು <xliff:g id="APP">%1$s</xliff:g> ಬಳಸುತ್ತಿದೆ."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"ನಿಮ್ಮ <xliff:g id="TYPES_LIST">%s</xliff:g> ಅನ್ನು ಆ್ಯಪ್‌ಗಳು ಬಳಸುತ್ತಿವೆ."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" ಮತ್ತು "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"ಕ್ಯಾಮರಾ"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"ಸ್ಥಳ"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"ಮೈಕ್ರೋಫೋನ್‌"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"ಸೆನ್ಸರ್‌ಗಳು ಆಫ್"</string>
<string name="device_services" msgid="1549944177856658705">"ಸಾಧನ ಸೇವೆಗಳು"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"ಯಾವುದೇ ಶೀರ್ಷಿಕೆಯಿಲ್ಲ"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"ಸಿಸ್ಟಂ ನ್ಯಾವಿಗೇಷನ ಅಪ್‌ಡೇಟ್ ಮಾಡಲಾಗಿದೆ ಬದಲಾವಣೆಗಳನ್ನು ಮಾಡಲು, ಸೆಟ್ಟಿಂಗ್‌ಗಳಿಗೆ ಹೋಗಿ."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"ಸಿಸ್ಟಂ ನ್ಯಾವಿಗೇಷನ್ ಅಪ್‌ಡೇಟ್ ಮಾಡಲು ಸೆಟ್ಟಿಂಗ್‌ಗಳಿಗೆ ಹೋಗಿ"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"ಸ್ಟ್ಯಾಂಡ್‌ಬೈ"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"ವರ್ಧನೆಯ ಓವರ್‌ಲೇ ವಿಂಡೋ"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"ವರ್ಧನೆಯ ವಿಂಡೋ"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"ವರ್ಧನೆಯ ವಿಂಡೋ ನಿಯಂತ್ರಣಗಳು"</string>
</resources>
diff --git a/packages/SystemUI/res/values-kn/strings_tv.xml b/packages/SystemUI/res/values-kn/strings_tv.xml
index c81bb5690700..d01e14780046 100644
--- a/packages/SystemUI/res/values-kn/strings_tv.xml
+++ b/packages/SystemUI/res/values-kn/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(ಶೀರ್ಷಿಕೆ ರಹಿತ ಕಾರ್ಯಕ್ರಮ)"</string>
<string name="pip_close" msgid="5775212044472849930">"PIP ಮುಚ್ಚಿ"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"ಪೂರ್ಣ ಪರದೆ"</string>
+ <string name="mic_active" msgid="5766614241012047024">"ಮೈಕ್ರೋಫೋನ್‌ ಸಕ್ರಿಯವಾಗಿದೆ"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s ನಿಮ್ಮ ಮೈಕ್ರೋಫೋನ್ ಅನ್ನು ಪ್ರವೇಶಿಸಿದೆ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index a60f73615508..b72a30ea3ca2 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"자세히 알아보기"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"전체화면 모드로 확대"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"전체화면 모드로 확대"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"스크린샷"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"캡쳐화면 저장 중..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"캡쳐화면 저장 중..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"스크린샷 저장됨"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"휴대전화 열기"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"음성 지원 열기"</string>
<string name="camera_label" msgid="8253821920931143699">"카메라 열기"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"취소"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"확인"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"다시 시도하세요."</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"탭하여 인증 취소"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"<xliff:g id="TIME">%s</xliff:g>에"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g>까지"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"어두운 테마"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"어두운 테마\n절전 모드"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"절전 모드"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"일몰에"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"일출까지"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC 사용 중지됨"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC 사용 설정됨"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"다시 탭하여 열기"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"위로 스와이프하여 열기"</string>
<string name="keyguard_retry" msgid="886802522584053523">"위로 스와이프하여 다시 시도해 주세요"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"조직에서 관리하는 기기입니다."</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>에서 관리하는 기기입니다."</string>
<string name="phone_hint" msgid="6682125338461375925">"전화 기능을 사용하려면 아이콘에서 스와이프하세요."</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"절전 모드 사용 중"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"성능 및 백그라운드 데이터를 줄입니다."</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"절전 모드 사용 중지"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"녹화 또는 전송 중에 <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>에서 오디오, 비밀번호, 결제 정보, 사진, 메시지 등 화면에 표시되거나 기기에서 재생되는 민감한 정보를 캡처할 수 있습니다."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"녹화 또는 전송 중에 이 기능을 제공하는 서비스에서 오디오, 비밀번호, 결제 정보, 사진, 메시지 등 화면에 표시되거나 기기에서 재생되는 민감한 정보를 캡처할 수 있습니다."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"전송/녹화 중에 민감한 정보 노출"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>이(가) 녹화 또는 전송 중에 화면에 표시되거나 기기에서 재생되는 모든 정보에 액세스할 수 있습니다. 여기에는 비밀번호, 결제 세부정보, 사진, 메시지, 재생하는 오디오 같은 정보가 포함됩니다."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"이 기능을 제공하는 서비스는 녹화 또는 전송 중에 화면에 표시되거나 기기에서 재생되는 모든 정보에 액세스할 수 있습니다. 여기에는 비밀번호, 결제 세부정보, 사진, 메시지, 재생하는 오디오 같은 정보가 포함됩니다."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>(으)로 녹화 또는 전송을 시작하시겠습니까?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"다시 표시 안함"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"모두 지우기"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"관리"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"키보드 전환 도구"</string>
<string name="save" msgid="3392754183673848006">"저장"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"재설정"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"버튼 너비 조정"</string>
<string name="clipboard" msgid="8517342737534284617">"클립보드"</string>
<string name="accessibility_key" msgid="3471162841552818281">"맞춤 탐색 버튼"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"오른쪽 화살표"</string>
<string name="tuner_menu" msgid="363690665924769420">"메뉴"</string>
<string name="tuner_app" msgid="6949280415826686972">"<xliff:g id="APP">%1$s</xliff:g> 앱"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"알림"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"배터리"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"스크린샷"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"일반 메시지"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> 실행 중"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"설치 없이 앱이 실행되었습니다."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"설치 없이 앱이 실행되었습니다. 탭하여 자세히 알아보세요."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"앱 정보"</string>
<string name="go_to_web" msgid="636673528981366511">"브라우저로 이동"</string>
<string name="mobile_data" msgid="4564407557775397216">"모바일 데이터"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g>, <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"설정"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"확인"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g>이(가) <xliff:g id="TYPES_LIST">%2$s</xliff:g>을(를) 사용 중입니다."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"애플리케이션이 <xliff:g id="TYPES_LIST">%s</xliff:g>을(를) 사용 중입니다."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" 및 "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"카메라"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"위치"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"마이크"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"센서 사용 안함"</string>
<string name="device_services" msgid="1549944177856658705">"기기 서비스"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"제목 없음"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"시스템 탐색이 업데이트되었습니다. 변경하려면 설정으로 이동하세요."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"설정으로 이동하여 시스템 탐색을 업데이트하세요."</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"대기"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"확대 오버레이 창"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"확대 창"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"확대 창 컨트롤"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ko/strings_tv.xml b/packages/SystemUI/res/values-ko/strings_tv.xml
index 0b590ddd7e31..0615fe85d72e 100644
--- a/packages/SystemUI/res/values-ko/strings_tv.xml
+++ b/packages/SystemUI/res/values-ko/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(제목 없는 프로그램)"</string>
<string name="pip_close" msgid="5775212044472849930">"PIP 닫기"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"전체화면"</string>
+ <string name="mic_active" msgid="5766614241012047024">"마이크 사용 중"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s에서 내 마이크에 액세스했습니다."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 80aa6a1fcfd4..d2f674f50cd0 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Кененирээк"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Экрнд тлтр ү. чен өлч өзг"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Экранды толтуруу ү-н чоюу"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Скриншот"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Скриншот сакталууда…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Скриншот сакталууда..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Скриншот сакталды"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"телефонду ачуу"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"үн жардамчысысын ачуу"</string>
<string name="camera_label" msgid="8253821920931143699">"камераны ачуу"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Жокко чыгаруу"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Ырастоо"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Кайталоо"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Аныктыгын текшерүүнү жокко чыгаруу үчүн таптаңыз"</string>
@@ -334,7 +332,7 @@
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Жайгашытрууну өчүрүү"</string>
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Медиа түзмөгү"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
- <string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Өзгөчө кырдаалда гана чалууга болот"</string>
+ <string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Кырсыктаганда гана чалуу"</string>
<string name="quick_settings_settings_label" msgid="2214639529565474534">"Жөндөөлөр"</string>
<string name="quick_settings_time_label" msgid="3352680970557509303">"Убакыт"</string>
<string name="quick_settings_user_label" msgid="1253515509432672496">"Мен"</string>
@@ -386,8 +384,10 @@
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Күн чыкканга чейин"</string>
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Саат <xliff:g id="TIME">%s</xliff:g> күйөт"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g> чейин"</string>
- <string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Түнкү режим"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Түнкү режим\nБатареяны үнөмдөгүч"</string>
+ <string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Караңгы тема"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Батареяны үнөмдөгүч"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Күн батканда күйөт"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Күн чыкканга чейин"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC өчүрүлгөн"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC иштетилген"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Ачуу үчүн кайра таптап коюңуз"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Ачуу үчүн өйдө сүрүңүз"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Кайталоо үчүн экранды өйдө сүрүңүз"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Бул түзмөк уюмуңуз тарабынан башкарылат"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Бул түзмөк <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> тарабынан башкарылат"</string>
<string name="phone_hint" msgid="6682125338461375925">"Сүрөтчөнү серпип телефонго өтүңүз"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Батареяны үнөмдөгүч режими күйүк"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Иштин майнаптуулугун начарлатып, фондук дайындарды чектейт"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Батареяны үнөмдөгүч режимин өчүрүү"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Жаздырып же тышкы экранга чыгаруу учурунда, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> колдонмосу ойноткон аудиоңуз, сырсөздөрүңүз, төлөө маалыматыңыз, сүрөттөрүңүз жана билдирүүлөрүңүз сыяктуу экранда көрсөтүлгөн купуя маалыматты жаздырып калышы мүмкүн."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Жаздырып же тышкы экранга чыгаруу учурунда, бул функцияны аткарып жаткан колдонмо ойноткон аудиоңуз, сырсөздөрүңүз, төлөө маалыматыңыз, сүрөттөрүңүз жана билдирүүлөрүңүз сыяктуу экранда көрсөтүлгөн купуя маалыматты жаздырып калышы мүмкүн."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Тышкы экранга чыгарууда/жаздырууда купуя маалыматты ачыктоо"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"Бул функцияны аткарган <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> кызматы экраныңызда көрүнүп турган бардык маалыматты же жаздыруу жана тышкы экранга чыгаруу учурунда түзмөгүңүздө ойнотулган маалыматты колдоно алат. Буга сырсөздөр, төлөмдүн чоо-жайы, сүрөттөр, билдирүүлөр жана ойнотулган аудио кирет."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Бул функцияны аткарган кызмат экраныңызда көрүнүп турган бардык маалыматты же жаздыруу жана тышкы экранга чыгаруу учурунда түзмөгүңүздө ойнотулган маалыматты колдоно алат. Буга сырсөздөр, төлөмдүн чоо-жайы, сүрөттөр, билдирүүлөр жана ойнотулган аудио кирет."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> менен жаздырылып же тышкы экранга чыгарылып башталсынбы?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Экинчи көрсөтүлбөсүн"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Баарын тазалап салуу"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Башкаруу"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Баскычтоп которуштургуч"</string>
<string name="save" msgid="3392754183673848006">"Сактоо"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Баштапкы абалга келтирүү"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Баскычтын жазылыгын тууралоо"</string>
<string name="clipboard" msgid="8517342737534284617">"Алмашуу буфери"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Ыңгайлаштырылган чабыттоо баскычы"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Оңго"</string>
<string name="tuner_menu" msgid="363690665924769420">"Меню"</string>
<string name="tuner_app" msgid="6949280415826686972">"<xliff:g id="APP">%1$s</xliff:g> колдонмосу"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Эскертүүлөр"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Батарея"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Скриншоттор"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Жалпы билдирүүлөр"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> иштеп жатат"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Колдонмо орнотулбастан ачылды."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Колдонмо орнотулбастан ачылды. Толугураак маалымат алуу үчүн таптап коюңуз."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Колдонмо тууралуу"</string>
<string name="go_to_web" msgid="636673528981366511">"Серепчиге өтүү"</string>
<string name="mobile_data" msgid="4564407557775397216">"Мобилдик Интернет"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Жөндөөлөр"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Түшүндүм"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> төмөнкүлөрдү колдонуп жатат: <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Колдонмолор төмөнкүлөрдү пайдаланып жатышат: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" жана "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"камера"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"жайгашкан жер"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"микрофон"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Сенсорлорду өчүрүү"</string>
<string name="device_services" msgid="1549944177856658705">"Түзмөк кызматтары"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Аталышы жок"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Тутум чабыттоосу жаңыртылды. Өзгөртүү үчүн, Жөндөөлөргө өтүңүз."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Тутум чабыттоосун жаңыртуу үчүн Жөндөөлөргө өтүңүз"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Көшүү режими"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Чоңойтуу терезесин үстүнө коюу"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Чоңойтуу терезеси"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Чоңойтуу терезесин башкаруу каражаттары"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ky/strings_tv.xml b/packages/SystemUI/res/values-ky/strings_tv.xml
index 0e400a58340f..5b40ca93bac2 100644
--- a/packages/SystemUI/res/values-ky/strings_tv.xml
+++ b/packages/SystemUI/res/values-ky/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Аталышы жок программа)"</string>
<string name="pip_close" msgid="5775212044472849930">"PIP\'ти жабуу"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Толук экран"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Микрофон күйүк"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s микрофонуңузду колдонууда"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 8b3be6498994..ca689724a4cf 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"ສຶກສາເພີ່ມເຕີມ"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"ຊູມໃຫ້ເຕັມໜ້າຈໍ"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"ປັບໃຫ້ເຕັມໜ້າຈໍ"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"ພາບໜ້າຈໍ"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"ກຳລັງບັນທຶກຮູບໜ້າຈໍ"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"ກຳລັງບັນທຶກພາບໜ້າຈໍ..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"ບັນທຶກຮູບໜ້າຈໍໄວ້ແລ້ວ"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"​ເປີດ​​ແປ້ນ​ໂທ​ລະ​ສັບ"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"ຊ່ວ​ເຫຼືອ​ເປີດ​ສຽງ"</string>
<string name="camera_label" msgid="8253821920931143699">"ເປີດ​ກ້ອງ"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"ຍົກເລີກ"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"ຢືນຢັນ"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"ລອງໃໝ່"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"ແຕະເພື່ອຍົກເລີກການກວດສອບຄວາມຖືກຕ້ອງ"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"ເປີດຕອນ <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"ຈົນກວ່າຈະຮອດ <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"ຮູບແບບສີສັນມືດ"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"ຮູບແບບສີສັນມືດ\nຕົວປະຢັດແບັດເຕີຣີ"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"ຕົວປະຢັດແບັດເຕີຣີ"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"ເປີດຕອນຕາເວັນຕົກ"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"ຈົນກວ່າຕາເວັນຂຶ້ນ"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC is disabled"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC is enabled"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"ແຕະ​ອີກ​ຄັ້ງ​ເພື່ອ​ເປີດ"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"ປັດຂຶ້ນເພື່ອເປີດ"</string>
<string name="keyguard_retry" msgid="886802522584053523">"ປັດຂຶ້ນເພື່ອລອງໃໝ່"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"ອຸປະກອນນີ້ແມ່ນຈັດການໂດຍອົງກອນຂອງທ່ານ"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"ອຸປະກອນນີ້ຖືກຈັດການໂດຍ <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"ປັດ​ຈາກ​ໄອ​ຄອນ​ສຳ​ລັບ​ໂທ​ລະ​ສັບ"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"ຕົວປະຢັດແບັດເຕີຣີເປີດຢູ່"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"ຫຼຸດ​ປະ​ສິ​ທິ​ພາບ​ແລະ​ການ​ນຳ​ໃຊ້​ຂໍ້​ມູນ​ພື້ນຫຼັງ"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"ປິດຕົວປະຢັດແບັດເຕີຣີ"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"ໃນລະຫວ່າງການບັນທຶກ ຫຼື ການຖ່າຍທອດສັນຍານ, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ຈະສາມາດບັນທຶກຂໍ້ມູນທີ່ລະອຽດອ່ອນໃດໆທີ່ສະແດງຢູ່ໜ້າຈໍຂອງທ່ານ ຫຼື ສາຍຈາກອຸປະກອນທ່ານ, ຮວມທັງຂໍ້ມູນທີ່ລະອຽດອ່ອນ ເຊັ່ນ: ສຽງ, ລະຫັດຜ່ານ, ຂໍ້ມູນການຈ່າຍເງິນ, ຮູບພາບ ແລະ ຂໍ້ຄວາມ."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"ໃນລະຫວ່າງການບັນທຶກ ຫຼື ການຖ່າຍທອດສັນຍານ, ບໍລິການທີ່ສະໜອງການເຮັດວຽກນີ້ຈະສາມາດບັນທຶກຂໍ້ມູນທີ່ລະອຽດອ່ອນໃດໆທີ່ສະແດງຢູ່ໜ້າຈໍຂອງທ່ານ ຫຼື ສາຍຈາກອຸປະກອນທ່ານ, ຮວມທັງຂໍ້ມູນທີ່ລະອຽດອ່ອນ ເຊັ່ນ: ສຽງ, ລະຫັດຜ່ານ, ຂໍ້ມູນການຈ່າຍເງິນ, ຮູບພາບ ແລະ ຂໍ້ຄວາມ."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"ເປີດເຜີຍຂໍ້ມູນລະອຽດອ່ອນໃນລະຫວ່າງການສົ່ງສັນຍານ/ການບັນທຶກ"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ຈະມີສິດເຂົ້າເຖິງຂໍ້ມູນທັງໝົດທີ່ປາກົດຢູ່ໜ້າຈໍຂອງທ່ານ ຫຼື ຫຼິ້ນຈາກອຸປະກອນຂອງທ່ານໃນເວລາບັນທຶກ ຫຼື ສົ່ງສັນຍານໜ້າຈໍ. ນີ້ຮວມເຖິງຂໍ້ມູນຕ່າງໆ ເຊັ່ນ: ລະຫັດຜ່ານ, ລາຍລະອຽດການຈ່າຍເງິນ, ຮູບ, ຂໍ້ຄວາມ ແລະ ສຽງທີ່ທ່ານຫຼິ້ນ."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"ບໍລິການທີ່ສະໜອງຄວາມສາມາດນີ້ຈະມີສິດເຂົ້າເຖິງຂໍ້ມູນທັງໝົດທີ່ປາກົດຢູ່ໜ້າຈໍຂອງທ່ານ ຫຼື ຫຼິ້ນຈາກອຸປະກອນຂອງທ່ານໃນເວລາບັນທຶກ ຫຼື ສົ່ງສັນຍານໜ້າຈໍ. ນີ້ຮວມເຖິງຂໍ້ມູນຕ່າງໆ ເຊັ່ນ: ລະຫັດຜ່ານ, ລາຍລະອຽດການຈ່າຍເງິນ, ຮູບ, ຂໍ້ຄວາມ ແລະ ສຽງທີ່ທ່ານຫຼິ້ນ."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"ເລີ່ມການບັນທຶກ ຫຼື ການສົ່ງສັນຍານໜ້າຈໍກັບ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ບໍ?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"ບໍ່​ຕ້ອງ​ສະ​ແດງ​ອີກ"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"ລຶບລ້າງທັງໝົດ"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"ຈັດການ"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"ຕົວສະຫຼັບແປ້ນພິມ"</string>
<string name="save" msgid="3392754183673848006">"ບັນທຶກ"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"ຣີເຊັດ"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"ປັບຄວາມກວ້າງຂອງປຸ່ມ"</string>
<string name="clipboard" msgid="8517342737534284617">"​ຄລິບບອດ"</string>
<string name="accessibility_key" msgid="3471162841552818281">"ປຸ່ມນຳທາງແບບກຳນົດເອງ"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"ຂວາ"</string>
<string name="tuner_menu" msgid="363690665924769420">"ເມນູ"</string>
<string name="tuner_app" msgid="6949280415826686972">"ແອັບ <xliff:g id="APP">%1$s</xliff:g>"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"ການແຈ້ງເຕືອນ"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"ແບັດເຕີຣີ"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"ຮູບຖ່າຍໜ້າຈໍ"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"ຂໍ້ຄວາມທົ່ວໄປ"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> ກຳລັງເຮັດວຽກຢູ່"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"ເປີດແອັບໂດຍບໍ່ມີການຕິດຕັ້ງແລ້ວ."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"ເປີດແອັບໂດຍບໍ່ມີການຕິດຕັ້ງແລ້ວ. ແຕະເພື່ອສຶກສາເພີ່ມເຕີມ."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"ຂໍ້ມູນແອັບ"</string>
<string name="go_to_web" msgid="636673528981366511">"ໄປທີ່ໂປຣແກຣມທ່ອງເວັບ"</string>
<string name="mobile_data" msgid="4564407557775397216">"ອິນເຕີເນັດມືຖື"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"ການຕັ້ງຄ່າ"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"ເຂົ້າໃຈແລ້ວ"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> ກຳລັງໃຊ້ <xliff:g id="TYPES_LIST">%2$s</xliff:g> ຂອງທ່ານ."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"ແອັບພລິເຄຊັນກຳລັງໃຊ້ <xliff:g id="TYPES_LIST">%s</xliff:g> ຂອງທ່ານ."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" ແລະ "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"ກ້ອງຖ່າຍຮູບ"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"ສະຖານທີ່"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"ໄມໂຄຣໂຟນ"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"ປິດການຮັບຮູ້ຢູ່"</string>
<string name="device_services" msgid="1549944177856658705">"ບໍລິການອຸປະກອນ"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"ບໍ່ມີຊື່"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"ອັບເດດການນຳທາງລະບົບແລ້ວ. ເພື່ອປ່ຽນແປງ, ກະລຸນາໄປທີ່ການຕັ້ງຄ່າ."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"ໄປທີ່ການຕັ້ງຄ່າເພື່ອອັບເດດການນຳທາງລະບົບ"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"ສະແຕນບາຍ"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"ໜ້າຈໍວາງທັບການຂະຫຍາຍ"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"ໜ້າຈໍການຂະຫຍາຍ"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"ການຄວບຄຸມໜ້າຈໍການຂະຫຍາຍ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lo/strings_tv.xml b/packages/SystemUI/res/values-lo/strings_tv.xml
index d4096c9b3ef6..7e7a4dded891 100644
--- a/packages/SystemUI/res/values-lo/strings_tv.xml
+++ b/packages/SystemUI/res/values-lo/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(ໂປຣແກຣມບໍ່ມີຊື່)"</string>
<string name="pip_close" msgid="5775212044472849930">"ປິດ PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"ເຕັມໜ້າຈໍ"</string>
+ <string name="mic_active" msgid="5766614241012047024">"ໄມໂຄຣໂຟນເປີດໃຊ້ຢູ່"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s ເຂົ້າເຖິງໄມໂຄຣໂຟນຂອງທ່ານແລ້ວ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index c7282cd94836..60b4fe4c2978 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Sužinokite daugiau"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Keisti mast., kad atit. ekr."</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Ištempti, kad atit. ekr."</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Ekrano kopija"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Išsaugoma ekrano kopija..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Išsaugoma ekrano kopija..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Ekrano kopija išsaugota"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"atidaryti telefoną"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"atidaryti „Voice Assist“"</string>
<string name="camera_label" msgid="8253821920931143699">"atidaryti fotoaparatą"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Atšaukti"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Patvirtinkite"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Bandyti dar kartą"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Palieskite, jei norite atšaukti autentifikavimą"</string>
@@ -391,7 +389,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"<xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Iki <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Tamsioji tema"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Tamsioji tema\nAkumul. tausojimo priemonė"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Akum. taus. priemonė"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Per saulėlydį"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Iki saulėtekio"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"ALR"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"ALR išjungtas"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"ALR įjungtas"</string>
@@ -416,10 +416,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Palieskite dar kartą, kad atidarytumėte"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Perbraukite aukštyn, kad atidarytumėte"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Jei norite bandyti dar kartą, perbraukite aukštyn"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Šį įrenginį tvarko jūsų organizacija"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Šį įrenginį tvarko <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Perbraukite iš telefono piktogramos"</string>
@@ -473,9 +469,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Akumuliatoriaus tausojimo priemonė įjungta"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Sumažinamas našumas ir foninių duomenų naudojimas"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Išjungti Akumuliatoriaus tausojimo priemonę"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Įrašant ar perduodant turinį, programa „<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>“ gali fiksuoti bet kokią neskelbtiną informaciją, rodomą ekrane ar leidžiamą iš įrenginio (įskaitant tokią neskelbtiną informaciją kaip garso įrašai, slaptažodžiai, mokėjimo informacija, nuotraukos ir pranešimai)."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Įrašant ar perduodant turinį, šią funkciją teikianti paslauga gali fiksuoti bet kokią neskelbtiną informaciją, rodomą ekrane ar leidžiamą iš įrenginio (įskaitant tokią neskelbtiną informaciją kaip garso įrašai, slaptažodžiai, mokėjimo informacija, nuotraukos ir pranešimai)."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Neskelbtinos informacijos atskleidimas perduodant / įrašant"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"„<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>“ galės pasiekti visą informaciją, matomą ekrane ir leidžiamą iš įrenginio įrašant ar perduodant turinį. Tai apima įvairią informaciją, pvz., slaptažodžius, išsamią mokėjimo informaciją, nuotraukas, pranešimus ir leidžiamus garso įrašus."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Šią funkcija teikianti paslauga galės pasiekti visą informaciją, matomą ekrane ir leidžiamą iš įrenginio įrašant ar perduodant turinį. Tai apima įvairią informaciją, pvz., slaptažodžius, išsamią mokėjimo informaciją, nuotraukas, pranešimus ir leidžiamus garso įrašus."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Pradėti įrašyti ar perduoti turinį naudojant „<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>“?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Daugiau neberodyti"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Viską išvalyti"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Tvarkyti"</string>
@@ -796,8 +794,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Klaviatūros perjungiklis"</string>
<string name="save" msgid="3392754183673848006">"Išsaugoti"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Nustatyti iš naujo"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Mygtuko pločio koregavimas"</string>
<string name="clipboard" msgid="8517342737534284617">"Iškarpinė"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Tinkintas naršymo mygtukas"</string>
@@ -893,8 +890,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Dešinėje"</string>
<string name="tuner_menu" msgid="363690665924769420">"Meniu"</string>
<string name="tuner_app" msgid="6949280415826686972">"Programa „<xliff:g id="APP">%1$s</xliff:g>“"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Įspėjimai"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Akumuliatorius"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Ekrano kopijos"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Bendrieji pranešimai"</string>
@@ -904,8 +900,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"Programa „<xliff:g id="APP">%1$s</xliff:g>“ paleista"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Programa atidaryta jos neįdiegus."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Programa atidaryta jos neįdiegus. Palieskite, kad sužinotumėte daugiau."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Progr. informacija"</string>
<string name="go_to_web" msgid="636673528981366511">"Eiti į naršyklę"</string>
<string name="mobile_data" msgid="4564407557775397216">"Mobilieji duomenys"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g>–<xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -939,13 +934,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Nustatymai"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Supratau"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Pat. „SysUI“ krūvą"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"Programa „<xliff:g id="APP">%1$s</xliff:g>“ naudoja: <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Programos naudoja: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" ir "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"fotoaparatą"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"vietovę"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofoną"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Jutikliai išjungti"</string>
<string name="device_services" msgid="1549944177856658705">"Įrenginio paslaugos"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Nėra pavadinimo"</string>
@@ -968,4 +956,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Sistemos naršymo funkcijos atnaujintos. Jei norite pakeisti, eikite į skiltį „Nustatymai“."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Eikite į skiltį „Nustatymai“, kad atnaujintumėte sistemos naršymo funkcijas"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Budėjimo laikas"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Didinimo perdangos langas"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Didinimo langas"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Didinimo lango valdikliai"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lt/strings_tv.xml b/packages/SystemUI/res/values-lt/strings_tv.xml
index d1e55d8da82d..cb0cb6c2845b 100644
--- a/packages/SystemUI/res/values-lt/strings_tv.xml
+++ b/packages/SystemUI/res/values-lt/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Programa be pavadinimo)"</string>
<string name="pip_close" msgid="5775212044472849930">"Uždaryti PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Visas ekranas"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Mikrofonas aktyvus"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"„%1$s“ pasiekė jūsų mikrofoną"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index e99462b97cce..197319261ec1 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Uzzināt vairāk"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Tālumm., lai aizp. ekr."</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Stiepiet, lai aizp. ekr."</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Ekrānuzņēmums"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Saglabā ekrānuzņēmumu…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Notiek ekrānuzņēmuma saglabāšana..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Ekrānuzņēmums saglabāts"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"atvērt tālruni"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"atvērt balss palīgu"</string>
<string name="camera_label" msgid="8253821920931143699">"atvērt kameru"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Atcelt"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Apstiprināt"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Mēģināt vēlreiz"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Pieskarieties, lai atceltu autentifikāciju."</string>
@@ -389,7 +387,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Plkst. <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Līdz <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Tumšais motīvs"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Tumšais motīvs\nJaudas taupīšanas režīms"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Jaudas taupīšana"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Saulrietā"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Līdz saullēktam"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC ir atspējoti"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ir iespējoti"</string>
@@ -414,10 +414,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Pieskarieties vēlreiz, lai atvērtu"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Velciet augšup, lai atvērtu"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Velciet augšup, lai mēģinātu vēlreiz"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Šo ierīci pārvalda jūsu organizācija"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Šo ierīci pārvalda <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Lai lietotu tālruni, velciet no ikonas"</string>
@@ -470,9 +466,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Akumulatora jaudas taupīšanas režīms ir ieslēgts"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Samazina veiktspēju un fona datus"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Izslēgt akumulatora jaudas taupīšanas režīmu"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Ierakstīšanas un apraides laikā lietotne <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> var tvert jebkādu sensitīvu informāciju, kas tiek rādīta jūsu ekrānā vai atskaņota jūsu ierīcē, tostarp tādu sensitīvu informāciju kā audio, paroles, maksājumu informāciju, fotoattēlus un ziņojumus."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Ierakstīšanas vai apraides laikā pakalpojums, kurš nodrošina šo funkciju, var tvert jebkādu sensitīvu informāciju, kas tiek rādīta jūsu ekrānā vai atskaņota jūsu ierīcē, tostarp tādu sensitīvu informāciju kā audio, paroles, maksājumu informāciju, fotoattēlus un ziņojumus."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Sensitīvas informācijas atklāšana apraides/ierakstīšanas laikā"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> iegūs piekļuvi visai informācijai, kas ierakstīšanas vai apraides laikā tiks rādīta jūsu ekrānā vai atskaņota jūsu ierīcē. Atļauja attiecas uz tādu informāciju kā paroles, maksājumu informācija, fotoattēli, ziņojumi un jūsu atskaņotais audio saturs."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Pakalpojums, kas nodrošina šo funkciju, iegūs piekļuvi visai informācijai, kas ierakstīšanas vai apraides laikā tiks rādīta jūsu ekrānā vai atskaņota jūsu ierīcē. Atļauja attiecas uz tādu informāciju kā paroles, maksājumu informācija, fotoattēli, ziņojumi un jūsu atskaņotais audio saturs."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Vai vēlaties sākt ierakstīšanu vai apraidi, izmantojot lietotni <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Vairs nerādīt"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Dzēst visu"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Pārvaldīt"</string>
@@ -791,8 +789,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Tastatūras pārslēdzējs"</string>
<string name="save" msgid="3392754183673848006">"Saglabāt"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Atiestatīt"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Pogas platuma pielāgošana"</string>
<string name="clipboard" msgid="8517342737534284617">"Starpliktuve"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Pielāgota navigācijas poga"</string>
@@ -888,8 +885,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Pa labi"</string>
<string name="tuner_menu" msgid="363690665924769420">"Izvēlne"</string>
<string name="tuner_app" msgid="6949280415826686972">"<xliff:g id="APP">%1$s</xliff:g> lietotne"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Brīdinājumi"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Akumulators"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Ekrānuzņēmumi"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Vispārīgi ziņojumi"</string>
@@ -899,8 +895,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"Lietotne <xliff:g id="APP">%1$s</xliff:g> darbojas"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Lai atvērtu šo lietotni, tā nav jāinstalē."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Lai atvērtu šo lietotni, tā nav jāinstalē. Pieskarieties, lai uzzinātu vairāk."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Par lietotni"</string>
<string name="go_to_web" msgid="636673528981366511">"Atvērt pārlūku"</string>
<string name="mobile_data" msgid="4564407557775397216">"Mobilie dati"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -934,13 +929,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Iestatījumi"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Labi"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"Lietotne <xliff:g id="APP">%1$s</xliff:g> izmanto funkcijas <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Lietojumprogrammas izmanto šādas funkcijas: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" un "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"atrašanās vieta"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofons"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensori izslēgti"</string>
<string name="device_services" msgid="1549944177856658705">"Ierīces pakalpojumi"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Nav nosaukuma"</string>
@@ -963,4 +951,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Sistēmas navigācija ir atjaunināta. Lai veiktu izmaiņas, atveriet iestatījumus."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Atveriet iestatījumus, lai atjauninātu sistēmas navigāciju"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Gaidstāve"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Palielināšanas pārklājuma logs"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Palielināšanas logs"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Palielināšanas loga vadīklas"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lv/strings_tv.xml b/packages/SystemUI/res/values-lv/strings_tv.xml
index a712b974cbe9..e08b0ea4379f 100644
--- a/packages/SystemUI/res/values-lv/strings_tv.xml
+++ b/packages/SystemUI/res/values-lv/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Programma bez nosaukuma)"</string>
<string name="pip_close" msgid="5775212044472849930">"Aizvērt PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Pilnekrāna režīms"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Mikrofons ir aktīvs"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"Lietotne %1$s piekļuva jūsu mikrofonam"</string>
</resources>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index a607f75054d0..5233b165d0e0 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Дознајте повеќе"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Зумирај да се исполни екранот"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Растегни да се исполни екранот"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Слика од екранот"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Сликата на екранот се зачувува..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Сликата на екранот се зачувува..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Сликата од екранот е зачувана"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"отвори телефон"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"отвори гласовна помош"</string>
<string name="camera_label" msgid="8253821920931143699">"отвори камера"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Откажи"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Потврди"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Обиди се повторно"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Допрете за да ја откажете проверката"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Ќе се вклучи во <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"До <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Темна тема"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Темна тема\nШтедач на батерија"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Штедач на батерија"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Вклуч. на зајдисонце"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"До изгрејсонце"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC е оневозможено"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC е овозможено"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Допрете повторно за да се отвори"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Повлечете за да отворите"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Повлечете нагоре за да се обидете повторно"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Вашата организација управува со уредов"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Уредов го управува <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Повлечете од иконата за телефонот"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Штедачот на батерија е вклучен"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Ја намалува изведбата и податоците во заднина"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Исклучете го штедачот на батерија"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"При снимањето или емитувањето, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> може да ги сними чувствителните информации што се прикажани на вашиот екран или пуштени од вашиот уред, вклучувајќи чувствителни информации како што се аудио, лозинки, информации за плаќање, фотографии и пораки."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"При снимањето или емитувањето, услугата што ја обезбедува функцијава може да ги сними чувствителните информации што се прикажани на вашиот екран или пуштени од вашиот уред, вклучувајќи чувствителни информации како што се аудио, лозинки, информации за плаќање, фотографии и пораки."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Изложување чувствителни информации при емитување/снимање"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ќе има пристап до сите информации што се видливи на екранот или пуштени од вашиот уред додека се снима или емитува. Ова вклучува информации како, на пример, лозинки, детали на исплатата, фотографии, пораки и аудио што го пуштате."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Услугата што ја обезбедува функцијава ќе има пристап до сите информации што се видливи на екранот или пуштени од вашиот уред додека се снима или емитува. Ова вклучува информации како, на пример, лозинки, детали на исплатата, фотографии, пораки и аудио што го пуштате."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Да почне снимање или емитување со <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Не покажувај повторно"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Избриши сѐ"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Управувајте"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Менувач на тастатура"</string>
<string name="save" msgid="3392754183673848006">"Зачувај"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Ресетирај"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Приспособи ја ширината на копчето"</string>
<string name="clipboard" msgid="8517342737534284617">"Табла со исечоци"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Приспособено копче за навигација"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Десно"</string>
<string name="tuner_menu" msgid="363690665924769420">"Мени"</string>
<string name="tuner_app" msgid="6949280415826686972">"Апликација <xliff:g id="APP">%1$s</xliff:g>"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Известувања"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Батерија"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Слики од екранот"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Општи пораки"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"Се извршува <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Апликацијата беше отворена без да се инсталира."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Апликацијата беше отворена без да се инсталира. Допрете за да дознаете повеќе."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Инфо. за апликација"</string>
<string name="go_to_web" msgid="636673528981366511">"Одете на прелистувач"</string>
<string name="mobile_data" msgid="4564407557775397216">"Мобилен интернет"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> - <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Поставки"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Сфатив"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Извади SysUI-слика"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> користи <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Апликациите користат <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" и "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"камера"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"локација"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"микрофон"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Сензорите се исклучени"</string>
<string name="device_services" msgid="1549944177856658705">"Услуги за уредот"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Без наслов"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Навигацијата на системот е ажурирана. За да извршите промени, одете во „Поставки“."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Одете во „Поставки“ за да ја ажурирате навигацијата на системот"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Подготвеност"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Прозорец за преклопување на зголемувањето"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Прозорец за зголемување"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Контроли на прозорец за зголемување"</string>
</resources>
diff --git a/packages/SystemUI/res/values-mk/strings_tv.xml b/packages/SystemUI/res/values-mk/strings_tv.xml
index 07b05dee34b2..b4de2156155c 100644
--- a/packages/SystemUI/res/values-mk/strings_tv.xml
+++ b/packages/SystemUI/res/values-mk/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Програма без наслов)"</string>
<string name="pip_close" msgid="5775212044472849930">"Затвори PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Цел екран"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Микрофонот е активен"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s пристапи до вашиот микрофон"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 53ce5aba07c2..a8303139756c 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"കൂടുതലറിയുക"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"സ്‌ക്രീനിൽ ഉൾക്കൊള്ളിക്കാൻ സൂം ചെയ്യുക"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"സ്‌ക്രീനിൽ ഉൾക്കൊള്ളിക്കാൻ വലിച്ചുനീട്ടുക"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"സ്ക്രീൻഷോട്ട്"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"സ്‌ക്രീൻഷോട്ട് സംരക്ഷിക്കുന്നു..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"സ്‌ക്രീൻഷോട്ട് സംരക്ഷിക്കുന്നു..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"സ്‌ക്രീൻഷോട്ട് സംരക്ഷിച്ചു"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"ഫോൺ തുറക്കുക"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"വോയ്‌സ് അസിസ്റ്റ് തുറക്കുക"</string>
<string name="camera_label" msgid="8253821920931143699">"ക്യാമറ തുറക്കുക"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"റദ്ദാക്കുക"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"സ്ഥിരീകരിക്കുക"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"വീണ്ടും ശ്രമിക്കുക"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"പരിശോധിച്ചുറപ്പിക്കൽ റദ്ദാക്കാൻ ടാപ്പ് ചെയ്യുക"</string>
@@ -312,7 +310,7 @@
<string name="quick_settings_dnd_priority_label" msgid="6251076422352664571">"മുൻഗണന മാത്രം"</string>
<string name="quick_settings_dnd_alarms_label" msgid="1241780970469630835">"അലാറങ്ങൾ മാത്രം"</string>
<string name="quick_settings_dnd_none_label" msgid="8420869988472836354">"പൂർണ്ണ നിശബ്‌ദത"</string>
- <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"ബ്ലൂടൂത്ത്"</string>
+ <string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="6595808498429809855">"ബ്ലൂടൂത്ത് (<xliff:g id="NUMBER">%d</xliff:g> ഉപകരണങ്ങൾ)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="6375098046500790870">"ബ്ലൂടൂത്ത് ഓഫുചെയ്യുക"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"ജോടിയാക്കിയ ഉപകരണങ്ങളൊന്നും ലഭ്യമല്ല"</string>
@@ -323,7 +321,7 @@
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"ശ്രവണ സഹായികൾ"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"ഓണാക്കുന്നു…"</string>
<string name="quick_settings_brightness_label" msgid="680259653088849563">"തെളിച്ചം"</string>
- <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"സ്‌ക്രീൻ സ്വയമേവ തിരിയുക"</string>
+ <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"സ്‌ക്രീൻ സ്വയമേവ തിരിയൽ"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"സ്‌ക്രീൻ സ്വയമേവ തിരിക്കുക"</string>
<string name="accessibility_quick_settings_rotation_value" msgid="2916484894750819251">"<xliff:g id="ID_1">%s</xliff:g> മോഡ്"</string>
<string name="quick_settings_rotation_locked_label" msgid="4420863550666310319">"റൊട്ടേഷൻ ലോക്കുചെയ്‌തു"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"<xliff:g id="TIME">%s</xliff:g>-ന്"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g> വരെ"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"ഡാർക്ക് തീം"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"ഇരുണ്ട തീം\nബാറ്ററി ലാഭിക്കൽ"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"ബാറ്ററി ലാഭിക്കൽ"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"സൂര്യാസ്‌തമയത്തിന്"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"സൂര്യോദയം വരെ"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC പ്രവർത്തനരഹിതമാക്കി"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC പ്രവർത്തനക്ഷമമാക്കി"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"തുറക്കുന്നതിന് വീണ്ടും ടാപ്പുചെയ്യുക"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"തുറക്കാൻ മുകളിലോട്ട് സ്വൈപ്പ് ചെയ്യുക"</string>
<string name="keyguard_retry" msgid="886802522584053523">"വീണ്ടും ശ്രമിക്കാൻ മുകളിലേക്ക് സ്വൈപ്പ് ചെയ്യുക"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"ഈ ഉപകരണം മാനേജുചെയ്യുന്നത് നിങ്ങളുടെ സ്ഥാപനമാണ്"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"<xliff:g id="ORGANIZATION_NAME">%s</xliff:g> മാനേജുചെയ്യുന്ന ഉപകരണമാണിത്"</string>
<string name="phone_hint" msgid="6682125338461375925">"ഫോൺ ഐക്കണിൽ നിന്ന് സ്വൈപ്പുചെയ്യുക"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"ബാറ്ററി ലാഭിക്കൽ ഓണാണ്"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"പ്രവർത്തനവും പശ്ചാത്തല ഡാറ്റയും കുറയ്‌ക്കുന്നു"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"ബാറ്ററി ലാഭിക്കൽ ഓഫാക്കുക"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"റെക്കോർഡ് അല്ലെങ്കിൽ കാസ്‌റ്റ് ചെയ്യുന്നതിനിടെ, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> എന്നതിന് നിങ്ങളുടെ സ്ക്രീനിൽ ദൃശ്യമാകുന്നതോ നിങ്ങളുടെ ഉപകരണത്തിൽ നിന്ന് പ്ലേ ചെയ്‌തതോ ആയ ഓഡിയോ, പാസ്‌വേഡുകൾ, പേയ്മെന്റ് വിവരം, ഫോട്ടോകൾ, സന്ദേശങ്ങൾ എന്നിവ ഉൾപ്പെടെയുള്ള തന്ത്രപ്രധാന വിവരങ്ങൾ ക്യാപ്‌ചർ ചെയ്യാനാവും."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"റെക്കോർഡ് അല്ലെങ്കിൽ കാസ്‌റ്റ് ചെയ്യുന്നതിനിടെ, ഈ പ്രവർത്തനത്തിനാവശ്യമായ സേവനത്തിന്, നിങ്ങളുടെ സ്ക്രീനിൽ ദൃശ്യമാകുന്നതോ ഉപകരണത്തിൽ നിന്ന് പ്ലേ ചെയ്‌തതോ ആയ ഓഡിയോ, പാസ്‌വേഡുകൾ, പേയ്മെന്റ് വിവരം, ഫോട്ടോകൾ, സന്ദേശങ്ങൾ എന്നിവ ഉൾപ്പെടെയുള്ള തന്ത്രപ്രധാന വിവരങ്ങൾ ക്യാപ്‌ചർ ചെയ്യാനാവും."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"കാസ്‌റ്റ്/റെക്കോർഡ് ചെയ്യുമ്പോൾ സൂക്ഷ്‌മമായി കൈകാര്യം ചെയ്യേണ്ട വിവരം വെളിപ്പെടുത്തുന്നു"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"റെക്കോർഡ് ചെയ്യുമ്പോഴോ കാസ്‌റ്റ് ചെയ്യുമ്പോഴോ നിങ്ങളുടെ ഉപകരണത്തിൽ നിന്ന് പ്ലേ ചെയ്യുന്നതോ നിങ്ങളുടെ സ്‌ക്രീനിൽ ദൃശ്യമാകുന്നതോ ആയ എല്ലാ വിവരങ്ങളിലേക്കും <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> എന്നതിന് ആക്‌സസ് ഉണ്ടായിരിക്കും. നിങ്ങൾ പ്ലേ ചെയ്യുന്ന ഒഡിയോ, സന്ദേശങ്ങൾ, ഫോട്ടോകൾ, പേയ്‌മെന്റ് വിശദാംശങ്ങൾ, പാസ്‌വേഡുകൾ എന്നിവ പോലുള്ള വിവരങ്ങൾ ഇതിൽ ഉൾപ്പെടുന്നു."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"റെക്കോർഡ് ചെയ്യുമ്പോഴോ കാസ്‌റ്റ് ചെയ്യുമ്പോഴോ നിങ്ങളുടെ ഉപകരണത്തിൽ നിന്ന് പ്ലേ ചെയ്യുന്നതോ നിങ്ങളുടെ സ്‌ക്രീനിൽ ദൃശ്യമാകുന്നതോ ആയ എല്ലാ വിവരങ്ങളിലേക്കും ഈ ഫംഗ്‌ഷൻ ലഭ്യമാക്കുന്ന സേവനത്തിന് ആക്‌സസ് ഉണ്ടായിരിക്കും. നിങ്ങൾ പ്ലേ ചെയ്യുന്ന ഒഡിയോ, സന്ദേശങ്ങൾ, ഫോട്ടോകൾ, പേയ്‌മെന്റ് വിശദാംശങ്ങൾ, പാസ്‌വേഡുകൾ എന്നിവ പോലുള്ള വിവരങ്ങൾ ഇതിൽ ഉൾപ്പെടുന്നു."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ഉപയോഗിച്ച് റെക്കോർഡ് ചെയ്യൽ അല്ലെങ്കിൽ കാസ്‌റ്റ് ചെയ്യൽ ആരംഭിക്കണോ?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"വീണ്ടും കാണിക്കരുത്"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"എല്ലാം മായ്‌ക്കുക"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"മാനേജ് ചെയ്യുക"</string>
@@ -573,7 +571,7 @@
<string name="stream_music" msgid="2188224742361847580">"മീഡിയ"</string>
<string name="stream_alarm" msgid="16058075093011694">"അലാറം"</string>
<string name="stream_notification" msgid="7930294049046243939">"അറിയിപ്പ്"</string>
- <string name="stream_bluetooth_sco" msgid="6234562365528664331">"ബ്ലൂടൂത്ത്"</string>
+ <string name="stream_bluetooth_sco" msgid="6234562365528664331">"Bluetooth"</string>
<string name="stream_dtmf" msgid="7322536356554673067">"ഡ്യുവൽ മൾട്ടി റ്റോൺ ഫ്രീക്വൻസി"</string>
<string name="stream_accessibility" msgid="3873610336741987152">"ഉപയോഗസഹായി"</string>
<string name="ring_toggle_title" msgid="5973120187287633224">"കോളുകൾ"</string>
@@ -667,12 +665,10 @@
<string name="inline_keep_showing_app" msgid="4393429060390649757">"ഈ ആപ്പിൽ നിന്നുള്ള അറിയിപ്പുകൾ തുടർന്നും കാണിക്കണോ?"</string>
<string name="notification_silence_title" msgid="8608090968400832335">"നിശബ്‌ദം"</string>
<string name="notification_alert_title" msgid="7629202599338071971">"മുന്നറിയിപ്പ് നൽകൽ"</string>
- <!-- no translation found for notification_bubble_title (8330481035191903164) -->
- <skip />
+ <string name="notification_bubble_title" msgid="8330481035191903164">"ബബ്ൾ"</string>
<string name="notification_channel_summary_low" msgid="7300447764759926720">"ശബ്‌ദമോ വൈബ്രേഷനോ ഇല്ലാതെ ശ്രദ്ധ കേന്ദ്രീകരിക്കാൻ നിങ്ങളെ സഹായിക്കുന്നു."</string>
<string name="notification_channel_summary_default" msgid="3539949463907902037">"ശബ്‌ദമോ വെെബ്രേഷനോ ഉപയോഗിച്ച് നിങ്ങളുടെ ശ്രദ്ധ ക്ഷണിക്കുന്നു."</string>
- <!-- no translation found for notification_channel_summary_bubble (7235935211580860537) -->
- <skip />
+ <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ഈ ഉള്ളടക്കത്തിലേക്ക് ഒരു ഫ്ലോട്ടിംഗ് കുറുക്കുവഴി ഉപയോഗിച്ച് നിങ്ങളുടെ ശ്രദ്ധ നിലനിർത്തുന്നു."</string>
<string name="notification_unblockable_desc" msgid="2073030886006190804">"ഈ അറിയിപ്പുകൾ പരിഷ്ക്കരിക്കാനാവില്ല."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"അറിയിപ്പുകളുടെ ഈ ഗ്രൂപ്പ് ഇവിടെ കോണ്‍ഫിഗര്‍ ചെയ്യാൻ കഴിയില്ല"</string>
<string name="notification_delegate_header" msgid="1264510071031479920">"പ്രോക്‌സി അറിയിപ്പ്"</string>
@@ -788,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"കീബോർഡ് സ്വിച്ചർ"</string>
<string name="save" msgid="3392754183673848006">"സംരക്ഷിക്കുക"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"റീസെറ്റ് ചെയ്യുക"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"ബട്ടൺ വീതി ക്രമീകരിക്കുക"</string>
<string name="clipboard" msgid="8517342737534284617">"ക്ലിപ്പ്ബോർഡ്"</string>
<string name="accessibility_key" msgid="3471162841552818281">"ഇഷ്ടാനുസൃത നാവിഗേഷൻ ബട്ടൺ"</string>
@@ -885,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"വലത്"</string>
<string name="tuner_menu" msgid="363690665924769420">"മെനു"</string>
<string name="tuner_app" msgid="6949280415826686972">"<xliff:g id="APP">%1$s</xliff:g> ആപ്പ്"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"മുന്നറിയിപ്പുകൾ"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"ബാറ്ററി"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"സ്‌ക്രീൻഷോട്ടുകൾ"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"പൊതുവായ സന്ദേശങ്ങൾ"</string>
@@ -896,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> റണ്‍ ചെയ്യുന്നു"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"ഇൻസ്‌റ്റാൾ ചെയ്യാതെ ആപ്പ് തുറന്നു."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"ഇൻസ്‌റ്റാൾ ചെയ്യാതെ ആപ്പ് തുറന്നു. കൂടുതലറിയാൻ ടാപ്പ് ചെയ്യുക."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"ആപ്പ് വിവരം"</string>
<string name="go_to_web" msgid="636673528981366511">"ബ്രൗസറിലേക്ക് പോവുക"</string>
<string name="mobile_data" msgid="4564407557775397216">"മൊബൈൽ ഡാറ്റ"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -931,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"ക്രമീകരണം"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"മനസ്സിലായി"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"SysUI ഹീപ്പ് ഡമ്പ് ചെയ്യുക"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> നിങ്ങളുടെ <xliff:g id="TYPES_LIST">%2$s</xliff:g> ഉപയോഗിക്കുന്നു."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"ആപ്പുകൾ നിങ്ങളുടെ <xliff:g id="TYPES_LIST">%s</xliff:g> ഉപയോഗിക്കുന്നു."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" കൂടാതെ "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"ക്യാമറ"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"ലൊക്കേഷന്‍"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"മൈക്രോഫോൺ"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"സെൻസറുകൾ ഓഫാണ്"</string>
<string name="device_services" msgid="1549944177856658705">"ഉപകരണ സേവനങ്ങള്‍"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"പേരില്ല"</string>
@@ -960,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"സിസ്‌റ്റം നാവിഗേഷൻ അപ്‌ഡേറ്റ് ചെയ്‌തു. മാറ്റങ്ങൾ വരുത്താൻ ക്രമീകരണത്തിലേക്ക് പോവുക."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"സിസ്‌റ്റം നാവിഗേഷൻ അപ്‌ഡേറ്റ് ചെയ്യാൻ ക്രമീകരണത്തിലേക്ക് പോവുക"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"സ്‌റ്റാൻഡ്‌ബൈ"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"മാഗ്നിഫിക്കേഷൻ ഓവർലേ വിൻഡോ"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"മാഗ്നിഫിക്കേഷൻ വിൻഡോ"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"മാഗ്നിഫിക്കേഷൻ വിൻഡോ നിയന്ത്രണങ്ങൾ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ml/strings_tv.xml b/packages/SystemUI/res/values-ml/strings_tv.xml
index 7773b4ac4086..bf925c454f6d 100644
--- a/packages/SystemUI/res/values-ml/strings_tv.xml
+++ b/packages/SystemUI/res/values-ml/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(പേരില്ലാത്ത പ്രോഗ്രാം)"</string>
<string name="pip_close" msgid="5775212044472849930">"PIP അടയ്ക്കുക"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"പൂര്‍ണ്ണ സ്ക്രീന്‍"</string>
+ <string name="mic_active" msgid="5766614241012047024">"മൈക്രോഫോൺ സജീവമാണ്"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s, നിങ്ങളുടെ മൈക്രോഫോൺ ആക്‌സസ് ചെയ്‌തു"</string>
</resources>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 75af9cd5e272..862f63e586eb 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Нэмэлт мэдээлэл авах"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Дэлгэц дүүргэх бол өсгөнө үү"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Дэлгэц дүүргэх бол татна уу"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Дэлгэцийн зураг дарах"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Дэлгэцийн агшинг хадгалж байна…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Дэлгэцийн агшинг хадгалж байна…"</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Дэлгэцээс дарсан зургийг хадгалсан"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"утас нээх"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"дуут туслахыг нээнэ"</string>
<string name="camera_label" msgid="8253821920931143699">"камер нээх"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Цуцлах"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Баталгаажуулах"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Дахин оролдох"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Нотолгоог цуцлахын тулд товшино уу"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"<xliff:g id="TIME">%s</xliff:g>-д"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g> хүртэл"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Бараан загвар"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Бараан загвар\nБатарей хэмнэгч"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Батарей хэмнэгч"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Нар жаргах үед"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Нар мандах хүртэл"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC-г цуцалсан"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC-г идэвхжүүлсэн"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Нээхийн тулд дахин товшино уу"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Нээхийн тулд дээш шударна уу"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Дахин оролдохын тулд дээш шударна уу"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Энэ төхөөрөмжийг таны байгууллага удирдаж байна"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Энэ төхөөрөмжийг <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> удирддаг"</string>
<string name="phone_hint" msgid="6682125338461375925">"Утсыг гаргахын тулд дүрс тэмдгээс шудрах"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Тэжээл хэмнэгч асаалттай байна"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Ажиллагаа болон далд датаг бууруулна"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Тэжээл хэмнэгчийг унтраах"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Бичиж эсвэл дамжуулж байх үед <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> аудио, нууц үг, төлбөрийн мэдээлэл, зураг болон мессеж зэрэг эмзэг мэдээлэл буюу таны дэлгэц дээрээ харуулдаг эсвэл төхөөрөмжөөсөө тоглуулдаг эмзэг мэдээллийг авах боломжтой."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Бичиж эсвэл дамжуулж байх үед энэ функцийг үзүүлж буй үйлчилгээ нь аудио, нууц үг, төлбөрийн мэдээлэл, зураг болон мессеж зэрэг эмзэг мэдээлэл буюу таны дэлгэц дээрээ харуулдаг эсвэл төхөөрөмжөөсөө тоглуулдаг эмзэг мэдээллийг авах боломжтой."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Дамжуулах/бичих үед эмзэг мэдээллийг задруулж байна"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> нь бичлэг хийх эсвэл дамжуулах үед таны дэлгэц дээр харагдах эсвэл таны төхөөрөмжөөс тоглуулах бүх мэдээлэлд хандах боломжтой байна. Үүнд нууц үг, төлбөрийн дэлгэрэнгүй, зураг болон таны тоглуулдаг аудио зэрэг мэдээлэл багтана."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Энэ функцийг ажиллуулж байгаа үйлчилгээ нь бичлэг хийх эсвэл дамжуулах үед таны дэлгэц дээр харагдах эсвэл таны төхөөрөмжөөс тоглуулах бүх мэдээлэлд хандах боломжтой байна. Үүнд нууц үг, төлбөрийн дэлгэрэнгүй, зураг болон таны тоглуулдаг аудио зэрэг мэдээлэл багтана."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>-тай бичлэг хийж эсвэл дамжуулж эхлэх үү?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Дахиж үл харуулах"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Бүгдийг арилгах"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Удирдах"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Гар солигч"</string>
<string name="save" msgid="3392754183673848006">"Хадгалах"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Шинэчлэх"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Товчлуурын өргөнг тохируулах"</string>
<string name="clipboard" msgid="8517342737534284617">"Түр санах ой"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Навигацийн товчлуурыг өөрчлөх"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Баруун"</string>
<string name="tuner_menu" msgid="363690665924769420">"Цэс"</string>
<string name="tuner_app" msgid="6949280415826686972">"<xliff:g id="APP">%1$s</xliff:g> апп"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Сэрэмжлүүлэг"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Батарей"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Дэлгэцийн зураг дарах"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Энгийн зурвас"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g>-г ажиллуулж байна"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Аппыг суулгахгүйгээр нээсэн."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Аппыг суулгахгүйгээр нээсэн. Нэмэлт мэдээлэл авахын тулд товшино уу."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Аппын мэдээлэл"</string>
<string name="go_to_web" msgid="636673528981366511">"Хөтчид очих"</string>
<string name="mobile_data" msgid="4564407557775397216">"Мобайл дата"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Тохиргоо"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Ойлголоо"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> таны <xliff:g id="TYPES_LIST">%2$s</xliff:g>-г ашиглаж байна."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Аппууд таны <xliff:g id="TYPES_LIST">%s</xliff:g>-г ашиглаж байна."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" болон "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"камер"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"байршил"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"микрофон"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Мэдрэгчийг унтраах"</string>
<string name="device_services" msgid="1549944177856658705">"Төхөөрөмжийн үйлчилгээ"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Гарчиггүй"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Системийн навигацыг шинэчиллээ. Өөрчлөхийн тулд Тохиргоо руу очно уу."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Системийн навигацыг шинэчлэхийн тулд Тохиргоо руу очно уу"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Зогсолтын горим"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Томруулалтыг давхарласан цонх"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Томруулалтын цонх"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Томруулалтын цонхны хяналт"</string>
</resources>
diff --git a/packages/SystemUI/res/values-mn/strings_tv.xml b/packages/SystemUI/res/values-mn/strings_tv.xml
index 9af7174a6f65..6eb4449a9796 100644
--- a/packages/SystemUI/res/values-mn/strings_tv.xml
+++ b/packages/SystemUI/res/values-mn/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Гарчиггүй хөтөлбөр)"</string>
<string name="pip_close" msgid="5775212044472849930">"PIP-г хаах"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Бүтэн дэлгэц"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Микрофон идэвхтэй байна"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s нь таны микрофонд хандcан байна"</string>
</resources>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 089df331ce72..3eb74b76ba44 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"अधिक जाणून घ्या"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"स्क्रीन भरण्यासाठी झूम करा"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"स्क्रीन भरण्यासाठी ताणा"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"स्क्रीनशॉट"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"स्क्रीनशॉट सेव्ह करत आहे…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"स्क्रीनशॉट सेव्ह करत आहे…"</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"स्क्रीनशॉट सेव्ह केला"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"फोन उघडा"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"व्हॉइस सहाय्य उघडा"</string>
<string name="camera_label" msgid="8253821920931143699">"कॅमेरा उघडा"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"रद्द करा"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"खात्री करा"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"पुन्हा प्रयत्न करा"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"ऑथेंटिकेशन रद्द करण्यासाठी टॅप करा"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"<xliff:g id="TIME">%s</xliff:g> वाजता चालू"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g> पर्यंत"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"गडद थीम"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"गडद थीम\nबॅटरी सेव्हर"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"बॅटरी सेव्‍हर"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"संध्याकाळी सुरू होते"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"सूर्योदयापर्यंत"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC अक्षम केले आहे"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC सक्षम केले आहे"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"उघडण्यासाठी पुन्हा टॅप करा"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"उघडण्यासाठी वर स्वाइप करा"</string>
<string name="keyguard_retry" msgid="886802522584053523">"पुन्हा प्रयत्न करण्यासाठी वर स्‍वाइप करा"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"हे डिव्हाइस तुमची संस्था व्यवस्थापित करते"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"हे डिव्हाइस <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> ने व्यवस्थापित केले आहे"</string>
<string name="phone_hint" msgid="6682125338461375925">"फोनसाठी चिन्हावरून स्वाइप करा"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"बॅटरी सेव्‍हर चालू आहे"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"कामगिरी आणि पार्श्वभूमीवरील डेटा कमी करते"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"बॅटरी सेव्हर बंद करा"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"रेकॉर्ड किंवा कास्ट करत असताना, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> हे ऑडिओ, पासवर्ड, पेमेंट माहिती, फोटो आणि मेसेज यासारख्या संवेदनशील माहितीच्या समावेशासह तुमच्या स्क्रीनवर दाखवलेली किंवा डिव्हाइसवर प्ले केलेली कोणतीही संवेदनशील माहिती कॅप्चर करू शकते."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"रेकॉर्ड किंवा कास्ट करत असताना, हे फंक्शन देऊ करणारी सेवा ऑडिओ, पासवर्ड, पेमेंट माहिती, फोटो आणि मेसेज यासारख्या संवेदनशील माहितीच्या समावेशासह तुमच्या स्क्रीनवर दाखवलेली किंवा डिव्हाइसवर प्ले केलेली कोणतीही संवेदनशील माहिती कॅप्चर करू शकते."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"कास्टिंग/रेकॉर्डिंग करत असताना संवेदनशील माहिती उघड करत आहे"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"तुमच्या स्क्रीनवर दृश्यमान असलेल्या किंवा रेकॉर्ड किंवा कास्ट करताना तुमच्या डिव्हाइसमधून प्ले केलेल्या सर्व माहितीचा अ‍ॅक्सेस <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ला असेल. यामध्ये पासवर्ड, पेमेंट तपशील, फोटो, मेसेज आणि तुम्ही प्ले केलेला ऑडिओ यासारख्या माहितीचा समावेश असतो."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"हे कार्य पुरवठा करणाऱ्या सेवेस तुमच्या स्क्रीनवर दृश्यमान असलेल्या किंवा रेकॉर्ड किंवा कास्ट करताना तुमच्या डिव्हाइसमधून प्ले केलेल्या सर्व माहितीचा अ‍ॅक्सेस असेल. यामध्ये पासवर्ड, पेमेंट तपशील, फोटो, मेसेज आणि तुम्ही प्ले केलेला ऑडिओ यासारख्या माहितीचा समावेश असतो."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ने रेकॉर्ड करणे किंवा कास्ट करणे सुरू करा?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"पुन्हा दर्शवू नका"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"सर्व साफ करा"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"व्यवस्थापित करा"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"कीबोर्ड स्विचर"</string>
<string name="save" msgid="3392754183673848006">"सेव्ह करा"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"रीसेट करा"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"बटण रूंदी समायोजित करा"</string>
<string name="clipboard" msgid="8517342737534284617">"क्लिपबोर्ड"</string>
<string name="accessibility_key" msgid="3471162841552818281">"कस्टम नेव्हिगेशन बटण"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"उजवा"</string>
<string name="tuner_menu" msgid="363690665924769420">"मेनू"</string>
<string name="tuner_app" msgid="6949280415826686972">"<xliff:g id="APP">%1$s</xliff:g> अ‍ॅप"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"सूचना"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"बॅटरी"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"स्क्रीनशॉट"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"सर्वसाधारण मेसेज"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> रन होत आहे"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"इंस्टॉल केल्याशिवाय अ‍ॅप उघडले."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"इंस्टॉल केल्याशिवाय अ‍ॅप उघडले. अधिक जाणून घेण्यासाठी टॅप करा."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"अ‍ॅप माहिती"</string>
<string name="go_to_web" msgid="636673528981366511">"ब्राउझरवर जा"</string>
<string name="mobile_data" msgid="4564407557775397216">"मोबाइल डेटा"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"सेटिंग्ज"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"समजले"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"SysUI हीप डंप करा"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> तुमचे <xliff:g id="TYPES_LIST">%2$s</xliff:g> वापरत आहे."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"ॲप्लिकेशन्स तुमचे <xliff:g id="TYPES_LIST">%s</xliff:g> वापरत आहे."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" आणि "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"कॅमेरा"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"स्थान"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"मायक्रोफोन"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"सेन्सर बंद आहेत"</string>
<string name="device_services" msgid="1549944177856658705">"डिव्हाइस सेवा"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"शीर्षक नाही"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"सिस्टम नेव्हिगेशन अपडेट केले. बदल करण्यासाठी, सेटिंग्जवर जा."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"सिस्टम नेव्हिगेशन अपडेट करण्यासाठी सेटिंग्जवर जा"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"स्टँडबाय"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"मॅग्निफिकेशन ओव्हरले विंडो"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"मॅग्निफिकेशन विंडो"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"मॅग्निफिकेशन विंडो नियंत्रणे"</string>
</resources>
diff --git a/packages/SystemUI/res/values-mr/strings_tv.xml b/packages/SystemUI/res/values-mr/strings_tv.xml
index b89982a37393..587832a6bda6 100644
--- a/packages/SystemUI/res/values-mr/strings_tv.xml
+++ b/packages/SystemUI/res/values-mr/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(शीर्षक नसलेला कार्यक्रम)"</string>
<string name="pip_close" msgid="5775212044472849930">"PIP बंद करा"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"फुल स्क्रीन"</string>
+ <string name="mic_active" msgid="5766614241012047024">"मायक्रोफोन ॲक्टिव्ह आहे"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s यांनी तुमचा मायक्रोफोन अ‍ॅक्सेस केला आहे"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 3073c9f65491..9a8b50fcb7f1 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Ketahui lebih lanjut"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Zum untuk memenuhi skrin"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Regang utk memenuhi skrin"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Tangkapan skrin"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Menyimpan tangkapan skrin..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Menyimpan tangkapan skrin..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Tangkapan skrin disimpan"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"buka telefon"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"buka bantuan suara"</string>
<string name="camera_label" msgid="8253821920931143699">"buka kamera"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Batal"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Sahkan"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Cuba lagi"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Ketik untuk membatalkan pengesahan"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Dihidupkan pada <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Hingga <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Tema gelap"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Tema gelap\nPenjimat bateri"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Penjimat Bateri"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Dihidupkan pd senja"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Hingga matahari trbt"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC dilumpuhkan"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC didayakan"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Ketik lagi untuk membuka"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Leret ke atas untuk buka"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Leret ke atas untuk mencuba lagi"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Peranti ini diurus oleh organisasi anda"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Peranti ini diurus oleh <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Leret dari ikon untuk telefon"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Penjimat Bateri dihidupkan"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Mengurangkan prestasi dan data latar belakang"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Matikan Penjimat Bateri"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Semasa merakam atau menghantar, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> boleh menangkap sebarang maklumat sensitif yang dipaparkan pada skrin anda atau dimainkan daripada peranti anda, termasuk maklumat sensitif seperti audio, kata laluan, maklumat pembayaran, foto dan mesej."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Semasa merakam atau menghantar, perkhidmatan yang menyediakan fungsi ini boleh menangkap sebarang maklumat sensitif yang dipaparkan pada skrin anda atau dimainkan daripada peranti anda, termasuk maklumat sensitif seperti audio, kata laluan, maklumat pembayaran, foto dan mesej."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Mendedahkan maklumat sensitif semasa menghantar/merakam"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> akan mempunyai akses kepada semua maklumat yang kelihatan pada skrin anda atau yang dimainkan daripada peranti anda semasa merakam atau membuat penghantaran. Ini termasuklah maklumat seperti kata laluan, butiran pembayaran, foto, mesej dan audio yang anda mainkan."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Perkhidmatan yang menyediakan fungsi ini akan mempunyai akses kepada semua maklumat yang kelihatan pada skrin anda atau dimainkan daripada peranti anda semasa merakam atau membuat penghantaran. Ini termasuklah maklumat seperti kata laluan, butiran pembayaran, foto, mesej dan audio yang anda mainkan."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Mulakan rakaman atau penghantaran dengan <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Jangan tunjukkan lagi"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Kosongkan semua"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Urus"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Penukar papan kekunci"</string>
<string name="save" msgid="3392754183673848006">"Simpan"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Tetapkan Semula"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Laraskan lebar butang"</string>
<string name="clipboard" msgid="8517342737534284617">"Papan Keratan"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Butang navigasi tersuai"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Kanan"</string>
<string name="tuner_menu" msgid="363690665924769420">"Menu"</string>
<string name="tuner_app" msgid="6949280415826686972">"Apl <xliff:g id="APP">%1$s</xliff:g>"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Makluman"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Bateri"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Tangkapan skrin"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Mesej Am"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> sedang berjalan"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Apl dibuka tanpa dipasang."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Apl dibuka tanpa dipasang. Ketik untuk mengetahui lebih lanjut."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Maklumat apl"</string>
<string name="go_to_web" msgid="636673528981366511">"Pergi ke penyemak imbas"</string>
<string name="mobile_data" msgid="4564407557775397216">"Data mudah alih"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Tetapan"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"OK"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Longgok Tmbunn SysUI"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> sedang menggunakan <xliff:g id="TYPES_LIST">%2$s</xliff:g> anda."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplikasi sedang menggunakan <xliff:g id="TYPES_LIST">%s</xliff:g> anda."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" dan "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"lokasi"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Penderia dimatikan"</string>
<string name="device_services" msgid="1549944177856658705">"Perkhidmatan Peranti"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Tiada tajuk"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Navigasi sistem dikemas kini. Untuk membuat perubahan, pergi ke Tetapan."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Pergi ke Tetapan untuk mengemas kini navigasi sistem"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Tunggu sedia"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Tetingkap Tindanan Pembesaran"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Tetingkap Pembesaran"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Kawalan Tetingkap Pembesaran"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ms/strings_tv.xml b/packages/SystemUI/res/values-ms/strings_tv.xml
index c695ce65beb8..ba6a85e3e546 100644
--- a/packages/SystemUI/res/values-ms/strings_tv.xml
+++ b/packages/SystemUI/res/values-ms/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Program tiada tajuk)"</string>
<string name="pip_close" msgid="5775212044472849930">"Tutup PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Skrin penuh"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Mikrofon Aktif"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s telah mengakses mikrofon anda"</string>
</resources>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 9fcb86e04617..45893c1f22d6 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"ပိုမိုလေ့လာရန်"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"ဇူးမ်အပြည့်ဆွဲခြင်း"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"ဖန်သားပြင်အပြည့်ဆန့်ခြင်း"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"ဖန်သားပြင်ဓာတ်ပုံ"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"ဖန်သားပြင်ဓါတ်ပုံသိမ်းစဉ်.."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"ဖန်သားပြင်ဓါတ်ပုံရိုက်ခြင်းအား သိမ်းဆည်းပါမည်"</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"ဖန်သားပြင်ဓာတ်ပုံကို သိမ်းပြီးပါပြီ"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"ဖုန်းကို ဖွင့်ရန်"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"အသံ အကူအညီအား ဖွင့်ရန်"</string>
<string name="camera_label" msgid="8253821920931143699">"ကင်မရာ ဖွင့်ရန်"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"မလုပ်တော့"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"အတည်ပြုပါ"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"ထပ်စမ်းကြည့်ရန်"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"အထောက်အထားစိစစ်ခြင်းကို ပယ်ဖျက်ရန် တို့ပါ"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"<xliff:g id="TIME">%s</xliff:g> တွင် ဖွင့်ရန်"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g> အထိ"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"မှောင်သည့် အပြင်အဆင်"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"မှောင်သည့် အပြင်အဆင်\nဘက်ထရီ အားထိန်း"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"ဘက်ထရီ အားထိန်း"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"နေဝင်ချိန်၌ ဖွင့်ရန်"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"နေထွက်ချိန် အထိ"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC ကို ပိတ်ထားသည်"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ကို ဖွင့်ထားသည်"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"ဖွင့်ရန် ထပ်ပြီး ပုတ်ပါ"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"ဖွင့်ရန် အပေါ်သို့ပွတ်ဆွဲပါ"</string>
<string name="keyguard_retry" msgid="886802522584053523">"ထပ်စမ်းကြည့်ရန် အပေါ်သို့ပွတ်ဆွဲပါ"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"ဤစက်ပစ္စည်းကို သင်၏အဖွဲ့အစည်းက စီမံခန့်ခွဲထားပါသည်"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"ဤစက်ပစ္စည်းကို <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> က စီမံခန့်ခွဲထားပါသည်"</string>
<string name="phone_hint" msgid="6682125338461375925">"ဖုန်းအတွက် သင်္ကေတပုံအား ပွတ်ဆွဲပါ"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"ဘက်ထရီ အားထိန်းကို ဖွင့်ထားခြင်း"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"လုပ်ကိုင်မှုကို လျှော့ချလျက် နောက်ခံ ဒေတာကို ကန့်သတ်သည်"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"ဘက်ထရီ အားထိန်းကို ပိတ်ရန်"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"အသံဖမ်းနေစဉ် (သို့) ကာစ်လုပ်နေစဉ် <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> သည် အသံ၊ စကားဝှက်၊ ငွေပေးချေမှုဆိုင်ရာ အချက်အလက်၊ ဓာတ်ပုံနှင့် မက်ဆေ့ဂျ်များကဲ့သို့ အရေးကြီးသည့် အချက်အလက်များအပါအဝင် ဖန်သားပြင်တွင် ပြသထားသော (သို့) သင့်စက်တွင် ဖွင့်ထားသော အရေးကြီးသည့် အချက်အလက်မှန်သမျှကို ဖမ်းယူနိုင်ပါသည်။"</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"အသံဖမ်းနေစဉ် (သို့) ကာစ်လုပ်နေစဉ် ဤလုပ်ဆောင်ချက်ကို ပေးအပ်သည့် ဝန်ဆောင်မှုသည် အသံ၊ စကားဝှက်၊ ငွေပေးချေမှုဆိုင်ရာ အချက်အလက်၊ ဓာတ်ပုံနှင့် မက်ဆေ့ဂျ်များကဲ့သို့ အရေးကြီးသည့် အချက်အလက်များအပါအဝင် သင့်မျက်နှာပြင်တွင် ပြသထားသော (သို့) သင့်စက်တွင် ဖွင့်ထားသော အရေးကြီးသည့် အချက်အလက်မှန်သမျှကို ဖမ်းယူနိုင်ပါသည်။"</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"ကာစ်လုပ်နေစဉ်/အသံဖမ်းနေစဉ် အရေးကြီးသောအချက်အလက်များ ထုတ်ဖော်မိခြင်း"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> သည် အသံဖမ်းနေစဉ် (သို့) ကာစ်လုပ်နေစဉ် သင့်မျက်နှာပြင်တွင် မြင်ရသော (သို့) သင့်စက်တွင် ဖွင့်ထားသော အချက်အလက်မှန်သမျှကို သုံးနိုင်ပါမည်။ ၎င်းတွင် စကားဝှက်များ၊ ငွေပေးချေမှုအသေးစိတ်များ၊ ဓာတ်ပုံများ၊ မက်ဆေ့ဂျ်များနှင့် သင်ဖွင့်သည့်အသံကဲ့သို့သော အချက်အလက်များ ပါဝင်သည်။"</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"ဤလုပ်ဆောင်ချက်ကို ပေးအပ်သည့် ဝန်ဆောင်မှုသည် အသံဖမ်းနေစဉ် (သို့) ကာစ်လုပ်နေစဉ် သင့်မျက်နှာပြင်တွင် မြင်ရသော (သို့) သင့်စက်တွင် ဖွင့်ထားသော အချက်အလက်မှန်သမျှကို သုံးနိုင်ပါမည်။ ၎င်းတွင် စကားဝှက်များ၊ ငွေပေးချေမှုအသေးစိတ်များ၊ ဓာတ်ပုံများ၊ မက်ဆေ့ဂျ်များနှင့် သင်ဖွင့်သည့်အသံကဲ့သို့သော အချက်အလက်များ ပါဝင်သည်။"</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> နှင့် ဖမ်းယူခြင်း သို့မဟုတ် ကာစ်လုပ်ခြင်း စတင်မလား။"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"နောက်ထပ် မပြပါနှင့်"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"အားလုံး ဖယ်ရှားရန်"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"စီမံရန်"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"ကီးဘုတ် ပြောင်းလဲပေးသည့်စနစ်"</string>
<string name="save" msgid="3392754183673848006">"သိမ်းရန်"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"ပြင်ဆင်သတ်မှတ်ရန်"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"ခလုတ်အလျားကို ချိန်ညှိပါ"</string>
<string name="clipboard" msgid="8517342737534284617">"ကလစ်ဘုတ်"</string>
<string name="accessibility_key" msgid="3471162841552818281">"စိတ်ကြိုက်ရွှေ့လျားရန် ခလုတ်"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"လက်ယာ"</string>
<string name="tuner_menu" msgid="363690665924769420">"မီနူး"</string>
<string name="tuner_app" msgid="6949280415826686972">"<xliff:g id="APP">%1$s</xliff:g> အက်ပ်"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"သတိပေးချက်များ"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"ဘက်ထရီ"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"မျက်နှာပြင်ဓာတ်ပုံများ"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"အထွေထွေ မက်ဆေ့ဂျ်များ"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> လုပ်ဆောင်နေသည်"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"အက်ပ်ကိုမထည့်သွင်းဘဲ ဖွင့်ထားသည်။"</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"အက်ပ်ကိုမထည့်သွင်းဘဲ ဖွင့်ထားသည်။ ပိုမိုလေ့လာရန် တို့ပါ။"</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"အက်ပ် အချက်အလက်"</string>
<string name="go_to_web" msgid="636673528981366511">"ဘရောင်ဇာသို့ သွားပါ"</string>
<string name="mobile_data" msgid="4564407557775397216">"မိုဘိုင်းဒေတာ"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> —<xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"ဆက်တင်များ"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"ရပါပြီ"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> က သင်၏ <xliff:g id="TYPES_LIST">%2$s</xliff:g> ကို အသုံးပြုနေသည်။"</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"အပလီကေးရှင်းများက သင်၏ <xliff:g id="TYPES_LIST">%s</xliff:g> ကို အသုံးပြုနေသည်။"</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">"၊ "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" နှင့် "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"ကင်မရာ"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"တည်နေရာ"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"မိုက်ခရိုဖုန်း"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"အာရုံခံကိရိယာများ ပိတ်ထားသည်"</string>
<string name="device_services" msgid="1549944177856658705">"စက်ပစ္စည်းဝန်ဆောင်မှုများ"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"ခေါင်းစဉ် မရှိပါ"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"စနစ်လမ်းညွှန်ခြင်း အပ်ဒိတ်လုပ်ပြီးပါပြီ။ အပြောင်းအလဲများ ပြုလုပ်ရန် \'ဆက်တင်များ\' သို့သွားပါ။"</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"စနစ်လမ်းညွှန်ခြင်း အပ်ဒိတ်လုပ်ရန် \'ဆက်တင်များ\' သို့သွားပါ"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"အသင့်အနေအထား"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"ဝင်းဒိုး ထပ်ပိုးလွှာ ချဲ့ခြင်း"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"ဝင်းဒိုး ချဲ့ခြင်း"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"ဝင်းဒိုး ထိန်းချုပ်မှုများ ချဲ့ခြင်း"</string>
</resources>
diff --git a/packages/SystemUI/res/values-my/strings_tv.xml b/packages/SystemUI/res/values-my/strings_tv.xml
index d712bca7fcc4..e33a1c32557a 100644
--- a/packages/SystemUI/res/values-my/strings_tv.xml
+++ b/packages/SystemUI/res/values-my/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(ခေါင်းစဉ်မဲ့ အစီအစဉ်)"</string>
<string name="pip_close" msgid="5775212044472849930">"PIP ကိုပိတ်ပါ"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"မျက်နှာပြင် အပြည့်"</string>
+ <string name="mic_active" msgid="5766614241012047024">"မိုက်ခရိုဖုန်း ဖွင့်ထားသည်"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s က သင့်မိုက်ခရိုဖုန်းကို သုံးထားသည်"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 9a9854b716a3..d07bd8e44824 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Finn ut mer"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Zoom for å fylle skjermen"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Strekk for å fylle skjerm"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Skjermdump"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Lagrer skjermdumpen …"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Lagrer skjermdumpen …"</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Skjermdumpen er lagret"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"åpne telefonen"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"åpne talehjelp"</string>
<string name="camera_label" msgid="8253821920931143699">"åpne kamera"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Avbryt"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Bekreft"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Prøv på nytt"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Trykk for å avbryte autentiseringen"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"På kl. <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Til <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Mørkt tema"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Mørkt tema\nBatterisparing"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Batterisparing"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"På ved solnedgang"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Til soloppgang"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC er slått av"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC er slått på"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Trykk på nytt for å åpne"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Sveip opp for å åpne"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Sveip opp for å prøve igjen"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Denne enheten administreres av organisasjonen din"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Denne enheten administreres av <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Sveip ikonet for å åpne telefon"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Batterisparing er på"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Reduserer ytelsen og begrenser bakgrunnsdataene"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Slå av batterisparing"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Under opptak eller casting kan <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> registrere all sensitiv informasjon som vises på skjermen eller spilles av fra enheten, for eksempel lyd, passord, betalingsinformasjon, bilder og meldinger."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Under opptak eller casting kan tjenesten som leverer denne funksjonen, registrere all sensitiv informasjon som vises på skjermen eller spilles av fra enheten, for eksempel lyd, passord, betalingsinformasjon, bilder og meldinger."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Avdekking av sensitiv informasjon under casting/opptak"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> får tilgang til all informasjon som er synlig på skjermen din, eller som spilles av fra enheten når du tar opp eller caster. Dette inkluderer informasjon som passord, betalingsopplysninger, bilder, meldinger og lyd du spiller av."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Tjenesten som leverer denne funksjonen, får tilgang til all informasjon som er synlig på skjermen din, eller som spilles av fra enheten når du tar opp eller caster. Dette inkluderer informasjon som passord, betalingsopplysninger, bilder, meldinger og lyd du spiller av."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Vil du starte opptak eller casting med <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Ikke vis igjen"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Fjern alt"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Administrer"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Bytteknapp for tastatur"</string>
<string name="save" msgid="3392754183673848006">"Lagre"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Tilbakestill"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Juster bredden på knappen"</string>
<string name="clipboard" msgid="8517342737534284617">"Utklippstavle"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Spesialtilpasset navigasjonsknapp"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Høyre"</string>
<string name="tuner_menu" msgid="363690665924769420">"Meny"</string>
<string name="tuner_app" msgid="6949280415826686972">"<xliff:g id="APP">%1$s</xliff:g>-appen"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Varsler"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Batteri"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Skjermdumper"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Generelle meldinger"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> kjører"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Appen ble åpnet uten at den ble installert."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Appen ble åpnet uten at den ble installert. Trykk for å finne ut mer."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Appinformasjon"</string>
<string name="go_to_web" msgid="636673528981366511">"Gå til nettleser"</string>
<string name="mobile_data" msgid="4564407557775397216">"Mobildata"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Innstillinger"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Greit"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI-heap"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> bruker <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Apper bruker <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" og "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"posisjon"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensorer er av"</string>
<string name="device_services" msgid="1549944177856658705">"Enhetstjenester"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Ingen tittel"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Systemnavigeringen er oppdatert. For å gjøre endringer, gå til Innstillinger."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Gå til Innstillinger for å oppdatere systemnavigeringen"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Ventemodus"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Overleggsvindu for forstørring"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Forstørringsvindu"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Kontroller for forstørringsvindu"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nb/strings_tv.xml b/packages/SystemUI/res/values-nb/strings_tv.xml
index b4e7d1fd86ba..22580e645ca0 100644
--- a/packages/SystemUI/res/values-nb/strings_tv.xml
+++ b/packages/SystemUI/res/values-nb/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Program uten tittel)"</string>
<string name="pip_close" msgid="5775212044472849930">"Lukk PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Fullskjerm"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Mikrofonen er aktiv"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s brukte mikrofonen din"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index fa1fa56a4a15..ef6bc476adaa 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"थप जान्नुहोस्"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"स्क्रिन भर्न जुम गर्नुहोस्"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"स्क्रिन भर्न तन्काउनुहोस्"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"स्क्रिनसट"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"स्क्रिनसट बचत गर्दै…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"स्क्रिनसट बचत गर्दै…"</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"स्क्रिनसट सुरक्षित गरियो"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"फोन खोल्नुहोस्"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"आवाज सहायता खोल्नुहोस्"</string>
<string name="camera_label" msgid="8253821920931143699">"क्यामेरा खोल्नुहोस्"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"रद्द गर्नुहोस्"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"पुष्टि गर्नुहोस्"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"फेरि प्रयास गर्नुहोस्"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"प्रमाणीकरण रद्द गर्न ट्याप गर्नुहोस्"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"<xliff:g id="TIME">%s</xliff:g> मा सक्रिय"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g> सम्म"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"अँध्यारो विषयवस्तु"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"अँध्यारो विषयवस्तु\nब्याट्री सेभर"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"ब्याट्री सेभर"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"सूर्यास्तमा सक्रिय"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"सूर्योदयसम्म"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC लाई असक्षम पारिएको छ"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC लाई सक्षम पारिएको छ"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"खोल्न पुनः ट्याप गर्नुहोस्"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"खोल्न माथितिर स्वाइप गर्नुहोस्"</string>
<string name="keyguard_retry" msgid="886802522584053523">"फेरि प्रयास गर्न माथितिर स्वाइप गर्नुहोस्"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"तपाईंको संगठनले यस यन्त्रलाई व्यवस्थापन गर्दछ"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"यो यन्त्र <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> द्वारा व्यवस्थापन गरिएको छ"</string>
<string name="phone_hint" msgid="6682125338461375925">"फोनको लागि आइकनबाट स्वाइप गर्नुहोस्"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"ब्याट्री सेभर सक्रिय छ"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"प्रदर्शन र पृष्ठभूमि डेटा घटाउँनुहोस्"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"ब्याट्री सेभर निष्क्रिय पार्नुहोस्"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"रेकर्ड वा casting गर्दा <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ले पासवर्ड, भुक्तानीसम्बन्धी जानकारी, तस्बिर तथा सन्देशहरू जस्ता संवेदनशील जानकारीलगायत तपाईंको स्क्रिनमा देखाइएको सबै संवेदनशील जानकारी वा तपाईंको यन्त्रबाट प्ले गरिएको सबै कुरा लिन सक्छ।"</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"रेकर्ड वा casting गर्दा यो सुविधा प्रदान गर्ने सेवा प्रदायकले पासवर्ड, भुक्तानीसम्बन्धी जानकारी, तस्बिर तथा सन्देशहरू जस्ता संवेदनशील जानकारीलगायत तपाईंको स्क्रिनमा देखाइएको सबै संवेदनशील जानकारी वा तपाईंको यन्त्रबाट प्ले गरिएको सबै कुरा लिन सक्छ।"</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"कास्टिङ/रेकर्डिङका क्रममा संवेदनशील जानकारी देखाइँदै"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ले तपाईंको स्क्रिनमा देख्न सकिने सबै जानकारी अथवा रेकर्ड वा cast गर्दा तपाईंको यन्त्रबाट प्ले गरिएका कुरामाथि पहुँच राख्न सक्ने छ। यसअन्तर्गत पासवर्ड, भुक्तानीका विवरण, तस्बिर, सन्देश र तपाईंले प्ले गर्ने अडियो जस्ता जानकारी समावेश हुन्छन्।"</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"यो कार्य प्रदान गर्ने सेवाले तपाईंको स्क्रिनमा देख्न सकिने सबै जानकारी अथवा रेकर्ड वा cast गर्दा तपाईंको यन्त्रबाट प्ले गरिएका कुरामाथि पहुँच राख्न सक्ने छ। यसअन्तर्गत पासवर्ड, भुक्तानीका विवरण, तस्बिर, सन्देश र तपाईंले प्ले गर्ने अडियो जस्ता जानकारी समावेश हुन्छन्।"</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> मार्फत रेकर्ड गर्न वा cast गर्न थाल्ने हो?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"फेरि नदेखाउनुहोस्"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"सबै हटाउनुहोस्"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"व्यवस्थित गर्नुहोस्"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"किबोर्ड स्विचर"</string>
<string name="save" msgid="3392754183673848006">"सुरक्षित गर्नुहोस्"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"रिसेट गर्नुहोस्"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"बटनको चौडाइ समायोजन गर्नुहोस्"</string>
<string name="clipboard" msgid="8517342737534284617">"क्लिपबोर्ड"</string>
<string name="accessibility_key" msgid="3471162841552818281">"अनुकूलनको नेभिगेशन बटन"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"दायाँ"</string>
<string name="tuner_menu" msgid="363690665924769420">"मेनु"</string>
<string name="tuner_app" msgid="6949280415826686972">"<xliff:g id="APP">%1$s</xliff:g> अनुप्रयोग"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"सतर्कताहरू"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"ब्याट्री"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"स्क्रिनशटहरू"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"सामान्य सन्देशहरू"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> चलिरहेको छ"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"स्थापना नगरिकनै अनुप्रयोग खोलियो।"</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"स्थापना नगरिकनै अनुप्रयोग खोलियो। थप जान्न ट्याप गर्नुहोस्।"</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"एपसम्बन्धी जानकारी"</string>
<string name="go_to_web" msgid="636673528981366511">"ब्राउजरमा जानुहोस्"</string>
<string name="mobile_data" msgid="4564407557775397216">"मोबाइल डेटा"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"सेटिङहरू"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"बुझेँ"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> ले तपाईंको <xliff:g id="TYPES_LIST">%2$s</xliff:g> प्रयोग गर्दै छ।"</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"अनुप्रयोगहरूले तपाईंको <xliff:g id="TYPES_LIST">%s</xliff:g> प्रयोग गर्दै छन्‌।"</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" र "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"क्यामेरा"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"स्थान"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"माइक्रोफोन"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"सेन्सरहरू निष्क्रिय छन्"</string>
<string name="device_services" msgid="1549944177856658705">"यन्त्रका सेवाहरू"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"शीर्षक छैन"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"प्रणालीको नेभिगेसन अद्यावधिक गरियो। परिवर्तन गर्न सेटिङमा जानुहोस्।"</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"प्रणालीको नेभिगेसन अद्यावधिक गर्न सेटिङमा जानुहोस्"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"स्ट्यान्डबाई"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"म्याग्निफिकेसन ओभरले विन्डो"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"म्याग्निफिकेसन विन्डो"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"म्याग्निफिकेसन विन्डोका नियन्त्रणहरू"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ne/strings_tv.xml b/packages/SystemUI/res/values-ne/strings_tv.xml
index a59a3680dbcd..6998f39cec2b 100644
--- a/packages/SystemUI/res/values-ne/strings_tv.xml
+++ b/packages/SystemUI/res/values-ne/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(शीर्षकविहीन कार्यक्रम)"</string>
<string name="pip_close" msgid="5775212044472849930">"PIP लाई बन्द गर्नुहोस्"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"पूर्ण स्क्रिन"</string>
+ <string name="mic_active" msgid="5766614241012047024">"माइक्रोफोन सक्रिय छ"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s ले तपाईंको माइक्रोफोनमाथि पहुँच राख्यो"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 9aa9f1e8cfc7..5d57927bfd13 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Meer informatie"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Zoom om scherm te vullen"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Rek uit v. schermvulling"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Screenshot opslaan..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Screenshot opslaan..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot opgeslagen"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"telefoon openen"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"spraakassistent openen"</string>
<string name="camera_label" msgid="8253821920931143699">"camera openen"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Annuleren"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Bevestigen"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Opnieuw proberen"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Tik om de verificatie te annuleren"</string>
@@ -168,7 +166,7 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX: twee streepjes."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX: drie streepjes."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX-signaal is op volle sterkte."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet-verbinding verbroken."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernetverbinding verbroken."</string>
<string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet verbonden."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Geen signaal."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Niet verbonden."</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Aan om <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Tot <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Donker thema"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Donker thema\nBatterijbesparing"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Batterijbesparing"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Aan bij zonsondergang"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Tot zonsopgang"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC is uitgeschakeld"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC is ingeschakeld"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Tik nog eens om te openen"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Veeg omhoog om te openen"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Veeg omhoog om het opnieuw te proberen"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Dit apparaat wordt beheerd door je organisatie"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Dit apparaat wordt beheerd door <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Vegen voor telefoon"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Batterijbesparing aan"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Vermindert de prestaties en achtergrondgegevens"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Batterijbesparing uitschakelen"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Tijdens het opnemen of casten kan <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> gevoelige informatie opvangen die op je scherm wordt weergegeven of op je apparaat wordt afgespeeld, waaronder gevoelige informatie zoals audio, wachtwoorden, betalingsgegevens, foto\'s en berichten."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Tijdens het opnemen of casten kan de service die deze functie levert gevoelige informatie opvangen die op je scherm wordt weergegeven of op je apparaat wordt afgespeeld, waaronder gevoelige informatie zoals audio, wachtwoorden, betalingsgegevens, foto\'s en berichten."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Gevoelige informatie vrijgeven tijdens casten/opnemen"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> krijgt toegang tot alle informatie die zichtbaar is op je scherm of die wordt afgespeeld vanaf je apparaat tijdens het opnemen of casten. Dit omvat informatie zoals wachtwoorden, betalingsgegevens, foto\'s, berichten en audio die je afspeelt."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"De service die deze functie levert, krijgt toegang tot alle informatie die zichtbaar is op je scherm of die wordt afgespeeld vanaf je apparaat tijdens het opnemen of casten. Dit omvat informatie zoals wachtwoorden, betalingsgegevens, foto\'s, berichten en audio die je afspeelt."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Beginnen met opnemen of casten met <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Niet opnieuw weergeven"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Alles wissen"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Beheren"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Toetsenbordschakelaar"</string>
<string name="save" msgid="3392754183673848006">"Opslaan"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Resetten"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Breedte van knop aanpassen"</string>
<string name="clipboard" msgid="8517342737534284617">"Klembord"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Aangepaste navigatieknop"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Rechts"</string>
<string name="tuner_menu" msgid="363690665924769420">"Menu"</string>
<string name="tuner_app" msgid="6949280415826686972">"<xliff:g id="APP">%1$s</xliff:g>-app"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Meldingen"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Batterij"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Screenshots"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Algemene berichten"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> actief"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"App geopend zonder dat deze is geïnstalleerd."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"App geopend zonder dat deze is geïnstalleerd. Tik voor meer informatie."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"App-info"</string>
<string name="go_to_web" msgid="636673528981366511">"Ga naar browser"</string>
<string name="mobile_data" msgid="4564407557775397216">"Mobiele data"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Instellingen"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"OK"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> gebruikt je <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Apps gebruiken je <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" en "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"camera"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"locatie"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"microfoon"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensoren uit"</string>
<string name="device_services" msgid="1549944177856658705">"Apparaatservices"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Geen titel"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Systeemnavigatie geüpdatet. Als je wijzigingen wilt aanbrengen, ga je naar Instellingen."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Ga naar Instellingen om de systeemnavigatie te updaten"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Stand-by"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Overlay voor vergrotingsvenster"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Vergrotingsvenster"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Bediening van vergrotingsvenster"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nl/strings_tv.xml b/packages/SystemUI/res/values-nl/strings_tv.xml
index 5ad85ab7a1ad..c8dd088f8725 100644
--- a/packages/SystemUI/res/values-nl/strings_tv.xml
+++ b/packages/SystemUI/res/values-nl/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Naamloos programma)"</string>
<string name="pip_close" msgid="5775212044472849930">"PIP sluiten"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Volledig scherm"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Microfoon actief"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s heeft toegang tot je microfoon gehad"</string>
</resources>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 4d467fe9033b..7586be567fde 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"ଅଧିକ ଜାଣନ୍ତୁ"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"ସ୍କ୍ରୀନ ଭରିବା ପାଇଁ ଜୁମ୍ କରନ୍ତୁ"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"ସ୍କ୍ରୀନ୍‌କୁ ଭରିବା ପାଇଁ ଟାଣନ୍ତୁ"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"ସ୍କ୍ରିନ୍‌ସଟ୍ ନିଅନ୍ତୁ"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"ସ୍କ୍ରୀନଶଟ୍‍ ସେଭ୍‍ କରାଯାଉଛି…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"ସ୍କ୍ରୀନଶଟ୍‍ ସେଭ୍‍ କରାଯାଉଛି…"</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"ସ୍କ୍ରୀନଶଟ୍ ସେଭ୍ ହୋଇଛି"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"ଫୋନ୍‌ ଖୋଲନ୍ତୁ"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"ଭଏସ୍‍ ସହାୟକ ଖୋଲନ୍ତୁ"</string>
<string name="camera_label" msgid="8253821920931143699">"କ୍ୟାମେରା ଖୋଲନ୍ତୁ"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"ବାତିଲ୍ କରନ୍ତୁ"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"ନିଶ୍ଚିତ କରନ୍ତୁ"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"ପ୍ରାମାଣିକତା ବାତିଲ୍ କରିବାକୁ ଟାପ୍ କରନ୍ତୁ"</string>
@@ -381,13 +379,15 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"<xliff:g id="DATA_LIMIT">%s</xliff:g> ସୀମା"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"<xliff:g id="DATA_LIMIT">%s</xliff:g> ଚେତାବନୀ"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"ୱର୍କ ପ୍ରୋଫାଇଲ୍‌"</string>
- <string name="quick_settings_night_display_label" msgid="8180030659141778180">"ରାତି ଆଲୋକ"</string>
+ <string name="quick_settings_night_display_label" msgid="8180030659141778180">"ନାଇଟ୍ ଲାଇଟ୍"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"ସୂର୍ଯ୍ୟାସ୍ତ ବେଳେ ଅନ୍ ହେବ"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"ସୂର୍ଯ୍ୟୋଦୟ ପର୍ଯ୍ୟନ୍ତ"</string>
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"<xliff:g id="TIME">%s</xliff:g>ରେ ଅନ୍ ହେବ"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g> ପର୍ଯ୍ୟନ୍ତ"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"ଗାଢ଼ ଥିମ୍"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"ଗାଢ଼ ଥିମ୍\nବ୍ୟାଟେରୀ ସେଭର୍"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"ବ୍ୟାଟେରୀ ସେଭର୍"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"ସନ୍ଧ୍ୟାରେ ଚାଲୁ ହେବ"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"ସକାଳ ପର୍ଯ୍ୟନ୍ତ"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC ଅକ୍ଷମ କରାଯାଇଛି"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ସକ୍ଷମ କରାଯାଇଛି"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"ଖୋଲିବା ପାଇଁ ପୁଣି ଟାପ୍‍ କରନ୍ତୁ"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"ଖୋଲିବା ପାଇଁ ଉପରକୁ ସ୍ୱାଇପ୍ କରନ୍ତୁ"</string>
<string name="keyguard_retry" msgid="886802522584053523">"ପୁଣି ଚେଷ୍ଟା କରିବା ପାଇଁ ଉପରକୁ ସ୍ୱାଇପ୍ କରନ୍ତୁ"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"ଏହି ଡିଭାଇସ୍‌ ଆପଣଙ୍କ ସଂସ୍ଥା ଦ୍ୱାରା ପରିଚାଳିତ।"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"ଏହି ଡିଭାଇସ୍‌ <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> ଦ୍ୱାରା ପରିଚାଳିତ ହେଉଛି"</string>
<string name="phone_hint" msgid="6682125338461375925">"ଫୋନ୍‍ ପାଇଁ ଆଇକନରୁ ସ୍ୱାଇପ୍‍ କରନ୍ତୁ"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"ବ୍ୟାଟେରୀ ସେଭର୍‌ ଅନ୍‌ ଅଛି"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"କାର୍ଯ୍ୟ ସମ୍ପାଦନ ଓ ବ୍ୟାକ୍‌ଗ୍ରାଉଣ୍ଡ ଡାଟା କମ୍ କରନ୍ତୁ"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"ବ୍ୟାଟେରୀ ସେଭର୍‌ ଅଫ୍‍ କରନ୍ତୁ"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"ରେକର୍ଡିଂ କିମ୍ବା କାଷ୍ଟିଂ ସମୟରେ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ଯେ କୌଣସି ସମ୍ବେଦନଶୀଳ ସୂଚନା କ୍ୟାପଚର୍ କରିପାରିବ ଯାହା ଅଡ଼ିଓ, ପାସ୍‌ୱାର୍ଡ, ପେମେଣ୍ଟ ସୂଚନା, ଫଟୋ ଏବଂ ମେସେଜ୍‌ଗୁଡ଼ିକ ପରି ସମ୍ବେଦନଶୀଳ ସୂଚନା ଆପଣଙ୍କର ଡିଭାଇସ୍‌ରେ ଚାଲିବ ବା ଆପଣଙ୍କ ସ୍କ୍ରିନ୍‌ରେ ଦେଖାଯିବ।"</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"ରେକର୍ଡିଂ କିମ୍ବା କାଷ୍ଟିଂ ସମୟରେ ଏହି ପ୍ରକାର୍ଯ୍ୟ ପ୍ରଦାନ କରୁଥିବା ସେବା ଅଡ଼ିଓ, ପାସ୍‌ୱାର୍ଡ, ପେମେଣ୍ଟ ସୂଚନା, ଫଟୋ ଏବଂ ମେସେଜ୍‌ଗୁଡ଼ିକ ପରି ସମ୍ବେଦନଶୀଳ ସୂଚନା କ୍ୟାପଚର୍ କରିପାରିବ ଯାହା ଆପଣଙ୍କର ଡିଭାଇସ୍‌ରେ ଚାଲିବ ବା ଆପଣଙ୍କ ସ୍କ୍ରିନ୍‌ରେ ଦେଖାଯିବ।"</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"କାଷ୍ଟିଂ/ରେକର୍ଡିଂ ସମୟରେ ସମ୍ବେଦନଶୀଳ ସୂଚନା ଦେଖାନ୍ତୁ"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>ରେ ସମସ୍ତ ସୂଚନାକୁ ଆକ୍ସେସ୍ ରହିବ ଯାହା ଆପଣଙ୍କର ସ୍କ୍ରିନ୍‌ରେ ଦେଖାଯିବ ବା ରେକର୍ଡିଂ ବା କାଷ୍ଟିଂ ବେଳେ ଆପଣଙ୍କର ଡିଭାଇସ୍ ଠାରୁ ଚାଲିବ। ପାସ୍‌ୱାର୍ଡ, ପେମେଣ୍ଟ ବିବରଣୀ, ଫଟୋ, ମେସେଜ୍ ଏବଂ ଆପଣ ଚଲାଉଥିବା ଅଡିଓ ପରି ସୂଚନା ଅନ୍ତର୍ଭୁକ୍ତ ଅଛି।"</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"ଏହି ପ୍ରକାର୍ଯ୍ୟ ପ୍ରଦାନ କରୁଥିବା ସେବା ସମସ୍ତ ସୂଚନାକୁ ଆକ୍ସେସ୍ ରହିବ ଯାହା ସ୍କ୍ରିନ୍‌ରେ ଦେଖାଯିବ ବା ରେକର୍ଡିଂ ବା କାଷ୍ଟିଂ ବେଳେ ଆପଣଙ୍କର ଡିଭାଇସ୍ ଠାରୁ ଚାଲିବ। ପାସ୍‌ୱାର୍ଡ, ପେମେଣ୍ଟ ବିବରଣୀ, ଫଟୋ, ମେସେଜ୍ ଏବଂ ଆପଣ ଚଲାଉଥିବା ଅଡିଓ ପରି ସୂଚନା ଅନ୍ତର୍ଭୁକ୍ତ ଅଛି।"</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ସହ ରେକର୍ଡିଂ ବା କାଷ୍ଟିଂ ଆରମ୍ଭ କରିବେ?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"ପୁଣି ଦେଖାନ୍ତୁ ନାହିଁ"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"ସମସ୍ତ ଖାଲି କରନ୍ତୁ"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"ପରିଚାଳନା କରନ୍ତୁ"</string>
@@ -667,12 +665,10 @@
<string name="inline_keep_showing_app" msgid="4393429060390649757">"ଏହି ଆପ୍‌ରୁ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକୁ ଦେଖାଇବା ଜାରି ରଖିବେ?"</string>
<string name="notification_silence_title" msgid="8608090968400832335">"ନୀରବ"</string>
<string name="notification_alert_title" msgid="7629202599338071971">"ଆଲର୍ଟ କରିବା"</string>
- <!-- no translation found for notification_bubble_title (8330481035191903164) -->
- <skip />
+ <string name="notification_bubble_title" msgid="8330481035191903164">"ବବଲ୍"</string>
<string name="notification_channel_summary_low" msgid="7300447764759926720">"ବିନା ସାଉଣ୍ଡ କିମ୍ବା ଭାଇବ୍ରେସନ୍‌ରେ ଆପଣଙ୍କୁ ଫୋକସ୍ କରିବାରେ ସାହାଯ୍ୟ କରେ।"</string>
<string name="notification_channel_summary_default" msgid="3539949463907902037">"ସାଉଣ୍ଡ କିମ୍ବା ଭାଇବ୍ରେସନ୍ ମାଧ୍ୟମରେ ଆପଣଙ୍କର ଧ୍ୟାନ ଆକର୍ଷିତ କରିଥାଏ।"</string>
- <!-- no translation found for notification_channel_summary_bubble (7235935211580860537) -->
- <skip />
+ <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ଏହି ବିଷୟବସ୍ତୁ ପାଇଁ ଏକ ଭାସମାନ ସର୍ଟକଟ୍ ସହ ଆପଣଙ୍କର ଧ୍ୟାନ ଦିଅନ୍ତୁ।"</string>
<string name="notification_unblockable_desc" msgid="2073030886006190804">"ଏହି ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ପରିବର୍ତ୍ତନ କରିହେବ ନାହିଁ।"</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"ଏଠାରେ ଏହି ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକର ଗ୍ରୁପ୍ କନଫ୍ୟୁଗର୍ କରାଯାଇପାରିବ ନାହିଁ"</string>
<string name="notification_delegate_header" msgid="1264510071031479920">"ବିଜ୍ଞପ୍ତି ପ୍ରକ୍ସୀ ହୋଇଛି"</string>
@@ -767,7 +763,7 @@
<string name="data_saver" msgid="3484013368530820763">"ଡାଟା ସେଭର୍‍"</string>
<string name="accessibility_data_saver_on" msgid="5394743820189757731">"ଡାଟା ସେଭର୍‌ ଅନ୍‌ ଅଛି"</string>
<string name="accessibility_data_saver_off" msgid="58339669022107171">"ଡାଟା ସେଭର୍‍ ଅଫ୍ ଅଛି"</string>
- <string name="switch_bar_on" msgid="1770868129120096114">"ଅନ୍"</string>
+ <string name="switch_bar_on" msgid="1770868129120096114">"ଚାଲୁ"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"ବନ୍ଦ"</string>
<string name="nav_bar" msgid="4642708685386136807">"ନାଭିଗେଶନ୍ ବାର୍‍"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"ଲେଆଉଟ୍"</string>
@@ -788,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"କୀ\'ବୋର୍ଡ ବଦଳକାରୀ"</string>
<string name="save" msgid="3392754183673848006">"ସେଭ୍‌ କରନ୍ତୁ"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"ରିସେଟ୍ କରନ୍ତୁ"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"ବଟନ୍‌ର ମୋଟେଇ ଆଡ୍‌ଜଷ୍ଟ କରନ୍ତୁ"</string>
<string name="clipboard" msgid="8517342737534284617">"କ୍ଲିପ୍‌ବୋର୍ଡ"</string>
<string name="accessibility_key" msgid="3471162841552818281">"କଷ୍ଟମ୍‍ ନାଭିଗେଶନ୍ ବଟନ୍‍"</string>
@@ -885,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"ଡାହାଣ"</string>
<string name="tuner_menu" msgid="363690665924769420">"ମେନୁ"</string>
<string name="tuner_app" msgid="6949280415826686972">"<xliff:g id="APP">%1$s</xliff:g> ଆପ୍‍"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"ଆଲର୍ଟଗୁଡ଼ିକ"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"ବ୍ୟାଟେରୀ"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"ସ୍କ୍ରୀନଶଟ୍‍"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"ସାଧାରଣ ମେସେଜ୍"</string>
@@ -896,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> ଚାଲୁଛି"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"ଇନ୍‍ଷ୍ଟଲ୍‍ ନହୋଇ ଆପ୍‍ ଖୋଲିଛି।"</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"ଇନ୍‍ଷ୍ଟଲ୍‍ ନହୋଇ ଆପ୍‍ ଖୋଲିଛି। ଅଧିକ ଜାଣିବା ପାଇଁ ଟାପ୍‍ କରନ୍ତୁ।"</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"ଆପ୍ ସୂଚନା"</string>
<string name="go_to_web" msgid="636673528981366511">"ବ୍ରାଉଜର୍‌କୁ ଯାଆନ୍ତୁ"</string>
<string name="mobile_data" msgid="4564407557775397216">"ମୋବାଇଲ୍‌ ଡାଟା"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -931,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"ସେଟିଙ୍ଗ"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"ବୁଝିଲି"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"SysUI ହିପ୍ ଡମ୍ପ୍ କରନ୍ତୁ"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> ଆପଣଙ୍କ <xliff:g id="TYPES_LIST">%2$s</xliff:g> ବ୍ୟବହାର କରୁଛନ୍ତି।"</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"ଆପ୍ଲିକେସନ୍‍ଗୁଡିକ ଆପଣଙ୍କ <xliff:g id="TYPES_LIST">%s</xliff:g> ବ୍ୟବହାର କରୁଛନ୍ତି।"</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" ଏବଂ "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"କ୍ୟାମେରା"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"ଲୋକେସନ୍‍"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"ମାଇକ୍ରୋଫୋନ୍"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"ସେନ୍ସର୍‍ଗୁଡ଼ିକ ବନ୍ଦ ଅଛି"</string>
<string name="device_services" msgid="1549944177856658705">"ଡିଭାଇସ୍‍ ସେବାଗୁଡିକ"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"କୌଣସି ଶୀର୍ଷକ ନାହିଁ"</string>
@@ -960,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"ସିଷ୍ଟମ୍ ନାଭିଗେସନ୍ ଅପ୍‌ଡେଟ୍ ହୋଇଛି। ପରିବର୍ତ୍ତନ କରିବା ପାଇଁ, ସେଟିଂସ୍‌କୁ ଯାଆନ୍ତୁ।"</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"ସିଷ୍ଟମ୍ ନାଭିଗେସନ୍ ଅପ୍‌ଡେଟ୍ କରିବା ପାଇଁ ସେଟିଂସ୍‍କୁ ଯାଆନ୍ତୁ"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"ଷ୍ଟାଣ୍ଡବାଏ"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"ମ୍ୟାଗ୍ନିଫିକେସନ୍ ଓଭର୍‌ଲେ ୱିଣ୍ଡୋ"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"ମ୍ୟାଗ୍ନିଫିକେସନ୍ ୱିଣ୍ଡୋ"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"ମ୍ୟାଗ୍ନିଫିକେସନ୍ ୱିଣ୍ଡୋ ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-or/strings_tv.xml b/packages/SystemUI/res/values-or/strings_tv.xml
index bc5660a82732..4593d6ad8c6c 100644
--- a/packages/SystemUI/res/values-or/strings_tv.xml
+++ b/packages/SystemUI/res/values-or/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(କୌଣସି ଟାଇଟଲ୍‍ ପ୍ରୋଗ୍ରାମ୍‍ ନାହିଁ)"</string>
<string name="pip_close" msgid="5775212044472849930">"PIP ବନ୍ଦ କରନ୍ତୁ"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"ପୂର୍ଣ୍ଣ ସ୍କ୍ରୀନ୍‍"</string>
+ <string name="mic_active" msgid="5766614241012047024">"ମାଇକ୍ରୋଫୋନ୍ ସକ୍ରିୟ"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s ଆପଣଙ୍କର ମାଇକ୍ରୋଫୋନ୍‌କୁ ଆକ୍ସେସ୍ କରିଛି"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index cce1df3f726e..6e1f23060614 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"ਹੋਰ ਜਾਣੋ"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"ਸਕ੍ਰੀਨ ਭਰਨ ਲਈ ਜ਼ੂਮ ਕਰੋ"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"ਸਕ੍ਰੀਨ ਭਰਨ ਲਈ ਸਟ੍ਰੈਚ ਕਰੋ"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"ਸਕ੍ਰੀਨਸ਼ਾਟ"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਸੁਰੱਖਿਅਤ ਕਰ ਰਿਹਾ ਹੈ…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਸੁਰੱਖਿਅਤ ਕਰ ਰਿਹਾ ਹੈ…"</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਰੱਖਿਅਤ ਕੀਤਾ ਗਿਆ"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"ਫ਼ੋਨ ਖੋਲ੍ਹੋ"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"ਅਵਾਜ਼ੀ ਸਹਾਇਕ ਖੋਲ੍ਹੋ"</string>
<string name="camera_label" msgid="8253821920931143699">"ਕੈਮਰਾ ਖੋਲ੍ਹੋ"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"ਰੱਦ ਕਰੋ"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"ਪੁਸ਼ਟੀ ਕਰੋ"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"ਪ੍ਰਮਾਣੀਕਰਨ ਰੱਦ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
@@ -323,7 +321,7 @@
<string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"ਸੁਣਨ ਦੇ ਸਾਧਨ"</string>
<string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"ਚਾਲੂ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…"</string>
<string name="quick_settings_brightness_label" msgid="680259653088849563">"ਚਮਕ"</string>
- <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"ਆਟੋ-ਰੋਟੇਟ"</string>
+ <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"ਸਵੈ-ਘੁੰਮਾਓ"</string>
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"ਸਕ੍ਰੀਨ ਨੂੰ ਆਪਣੇ ਆਪ ਘੁੰਮਾਓ"</string>
<string name="accessibility_quick_settings_rotation_value" msgid="2916484894750819251">"<xliff:g id="ID_1">%s</xliff:g> ਮੋਡ"</string>
<string name="quick_settings_rotation_locked_label" msgid="4420863550666310319">"ਰੋਟੇਸ਼ਨ ਲਾਕ ਕੀਤੀ"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"<xliff:g id="TIME">%s</xliff:g> ਵਜੇ ਚਾਲੂ"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g> ਤੱਕ"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"ਗੂੜ੍ਹਾ ਥੀਮ"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"ਗੂੜ੍ਹਾ ਥੀਮ\nਬੈਟਰੀ ਸੇਵਰ"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"ਬੈਟਰੀ ਸੇਵਰ"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"ਸੂਰਜ ਛਿਪਣ \'ਤੇ ਚਾਲੂ"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"ਸੂਰਜ ਚੜ੍ਹਨ ਤੱਕ"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC ਨੂੰ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ ਹੈ"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ਨੂੰ ਯੋਗ ਬਣਾਇਆ ਗਿਆ ਹੈ"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"ਖੋਲ੍ਹਣ ਲਈ ਦੁਬਾਰਾ ਟੈਪ ਕਰੋ"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"ਖੋਲ੍ਹਣ ਲਈ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ"</string>
<string name="keyguard_retry" msgid="886802522584053523">"ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰਨ ਲਈ ਉੱਤੇ ਵੱਲ ਸਵਾਈਪ ਕਰੋ"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"ਇਸ ਡੀਵਾਈਸ ਦਾ ਪ੍ਰਬੰਧਨ ਤੁਹਾਡੇ ਸੰਗਠਨ ਵੱਲੋਂ ਕੀਤਾ ਜਾਂਦਾ ਹੈ"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"ਇਹ ਡੀਵਾਈਸ <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> ਵੱਲੋਂ ਪ੍ਰਬੰਧਿਤ ਕੀਤਾ ਗਿਆ ਹੈ"</string>
<string name="phone_hint" msgid="6682125338461375925">"ਫ਼ੋਨ ਲਈ ਪ੍ਰਤੀਕ ਤੋਂ ਸਵਾਈਪ ਕਰੋ"</string>
@@ -467,13 +463,15 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"ਬੈਟਰੀ ਸੇਵਰ ਚਾਲੂ ਹੈ"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"ਪ੍ਰਦਰਸ਼ਨ ਅਤੇ ਪਿਛੋਕੜ ਡਾਟਾ ਘੱਟ ਕਰਦਾ ਹੈ"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"ਬੈਟਰੀ ਸੇਵਰ ਬੰਦ ਕਰੋ"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"ਰਿਕਾਰਡਿੰਗ ਜਾਂ ਕਾਸਟ ਕਰਨ ਵੇਲੇ, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ਐਪ ਸਕ੍ਰੀਨ \'ਤੇ ਦਿਸਣ ਜਾਂ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਤੋਂ ਚੱਲਣ ਵਾਲੀ ਕੋਈ ਵੀ ਸੰਵੇਦਨਸ਼ੀਲ ਜਾਣਕਾਰੀ ਨੂੰ ਕੈਪਚਰ ਕਰ ਸਕਦੀ ਹੈ, ਜਿਸ ਵਿੱਚ ਆਡੀਓ, ਪਾਸਵਰਡਾਂ, ਭੁਗਤਾਨ ਜਾਣਕਾਰੀ, ਫ਼ੋਟੋਆਂ ਅਤੇ ਸੁਨੇਹਿਆਂ ਵਰਗੀ ਸੰਵੇਦਨਸ਼ੀਲ ਜਾਣਕਾਰੀ ਸ਼ਾਮਲ ਹੈ।"</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"ਰਿਕਾਰਡਿੰਗ ਜਾਂ ਕਾਸਟ ਕਰਨ ਵੇਲੇ, ਇਹ ਫੰਕਸ਼ਨ ਮੁਹੱਈਆ ਕਰਵਾਉਣ ਵਾਲੀ ਸੇਵਾ ਸਕ੍ਰੀਨ \'ਤੇ ਦਿਸਣ ਜਾਂ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਤੋਂ ਚੱਲਣ ਵਾਲੀ ਕੋਈ ਵੀ ਸੰਵੇਦਨਸ਼ੀਲ ਜਾਣਕਾਰੀ ਨੂੰ ਕੈਪਚਰ ਕਰ ਸਕਦੀ ਹੈ, ਜਿਸ ਵਿੱਚ ਆਡੀਓ, ਪਾਸਵਰਡਾਂ, ਭੁਗਤਾਨ ਜਾਣਕਾਰੀ, ਫ਼ੋਟੋਆਂ ਅਤੇ ਸੁਨੇਹਿਆਂ ਵਰਗੀ ਸੰਵੇਦਨਸ਼ੀਲ ਜਾਣਕਾਰੀ ਸ਼ਾਮਲ ਹੈ।"</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"ਕਾਸਟ ਕਰਨ/ਰਿਕਾਰਡ ਕਰਨ ਵੇਲੇ ਸੰਵੇਦਨਸ਼ੀਲ ਜਾਣਕਾਰੀ ਦਾ ਖੁਲਾਸਾ ਹੋ ਜਾਣਾ"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ਕੋਲ ਬਾਕੀ ਸਾਰੀ ਜਾਣਕਾਰੀ ਤੱਕ ਪਹੁੰਚ ਹੋਵੇਗੀ ਜੋ ਕਿ ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ \'ਤੇ ਦਿਖਣਯੋਗ ਹੈ ਜਾਂ ਰਿਕਾਰਡਿੰਗ ਜਾਂ ਕਾਸਟ ਕਰਨ ਵੇਲੇ ਤੁਹਾਡੇ ਡੀਵਾਈਸ \'ਤੇ ਚਲਾਈ ਜਾਂਦੀ ਹੈ। ਇਸ ਵਿੱਚ ਪਾਸਵਰਡ, ਭੁਗਤਾਨ ਵੇਰਵੇ, ਫ਼ੋਟੋਆਂ, ਸੁਨੇਹੇ ਅਤੇ ਤੁਹਾਡੇ ਵੱਲੋਂ ਚਲਾਏ ਆਡੀਓ ਦੀ ਜਾਣਕਾਰੀ ਸ਼ਾਮਲ ਹੁੰਦੀ ਹੈ।"</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"ਇਸ ਫੰਕਸ਼ਨ ਦੇ ਸੇਵਾ ਪ੍ਰਦਾਨਕ ਕੋਲ ਬਾਕੀ ਸਾਰੀ ਜਾਣਕਾਰੀ ਤੱਕ ਪਹੁੰਚ ਹੋਵੇਗੀ ਜੋ ਕਿ ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ \'ਤੇ ਦਿਖਣਯੋਗ ਹੁੰਦੀ ਹੈ ਜਾਂ ਰਿਕਾਰਡਿੰਗ ਜਾਂ ਕਾਸਟ ਕਰਨ ਵੇਲੇ ਤੁਹਾਡੇ ਡੀਵਾਈਸ \'ਤੇ ਚਲਾਈ ਜਾਂਦੀ ਹੈ। ਇਸ ਵਿੱਚ ਪਾਸਵਰਡ, ਭੁਗਤਾਨ ਵੇਰਵੇ, ਫ਼ੋਟੋਆਂ, ਸੁਨੇਹੇ ਅਤੇ ਤੁਹਾਡੇ ਵੱਲੋਂ ਚਲਾਏ ਆਡੀਓ ਦੀ ਜਾਣਕਾਰੀ ਸ਼ਾਮਲ ਹੁੰਦੀ ਹੈ।"</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ਨਾਲ ਰਿਕਾਰਡਿੰਗ ਜਾਂ ਕਾਸਟ ਕਰਨਾ ਸ਼ੁਰੂ ਕਰਨਾ ਹੈ?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"ਦੁਬਾਰਾ ਨਾ ਦਿਖਾਓ"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"ਸਭ ਕਲੀਅਰ ਕਰੋ"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"ਪ੍ਰਬੰਧਨ ਕਰੋ"</string>
- <string name="notification_section_header_gentle" msgid="3044910806569985386">"ਖਾਮੋਸ਼ ਸੂਚਨਾਵਾਂ"</string>
+ <string name="notification_section_header_gentle" msgid="3044910806569985386">"ਸ਼ਾਂਤ ਸੂਚਨਾਵਾਂ"</string>
<string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"ਸਾਰੀਆਂ ਖਾਮੋਸ਼ ਸੂਚਨਾਵਾਂ ਕਲੀਅਰ ਕਰੋ"</string>
<string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"\'ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ\' ਵੱਲੋਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਰੋਕਿਆ ਗਿਆ"</string>
<string name="media_projection_action_text" msgid="3634906766918186440">"ਹੁਣ ਚਾਲੂ ਕਰੋ"</string>
@@ -667,12 +665,10 @@
<string name="inline_keep_showing_app" msgid="4393429060390649757">"ਕੀ ਇਸ ਐਪ ਤੋਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਦਿਖਾਉਣਾ ਜਾਰੀ ਰੱਖਣਾ ਹੈ?"</string>
<string name="notification_silence_title" msgid="8608090968400832335">"ਸ਼ਾਂਤ"</string>
<string name="notification_alert_title" msgid="7629202599338071971">"ਸੁਚੇਤਨਾ"</string>
- <!-- no translation found for notification_bubble_title (8330481035191903164) -->
- <skip />
+ <string name="notification_bubble_title" msgid="8330481035191903164">"ਬੁਲਬੁਲਾ"</string>
<string name="notification_channel_summary_low" msgid="7300447764759926720">"ਤੁਹਾਨੂੰ ਬਿਨਾਂ ਧੁਨੀ ਅਤੇ ਥਰਥਰਾਹਟ ਦੇ ਫੋਕਸ ਕਰਨ ਵਿੱਚ ਮਦਦ ਕਰਦਾ ਹੈ।"</string>
<string name="notification_channel_summary_default" msgid="3539949463907902037">"ਧੁਨੀ ਅਤੇ ਥਰਥਰਾਹਟ ਨਾਲ ਤੁਹਾਡਾ ਧਿਆਨ ਖਿੱਚਦੀ ਹੈ।"</string>
- <!-- no translation found for notification_channel_summary_bubble (7235935211580860537) -->
- <skip />
+ <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ਇਸ ਸਮੱਗਰੀ ਦੇ ਅਸਥਿਰ ਸ਼ਾਰਟਕੱਟ ਨਾਲ ਆਪਣਾ ਧਿਆਨ ਕੇਂਦਰਿਤ ਰੱਖੋ।"</string>
<string name="notification_unblockable_desc" msgid="2073030886006190804">"ਇਹਨਾਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਸੋਧਿਆ ਨਹੀਂ ਜਾ ਸਕਦਾ।"</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"ਇਹ ਸੂਚਨਾਵਾਂ ਦਾ ਗਰੁੱਪ ਇੱਥੇ ਸੰਰੂਪਿਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string>
<string name="notification_delegate_header" msgid="1264510071031479920">"ਇੱਕ ਐਪ ਦੀ ਥਾਂ \'ਤੇ ਦੂਜੀ ਐਪ ਰਾਹੀਂ ਦਿੱਤੀ ਗਈ ਸੂਚਨਾ"</string>
@@ -788,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"ਕੀ-ਬੋਰਡ ਸਵਿੱਚਰ"</string>
<string name="save" msgid="3392754183673848006">"ਰੱਖਿਅਤ ਕਰੋ"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"ਰੀਸੈੱਟ ਕਰੋ"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"ਬਟਨ ਚੁੜਾਈ ਵਿਵਸਥਿਤ ਕਰੋ"</string>
<string name="clipboard" msgid="8517342737534284617">"ਕਲਿੱਪਬੋਰਡ"</string>
<string name="accessibility_key" msgid="3471162841552818281">"ਵਿਉਂਂਤੀ ਨੈਵੀਗੇਟ ਬਟਨ"</string>
@@ -885,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"ਸੱਜਾ"</string>
<string name="tuner_menu" msgid="363690665924769420">"ਮੀਨੂ"</string>
<string name="tuner_app" msgid="6949280415826686972">"<xliff:g id="APP">%1$s</xliff:g> ਐਪ"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"ਸੁਚੇਤਨਾਵਾਂ"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"ਬੈਟਰੀ"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"ਸਕ੍ਰੀਨਸ਼ਾਟ"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"ਆਮ ਸੁਨੇਹੇ"</string>
@@ -896,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> ਚੱਲ ਰਹੀ ਹੈ"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"ਸਥਾਪਤ ਕੀਤੇ ਬਿਨਾਂ ਐਪ ਖੋਲ੍ਹੀ ਗਈ।"</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"ਸਥਾਪਤ ਕੀਤੇ ਬਿਨਾਂ ਐਪ ਖੋਲ੍ਹੀ ਗਈ। ਹੋਰ ਜਾਣਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"ਐਪ ਜਾਣਕਾਰੀ"</string>
<string name="go_to_web" msgid="636673528981366511">"ਬ੍ਰਾਊਜ਼ਰ \'ਤੇ ਜਾਓ"</string>
<string name="mobile_data" msgid="4564407557775397216">"ਮੋਬਾਈਲ ਡਾਟਾ"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -931,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"ਸੈਟਿੰਗਾਂ"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"ਸਮਝ ਲਿਆ"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"SysUI ਹੀਪ ਡੰਪ ਕਰੋ"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> ਤੁਹਾਡੇ <xliff:g id="TYPES_LIST">%2$s</xliff:g> ਦੀ ਵਰਤੋਂ ਕਰ ਰਹੀ ਹੈ।"</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"ਐਪਲੀਕੇਸ਼ਨਾਂ ਤੁਹਾਡੇ <xliff:g id="TYPES_LIST">%s</xliff:g> ਦੀ ਵਰਤੋਂ ਕਰ ਰਹੀਆਂ ਹਨ।"</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" ਅਤੇ "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"ਕੈਮਰਾ"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"ਟਿਕਾਣਾ"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"ਮਾਈਕ੍ਰੋਫ਼ੋਨ"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"ਸੈਂਸਰ ਬੰਦ ਕਰੋ"</string>
<string name="device_services" msgid="1549944177856658705">"ਡੀਵਾਈਸ ਸੇਵਾਵਾਂ"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"ਕੋਈ ਸਿਰਲੇਖ ਨਹੀਂ"</string>
@@ -960,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"ਸਿਸਟਮ ਨੈਵੀਗੇਸ਼ਨ ਅੱਪਡੇਟ ਹੋ ਗਿਆ। ਤਬਦੀਲੀਆਂ ਕਰਨ ਲਈ, ਸੈਟਿੰਗਾਂ \'ਤੇ ਜਾਓ।"</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"ਸਿਸਟਮ ਨੈਵੀਗੇਸ਼ਨ ਨੂੰ ਅੱਪਡੇਟ ਕਰਨ ਲਈ ਸੈਟਿੰਗਾਂ \'ਤੇ ਜਾਓ"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"ਸਟੈਂਡਬਾਈ"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"ਵੱਡਦਰਸ਼ੀਕਰਨ ਓਵਰਲੇ Window"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"ਵੱਡਦਰਸ਼ੀਕਰਨ Window"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"ਵੱਡਦਰਸ਼ੀਕਰਨ Window ਦੇ ਕੰਟਰੋਲ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pa/strings_tv.xml b/packages/SystemUI/res/values-pa/strings_tv.xml
index 42deae700fa4..fd567698088b 100644
--- a/packages/SystemUI/res/values-pa/strings_tv.xml
+++ b/packages/SystemUI/res/values-pa/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(ਸਿਰਲੇਖ-ਰਹਿਤ ਪ੍ਰੋਗਰਾਮ)"</string>
<string name="pip_close" msgid="5775212044472849930">"PIP ਬੰਦ ਕਰੋ"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"ਪੂਰੀ ਸਕ੍ਰੀਨ"</string>
+ <string name="mic_active" msgid="5766614241012047024">"ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਕਿਰਿਆਸ਼ੀਲ"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s ਨੇ ਤੁਹਾਡੇ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਤੱਕ ਪਹੁੰਚ ਕੀਤੀ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 0a9c1745e510..d3f5ae24dfd1 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Więcej informacji"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Powiększ, aby wypełnić ekran"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Rozciągnij, aby wypełnić ekran"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Zrzut ekranu"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Zapisywanie zrzutu ekranu..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Zapisywanie zrzutu ekranu..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Zrzut ekranu został zapisany"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"otwórz telefon"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"otwórz pomoc głosową"</string>
<string name="camera_label" msgid="8253821920931143699">"otwórz aparat"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Anuluj"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Potwierdź"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Spróbuj jeszcze raz"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Kliknij, by anulować uwierzytelnianie"</string>
@@ -285,7 +283,7 @@
<string name="data_usage_disabled_dialog_title" msgid="9131615296036724838">"Transmisja danych została wstrzymana"</string>
<string name="data_usage_disabled_dialog" msgid="7933201635215099780">"Osiągnięto ustawiony limit danych. Nie korzystasz już z mobilnej transmisji danych.\n\nJeśli włączysz ją ponownie, może zostać naliczona opłata za użycie danych."</string>
<string name="data_usage_disabled_dialog_enable" msgid="2796648546086408937">"Wznów"</string>
- <string name="gps_notification_searching_text" msgid="231304732649348313">"Wyszukiwanie sygnału GPS"</string>
+ <string name="gps_notification_searching_text" msgid="231304732649348313">"Szukam GPS"</string>
<string name="gps_notification_found_text" msgid="3145873880174658526">"Lokalizacja z GPSa"</string>
<string name="accessibility_location_active" msgid="2845747916764660369">"Prośby o lokalizację są aktywne"</string>
<string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Wyłączenie czujników aktywne"</string>
@@ -391,7 +389,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Włącz o <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Tryb ciemny"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Ciemny motyw\nOszczędzanie baterii"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Oszczędzanie baterii"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Włącz o zachodzie"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Do wschodu słońca"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"Komunikacja NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"Komunikacja NFC jest wyłączona"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"Komunikacja NFC jest włączona"</string>
@@ -416,10 +416,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Kliknij ponownie, by otworzyć"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Przesuń w górę, by otworzyć"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Przesuń w górę, by spróbować ponownie"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Tym urządzeniem zarządza Twoja organizacja"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Tym urządzeniem zarządza <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Aby włączyć telefon, przesuń palcem od ikony"</string>
@@ -473,9 +469,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Oszczędzanie baterii jest włączone"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Zmniejsza wydajność i ogranicza dane w tle"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Wyłącz Oszczędzanie baterii"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Podczas nagrywania lub przesyłania aplikacja <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> może rejestrować wszelkie informacje poufne wyświetlane na ekranie lub odtwarzane na urządzeniu, takie jak dźwięki czy podawane hasła, informacje o płatnościach, zdjęcia i wiadomości."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Podczas nagrywania lub przesyłania usługa udostępniająca tę funkcję może rejestrować wszelkie informacje poufne wyświetlane na ekranie lub odtwarzane na urządzeniu takie jak dźwięki czy podawane hasła, informacje o płatnościach, zdjęcia i wiadomości."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Ujawnianie poufnych informacji podczas przesyłania/nagrywania"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"Podczas nagrywania i przesyłania aplikacja <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> będzie mieć dostęp do wszystkich informacji widocznych na ekranie lub odtwarzanych na urządzeniu. Dotyczy to m.in. haseł, szczegółów płatności, zdjęć, wiadomości i odtwarzanych dźwięków."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Podczas nagrywania i przesyłania usługa udostępniająca tę funkcję będzie miała dostęp do wszystkich informacji widocznych na ekranie lub odtwarzanych na urządzeniu. Dotyczy to m.in. haseł, szczegółów płatności, zdjęć, wiadomości i odtwarzanych dźwięków."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Rozpocząć nagrywanie lub przesyłanie za pomocą aplikacji <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Nie pokazuj ponownie"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Usuń wszystkie"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Zarządzaj"</string>
@@ -796,8 +794,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Przełączanie klawiatury"</string>
<string name="save" msgid="3392754183673848006">"Zapisz"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Resetuj"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Regulacja szerokości przycisku"</string>
<string name="clipboard" msgid="8517342737534284617">"Schowek"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Niestandardowy przycisk nawigacji"</string>
@@ -893,8 +890,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Strzałka w prawo"</string>
<string name="tuner_menu" msgid="363690665924769420">"Menu"</string>
<string name="tuner_app" msgid="6949280415826686972">"Aplikacja <xliff:g id="APP">%1$s</xliff:g>"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Alerty"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Bateria"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Zrzuty ekranu"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Wiadomości"</string>
@@ -904,8 +900,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"Aplikacja <xliff:g id="APP">%1$s</xliff:g> działa"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Aplikacja została otwarta bez zainstalowania."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Aplikacja została otwarta bez zainstalowania. Kliknij, by dowiedzieć się więcej."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"O aplikacji"</string>
<string name="go_to_web" msgid="636673528981366511">"Otwórz przeglądarkę"</string>
<string name="mobile_data" msgid="4564407557775397216">"Dane mobilne"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -939,13 +934,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Ustawienia"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"OK"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Zrzut stosu SysUI"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"Aplikacja <xliff:g id="APP">%1$s</xliff:g> używa: <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplikacje używają: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" i "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"aparat"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"lokalizacja"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Wyłącz czujniki"</string>
<string name="device_services" msgid="1549944177856658705">"Usługi urządzenia"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Bez tytułu"</string>
@@ -968,4 +956,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Nawigacja w systemie została zaktualizowana. Aby wprowadzić zmiany, otwórz Ustawienia."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Otwórz Ustawienia, by zaktualizować nawigację w systemie"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Tryb gotowości"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Okno nakładki powiększenia"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Okno powiększenia"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Elementy sterujące okna powiększenia"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pl/strings_tv.xml b/packages/SystemUI/res/values-pl/strings_tv.xml
index f2e459dc117c..5921aa7a9963 100644
--- a/packages/SystemUI/res/values-pl/strings_tv.xml
+++ b/packages/SystemUI/res/values-pl/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Program bez tytułu)"</string>
<string name="pip_close" msgid="5775212044472849930">"Zamknij PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Pełny ekran"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Mikrofon aktywny"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"Aplikacja %1$s korzystała z mikrofonu"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 9459e81a8826..4d4a607ac453 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Saiba mais"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Zoom p/ preencher a tela"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Ampliar p/ preencher tela"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Capturar tela"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Salvando captura de tela..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Salvando captura de tela..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Captura de tela salva"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"abrir telefone"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"abrir assistência de voz"</string>
<string name="camera_label" msgid="8253821920931143699">"abrir câmera"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Cancelar"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Confirmar"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Tentar novamente"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Toque para cancelar a autenticação"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Ativado às <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Até <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Tema escuro"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Tema escuro\nEconomia de bateria"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Economia de bateria"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Ativ. ao pôr do sol"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Até o nascer do sol"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"A NFC está desativada"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"A NFC está ativada"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Toque novamente para abrir"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Deslize para cima para abrir"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Deslize para cima para tentar novamente"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Este dispositivo é gerenciado pela sua organização"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Este dispositivo é gerenciado por <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Deslize a partir do ícone do telefone"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Economia de bateria ativada"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Reduz o desempenho e os dados em segundo plano"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Desativar a Economia de bateria"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Ao gravar ou transmitir, o app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> pode capturar informações confidenciais exibidas na tela ou acessadas pelo dispositivo, incluindo áudio, senhas, informações de pagamento, fotos e mensagens."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Ao gravar ou transmitir, o serviço relacionado a esta função pode capturar informações confidenciais exibidas na tela ou acessadas pelo dispositivo, incluindo áudio, senhas, informações de pagamento, fotos e mensagens."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Exposição de informações confidenciais durante transmissão/gravação"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"O app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> terá acesso a todas as informações visíveis na tela ou tocadas no dispositivo, como gravação ou transmissão Isso inclui informações como senhas, detalhes de pagamento, fotos, mensagens e áudio que você toca."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"O serviço que oferece essa função terá acesso a todas as informações visíveis na tela ou tocadas no dispositivo durante uma gravação ou transmissão. Isso inclui informações como senhas, detalhes de pagamento, fotos, mensagens e áudio que você toca."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Iniciar gravação ou transmissão com o app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Não mostrar novamente"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Limpar tudo"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Gerenciar"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Alternador de teclado"</string>
<string name="save" msgid="3392754183673848006">"Salvar"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Redefinir"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Ajustar largura do botão"</string>
<string name="clipboard" msgid="8517342737534284617">"Prancheta"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Botão de navegação personalizado"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Para a direita"</string>
<string name="tuner_menu" msgid="363690665924769420">"Menu"</string>
<string name="tuner_app" msgid="6949280415826686972">"App <xliff:g id="APP">%1$s</xliff:g>"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Alertas"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Bateria"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Capturas de tela"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Mensagens gerais"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> em execução"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"O app é aberto sem precisar ser instalado."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"O app é aberto sem precisar ser instalado. Toque para saber mais."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Informações do app"</string>
<string name="go_to_web" msgid="636673528981366511">"Abrir o navegador"</string>
<string name="mobile_data" msgid="4564407557775397216">"Dados móveis"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Configurações"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Ok"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Despejar heap SysUI"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"O app <xliff:g id="APP">%1$s</xliff:g> está usando <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplicativos estão usando <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" e "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"câmera"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"localização"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"microfone"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensores desativados"</string>
<string name="device_services" msgid="1549944177856658705">"Serviços do dispositivo"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Sem título"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Navegação no sistema atualizada. Se quiser alterá-la, acesse as configurações."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Acesse as configurações para atualizar a navegação no sistema"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Em espera"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Janela de sobreposição de ampliação"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Janela de ampliação"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Controles da janela de ampliação"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings_tv.xml b/packages/SystemUI/res/values-pt-rBR/strings_tv.xml
index f38278c0bcbe..a0cbeafb9c9a 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings_tv.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(programa sem título)"</string>
<string name="pip_close" msgid="5775212044472849930">"Fechar PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Tela cheia"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Microfone ativado"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s acessou seu microfone"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index b235bda4c4bc..1f2315943bc4 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Saiba mais"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Zoom para preencher o ecrã"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Esticar p. caber em ec. int."</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Captura de ecrã"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"A guardar captura de ecrã..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"A guardar captura de ecrã..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Captura de ecrã guardada"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"abrir telemóvel"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"abrir assistente de voz"</string>
<string name="camera_label" msgid="8253821920931143699">"abrir câmara"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Cancelar"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Confirmar"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Tentar novamente"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Toque para cancelar a autenticação."</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Ativada à(s) <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Até à(s) <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Tema escuro"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Tema escuro\nPoupança de bateria"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Poupança de bateria"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Ativ. ao pôr do sol"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Até ao amanhecer"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"O NFC está desativado"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"O NFC está ativado"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Toque novamente para abrir"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Deslize rapidamente para cima para abrir"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Deslize rapidamente para cima para tentar novamente."</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Este dispositivo é gerido pela sua entidade"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Este dispositivo é gerido por <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Deslize rapid. a partir do ícone para aceder ao telemóvel"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Poupança de bateria ativada"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Reduz o desempenho e os dados de segundo plano"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Desativar a Poupança de bateria"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Durante a gravação ou a transmissão, a aplicação <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> pode capturar quaisquer informações confidenciais apresentadas no ecrã ou reproduzidas a partir do seu dispositivo, incluindo áudio, palavras-passe, informações de pagamento, fotos e mensagens."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Durante a gravação ou a transmissão, o serviço que fornece esta função pode capturar quaisquer informações confidenciais apresentadas no ecrã ou reproduzidas a partir do seu dispositivo, incluindo áudio, palavras-passe, informações de pagamento, fotos e mensagens."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Exposição de informações confidenciais durante a transmissão/gravação"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"A aplicação <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> terá acesso a todas as informações que estiverem visíveis no ecrã ou que forem reproduzidas a partir do dispositivo durante a gravação ou transmissão. Isto inclui informações como palavras-passe, detalhes de pagamentos, fotos, mensagens e áudio reproduzido."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"O serviço que fornece esta função terá acesso a todas as informações que estiverem visíveis no ecrã ou que forem reproduzidas a partir do dispositivo durante a gravação ou transmissão. Isto inclui informações como palavras-passe, detalhes de pagamentos, fotos, mensagens e áudio reproduzido."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Pretende começar a gravar ou a transmitir com a aplicação <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Não mostrar de novo"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Limpar tudo"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Gerir"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Comutador de teclado"</string>
<string name="save" msgid="3392754183673848006">"Guardar"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Repor"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Ajustar largura do botão"</string>
<string name="clipboard" msgid="8517342737534284617">"Área de transferência"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Botão de navegação personalizado"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Direita"</string>
<string name="tuner_menu" msgid="363690665924769420">"Menu"</string>
<string name="tuner_app" msgid="6949280415826686972">"Aplicação <xliff:g id="APP">%1$s</xliff:g>"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Alertas"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Bateria"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Capturas de ecrã"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Mensagens gerais"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> em execução"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"A aplicação é aberta sem ser instalada."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"A aplicação é aberta sem ser instalada. Toque para saber mais."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Info. da aplicação"</string>
<string name="go_to_web" msgid="636673528981366511">"Ir para o navegador"</string>
<string name="mobile_data" msgid="4564407557775397216">"Dados móveis"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Definições"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Compreendi"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Despejar pilha SysUI"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"A aplicação <xliff:g id="APP">%1$s</xliff:g> está a utilizar o(a) <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"As aplicações estão a utilizar o(a) <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" e "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"câmara"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"localização"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"microfone"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensores desativados"</string>
<string name="device_services" msgid="1549944177856658705">"Serviços do dispositivo"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Sem título"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"A navegação no sistema foi atualizada. Para efetuar alterações, aceda às Definições."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Aceda às Definições para atualizar a navegação no sistema."</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Modo de espera"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Janela de sobreposição da ampliação"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Janela de ampliação"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Controlos da janela de ampliação"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings_tv.xml b/packages/SystemUI/res/values-pt-rPT/strings_tv.xml
index 0b2317d4202b..65a6f03ede5a 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings_tv.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Sem título do programa)"</string>
<string name="pip_close" msgid="5775212044472849930">"Fechar PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Ecrã inteiro"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Microfone ativado"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s acedeu ao microfone"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 9459e81a8826..4d4a607ac453 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Saiba mais"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Zoom p/ preencher a tela"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Ampliar p/ preencher tela"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Capturar tela"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Salvando captura de tela..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Salvando captura de tela..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Captura de tela salva"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"abrir telefone"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"abrir assistência de voz"</string>
<string name="camera_label" msgid="8253821920931143699">"abrir câmera"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Cancelar"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Confirmar"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Tentar novamente"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Toque para cancelar a autenticação"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Ativado às <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Até <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Tema escuro"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Tema escuro\nEconomia de bateria"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Economia de bateria"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Ativ. ao pôr do sol"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Até o nascer do sol"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"A NFC está desativada"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"A NFC está ativada"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Toque novamente para abrir"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Deslize para cima para abrir"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Deslize para cima para tentar novamente"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Este dispositivo é gerenciado pela sua organização"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Este dispositivo é gerenciado por <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Deslize a partir do ícone do telefone"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Economia de bateria ativada"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Reduz o desempenho e os dados em segundo plano"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Desativar a Economia de bateria"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Ao gravar ou transmitir, o app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> pode capturar informações confidenciais exibidas na tela ou acessadas pelo dispositivo, incluindo áudio, senhas, informações de pagamento, fotos e mensagens."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Ao gravar ou transmitir, o serviço relacionado a esta função pode capturar informações confidenciais exibidas na tela ou acessadas pelo dispositivo, incluindo áudio, senhas, informações de pagamento, fotos e mensagens."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Exposição de informações confidenciais durante transmissão/gravação"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"O app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> terá acesso a todas as informações visíveis na tela ou tocadas no dispositivo, como gravação ou transmissão Isso inclui informações como senhas, detalhes de pagamento, fotos, mensagens e áudio que você toca."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"O serviço que oferece essa função terá acesso a todas as informações visíveis na tela ou tocadas no dispositivo durante uma gravação ou transmissão. Isso inclui informações como senhas, detalhes de pagamento, fotos, mensagens e áudio que você toca."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Iniciar gravação ou transmissão com o app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Não mostrar novamente"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Limpar tudo"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Gerenciar"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Alternador de teclado"</string>
<string name="save" msgid="3392754183673848006">"Salvar"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Redefinir"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Ajustar largura do botão"</string>
<string name="clipboard" msgid="8517342737534284617">"Prancheta"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Botão de navegação personalizado"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Para a direita"</string>
<string name="tuner_menu" msgid="363690665924769420">"Menu"</string>
<string name="tuner_app" msgid="6949280415826686972">"App <xliff:g id="APP">%1$s</xliff:g>"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Alertas"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Bateria"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Capturas de tela"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Mensagens gerais"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> em execução"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"O app é aberto sem precisar ser instalado."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"O app é aberto sem precisar ser instalado. Toque para saber mais."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Informações do app"</string>
<string name="go_to_web" msgid="636673528981366511">"Abrir o navegador"</string>
<string name="mobile_data" msgid="4564407557775397216">"Dados móveis"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Configurações"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Ok"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Despejar heap SysUI"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"O app <xliff:g id="APP">%1$s</xliff:g> está usando <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplicativos estão usando <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" e "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"câmera"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"localização"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"microfone"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensores desativados"</string>
<string name="device_services" msgid="1549944177856658705">"Serviços do dispositivo"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Sem título"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Navegação no sistema atualizada. Se quiser alterá-la, acesse as configurações."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Acesse as configurações para atualizar a navegação no sistema"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Em espera"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Janela de sobreposição de ampliação"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Janela de ampliação"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Controles da janela de ampliação"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt/strings_tv.xml b/packages/SystemUI/res/values-pt/strings_tv.xml
index f38278c0bcbe..a0cbeafb9c9a 100644
--- a/packages/SystemUI/res/values-pt/strings_tv.xml
+++ b/packages/SystemUI/res/values-pt/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(programa sem título)"</string>
<string name="pip_close" msgid="5775212044472849930">"Fechar PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Tela cheia"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Microfone ativado"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s acessou seu microfone"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index ea82ec373c67..63c2c0a54da9 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Mai multe"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Zoom pt. a umple ecranul"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Înt. pt. a umple ecranul"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Captură de ecran"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Se salv. captura de ecran..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Se salvează captura de ecran..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Captură de ecran salvată"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"deschideți telefonul"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"deschideți asistentul vocal"</string>
<string name="camera_label" msgid="8253821920931143699">"deschideți camera foto"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Anulați"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Confirmați"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Încercați din nou"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Atingeți pentru a anula autentificarea"</string>
@@ -389,7 +387,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Activată la <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Până la <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Temă întunecată"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Temă întunecată\nEconomisirea bateriei"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Economisire baterie"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Activată la apus"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Până la răsărit"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"Serviciul NFC este dezactivat"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"Serviciul NFC este activat"</string>
@@ -414,10 +414,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Atingeți din nou pentru a deschide"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Glisați în sus pentru a deschide"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Glisați pentru a încerca din nou"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Acest dispozitiv este gestionat de organizația dvs."</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Acest dispozitiv este gestionat de <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Glisați dinspre telefon"</string>
@@ -470,9 +466,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Economisire baterie activată"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Reduce performanța și datele de fundal"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Dezactivați economisirea bateriei"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"În timp ce înregistrați sau proiectați, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> poate captura toate informațiile sensibile care sunt afișate pe ecran sau redate pe dispozitiv, inclusiv informații sensibile precum conținutul audio, parolele, informațiile de plată, fotografiile și mesajele."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"În timp ce înregistrați sau proiectați, serviciul care oferă această funcție poate captura toate informațiile sensibile care sunt afișate pe ecran sau redate pe dispozitiv, inclusiv informații sensibile precum conținutul audio, parolele, informațiile de plată, fotografiile și mesajele."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Se expun informații sensibile în timpul proiectării/înregistrării"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> va avea acces la toate informațiile vizibile pe ecran sau redate pe dispozitiv în timp ce înregistrați sau proiectați. Între aceste informații se numără parole, detalii de plată, fotografii, mesaje și conținutul audio pe care îl redați."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Serviciul care oferă această funcție va avea acces la toate informațiile vizibile pe ecran sau redate pe dispozitiv în timp ce înregistrați sau proiectați. Între aceste informații se numără parole, detalii de plată, fotografii, mesaje și conținutul audio pe care îl redați."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Începeți să înregistrați sau să proiectați cu <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Nu se mai afișează"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Ștergeți toate notificările"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Gestionați"</string>
@@ -791,8 +789,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Comutator tastatură"</string>
<string name="save" msgid="3392754183673848006">"Salvați"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Resetați"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Ajustați lățimea butonului"</string>
<string name="clipboard" msgid="8517342737534284617">"Clipboard"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Buton personalizat pentru navigare"</string>
@@ -888,8 +885,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Dreapta"</string>
<string name="tuner_menu" msgid="363690665924769420">"Meniu"</string>
<string name="tuner_app" msgid="6949280415826686972">"Aplicația <xliff:g id="APP">%1$s</xliff:g>"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Alerte"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Baterie"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Capturi de ecran"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Mesaje generale"</string>
@@ -899,8 +895,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> rulează"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Aplicația a fost deschisă fără a fi instalată."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Aplicația a fost deschisă fără a fi instalată. Atingeți pentru a afla mai multe."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Informații aplicație"</string>
<string name="go_to_web" msgid="636673528981366511">"Accesați browserul"</string>
<string name="mobile_data" msgid="4564407557775397216">"Date mobile"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -934,13 +929,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Setări"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"OK"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Extrageți memoria SysUI"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> folosește <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplicațiile folosesc <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" și "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"cameră foto"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"locație"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"microfon"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Senzori dezactivați"</string>
<string name="device_services" msgid="1549944177856658705">"Servicii pentru dispozitiv"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Fără titlu"</string>
@@ -963,4 +951,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Navigarea în sistem a fost actualizată. Pentru a face modificări, accesați Setările."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Accesați Setările pentru a actualiza navigarea în sistem"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Standby"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Fereastra de suprapunere pentru mărire"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Fereastra de mărire"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Comenzi pentru fereastra de mărire"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ro/strings_tv.xml b/packages/SystemUI/res/values-ro/strings_tv.xml
index 79bd896abf24..1bfbd71fef9b 100644
--- a/packages/SystemUI/res/values-ro/strings_tv.xml
+++ b/packages/SystemUI/res/values-ro/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Program fără titlu)"</string>
<string name="pip_close" msgid="5775212044472849930">"Închideți PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Ecran complet"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Microfon activ"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s a accesat microfonul"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index fddb73525b37..2da136fa7a8a 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Подробнее"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Подогнать по размерам экрана"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Растянуть на весь экран"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Скриншот"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Сохранение..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Сохранение..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Скриншот сохранен"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"Открыть телефон."</string>
<string name="voice_assist_label" msgid="3725967093735929020">"включить аудиоподсказки"</string>
<string name="camera_label" msgid="8253821920931143699">"Открыть камеру."</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Отмена"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Подтвердить"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Повторить попытку"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Нажмите, чтобы отменить аутентификацию"</string>
@@ -391,7 +389,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Включить в <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"До <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Тёмная тема"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Тёмная тема\nРежим энергосбережения"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Режим энергосбер."</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Вкл. на закате"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"До рассвета"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"Модуль NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"Модуль NFC отключен"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"Модуль NFC включен"</string>
@@ -416,10 +416,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Нажмите ещё раз, чтобы открыть"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Проведите вверх, чтобы открыть"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Чтобы повторить попытку, проведите вверх"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Этим устройством управляет ваша организация"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Этим устройством управляет компания \"<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>\""</string>
<string name="phone_hint" msgid="6682125338461375925">"Телефон: проведите от значка"</string>
@@ -473,9 +469,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Режим энергосбережения включен"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Откл. фоновой передачи данных"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Отключить режим энергосбережения"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"При записи сообщений или трансляции экрана приложение <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> может получить доступ к конфиденциальной информации, которая отображается на экране или воспроизводится на устройстве, например к аудиозаписям, паролям, фото, сообщениям и платежным данным."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"При записи сообщений или трансляции экрана сервис может получить доступ к конфиденциальной информации, которая отображается на экране или воспроизводится на устройстве, например к аудиозаписям, паролям, фото, сообщениям и платежным данным."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Раскрытие личной информации при записи или трансляции"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"Во время записи или трансляции у приложения \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\" будет доступ ко всей информации, которая видна на экране или воспроизводится с устройства, в том числе к паролям, сведениям о платежах, фотографиям, сообщениям и прослушиваемым аудиозаписям."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Во время записи или трансляции у сервиса, предоставляющего эту функцию, будет доступ ко всей информации, которая видна на экране или воспроизводится с устройства, в том числе к паролям, сведениям о платежах, фотографиям, сообщениям и прослушиваемым аудиозаписям."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Начать запись или трансляцию через приложение \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\"?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Больше не показывать"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Очистить все"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Настроить"</string>
@@ -796,8 +794,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Переключение раскладки"</string>
<string name="save" msgid="3392754183673848006">"Сохранить"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Сбросить"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Выбор ширины кнопки"</string>
<string name="clipboard" msgid="8517342737534284617">"Буфер обмена"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Персонализированная кнопка навигации"</string>
@@ -893,8 +890,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Вправо"</string>
<string name="tuner_menu" msgid="363690665924769420">"Меню"</string>
<string name="tuner_app" msgid="6949280415826686972">"Приложение \"<xliff:g id="APP">%1$s</xliff:g>\""</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Оповещения"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Батарея"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Скриншоты"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Сообщения"</string>
@@ -904,8 +900,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> уже здесь!"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Приложение готово к работе, установка не требуется."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Приложение готово к работе, установка не требуется. Нажмите, чтобы узнать больше."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"О приложении"</string>
<string name="go_to_web" msgid="636673528981366511">"Перейти в браузер"</string>
<string name="mobile_data" msgid="4564407557775397216">"Моб. Интернет"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -939,13 +934,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Открыть настройки"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"ОК"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Передача SysUI"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"В приложении \"<xliff:g id="APP">%1$s</xliff:g>\" используется <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"В приложениях используется <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" и "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"камера"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"местоположение"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"микрофон"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Датчики отключены"</string>
<string name="device_services" msgid="1549944177856658705">"Сервисы устройства"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Без названия"</string>
@@ -968,4 +956,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Параметры навигации в системе обновлены. Чтобы изменить их, перейдите в настройки."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Чтобы обновить параметры навигации в системе, перейдите в настройки."</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Переход в режим ожидания"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Наложение окна увеличения"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Окно увеличения"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Настройки окна увеличения"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ru/strings_tv.xml b/packages/SystemUI/res/values-ru/strings_tv.xml
index cff67f000b5a..b668cf96908b 100644
--- a/packages/SystemUI/res/values-ru/strings_tv.xml
+++ b/packages/SystemUI/res/values-ru/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Без названия)"</string>
<string name="pip_close" msgid="5775212044472849930">"\"Кадр в кадре\" – выйти"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Во весь экран"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Микрофон включен"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"Приложение \"%1$s\" использовало доступ к микрофону."</string>
</resources>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index c28b189e2718..94a744842e19 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"තවත් දැන ගන්න"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"තිරය පිරවීමට විශාලනය කරන්න"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"තිරය පිරවීමට අදින්න"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"තිර රුව"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"තිර රුව සුරකිමින්…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"තිර රුව සුරැකෙමින් පවතී…"</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"තිර රුව සුරකින ලදී"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"දුරකථනය විවෘත කරන්න"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"විවෘත හඬ සහාය"</string>
<string name="camera_label" msgid="8253821920931143699">"කැමරාව විවෘත කරන්න"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"අවලංගු කරන්න"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"තහවුරු කරන්න"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"නැවත උත්සාහ කරන්න"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"සත්‍යාපනය අවලංගු කිරීමට තට්ටු කරන්න"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"<xliff:g id="TIME">%s</xliff:g>ට ක්‍රියාත්මකයි"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g> තෙක්"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"අඳුරු තේමාව"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"අඳුරු තේමාව\nබැටරි සුරැකුම"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"බැටරි සුරැකුම"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"හිරු බැසීමේදී ඔන්ය"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"හිරු නගින තෙක්"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC අබලයි"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC සබලයි"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"විවෘත කිරීමට නැවත තට්ටු කරන්න"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"විවෘත කිරීමට ස්වයිප් කරන්න"</string>
<string name="keyguard_retry" msgid="886802522584053523">"නැවත උත්සාහ කිරීමට ඉහළට ස්වයිප් කරන්න"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"මෙම උපාංගය ඔබගේ සංවිධානය විසින් කළමනාකරණය කරනු ලැබේ"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"මෙම උපාංගය <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> මගින් කළමනාකරණය කෙරේ"</string>
<string name="phone_hint" msgid="6682125338461375925">"දුරකථනය සඳහා නිරූපකය වෙතින් ස්වයිප් කරන්න"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"බැටරි සුරැකුම ක්‍රියාත්මකයි"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"ක්‍රියාකාරිත්වය සහ පසුබිම් දත්ත අඩු කරන්න"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"බැටරි සුරැකුම ක්‍රියාවිරහිත කරන්න"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"පටිගත හෝ විකාශය කරන අතරේ, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> හට ශ්‍රව්‍ය, මුරපද, ගෙවීමේ තතු, ඡායාරූප, සහ පණිවිඩ වැනි, ඔබේ තිරයෙහි සංදර්ශනය වන හෝ ඔබේ උපාංගයෙන් වාදනය වන ඕනෑම සංවේදී තොරතුරක් ග්‍රහණය කළ හැකිය."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"පටිගත හෝ විකාශය කරන අතරේ, මෙම කාර්යය සපයන සේවාවට ශ්‍රව්‍ය, මුරපද, ගෙවීමේ තතු, ඡායාරූප, සහ පණිවිඩ වැනි, ඔබේ තිරයෙහි සංදර්ශනය වන හෝ ඔබේ උපාංගයෙන් වාදනය වන ඕනෑම සංවේදී තොරතුරක් ග්‍රහණය කළ හැකිය."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"විකාශනය/පටිගත කිරීම අතරතුර සංවේදී තොරතුරු හෙළි කිරීම"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>ට පටිගත කරන හෝ විකාශ කරන අතරතුර ඔබේ තිරයේ දිස් වන හෝ ඔබේ උපාංගයෙන් වාදනය කරන සියලු තොරතුරු වෙත ප්‍රවේශ ලැබෙනු ඇත. මෙහි මුරපද, ගෙවීම් විස්තර, ඡායාරූප, පණිවිඩ සහ ඔබ වාදනය කරන ඕඩියෝ යනාදි තොරතුරු ඇතුළත් වේ."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"මෙම ශ්‍රිතය සපයන සේවාවට පටිගත කරන හෝ විකාශ කරන අතරතුර ඔබේ තිරයේ දිස් වන හෝ ඔබේ උපාංගයෙන් වාදනය කරන සියලු තොරතුරු වෙත ප්‍රවේශය ලැබෙනු ඇත. මෙහි මුරපද, ගෙවීම් විස්තර, ඡායාරූප, පණිවිඩ සහ ඔබ වාදනය කරන ඕඩියෝ යනාදි තොරතුරු ඇතුළත් වේ."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> සමග පටිගත කිරීම හෝ විකාශය කිරීම ආරම්භ කරන්නද?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"නැවත නොපෙන්වන්න"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"සියල්ල හිස් කරන්න"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"කළමනාකරණය කරන්න"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"යතුරු පුවරු මාරුව"</string>
<string name="save" msgid="3392754183673848006">"සුරකින්න"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"යළි සකසන්න"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"බොත්තම් පළල සීරුමාරු කරන්න"</string>
<string name="clipboard" msgid="8517342737534284617">"පසුරු පුවරුව"</string>
<string name="accessibility_key" msgid="3471162841552818281">"අභිරුචි සංචලන බොත්තම"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"දකුණු"</string>
<string name="tuner_menu" msgid="363690665924769420">"මෙනුව"</string>
<string name="tuner_app" msgid="6949280415826686972">"<xliff:g id="APP">%1$s</xliff:g> යෙදුම"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"ඇඟවීම්"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"බැටරිය"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"තිර රු"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"පොදු පණිවිඩ"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> ධාවනය වෙමින්"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"ස්ථාපනය නොකර යෙදුම විවෘත කර ඇත."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"ස්ථාපනය නොකර යෙදුම විවෘත කර ඇත. තව දැන ගැනීමට තට්ටු කරන්න."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"යෙදුම් තොරතුරු"</string>
<string name="go_to_web" msgid="636673528981366511">"බ්‍රවුසරය වෙත යන්න"</string>
<string name="mobile_data" msgid="4564407557775397216">"ජංගම දත්ත"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"සැකසීම්"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"තේරුණා"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> ඔබේ <xliff:g id="TYPES_LIST">%2$s</xliff:g> භාවිත කරමින් සිටී."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"යෙදුම් ඔබේ <xliff:g id="TYPES_LIST">%s</xliff:g> භාවිත කරමින් සිටී."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" සහ "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"කැමරාව"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"ස්ථානය"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"මයික්‍රෝෆෝනය"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"සංවේදක ක්‍රියාවිරහිතයි"</string>
<string name="device_services" msgid="1549944177856658705">"උපාංග සේවා"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"මාතෘකාවක් නැත"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"පද්ධති සංචලනය යාවත්කාලීන කළා. වෙනස්කම් සිදු කිරීමට, සැකසීම් වෙත යන්න."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"පද්ධති සංචලනය යාවත්කාලීන කිරීමට සැකසීම් වෙත යන්න"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"පොරොත්තු"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"විශාලන උඩැතිරි කවුළුව"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"විශාලන කවුළුව"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"විශාලනය කිරීමේ කවුළු පාලන"</string>
</resources>
diff --git a/packages/SystemUI/res/values-si/strings_tv.xml b/packages/SystemUI/res/values-si/strings_tv.xml
index e309ee324f28..167d10578f16 100644
--- a/packages/SystemUI/res/values-si/strings_tv.xml
+++ b/packages/SystemUI/res/values-si/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(මාතෘකාවක් නැති වැඩසටහන)"</string>
<string name="pip_close" msgid="5775212044472849930">"PIP වසන්න"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"සම්පූර්ණ තිරය"</string>
+ <string name="mic_active" msgid="5766614241012047024">"මයික්‍රොෆෝනය සක්‍රියයි"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s ඔබේ මයික්‍රොෆෝනයට ප්‍රවේශ වී ඇත"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index ca929a0d7d82..6fc30deeb9b1 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Ďalšie informácie"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Priblížiť na celú obrazovku"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Na celú obrazovku"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Snímka obrazovky"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Prebieha ukladanie snímky obrazovky..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Prebieha ukladanie snímky obrazovky..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Snímka obrazovky bola uložená"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"otvoriť telefón"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"otvoriť hlasového asistenta"</string>
<string name="camera_label" msgid="8253821920931143699">"spustiť fotoaparát"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Zrušiť"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Potvrdiť"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Skúsiť znova"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Klepnutím zrušíte overenie"</string>
@@ -391,7 +389,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Od <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Tmavý motív"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Tmavý motív\nŠetrič batérie"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Šetrič batérie"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Zap. pri záp. slnka"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Do východu slnka"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC je deaktivované"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC je aktivované"</string>
@@ -416,10 +416,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Upozornenie otvoríte opätovným klepnutím"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Otvorte potiahnutím prstom nahor"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Potiahnutím nahor to skúste znova"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Toto zariadenie spravuje vaša organizácia"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Toto zariadenie spravuje organizácia <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Telefón otvoríte prejdením prstom od ikony"</string>
@@ -473,9 +469,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Šetrič batérie je zapnutý"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Obmedzí výkonnosť a prenos údajov na pozadí"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Vypnúť šetrič batérie"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Počas nahrávania alebo prenosu môže aplikácia <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> zachytiť citlivé údaje zobrazené na obrazovke alebo prehrávané zo zariadenia, napríklad zvuk, heslá, platobné údaje, fotky a správy."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Počas nahrávania alebo prenosu môže služba poskytujúca túto funkciu zachytiť citlivé údaje zobrazené na obrazovke alebo prehrávané zo zariadenia, napríklad zvuk, heslá, platobné údaje, fotky a správy."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Počas prenášania/zaznamenávania sa odhaľujú citlivé údaje"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"Povolenie <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> bude mať prístup k všetkým informáciám zobrazovaným na obrazovke alebo prehrávaným v zariadení počas nahrávania či prenosu. Patria medzi ne informácie, akými sú napríklad heslá, platobné podrobnosti, fotky, správy a prehrávaný zvuk."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Služba poskytujúca túto funkciu bude mať prístup k všetkým informáciám zobrazovaným na obrazovke alebo prehrávaným v zariadení počas nahrávania či prenosu. Patria medzi ne informácie, akými sú napríklad heslá, platobné podrobnosti, fotky, správy a prehrávaný zvuk."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Chcete spustiť nahrávanie alebo prenos s aktivovaným povolením <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Nabudúce nezobrazovať"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Vymazať všetko"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Spravovať"</string>
@@ -796,8 +794,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Prepínač klávesnice"</string>
<string name="save" msgid="3392754183673848006">"Uložiť"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Resetovať"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Upraviť šírku tlačidla"</string>
<string name="clipboard" msgid="8517342737534284617">"Schránka"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Vlastné tlačidlo navigácie"</string>
@@ -893,8 +890,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Doprava"</string>
<string name="tuner_menu" msgid="363690665924769420">"Ponuka"</string>
<string name="tuner_app" msgid="6949280415826686972">"Aplikácia <xliff:g id="APP">%1$s</xliff:g>"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Upozornenia"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Batéria"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Snímky obrazovky"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Všeobecné správy"</string>
@@ -904,8 +900,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"Aplikácia <xliff:g id="APP">%1$s</xliff:g> je spustená"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Aplikácia bola otvorená bez inštalácie."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Aplikácia bola otvorená bez inštalácie. Klepnutím zobrazíte ďalšie informácie."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Aplikácia"</string>
<string name="go_to_web" msgid="636673528981366511">"Otvoriť prehliadač"</string>
<string name="mobile_data" msgid="4564407557775397216">"Mobilné dáta"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -939,13 +934,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Nastavenia"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Dobre"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> používa zoznam <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplikácie používajú zoznam <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" a "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"fotoaparát"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"poloha"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofón"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Senzory sú vypnuté"</string>
<string name="device_services" msgid="1549944177856658705">"Služby zariadenia"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Bez názvu"</string>
@@ -968,4 +956,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Navigácia v systéme bola aktualizovaná. Ak chcete vykonať zmeny, prejdite do Nastavení."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Prejdite do Nastavení a aktualizujte navigáciu v systéme"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Pohotovostný režim"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Okno prekrytia priblíženia"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Okno priblíženia"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Ovládacie prvky okna priblíženia"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sk/strings_tv.xml b/packages/SystemUI/res/values-sk/strings_tv.xml
index 6b6d6567bf30..562742ae5f1b 100644
--- a/packages/SystemUI/res/values-sk/strings_tv.xml
+++ b/packages/SystemUI/res/values-sk/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Program bez názvu)"</string>
<string name="pip_close" msgid="5775212044472849930">"Zavrieť režim PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Celá obrazovka"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Mikrofón je aktívny"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"Aplikácia %1$s použila váš mikrofón"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 5b65bbcf2189..2c8893e1ed60 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Več o tem"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Povečava čez cel zaslon"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Raztegnitev čez zaslon"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Posnetek zaslona"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Shranjev. posnetka zaslona ..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Shranjevanje posnetka zaslona ..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Posnetek zaslona je shranjen"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"odpri telefon"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"odpri glasovnega pomočnika"</string>
<string name="camera_label" msgid="8253821920931143699">"odpri fotoaparat"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Prekliči"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Potrdite"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Poskusi znova"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Če želite preklicati preverjanje pristnosti, se dotaknite"</string>
@@ -391,7 +389,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Vklop ob <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Temna tema"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Temna tema\nVarčevanje z energijo akumul."</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Varč. z ener. bater."</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Ob sončnem zahodu"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Do sončnega vzhoda"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"Tehnologija NFC je onemogočena"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"Tehnologija NFC je omogočena"</string>
@@ -416,10 +416,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Znova se dotaknite, da odprete"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Povlecite navzgor, da odprete"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Povlecite navzgor za vnovičen poskus"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"To napravo upravlja vaša organizacija"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"To napravo upravlja <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Povlecite z ikone za telefon"</string>
@@ -473,9 +469,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Varčevanje z energijo akumulatorja je vklopljeno"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Omeji zmogljivost delovanja in prenos podatkov v ozadju"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Izklop varčevanja z energijo akumulatorja"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Med snemanjem ali predvajanjem lahko aplikacija <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> zajame morebitne občutljive podatke, ki so prikazani na vašem zaslonu ali se predvajajo iz vaše naprave, vključno z občutljivimi podatki, kot so zvok, gesla, podatki o plačilu, fotografije in sporočila."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Med snemanjem ali predvajanjem lahko storitev, ki zagotavlja to funkcijo, zajame morebitne občutljive podatke, ki so prikazani na vašem zaslonu ali se predvajajo iz vaše naprave, vključno z občutljivimi podatki, kot so zvok, gesla, podatki o plačilu, fotografije in sporočila."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Med predvajanjem/snemanjem so izpostavljeni občutljivi podatki"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"Aplikacija <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> bo imela dostop do vseh podatkov, ki so med snemanjem ali predvajanjem prikazani na vašem zaslonu ali se predvajajo iz vaše naprave. To vključuje podatke, kot so gesla, podrobnosti o plačilu, fotografije, sporočila in zvok, ki ga predvajate."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Storitev, ki zagotavlja to funkcijo, bo imela dostop do vseh podatkov, ki so med snemanjem ali predvajanjem prikazani na vašem zaslonu ali se predvajajo iz vaše naprave. To vključuje podatke, kot so gesla, podrobnosti o plačilu, fotografije, sporočila in zvok, ki ga predvajate."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Želite začeti snemati ali predvajati z aplikacijo <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Tega ne prikaži več"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Izbriši vse"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Upravljanje"</string>
@@ -551,7 +549,7 @@
<string name="accessibility_volume_settings" msgid="1458961116951564784">"Nastavitve zvoka"</string>
<string name="accessibility_volume_expand" msgid="7653070939304433603">"Razširi"</string>
<string name="accessibility_volume_collapse" msgid="2746845391013829996">"Strni"</string>
- <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Samod. napisi predstavnosti"</string>
+ <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Sam. podnapisi predstavnosti"</string>
<string name="accessibility_volume_close_odi_captions_tip" msgid="8924753283621160480">"Zapiranje namiga za podnapise"</string>
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Prekrivni podnapisi"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"omogoči"</string>
@@ -796,8 +794,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Preklopnik tipkovnice"</string>
<string name="save" msgid="3392754183673848006">"Shrani"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Ponastavi"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Prilagajanje širine gumba"</string>
<string name="clipboard" msgid="8517342737534284617">"Odložišče"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Gumb za krmarjenje po meri"</string>
@@ -893,8 +890,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Desno"</string>
<string name="tuner_menu" msgid="363690665924769420">"Meni"</string>
<string name="tuner_app" msgid="6949280415826686972">"Aplikacija <xliff:g id="APP">%1$s</xliff:g>"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Opozorila"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Akumulator"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Posnetki zaslona"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Splošna sporočila"</string>
@@ -904,8 +900,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"Aplikacija <xliff:g id="APP">%1$s</xliff:g> se izvaja"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Aplikacija je odprta brez namestitve."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Aplikacija je odprta brez namestitve. Dotaknite se, če želite izvedeti več."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Podatki o aplikaciji"</string>
<string name="go_to_web" msgid="636673528981366511">"Odpri brskalnik"</string>
<string name="mobile_data" msgid="4564407557775397216">"Mobilni podatki"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -939,13 +934,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Nastavitve"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"V redu"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Izvoz kopice SysUI"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"Aplikacija <xliff:g id="APP">%1$s</xliff:g> uporablja <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplikacije uporabljajo <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" in "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"fotoaparat"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"lokacijo"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Izklop za tipala"</string>
<string name="device_services" msgid="1549944177856658705">"Storitve naprave"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Brez naslova"</string>
@@ -968,4 +956,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Krmarjenje po sistemu je posodobljeno. Če želite opraviti spremembe, odprite nastavitve."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Če želite posodobiti krmarjenje po sistemu, odprite nastavitve"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Stanje pripravljenosti"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Prekrivno povečevalno okno"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Povečevalno okno"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Kontrolniki povečevalnega okna"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sl/strings_tv.xml b/packages/SystemUI/res/values-sl/strings_tv.xml
index a69dfb044ae7..d3e4f259f881 100644
--- a/packages/SystemUI/res/values-sl/strings_tv.xml
+++ b/packages/SystemUI/res/values-sl/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Program brez naslova)"</string>
<string name="pip_close" msgid="5775212044472849930">"Zapri način PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Celozaslonsko"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Mikrofon je aktiven"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"Aplikacija %1$s je dostopala do mikrofona"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index b1be1fde1fb5..730f4b0897e3 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Mëso më shumë"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Zmadho për të mbushur ekranin"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Shtrije për të mbushur ekranin"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Pamja e ekranit"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Po ruan pamjen e ekranit..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Po ruan pamjen e ekranit…"</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Pamja e ekranit u ruajt"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"hap telefonin"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"hap ndihmën zanore"</string>
<string name="camera_label" msgid="8253821920931143699">"hap kamerën"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Anulo"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Konfirmo"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Provo përsëri"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Trokit për të anuluar vërtetimin"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Aktive në <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Deri në <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Tema e errët"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Tema e errët\nKursyesi i baterisë"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Kursyesi i baterisë"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Aktiv në perëndim"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Deri në lindje të diellit"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC është çaktivizuar"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC është aktivizuar"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Trokit përsëri për ta hapur"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Rrëshqit lart për ta hapur"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Rrëshqit lart për të provuar përsëri"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Kjo pajisje menaxhohet nga organizata jote"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Kjo pajisje menaxhohet nga <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Rrëshqit për të hapur telefonin"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"\"Kursyesi i baterisë\" është i aktivizuar"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Pakëson veprimtarinë dhe të dhënat në sfond"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Çaktivizo \"Kursyesin e baterisë\""</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Gjatë regjistrimit ose transmetimit, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> mund të regjistrojë çdo informacion të ndjeshëm që shfaqet në ekranin tënd ose luhet nga kjo pajisje, duke përfshirë informacionin e ndjeshëm si p.sh. audion, fjalëkalimet, informacionin e pagesës, fotografitë dhe mesazhet."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Gjatë regjistrimit ose transmetimit, shërbimi që ofron këtë funksion mund të regjistrojë çdo informacion të ndjeshëm që shfaqet në ekranin tënd ose luhet nga kjo pajisje, duke përfshirë informacionin e ndjeshëm si p.sh. audion, fjalëkalimet, informacionin e pagesës, fotografitë dhe mesazhet."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Ekspozimi i informacioneve delikate gjatë transmetimit/regjistrimit"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> do të ketë qasje te të gjitha informacionet që janë të dukshme në ekran ose që luhen nga pajisja jote gjatë regjistrimit ose transmetimit. Kjo përfshin informacione si p.sh. fjalëkalimet, detajet e pagesave, fotografitë, mesazhet dhe audion që luan ti."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Shërbimi që e ofron këtë funksion do të ketë qasje te të gjitha informacionet që janë të dukshme në ekran ose që luhen nga pajisja jote gjatë regjistrimit ose transmetimit. Kjo përfshin informacione si p.sh. fjalëkalimet, detajet e pagesave, fotografitë, mesazhet dhe audion që luan ti."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Fillo regjistrimin ose transmetimin me <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Mos e shfaq sërish"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Pastroji të gjitha"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Menaxho"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Ndërruesi i tastierës"</string>
<string name="save" msgid="3392754183673848006">"Ruaj"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Rivendos"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Rregullo gjerësinë e butonit"</string>
<string name="clipboard" msgid="8517342737534284617">"Kujtesa e fragmenteve"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Butoni i personalizuar i navigimit"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Djathtas"</string>
<string name="tuner_menu" msgid="363690665924769420">"Menyja"</string>
<string name="tuner_app" msgid="6949280415826686972">"Aplikacioni <xliff:g id="APP">%1$s</xliff:g>"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Sinjalizimet"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Bateria"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Pamje ekrani"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Mesazhe të përgjithshme"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"Po ekzekutohet <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Aplikacioni u hap pa u instaluar."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Aplikacioni u hap pa u instaluar. Trokit për të mësuar më shumë."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Informacioni i aplikacionit"</string>
<string name="go_to_web" msgid="636673528981366511">"Shko te shfletuesi"</string>
<string name="mobile_data" msgid="4564407557775397216">"Të dhënat celulare"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> - <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Cilësimet"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"E kuptova"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Hidh grumbullin SysUI"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> po përdor <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplikacionet po përdorin <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" dhe "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"kamerën"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"vendndodhjen"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofonin"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensorët joaktivë"</string>
<string name="device_services" msgid="1549944177856658705">"Shërbimet e pajisjes"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Pa titull"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Navigimi i sistemit u përditësua. Për të bërë ndryshime, shko te \"Cilësimet\"."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Shko te \"Cilësimet\" për të përditësuar navigimin e sistemit"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Në gatishmëri"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Dritarja e mbivendosjes së zmadhimit"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Dritarja e zmadhimit"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Kontrollet e dritares së zmadhimit"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sq/strings_tv.xml b/packages/SystemUI/res/values-sq/strings_tv.xml
index d25ea2417b5b..624be930cc92 100644
--- a/packages/SystemUI/res/values-sq/strings_tv.xml
+++ b/packages/SystemUI/res/values-sq/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Program pa titull)"</string>
<string name="pip_close" msgid="5775212044472849930">"Mbyll PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Ekrani i plotë"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Mikrofoni aktiv"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s pati qasje te mikrofoni yt"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 26c6220fe3c3..3660b0610e4c 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Сазнајте више"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Зумирај на целом екрану"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Развуци на цео екран"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Снимак екрана"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Чување снимка екрана..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Чување снимка екрана..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Снимак екрана је сачуван"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"отвори телефон"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"отвори гласовну помоћ"</string>
<string name="camera_label" msgid="8253821920931143699">"отвори камеру"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Откажи"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Потврди"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Пробај поново"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Додирните да бисте отказали потврду идентитета"</string>
@@ -389,7 +387,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Укључује се у <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"До <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Тамна тема"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Тамна тема\nУштеда батерије"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Уштеда батерије"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Укључује се по заласку сунца"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"До изласка сунца"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC је онемогућен"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC је омогућен"</string>
@@ -414,10 +414,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Додирните поново да бисте отворили"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Превуците нагоре да бисте отворили"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Превуците нагоре да бисте пробали поново"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Овим уређајем управља организација"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Овим уређајем управља <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Превуците од иконе за телефон"</string>
@@ -470,9 +466,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Уштеда батерије је укључена"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Смањује перформансе и позадинске податке"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Искључи Уштеду батерије"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Када снимате или пребацујете, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> може да чува осетљиве информације које се приказују на екрану или репродукују са уређаја, укључујући осетљиве информације као што су звук, лозинке, информације о плаћању, слике и поруке."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Када снимате или пребацујете, услуга која пружа ову функцију може да чува осетљиве информације које се приказују на екрану или репродукују са уређаја, укључујући осетљиве информације као што су звук, лозинке, информације о плаћању, слике и поруке."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Откривање осетљивих информација током пребацивања/снимања"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ће имати приступ свим информацијама које се приказују на екрану или репродукују са уређаја током снимања или пребацивања. То обухвата информације попут лозинки, информација о плаћању, слика, порука и звука који пуштате."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Услуга која пружа ову функцију ће имати приступ свим информацијама које се приказују на екрану или репродукују са уређаја током снимања или пребацивања. То обухвата информације попут лозинки, информација о плаћању, слика, порука и звука који пуштате."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Желите да почнете снимање или пребацивање помоћу апликације <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Не приказуј поново"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Обриши све"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Управљајте"</string>
@@ -791,8 +789,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Пребацивач за тастатуру"</string>
<string name="save" msgid="3392754183673848006">"Сачувај"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Ресетуј"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Прилагоди ширину дугмета"</string>
<string name="clipboard" msgid="8517342737534284617">"Привремена меморија"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Прилагођено дугме за навигацију"</string>
@@ -888,8 +885,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Стрелица удесно"</string>
<string name="tuner_menu" msgid="363690665924769420">"Мени"</string>
<string name="tuner_app" msgid="6949280415826686972">"Апликација <xliff:g id="APP">%1$s</xliff:g>"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Обавештења"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Батерија"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Снимци екрана"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Опште поруке"</string>
@@ -899,8 +895,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"Апликација <xliff:g id="APP">%1$s</xliff:g> је покренута"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Апликација се отворила без инсталирања."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Апликација се отворила без инсталирања. Додирните да бисте сазнали више."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Информације о апликацији"</string>
<string name="go_to_web" msgid="636673528981366511">"Иди на прегледач"</string>
<string name="mobile_data" msgid="4564407557775397216">"Мобилни подаци"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -934,13 +929,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Подешавања"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Важи"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Издвоји SysUI мем."</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> користи <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Апликације користе <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" и "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"камеру"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"локацију"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"микрофон"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Сензори су искључени"</string>
<string name="device_services" msgid="1549944177856658705">"Услуге за уређаје"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Без наслова"</string>
@@ -963,4 +951,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Навигација система је ажурирана. Да бисте унели измене, идите у Подешавања."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Идите у Подешавања да бисте ажурирали навигацију система"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Стање приправности"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Преклопни прозор за увећање"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Прозор за увећање"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Контроле прозора за увећање"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sr/strings_tv.xml b/packages/SystemUI/res/values-sr/strings_tv.xml
index 99a011054e5e..96846e702002 100644
--- a/packages/SystemUI/res/values-sr/strings_tv.xml
+++ b/packages/SystemUI/res/values-sr/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Програм без наслова)"</string>
<string name="pip_close" msgid="5775212044472849930">"Затвори PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Цео екран"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Микрофон је активан"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"Апликација %1$s је приступила микрофону"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 4f32f0374421..67e2e04ffef0 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Läs mer"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Zooma för att fylla skärm"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Dra för att fylla skärmen"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Skärmdump"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Skärmdumpen sparas ..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Skärmdumpen sparas ..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Skärmdumpen har sparats"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"öppna mobilen"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"öppna röstassistenten"</string>
<string name="camera_label" msgid="8253821920931143699">"öppna kameran"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Avbryt"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Bekräfta"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Försök igen"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Tryck för att avbryta autentiseringen"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"På från <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Till <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Mörkt tema"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Mörkt tema\nBatterisparläge"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Batterisparläge"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"På från solnedgången"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Till soluppgången"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC är inaktiverat"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC är aktiverat"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Tryck igen för att öppna"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Öppna genom att svepa uppåt"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Svep uppåt om du vill försöka igen"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Den här enheten hanteras av organisationen"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Den här enheten hanteras av <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Svep från ikonen och öppna telefonen"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Batterisparläget är aktiverat"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Minskar prestanda och bakgrundsdata"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Inaktivera batterisparläget"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"När du spelar in eller castar kan <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> registrera vilka känsliga uppgifter som helst som visas på skärmen eller spelas upp på enheten, inklusive ljud, lösenord, betalningsuppgifter, foton och meddelanden."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"När du spelar in eller castar kan tjänsten som tillhandahåller funktionen registrera vilka känsliga uppgifter som helst som visas på skärmen eller spelas upp på enheten, inklusive ljud, lösenord, betalningsuppgifter, foton och meddelanden."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Känsliga uppgifters synlighet under inspelning och vid castning"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> får åtkomst till all information som visas på skärmen eller spelas upp från enheten när du spelar in eller castar. Detta omfattar uppgifter som lösenord, betalningsinformation, foton, meddelanden och ljud som du spelar upp."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Den tjänst som tillhandahåller funktionen får åtkomst till all information som visas på skärmen eller spelas upp från enheten när du spelar in eller castar. Detta omfattar uppgifter som lösenord, betalningsinformation, foton, meddelanden och ljud som du spelar upp."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Vill du börja spela in eller casta med <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Visa inte igen"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Rensa alla"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Hantera"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Byt mellan meny/tangentbord"</string>
<string name="save" msgid="3392754183673848006">"Spara"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Återställ"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Justera knappens bredd"</string>
<string name="clipboard" msgid="8517342737534284617">"Urklipp"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Anpassad navigeringsknapp"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Höger"</string>
<string name="tuner_menu" msgid="363690665924769420">"Meny"</string>
<string name="tuner_app" msgid="6949280415826686972">"Appen <xliff:g id="APP">%1$s</xliff:g>"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Aviseringar"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Batteri"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Skärmdumpar"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Allmänna meddelanden"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> körs"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Appen öppnades utan installation."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Appen öppnades utan installation. Tryck om du vill veta mer."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Appinformation"</string>
<string name="go_to_web" msgid="636673528981366511">"Öppna webbläsaren"</string>
<string name="mobile_data" msgid="4564407557775397216">"Mobildata"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Inställningar"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"OK"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dumpa SysUI-heap"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="TYPES_LIST">%2$s</xliff:g> används av <xliff:g id="APP">%1$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"<xliff:g id="TYPES_LIST">%s</xliff:g> används av appar."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" och "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"plats"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensorer har inaktiverats"</string>
<string name="device_services" msgid="1549944177856658705">"Enhetstjänster"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Ingen titel"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Systemnavigeringen har uppdaterats. Öppna inställningarna om du vill ändra något."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Öppna inställningarna och uppdatera systemnavigeringen"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Viloläge"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Överlagrat förstoringsfönster"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Förstoringsfönster"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Inställningar för förstoringsfönster"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sv/strings_tv.xml b/packages/SystemUI/res/values-sv/strings_tv.xml
index d44ff564f2cb..64d61621b001 100644
--- a/packages/SystemUI/res/values-sv/strings_tv.xml
+++ b/packages/SystemUI/res/values-sv/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Namnlöst program)"</string>
<string name="pip_close" msgid="5775212044472849930">"Stäng PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Helskärm"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Mikrofonen är aktiv"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s har använt mikrofonen"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 921bdd959dbb..9f319a68c474 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Pata maelezo zaidi"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Kuza ili kujaza skrini"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Tanua ili kujaza skrini"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Picha ya skrini"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Inahifadhi picha ya skrini..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Inahifadhi picha ya skrini..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Imehifadhi picha ya skrini"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"fungua simu"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"fungua mapendekezo ya sauti"</string>
<string name="camera_label" msgid="8253821920931143699">"fungua kamera"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Ghairi"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Thibitisha"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Jaribu tena"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Gusa ili ughairi uthibitishaji"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Itawashwa saa <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Hadi <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Mandhari meusi"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Mandhari meusi\nKiokoa betri"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Kiokoa betri"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Itawashwa machweo"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Hadi macheo"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC imezimwa"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC imewashwa"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Gusa tena ili ufungue"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Telezesha kidole juu ili ufungue"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Telezesha kidole juu ili ujaribu tena"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Kifaa hiki kinasimamiwa na shirika lako"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Kifaa hiki kinadhibitiwa na <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Telezesha kidole kutoka kwa aikoni ili ufikie simu"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Kiokoa Betri kimewashwa"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Hupunguza utendaji na data ya chini chini"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Zima Kiokoa Betri"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Inaporekodi au kutuma, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> inaweza kunasa maelezo nyeti yanayoonyeshwa kwenye skrini yako au yanayochezwa kwenye kifaa chako, ikiwa ni pamoja na maelezo nyeti kama vile sauti, manenosiri, maelezo ya malipo, picha na ujumbe."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Inaporekodi au kutuma, huduma inayotoa utendaji huu inaweza kunasa maelezo yoyote nyeti yanayoonyeshwa kwenye skrini yako au yanayochezwa kwenye kifaa chako, ikiwa ni pamoja na maelezo nyeti kama vile sauti, manenosiri, maelezo ya malipo, picha na ujumbe."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Inatoa maelezo nyeti wakati wa kutuma/kurekodi"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> itaweza kufikia maelezo yote yanayoonekana kwenye skrini yako au yanayochezwa kwenye kifaa chako wakati wa kurekodi au kutuma. Hii ni pamoja na maelezo kama vile manenosiri, maelezo ya malipo, picha, ujumbe na sauti unayocheza."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Huduma inayotoa utendaji huu itaweza kufikia maelezo yote yanayoonekana kwenye skrini yako au yanayochezwa kwenye kifaa chako wakati wa kurekodi au kutuma. Hii ni pamoja na maelezo kama vile manenosiri, maelezo ya malipo, picha, ujumbe na sauti unayocheza."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Ungependa kuanza kurekodi au kutuma ukitumia <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Usionyeshe tena"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Futa zote"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Dhibiti"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Kibadilishaji cha kibodi"</string>
<string name="save" msgid="3392754183673848006">"Hifadhi"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Weka upya"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Rekebisha upana wa kitufe"</string>
<string name="clipboard" msgid="8517342737534284617">"Ubao klipu"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Kitufe maalum cha uelekezaji"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Kulia"</string>
<string name="tuner_menu" msgid="363690665924769420">"Menyu"</string>
<string name="tuner_app" msgid="6949280415826686972">"Programu ya <xliff:g id="APP">%1$s</xliff:g>"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Arifa"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Betri"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Picha za skrini"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Ujumbe wa Jumla"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> inaendelea kutumika"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Programu inafunguka bila kusakinishwa."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Programu inafunguka bila kusakinishwa. Gusa ili upate maelezo zaidi."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Maelezo ya programu"</string>
<string name="go_to_web" msgid="636673528981366511">"Tumia kivinjari"</string>
<string name="mobile_data" msgid="4564407557775397216">"Data ya simu"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g><xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Mipangilio"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Nimeelewa"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> inatumia <xliff:g id="TYPES_LIST">%2$s</xliff:g> yako."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Programu zinatumia <xliff:g id="TYPES_LIST">%s</xliff:g> yako."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" na "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"mahali"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"maikrofoni"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Umezima vitambuzi"</string>
<string name="device_services" msgid="1549944177856658705">"Huduma za Kifaa"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Wimbo hauna jina"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Umesasisha usogezaji kwenye mfumo. Ili ufanye mabadiliko, nenda kwenye Mipangilio."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Nenda kwenye mipangilio ili usasishe usogezaji kwenye mfumo"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Hali tuli"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Dirisha la Kuwekelea Linalokuza"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Dirisha la Ukuzaji"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Vidhibiti vya Dirisha la Ukuzaji"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sw/strings_tv.xml b/packages/SystemUI/res/values-sw/strings_tv.xml
index 25ced320d16f..7e2a64cf5a6c 100644
--- a/packages/SystemUI/res/values-sw/strings_tv.xml
+++ b/packages/SystemUI/res/values-sw/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Programu isiyo na jina)"</string>
<string name="pip_close" msgid="5775212044472849930">"Funga PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Skrini nzima"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Maikrofoni Inatumika"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s imefikia maikrofoni yako"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 5ca715b7efe7..d4c3c05a7007 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"மேலும் அறிக"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"திரையை நிரப்ப அளவை மாற்று"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"திரையை நிரப்ப இழு"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"ஸ்கிரீன்ஷாட்"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"ஸ்க்ரீன் ஷாட்டைச் சேமிக்கிறது…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"ஸ்க்ரீன் ஷாட்டைச் சேமிக்கிறது…"</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"ஸ்கிரீன்ஷாட் சேமிக்கப்பட்டது"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"ஃபோனைத் திற"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"குரல் உதவியைத் திற"</string>
<string name="camera_label" msgid="8253821920931143699">"கேமராவைத் திற"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"ரத்துசெய்"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"உறுதிப்படுத்துக"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"மீண்டும் முயல்க"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"பயோமெட்ரிக் அடையாளத்தை ரத்துசெய்ய தட்டவும்"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"<xliff:g id="TIME">%s</xliff:g>க்கு ஆன் செய்"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g> வரை"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"டார்க் தீம்"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"டார்க் தீம்\nபேட்டரி சேமிப்பான்"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"பேட்டரி சேமிப்பான்"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"மாலையில் ஆன் செய்"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"காலை வரை"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC முடக்கப்பட்டது"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC இயக்கப்பட்டது"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"திறக்க, மீண்டும் தட்டவும்"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"திறப்பதற்கு மேல் நோக்கி ஸ்வைப் செய்யவும்"</string>
<string name="keyguard_retry" msgid="886802522584053523">"மீண்டும் முயல மேல்நோக்கி ஸ்வைப் செய்யவும்"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"இந்தச் சாதனத்தை உங்கள் நிறுவனம் நிர்வகிக்கிறது"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"இந்தச் சாதனத்தை நிர்வகிப்பது: <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"ஃபோனிற்கு ஐகானிலிருந்து ஸ்வைப் செய்யவும்"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"பேட்டரி சேமிப்பான் ஆன் செய்யப்பட்டுள்ளது"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"செயல்திறனையும் பின்புல டேட்டா உபயோகத்தையும் குறைக்கிறது"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"பேட்டரி சேமிப்பானை ஆஃப் செய்"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"ரெக்கார்டிங் செய்யும்போதோ அலைபரப்பும்போதோ, உங்கள் திரையில் காட்டப்படும் அல்லது உங்கள் சாதனத்திலிருந்து இயக்கப்படும் (ஆடியோ, கடவுச்சொற்கள், கட்டணத் தகவல், படங்கள், மெசேஜ்கள் உள்ளிட்ட) எந்த ஒரு அதிமுக்கியத் தகவலையும் <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ஆல் படமெடுக்க முடியும்."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"ரெக்கார்டிங் செய்யும்போதோ அலைபரப்பும்போதோ உங்கள் திரையில் காட்டப்படும் அல்லது உங்கள் சாதனத்திலிருந்து இயக்கப்படும் (ஆடியோ, கடவுச்சொற்கள், கட்டணத் தகவல், படங்கள், மெசேஜ்கள் உள்ளிட்ட) எந்த ஒரு அதிமுக்கியத் தகவலையும் இந்தச் செயல்பாட்டை வழங்கும் சேவையால் படமெடுக்க முடியும்."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"அலைபரப்பும்போதோ ரெக்கார்டிங் செய்யும்போதோ தனிப்பட்ட விவரங்கள் அறியப்படும் வாய்ப்புள்ளது"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> உங்கள் திரையில் தெரியும் தகவல்கள், ரெக்கார்டு செய்யும்போதோ அனுப்பும்போதோ உங்கள் சாதனத்திலிருந்து பிளே ஆகும் அனைத்து தகவல்கள் ஆகியவற்றுக்கான அணுகலைக் கொண்டிருக்கும். கடவுச்சொற்கள், பேமெண்ட் தொடர்பான தகவல்கள், படங்கள், மெசேஜ்கள், நீங்கள் பிளே செய்யும் ஆடியோ போன்ற அனைத்துத் தகவல்களும் இதில் அடங்கும்."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"இந்தச் செயல்பாட்டை வழங்கும் சேவையானது உங்கள் திரையில் தெரியும் தகவல்கள், ரெக்கார்டு செய்யும்போதோ அனுப்பும்போதோ உங்கள் சாதனத்திலிருந்து பிளே ஆகும் அனைத்துத் தகவல்கள் ஆகியவற்றுக்கான அணுகலைக் கொண்டிருக்கும். கடவுச்சொற்கள், பேமெண்ட் தொடர்பான தகவல்கள், படங்கள், மெசேஜ்கள், நீங்கள் பிளே செய்யும் ஆடியோ போன்ற அனைத்துத் தகவல்களும் இதில் அடங்கும்."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> மூலம் ரெக்கார்டிங் செய்யவோ அனுப்புவதற்கோ தொடங்கிவீட்டீர்களா?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"மீண்டும் காட்டாதே"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"எல்லாவற்றையும் அழி"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"அறிவிப்புகளை நிர்வகி"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"விசைப்பலகை மாற்றி"</string>
<string name="save" msgid="3392754183673848006">"சேமி"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"மீட்டமை"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"பட்டனின் அகலத்தை மாற்று"</string>
<string name="clipboard" msgid="8517342737534284617">"கிளிப்போர்டு"</string>
<string name="accessibility_key" msgid="3471162841552818281">"தனிப்பயன் வழிசெலுத்தல் பட்டன்"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"வலது"</string>
<string name="tuner_menu" msgid="363690665924769420">"மெனு"</string>
<string name="tuner_app" msgid="6949280415826686972">"<xliff:g id="APP">%1$s</xliff:g> ஆப்ஸ்"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"விழிப்பூட்டல்கள்"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"பேட்டரி"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"ஸ்கிரீன் ஷாட்டுகள்"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"பொதுச் செய்திகள்"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> இயங்குகிறது"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"நிறுவ வேண்டிய தேவையில்லாமல் ஆப்ஸ் திறக்கப்பட்டது."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"நிறுவ வேண்டிய தேவையில்லாமல் ஆப்ஸ் திறக்கப்பட்டது. மேலும் அறியத் தட்டவும்."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"ஆப்ஸ் தகவல்"</string>
<string name="go_to_web" msgid="636673528981366511">"உலாவிக்குச் செல்"</string>
<string name="mobile_data" msgid="4564407557775397216">"மொபைல் டேட்டா"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"அமைப்புகள்"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"சரி"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"உங்கள் <xliff:g id="TYPES_LIST">%2$s</xliff:g>ஐ <xliff:g id="APP">%1$s</xliff:g> ஆப்ஸ் பயன்படுத்துகிறது."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"உங்கள் <xliff:g id="TYPES_LIST">%s</xliff:g> ஆகியவற்றை ஆப்ஸ் பயன்படுத்துகின்றன."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" மற்றும் "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"கேமரா"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"இருப்பிடம்"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"மைக்ரோஃபோன்"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"சென்சார்களை ஆஃப் செய்தல்"</string>
<string name="device_services" msgid="1549944177856658705">"சாதன சேவைகள்"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"தலைப்பு இல்லை"</string>
@@ -958,4 +946,10 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"சிஸ்டம் நேவிகேஷன் மாற்றப்பட்டது. மாற்றங்களைச் செய்ய ‘அமைப்புகளுக்குச்’ செல்லவும்."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"சிஸ்டம் நேவிகேஷனை மாற்ற ’அமைப்புகளுக்குச்’ செல்லவும்"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"இயக்க நேரம்"</string>
+ <!-- no translation found for magnification_overlay_title (6584179429612427958) -->
+ <skip />
+ <!-- no translation found for magnification_window_title (4863914360847258333) -->
+ <skip />
+ <!-- no translation found for magnification_controls_title (8421106606708891519) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ta/strings_tv.xml b/packages/SystemUI/res/values-ta/strings_tv.xml
index d556139d5fda..43418053f841 100644
--- a/packages/SystemUI/res/values-ta/strings_tv.xml
+++ b/packages/SystemUI/res/values-ta/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(தலைப்பு இல்லை)"</string>
<string name="pip_close" msgid="5775212044472849930">"PIPஐ மூடு"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"முழுத்திரை"</string>
+ <string name="mic_active" msgid="5766614241012047024">"மைக்ரோஃபோன் செயலிலுள்ளது"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s உங்கள் மைக்ரோஃபோனைப் பயன்படுத்தியது"</string>
</resources>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 07fef971ca08..1baf89c5f0d5 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"మరింత తెలుసుకోండి"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"స్క్రీన్‌కు నింపేలా జూమ్ చేయండి"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"స్క్రీన్‌కు నింపేలా విస్తరించండి"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"స్క్రీన్‌షాట్"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"స్క్రీన్‌షాట్‌ను సేవ్ చేస్తోంది…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"స్క్రీన్‌షాట్‌ను సేవ్ చేస్తోంది…"</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"స్క్రీన్‌షాట్ సేవ్ చేయబడింది"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"ఫోన్‌ను తెరువు"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"వాయిస్ అసిస్టెంట్‌ను తెరువు"</string>
<string name="camera_label" msgid="8253821920931143699">"కెమెరాను తెరువు"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"రద్దు చేయి"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"నిర్ధారించు"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"మళ్లీ ప్రయత్నించు"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"ప్రామాణీకరణను రద్దు చేయడానికి నొక్కండి"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"<xliff:g id="TIME">%s</xliff:g>కి"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g> వరకు"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"ముదురు రంగు థీమ్"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"ముదురు రంగు థీమ్\nబ్యాటరీ సేవర్"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"బ్యాటరీ సేవర్"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"సూర్యాస్తమయానికి"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"సూర్యోదయం వరకు"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC నిలిపివేయబడింది"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ప్రారంభించబడింది"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"తెరవడానికి మళ్లీ నొక్కండి"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"తెరవడానికి, పైకి స్వైప్ చేయండి"</string>
<string name="keyguard_retry" msgid="886802522584053523">"మళ్ళీ ప్రయత్నించడానికి పైకి స్వైప్ చేయండి"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"ఈ పరికరాన్ని మీ సంస్థ నిర్వహిస్తోంది"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"ఈ పరికరం <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> నిర్వహణలో ఉంది"</string>
<string name="phone_hint" msgid="6682125338461375925">"ఫోన్ కోసం చిహ్నాన్ని స్వైప్ చేయండి"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"బ్యాటరీ సేవర్ ఆన్‌లో ఉంది"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"పనితీరుని మరియు నేపథ్య డేటాను తగ్గిస్తుంది"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"బ్యాటరీ సేవర్‌ను ఆఫ్ చేయండి"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"రికార్డ్ చేస్తున్నప్పుడు లేదా ప్రసారం చేస్తున్నప్పుడు, మీ స్క్రీన్‌పై ప్రదర్శించబడిన లేదా మీ పరికరం నుండి ప్లే చేయబడిన ఆడియో, పాస్‌వర్డ్‌లు, చెల్లింపు సమాచారం, ఫోటోలు మరియు సందేశాలతో సహా గోప్యమైన సమాచారాన్ని <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> క్యాప్చర్ చేయగలుగుతుంది."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"రికార్డ్ చేస్తున్నప్పుడు లేదా ప్రసారం చేస్తున్నప్పుడు, మీ స్క్రీన్‌పై ప్రదర్శించబడిన లేదా మీ పరికరం నుండి ప్లే చేయబడిన ఆడియో, పాస్‌వర్డ్‌లు, చెల్లింపు సమాచారం, ఫోటోలు మరియు సందేశాలతో సహా గోప్యమైన సమాచారాన్ని ఈ ఫంక్షన్‌ను అందిస్తున్న సేవా ప్రదాత క్యాప్చర్ చేయగలుగుతుంది."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"ప్రసారం/రికార్డ్ అయ్యే సమయాలలో గోప్యమైన సమాచారాన్ని బహిర్గతపరచడం"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"రికార్డ్ చేస్తున్నప్పుడు లేదా ప్రసారం చేస్తున్నప్పుడు, మీ స్క్రీన్‌పై ప్రదర్శించబడిన లేదా మీ పరికరం నుండి ప్లే చేయబడిన సమాచారం మొత్తాన్ని, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> యాక్సెస్ చేయగలుగుతుంది. ఈ సమాచారంలో, పాస్‌వర్డ్‌లు, చెల్లింపు వివరాలు, ఫోటోలు, సందేశాలు, మీరు ప్లే చేసే ఆడియో వంటివి ఉంటాయి."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"రికార్డ్ చేస్తున్నప్పుడు లేదా ప్రసారం చేస్తున్నప్పుడు మీ స్క్రీన్‌పై ప్రదర్శించబడిన లేదా మీ పరికరం నుండి ప్లే చేయబడిన సమాచారం మొత్తాన్ని, ఈ ఫంక్షన్‌ను అందిస్తున్న సర్వీసు యాక్సెస్ చేయగలదు. ఈ సమాచారంలో, పాస్‌వర్డ్‌లు, చెల్లింపు వివరాలు, ఫోటోలు, సందేశాలు, మీరు ప్లే చేసే ఆడియో వంటివి ఉంటాయి."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>తో రికార్డ్ చేయడం లేదా ప్రసారం చేయడం ప్రారంభించాలా?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"మళ్లీ చూపవద్దు"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"అన్నీ క్లియర్ చేయండి"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"నిర్వహించండి"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"కీబోర్డ్ స్విచర్"</string>
<string name="save" msgid="3392754183673848006">"సేవ్ చేయి"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"రీసెట్ చేయండి"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"బటన్ వెడల్పును సర్దుబాటు చేయండి"</string>
<string name="clipboard" msgid="8517342737534284617">"క్లిప్‌బోర్డ్"</string>
<string name="accessibility_key" msgid="3471162841552818281">"అనుకూల నావిగేషన్ బటన్"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"కుడి"</string>
<string name="tuner_menu" msgid="363690665924769420">"మెను"</string>
<string name="tuner_app" msgid="6949280415826686972">"<xliff:g id="APP">%1$s</xliff:g> అనురవర్తనం"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"హెచ్చరికలు"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"బ్యాటరీ"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"స్క్రీన్‌షాట్‌లు"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"సాధారణ సందేశాలు"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> అమలవుతోంది"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"ఇన్‌స్టాల్ చేయకుండా యాప్ తెరవబడింది."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"ఇన్‌స్టాల్ చేయకుండా యాప్ తెరవబడింది. మరింత తెలుసుకోవడానికి నొక్కండి."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"యాప్ సమాచారం"</string>
<string name="go_to_web" msgid="636673528981366511">"బ్రౌజర్‌కు వెళ్లండి"</string>
<string name="mobile_data" msgid="4564407557775397216">"మొబైల్ డేటా"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"సెట్టింగ్‌లు"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"అర్థమైంది"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"డంప్ SysUI హీప్"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> మీ <xliff:g id="TYPES_LIST">%2$s</xliff:g>ని ఉపయోగిస్తోంది."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"అప్లికేషన్‌లు మీ <xliff:g id="TYPES_LIST">%s</xliff:g>ని ఉపయోగిస్తున్నాయి."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" మరియు "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"కెమెరా"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"స్థానం"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"మైక్రోఫోన్"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"సెన్సార్‌లు ఆఫ్"</string>
<string name="device_services" msgid="1549944177856658705">"పరికర సేవలు"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"శీర్షిక లేదు"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"సిస్టమ్ నావిగేషన్ అప్‌డేట్ చేయబడింది. మార్పులు చేయడానికి, సెట్టింగ్‌లకు వెళ్లండి."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"సిస్టమ్ నావిగేషన్‌ను అప్‌డేట్ చేయడానికి సెట్టింగ్‌లకు వెళ్లండి"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"స్టాండ్‌బై"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"మాగ్నిఫికేషన్ ఓవర్‌లే విండో"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"మాగ్నిఫికేషన్ విండో"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"మాగ్నిఫికేషన్ నియంత్రణల విండో"</string>
</resources>
diff --git a/packages/SystemUI/res/values-te/strings_tv.xml b/packages/SystemUI/res/values-te/strings_tv.xml
index e0c82c7424a0..ded2f505c70c 100644
--- a/packages/SystemUI/res/values-te/strings_tv.xml
+++ b/packages/SystemUI/res/values-te/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(శీర్షిక లేని ప్రోగ్రామ్)"</string>
<string name="pip_close" msgid="5775212044472849930">"PIPని మూసివేయి"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"పూర్తి స్క్రీన్"</string>
+ <string name="mic_active" msgid="5766614241012047024">"మైక్రోఫోన్ యాక్టివ్‌గా ఉంది"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"మీ మైక్రోఫోన్‌ను %1$s యాక్సెస్ చేసింది"</string>
</resources>
diff --git a/packages/SystemUI/res/values-television/config.xml b/packages/SystemUI/res/values-television/config.xml
index 27db294a98d8..4cc5a6731108 100644
--- a/packages/SystemUI/res/values-television/config.xml
+++ b/packages/SystemUI/res/values-television/config.xml
@@ -22,6 +22,7 @@
<resources>
<!-- SystemUI Services: The classes of the stuff to start. -->
<string-array name="config_systemUIServiceComponents" translatable="false">
+ <item>com.android.systemui.util.NotificationChannels</item>
<item>com.android.systemui.volume.VolumeUI</item>
<item>com.android.systemui.stackdivider.Divider</item>
<item>com.android.systemui.statusbar.tv.TvStatusBar</item>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 14b7d746f7f0..569b05c8dedb 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"ดูข้อมูลเพิ่มเติม"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"ขยายจนเต็มหน้าจอ"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"ยืดจนเต็มหน้าจอ"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"ภาพหน้าจอ"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"กำลังบันทึกภาพหน้าจอ..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"กำลังบันทึกภาพหน้าจอ..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"บันทึกภาพหน้าจอแล้ว"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"เปิดโทรศัพท์"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"เปิดตัวช่วยเสียง"</string>
<string name="camera_label" msgid="8253821920931143699">"เปิดกล้อง"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"ยกเลิก"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"ยืนยัน"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"ลองอีกครั้ง"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"แตะเพื่อยกเลิกการตรวจสอบสิทธิ์"</string>
@@ -386,8 +384,10 @@
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"จนพระอาทิตย์ขึ้น"</string>
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"เปิดเวลา <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"จนถึง <xliff:g id="TIME">%s</xliff:g>"</string>
- <string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"ธีมสีเข้ม"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"ธีมสีเข้ม\nโหมดประหยัดแบตเตอรี่"</string>
+ <string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"ธีมมืด"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"โหมดประหยัดแบตเตอรี่"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"เปิดตอนพระอาทิตย์ตก"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"จนพระอาทิตย์ขึ้น"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC ถูกปิดใช้งาน"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"เปิดใช้งาน NFC แล้ว"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"แตะอีกครั้งเพื่อเปิด"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"เลื่อนขึ้นเพื่อเปิด"</string>
<string name="keyguard_retry" msgid="886802522584053523">"เลื่อนขึ้นเพื่อลองอีกครั้ง"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"อุปกรณ์นี้จัดการโดยองค์กรของคุณ"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"อุปกรณ์เครื่องนี้จัดการโดย <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"เลื่อนไอคอนโทรศัพท์"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"เปิดโหมดประหยัดแบตเตอรี่อยู่"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"ลดการใช้แบตเตอรี่และอินเทอร์เน็ตที่ใช้งานอยู่เบื้องหลัง"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"ปิดโหมดประหยัดแบตเตอรี่"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"ขณะที่กำลังบันทึกหรือแคสต์ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> มีสิทธิ์บันทึกข้อมูลที่ละเอียดอ่อนซึ่งแสดงบนหน้าจอหรือเล่นจากอุปกรณ์ของคุณ เช่น เสียง รหัสผ่าน ข้อมูลการชำระเงิน รูปภาพ และข้อความ"</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"ขณะที่กำลังบันทึกหรือแคสต์ บริการที่มีฟังก์ชันนี้มีสิทธิ์บันทึกข้อมูลที่ละเอียดอ่อนซึ่งแสดงบนหน้าจอหรือเล่นจากอุปกรณ์ของคุณ เช่น เสียง รหัสผ่าน ข้อมูลการชำระเงิน รูปภาพ และข้อความ"</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"มีการเปิดเผยข้อมูลที่ละเอียดอ่อนระหว่างการแคสต์/บันทึก"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> จะมีสิทธิ์เข้าถึงข้อมูลทั้งหมดที่ปรากฏบนหน้าจอหรือเปิดจากอุปกรณ์ของคุณขณะบันทึกหรือแคสต์ ซึ่งรวมถึงข้อมูลอย่างเช่นรหัสผ่าน รายละเอียดการชำระเงิน รูปภาพ ข้อความ และเสียงที่คุณเล่น"</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"บริการที่มีฟังก์ชันนี้จะมีสิทธิ์เข้าถึงข้อมูลทั้งหมดที่ปรากฏบนหน้าจอหรือเปิดจากอุปกรณ์ของคุณขณะบันทึกหรือแคสต์ ซึ่งรวมถึงข้อมูลอย่างเช่นรหัสผ่าน รายละเอียดการชำระเงิน รูปภาพ ข้อความ และเสียงที่คุณเล่น"</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"เริ่มบันทึกหรือแคสต์ด้วย <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> เลยไหม"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"ไม่ต้องแสดงข้อความนี้อีก"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"ล้างทั้งหมด"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"จัดการ"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"ปุ่มสลับแป้นพิมพ์"</string>
<string name="save" msgid="3392754183673848006">"บันทึก"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"รีเซ็ต"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"ปรับความกว้างของปุ่ม"</string>
<string name="clipboard" msgid="8517342737534284617">"คลิปบอร์ด"</string>
<string name="accessibility_key" msgid="3471162841552818281">"ปุ่มนำทางที่กำหนดเอง"</string>
@@ -795,7 +792,7 @@
<string name="right_keycode" msgid="2480715509844798438">"Keycode ทางขวา"</string>
<string name="left_icon" msgid="5036278531966897006">"ไอคอนทางซ้าย"</string>
<string name="right_icon" msgid="1103955040645237425">"ไอคอนทางขวา"</string>
- <string name="drag_to_add_tiles" msgid="8933270127508303672">"กดค้างแล้วลากเพื่อเพิ่มไทล์"</string>
+ <string name="drag_to_add_tiles" msgid="8933270127508303672">"กดค้างแล้วลากเพื่อเพิ่มชิ้นส่วน"</string>
<string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"กดไทล์ค้างไว้แล้วลากเพื่อจัดเรียงใหม่"</string>
<string name="drag_to_remove_tiles" msgid="4682194717573850385">"ลากมาที่นี่เพื่อนำออก"</string>
<string name="drag_to_remove_disabled" msgid="933046987838658850">"คุณต้องมีการ์ดอย่างน้อย <xliff:g id="MIN_NUM_TILES">%1$d</xliff:g> รายการ"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"ขวา"</string>
<string name="tuner_menu" msgid="363690665924769420">"เมนู"</string>
<string name="tuner_app" msgid="6949280415826686972">"แอป <xliff:g id="APP">%1$s</xliff:g>"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"การแจ้งเตือน"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"แบตเตอรี"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"ภาพหน้าจอ"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"ข้อความทั่วไป"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> ทำงานอยู่"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"เปิดแอปได้โดยไม่ต้องติดตั้ง"</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"เปิดแอปได้โดยไม่ต้องติดตั้ง แตะเพื่อดูข้อมูลเพิ่มเติม"</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"ข้อมูลแอป"</string>
<string name="go_to_web" msgid="636673528981366511">"ไปที่เบราว์เซอร์"</string>
<string name="mobile_data" msgid="4564407557775397216">"เน็ตมือถือ"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"การตั้งค่า"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"รับทราบ"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> ใช้<xliff:g id="TYPES_LIST">%2$s</xliff:g>ของคุณอยู่"</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"หลายแอปพลิเคชันใช้<xliff:g id="TYPES_LIST">%s</xliff:g>ของคุณอยู่"</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" และ "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"กล้องถ่ายรูป"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"ตำแหน่ง"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"ไมโครโฟน"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"ปิดเซ็นเซอร์"</string>
<string name="device_services" msgid="1549944177856658705">"บริการของอุปกรณ์"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"ไม่มีชื่อ"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"อัปเดตการไปยังส่วนต่างๆ ของระบบแล้ว หากต้องการเปลี่ยนแปลง ให้ไปที่การตั้งค่า"</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"ไปที่การตั้งค่าเพื่ออัปเดตการไปยังส่วนต่างๆ ของระบบ"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"สแตนด์บาย"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"หน้าต่างการขยายที่วางซ้อน"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"หน้าต่างการขยาย"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"การควบคุมหน้าต่างการขยาย"</string>
</resources>
diff --git a/packages/SystemUI/res/values-th/strings_tv.xml b/packages/SystemUI/res/values-th/strings_tv.xml
index b4ba5e96ec5d..14d458a5a4f2 100644
--- a/packages/SystemUI/res/values-th/strings_tv.xml
+++ b/packages/SystemUI/res/values-th/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(ไม่มีชื่อรายการ)"</string>
<string name="pip_close" msgid="5775212044472849930">"ปิด PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"เต็มหน้าจอ"</string>
+ <string name="mic_active" msgid="5766614241012047024">"ไมโครโฟนเปิดใช้งานอยู่"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s เข้าถึงไมโครโฟนแล้ว"</string>
</resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 382126207263..027eaabdcc0d 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Matuto pa"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"I-zoom upang punan screen"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"I-stretch upang mapuno screen"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Sine-save ang screenshot…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Sine-save ang screenshot…"</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Na-save ang screenshot"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"buksan ang telepono"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"buksan ang voice assist"</string>
<string name="camera_label" msgid="8253821920931143699">"buksan ang camera"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Kanselahin"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Kumpirmahin"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Subukang muli"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"I-tap para kanselahin ang pag-authenticate"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Mao-on sa ganap na <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Hanggang <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Madilim na tema"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Madilim na tema\nPangtipid sa baterya"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Pangtipid sa Baterya"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Mao-on sa sunset"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Hanggang sunrise"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"Naka-disable ang NFC"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"Naka-enable ang NFC"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"I-tap ulit upang buksan"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Mag-swipe pataas para buksan"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Mag-swipe pataas para subukan ulit"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Ang device na ito ay pinamamahalaan ng iyong organisasyon"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Pinamamahalaan ng <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> ang device na ito"</string>
<string name="phone_hint" msgid="6682125338461375925">"Mag-swipe mula sa icon para sa telepono"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Naka-on ang Pangtipid sa Baterya"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Binabawasan ang performance at data sa background"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"I-off ang Pangtipid sa Baterya"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Habang nagre-record o nagka-cast, puwedeng kunin ng <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ang anumang sensitibong impormasyong ipinapakita sa iyong screen o pine-play mula sa device mo, kasama ang sensitibong impormasyon gaya ng audio, mga password, impormasyon sa pagbabayad, mga larawan, at mga mensahe."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Habang nagre-record o nagka-cast, puwedeng kunin ng serbisyong nagbibigay ng function na ito ang anumang sensitibong impormasyong ipinapakita sa iyong screen o pine-play mula sa device mo, kasama ang sensitibong impormasyon gaya ng audio, mga password, impormasyon sa pagbabayad, mga larawan, at mga mensahe."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Mag-e-expose ng sensitibong impormasyon habang nagka-cast/nagre-record"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"Magkakaroon ng access ang <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> sa lahat ng impormasyong nakikita sa iyong screen o pine-play mula sa device mo habang nagre-record o nagka-cast. Kasama rito ang impormasyong tulad ng mga password, detalye ng pagbabayad, larawan, mensahe, at audio na pine-play mo."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Ang serbisyong nagbibigay ng function na ito ay magkakaroon ng access sa lahat ng impormasyong nakikita sa iyong screen o pine-play mula sa device mo habang nagre-record o nagka-cast. Kasama rito ang impormasyong tulad ng mga password, detalye ng pagbabayad, larawan, mensahe, at audio na pine-play mo."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Simulang mag-record o mag-cast gamit ang <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Huwag ipakitang muli"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"I-clear lahat"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Pamahalaan"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Keyboard switcher"</string>
<string name="save" msgid="3392754183673848006">"I-save"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"I-reset"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Isaayos ang lapad ng button"</string>
<string name="clipboard" msgid="8517342737534284617">"Clipboard"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Custom na button ng navigation"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Kanan"</string>
<string name="tuner_menu" msgid="363690665924769420">"Menu"</string>
<string name="tuner_app" msgid="6949280415826686972">"<xliff:g id="APP">%1$s</xliff:g> app"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Mga Alerto"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Baterya"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Mga Screenshot"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Mga Pangkalahatang Mensahe"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"Tumatakbo ang <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Nabuksan ang app nang hindi ini-install."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Nabuksan ang app nang hindi ini-install. I-tap para matuto pa."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Impormasyon ng app"</string>
<string name="go_to_web" msgid="636673528981366511">"Pumunta sa browser"</string>
<string name="mobile_data" msgid="4564407557775397216">"Mobile data"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Mga Setting"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"OK"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"Ginagamit ng <xliff:g id="APP">%1$s</xliff:g> ang iyong <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Ginagamit ng mga application ang iyong <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" at "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"camera"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"lokasyon"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"mikropono"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Naka-off ang mga sensor"</string>
<string name="device_services" msgid="1549944177856658705">"Mga Serbisyo ng Device"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Walang pamagat"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Na-update na ang pag-navigate ng system. Para gumawa ng mga pagbabago, pumunta sa Mga Setting."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Pumunta sa Mga Setting para i-update ang pag-navigate sa system"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Naka-standby"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Window ng Overlay sa Pag-magnify"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Window ng Pag-magnify"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Mga Kontrol sa Pag-magnify ng Window"</string>
</resources>
diff --git a/packages/SystemUI/res/values-tl/strings_tv.xml b/packages/SystemUI/res/values-tl/strings_tv.xml
index 3402f6a0d119..6e873f30edf2 100644
--- a/packages/SystemUI/res/values-tl/strings_tv.xml
+++ b/packages/SystemUI/res/values-tl/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Walang pamagat na programa)"</string>
<string name="pip_close" msgid="5775212044472849930">"Isara ang PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Full screen"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Aktibo ang Mikropono"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"Na-access ng %1$s ang iyong mikropono"</string>
</resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 3dddbf5e70d0..e9f08d3eeac0 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Daha fazla bilgi"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Yakınlaştır (ekranı kaplasın)"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Genişlet (ekran kapansın)"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Ekran görüntüsü"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Ekran görüntüsü kaydediliyor..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Ekran görüntüsü kaydediliyor..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Ekran görüntüsü kaydedildi"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"telefonu aç"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"sesli yardımı aç"</string>
<string name="camera_label" msgid="8253821920931143699">"kamerayı aç"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"İptal"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Onaylayın"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Tekrar dene"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Kimlik doğrulama işlemini iptal etmek için dokunun"</string>
@@ -383,11 +381,13 @@
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"İş profili"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"Gece Işığı"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Gün batımı açılacak"</string>
- <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Gün doğumuna kadar"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Sabaha kadar"</string>
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Şu saatte açılacak: <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Şu saate kadar: <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Koyu tema"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Koyu tema\nPil tasarrufu"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Pil Tasarrufu"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Gün batımı açılacak"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Sabaha kadar"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC devre dışı"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC etkin"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Açmak için tekrar dokunun"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Açmak için yukarı kaydırın"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Tekrar denemek için yukarı kaydırın"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Bu cihaz kuruluşunuz tarafından yönetiliyor"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Bu cihaz <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> tarafından yönetilmektedir."</string>
<string name="phone_hint" msgid="6682125338461375925">"Telefon için, simgeden hızlıca kaydırın"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Pil Tasarrufu açık"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Performansı ve arka plan verilerini azaltır"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Pil Tasarrufu\'nu kapat"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Kayıt veya yayın sırasında <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>, ekranınızda gösterilen veya cihazınızdan oynatılan ses, şifre, ödeme bilgileri, fotoğraflar ve mesajlar gibi hassas bilgileri yakalayabilir."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Kayıt veya yayın sırasında bu işlevi sağlayan servis, ekranınızda gösterilen veya cihazınızdan oynatılan ses, şifre, ödeme bilgileri, fotoğraflar ve mesajlar gibi hassas bilgileri yakalayabilir."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Yayın/kayıt sırasında hassas bilgileri gösterme"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>, ekranınızda görünen veya kayıt ya da yayın sırasında cihazınızdan oynatılan tüm bilgilere erişecektir. Bu bilgiler arasında şifreler, ödeme detayları, fotoğraflar, mesajlar ve çaldığınız sesler gibi bilgiler yer alır."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Bu işlevi sağlayan hizmet, ekranınızda görünen veya kayıt ya da yayın sırasında cihazınızdan oynatılan tüm bilgilere erişecektir. Bu bilgiler arasında şifreler, ödeme detayları, fotoğraflar, mesajlar ve çaldığınız sesler gibi bilgiler yer alır."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ile kayıt veya yayınlama başlatılsın mı?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Bir daha gösterme"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Tümünü temizle"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Yönet"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Klavye değiştirici"</string>
<string name="save" msgid="3392754183673848006">"Kaydet"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Sıfırla"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Düğme genişliğini düzenle"</string>
<string name="clipboard" msgid="8517342737534284617">"Pano"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Özel gezinme düğmesi"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Sağ"</string>
<string name="tuner_menu" msgid="363690665924769420">"Menü"</string>
<string name="tuner_app" msgid="6949280415826686972">"<xliff:g id="APP">%1$s</xliff:g> uygulaması"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Uyarılar"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Pil"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Ekran görüntüleri"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Genel Mesajlar"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> çalışıyor"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Uygulama yüklenmeden açıldı."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Uygulama yüklenmeden açıldı. Daha fazla bilgi için dokunun."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Uygulama bilgisi"</string>
<string name="go_to_web" msgid="636673528981366511">"Tarayıcıya git"</string>
<string name="mobile_data" msgid="4564407557775397216">"Mobil veriler"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Ayarlar"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Anladım"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"SysUI Yığın Dökümü"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> şunları kullanıyor: <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Uygulamalar şunları kullanıyor: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" ve "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"konum"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensörler kapalı"</string>
<string name="device_services" msgid="1549944177856658705">"Cihaz Hizmetleri"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Başlıksız"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Sistemde gezinme yöntemi güncellendi. Değişiklik yapmak için Ayarlar\'a gidin."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Sistemde gezinme yöntemini güncellemek için Ayarlar\'a gidin"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Beklemeye alınıyor"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Yer Paylaşımlı Büyütme Penceresi"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Büyütme Penceresi"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Büyütme Penceresi Kontrolleri"</string>
</resources>
diff --git a/packages/SystemUI/res/values-tr/strings_tv.xml b/packages/SystemUI/res/values-tr/strings_tv.xml
index 85d32400a8bf..be87e4cbcbda 100644
--- a/packages/SystemUI/res/values-tr/strings_tv.xml
+++ b/packages/SystemUI/res/values-tr/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Başlıksız program)"</string>
<string name="pip_close" msgid="5775212044472849930">"PIP\'yi kapat"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Tam ekran"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Mikrofon Etkin"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s mikrofonunuza erişti"</string>
</resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index a3e9e6280d29..94377d7f33e8 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Докладніше"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Масштабув. на весь екран"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Розтягнути на весь екран"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Знімок екрана"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Збереження знімка екрана..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Збереження знімка екрана..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Знімок екрана збережено"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"відкрити телефон"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"запустити голосові підказки"</string>
<string name="camera_label" msgid="8253821920931143699">"відкрити камеру"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Скасувати"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Підтвердити"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Повторити спробу"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Натисніть, щоб скасувати автентифікацію"</string>
@@ -391,7 +389,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Вмикається о <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"До <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Темна тема"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Темна тема\nЕнергозбереження"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Режим енергозбереження"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Увімкнеться ввечері"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"До сходу сонця"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC вимкнено"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ввімкнено"</string>
@@ -416,10 +416,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Торкніться знову, щоб відкрити"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Проведіть пальцем угору, щоб відкрити"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Проведіть пальцем угору, щоб повторити спробу"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Цим пристроєм керує адміністратор вашої організації"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Цим пристроєм керує організація <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Телефон: проведіть пальцем від значка"</string>
@@ -473,9 +469,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Режим енергозбереження ввімкнено"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Знижується продуктивність і обмежуються фонові дані"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Вимкнути режим економії заряду акумулятора"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Під час запису або трансляції додаток <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> може фіксувати будь-яку конфіденційну інформацію (зокрема, аудіо, паролі, платіжну інформацію, фотографії та повідомлення), яка з\'являється на екрані або відтворюється на пристрої."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Під час запису або трансляції сервіс, що надає цю функцію, може фіксувати будь-яку конфіденційну інформацію (зокрема, аудіо, паролі, платіжну інформацію, фотографії та повідомлення), яка з\'являється на екрані або відтворюється на пристрої."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Розкриття конфіденційної інформації під час трансляції або запису"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"Додаток <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> матиме доступ до всієї інформації, яка з\'являється на екрані або відтворюється на пристрої під час запису чи трансляції, зокрема до паролів, інформації про платежі, фотографій, повідомлень і аудіофайлів."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Сервіс, що надає цю функцію, матиме доступ до всієї інформації, яка з\'являється на екрані або відтворюється на пристрої під час запису чи трансляції, зокрема до паролів, інформації про платежі, фотографій, повідомлень і аудіофайлів."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Почати запис або трансляцію за допомогою додатка <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Більше не показувати"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Очистити все"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Керувати"</string>
@@ -796,8 +794,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Вибір клавіатури"</string>
<string name="save" msgid="3392754183673848006">"Зберегти"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Скинути"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Змінити ширину кнопки"</string>
<string name="clipboard" msgid="8517342737534284617">"Буфер обміну"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Спеціальна кнопка навігації"</string>
@@ -893,8 +890,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Праворуч"</string>
<string name="tuner_menu" msgid="363690665924769420">"Меню"</string>
<string name="tuner_app" msgid="6949280415826686972">"Додаток <xliff:g id="APP">%1$s</xliff:g>"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Сповіщення"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Акумулятор"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Знімки екрана"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Загальні повідомлення"</string>
@@ -904,8 +900,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> працює"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Додаток відкрито без встановлення."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Додаток відкрито без встановлення. Торкніться, щоб дізнатися більше."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Про додаток"</string>
<string name="go_to_web" msgid="636673528981366511">"Веб-переглядач"</string>
<string name="mobile_data" msgid="4564407557775397216">"Мобільний трафік"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -939,13 +934,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Налаштування"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"OK"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"Додаток <xliff:g id="APP">%1$s</xliff:g> використовує <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Додатки використовують <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" і "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"камеру"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"місце"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"мікрофон"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Датчики вимкнено"</string>
<string name="device_services" msgid="1549944177856658705">"Сервіси на пристрої"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Без назви"</string>
@@ -968,4 +956,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Навігацію в системі оновлено. Щоб внести зміни, перейдіть у налаштування."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Перейдіть у налаштування, щоб оновити навігацію в системі"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Режим очікування"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Вікно збільшення з накладанням"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Вікно збільшення"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Елементи керування вікна збільшення"</string>
</resources>
diff --git a/packages/SystemUI/res/values-uk/strings_tv.xml b/packages/SystemUI/res/values-uk/strings_tv.xml
index b01316aebd8c..a11e553fea62 100644
--- a/packages/SystemUI/res/values-uk/strings_tv.xml
+++ b/packages/SystemUI/res/values-uk/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Програма без назви)"</string>
<string name="pip_close" msgid="5775212044472849930">"Закрити PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"На весь екран"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Мікрофон активовано"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"Додаток %1$s отримав доступ до вашого мікрофона"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index e30b9aeaa85f..ec11d1fbb1c0 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"مزید جانیں"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"پوری سکرین پر زوم کریں"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"پوری سکرین پر پھیلائیں"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"اسکرین شاٹ"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"اسکرین شاٹ محفوظ ہو رہا ہے…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"اسکرین شاٹ محفوظ ہو رہا ہے…"</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"اسکرین شاٹ محفوظ ہو گیا"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"فون کھولیں"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"صوتی معاون کھولیں"</string>
<string name="camera_label" msgid="8253821920931143699">"کیمرا کھولیں"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"منسوخ کريں"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"تصدیق کریں"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"دوبارہ کوشش کریں"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"تصدیق کو منسوخ کرنے کے لیے تھپتھپائیں"</string>
@@ -241,7 +239,7 @@
<string name="accessibility_quick_settings_airplane_changed_on" msgid="6327378061894076288">"ہوائی جہاز وضع کو آن کر دیا گیا۔"</string>
<string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"مکمل خاموشی"</string>
<string name="accessibility_quick_settings_dnd_alarms_on" msgid="3375848309132140014">"صرف الارمز"</string>
- <string name="accessibility_quick_settings_dnd" msgid="2415967452264206047">"\'ڈسٹرب نہ کریں\'۔"</string>
+ <string name="accessibility_quick_settings_dnd" msgid="2415967452264206047">"ڈسٹرب نہ کریں۔"</string>
<string name="accessibility_quick_settings_dnd_changed_off" msgid="1457150026842505799">"\'ڈسٹرب نہ کریں\' کو آف کر دیا گیا۔"</string>
<string name="accessibility_quick_settings_dnd_changed_on" msgid="186315911607486129">"\'ڈسٹرب نہ کریں\' کو آن کر دیا گیا۔"</string>
<string name="accessibility_quick_settings_bluetooth" msgid="8250942386687551283">"بلوٹوتھ۔"</string>
@@ -308,7 +306,7 @@
<string name="start_dreams" msgid="9131802557946276718">"اسکرین سیور"</string>
<string name="ethernet_label" msgid="2203544727007463351">"ایتھرنیٹ"</string>
<string name="quick_settings_header_onboarding_text" msgid="1918085351115504765">"مزید اختیارات کے لیے آئیکنز کو ٹچ کریں اور دبائیں رکھیں"</string>
- <string name="quick_settings_dnd_label" msgid="7728690179108024338">"\'ڈسٹرب نہ کریں\'"</string>
+ <string name="quick_settings_dnd_label" msgid="7728690179108024338">"ڈسٹرب نہ کریں"</string>
<string name="quick_settings_dnd_priority_label" msgid="6251076422352664571">"صرف ترجیحی"</string>
<string name="quick_settings_dnd_alarms_label" msgid="1241780970469630835">"صرف الارمز"</string>
<string name="quick_settings_dnd_none_label" msgid="8420869988472836354">"مکمل خاموشی"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"آن ہوگی بوقت <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g> تک"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"گہری تھیم"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"گہری تھیم\nبیٹری سیور"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"بیٹری سیور"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"شام کے وقت آن ہوگی"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"طلوع آفتاب تک"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"‏NFC غیر فعال ہے"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"‏NFC فعال ہے"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"کھولنے کیلئے دوبارہ تھپتھپائیں"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"کھولنے کے لیے اوپر سوائپ کريں"</string>
<string name="keyguard_retry" msgid="886802522584053523">"دوبارہ کوشش کرنے کے لیے اوپر سوائپ کريں"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"یہ آلہ آپ کی تنظیم کے زیر انتظام ہے"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"یہ آلہ <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> کے زیر انتظام ہے"</string>
<string name="phone_hint" msgid="6682125338461375925">"فون کیلئے آئیکن سے سوائپ کریں"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"بیٹری سیور آن ہے"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"کارکردگی اور پس منظر کا ڈیٹا کم کر دیتا ہے"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"بیٹری سیور آف کریں"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"ریکارڈ یا کاسٹ کرنے کے دوران، <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> کسی بھی ایسی حساس معلومات کو کیپچر کر سکتا ہے جو آپ کی اسکرین پر ڈسپلے ہوتی ہے یا آپ کے آلہ سے چلائی جاتی ہے، بشمول حساس معلومات جیسے کہ آڈیو، پاسورڈز، ادائیگی کی معلومات، تصاویر اور پیغامات۔"</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"ریکارڈ یا کاسٹ کرنے کے دوران، اس فنکشن کی خدمت کا فراہم کنندہ کسی بھی ایسی حساس معلومات کو کیپچر کر سکتا ہے جو آپ کی اسکرین پر ڈسپلے ہوتی ہے یا آپ کے آلہ سے چلائی جاتی ہے، بشمول حساس معلومات جیسے کہ آڈیو، پاسورڈز، ادائیگی کی معلومات، تصاویر اور پیغامات۔"</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"کاسٹ/ریکارڈ کرنے کے دوران حساس معلومات کا افشاء"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> کو ان تمام معلومات تک رسائی حاصل ہوگی جو آپ کی اسکرین پر مرئی ہے یا ریکارڈنگ یا کاسٹنگ کے دوران آپ کے آلے سے چلائے گئے ہوں۔ اس میں پاس ورڈز، ادائیگی کی تفصیلات، تصاویر، پیغامات، اور آپ کے ذریعے چلائی جانے والی آڈیو جیسی معلومات شامل ہے۔"</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"یہ فنکشن فراہم کرنے والی سروس کو ان تمام معلومات تک رسائی حاصل ہوگی جو آپ کی اسکرین پر مرئی ہے یا ریکارڈنگ یا کاسٹنگ کے دوران آپ کے آلے سے چلائے گئے ہوں۔ اس میں پاس ورڈز، ادائیگی کی تفصیلات، تصاویر، پیغامات، اور آپ کے ذریعے چلائی جانے والی آڈیو جیسی معلومات شامل ہے۔"</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> کے ذریعے ریکارڈنگ یا کاسٹنگ شروع کریں؟"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"دوبارہ نہ دکھائیں"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"سبھی کو صاف کریں"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"نظم کریں"</string>
@@ -753,7 +751,7 @@
<string name="keyboard_shortcut_group_applications_youtube" msgid="5078136084632450333">"YouTube"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"کیلنڈر"</string>
<string name="tuner_full_zen_title" msgid="5120366354224404511">"والیوم کنٹرولز کے ساتھ دکھائیں"</string>
- <string name="volume_and_do_not_disturb" msgid="502044092739382832">"\'ڈسٹرب نہ کریں\'"</string>
+ <string name="volume_and_do_not_disturb" msgid="502044092739382832">"ڈسٹرب نہ کریں"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"والیوم بٹنز کے شارٹ کٹ"</string>
<string name="volume_up_silent" msgid="1035180298885717790">"والیوم بڑھانے پر \'ڈسٹرب نہ کریں\' سے باہر نکلیں"</string>
<string name="battery" msgid="769686279459897127">"بیٹری"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"کی بورڈ سوئچر"</string>
<string name="save" msgid="3392754183673848006">"محفوظ کریں"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"دوبارہ ترتیب دیں"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"بٹن کی چوڑائی ایڈجسٹ کریں"</string>
<string name="clipboard" msgid="8517342737534284617">"کلپ بورڈ"</string>
<string name="accessibility_key" msgid="3471162841552818281">"حسب ضرورت نیویگیشن بٹن"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"دائیں"</string>
<string name="tuner_menu" msgid="363690665924769420">"مینو"</string>
<string name="tuner_app" msgid="6949280415826686972">"<xliff:g id="APP">%1$s</xliff:g> ایپ"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"الرٹس"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"بیٹری"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"اسکرین شاٹس"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"عمومی پیغامات"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> چل رہی ہے"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"انسٹال کیے بغیر کھلنے والی ایپ۔"</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"انسٹال کیے بغیر کھلنے والی ایپ۔ مزید جاننے کے لیے تھپتھپائيں۔"</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"ایپ کی معلومات"</string>
<string name="go_to_web" msgid="636673528981366511">"براؤزر پر جائیں"</string>
<string name="mobile_data" msgid="4564407557775397216">"موبائل ڈیٹا"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"ترتیبات"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"سمجھ آ گئی"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> آپ کی <xliff:g id="TYPES_LIST">%2$s</xliff:g> کا استعمال کر رہی ہے۔"</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"ایپلیکیشنز آپ کی <xliff:g id="TYPES_LIST">%s</xliff:g> کا استعمال کر رہی ہیں۔"</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">"، "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" اور "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"کیمرا"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"مقام"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"مائیکروفون"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"سینسرز آف ہیں"</string>
<string name="device_services" msgid="1549944177856658705">"آلہ کی سروس"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"کوئی عنوان نہیں ہے"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"سسٹم نیویگیشن اپ ڈیٹ کیا گیا۔ تبدیلیاں کرنے کے لیے، ترتیبات پر جائیں۔"</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"سسٹم نیویگیشن اپ ڈیٹ کرنے کے لیے ترتیبات پر جائیں"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"اسٹینڈ بائی"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"میگنیفیکیشن اوورلے ونڈو"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"میگنیفکیشن ونڈو"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"میگنیفکیشن ونڈو کنٹرولز"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ur/strings_tv.xml b/packages/SystemUI/res/values-ur/strings_tv.xml
index 2d1cff60e1d9..8f5ad0d63cf1 100644
--- a/packages/SystemUI/res/values-ur/strings_tv.xml
+++ b/packages/SystemUI/res/values-ur/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(بلا عنوان پروگرام)"</string>
<string name="pip_close" msgid="5775212044472849930">"‏PIP بند کریں"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"فُل اسکرین"</string>
+ <string name="mic_active" msgid="5766614241012047024">"مائیکروفون فعال ہے"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"‏%1$s نے آپ کے مائیکروفون تک رسائی حاصل کی ہے"</string>
</resources>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index ec8639b0f746..df40325284c3 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Batafsil"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Ekranga moslashtirish"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Ekran hajmida cho‘zish"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Skrinshot"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Skrinshot saqlanmoqda…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Skrinshot saqlanmoqda…"</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Skrinshot saqlandi"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"telefonni ochish"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"ovozli yordamni yoqish"</string>
<string name="camera_label" msgid="8253821920931143699">"kamerani ochish"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Bekor qilish"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"OK"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Qayta urinish"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Tekshiruvni bekor qilish uchun bosing"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"<xliff:g id="TIME">%s</xliff:g> da yoqish"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g> gacha"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Tungi mavzu"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Tungi mavzu\nQuvvat tejash"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Quvvat tejash"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Kunbotarda yoqish"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Quyosh chiqqunicha"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC o‘chiq"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC yoniq"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Ochish uchun yana bosing"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Ochish uchun tepaga suring"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Qayta urinish uchun tepaga suring"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Bu – tashkilotingiz tomonidan boshqariladigan qurilma"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Bu – <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> tomonidan boshqariladigan qurilma"</string>
<string name="phone_hint" msgid="6682125338461375925">"Telefonni ochish uchun suring"</string>
@@ -467,13 +463,15 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Quvvat tejash rejimi yoniq"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Unumdorlik pasayadi va fonda internetdan foydalanish cheklanadi"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Quvvat tejash rejimidan chiqish"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Yozib olinayotganda yoki translatsiya paytida, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ijro etilgan audiolar va qurilma ekraniga chiqadigan har qanday axborotni, jumladan, audio, parollar, toʻlov axborotlari, suratlar va xabarlar kabi har qanday shaxsiy maʼlumotlarni yozib olishi mumkin."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Yozib olinayotganda yoki translatsiya paytida, bu funksiya ijro etilgan audiolar va qurilma ekraniga chiqadigan har qanday axborotni, jumladan, audio, parollar, toʻlov axborotlari, suratlar va xabarlar kabi har qanday shaxsiy maʼlumotlarni yozib olishi mumkin."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Translatsiya/yozib olish paytida shaxsiy maʼlumotlarning oshkor boʻlishi"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ekranda chiqqan yoki yozib olish va translatsiya vaqtida ijro etilgan barcha axborotlarga ruxsat oladi. Bu axborotlar parollar, toʻlov tafsilotlari, rasmlar, xabarlar va ijro etilgan audiolardan iborat boʻlishi mumkin."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Bu funksiyani taʼminlovchi xizmat ekranda chiqqan yoki yozib olish va translatsiya vaqtida ijro etilgan barcha axborotlarga ruxsat oladi. Bu axborotlar parollar, toʻlov tafsilotlari, rasmlar, xabarlar va ijro etilgan audiolardan iborat boʻlishi mumkin."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> bilan yozib olinsin yoki translatsiya qilinsinmi?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Boshqa ko‘rsatilmasin"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Hammasini tozalash"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Boshqarish"</string>
- <string name="notification_section_header_gentle" msgid="3044910806569985386">"Sokin bildirishnomalar"</string>
+ <string name="notification_section_header_gentle" msgid="3044910806569985386">"Tovushsiz bildirishnomalar"</string>
<string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Barcha tovushsiz bildirishnomalarni tozalash"</string>
<string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Bezovta qilinmasin rejimida bildirishnomalar pauza qilingan"</string>
<string name="media_projection_action_text" msgid="3634906766918186440">"Boshlash"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Klaviaturani almashtirish"</string>
<string name="save" msgid="3392754183673848006">"Saqlash"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Asliga qaytarish"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Tugma enini moslashtiring"</string>
<string name="clipboard" msgid="8517342737534284617">"Vaqtinchalik xotira"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Maxsus navigatsiya tugmasi"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"O‘ngga"</string>
<string name="tuner_menu" msgid="363690665924769420">"Menyu"</string>
<string name="tuner_app" msgid="6949280415826686972">"<xliff:g id="APP">%1$s</xliff:g> ilovasi"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Bildirishnomalar"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Batareya"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Skrinshotlar"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Umumiy xabarlar"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> ishlayapti"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Ilova o‘rnatilmasdan ochildi."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Ilova o‘rnatilmasdan ochildi. Batafsil axborot uchun bu yerga bosing."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Ilova haqida"</string>
<string name="go_to_web" msgid="636673528981366511">"Brauzerni ochish"</string>
<string name="mobile_data" msgid="4564407557775397216">"Mobil internet"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Sozlamalar"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"OK"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> ishlatmoqda: <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Ilovalarda ishlatilmoqda: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" va "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"joylashuv"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensorlar nofaol"</string>
<string name="device_services" msgid="1549944177856658705">"Qurilma xizmatlari"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Nomsiz"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Tizim navigatsiyasi yangilandi. Buni Sozlamalar orqali oʻzgartirishingiz mumkin."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Tizim navigatsiyasini yangilash uchun Sozlamalarni oching"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Kutib turing"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Kattalashtirish oynasining ustidan ochilishi"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Kattalashtirish oynasi"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Kattalashtirish oynasi sozlamalari"</string>
</resources>
diff --git a/packages/SystemUI/res/values-uz/strings_tv.xml b/packages/SystemUI/res/values-uz/strings_tv.xml
index 16cddfdab709..6fb5d732bfbd 100644
--- a/packages/SystemUI/res/values-uz/strings_tv.xml
+++ b/packages/SystemUI/res/values-uz/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Nomsiz)"</string>
<string name="pip_close" msgid="5775212044472849930">"Kadr ichida kadr – chiqish"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Butun ekran"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Mikrofon faol"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s mikrofondan foydalandi"</string>
</resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 9291563f5268..8a99f436a34f 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Tìm hiểu thêm"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"T.phóng để lấp đầy m.hình"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Giãn ra để lấp đầy m.hình"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Chụp ảnh màn hình"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Đang lưu ảnh chụp màn hình..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Đang lưu ảnh chụp màn hình..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Đã lưu ảnh chụp màn hình"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"mở điện thoại"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"mở trợ lý thoại"</string>
<string name="camera_label" msgid="8253821920931143699">"mở máy ảnh"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Hủy"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Xác nhận"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Thử lại"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Nhấn để hủy quá trình xác thực"</string>
@@ -309,7 +307,7 @@
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_header_onboarding_text" msgid="1918085351115504765">"Chạm và giữ các biểu tượng để xem thêm tùy chọn khác"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Không làm phiền"</string>
- <string name="quick_settings_dnd_priority_label" msgid="6251076422352664571">"Chỉ ưu tiên"</string>
+ <string name="quick_settings_dnd_priority_label" msgid="6251076422352664571">"Chỉ cho các mục ưu tiên"</string>
<string name="quick_settings_dnd_alarms_label" msgid="1241780970469630835">"Chỉ chuông báo"</string>
<string name="quick_settings_dnd_none_label" msgid="8420869988472836354">"Hoàn toàn tắt tiếng"</string>
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Bật vào lúc <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Cho đến <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Giao diện tối"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Giao diện tối\nTrình tiết kiệm pin"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Trình tiết kiệm pin"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Bật khi trời tối"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Cho đến khi trời sáng"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC đã được tắt"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC đã được bật"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Nhấn lại để mở"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Vuốt lên để mở"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Vuốt lên để thử lại"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Thiết bị này do tổ chức của bạn quản lý"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Thiết bị này được <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> quản lý"</string>
<string name="phone_hint" msgid="6682125338461375925">"Vuốt từ biểu tượng để mở điện thoại"</string>
@@ -423,7 +419,7 @@
<string name="camera_hint" msgid="4519495795000658637">"Vuốt từ biểu tượng để mở máy ảnh"</string>
<string name="interruption_level_none_with_warning" msgid="8394434073508145437">"Tắt tiếng hoàn toàn. Cài đặt này cũng sẽ tắt tiếng trình đọc màn hình."</string>
<string name="interruption_level_none" msgid="219484038314193379">"Hoàn toàn tắt tiếng"</string>
- <string name="interruption_level_priority" msgid="661294280016622209">"Chỉ ưu tiên"</string>
+ <string name="interruption_level_priority" msgid="661294280016622209">"Chỉ cho các mục ưu tiên"</string>
<string name="interruption_level_alarms" msgid="2457850481335846959">"Chỉ chuông báo"</string>
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"Hoàn toàn\ntắt tiếng"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"Chỉ\nưu tiên"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Trình tiết kiệm pin đang bật"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Giảm hiệu suất và dữ liệu nền"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Tắt trình tiết kiệm pin"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Trong khi quay hoặc truyền, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> có thể ghi lại mọi thông tin nhạy cảm hiển thị trên màn hình hoặc phát trên thiết bị của bạn, bao gồm cả thông tin nhạy cảm như âm thanh, mật khẩu, thông tin thanh toán, ảnh và tin nhắn."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Trong khi quay hoặc truyền, dịch vụ cung cấp chức năng này có thể ghi lại mọi thông tin nhạy cảm hiển thị trên màn hình hoặc phát trên thiết bị của bạn, bao gồm cả thông tin nhạy cảm như âm thanh, mật khẩu, thông tin thanh toán, ảnh và tin nhắn."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Để lộ thông tin nhạy cảm khi truyền/quay"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> sẽ có quyền truy cập vào tất cả các thông tin hiển thị trên màn hình của bạn hoặc phát từ thiết bị trong khi ghi âm/ghi hình hoặc truyền, bao gồm cả thông tin như mật khẩu, chi tiết thanh toán, ảnh, tin nhắn và âm thanh mà bạn phát."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Dịch vụ cung cấp chức năng này có quyền truy cập vào tất cả các thông tin hiển thị trên màn hình của bạn hoặc phát từ thiết bị trong khi ghi âm/ghi hình hoặc truyền, bao gồm cả thông tin như mật khẩu, chi tiết thanh toán, ảnh, tin nhắn và âm thanh mà bạn phát."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Bắt đầu ghi âm/ghi hình hoặc truyền bằng <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Không hiển thị lại"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Xóa tất cả"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Quản lý"</string>
@@ -667,12 +665,10 @@
<string name="inline_keep_showing_app" msgid="4393429060390649757">"Tiếp tục hiển thị các thông báo từ ứng dụng này?"</string>
<string name="notification_silence_title" msgid="8608090968400832335">"Im lặng"</string>
<string name="notification_alert_title" msgid="7629202599338071971">"Cảnh báo"</string>
- <!-- no translation found for notification_bubble_title (8330481035191903164) -->
- <skip />
+ <string name="notification_bubble_title" msgid="8330481035191903164">"Bong bóng"</string>
<string name="notification_channel_summary_low" msgid="7300447764759926720">"Giúp bạn tập trung bằng cách tắt tiếng hoặc không rung."</string>
<string name="notification_channel_summary_default" msgid="3539949463907902037">"Thu hút sự chú ý của bạn bằng cách bật tiếng hoặc rung."</string>
- <!-- no translation found for notification_channel_summary_bubble (7235935211580860537) -->
- <skip />
+ <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Luôn chú ý vào nội dung này bằng phím tắt nổi."</string>
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Không thể sửa đổi các thông báo này."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Không thể định cấu hình nhóm thông báo này tại đây"</string>
<string name="notification_delegate_header" msgid="1264510071031479920">"Thông báo đã xử lý qua máy chủ proxy"</string>
@@ -788,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Trình chuyển đổi bàn phím"</string>
<string name="save" msgid="3392754183673848006">"Lưu"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Đặt lại"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Điều chỉnh chiều rộng nút"</string>
<string name="clipboard" msgid="8517342737534284617">"Khay nhớ tạm"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Nút điều hướng tùy chỉnh"</string>
@@ -885,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Bên phải"</string>
<string name="tuner_menu" msgid="363690665924769420">"Menu"</string>
<string name="tuner_app" msgid="6949280415826686972">"Ứng dụng <xliff:g id="APP">%1$s</xliff:g>"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Cảnh báo"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Pin"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Ảnh chụp màn hình"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Thông báo chung"</string>
@@ -896,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> đang chạy"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Ứng dụng được mở mà không cần cài đặt."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Ứng dụng được mở mà không cần cài đặt. Nhấn để tìm hiểu thêm."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Thông tin ứng dụng"</string>
<string name="go_to_web" msgid="636673528981366511">"Đi tới trình duyệt"</string>
<string name="mobile_data" msgid="4564407557775397216">"Dữ liệu di động"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -931,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Cài đặt"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"OK"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Trích xuất bộ nhớ SysUI"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> đang dùng <xliff:g id="TYPES_LIST">%2$s</xliff:g> của bạn."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Các ứng dụng đang dùng <xliff:g id="TYPES_LIST">%s</xliff:g> của bạn."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" và "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"máy ảnh"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"vị trí"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"micrô"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Tắt cảm biến"</string>
<string name="device_services" msgid="1549944177856658705">"Dịch vụ cho thiết bị"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Không có tiêu đề"</string>
@@ -960,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Đã cập nhật chế độ di chuyển trên hệ thống. Để thay đổi, hãy chuyển đến phần Cài đặt."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Chuyển đến phần Cài đặt để cập nhật chế độ di chuyển trên hệ thống"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Chế độ chờ"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Cửa sổ lớp phủ phóng to"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Cửa sổ phóng to"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Các tùy chọn điều khiển cửa sổ phóng to"</string>
</resources>
diff --git a/packages/SystemUI/res/values-vi/strings_tv.xml b/packages/SystemUI/res/values-vi/strings_tv.xml
index f7c97b832249..03b53561d06e 100644
--- a/packages/SystemUI/res/values-vi/strings_tv.xml
+++ b/packages/SystemUI/res/values-vi/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Không có chương trình tiêu đề)"</string>
<string name="pip_close" msgid="5775212044472849930">"Đóng PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Toàn màn hình"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Micrô đang hoạt động"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s đang dùng micrô của bạn"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 55db2b559281..66bf66bba47b 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"了解详情"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"缩放以填满屏幕"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"拉伸以填满屏幕"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"屏幕截图"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"正在保存屏幕截图..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"正在保存屏幕截图..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"已保存屏幕截图"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"打开电话"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"打开语音助理"</string>
<string name="camera_label" msgid="8253821920931143699">"打开相机"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"取消"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"确认"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"重试"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"点按即可取消身份验证"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"在<xliff:g id="TIME">%s</xliff:g> 开启"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"直到<xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"深色主题"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"深色主题背景\n省电模式"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"省电模式"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"在日落时开启"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"在日出时关闭"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC 已停用"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC 已启用"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"再次点按即可打开"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"向上滑动即可打开"</string>
<string name="keyguard_retry" msgid="886802522584053523">"向上滑动即可重试"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"此设备由您所属单位管理"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"此设备是由<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>托管"</string>
<string name="phone_hint" msgid="6682125338461375925">"滑动图标即可拨打电话"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"省电模式已开启"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"降低性能并限制后台流量"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"关闭省电模式"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"在录制或投射内容时,<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>可以获取您屏幕上显示或设备中播放的所有敏感信息,例如音频、密码、付款信息、照片、消息等。"</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"在录制或投射内容时,提供录制或投射功能的服务可以获取您屏幕上显示或设备中播放的所有敏感信息,例如音频、密码、付款信息、照片、消息等。"</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"在投射/录制时显示敏感信息"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"在录制或投射内容时,<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>将可获取您屏幕上显示或设备中播放的所有信息,其中包括密码、付款明细、照片、消息以及您播放的音频等信息。"</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"在录制或投射内容时,提供此功能的服务将可获取您屏幕上显示或设备中播放的所有信息,其中包括密码、付款明细、照片、消息以及您播放的音频等信息。"</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"要开始使用<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>录制或投射内容吗?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"不再显示"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"全部清除"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"管理"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"键盘切换器"</string>
<string name="save" msgid="3392754183673848006">"保存"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"重置"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"调整按钮宽度"</string>
<string name="clipboard" msgid="8517342737534284617">"剪贴板"</string>
<string name="accessibility_key" msgid="3471162841552818281">"自定义导航按钮"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"向右"</string>
<string name="tuner_menu" msgid="363690665924769420">"菜单"</string>
<string name="tuner_app" msgid="6949280415826686972">"<xliff:g id="APP">%1$s</xliff:g>应用"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"提醒"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"电池"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"屏幕截图"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"常规消息"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"正在运行<xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"已打开免安装应用。"</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"已打开免安装应用。点按即可了解详情。"</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"应用信息"</string>
<string name="go_to_web" msgid="636673528981366511">"转到浏览器"</string>
<string name="mobile_data" msgid="4564407557775397216">"移动数据"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> - <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"设置"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"知道了"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"转储 SysUI 堆"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g>正在使用您的<xliff:g id="TYPES_LIST">%2$s</xliff:g>。"</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"有多个应用正在使用您的<xliff:g id="TYPES_LIST">%s</xliff:g>。"</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">"、 "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" 和 "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"相机"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"位置信息"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"麦克风"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"已关闭传感器"</string>
<string name="device_services" msgid="1549944177856658705">"设备服务"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"无标题"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"系统导航已更新。要进行更改,请转到“设置”。"</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"转到“设置”即可更新系统导航"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"待机"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"放大叠加窗口"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"放大窗口"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"放大窗口控件"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings_tv.xml b/packages/SystemUI/res/values-zh-rCN/strings_tv.xml
index e3c18205c83a..acb6ee0123e6 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings_tv.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(节目没有标题)"</string>
<string name="pip_close" msgid="5775212044472849930">"关闭画中画"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"全屏"</string>
+ <string name="mic_active" msgid="5766614241012047024">"麦克风处于启用状态"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s访问过您的麦克风"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 8a28aef0be13..10348fbce886 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"瞭解詳情"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"放大為全螢幕"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"放大為全螢幕"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"螢幕截圖"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"正在儲存螢幕擷取畫面..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"正在儲存螢幕擷取畫面..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"螢幕擷取畫面已儲存"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"開啟電話"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"開啟語音助手"</string>
<string name="camera_label" msgid="8253821920931143699">"開啟相機"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"取消"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"確認"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"請再試一次"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"輕按即可取消驗證"</string>
@@ -381,13 +379,15 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"上限為 <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"<xliff:g id="DATA_LIMIT">%s</xliff:g> 警告"</string>
<string name="quick_settings_work_mode_label" msgid="2754212289804324685">"工作設定檔"</string>
- <string name="quick_settings_night_display_label" msgid="8180030659141778180">"夜燈模式"</string>
+ <string name="quick_settings_night_display_label" msgid="8180030659141778180">"夜間模式"</string>
<string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"在日落時開啟"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"在日出時關閉"</string>
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"<xliff:g id="TIME">%s</xliff:g> 開啟"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"直到<xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"深色主題背景"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"深色主題背景\n省電模式"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"省電模式"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"在日落時開啟"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"在日出時關閉"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC 已停用"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC 已啟用"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"再次輕按即可開啟"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"向上滑動即可開啟"</string>
<string name="keyguard_retry" msgid="886802522584053523">"請向上滑動以再試一次"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"此裝置由您的機構管理"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"此裝置由<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>管理"</string>
<string name="phone_hint" msgid="6682125338461375925">"從圖示滑動即可使用手機功能"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"省電模式已開啟"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"降低效能並限制背景數據傳輸"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"關閉省電模式"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"錄製或投放期間,「<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>」可以擷取螢幕顯示或裝置播放的任何敏感資料,包括音效、密碼、付款資料、相片和訊息等敏感資料。"</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"錄製或投放期間,此功能的服務供應商可以擷取螢幕顯示或裝置播放的任何敏感資料,包括音效、密碼、付款資料、相片和訊息等敏感資料。"</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"在投放/錄製期間披露敏感資訊"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"在錄影或投放時,「<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>」可以存取螢幕顯示或裝置播放的任何資料,當中包括密碼、付款詳情、相片、訊息和播放的語音等。"</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"在錄影或投放時,此功能的服務供應商可以存取螢幕顯示或裝置播放的任何資料,當中包括密碼、付款詳情、相片、訊息和播放的語音等。"</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"要使用「<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>」開始錄影或投放嗎?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"不用再顯示"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"全部清除"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"管理"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"鍵盤切換工具"</string>
<string name="save" msgid="3392754183673848006">"儲存"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"重設"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"調整按鈕寬度"</string>
<string name="clipboard" msgid="8517342737534284617">"剪貼簿"</string>
<string name="accessibility_key" msgid="3471162841552818281">"自訂導覽按鈕"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"向右"</string>
<string name="tuner_menu" msgid="363690665924769420">"選單"</string>
<string name="tuner_app" msgid="6949280415826686972">"「<xliff:g id="APP">%1$s</xliff:g>」應用程式"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"通知"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"電池"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"螢幕擷取畫面"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"一般訊息"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> 運作中"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"已開啟免安裝應用程式。"</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"已開啟免安裝應用程式。輕按即可瞭解詳情。"</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"應用程式資料"</string>
<string name="go_to_web" msgid="636673528981366511">"前往瀏覽器"</string>
<string name="mobile_data" msgid="4564407557775397216">"流動數據"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> - <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"設定"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"知道了"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"轉儲 SysUI 堆"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"「<xliff:g id="APP">%1$s</xliff:g>」正在使用<xliff:g id="TYPES_LIST">%2$s</xliff:g>。"</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"有多個應用程式正在使用<xliff:g id="TYPES_LIST">%s</xliff:g>。"</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">"、 "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" 和 "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"相機"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"位置"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"麥克風"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"感應器已關閉"</string>
<string name="device_services" msgid="1549944177856658705">"裝置服務"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"無標題"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"系統導覽已更新。如需變更,請前往「設定」。"</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"前往「設定」更新系統導覽"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"待機"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"放大重疊視窗"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"放大視窗"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"放大視窗控制項"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings_tv.xml b/packages/SystemUI/res/values-zh-rHK/strings_tv.xml
index 24fd41a9169e..3cf2b43ed1ff 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings_tv.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(沒有標題的節目)"</string>
<string name="pip_close" msgid="5775212044472849930">"關閉 PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"全螢幕"</string>
+ <string name="mic_active" msgid="5766614241012047024">"麥克風已啟用"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s 曾存取您的麥克風"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 79f336d50be9..1586bb8eb1e6 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"瞭解詳情"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"放大為全螢幕"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"放大為全螢幕"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"擷取螢幕畫面"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"正在儲存螢幕截圖…"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"正在儲存螢幕截圖…"</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"螢幕截圖已儲存"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"開啟電話"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"開啟語音小幫手"</string>
<string name="camera_label" msgid="8253821920931143699">"開啟攝影機"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"取消"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"確認"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"再試一次"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"輕觸即可取消驗證"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"<xliff:g id="TIME">%s</xliff:g> 開啟"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g> 關閉"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"深色主題"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"深色主題\n節約耗電量"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"節約耗電量"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"於日落時開啟"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"於日出時關閉"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC 已停用"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC 已啟用"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"再次輕觸即可開啟"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"向上滑動即可開啟"</string>
<string name="keyguard_retry" msgid="886802522584053523">"向上滑動即可重試"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"這個裝置是由貴機構所管理"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"這個裝置是由 <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> 所管理"</string>
<string name="phone_hint" msgid="6682125338461375925">"滑動手機圖示即可啟用"</string>
@@ -439,7 +435,7 @@
<string name="user_add_user" msgid="4336657383006913022">"新增使用者"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"新使用者"</string>
<string name="guest_nickname" msgid="1863770639799615889">"訪客"</string>
- <string name="guest_new_guest" msgid="962155336259570156">"新增邀請對象"</string>
+ <string name="guest_new_guest" msgid="962155336259570156">"新增訪客"</string>
<string name="guest_exit_guest" msgid="4030840507598850886">"移除訪客"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"移除訪客?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"這個工作階段中的所有應用程式和資料都會遭到刪除。"</string>
@@ -447,7 +443,7 @@
<string name="guest_wipe_session_title" msgid="7147965814683990944">"訪客你好,歡迎回來!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"你要繼續這個工作階段嗎?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"重新開始"</string>
- <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"是,請繼續"</string>
+ <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"是,繼續"</string>
<string name="guest_notification_title" msgid="4434456703930764167">"訪客使用者"</string>
<string name="guest_notification_text" msgid="4202692942089571351">"如要刪除應用程式和資料,請移除訪客使用者"</string>
<string name="guest_notification_remove_action" msgid="4153019027696868099">"移除訪客"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"節約耗電量模式已開啟"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"降低效能並限制背景數據傳輸"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"關閉節約耗電量模式"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"在錄製或投放內容時,「<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>」可擷取畫面所顯示或裝置所播放的任何機密資訊,例如音訊、密碼、付款資訊、相片和訊息等。"</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"在錄製或投放內容時,提供這項功能的服務可擷取畫面所顯示或裝置所播放的任何機密資訊,例如音訊、密碼、付款資訊、相片和訊息等。"</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"在投放/錄製時顯示機密資訊"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"在錄製或投放內容時,「<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>」可存取畫面上顯示的任何資訊或裝置播放的任何內容,包括密碼、付款詳情、相片、訊息和你播放的音訊。"</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"在錄製或投放內容時,提供這項功能的服務可存取畫面上顯示的任何資訊或裝置播放的任何內容,包括密碼、付款詳情、相片、訊息和你播放的音訊。"</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"要使用「<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>」開始錄製或投放內容嗎?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"不要再顯示"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"全部清除"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"管理"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"鍵盤切換工具"</string>
<string name="save" msgid="3392754183673848006">"儲存"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"重設"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"調整按鈕寬度"</string>
<string name="clipboard" msgid="8517342737534284617">"剪貼簿"</string>
<string name="accessibility_key" msgid="3471162841552818281">"自訂導覽按鈕"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"向右"</string>
<string name="tuner_menu" msgid="363690665924769420">"選單"</string>
<string name="tuner_app" msgid="6949280415826686972">"「<xliff:g id="APP">%1$s</xliff:g>」應用程式"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"快訊"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"電池"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"螢幕截圖"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"一般訊息"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"正在執行「<xliff:g id="APP">%1$s</xliff:g>」"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"已開啟免安裝應用程式。"</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"已開啟免安裝應用程式。輕觸即可瞭解詳情。"</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"應用程式資訊"</string>
<string name="go_to_web" msgid="636673528981366511">"前往瀏覽器"</string>
<string name="mobile_data" msgid="4564407557775397216">"行動數據"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> - <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"設定"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"我知道了"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"傾印 SysUI 記憶體快照"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"「<xliff:g id="APP">%1$s</xliff:g>」正在使用<xliff:g id="TYPES_LIST">%2$s</xliff:g>。"</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"有多個應用程式正在使用<xliff:g id="TYPES_LIST">%s</xliff:g>。"</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">"、 "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" 和 "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"相機"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"位置"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"麥克風"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"已關閉感應器"</string>
<string name="device_services" msgid="1549944177856658705">"裝置服務"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"無標題"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"系統操作機制已更新。如要進行變更,請前往「設定」。"</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"請前往「設定」更新系統操作機制"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"待機"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"放大重疊視窗"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"放大視窗"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"放大視窗控制項"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings_tv.xml b/packages/SystemUI/res/values-zh-rTW/strings_tv.xml
index 0b246613ee97..b48fc6f99755 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings_tv.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(無標題的節目)"</string>
<string name="pip_close" msgid="5775212044472849930">"關閉子母畫面"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"全螢幕"</string>
+ <string name="mic_active" msgid="5766614241012047024">"麥克風已開啟"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"「%1$s」已存取你的麥克風"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index bc3fcc0f71a5..7ae14cc2e1a7 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -70,8 +70,7 @@
<string name="learn_more" msgid="4690632085667273811">"Funda kabanzi"</string>
<string name="compat_mode_on" msgid="4963711187149440884">"Sondeza ukugcwalisa isikrini"</string>
<string name="compat_mode_off" msgid="7682459748279487945">"Nweba ukugcwalisa isikrini"</string>
- <!-- no translation found for global_action_screenshot (2760267567509131654) -->
- <skip />
+ <string name="global_action_screenshot" msgid="2760267567509131654">"Isithombe-skrini"</string>
<string name="screenshot_saving_ticker" msgid="6519186952674544916">"Ilondoloz umfanekiso weskrini..."</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"Ilondoloz umfanekiso weskrini..."</string>
<string name="screenshot_saved_title" msgid="8893267638659083153">"Isithombe-skrini silondoloziwe"</string>
@@ -119,8 +118,7 @@
<string name="phone_label" msgid="5715229948920451352">"vula ifoni"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"vula isilekeleli sezwi"</string>
<string name="camera_label" msgid="8253821920931143699">"vula ikhamera"</string>
- <!-- no translation found for cancel (1089011503403416730) -->
- <skip />
+ <string name="cancel" msgid="1089011503403416730">"Khansela"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"Qinisekisa"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"Zama futhi"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Thepha ukuze ukhansele ukufakazela ubuqiniso"</string>
@@ -387,7 +385,9 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Kuvulwe ngo-<xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Kuze kube ngu-<xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Itimu emnyama"</string>
- <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="4506078248306696253">"Itimu emnyama\nIsilondolozi sebethri"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Isilondolozi sebhethri"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Kuvulwe ekushoneni kwelanga"</string>
+ <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Kuze kube sekuphumeni kwelanga"</string>
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"I-NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"I-NFC ikhutshaziwe"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"I-NFC inikwe amandla"</string>
@@ -412,10 +412,6 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Thepha futhi ukuze uvule"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Swayiphela phezulu ukuze uvule"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Swayiphela phezulu ukuze uzame futhi"</string>
- <!-- no translation found for dock_alignment_slow_charging (5148122851798085807) -->
- <skip />
- <!-- no translation found for dock_alignment_not_charging (1002617659995575624) -->
- <skip />
<string name="do_disclosure_generic" msgid="2388094207542706440">"Le divayisi iphethwe inhlangano yakho"</string>
<string name="do_disclosure_with_name" msgid="9113122674419739611">"Le divayisi iphethwe yi-<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Swayiphela ifoni kusukela kusithonjana"</string>
@@ -467,9 +463,11 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"Isilondolozi sebhethri sivuliwe"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Sehlisa ukusebenza nedatha yasemuva"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Vala isilondolozi sebhethri"</string>
- <string name="media_projection_dialog_text" msgid="5509958417853154019">"Ngenkathi irekhoda noma isakaza, i-<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ingathatha noma iluphi ulwazi olunozwelo oluboniswa kusikrini sakho noma oludlalwa kusukela kudivayisi yakho, okufaka ulwazi olunozwelo olufana nomsindo, amaphasiwedi, ulwazi lokukhokha, izithombe kanye nemilayezo."</string>
- <string name="media_projection_dialog_service_text" msgid="1046871290896249896">"Ngenkathi irekhoda noma isakaza, isevisi enikeza lokhu kusebenza ingathatha noma iluphi ulwazi olunozwelo oluboniswa kusikrini sakho noma oludlalwa kusukela kudivayisi yakho, okufaka ulwazi olunozwelo olufana nomsindo, amaphasiwedi, ulwazi lokukhokha, izithombe kanye nemilayezo."</string>
- <string name="media_projection_dialog_title" msgid="6379655487632663290">"Ukuveza ulwazi oluzwelayo ngesikhathi sokusakaza/ukurekhoda"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> izithola ukufinyelela kulo lonke ulwazi olubonakalayo esikrinini sakho noma idlalwe kusuka kudivayisi yakho ngenkathi urekhoda noma usakaza. Lokhu kubandakanya ulwazi olufana namaphasiwedi, imininingwane yenkokhelo, izithombe, imilayezo, nomsindo owudlalayo."</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Isevisi enikezela ngalo msebenzi izothola ukufinyelela kulo lonke ulwazi olubonakalayo esikrinini sakho noma oludlalwa kusuka kudivayisi yakho ngenkathi urekhoda noma usakaza. Lokhu kubandakanya ulwazi olufana namaphasiwedi, imininingwane yenkokhelo, izithombe, imilayezo, nomsindo owudlalayo."</string>
+ <!-- no translation found for media_projection_dialog_service_title (2888507074107884040) -->
+ <skip />
+ <string name="media_projection_dialog_title" msgid="3316063622495360646">"Qala ukurekhoda noma ukusakaza nge-<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"Ungabonisi futhi"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Sula konke"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Phatha"</string>
@@ -786,8 +784,7 @@
</string-array>
<string name="menu_ime" msgid="5677467548258017952">"Isishintshi sekhibhodi"</string>
<string name="save" msgid="3392754183673848006">"Londoloza"</string>
- <!-- no translation found for reset (8715144064608810383) -->
- <skip />
+ <string name="reset" msgid="8715144064608810383">"Setha kabusha"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Lungisa ububanzi benkinobho"</string>
<string name="clipboard" msgid="8517342737534284617">"Ibhodi lokunamathisela"</string>
<string name="accessibility_key" msgid="3471162841552818281">"Inkinobho yokuzula yangokwezifiso"</string>
@@ -883,8 +880,7 @@
<string name="tuner_right" msgid="8247571132790812149">"Kwesokudla"</string>
<string name="tuner_menu" msgid="363690665924769420">"Imenyu"</string>
<string name="tuner_app" msgid="6949280415826686972">"<xliff:g id="APP">%1$s</xliff:g> uhlelo lokusebenza"</string>
- <!-- no translation found for notification_channel_alerts (3385787053375150046) -->
- <skip />
+ <string name="notification_channel_alerts" msgid="3385787053375150046">"Izexwayiso"</string>
<string name="notification_channel_battery" msgid="9219995638046695106">"Ibhethri"</string>
<string name="notification_channel_screenshot" msgid="7665814998932211997">"Izithombe-skrini"</string>
<string name="notification_channel_general" msgid="4384774889645929705">"Imilayezo ejwayelekile"</string>
@@ -894,8 +890,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> esebenzayo"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Uhlelo lokusebenza luvulwe ngaphndle kokufakwa."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Uhlelo lokusebenza luvulwe ngaphandle kokufakwa. Thepha ukuze ufunde kabanzi."</string>
- <!-- no translation found for app_info (5153758994129963243) -->
- <skip />
+ <string name="app_info" msgid="5153758994129963243">"Ulwazi lohlelo lokusebenza"</string>
<string name="go_to_web" msgid="636673528981366511">"Iya kusiphequluli"</string>
<string name="mobile_data" msgid="4564407557775397216">"Idatha yeselula"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -929,13 +924,6 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Izilungiselelo"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Ngiyezwa"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"I-Dump SysUI Heap"</string>
- <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"I-<xliff:g id="APP">%1$s</xliff:g> isebenzisa i-<xliff:g id="TYPES_LIST">%2$s</xliff:g> yakho."</string>
- <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Izinhlelo zokusebenza zisebenzisa i-<xliff:g id="TYPES_LIST">%s</xliff:g> yakho."</string>
- <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
- <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" kanye "</string>
- <string name="privacy_type_camera" msgid="7974051382167078332">"ikhamera"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"indawo"</string>
- <string name="privacy_type_microphone" msgid="9136763906797732428">"imakrofoni"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Izinzwa zivaliwe"</string>
<string name="device_services" msgid="1549944177856658705">"Amasevisi edivayisi"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Asikho isihloko"</string>
@@ -958,4 +946,7 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Ukuzulazula kwesistimu kubuyekeziwe. Ukuze wenze ushintsho, hamba kokuthi Izilungiselelo."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Hamba kuzilungiselelo ukuze ubuyekeze ukuzulazula kwesistimu"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Ilindile"</string>
+ <string name="magnification_overlay_title" msgid="6584179429612427958">"Iwindi Lembondela Lesikhulisi"</string>
+ <string name="magnification_window_title" msgid="4863914360847258333">"Iwindi Lesikhulisi"</string>
+ <string name="magnification_controls_title" msgid="8421106606708891519">"Izilawuli Zewindi Lesikhulisi"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zu/strings_tv.xml b/packages/SystemUI/res/values-zu/strings_tv.xml
index 052cdf208705..c6f8d3ffcc74 100644
--- a/packages/SystemUI/res/values-zu/strings_tv.xml
+++ b/packages/SystemUI/res/values-zu/strings_tv.xml
@@ -23,4 +23,6 @@
<string name="pip_notification_unknown_title" msgid="4413256731340767259">"(Alukho uhlelo lwesihloko)"</string>
<string name="pip_close" msgid="5775212044472849930">"Vala i-PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Iskrini esigcwele"</string>
+ <string name="mic_active" msgid="5766614241012047024">"Imakrofoni iyasebenza"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s ifinyelele imakrofoni yakho"</string>
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 45318fde4f0e..52c0a26f09ba 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1140,13 +1140,16 @@
<string name="battery_saver_notification_action_text">Turn off Battery Saver</string>
<!-- Media projection permission dialog warning text. [CHAR LIMIT=NONE] -->
- <string name="media_projection_dialog_text">While recording or casting, <xliff:g id="app_seeking_permission" example="Hangouts">%s</xliff:g> can capture any sensitive information that is displayed on your screen or played from your device, including sensitive information such as audio, passwords, payment info, photos and messages.</string>
+ <string name="media_projection_dialog_text"><xliff:g id="app_seeking_permission" example="Hangouts">%s</xliff:g> will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information such as passwords, payment details, photos, messages, and audio that you play.</string>
<!-- Media projection permission dialog warning text for system services. [CHAR LIMIT=NONE] -->
- <string name="media_projection_dialog_service_text">While recording or casting, the service providing this function can capture any sensitive information that is displayed on your screen or played from your device, including sensitive information such as audio, passwords, payment info, photos and messages.</string>
+ <string name="media_projection_dialog_service_text">The service providing this function will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information such as passwords, payment details, photos, messages, and audio that you play.</string>
+
+ <!-- Media projection permission dialog warning title for system services. [CHAR LIMIT=NONE] -->
+ <string name="media_projection_dialog_service_title">Start recording or casting?</string>
<!-- Media projection permission dialog warning title. [CHAR LIMIT=NONE] -->
- <string name="media_projection_dialog_title">Exposing sensitive info during casting/recording </string>
+ <string name="media_projection_dialog_title">Start recording or casting with <xliff:g id="app_seeking_permission" example="Hangouts">%s</xliff:g>?</string>
<!-- Media projection permission dialog permanent grant check box. [CHAR LIMIT=NONE] -->
<string name="media_projection_remember_text">Don\'t show again</string>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityCompat.java
index 18dc185c6fbe..0c7e56e0715e 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityCompat.java
@@ -37,6 +37,13 @@ public class ActivityCompat {
}
/**
+ * @see Activity#unregisterRemoteAnimations
+ */
+ public void unregisterRemoteAnimations() {
+ mWrapped.unregisterRemoteAnimations();
+ }
+
+ /**
* @see android.view.ViewDebug#dumpv2(View, ByteArrayOutputStream)
*/
public boolean encodeViewHierarchy(ByteArrayOutputStream out) {
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 9f13718ec236..e28b1e2806e9 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
@@ -73,6 +73,8 @@ public class WindowManagerWrapper {
public static final int WINDOWING_MODE_UNDEFINED = WindowConfiguration.WINDOWING_MODE_UNDEFINED;
public static final int WINDOWING_MODE_FULLSCREEN =
WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+ public static final int WINDOWING_MODE_MULTI_WINDOW =
+ WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
public static final int WINDOWING_MODE_PINNED = WindowConfiguration.WINDOWING_MODE_PINNED;
public static final int WINDOWING_MODE_SPLIT_SCREEN_PRIMARY =
WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
index caf5ee02df06..4a5bc2a8e28e 100644
--- a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
+++ b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
@@ -43,7 +43,7 @@ import com.android.internal.telephony.TelephonyIntents;
import com.android.settingslib.WirelessUtils;
import com.android.systemui.Dependency;
import com.android.systemui.R;
-import com.android.systemui.dagger.qualifiers.MainResources;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import java.util.List;
@@ -302,7 +302,7 @@ public class CarrierTextController {
}
if (simState == TelephonyManager.SIM_STATE_READY) {
ServiceState ss = mKeyguardUpdateMonitor.mServiceStates.get(subId);
- if (ss != null && ss.getDataRegState() == ServiceState.STATE_IN_SERVICE) {
+ if (ss != null && ss.getDataRegistrationState() == ServiceState.STATE_IN_SERVICE) {
// hack for WFC (IWLAN) not turning off immediately once
// Wi-Fi is disassociated or disabled
if (ss.getRilDataRadioTechnology() != ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN
@@ -608,7 +608,7 @@ public class CarrierTextController {
private boolean mShowMissingSim;
@Inject
- public Builder(Context context, @MainResources Resources resources) {
+ public Builder(Context context, @Main Resources resources) {
mContext = context;
mSeparator = resources.getString(
com.android.internal.R.string.kg_text_message_separator);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 9bba2aab782d..694c623ac11f 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -92,7 +92,6 @@ import android.util.Log;
import android.util.SparseBooleanArray;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.telephony.IccCardConstants;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.widget.LockPatternUtils;
@@ -102,7 +101,7 @@ import com.android.systemui.DumpController;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dagger.qualifiers.MainLooper;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
@@ -1060,7 +1059,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
if (DEBUG_SIM_STATES) {
Log.v(TAG, "action " + action
+ " state: " + intent.getStringExtra(
- IccCardConstants.INTENT_KEY_ICC_STATE)
+ Intent.EXTRA_SIM_STATE)
+ " slotId: " + args.slotId + " subid: " + args.subId);
}
mHandler.obtainMessage(MSG_SIM_STATE_CHANGE, args.subId, args.slotId, args.simState)
@@ -1236,38 +1235,38 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
if (!TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(intent.getAction())) {
throw new IllegalArgumentException("only handles intent ACTION_SIM_STATE_CHANGED");
}
- String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
+ String stateExtra = intent.getStringExtra(Intent.EXTRA_SIM_STATE);
int slotId = intent.getIntExtra(PhoneConstants.PHONE_KEY, 0);
int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
- if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
+ if (Intent.SIM_STATE_ABSENT.equals(stateExtra)) {
final String absentReason = intent
- .getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
+ .getStringExtra(Intent.EXTRA_SIM_LOCKED_REASON);
- if (IccCardConstants.INTENT_VALUE_ABSENT_ON_PERM_DISABLED.equals(
+ if (Intent.SIM_ABSENT_ON_PERM_DISABLED.equals(
absentReason)) {
state = TelephonyManager.SIM_STATE_PERM_DISABLED;
} else {
state = TelephonyManager.SIM_STATE_ABSENT;
}
- } else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
+ } else if (Intent.SIM_STATE_READY.equals(stateExtra)) {
state = TelephonyManager.SIM_STATE_READY;
- } else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
+ } else if (Intent.SIM_STATE_LOCKED.equals(stateExtra)) {
final String lockedReason = intent
- .getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
- if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
+ .getStringExtra(Intent.EXTRA_SIM_LOCKED_REASON);
+ if (Intent.SIM_LOCKED_ON_PIN.equals(lockedReason)) {
state = TelephonyManager.SIM_STATE_PIN_REQUIRED;
- } else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
+ } else if (Intent.SIM_LOCKED_ON_PUK.equals(lockedReason)) {
state = TelephonyManager.SIM_STATE_PUK_REQUIRED;
} else {
state = TelephonyManager.SIM_STATE_UNKNOWN;
}
- } else if (IccCardConstants.INTENT_VALUE_LOCKED_NETWORK.equals(stateExtra)) {
+ } else if (Intent.SIM_LOCKED_NETWORK.equals(stateExtra)) {
state = TelephonyManager.SIM_STATE_NETWORK_LOCKED;
- } else if (IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR.equals(stateExtra)) {
+ } else if (Intent.SIM_STATE_CARD_IO_ERROR.equals(stateExtra)) {
state = TelephonyManager.SIM_STATE_CARD_IO_ERROR;
- } else if (IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(stateExtra)
- || IccCardConstants.INTENT_VALUE_ICC_IMSI.equals(stateExtra)) {
+ } else if (Intent.SIM_STATE_LOADED.equals(stateExtra)
+ || Intent.SIM_STATE_IMSI.equals(stateExtra)) {
// This is required because telephony doesn't return to "READY" after
// these state transitions. See bug 7197471.
state = TelephonyManager.SIM_STATE_READY;
@@ -1497,7 +1496,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
@VisibleForTesting
@Inject
- protected KeyguardUpdateMonitor(Context context, @MainLooper Looper mainLooper,
+ protected KeyguardUpdateMonitor(Context context, @Main Looper mainLooper,
BroadcastDispatcher broadcastDispatcher,
DumpController dumpController) {
mContext = context;
diff --git a/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java b/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java
index 41a7bc43eaa0..47a10af7c550 100644
--- a/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java
@@ -19,117 +19,99 @@ import android.content.Intent;
import android.view.View;
import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.statusbar.phone.StatusBar;
+
+import java.util.Optional;
import javax.inject.Inject;
import javax.inject.Singleton;
+import dagger.Lazy;
+
/**
* Single common instance of ActivityStarter that can be gotten and referenced from anywhere, but
- * delegates to an actual implementation such as StatusBar, assuming it exists.
+ * delegates to an actual implementation (StatusBar).
*/
+@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
@Singleton
public class ActivityStarterDelegate implements ActivityStarter {
- private ActivityStarter mActualStarter;
+ private Optional<Lazy<StatusBar>> mActualStarter;
@Inject
- public ActivityStarterDelegate() {
+ public ActivityStarterDelegate(Optional<Lazy<StatusBar>> statusBar) {
+ mActualStarter = statusBar;
}
@Override
public void startPendingIntentDismissingKeyguard(PendingIntent intent) {
- if (mActualStarter == null) {
- return;
- }
- mActualStarter.startPendingIntentDismissingKeyguard(intent);
+ mActualStarter.ifPresent(
+ starter -> starter.get().startPendingIntentDismissingKeyguard(intent));
}
@Override
public void startPendingIntentDismissingKeyguard(PendingIntent intent,
Runnable intentSentCallback) {
- if (mActualStarter == null) {
- return;
- }
- mActualStarter.startPendingIntentDismissingKeyguard(intent, intentSentCallback);
+ mActualStarter.ifPresent(
+ starter -> starter.get().startPendingIntentDismissingKeyguard(intent,
+ intentSentCallback));
}
@Override
public void startPendingIntentDismissingKeyguard(PendingIntent intent,
Runnable intentSentCallback, View associatedView) {
- if (mActualStarter == null) {
- return;
- }
- mActualStarter.startPendingIntentDismissingKeyguard(intent, intentSentCallback,
- associatedView);
+ mActualStarter.ifPresent(
+ starter -> starter.get().startPendingIntentDismissingKeyguard(intent,
+ intentSentCallback, associatedView));
}
@Override
public void startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade,
int flags) {
- if (mActualStarter == null) {
- return;
- }
- mActualStarter.startActivity(intent, onlyProvisioned, dismissShade, flags);
+ mActualStarter.ifPresent(
+ starter -> starter.get().startActivity(intent, onlyProvisioned, dismissShade,
+ flags));
}
@Override
public void startActivity(Intent intent, boolean dismissShade) {
- if (mActualStarter == null) {
- return;
- }
- mActualStarter.startActivity(intent, dismissShade);
+ mActualStarter.ifPresent(starter -> starter.get().startActivity(intent, dismissShade));
}
@Override
public void startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade) {
- if (mActualStarter == null) {
- return;
- }
- mActualStarter.startActivity(intent, onlyProvisioned, dismissShade);
+ mActualStarter.ifPresent(
+ starter -> starter.get().startActivity(intent, onlyProvisioned, dismissShade));
}
@Override
public void startActivity(Intent intent, boolean dismissShade, Callback callback) {
- if (mActualStarter == null) {
- return;
- }
- mActualStarter.startActivity(intent, dismissShade, callback);
+ mActualStarter.ifPresent(
+ starter -> starter.get().startActivity(intent, dismissShade, callback));
}
@Override
public void postStartActivityDismissingKeyguard(Intent intent, int delay) {
- if (mActualStarter == null) {
- return;
- }
- mActualStarter.postStartActivityDismissingKeyguard(intent, delay);
+ mActualStarter.ifPresent(
+ starter -> starter.get().postStartActivityDismissingKeyguard(intent, delay));
}
@Override
public void postStartActivityDismissingKeyguard(PendingIntent intent) {
- if (mActualStarter == null) {
- return;
- }
- mActualStarter.postStartActivityDismissingKeyguard(intent);
+ mActualStarter.ifPresent(
+ starter -> starter.get().postStartActivityDismissingKeyguard(intent));
}
@Override
public void postQSRunnableDismissingKeyguard(Runnable runnable) {
- if (mActualStarter == null) {
- return;
- }
- mActualStarter.postQSRunnableDismissingKeyguard(runnable);
+ mActualStarter.ifPresent(
+ starter -> starter.get().postQSRunnableDismissingKeyguard(runnable));
}
@Override
public void dismissKeyguardThenExecute(OnDismissAction action, Runnable cancel,
boolean afterKeyguardGone) {
- if (mActualStarter == null) {
- return;
- }
- mActualStarter.dismissKeyguardThenExecute(action, cancel, afterKeyguardGone);
- }
-
- public void setActivityStarterImpl(ActivityStarter starter) {
- mActualStarter = starter;
+ mActualStarter.ifPresent(starter -> starter.get().dismissKeyguardThenExecute(action, cancel,
+ afterKeyguardGone));
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/CornerHandleView.java b/packages/SystemUI/src/com/android/systemui/CornerHandleView.java
index 8e472f9c98a3..8503396975b5 100644
--- a/packages/SystemUI/src/com/android/systemui/CornerHandleView.java
+++ b/packages/SystemUI/src/com/android/systemui/CornerHandleView.java
@@ -57,6 +57,7 @@ public class CornerHandleView extends View {
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(getStrokePx());
+ setLayerType(View.LAYER_TYPE_SOFTWARE, mPaint);
final int dualToneDarkTheme = Utils.getThemeAttr(mContext, R.attr.darkIconTheme);
final int dualToneLightTheme = Utils.getThemeAttr(mContext, R.attr.lightIconTheme);
@@ -114,10 +115,17 @@ public class CornerHandleView extends View {
* appropriately. Intention is to match the home handle color.
*/
public void updateDarkness(float darkIntensity) {
+ // Handle color is same as home handle color.
int color = (int) ArgbEvaluator.getInstance().evaluate(darkIntensity,
mLightColor, mDarkColor);
+ // Shadow color is inverse of handle color.
+ int shadowColor = (int) ArgbEvaluator.getInstance().evaluate(darkIntensity,
+ mDarkColor, mLightColor);
if (mPaint.getColor() != color) {
mPaint.setColor(color);
+ mPaint.setShadowLayer(/** radius */ getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.assist_handle_shadow_radius), /** shadowDx */ 0,
+ /** shadowDy */ 0, /** color */ shadowColor);
if (getVisibility() == VISIBLE && getAlpha() > 0) {
invalidate();
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index dd38a332df68..eecc54c678c0 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -39,10 +39,8 @@ import com.android.systemui.assist.AssistManager;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.colorextraction.SysuiColorExtractor;
-import com.android.systemui.dagger.qualifiers.BgHandler;
-import com.android.systemui.dagger.qualifiers.BgLooper;
-import com.android.systemui.dagger.qualifiers.MainHandler;
-import com.android.systemui.dagger.qualifiers.MainLooper;
+import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dock.DockManager;
import com.android.systemui.fragments.FragmentService;
import com.android.systemui.keyguard.ScreenLifecycle;
@@ -210,7 +208,6 @@ public class Dependency {
private final ArrayMap<Object, LazyDependencyCreator> mProviders = new ArrayMap<>();
@Inject Lazy<ActivityStarter> mActivityStarter;
- @Inject Lazy<ActivityStarterDelegate> mActivityStarterDelegate;
@Inject Lazy<BroadcastDispatcher> mBroadcastDispatcher;
@Inject Lazy<AsyncSensorManager> mAsyncSensorManager;
@Inject Lazy<BluetoothController> mBluetoothController;
@@ -270,7 +267,6 @@ public class Dependency {
@Inject Lazy<KeyguardEnvironment> mKeyguardEnvironment;
@Inject Lazy<ShadeController> mShadeController;
@Inject Lazy<NotificationRemoteInputManager.Callback> mNotificationRemoteInputManagerCallback;
- @Inject Lazy<InitController> mInitController;
@Inject Lazy<AppOpsController> mAppOpsController;
@Inject Lazy<NavigationBarController> mNavigationBarController;
@Inject Lazy<StatusBarStateController> mStatusBarStateController;
@@ -298,10 +294,10 @@ public class Dependency {
@Inject Lazy<SensorPrivacyManager> mSensorPrivacyManager;
@Inject Lazy<AutoHideController> mAutoHideController;
@Inject Lazy<ForegroundServiceNotificationListener> mForegroundServiceNotificationListener;
- @Inject @BgLooper Lazy<Looper> mBgLooper;
- @Inject @BgHandler Lazy<Handler> mBgHandler;
- @Inject @MainLooper Lazy<Looper> mMainLooper;
- @Inject @MainHandler Lazy<Handler> mMainHandler;
+ @Inject @Background Lazy<Looper> mBgLooper;
+ @Inject @Background Lazy<Handler> mBgHandler;
+ @Inject @Main Lazy<Looper> mMainLooper;
+ @Inject @Main Lazy<Handler> mMainHandler;
@Inject @Named(TIME_TICK_HANDLER_NAME) Lazy<Handler> mTimeTickHandler;
@Nullable
@Inject @Named(LEAK_REPORT_EMAIL_NAME) Lazy<String> mLeakReportEmail;
@@ -341,7 +337,6 @@ public class Dependency {
mProviders.put(MAIN_LOOPER, mMainLooper::get);
mProviders.put(MAIN_HANDLER, mMainHandler::get);
mProviders.put(ActivityStarter.class, mActivityStarter::get);
- mProviders.put(ActivityStarterDelegate.class, mActivityStarterDelegate::get);
mProviders.put(BroadcastDispatcher.class, mBroadcastDispatcher::get);
mProviders.put(AsyncSensorManager.class, mAsyncSensorManager::get);
@@ -460,8 +455,6 @@ public class Dependency {
mProviders.put(NotificationRemoteInputManager.Callback.class,
mNotificationRemoteInputManagerCallback::get);
- mProviders.put(InitController.class, mInitController::get);
-
mProviders.put(AppOpsController.class, mAppOpsController::get);
mProviders.put(NavigationBarController.class, mNavigationBarController::get);
diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
index ecf4c0a86bfc..e2b12daf441e 100644
--- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
@@ -179,7 +179,8 @@ public class ExpandHelper implements Gefingerpoken {
mTouchSlop = configuration.getScaledTouchSlop();
mSGD = new ScaleGestureDetector(context, mScaleGestureListener);
- mFlingAnimationUtils = new FlingAnimationUtils(context, EXPAND_DURATION);
+ mFlingAnimationUtils = new FlingAnimationUtils(mContext.getResources().getDisplayMetrics(),
+ EXPAND_DURATION);
}
@VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java
index 41dd5bbf272b..82e665bdf5ac 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java
@@ -24,7 +24,7 @@ import android.util.SparseArray;
import com.android.internal.messages.nano.SystemMessageProto;
import com.android.systemui.appops.AppOpsController;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.util.Assert;
@@ -50,7 +50,7 @@ public class ForegroundServiceController {
@Inject
public ForegroundServiceController(NotificationEntryManager entryManager,
- AppOpsController appOpsController, @MainHandler Handler mainHandler) {
+ AppOpsController appOpsController, @Main Handler mainHandler) {
mEntryManager = entryManager;
mMainHandler = mainHandler;
appOpsController.addCallback(APP_OPS, (code, uid, packageName, active) -> {
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index 29a7167394ae..e50d08c0cf9d 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -108,12 +108,13 @@ public class ImageWallpaper extends WallpaperService {
if (mController != null) {
mController.addCallback(this /* StateListener */);
}
- mEglHelper = new EglHelper();
- mRenderer = new ImageWallpaperRenderer(context, this /* SurfaceProxy */);
}
@Override
public void onCreate(SurfaceHolder surfaceHolder) {
+ mEglHelper = new EglHelper();
+ // Deferred init renderer because we need to get wallpaper by display context.
+ mRenderer = new ImageWallpaperRenderer(getDisplayContext(), this /* SurfaceProxy */);
setFixedSizeAllowed(true);
setOffsetNotificationsEnabled(true);
updateSurfaceSize();
@@ -177,14 +178,13 @@ public class ImageWallpaper extends WallpaperService {
mRenderer = null;
mEglHelper.finish();
mEglHelper = null;
- getSurfaceHolder().getSurface().hwuiDestroy();
});
}
@Override
public void onSurfaceCreated(SurfaceHolder holder) {
mWorker.getThreadHandler().post(() -> {
- mEglHelper.init(holder);
+ mEglHelper.init(holder, needSupportWideColorGamut());
mRenderer.onSurfaceCreated();
});
}
@@ -257,7 +257,7 @@ public class ImageWallpaper extends WallpaperService {
// Check if we need to recreate egl surface.
if (mEglHelper.hasEglContext() && !mEglHelper.hasEglSurface()) {
- if (!mEglHelper.createEglSurface(getSurfaceHolder())) {
+ if (!mEglHelper.createEglSurface(getSurfaceHolder(), needSupportWideColorGamut())) {
Log.w(TAG, "recreate egl surface failed!");
}
}
@@ -340,6 +340,10 @@ public class ImageWallpaper extends WallpaperService {
&& mController.getState() == StatusBarState.KEYGUARD;
}
+ private boolean needSupportWideColorGamut() {
+ return mRenderer.isWcgContent();
+ }
+
@Override
protected void dump(String prefix, FileDescriptor fd, PrintWriter out, String[] args) {
super.dump(prefix, fd, out, args);
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index 9ce277eabbe8..0e736dcd11a8 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -68,7 +68,7 @@ import androidx.annotation.VisibleForTesting;
import com.android.internal.util.Preconditions;
import com.android.systemui.RegionInterceptingFrameLayout.RegionInterceptableView;
import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
import com.android.systemui.plugins.qs.QS;
@@ -147,7 +147,7 @@ public class ScreenDecorations extends SystemUI implements Tunable {
@Inject
public ScreenDecorations(Context context,
Lazy<StatusBar> statusBarLazy,
- @MainHandler Handler handler,
+ @Main Handler handler,
BroadcastDispatcher broadcastDispatcher,
TunerService tunerService) {
super(context);
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index 58c52a1fc50e..4728327d51b8 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -93,13 +93,11 @@ public class SwipeHelper implements Gefingerpoken {
private boolean mTouchAboveFalsingThreshold;
private boolean mDisableHwLayers;
private final boolean mFadeDependingOnAmountSwiped;
- private final Context mContext;
private final ArrayMap<View, Animator> mDismissPendingMap = new ArrayMap<>();
public SwipeHelper(
int swipeDirection, Callback callback, Context context, FalsingManager falsingManager) {
- mContext = context;
mCallback = callback;
mHandler = new Handler();
mSwipeDirection = swipeDirection;
@@ -114,7 +112,8 @@ public class SwipeHelper implements Gefingerpoken {
mFalsingThreshold = res.getDimensionPixelSize(R.dimen.swipe_helper_falsing_threshold);
mFadeDependingOnAmountSwiped = res.getBoolean(R.bool.config_fadeDependingOnAmountSwiped);
mFalsingManager = falsingManager;
- mFlingAnimationUtils = new FlingAnimationUtils(context, getMaxEscapeAnimDuration() / 1000f);
+ mFlingAnimationUtils = new FlingAnimationUtils(res.getDisplayMetrics(),
+ getMaxEscapeAnimDuration() / 1000f);
}
public void setDensityScale(float densityScale) {
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index e08de3943258..13151527cd5f 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -56,6 +56,7 @@ public class SystemUIApplication extends Application implements
private SystemUI[] mServices;
private boolean mServicesStarted;
private SystemUIAppComponentFactory.ContextAvailableCallback mContextAvailableCallback;
+ private SystemUIRootComponent mRootComponent;
public SystemUIApplication() {
super();
@@ -72,9 +73,9 @@ public class SystemUIApplication extends Application implements
Trace.TRACE_TAG_APP);
log.traceBegin("DependencyInjection");
mContextAvailableCallback.onContextAvailable(this);
- SystemUIRootComponent root = SystemUIFactory.getInstance().getRootComponent();
- mComponentHelper = root.getContextComponentHelper();
- mBootCompleteCache = root.provideBootCacheImpl();
+ mRootComponent = SystemUIFactory.getInstance().getRootComponent();
+ mComponentHelper = mRootComponent.getContextComponentHelper();
+ mBootCompleteCache = mRootComponent.provideBootCacheImpl();
log.traceEnd();
// Set the application theme that is inherited by all services. Note that setting the
@@ -209,7 +210,7 @@ public class SystemUIApplication extends Application implements
mServices[i].onBootCompleted();
}
}
- Dependency.get(InitController.class).executePostInitTasks();
+ mRootComponent.getInitController().executePostInitTasks();
log.traceEnd();
mServicesStarted = true;
@@ -218,11 +219,7 @@ public class SystemUIApplication extends Application implements
@Override
public void onConfigurationChanged(Configuration newConfig) {
if (mServicesStarted) {
- SystemUIFactory
- .getInstance()
- .getRootComponent()
- .getConfigurationController()
- .onConfigurationChanged(newConfig);
+ mRootComponent.getConfigurationController().onConfigurationChanged(newConfig);
int len = mServices.length;
for (int i = 0; i < len; i++) {
if (mServices[i] != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIService.java b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
index 164595742ae0..41d83148e093 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIService.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
@@ -27,7 +27,7 @@ import android.os.SystemProperties;
import android.util.Slog;
import com.android.internal.os.BinderInternal;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.shared.plugins.PluginManagerImpl;
@@ -41,7 +41,7 @@ public class SystemUIService extends Service {
private final Handler mMainHandler;
@Inject
- public SystemUIService(@MainHandler Handler mainHandler) {
+ public SystemUIService(@Main Handler mainHandler) {
super();
mMainHandler = mainHandler;
}
diff --git a/packages/SystemUI/src/com/android/systemui/UiOffloadThread.java b/packages/SystemUI/src/com/android/systemui/UiOffloadThread.java
index a726b42f714f..d5a46de980f9 100644
--- a/packages/SystemUI/src/com/android/systemui/UiOffloadThread.java
+++ b/packages/SystemUI/src/com/android/systemui/UiOffloadThread.java
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
package com.android.systemui;
@@ -36,7 +36,7 @@ public class UiOffloadThread {
public UiOffloadThread() {
}
- public Future<?> submit(Runnable runnable) {
+ public Future<?> execute(Runnable runnable) {
return mExecutorService.submit(runnable);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java
index 6178ff2ab2cb..895207d37816 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java
@@ -22,7 +22,7 @@ import android.os.Handler;
import android.provider.Settings;
import com.android.systemui.SystemUI;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -36,7 +36,7 @@ public class WindowMagnification extends SystemUI {
private final Handler mHandler;
@Inject
- public WindowMagnification(Context context, @MainHandler Handler mainHandler) {
+ public WindowMagnification(Context context, @Main Handler mainHandler) {
super(context);
mHandler = mainHandler;
}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
index e3694ac532fe..bfac4fce92eb 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
@@ -16,6 +16,8 @@
package com.android.systemui.accessibility;
+import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
+
import android.content.Context;
import android.content.res.Resources;
import android.graphics.PixelFormat;
@@ -196,6 +198,7 @@ public class WindowMagnificationController implements View.OnClickListener,
params.token = mOverlayView.getWindowToken();
params.x = mMagnificationFrame.left;
params.y = mMagnificationFrame.top;
+ params.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
params.setTitle(mContext.getString(R.string.magnification_window_title));
mMirrorView = LayoutInflater.from(mContext).inflate(R.layout.window_magnifier_view, null);
diff --git a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
index bad6b5458aa3..b0831232bcd4 100644
--- a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
@@ -30,7 +30,7 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.DumpController;
import com.android.systemui.Dumpable;
-import com.android.systemui.dagger.qualifiers.BgLooper;
+import com.android.systemui.dagger.qualifiers.Background;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -81,7 +81,7 @@ public class AppOpsControllerImpl implements AppOpsController,
};
@Inject
- public AppOpsControllerImpl(Context context, @BgLooper Looper bgLooper,
+ public AppOpsControllerImpl(Context context, @Background Looper bgLooper,
DumpController dumpController) {
this(context, bgLooper, new PermissionFlagsCache(context), dumpController);
}
diff --git a/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt
index 5cc70bc27c2a..8cb0cc5db1d3 100644
--- a/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt
+++ b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt
@@ -28,8 +28,8 @@ import android.util.Log
import android.util.SparseArray
import com.android.internal.annotations.VisibleForTesting
import com.android.systemui.Dumpable
-import com.android.systemui.dagger.qualifiers.BgLooper
-import com.android.systemui.dagger.qualifiers.MainHandler
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.dagger.qualifiers.Main
import java.io.FileDescriptor
import java.io.PrintWriter
import javax.inject.Inject
@@ -62,8 +62,8 @@ private const val DEBUG = true
@Singleton
open class BroadcastDispatcher @Inject constructor (
private val context: Context,
- @MainHandler private val mainHandler: Handler,
- @BgLooper private val bgLooper: Looper
+ @Main private val mainHandler: Handler,
+ @Background private val bgLooper: Looper
) : Dumpable {
// Only modify in BG thread
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java
index a6a3ce06324f..dc2499602125 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java
@@ -16,22 +16,15 @@
package com.android.systemui.bubbles;
import android.annotation.Nullable;
-import android.app.Notification;
import android.content.Context;
-import android.content.pm.LauncherApps;
+import android.graphics.Bitmap;
import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Matrix;
import android.graphics.Path;
import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.Icon;
import android.util.AttributeSet;
import android.util.PathParser;
import android.widget.ImageView;
-import com.android.internal.graphics.ColorUtils;
-import com.android.launcher3.icons.BitmapInfo;
import com.android.launcher3.icons.DotRenderer;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
@@ -46,9 +39,9 @@ import com.android.systemui.R;
public class BadgedImageView extends ImageView {
/** Same value as Launcher3 dot code */
- private static final float WHITE_SCRIM_ALPHA = 0.54f;
+ public static final float WHITE_SCRIM_ALPHA = 0.54f;
/** Same as value in Launcher3 IconShape */
- private static final int DEFAULT_PATH_SIZE = 100;
+ public static final int DEFAULT_PATH_SIZE = 100;
static final int DOT_STATE_DEFAULT = 0;
static final int DOT_STATE_SUPPRESSED_FOR_FLYOUT = 1;
@@ -58,7 +51,6 @@ public class BadgedImageView extends ImageView {
private int mCurrentDotState = DOT_STATE_SUPPRESSED_FOR_FLYOUT;
private Bubble mBubble;
- private BubbleIconFactory mBubbleIconFactory;
private int mIconBitmapSize;
private DotRenderer mDotRenderer;
@@ -94,6 +86,18 @@ public class BadgedImageView extends ImageView {
mDotRenderer = new DotRenderer(mIconBitmapSize, iconPath, DEFAULT_PATH_SIZE);
}
+ /**
+ * Updates the view with provided info.
+ */
+ public void update(Bubble bubble, Bitmap bubbleImage, int dotColor, Path dotPath) {
+ mBubble = bubble;
+ setImageBitmap(bubbleImage);
+ setDotState(DOT_STATE_SUPPRESSED_FOR_FLYOUT);
+ mDotColor = dotColor;
+ drawDot(dotPath);
+ animateDot();
+ }
+
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
@@ -140,14 +144,6 @@ public class BadgedImageView extends ImageView {
}
/**
- * The colour to use for the dot.
- */
- void setDotColor(int color) {
- mDotColor = ColorUtils.setAlphaComponent(color, 255 /* alpha */);
- invalidate();
- }
-
- /**
* @param iconPath The new icon path to use when calculating dot position.
*/
void drawDot(Path iconPath) {
@@ -187,25 +183,6 @@ public class BadgedImageView extends ImageView {
}
/**
- * Populates this view with a bubble.
- * <p>
- * This should only be called when a new bubble is being set on the view, updates to the
- * current bubble should use {@link #update(Bubble)}.
- *
- * @param bubble the bubble to display in this view.
- */
- public void setBubble(Bubble bubble) {
- mBubble = bubble;
- }
-
- /**
- * @param factory Factory for creating normalized bubble icons.
- */
- public void setBubbleIconFactory(BubbleIconFactory factory) {
- mBubbleIconFactory = factory;
- }
-
- /**
* The key for the {@link Bubble} associated with this view, if one exists.
*/
@Nullable
@@ -213,15 +190,6 @@ public class BadgedImageView extends ImageView {
return (mBubble != null) ? mBubble.getKey() : null;
}
- /**
- * Updates the UI based on the bubble, updates badge and animates messages as needed.
- */
- public void update(Bubble bubble) {
- mBubble = bubble;
- setDotState(DOT_STATE_SUPPRESSED_FOR_FLYOUT);
- updateViews();
- }
-
int getDotColor() {
return mDotColor;
}
@@ -277,47 +245,4 @@ public class BadgedImageView extends ImageView {
}
}).start();
}
-
- void updateViews() {
- if (mBubble == null || mBubbleIconFactory == null) {
- return;
- }
-
- Drawable bubbleDrawable = getBubbleDrawable(mContext);
- BitmapInfo badgeBitmapInfo = mBubbleIconFactory.getBadgedBitmap(mBubble);
- BitmapInfo bubbleBitmapInfo = mBubbleIconFactory.getBubbleBitmap(bubbleDrawable,
- badgeBitmapInfo);
- setImageBitmap(bubbleBitmapInfo.icon);
-
- // Update badge.
- mDotColor = ColorUtils.blendARGB(badgeBitmapInfo.color, Color.WHITE, WHITE_SCRIM_ALPHA);
- setDotColor(mDotColor);
-
- // Update dot.
- Path iconPath = PathParser.createPathFromPathData(
- getResources().getString(com.android.internal.R.string.config_icon_mask));
- Matrix matrix = new Matrix();
- float scale = mBubbleIconFactory.getNormalizer().getScale(bubbleDrawable,
- null /* outBounds */, null /* path */, null /* outMaskShape */);
- float radius = BadgedImageView.DEFAULT_PATH_SIZE / 2f;
- matrix.setScale(scale /* x scale */, scale /* y scale */, radius /* pivot x */,
- radius /* pivot y */);
- iconPath.transform(matrix);
- drawDot(iconPath);
-
- animateDot();
- }
-
- Drawable getBubbleDrawable(Context context) {
- if (mBubble.getShortcutInfo() != null && mBubble.usingShortcutInfo()) {
- LauncherApps launcherApps =
- (LauncherApps) getContext().getSystemService(Context.LAUNCHER_APPS_SERVICE);
- int density = getContext().getResources().getConfiguration().densityDpi;
- return launcherApps.getShortcutIconDrawable(mBubble.getShortcutInfo(), density);
- } else {
- Notification.BubbleMetadata metadata = mBubble.getEntry().getBubbleMetadata();
- Icon ic = metadata.getIcon();
- return ic.loadDrawable(context);
- }
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
index 7934e10c8605..77c8e0b07158 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
@@ -16,6 +16,7 @@
package com.android.systemui.bubbles;
+import static android.os.AsyncTask.Status.FINISHED;
import static android.view.Display.INVALID_DISPLAY;
import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE;
@@ -26,20 +27,17 @@ import android.app.Notification;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
-import android.content.pm.ApplicationInfo;
import android.content.pm.LauncherApps;
import android.content.pm.PackageManager;
import android.content.pm.ShortcutInfo;
import android.content.res.Resources;
import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Parcelable;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
-import android.view.LayoutInflater;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.R;
@@ -59,19 +57,19 @@ class Bubble {
private NotificationEntry mEntry;
private final String mKey;
private final String mGroupId;
+
+ private long mLastUpdated;
+ private long mLastAccessed;
+
+ // Items that are typically loaded later
private String mAppName;
- private Drawable mUserBadgedAppIcon;
private ShortcutInfo mShortcutInfo;
-
- private boolean mInflated;
private BadgedImageView mIconView;
private BubbleExpandedView mExpandedView;
- private BubbleIconFactory mBubbleIconFactory;
-
- private long mLastUpdated;
- private long mLastAccessed;
- private boolean mIsUserCreated;
+ private boolean mInflated;
+ private BubbleViewInfoTask mInflationTask;
+ private boolean mInflateSynchronously;
/**
* Whether this notification should be shown in the shade when it is also displayed as a bubble.
@@ -94,37 +92,11 @@ class Bubble {
/** Used in tests when no UI is required. */
@VisibleForTesting(visibility = PRIVATE)
- Bubble(Context context, NotificationEntry e) {
+ Bubble(NotificationEntry e) {
mEntry = e;
mKey = e.getKey();
mLastUpdated = e.getSbn().getPostTime();
mGroupId = groupId(e);
-
- String shortcutId = e.getSbn().getNotification().getShortcutId();
- if (BubbleExperimentConfig.useShortcutInfoToBubble(context)
- && shortcutId != null) {
- mShortcutInfo = BubbleExperimentConfig.getShortcutInfo(context,
- e.getSbn().getPackageName(),
- e.getSbn().getUser(), shortcutId);
- }
-
- PackageManager pm = context.getPackageManager();
- ApplicationInfo info;
- try {
- info = pm.getApplicationInfo(
- mEntry.getSbn().getPackageName(),
- PackageManager.MATCH_UNINSTALLED_PACKAGES
- | PackageManager.MATCH_DISABLED_COMPONENTS
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
- | PackageManager.MATCH_DIRECT_BOOT_AWARE);
- if (info != null) {
- mAppName = String.valueOf(pm.getApplicationLabel(info));
- }
- Drawable appIcon = pm.getApplicationIcon(mEntry.getSbn().getPackageName());
- mUserBadgedAppIcon = pm.getUserBadgedIcon(appIcon, mEntry.getSbn().getUser());
- } catch (PackageManager.NameNotFoundException unused) {
- mAppName = mEntry.getSbn().getPackageName();
- }
}
public String getKey() {
@@ -143,41 +115,22 @@ class Bubble {
return mEntry.getSbn().getPackageName();
}
+ @Nullable
public String getAppName() {
return mAppName;
}
- Drawable getUserBadgedAppIcon() {
- return mUserBadgedAppIcon;
- }
-
@Nullable
public ShortcutInfo getShortcutInfo() {
return mShortcutInfo;
}
- /**
- * Whether shortcut information should be used to populate the bubble.
- * <p>
- * To populate the activity use {@link LauncherApps#startShortcut(ShortcutInfo, Rect, Bundle)}.
- * To populate the icon use {@link LauncherApps#getShortcutIconDrawable(ShortcutInfo, int)}.
- */
- public boolean usingShortcutInfo() {
- return BubbleExperimentConfig.isShortcutIntent(getBubbleIntent());
- }
-
- void setBubbleIconFactory(BubbleIconFactory factory) {
- mBubbleIconFactory = factory;
- }
-
- boolean isInflated() {
- return mInflated;
- }
-
+ @Nullable
BadgedImageView getIconView() {
return mIconView;
}
+ @Nullable
BubbleExpandedView getExpandedView() {
return mExpandedView;
}
@@ -188,20 +141,62 @@ class Bubble {
}
}
- void inflate(LayoutInflater inflater, BubbleStackView stackView) {
- if (mInflated) {
- return;
+ /**
+ * Sets whether to perform inflation on the same thread as the caller. This method should only
+ * be used in tests, not in production.
+ */
+ @VisibleForTesting
+ void setInflateSynchronously(boolean inflateSynchronously) {
+ mInflateSynchronously = inflateSynchronously;
+ }
+
+ /**
+ * Starts a task to inflate & load any necessary information to display a bubble.
+ *
+ * @param callback the callback to notify one the bubble is ready to be displayed.
+ * @param context the context for the bubble.
+ * @param stackView the stackView the bubble is eventually added to.
+ * @param iconFactory the iconfactory use to create badged images for the bubble.
+ */
+ void inflate(BubbleViewInfoTask.Callback callback,
+ Context context,
+ BubbleStackView stackView,
+ BubbleIconFactory iconFactory) {
+ if (isBubbleLoading()) {
+ mInflationTask.cancel(true /* mayInterruptIfRunning */);
+ }
+ mInflationTask = new BubbleViewInfoTask(this,
+ context,
+ stackView,
+ iconFactory,
+ callback);
+ if (mInflateSynchronously) {
+ mInflationTask.onPostExecute(mInflationTask.doInBackground());
+ } else {
+ mInflationTask.execute();
}
- mIconView = (BadgedImageView) inflater.inflate(
- R.layout.bubble_view, stackView, false /* attachToRoot */);
- mIconView.setBubbleIconFactory(mBubbleIconFactory);
- mIconView.setBubble(this);
+ }
- mExpandedView = (BubbleExpandedView) inflater.inflate(
- R.layout.bubble_expanded_view, stackView, false /* attachToRoot */);
- mExpandedView.setBubble(this, stackView);
+ private boolean isBubbleLoading() {
+ return mInflationTask != null && mInflationTask.getStatus() != FINISHED;
+ }
- mInflated = true;
+ boolean isInflated() {
+ return mInflated;
+ }
+
+ void setViewInfo(BubbleViewInfoTask.BubbleViewInfo info) {
+ if (!isInflated()) {
+ mIconView = info.imageView;
+ mExpandedView = info.expandedView;
+ mInflated = true;
+ }
+
+ mShortcutInfo = info.shortcutInfo;
+ mAppName = info.appName;
+
+ mExpandedView.update(this);
+ mIconView.update(this, info.badgedBubbleImage, info.dotColor, info.dotPath);
}
/**
@@ -218,13 +213,12 @@ class Bubble {
}
}
- void updateEntry(NotificationEntry entry) {
+ /**
+ * Sets the entry associated with this bubble.
+ */
+ void setEntry(NotificationEntry entry) {
mEntry = entry;
mLastUpdated = entry.getSbn().getPostTime();
- if (mInflated) {
- mIconView.update(this);
- mExpandedView.update(this);
- }
}
/**
@@ -242,13 +236,6 @@ class Bubble {
}
/**
- * @return the timestamp in milliseconds when this bubble was last displayed in expanded state
- */
- long getLastAccessTime() {
- return mLastAccessed;
- }
-
- /**
* @return the display id of the virtual display on which bubble contents is drawn.
*/
int getDisplayId() {
@@ -352,6 +339,16 @@ class Bubble {
}
}
+ /**
+ * Whether shortcut information should be used to populate the bubble.
+ * <p>
+ * To populate the activity use {@link LauncherApps#startShortcut(ShortcutInfo, Rect, Bundle)}.
+ * To populate the icon use {@link LauncherApps#getShortcutIconDrawable(ShortcutInfo, int)}.
+ */
+ boolean usingShortcutInfo() {
+ return BubbleExperimentConfig.isShortcutIntent(getBubbleIntent());
+ }
+
@Nullable
PendingIntent getBubbleIntent() {
Notification.BubbleMetadata data = mEntry.getBubbleMetadata();
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index c82bc30338a7..7cd29ea48199 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -150,6 +150,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
private BubbleData mBubbleData;
@Nullable private BubbleStackView mStackView;
+ private BubbleIconFactory mBubbleIconFactory;
// Tracks the id of the current (foreground) user.
private int mCurrentUserId;
@@ -183,6 +184,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
/** Last known orientation, used to detect orientation changes in {@link #onConfigChanged}. */
private int mOrientation = Configuration.ORIENTATION_UNDEFINED;
+ private boolean mInflateSynchronously;
+
/**
* Listener to be notified when some states of the bubbles change.
*/
@@ -352,6 +355,16 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
mUserBlockedBubbles = new HashSet<>();
mScreenshotHelper = new ScreenshotHelper(context);
+ mBubbleIconFactory = new BubbleIconFactory(context);
+ }
+
+ /**
+ * Sets whether to perform inflation on the same thread as the caller. This method should only
+ * be used in tests, not in production.
+ */
+ @VisibleForTesting
+ void setInflateSynchronously(boolean inflateSynchronously) {
+ mInflateSynchronously = inflateSynchronously;
}
/**
@@ -415,16 +428,23 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
@Override
public void onUiModeChanged() {
- if (mStackView != null) {
- mStackView.onThemeChanged();
- }
+ updateForThemeChanges();
}
@Override
public void onOverlayChanged() {
+ updateForThemeChanges();
+ }
+
+ private void updateForThemeChanges() {
if (mStackView != null) {
mStackView.onThemeChanged();
}
+ mBubbleIconFactory = new BubbleIconFactory(mContext);
+ for (Bubble b: mBubbleData.getBubbles()) {
+ // Reload each bubble
+ b.inflate(null /* callback */, mContext, mStackView, mBubbleIconFactory);
+ }
}
@Override
@@ -508,14 +528,10 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
return (isSummary && isSuppressedSummary) || isBubbleAndSuppressed;
}
- void selectBubble(Bubble bubble) {
- mBubbleData.setSelectedBubble(bubble);
- }
-
@VisibleForTesting
void selectBubble(String key) {
Bubble bubble = mBubbleData.getBubbleWithKey(key);
- selectBubble(bubble);
+ mBubbleData.setSelectedBubble(bubble);
}
/**
@@ -562,11 +578,19 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
}
void updateBubble(NotificationEntry notif, boolean suppressFlyout, boolean showInShade) {
+ if (mStackView == null) {
+ // Lazy init stack view when a bubble is created
+ ensureStackViewCreated();
+ }
// If this is an interruptive notif, mark that it's interrupted
if (notif.getImportance() >= NotificationManager.IMPORTANCE_HIGH) {
notif.setInterruption();
}
- mBubbleData.notificationEntryUpdated(notif, suppressFlyout, showInShade);
+ Bubble bubble = mBubbleData.getOrCreateBubble(notif);
+ bubble.setInflateSynchronously(mInflateSynchronously);
+ bubble.inflate(
+ b -> mBubbleData.notificationEntryUpdated(b, suppressFlyout, showInShade),
+ mContext, mStackView, mBubbleIconFactory);
}
/**
@@ -783,16 +807,6 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
@Override
public void applyUpdate(BubbleData.Update update) {
- if (mStackView == null && update.addedBubble != null) {
- // Lazy init stack view when the first bubble is added.
- ensureStackViewCreated();
- }
-
- // If not yet initialized, ignore all other changes.
- if (mStackView == null) {
- return;
- }
-
if (update.addedBubble != null) {
mStackView.addBubble(update.addedBubble);
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
index b7df5baa4cf1..97224f1234dd 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
@@ -33,6 +33,7 @@ import android.util.Pair;
import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.R;
import com.android.systemui.bubbles.BubbleController.DismissReason;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -48,7 +49,6 @@ import java.util.Objects;
import javax.inject.Inject;
import javax.inject.Singleton;
-import com.android.systemui.R;
/**
* Keeps track of active bubbles.
@@ -180,28 +180,44 @@ public class BubbleData {
dispatchPendingChanges();
}
- void notificationEntryUpdated(NotificationEntry entry, boolean suppressFlyout,
- boolean showInShade) {
+ /**
+ * Constructs a new bubble or returns an existing one. Does not add new bubbles to
+ * bubble data, must go through {@link #notificationEntryUpdated(Bubble, boolean, boolean)}
+ * for that.
+ */
+ Bubble getOrCreateBubble(NotificationEntry entry) {
+ Bubble bubble = getBubbleWithKey(entry.getKey());
+ if (bubble == null) {
+ bubble = new Bubble(entry);
+ } else {
+ bubble.setEntry(entry);
+ }
+ return bubble;
+ }
+
+ /**
+ * When this method is called it is expected that all info in the bubble has completed loading.
+ * @see Bubble#inflate(BubbleViewInfoTask.Callback, Context,
+ * BubbleStackView, BubbleIconFactory).
+ */
+ void notificationEntryUpdated(Bubble bubble, boolean suppressFlyout, boolean showInShade) {
if (DEBUG_BUBBLE_DATA) {
- Log.d(TAG, "notificationEntryUpdated: " + entry);
+ Log.d(TAG, "notificationEntryUpdated: " + bubble);
}
- Bubble bubble = getBubbleWithKey(entry.getKey());
- suppressFlyout |= !shouldShowFlyout(entry);
+ Bubble prevBubble = getBubbleWithKey(bubble.getKey());
+ suppressFlyout |= !shouldShowFlyout(bubble.getEntry());
- if (bubble == null) {
+ if (prevBubble == null) {
// Create a new bubble
- bubble = new Bubble(mContext, entry);
bubble.setSuppressFlyout(suppressFlyout);
doAdd(bubble);
trim();
} else {
// Updates an existing bubble
- bubble.updateEntry(entry);
bubble.setSuppressFlyout(suppressFlyout);
doUpdate(bubble);
}
-
if (bubble.shouldAutoExpand()) {
setSelectedBubbleInternal(bubble);
if (!mExpanded) {
@@ -214,6 +230,7 @@ public class BubbleData {
bubble.setShowInShade(!isBubbleExpandedAndSelected && showInShade);
bubble.setShowDot(!isBubbleExpandedAndSelected /* show */, true /* animate */);
dispatchPendingChanges();
+
}
public void notificationEntryRemoved(NotificationEntry entry, @DismissReason int reason) {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
index 63d036d6362d..c1705dbb4e4b 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
@@ -99,7 +99,6 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList
private int mExpandedViewTouchSlop;
private Bubble mBubble;
- private String mAppName;
private BubbleController mBubbleController = Dependency.get(BubbleController.class);
private WindowManager mWindowManager;
@@ -339,68 +338,51 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList
}
}
- /**
- * Sets the bubble used to populate this view.
- */
- public void setBubble(Bubble bubble, BubbleStackView stackView) {
- if (DEBUG_BUBBLE_EXPANDED_VIEW) {
- Log.d(TAG, "setBubble: bubble=" + (bubble != null ? bubble.getKey() : "null"));
- }
+ void setStackView(BubbleStackView stackView) {
mStackView = stackView;
- mBubble = bubble;
- mAppName = bubble.getAppName();
-
- applyThemeAttrs();
- showSettingsIcon();
- updateExpandedView();
- }
-
- /**
- * Lets activity view know it should be shown / populated.
- */
- public void populateExpandedView() {
- if (DEBUG_BUBBLE_EXPANDED_VIEW) {
- Log.d(TAG, "populateExpandedView: "
- + "bubble=" + getBubbleKey());
- }
-
- if (usingActivityView()) {
- mActivityView.setCallback(mStateCallback);
- } else {
- Log.e(TAG, "Cannot populate expanded view.");
- }
}
/**
- * Updates the bubble backing this view. This will not re-populate ActivityView, it will
- * only update the deep-links in the title, and the height of the view.
+ * Sets the bubble used to populate this view.
*/
- public void update(Bubble bubble) {
+ void update(Bubble bubble) {
if (DEBUG_BUBBLE_EXPANDED_VIEW) {
Log.d(TAG, "update: bubble=" + (bubble != null ? bubble.getKey() : "null"));
}
- if (bubble.getKey().equals(mBubble.getKey())) {
+ boolean isNew = mBubble == null;
+ if (isNew || bubble.getKey().equals(mBubble.getKey())) {
mBubble = bubble;
- updateSettingsContentDescription();
- updateHeight();
+ mSettingsIcon.setContentDescription(getResources().getString(
+ R.string.bubbles_settings_button_description, bubble.getAppName()));
+
+ if (isNew) {
+ mBubbleIntent = mBubble.getBubbleIntent();
+ if (mBubbleIntent != null) {
+ setContentVisibility(false);
+ mActivityView.setVisibility(VISIBLE);
+ }
+ }
+ applyThemeAttrs();
} else {
Log.w(TAG, "Trying to update entry with different key, new bubble: "
+ bubble.getKey() + " old bubble: " + bubble.getKey());
}
}
- private void updateExpandedView() {
+ /**
+ * Lets activity view know it should be shown / populated with activity content.
+ */
+ void populateExpandedView() {
if (DEBUG_BUBBLE_EXPANDED_VIEW) {
- Log.d(TAG, "updateExpandedView: bubble="
- + getBubbleKey());
+ Log.d(TAG, "populateExpandedView: "
+ + "bubble=" + getBubbleKey());
}
- mBubbleIntent = mBubble.getBubbleIntent();
- if (mBubbleIntent != null) {
- setContentVisibility(false);
- mActivityView.setVisibility(VISIBLE);
+ if (usingActivityView()) {
+ mActivityView.setCallback(mStateCallback);
+ } else {
+ Log.e(TAG, "Cannot populate expanded view.");
}
- updateView();
}
boolean performBackPressIfNeeded() {
@@ -490,16 +472,6 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList
}
}
- private void updateSettingsContentDescription() {
- mSettingsIcon.setContentDescription(getResources().getString(
- R.string.bubbles_settings_button_description, mAppName));
- }
-
- void showSettingsIcon() {
- updateSettingsContentDescription();
- mSettingsIcon.setVisibility(VISIBLE);
- }
-
/**
* Update appearance of the expanded view being displayed.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleIconFactory.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleIconFactory.java
index 9ff033cb3411..b32dbb724258 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleIconFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleIconFactory.java
@@ -15,11 +15,14 @@
*/
package com.android.systemui.bubbles;
+import android.app.Notification;
import android.content.Context;
+import android.content.pm.LauncherApps;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
import com.android.launcher3.icons.BaseIconFactory;
import com.android.launcher3.icons.BitmapInfo;
@@ -42,19 +45,40 @@ public class BubbleIconFactory extends BaseIconFactory {
return mContext.getResources().getDimensionPixelSize(
com.android.launcher3.icons.R.dimen.profile_badge_size);
}
+ /**
+ * Returns the drawable that the developer has provided to display in the bubble.
+ */
+ Drawable getBubbleDrawable(Bubble b, Context context) {
+ if (b.getShortcutInfo() != null && b.usingShortcutInfo()) {
+ LauncherApps launcherApps =
+ (LauncherApps) context.getSystemService(Context.LAUNCHER_APPS_SERVICE);
+ int density = context.getResources().getConfiguration().densityDpi;
+ return launcherApps.getShortcutIconDrawable(b.getShortcutInfo(), density);
+ } else {
+ Notification.BubbleMetadata metadata = b.getEntry().getBubbleMetadata();
+ Icon ic = metadata.getIcon();
+ return ic.loadDrawable(context);
+ }
+ }
- BitmapInfo getBadgedBitmap(Bubble b) {
+ /**
+ * Returns a {@link BitmapInfo} for the app-badge that is shown on top of each bubble. This
+ * will include the workprofile indicator on the badge if appropriate.
+ */
+ BitmapInfo getBadgeBitmap(Drawable userBadgedAppIcon) {
Bitmap userBadgedBitmap = createIconBitmap(
- b.getUserBadgedAppIcon(), 1f, getBadgeSize());
+ userBadgedAppIcon, 1f, getBadgeSize());
Canvas c = new Canvas();
ShadowGenerator shadowGenerator = new ShadowGenerator(getBadgeSize());
c.setBitmap(userBadgedBitmap);
shadowGenerator.recreateIcon(Bitmap.createBitmap(userBadgedBitmap), c);
- BitmapInfo bitmapInfo = createIconBitmap(userBadgedBitmap);
- return bitmapInfo;
+ return createIconBitmap(userBadgedBitmap);
}
+ /**
+ * Returns a {@link BitmapInfo} for the entire bubble icon including the badge.
+ */
BitmapInfo getBubbleBitmap(Drawable bubble, BitmapInfo badge) {
BitmapInfo bubbleIconInfo = createBadgedIconBitmap(bubble,
null /* user */,
@@ -64,5 +88,4 @@ public class BubbleIconFactory extends BaseIconFactory {
new BitmapDrawable(mContext.getResources(), badge.icon));
return bubbleIconInfo;
}
-
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index 245b2320f99d..898768311031 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -516,14 +516,7 @@ public class BubbleStackView extends FrameLayout {
* Handle theme changes.
*/
public void onThemeChanged() {
- // Recreate icon factory to update default adaptive icon scale.
- mBubbleIconFactory = new BubbleIconFactory(mContext);
setUpFlyout();
- for (Bubble b: mBubbleData.getBubbles()) {
- b.getIconView().setBubbleIconFactory(mBubbleIconFactory);
- b.getIconView().updateViews();
- b.getExpandedView().applyThemeAttrs();
- }
}
/** Respond to the phone being rotated by repositioning the stack and hiding any flyouts. */
@@ -749,10 +742,6 @@ public class BubbleStackView extends FrameLayout {
mStackOnLeftOrWillBe = mStackAnimationController.isStackOnLeftSide();
}
- bubble.setBubbleIconFactory(mBubbleIconFactory);
- bubble.inflate(mInflater, this);
- bubble.getIconView().updateViews();
-
// Set the dot position to the opposite of the side the stack is resting on, since the stack
// resting slightly off-screen would result in the dot also being off-screen.
bubble.getIconView().setDotPosition(
@@ -1567,9 +1556,6 @@ public class BubbleStackView extends FrameLayout {
mExpandedViewContainer.setVisibility(mIsExpanded ? VISIBLE : GONE);
if (mIsExpanded) {
- // First update the view so that it calculates a new height (ensuring the y position
- // calculation is correct)
- mExpandedBubble.getExpandedView().updateView();
final float y = getExpandedViewY();
if (!mExpandedViewYAnim.isRunning()) {
// We're not animating so set the value
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleViewInfoTask.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleViewInfoTask.java
new file mode 100644
index 000000000000..41f5028ed5c7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleViewInfoTask.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.bubbles;
+
+import static com.android.systemui.bubbles.BadgedImageView.DEFAULT_PATH_SIZE;
+import static com.android.systemui.bubbles.BadgedImageView.WHITE_SCRIM_ALPHA;
+import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_BUBBLES;
+import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ShortcutInfo;
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.Path;
+import android.graphics.drawable.Drawable;
+import android.os.AsyncTask;
+import android.service.notification.StatusBarNotification;
+import android.util.Log;
+import android.util.PathParser;
+import android.view.LayoutInflater;
+
+import androidx.annotation.Nullable;
+
+import com.android.internal.graphics.ColorUtils;
+import com.android.launcher3.icons.BitmapInfo;
+import com.android.systemui.R;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * Simple task to inflate views & load necessary info to display a bubble.
+ */
+public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask.BubbleViewInfo> {
+ private static final String TAG = TAG_WITH_CLASS_NAME ? "BubbleViewInfoTask" : TAG_BUBBLES;
+
+
+ /**
+ * Callback to find out when the bubble has been inflated & necessary data loaded.
+ */
+ public interface Callback {
+ /**
+ * Called when data has been loaded for the bubble.
+ */
+ void onBubbleViewsReady(Bubble bubble);
+ }
+
+ private Bubble mBubble;
+ private WeakReference<Context> mContext;
+ private WeakReference<BubbleStackView> mStackView;
+ private BubbleIconFactory mIconFactory;
+ private Callback mCallback;
+
+ /**
+ * Creates a task to load information for the provided {@link Bubble}. Once all info
+ * is loaded, {@link Callback} is notified.
+ */
+ BubbleViewInfoTask(Bubble b,
+ Context context,
+ BubbleStackView stackView,
+ BubbleIconFactory factory,
+ Callback c) {
+ mBubble = b;
+ mContext = new WeakReference<>(context);
+ mStackView = new WeakReference<>(stackView);
+ mIconFactory = factory;
+ mCallback = c;
+ }
+
+ @Override
+ protected BubbleViewInfo doInBackground(Void... voids) {
+ return BubbleViewInfo.populate(mContext.get(), mStackView.get(), mIconFactory, mBubble);
+ }
+
+ @Override
+ protected void onPostExecute(BubbleViewInfo viewInfo) {
+ if (viewInfo != null) {
+ mBubble.setViewInfo(viewInfo);
+ if (mCallback != null && !isCancelled()) {
+ mCallback.onBubbleViewsReady(mBubble);
+ }
+ }
+ }
+
+ static class BubbleViewInfo {
+ BadgedImageView imageView;
+ BubbleExpandedView expandedView;
+ ShortcutInfo shortcutInfo;
+ String appName;
+ Bitmap badgedBubbleImage;
+ int dotColor;
+ Path dotPath;
+
+ @Nullable
+ static BubbleViewInfo populate(Context c, BubbleStackView stackView,
+ BubbleIconFactory iconFactory, Bubble b) {
+ BubbleViewInfo info = new BubbleViewInfo();
+
+ // View inflation: only should do this once per bubble
+ if (!b.isInflated()) {
+ LayoutInflater inflater = LayoutInflater.from(c);
+ info.imageView = (BadgedImageView) inflater.inflate(
+ R.layout.bubble_view, stackView, false /* attachToRoot */);
+
+ info.expandedView = (BubbleExpandedView) inflater.inflate(
+ R.layout.bubble_expanded_view, stackView, false /* attachToRoot */);
+ info.expandedView.setStackView(stackView);
+ }
+
+ StatusBarNotification sbn = b.getEntry().getSbn();
+ String packageName = sbn.getPackageName();
+
+ // Shortcut info for this bubble
+ String shortcutId = sbn.getNotification().getShortcutId();
+ if (BubbleExperimentConfig.useShortcutInfoToBubble(c)
+ && shortcutId != null) {
+ info.shortcutInfo = BubbleExperimentConfig.getShortcutInfo(c,
+ packageName,
+ sbn.getUser(), shortcutId);
+ }
+
+ // App name & app icon
+ PackageManager pm = c.getPackageManager();
+ ApplicationInfo appInfo;
+ Drawable badgedIcon;
+ try {
+ appInfo = pm.getApplicationInfo(
+ packageName,
+ PackageManager.MATCH_UNINSTALLED_PACKAGES
+ | PackageManager.MATCH_DISABLED_COMPONENTS
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+ | PackageManager.MATCH_DIRECT_BOOT_AWARE);
+ if (appInfo != null) {
+ info.appName = String.valueOf(pm.getApplicationLabel(appInfo));
+ }
+ Drawable appIcon = pm.getApplicationIcon(packageName);
+ badgedIcon = pm.getUserBadgedIcon(appIcon, sbn.getUser());
+ } catch (PackageManager.NameNotFoundException exception) {
+ // If we can't find package... don't think we should show the bubble.
+ Log.w(TAG, "Unable to find package: " + packageName);
+ return null;
+ }
+
+ // Badged bubble image
+ Drawable bubbleDrawable = iconFactory.getBubbleDrawable(b, c);
+ BitmapInfo badgeBitmapInfo = iconFactory.getBadgeBitmap(badgedIcon);
+ info.badgedBubbleImage = iconFactory.getBubbleBitmap(bubbleDrawable,
+ badgeBitmapInfo).icon;
+
+ // Dot color & placement
+ Path iconPath = PathParser.createPathFromPathData(
+ c.getResources().getString(com.android.internal.R.string.config_icon_mask));
+ Matrix matrix = new Matrix();
+ float scale = iconFactory.getNormalizer().getScale(bubbleDrawable,
+ null /* outBounds */, null /* path */, null /* outMaskShape */);
+ float radius = DEFAULT_PATH_SIZE / 2f;
+ matrix.setScale(scale /* x scale */, scale /* y scale */, radius /* pivot x */,
+ radius /* pivot y */);
+ iconPath.transform(matrix);
+ info.dotPath = iconPath;
+ info.dotColor = ColorUtils.blendARGB(badgeBitmapInfo.color,
+ Color.WHITE, WHITE_SCRIM_ALPHA);
+ return info;
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java
index 20742d6d2358..eb014ed0fc48 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java
@@ -37,8 +37,8 @@ import com.android.internal.logging.MetricsLogger;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.Dependency;
-import com.android.systemui.UiOffloadThread;
import com.android.systemui.analytics.DataCollector;
+import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
@@ -46,6 +46,7 @@ import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.util.sensors.AsyncSensorManager;
import java.io.PrintWriter;
+import java.util.concurrent.Executor;
/**
* When the phone is locked, listens to touch, sensor and phone events and sends them to
@@ -77,7 +78,7 @@ public class FalsingManagerImpl implements FalsingManager {
private final DataCollector mDataCollector;
private final HumanInteractionClassifier mHumanInteractionClassifier;
private final AccessibilityManager mAccessibilityManager;
- private final UiOffloadThread mUiOffloadThread;
+ private final Executor mUiBgExecutor;
private boolean mEnforceBouncer = false;
private boolean mBouncerOn = false;
@@ -137,13 +138,13 @@ public class FalsingManagerImpl implements FalsingManager {
}
};
- FalsingManagerImpl(Context context) {
+ FalsingManagerImpl(Context context, @UiBackground Executor uiBgExecutor) {
mContext = context;
mSensorManager = Dependency.get(AsyncSensorManager.class);
mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
mDataCollector = DataCollector.getInstance(mContext);
mHumanInteractionClassifier = HumanInteractionClassifier.getInstance(mContext);
- mUiOffloadThread = Dependency.get(UiOffloadThread.class);
+ mUiBgExecutor = uiBgExecutor;
mScreenOn = context.getSystemService(PowerManager.class).isInteractive();
mMetricsLogger = new MetricsLogger();
@@ -196,7 +197,7 @@ public class FalsingManagerImpl implements FalsingManager {
}
// This can be expensive, and doesn't need to happen on the main thread.
- mUiOffloadThread.submit(() -> {
+ mUiBgExecutor.execute(() -> {
mSensorManager.unregisterListener(mSensorEventListener);
});
}
@@ -237,7 +238,7 @@ public class FalsingManagerImpl implements FalsingManager {
if (s != null) {
// This can be expensive, and doesn't need to happen on the main thread.
- mUiOffloadThread.submit(() -> {
+ mUiBgExecutor.execute(() -> {
mSensorManager.registerListener(
mSensorEventListener, s, SensorManager.SENSOR_DELAY_GAME);
});
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
index db85fa0a3203..f475948b43f7 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
@@ -30,7 +30,8 @@ import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.Dependency;
import com.android.systemui.classifier.brightline.BrightLineFalsingManager;
import com.android.systemui.classifier.brightline.FalsingDataProvider;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.FalsingPlugin;
import com.android.systemui.plugins.PluginListener;
@@ -39,6 +40,7 @@ import com.android.systemui.util.DeviceConfigProxy;
import com.android.systemui.util.sensors.ProximitySensor;
import java.io.PrintWriter;
+import java.util.concurrent.Executor;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -58,13 +60,16 @@ public class FalsingManagerProxy implements FalsingManager {
private DeviceConfig.OnPropertiesChangedListener mDeviceConfigListener;
private final DeviceConfigProxy mDeviceConfig;
private boolean mBrightlineEnabled;
+ private Executor mUiBgExecutor;
@Inject
FalsingManagerProxy(Context context, PluginManager pluginManager,
- @MainHandler Handler handler,
+ @Main Handler handler,
ProximitySensor proximitySensor,
- DeviceConfigProxy deviceConfig) {
+ DeviceConfigProxy deviceConfig,
+ @UiBackground Executor uiBgExecutor) {
mProximitySensor = proximitySensor;
+ mUiBgExecutor = uiBgExecutor;
mProximitySensor.setTag(PROXIMITY_SENSOR_TAG);
mProximitySensor.setSensorDelay(SensorManager.SENSOR_DELAY_GAME);
mDeviceConfig = deviceConfig;
@@ -87,7 +92,7 @@ public class FalsingManagerProxy implements FalsingManager {
}
public void onPluginDisconnected(FalsingPlugin plugin) {
- mInternalFalsingManager = new FalsingManagerImpl(context);
+ mInternalFalsingManager = new FalsingManagerImpl(context, mUiBgExecutor);
}
};
@@ -117,7 +122,7 @@ public class FalsingManagerProxy implements FalsingManager {
mInternalFalsingManager.cleanup();
}
if (!brightlineEnabled) {
- mInternalFalsingManager = new FalsingManagerImpl(context);
+ mInternalFalsingManager = new FalsingManagerImpl(context, mUiBgExecutor);
} else {
mInternalFalsingManager = new BrightLineFalsingManager(
new FalsingDataProvider(context.getResources().getDisplayMetrics()),
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
index 6ea3f4ef958c..8d10552332ba 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
@@ -25,8 +25,6 @@ import android.hardware.display.AmbientDisplayConfiguration;
import android.hardware.display.NightDisplayListener;
import android.os.Handler;
import android.os.HandlerThread;
-import android.os.Looper;
-import android.os.Process;
import android.os.ServiceManager;
import android.util.DisplayMetrics;
import android.view.IWindowManager;
@@ -35,11 +33,8 @@ import android.view.LayoutInflater;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.ViewMediatorCallback;
-import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dagger.qualifiers.BgHandler;
-import com.android.systemui.dagger.qualifiers.BgLooper;
-import com.android.systemui.dagger.qualifiers.MainHandler;
-import com.android.systemui.dagger.qualifiers.MainLooper;
+import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.doze.AlwaysOnDisplayPolicy;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.plugins.PluginInitializerImpl;
@@ -54,8 +49,6 @@ 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.statusbar.policy.DeviceProvisionedController;
-import com.android.systemui.statusbar.policy.DeviceProvisionedControllerImpl;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.util.leak.LeakDetector;
@@ -85,35 +78,6 @@ public class DependencyProvider {
return new Handler(thread.getLooper());
}
- @Singleton
- @Provides
- @BgLooper
- public Looper provideBgLooper() {
- HandlerThread thread = new HandlerThread("SysUiBg",
- Process.THREAD_PRIORITY_BACKGROUND);
- thread.start();
- return thread.getLooper();
- }
-
- /** Main Looper */
- @Provides
- @MainLooper
- public Looper provideMainLooper() {
- return Looper.getMainLooper();
- }
-
- @Provides
- @BgHandler
- public Handler provideBgHandler(@BgLooper Looper bgLooper) {
- return new Handler(bgLooper);
- }
-
- @Provides
- @MainHandler
- public Handler provideMainHandler(@MainLooper Looper mainLooper) {
- return new Handler(mainLooper);
- }
-
/** */
@Provides
public AmbientDisplayConfiguration provideAmbientDispalyConfiguration(Context context) {
@@ -178,7 +142,7 @@ public class DependencyProvider {
@Singleton
@Provides
public NightDisplayListener provideNightDisplayListener(Context context,
- @BgHandler Handler bgHandler) {
+ @Background Handler bgHandler) {
return new NightDisplayListener(context, bgHandler);
}
@@ -191,7 +155,7 @@ public class DependencyProvider {
@Singleton
@Provides
public NavigationBarController provideNavigationBarController(Context context,
- @MainHandler Handler mainHandler, CommandQueue commandQueue) {
+ @Main Handler mainHandler, CommandQueue commandQueue) {
return new NavigationBarController(context, mainHandler, commandQueue);
}
@@ -204,7 +168,7 @@ public class DependencyProvider {
@Singleton
@Provides
public AutoHideController provideAutoHideController(Context context,
- @MainHandler Handler mainHandler,
+ @Main Handler mainHandler,
NotificationRemoteInputManager notificationRemoteInputManager,
IWindowManager iWindowManager) {
return new AutoHideController(context, mainHandler, notificationRemoteInputManager,
@@ -223,13 +187,6 @@ public class DependencyProvider {
return DevicePolicyManagerWrapper.getInstance();
}
- @Singleton
- @Provides
- public DeviceProvisionedController provideDeviceProvisionedController(Context context,
- @MainHandler Handler mainHandler, BroadcastDispatcher broadcastDispatcher) {
- return new DeviceProvisionedControllerImpl(context, mainHandler, broadcastDispatcher);
- }
-
/** */
@Provides
public LockPatternUtils provideLockPatternUtils(Context context) {
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java
index 534f350e4898..0b73ab6f9136 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java
@@ -44,8 +44,8 @@ import android.view.accessibility.AccessibilityManager;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.util.LatencyTracker;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
-import com.android.systemui.dagger.qualifiers.BgHandler;
-import com.android.systemui.dagger.qualifiers.MainResources;
+import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.shared.system.PackageManagerWrapper;
import javax.inject.Singleton;
@@ -126,7 +126,7 @@ public class SystemServicesModule {
@Provides
@Nullable
static LocalBluetoothManager provideLocalBluetoothController(Context context,
- @BgHandler Handler bgHandler) {
+ @Background Handler bgHandler) {
return LocalBluetoothManager.create(context, bgHandler, UserHandle.ALL);
}
@@ -150,7 +150,7 @@ public class SystemServicesModule {
}
@Provides
- @MainResources
+ @Main
static Resources provideResources(Context context) {
return context.getResources();
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
index ccb6c2f6381e..5c171e41db41 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
@@ -30,7 +30,7 @@ import com.android.systemui.power.EnhancedEstimates;
import com.android.systemui.power.EnhancedEstimatesImpl;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsImplementation;
-import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.stackdivider.DividerModule;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
@@ -40,15 +40,14 @@ import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.KeyguardEnvironmentImpl;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.ShadeControllerImpl;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.DeviceProvisionedControllerImpl;
import com.android.systemui.statusbar.policy.HeadsUpManager;
-import java.util.Optional;
-
import javax.inject.Named;
import javax.inject.Singleton;
import dagger.Binds;
-import dagger.Lazy;
import dagger.Module;
import dagger.Provides;
@@ -56,7 +55,7 @@ import dagger.Provides;
* A dagger module for injecting default implementations of components of System UI that may be
* overridden by the System UI implementation.
*/
-@Module
+@Module(includes = {DividerModule.class})
abstract class SystemUIDefaultModule {
@Singleton
@@ -93,12 +92,6 @@ abstract class SystemUIDefaultModule {
@Singleton
@Provides
- static Divider provideDivider(Context context, Optional<Lazy<Recents>> recentsOptionalLazy) {
- return new Divider(context, recentsOptionalLazy);
- }
-
- @Singleton
- @Provides
static HeadsUpManagerPhone provideHeadsUpManagerPhone(Context context,
StatusBarStateController statusBarStateController,
KeyguardBypassController bypassController) {
@@ -114,4 +107,8 @@ abstract class SystemUIDefaultModule {
CommandQueue commandQueue) {
return new Recents(context, recentsImplementation, commandQueue);
}
+
+ @Binds
+ abstract DeviceProvisionedController bindDeviceProvisionedController(
+ DeviceProvisionedControllerImpl deviceProvisionedController);
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIRootComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIRootComponent.java
index e50e0fe0d224..e14581ffcde8 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIRootComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIRootComponent.java
@@ -22,6 +22,7 @@ import android.content.ContentProvider;
import com.android.systemui.BootCompleteCacheImpl;
import com.android.systemui.Dependency;
+import com.android.systemui.InitController;
import com.android.systemui.SystemUIAppComponentFactory;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.fragments.FragmentService;
@@ -77,6 +78,13 @@ public interface SystemUIRootComponent {
@Singleton
FragmentService.FragmentCreator createFragmentCreator();
+
+ /**
+ * Creates a InitController.
+ */
+ @Singleton
+ InitController getInitController();
+
/**
* ViewCreator generates all Views that need injection.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/MainResources.java b/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/MainResources.java
deleted file mode 100644
index 3daeda550b4c..000000000000
--- a/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/MainResources.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.dagger.qualifiers;
-
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-
-import javax.inject.Qualifier;
-
-@Qualifier
-@Documented
-@Retention(RUNTIME)
-public @interface MainResources {
- // TODO: use attribute to get other, non-main resources?
-}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/BgLooper.java b/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/UiBackground.java
index 2aadda1215d5..bf2237aa8c11 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/BgLooper.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/UiBackground.java
@@ -23,8 +23,12 @@ import java.lang.annotation.Retention;
import javax.inject.Qualifier;
+
+/**
+ * An annotation for injecting instances related to UI operations off the main-thread.
+ */
@Qualifier
@Documented
@Retention(RUNTIME)
-public @interface BgLooper {
+public @interface UiBackground {
}
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index ef853e65c4a2..3ccad64d76dc 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -81,7 +81,6 @@ import com.android.internal.colorextraction.drawable.ScrimDrawable;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.statusbar.IStatusBarService;
-import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.util.EmergencyAffordanceManager;
import com.android.internal.util.ScreenRecordHelper;
import com.android.internal.util.ScreenshotHelper;
@@ -190,7 +189,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
filter.addAction(Intent.ACTION_SCREEN_OFF);
- filter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
+ filter.addAction(TelephonyManager.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
mBroadcastDispatcher.registerReceiver(mBroadcastReceiver, filter);
ConnectivityManager cm = (ConnectivityManager)
@@ -314,7 +313,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
mIsWaitingForEcmExit = true;
// Launch ECM exit dialog
Intent ecmDialogIntent =
- new Intent(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS, null);
+ new Intent(TelephonyManager.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS, null);
ecmDialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(ecmDialogIntent);
} else {
@@ -1420,7 +1419,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
if (!SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS.equals(reason)) {
mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_DISMISS, reason));
}
- } else if (TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED.equals(action)) {
+ } else if (TelephonyManager.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED.equals(action)) {
// Airplane mode can be changed after ECM exits if airplane toggle button
// is pressed during ECM mode
if (!(intent.getBooleanExtra("PHONE_IN_ECM_STATE", false)) &&
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/EglHelper.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/EglHelper.java
index c6812a75b3bf..4b28540d11a4 100644
--- a/packages/SystemUI/src/com/android/systemui/glwallpaper/EglHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/EglHelper.java
@@ -51,40 +51,65 @@ import android.opengl.EGLContext;
import android.opengl.EGLDisplay;
import android.opengl.EGLSurface;
import android.opengl.GLUtils;
+import android.text.TextUtils;
import android.util.Log;
import android.view.SurfaceHolder;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
/**
* A helper class to handle EGL management.
*/
public class EglHelper {
private static final String TAG = EglHelper.class.getSimpleName();
+ private static final int OPENGLES_VERSION = 2;
// Below two constants make drawing at low priority, so other things can preempt our drawing.
private static final int EGL_CONTEXT_PRIORITY_LEVEL_IMG = 0x3100;
private static final int EGL_CONTEXT_PRIORITY_LOW_IMG = 0x3103;
private static final boolean DEBUG = true;
+
+ private static final int EGL_GL_COLORSPACE_KHR = 0x309D;
+ private static final int EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT = 0x3490;
+
private static final String EGL_IMG_CONTEXT_PRIORITY = "EGL_IMG_context_priority";
+ /**
+ * https://www.khronos.org/registry/EGL/extensions/KHR/EGL_KHR_gl_colorspace.txt
+ */
+ private static final String KHR_GL_COLOR_SPACE = "EGL_KHR_gl_colorspace";
+
+ /**
+ * https://www.khronos.org/registry/EGL/extensions/EXT/EGL_EXT_gl_colorspace_display_p3_passthrough.txt
+ */
+ private static final String EXT_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH =
+ "EGL_EXT_gl_colorspace_display_p3_passthrough";
+
private EGLDisplay mEglDisplay;
private EGLConfig mEglConfig;
private EGLContext mEglContext;
private EGLSurface mEglSurface;
private final int[] mEglVersion = new int[2];
private boolean mEglReady;
- private boolean mContextPrioritySupported;
+ private final Set<String> mExts;
+
+ public EglHelper() {
+ mExts = new HashSet<>();
+ connectDisplay();
+ }
/**
- * Initialize EGL and prepare EglSurface.
+ * Initialize render context.
* @param surfaceHolder surface holder.
- * @return true if EglSurface is ready.
+ * @param wideColorGamut claim if a wcg surface is necessary.
+ * @return true if the render context is ready.
*/
- public boolean init(SurfaceHolder surfaceHolder) {
- mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- if (mEglDisplay == EGL_NO_DISPLAY) {
- Log.w(TAG, "eglGetDisplay failed: " + GLUtils.getEGLErrorString(eglGetError()));
+ public boolean init(SurfaceHolder surfaceHolder, boolean wideColorGamut) {
+ if (!hasEglDisplay() && !connectDisplay()) {
+ Log.w(TAG, "Can not connect display, abort!");
return false;
}
@@ -105,25 +130,38 @@ public class EglHelper {
return false;
}
- if (!createEglSurface(surfaceHolder)) {
+ if (!createEglSurface(surfaceHolder, wideColorGamut)) {
Log.w(TAG, "Can't create EGLSurface!");
return false;
}
- mContextPrioritySupported = isContextPrioritySuppported();
-
mEglReady = true;
return true;
}
- private boolean isContextPrioritySuppported() {
- String[] extensions = eglQueryString(mEglDisplay, EGL_EXTENSIONS).split(" ");
- for (String extension : extensions) {
- if (extension.equals(EGL_IMG_CONTEXT_PRIORITY)) {
- return true;
- }
+ private boolean connectDisplay() {
+ mExts.clear();
+ mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ if (!hasEglDisplay()) {
+ Log.w(TAG, "eglGetDisplay failed: " + GLUtils.getEGLErrorString(eglGetError()));
+ return false;
+ }
+ String queryString = eglQueryString(mEglDisplay, EGL_EXTENSIONS);
+ if (!TextUtils.isEmpty(queryString)) {
+ Collections.addAll(mExts, queryString.split(" "));
}
- return false;
+ return true;
+ }
+
+ private boolean checkExtensionCapability(String extName) {
+ return mExts.contains(extName);
+ }
+
+ private int getWcgCapability() {
+ if (checkExtensionCapability(EXT_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH)) {
+ return EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT;
+ }
+ return 0;
}
private EGLConfig chooseEglConfig() {
@@ -148,7 +186,7 @@ public class EglHelper {
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
- EGL_ALPHA_SIZE, 8,
+ EGL_ALPHA_SIZE, 0,
EGL_DEPTH_SIZE, 0,
EGL_STENCIL_SIZE, 0,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
@@ -160,21 +198,27 @@ public class EglHelper {
/**
* Prepare an EglSurface.
* @param surfaceHolder surface holder.
+ * @param wcg if need to support wcg.
* @return true if EglSurface is ready.
*/
- public boolean createEglSurface(SurfaceHolder surfaceHolder) {
+ public boolean createEglSurface(SurfaceHolder surfaceHolder, boolean wcg) {
if (DEBUG) {
Log.d(TAG, "createEglSurface start");
}
if (hasEglDisplay()) {
- mEglSurface = eglCreateWindowSurface(mEglDisplay, mEglConfig, surfaceHolder, null, 0);
+ int[] attrs = null;
+ int wcgCapability = getWcgCapability();
+ if (wcg && checkExtensionCapability(KHR_GL_COLOR_SPACE) && wcgCapability > 0) {
+ attrs = new int[] {EGL_GL_COLORSPACE_KHR, wcgCapability, EGL_NONE};
+ }
+ mEglSurface = eglCreateWindowSurface(mEglDisplay, mEglConfig, surfaceHolder, attrs, 0);
} else {
Log.w(TAG, "mEglDisplay is null");
return false;
}
- if (mEglSurface == null || mEglSurface == EGL_NO_SURFACE) {
+ if (!hasEglSurface()) {
Log.w(TAG, "createWindowSurface failed: " + GLUtils.getEGLErrorString(eglGetError()));
return false;
}
@@ -221,12 +265,12 @@ public class EglHelper {
int[] attrib_list = new int[5];
int idx = 0;
attrib_list[idx++] = EGL_CONTEXT_CLIENT_VERSION;
- attrib_list[idx++] = 2;
- if (mContextPrioritySupported) {
+ attrib_list[idx++] = OPENGLES_VERSION;
+ if (checkExtensionCapability(EGL_IMG_CONTEXT_PRIORITY)) {
attrib_list[idx++] = EGL_CONTEXT_PRIORITY_LEVEL_IMG;
attrib_list[idx++] = EGL_CONTEXT_PRIORITY_LOW_IMG;
}
- attrib_list[idx++] = EGL_NONE;
+ attrib_list[idx] = EGL_NONE;
if (hasEglDisplay()) {
mEglContext = eglCreateContext(mEglDisplay, mEglConfig, EGL_NO_CONTEXT, attrib_list, 0);
} else {
@@ -234,7 +278,7 @@ public class EglHelper {
return false;
}
- if (mEglContext == EGL_NO_CONTEXT) {
+ if (!hasEglContext()) {
Log.w(TAG, "eglCreateContext failed: " + GLUtils.getEGLErrorString(eglGetError()));
return false;
}
@@ -260,7 +304,7 @@ public class EglHelper {
* @return true if EglContext is ready.
*/
public boolean hasEglContext() {
- return mEglContext != null;
+ return mEglContext != null && mEglContext != EGL_NO_CONTEXT;
}
/**
@@ -268,7 +312,7 @@ public class EglHelper {
* @return true if EglDisplay is ready.
*/
public boolean hasEglDisplay() {
- return mEglDisplay != null;
+ return mEglDisplay != null && mEglDisplay != EGL_NO_DISPLAY;
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/GLWallpaperRenderer.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/GLWallpaperRenderer.java
index 60ea1cdf6b22..88ab9ef4b014 100644
--- a/packages/SystemUI/src/com/android/systemui/glwallpaper/GLWallpaperRenderer.java
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/GLWallpaperRenderer.java
@@ -27,6 +27,11 @@ import java.io.PrintWriter;
public interface GLWallpaperRenderer {
/**
+ * Check if the content to render is a WCG content.
+ */
+ boolean isWcgContent();
+
+ /**
* Called when the surface is created or recreated.
*/
void onSurfaceCreated();
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageProcessHelper.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageProcessHelper.java
index 24a4b9e3052b..54eca0e26692 100644
--- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageProcessHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageProcessHelper.java
@@ -116,7 +116,8 @@ class ImageProcessHelper {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
- Bitmap grayscale = Bitmap.createBitmap(width, height, bitmap.getConfig());
+ Bitmap grayscale = Bitmap.createBitmap(width, height, bitmap.getConfig(),
+ false /* hasAlpha */, bitmap.getColorSpace());
Canvas canvas = new Canvas(grayscale);
ColorMatrix cm = new ColorMatrix(LUMINOSITY_MATRIX);
Paint paint = new Paint();
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
index a8371e31d71c..fa8269d1c198 100644
--- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
@@ -62,6 +62,7 @@ public class ImageWallpaperRenderer implements GLWallpaperRenderer,
private boolean mScissorMode;
private float mXOffset;
private float mYOffset;
+ private boolean mWcgContent;
public ImageWallpaperRenderer(Context context, SurfaceProxy proxy) {
mWallpaperManager = context.getSystemService(WallpaperManager.class);
@@ -94,6 +95,11 @@ public class ImageWallpaperRenderer implements GLWallpaperRenderer,
}
@Override
+ public boolean isWcgContent() {
+ return mWcgContent;
+ }
+
+ @Override
public void onSurfaceCreated() {
glClearColor(0f, 0f, 0f, 1.0f);
mProgram.useGLProgram(
@@ -112,7 +118,8 @@ public class ImageWallpaperRenderer implements GLWallpaperRenderer,
Log.d(TAG, "loadBitmap: mBitmap=" + mBitmap);
}
if (mWallpaperManager != null && mBitmap == null) {
- mBitmap = mWallpaperManager.getBitmap();
+ mBitmap = mWallpaperManager.getBitmap(false /* hardware */);
+ mWcgContent = mWallpaperManager.wallpaperSupportsWcg(WallpaperManager.FLAG_SYSTEM);
mWallpaperManager.forgetLoadedWallpaper();
if (mBitmap != null) {
float scale = (float) mScissor.height() / mBitmap.getHeight();
@@ -231,6 +238,7 @@ public class ImageWallpaperRenderer implements GLWallpaperRenderer,
out.print(prefix); out.print("mYOffset="); out.print(mYOffset);
out.print(prefix); out.print("threshold="); out.print(mImageProcessHelper.getThreshold());
out.print(prefix); out.print("mReveal="); out.print(mImageRevealHelper.getReveal());
+ out.print(prefix); out.print("mWcgContent="); out.print(mWcgContent);
mWallpaper.dump(prefix, fd, out, args);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java b/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java
index 25ac8f868435..f6f3b9985371 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java
@@ -11,16 +11,16 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
package com.android.systemui.keyguard;
import com.android.internal.policy.IKeyguardDismissCallback;
-import com.android.systemui.Dependency;
-import com.android.systemui.UiOffloadThread;
+import com.android.systemui.dagger.qualifiers.UiBackground;
import java.util.ArrayList;
+import java.util.concurrent.Executor;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -32,10 +32,12 @@ import javax.inject.Singleton;
public class DismissCallbackRegistry {
private final ArrayList<DismissCallbackWrapper> mDismissCallbacks = new ArrayList<>();
- private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
+ private final Executor mUiBgExecutor;
@Inject
- public DismissCallbackRegistry() {}
+ public DismissCallbackRegistry(@UiBackground Executor uiBgExecutor) {
+ mUiBgExecutor = uiBgExecutor;
+ }
public void addCallback(IKeyguardDismissCallback callback) {
mDismissCallbacks.add(new DismissCallbackWrapper(callback));
@@ -44,7 +46,7 @@ public class DismissCallbackRegistry {
public void notifyDismissCancelled() {
for (int i = mDismissCallbacks.size() - 1; i >= 0; i--) {
DismissCallbackWrapper callback = mDismissCallbacks.get(i);
- mUiOffloadThread.submit(callback::notifyDismissCancelled);
+ mUiBgExecutor.execute(callback::notifyDismissCancelled);
}
mDismissCallbacks.clear();
}
@@ -52,7 +54,7 @@ public class DismissCallbackRegistry {
public void notifyDismissSucceeded() {
for (int i = mDismissCallbacks.size() - 1; i >= 0; i--) {
DismissCallbackWrapper callback = mDismissCallbacks.get(i);
- mUiOffloadThread.submit(callback::notifyDismissSucceeded);
+ mUiBgExecutor.execute(callback::notifyDismissSucceeded);
}
mDismissCallbacks.clear();
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index beba203b9702..9fcf0221e41a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
package com.android.systemui.keyguard;
@@ -81,8 +81,8 @@ import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
import com.android.systemui.SystemUIFactory;
-import com.android.systemui.UiOffloadThread;
import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.phone.BiometricUnlockController;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
@@ -95,6 +95,7 @@ import com.android.systemui.util.InjectionInflationController;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.concurrent.Executor;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -211,7 +212,7 @@ public class KeyguardViewMediator extends SystemUI {
private AudioManager mAudioManager;
private StatusBarManager mStatusBarManager;
private final StatusBarWindowController mStatusBarWindowController;
- private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
+ private final Executor mUiBgExecutor;
private boolean mSystemReady;
private boolean mBootCompleted;
@@ -689,7 +690,8 @@ public class KeyguardViewMediator extends SystemUI {
BroadcastDispatcher broadcastDispatcher,
StatusBarWindowController statusBarWindowController,
Lazy<StatusBarKeyguardViewManager> statusBarKeyguardViewManagerLazy,
- DismissCallbackRegistry dismissCallbackRegistry) {
+ DismissCallbackRegistry dismissCallbackRegistry,
+ @UiBackground Executor uiBgExecutor) {
super(context);
mFalsingManager = falsingManager;
mLockPatternUtils = lockPatternUtils;
@@ -697,6 +699,7 @@ public class KeyguardViewMediator extends SystemUI {
mStatusBarWindowController = statusBarWindowController;
mStatusBarKeyguardViewManagerLazy = statusBarKeyguardViewManagerLazy;
mDismissCallbackRegistry = dismissCallbackRegistry;
+ mUiBgExecutor = uiBgExecutor;
}
public void userActivity() {
@@ -1662,7 +1665,7 @@ public class KeyguardViewMediator extends SystemUI {
private void handleKeyguardDone() {
Trace.beginSection("KeyguardViewMediator#handleKeyguardDone");
final int currentUser = KeyguardUpdateMonitor.getCurrentUser();
- mUiOffloadThread.submit(() -> {
+ mUiBgExecutor.execute(() -> {
if (mLockPatternUtils.isSecure(currentUser)) {
mLockPatternUtils.getDevicePolicyManager().reportKeyguardDismissed(currentUser);
}
@@ -1705,7 +1708,7 @@ public class KeyguardViewMediator extends SystemUI {
final UserHandle currentUser = new UserHandle(currentUserId);
final UserManager um = (UserManager) mContext.getSystemService(
Context.USER_SERVICE);
- mUiOffloadThread.submit(() -> {
+ mUiBgExecutor.execute(() -> {
for (int profileId : um.getProfileIdsWithDisabled(currentUser.getIdentifier())) {
mContext.sendBroadcastAsUser(USER_PRESENT_INTENT, UserHandle.of(profileId));
}
@@ -1756,7 +1759,7 @@ public class KeyguardViewMediator extends SystemUI {
mUiSoundsStreamType = mAudioManager.getUiSoundsStreamType();
}
- mUiOffloadThread.submit(() -> {
+ mUiBgExecutor.execute(() -> {
// If the stream is muted, don't play the sound
if (mAudioManager.isStreamMute(mUiSoundsStreamType)) return;
@@ -1775,7 +1778,7 @@ public class KeyguardViewMediator extends SystemUI {
}
private void updateActivityLockScreenState(boolean showing, boolean aodShowing) {
- mUiOffloadThread.submit(() -> {
+ mUiBgExecutor.execute(() -> {
if (DEBUG) {
Log.d(TAG, "updateActivityLockScreenState(" + showing + ", " + aodShowing + ")");
}
@@ -1854,7 +1857,7 @@ public class KeyguardViewMediator extends SystemUI {
// Posting to mUiOffloadThread to ensure that calls to ActivityTaskManager will be in
// order.
final int keyguardFlag = flags;
- mUiOffloadThread.submit(() -> {
+ mUiBgExecutor.execute(() -> {
try {
ActivityTaskManager.getService().keyguardGoingAway(keyguardFlag);
} catch (RemoteException e) {
@@ -2217,7 +2220,7 @@ public class KeyguardViewMediator extends SystemUI {
}
});
updateInputRestrictedLocked();
- mUiOffloadThread.submit(() -> {
+ mUiBgExecutor.execute(() -> {
mTrustManager.reportKeyguardShowingChanged();
});
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java
index ca04633b316a..24ad75d7dcc0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java
@@ -52,12 +52,6 @@ public class WorkLockActivity extends Activity {
private static final String TAG = "WorkLockActivity";
/**
- * Add additional extra {@link com.android.settings.password.ConfirmDeviceCredentialActivity} to
- * enable device policy management enforcement from systemui.
- */
- public static final String EXTRA_FROM_WORK_LOCK_ACTIVITY = "from_work_lock_activity";
-
- /**
* Contains a {@link TaskDescription} for the activity being covered.
*/
static final String EXTRA_TASK_DESCRIPTION =
@@ -156,7 +150,8 @@ public class WorkLockActivity extends Activity {
}
final Intent credential = getKeyguardManager()
- .createConfirmDeviceCredentialIntent(null, null, getTargetUserId());
+ .createConfirmDeviceCredentialIntent(null, null, getTargetUserId(),
+ true /* disallowBiometricsIfPolicyExists */);
if (credential == null) {
return;
}
@@ -172,7 +167,6 @@ public class WorkLockActivity extends Activity {
if (target != null) {
credential.putExtra(Intent.EXTRA_INTENT, target.getIntentSender());
- credential.putExtra(EXTRA_FROM_WORK_LOCK_ACTIVITY, true);
}
final ActivityOptions launchOptions = ActivityOptions.makeBasic();
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
index f78429316e5a..66c51d278dab 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
@@ -98,8 +98,10 @@ public class MediaProjectionPermissionActivity extends Activity
paint.setTextSize(42);
CharSequence dialogText = null;
+ CharSequence dialogTitle = null;
if (Utils.isHeadlessRemoteDisplayProvider(packageManager, mPackageName)) {
dialogText = getString(R.string.media_projection_dialog_service_text);
+ dialogTitle = getString(R.string.media_projection_dialog_service_title);
} else {
String label = aInfo.loadLabel(packageManager).toString();
@@ -138,10 +140,9 @@ public class MediaProjectionPermissionActivity extends Activity
appNameIndex, appNameIndex + appName.length(), 0);
}
dialogText = message;
+ dialogTitle = getString(R.string.media_projection_dialog_title, appName);
}
- String dialogTitle = getString(R.string.media_projection_dialog_title);
-
View dialogTitleView = View.inflate(this, R.layout.media_projection_dialog_title, null);
TextView titleText = (TextView) dialogTitleView.findViewById(R.id.dialog_title);
titleText.setText(dialogTitle);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/BasePipManager.java b/packages/SystemUI/src/com/android/systemui/pip/BasePipManager.java
index 75e260e7fa70..d1d9b3de7e69 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/BasePipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/BasePipManager.java
@@ -20,11 +20,13 @@ import android.content.Context;
import android.content.res.Configuration;
import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.wm.DisplayWindowController;
import java.io.PrintWriter;
public interface BasePipManager {
- void initialize(Context context, BroadcastDispatcher broadcastDispatcher);
+ void initialize(Context context, BroadcastDispatcher broadcastDispatcher,
+ DisplayWindowController displayWindowController);
void showPictureInPictureMenu();
default void expandPip() {}
default void hidePipMenu(Runnable onStartCallback, Runnable onEndCallback) {}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
index f10274a952bc..8e34a90e7b51 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
@@ -16,8 +16,14 @@
package com.android.systemui.pip;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.util.TypedValue.COMPLEX_UNIT_DIP;
+import static android.view.Surface.ROTATION_0;
+import static android.view.Surface.ROTATION_180;
+import android.app.ActivityManager;
+import android.app.ActivityTaskManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.res.Resources;
@@ -32,10 +38,9 @@ import android.view.DisplayInfo;
import android.view.Gravity;
import android.view.IPinnedStackController;
import android.view.IWindowManager;
+import android.view.WindowContainerTransaction;
import android.view.WindowManagerGlobal;
-import com.android.internal.policy.PipSnapAlgorithm;
-
import java.io.PrintWriter;
/**
@@ -154,6 +159,7 @@ public class PipBoundsHandler {
*/
public void onMinimizedStateChanged(boolean minimized) {
mIsMinimized = minimized;
+ mSnapAlgorithm.setMinimized(minimized);
}
/**
@@ -199,6 +205,7 @@ public class PipBoundsHandler {
mReentrySnapFraction = INVALID_SNAP_FRACTION;
mReentrySize = null;
mLastPipComponentName = null;
+ mLastDestinationBounds.setEmpty();
}
public Rect getLastDestinationBounds() {
@@ -235,8 +242,9 @@ public class PipBoundsHandler {
*/
public void onPrepareAnimation(Rect sourceRectHint, float aspectRatio, Rect bounds) {
final Rect destinationBounds;
+ final Rect defaultBounds = getDefaultBounds(mReentrySnapFraction, mReentrySize);
if (bounds == null) {
- destinationBounds = getDefaultBounds(mReentrySnapFraction, mReentrySize);
+ destinationBounds = new Rect(defaultBounds);
} else {
destinationBounds = new Rect(bounds);
}
@@ -253,12 +261,85 @@ public class PipBoundsHandler {
mPinnedStackController.startAnimation(destinationBounds, sourceRectHint,
-1 /* animationDuration */);
mLastDestinationBounds.set(destinationBounds);
+ mPinnedStackController.reportBounds(defaultBounds,
+ getMovementBounds(defaultBounds));
} catch (RemoteException e) {
Log.e(TAG, "Failed to start PiP animation from SysUI", e);
}
}
/**
+ * Updates the display info, calculating and returning the new stack and movement bounds in the
+ * new orientation of the device if necessary.
+ *
+ * @return {@code true} if internal {@link DisplayInfo} is rotated, {@code false} otherwise.
+ */
+ public boolean onDisplayRotationChanged(Rect outBounds, int displayId, int fromRotation,
+ int toRotation, WindowContainerTransaction t) {
+ // Bail early if the event is not sent to current {@link #mDisplayInfo}
+ if ((displayId != mDisplayInfo.displayId) || (fromRotation == toRotation)) {
+ return false;
+ }
+
+ // Bail early if the pinned stack is staled.
+ final ActivityManager.StackInfo pinnedStackInfo;
+ try {
+ pinnedStackInfo = ActivityTaskManager.getService()
+ .getStackInfo(WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
+ if (pinnedStackInfo == null) return false;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to get StackInfo for pinned stack", e);
+ return false;
+ }
+
+ // Calculate the snap fraction of the current stack along the old movement bounds
+ final Rect postChangeStackBounds = new Rect(mLastDestinationBounds);
+ final float snapFraction = getSnapFraction(postChangeStackBounds);
+
+ // Populate the new {@link #mDisplayInfo}.
+ // The {@link DisplayInfo} queried from DisplayManager would be the one before rotation,
+ // therefore, the width/height may require a swap first.
+ // Moving forward, we should get the new dimensions after rotation from DisplayLayout.
+ mDisplayInfo.rotation = toRotation;
+ updateDisplayInfoIfNeeded();
+
+ // Calculate the stack bounds in the new orientation based on same fraction along the
+ // rotated movement bounds.
+ final Rect postChangeMovementBounds = getMovementBounds(postChangeStackBounds,
+ false /* adjustForIme */);
+ mSnapAlgorithm.applySnapFraction(postChangeStackBounds, postChangeMovementBounds,
+ snapFraction);
+ if (mIsMinimized) {
+ applyMinimizedOffset(postChangeStackBounds, postChangeMovementBounds);
+ }
+
+ try {
+ outBounds.set(postChangeStackBounds);
+ mLastDestinationBounds.set(outBounds);
+ mPinnedStackController.resetBoundsAnimation(outBounds);
+ mPinnedStackController.reportBounds(outBounds, getMovementBounds(outBounds));
+ t.setBounds(pinnedStackInfo.stackToken, outBounds);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to resize PiP on display rotation", e);
+ }
+ return true;
+ }
+
+ private void updateDisplayInfoIfNeeded() {
+ final boolean updateNeeded;
+ if ((mDisplayInfo.rotation == ROTATION_0) || (mDisplayInfo.rotation == ROTATION_180)) {
+ updateNeeded = (mDisplayInfo.logicalWidth > mDisplayInfo.logicalHeight);
+ } else {
+ updateNeeded = (mDisplayInfo.logicalWidth < mDisplayInfo.logicalHeight);
+ }
+ if (updateNeeded) {
+ final int newLogicalHeight = mDisplayInfo.logicalWidth;
+ mDisplayInfo.logicalWidth = mDisplayInfo.logicalHeight;
+ mDisplayInfo.logicalHeight = newLogicalHeight;
+ }
+ }
+
+ /**
* @return whether the given {@param aspectRatio} is valid.
*/
private boolean isValidPictureInPictureAspectRatio(float aspectRatio) {
diff --git a/core/java/com/android/internal/policy/PipSnapAlgorithm.java b/packages/SystemUI/src/com/android/systemui/pip/PipSnapAlgorithm.java
index e3623c5f332c..f3e707c6408c 100644
--- a/core/java/com/android/internal/policy/PipSnapAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipSnapAlgorithm.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.internal.policy;
+package com.android.systemui.pip;
import android.content.Context;
import android.content.res.Configuration;
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipUI.java b/packages/SystemUI/src/com/android/systemui/pip/PipUI.java
index 583ce67e26d4..29de90bb2824 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipUI.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipUI.java
@@ -28,6 +28,7 @@ import android.os.UserManager;
import com.android.systemui.SystemUI;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.wm.DisplayWindowController;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -44,15 +45,17 @@ public class PipUI extends SystemUI implements CommandQueue.Callbacks {
private final CommandQueue mCommandQueue;
private BasePipManager mPipManager;
private final BroadcastDispatcher mBroadcastDispatcher;
-
+ private final DisplayWindowController mDisplayWindowController;
private boolean mSupportsPip;
@Inject
public PipUI(Context context, CommandQueue commandQueue,
- BroadcastDispatcher broadcastDispatcher) {
+ BroadcastDispatcher broadcastDispatcher,
+ DisplayWindowController displayWindowController) {
super(context);
mBroadcastDispatcher = broadcastDispatcher;
mCommandQueue = commandQueue;
+ mDisplayWindowController = displayWindowController;
}
@Override
@@ -72,7 +75,7 @@ public class PipUI extends SystemUI implements CommandQueue.Callbacks {
mPipManager = pm.hasSystemFeature(FEATURE_LEANBACK_ONLY)
? com.android.systemui.pip.tv.PipManager.getInstance()
: com.android.systemui.pip.phone.PipManager.getInstance();
- mPipManager.initialize(mContext, mBroadcastDispatcher);
+ mPipManager.initialize(mContext, mBroadcastDispatcher, mDisplayWindowController);
mCommandQueue.addCallback(this);
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
index a4707cfb4948..f39d1ecb0585 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -34,6 +34,7 @@ import android.util.Log;
import android.util.Pair;
import android.view.DisplayInfo;
import android.view.IPinnedStackController;
+import android.view.WindowContainerTransaction;
import com.android.systemui.Dependency;
import com.android.systemui.UiOffloadThread;
@@ -45,6 +46,7 @@ import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.PinnedStackListenerForwarder.PinnedStackListener;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.WindowManagerWrapper;
+import com.android.systemui.wm.DisplayWindowController;
import java.io.PrintWriter;
@@ -75,9 +77,22 @@ public class PipManager implements BasePipManager {
private PipAppOpsListener mAppOpsListener;
/**
+ * Handler for display rotation changes.
+ */
+ private final DisplayWindowController.OnDisplayWindowRotationController mRotationController = (
+ int displayId, int fromRotation, int toRotation, WindowContainerTransaction t) -> {
+ final boolean changed = mPipBoundsHandler.onDisplayRotationChanged(mTmpNormalBounds,
+ displayId, fromRotation, toRotation, t);
+ if (changed) {
+ updateMovementBounds(mTmpNormalBounds, false /* fromImeAdjustment */,
+ false /* fromShelfAdjustment */);
+ }
+ };
+
+ /**
* Handler for system task stack changes.
*/
- TaskStackChangeListener mTaskStackListener = new TaskStackChangeListener() {
+ private final TaskStackChangeListener mTaskStackListener = new TaskStackChangeListener() {
@Override
public void onActivityPinned(String packageName, int userId, int taskId, int stackId) {
mTouchHandler.onActivityPinned();
@@ -85,7 +100,7 @@ public class PipManager implements BasePipManager {
mMenuController.onActivityPinned();
mAppOpsListener.onActivityPinned(packageName);
- Dependency.get(UiOffloadThread.class).submit(() -> {
+ Dependency.get(UiOffloadThread.class).execute(() -> {
WindowManagerWrapper.getInstance().setPipVisibility(true);
});
}
@@ -99,7 +114,7 @@ public class PipManager implements BasePipManager {
mTouchHandler.onActivityUnpinned(topActivity);
mAppOpsListener.onActivityUnpinned();
- Dependency.get(UiOffloadThread.class).submit(() -> {
+ Dependency.get(UiOffloadThread.class).execute(() -> {
WindowManagerWrapper.getInstance().setPipVisibility(topActivity != null);
});
}
@@ -214,7 +229,8 @@ public class PipManager implements BasePipManager {
/**
* Initializes {@link PipManager}.
*/
- public void initialize(Context context, BroadcastDispatcher broadcastDispatcher) {
+ public void initialize(Context context, BroadcastDispatcher broadcastDispatcher,
+ DisplayWindowController displayWindowController) {
mContext = context;
mActivityManager = ActivityManager.getService();
mActivityTaskManager = ActivityTaskManager.getService();
@@ -235,6 +251,7 @@ public class PipManager implements BasePipManager {
mMenuController, mInputConsumerController, mPipBoundsHandler);
mAppOpsListener = new PipAppOpsListener(context, mActivityManager,
mTouchHandler.getMotionHelper());
+ displayWindowController.addRotationController(mRotationController);
// If SystemUI restart, and it already existed a pinned stack,
// register the pip input consumer to ensure touch can send to it.
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
index fa6047755619..6afa0bfcbdb6 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
@@ -46,7 +46,7 @@ import android.view.animation.Interpolator;
import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
import com.android.internal.os.SomeArgs;
-import com.android.internal.policy.PipSnapAlgorithm;
+import com.android.systemui.pip.PipSnapAlgorithm;
import com.android.systemui.shared.system.WindowManagerWrapper;
import com.android.systemui.statusbar.FlingAnimationUtils;
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index 2e90a3e28841..95e3444f4779 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -46,9 +46,9 @@ import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityWindowInfo;
import com.android.internal.os.logging.MetricsLoggerWrapper;
-import com.android.internal.policy.PipSnapAlgorithm;
import com.android.systemui.R;
import com.android.systemui.pip.PipBoundsHandler;
+import com.android.systemui.pip.PipSnapAlgorithm;
import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.statusbar.FlingAnimationUtils;
@@ -194,7 +194,8 @@ public class PipTouchHandler {
mMenuController.addListener(mMenuListener);
mDismissViewController = new PipDismissViewController(context);
mSnapAlgorithm = new PipSnapAlgorithm(mContext);
- mFlingAnimationUtils = new FlingAnimationUtils(context, 2.5f);
+ mFlingAnimationUtils = new FlingAnimationUtils(context.getResources().getDisplayMetrics(),
+ 2.5f);
mGestures = new PipTouchGesture[] {
mDefaultMovementGesture
};
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
index 195fca85a314..1d92375a7541 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
@@ -55,6 +55,7 @@ import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.PinnedStackListenerForwarder.PinnedStackListener;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.WindowManagerWrapper;
+import com.android.systemui.wm.DisplayWindowController;
import java.util.ArrayList;
import java.util.List;
@@ -228,7 +229,8 @@ public class PipManager implements BasePipManager {
/**
* Initializes {@link PipManager}.
*/
- public void initialize(Context context, BroadcastDispatcher broadcastDispatcher) {
+ public void initialize(Context context, BroadcastDispatcher broadcastDispatcher,
+ DisplayWindowController displayWindowController) {
if (mInitialized) {
return;
}
@@ -748,7 +750,7 @@ public class PipManager implements BasePipManager {
}
private void updatePipVisibility(final boolean visible) {
- Dependency.get(UiOffloadThread.class).submit(() -> {
+ Dependency.get(UiOffloadThread.class).execute(() -> {
WindowManagerWrapper.getInstance().setPipVisibility(visible);
});
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroupController.java b/packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroupController.java
index ac94858cff27..fb106425ec63 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroupController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroupController.java
@@ -32,8 +32,8 @@ import android.widget.TextView;
import androidx.annotation.VisibleForTesting;
import com.android.keyguard.CarrierTextController;
-import com.android.systemui.dagger.qualifiers.BgHandler;
-import com.android.systemui.dagger.qualifiers.MainLooper;
+import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.statusbar.policy.NetworkController;
@@ -111,7 +111,7 @@ public class QSCarrierGroupController {
}
private QSCarrierGroupController(QSCarrierGroup view, ActivityStarter activityStarter,
- @BgHandler Handler bgHandler, @MainLooper Looper mainLooper,
+ @Background Handler bgHandler, @Main Looper mainLooper,
NetworkController networkController,
CarrierTextController.Builder carrierTextControllerBuilder) {
mActivityStarter = activityStarter;
@@ -308,8 +308,8 @@ public class QSCarrierGroupController {
private final CarrierTextController.Builder mCarrierTextControllerBuilder;
@Inject
- public Builder(ActivityStarter activityStarter, @BgHandler Handler handler,
- @MainLooper Looper looper, NetworkController networkController,
+ public Builder(ActivityStarter activityStarter, @Background Handler handler,
+ @Main Looper looper, NetworkController networkController,
CarrierTextController.Builder carrierTextControllerBuilder) {
mActivityStarter = activityStarter;
mHandler = handler;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
index c01bc8fe19e6..86ed274e9b5c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
@@ -34,8 +34,8 @@ import com.android.systemui.DumpController;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dagger.qualifiers.BgLooper;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.plugins.qs.QSFactory;
import com.android.systemui.plugins.qs.QSTile;
@@ -96,8 +96,8 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D
public QSTileHost(Context context,
StatusBarIconController iconController,
QSFactoryImpl defaultFactory,
- @MainHandler Handler mainHandler,
- @BgLooper Looper bgLooper,
+ @Main Handler mainHandler,
+ @Background Looper bgLooper,
PluginManager pluginManager,
TunerService tunerService,
Provider<AutoTileManager> autoTiles,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
index 926141297add..bbff117c6f81 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
@@ -42,6 +42,7 @@ import com.android.systemui.broadcast.BroadcastDispatcher;
import java.util.Objects;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
/**
* Manages the lifecycle of a TileService.
@@ -84,7 +85,8 @@ public class TileLifecycleManager extends BroadcastReceiver implements
private int mBindTryCount;
private int mBindRetryDelay = DEFAULT_BIND_RETRY_DELAY;
private boolean mBound;
- boolean mReceiverRegistered;
+ private AtomicBoolean mPackageReceiverRegistered = new AtomicBoolean(false);
+ private AtomicBoolean mUserReceiverRegistered = new AtomicBoolean(false);
private boolean mUnbindImmediate;
private TileChangeListener mChangeListener;
// Return value from bindServiceAsUser, determines whether safe to call unbind.
@@ -274,7 +276,7 @@ public class TileLifecycleManager extends BroadcastReceiver implements
public void handleDestroy() {
if (DEBUG) Log.d(TAG, "handleDestroy");
- if (mReceiverRegistered) {
+ if (mPackageReceiverRegistered.get() || mUserReceiverRegistered.get()) {
stopPackageListening();
}
}
@@ -310,17 +312,31 @@ public class TileLifecycleManager extends BroadcastReceiver implements
IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
filter.addDataScheme("package");
- mContext.registerReceiverAsUser(this, mUser, filter, null, mHandler);
+ try {
+ mPackageReceiverRegistered.set(true);
+ mContext.registerReceiverAsUser(this, mUser, filter, null, mHandler);
+ } catch (Exception ex) {
+ mPackageReceiverRegistered.set(false);
+ Log.e(TAG, "Could not register package receiver", ex);
+ }
filter = new IntentFilter(Intent.ACTION_USER_UNLOCKED);
- mBroadcastDispatcher.registerReceiver(this, filter, mHandler, mUser);
- mReceiverRegistered = true;
+ try {
+ mUserReceiverRegistered.set(true);
+ mBroadcastDispatcher.registerReceiver(this, filter, mHandler, mUser);
+ } catch (Exception ex) {
+ mUserReceiverRegistered.set(false);
+ Log.e(TAG, "Could not register unlock receiver", ex);
+ }
}
private void stopPackageListening() {
if (DEBUG) Log.d(TAG, "stopPackageListening");
- mContext.unregisterReceiver(this);
- mBroadcastDispatcher.unregisterReceiver(this);
- mReceiverRegistered = false;
+ if (mUserReceiverRegistered.compareAndSet(true, false)) {
+ mBroadcastDispatcher.unregisterReceiver(this);
+ }
+ if (mPackageReceiverRegistered.compareAndSet(true, false)) {
+ mContext.unregisterReceiver(this);
+ }
}
public void setTileChangeListener(TileChangeListener changeListener) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
index 9a33c8c825cf..f06c849f5d3c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
@@ -38,7 +38,6 @@ import com.android.systemui.qs.tiles.DataSaverTile;
import com.android.systemui.qs.tiles.DndTile;
import com.android.systemui.qs.tiles.FlashlightTile;
import com.android.systemui.qs.tiles.HotspotTile;
-import com.android.systemui.qs.tiles.IntentTile;
import com.android.systemui.qs.tiles.LocationTile;
import com.android.systemui.qs.tiles.NfcTile;
import com.android.systemui.qs.tiles.NightDisplayTile;
@@ -182,8 +181,7 @@ public class QSFactoryImpl implements QSFactory {
return mUiModeNightTileProvider.get();
}
- // Intent tiles.
- if (tileSpec.startsWith(IntentTile.PREFIX)) return IntentTile.create(mHost, tileSpec);
+ // Custom tiles
if (tileSpec.startsWith(CustomTile.PREFIX)) return CustomTile.create(mHost, tileSpec);
// Debug tiles.
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
index 4afcf013507d..5e297e21686b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
@@ -26,11 +26,11 @@ import android.provider.Settings;
import android.provider.Settings.Global;
import android.service.quicksettings.Tile;
import android.sysprop.TelephonyProperties;
+import android.telephony.TelephonyManager;
import android.widget.Switch;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.internal.telephony.TelephonyIntents;
import com.android.systemui.R;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.plugins.ActivityStarter;
@@ -76,7 +76,7 @@ public class AirplaneModeTile extends QSTileImpl<BooleanState> {
MetricsLogger.action(mContext, getMetricsCategory(), !airplaneModeEnabled);
if (!airplaneModeEnabled && TelephonyProperties.in_ecm_mode().orElse(false)) {
mActivityStarter.postStartActivityDismissingKeyguard(
- new Intent(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS), 0);
+ new Intent(TelephonyManager.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS), 0);
return;
}
setEnabled(!airplaneModeEnabled);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
deleted file mode 100644
index a639a9525dd4..000000000000
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.qs.tiles;
-
-import android.app.PendingIntent;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.os.UserHandle;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.Dependency;
-import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.plugins.qs.QSTile.State;
-import com.android.systemui.qs.QSHost;
-import com.android.systemui.qs.tileimpl.QSTileImpl;
-
-import java.util.Arrays;
-import java.util.Objects;
-
-public class IntentTile extends QSTileImpl<State> {
- public static final String PREFIX = "intent(";
-
- private PendingIntent mOnClick;
- private String mOnClickUri;
- private PendingIntent mOnLongClick;
- private String mOnLongClickUri;
- private int mCurrentUserId;
- private String mIntentPackage;
-
- private Intent mLastIntent;
-
- private IntentTile(QSHost host, String action) {
- super(host);
- mContext.registerReceiver(mReceiver, new IntentFilter(action));
- }
-
- @Override
- protected void handleDestroy() {
- super.handleDestroy();
- mContext.unregisterReceiver(mReceiver);
- }
-
- public static IntentTile create(QSHost host, String spec) {
- if (spec == null || !spec.startsWith(PREFIX) || !spec.endsWith(")")) {
- throw new IllegalArgumentException("Bad intent tile spec: " + spec);
- }
- final String action = spec.substring(PREFIX.length(), spec.length() - 1);
- if (action.isEmpty()) {
- throw new IllegalArgumentException("Empty intent tile spec action");
- }
- return new IntentTile(host, action);
- }
-
- @Override
- public void handleSetListening(boolean listening) {
- }
-
- @Override
- public State newTileState() {
- return new State();
- }
-
- @Override
- protected void handleUserSwitch(int newUserId) {
- super.handleUserSwitch(newUserId);
- mCurrentUserId = newUserId;
- }
-
- @Override
- protected void handleClick() {
- sendIntent("click", mOnClick, mOnClickUri);
- }
-
- @Override
- public Intent getLongClickIntent() {
- return null;
- }
-
- @Override
- protected void handleLongClick() {
- sendIntent("long-click", mOnLongClick, mOnLongClickUri);
- }
-
- private void sendIntent(String type, PendingIntent pi, String uri) {
- try {
- if (pi != null) {
- if (pi.isActivity()) {
- Dependency.get(ActivityStarter.class).postStartActivityDismissingKeyguard(pi);
- } else {
- pi.send();
- }
- } else if (uri != null) {
- final Intent intent = Intent.parseUri(uri, Intent.URI_INTENT_SCHEME);
- mContext.sendBroadcastAsUser(intent, new UserHandle(mCurrentUserId));
- }
- } catch (Throwable t) {
- Log.w(TAG, "Error sending " + type + " intent", t);
- }
- }
-
- @Override
- public CharSequence getTileLabel() {
- return getState().label;
- }
-
- @Override
- protected void handleUpdateState(State state, Object arg) {
- Intent intent = (Intent) arg;
- if (intent == null) {
- if (mLastIntent == null) {
- return;
- }
- // No intent but need to refresh state, just use the last one.
- intent = mLastIntent;
- }
- // Save the last one in case we need it later.
- mLastIntent = intent;
- state.contentDescription = intent.getStringExtra("contentDescription");
- state.label = intent.getStringExtra("label");
- state.icon = null;
- final byte[] iconBitmap = intent.getByteArrayExtra("iconBitmap");
- if (iconBitmap != null) {
- try {
- state.icon = new BytesIcon(iconBitmap);
- } catch (Throwable t) {
- Log.w(TAG, "Error loading icon bitmap, length " + iconBitmap.length, t);
- }
- } else {
- final int iconId = intent.getIntExtra("iconId", 0);
- if (iconId != 0) {
- final String iconPackage = intent.getStringExtra("iconPackage");
- if (!TextUtils.isEmpty(iconPackage)) {
- state.icon = new PackageDrawableIcon(iconPackage, iconId);
- } else {
- state.icon = ResourceIcon.get(iconId);
- }
- }
- }
- mOnClick = intent.getParcelableExtra("onClick");
- mOnClickUri = intent.getStringExtra("onClickUri");
- mOnLongClick = intent.getParcelableExtra("onLongClick");
- mOnLongClickUri = intent.getStringExtra("onLongClickUri");
- mIntentPackage = intent.getStringExtra("package");
- mIntentPackage = mIntentPackage == null ? "" : mIntentPackage;
- }
-
- @Override
- public int getMetricsCategory() {
- return MetricsEvent.QS_INTENT;
- }
-
- private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- refreshState(intent);
- }
- };
-
- private static class BytesIcon extends Icon {
- private final byte[] mBytes;
-
- public BytesIcon(byte[] bytes) {
- mBytes = bytes;
- }
-
- @Override
- public Drawable getDrawable(Context context) {
- final Bitmap b = BitmapFactory.decodeByteArray(mBytes, 0, mBytes.length);
- return new BitmapDrawable(context.getResources(), b);
- }
-
- @Override
- public boolean equals(Object o) {
- return o instanceof BytesIcon && Arrays.equals(((BytesIcon) o).mBytes, mBytes);
- }
-
- @Override
- public String toString() {
- return String.format("BytesIcon[len=%s]", mBytes.length);
- }
- }
-
- private class PackageDrawableIcon extends Icon {
- private final String mPackage;
- private final int mResId;
-
- public PackageDrawableIcon(String pkg, int resId) {
- mPackage = pkg;
- mResId = resId;
- }
-
- @Override
- public boolean equals(Object o) {
- if (!(o instanceof PackageDrawableIcon)) return false;
- final PackageDrawableIcon other = (PackageDrawableIcon) o;
- return Objects.equals(other.mPackage, mPackage) && other.mResId == mResId;
- }
-
- @Override
- public Drawable getDrawable(Context context) {
- try {
- return context.createPackageContext(mPackage, 0).getDrawable(mResId);
- } catch (Throwable t) {
- Log.w(TAG, "Error loading package drawable pkg=" + mPackage + " id=" + mResId, t);
- return null;
- }
- }
-
- @Override
- public String toString() {
- return String.format("PackageDrawableIcon[pkg=%s,id=0x%08x]", mPackage, mResId);
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
index d3ccbeb0afb1..77c3ad971ef0 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
@@ -27,7 +27,6 @@ import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
-import android.graphics.Point;
import android.graphics.drawable.Icon;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
@@ -42,6 +41,7 @@ import android.util.DisplayMetrics;
import android.util.Log;
import android.util.Size;
import android.view.Surface;
+import android.view.WindowManager;
import android.widget.Toast;
import com.android.systemui.R;
@@ -76,7 +76,7 @@ public class RecordingService extends Service {
private static final String ACTION_DELETE = "com.android.systemui.screenrecord.DELETE";
private static final int TOTAL_NUM_TRACKS = 1;
- private static final int VIDEO_BIT_RATE = 6000000;
+ private static final int VIDEO_BIT_RATE = 10000000;
private static final int VIDEO_FRAME_RATE = 30;
private static final int AUDIO_BIT_RATE = 16;
private static final int AUDIO_SAMPLE_RATE = 44100;
@@ -238,7 +238,9 @@ public class RecordingService extends Service {
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
// Set up video
- DisplayMetrics metrics = getResources().getDisplayMetrics();
+ DisplayMetrics metrics = new DisplayMetrics();
+ WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
+ wm.getDefaultDisplay().getRealMetrics(metrics);
int screenWidth = metrics.widthPixels;
int screenHeight = metrics.heightPixels;
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 00220cef5d7c..02c4beb7ac1b 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -16,8 +16,6 @@
package com.android.systemui.screenshot;
-import static android.content.Context.NOTIFICATION_SERVICE;
-import static android.os.AsyncTask.THREAD_POOL_EXECUTOR;
import static android.provider.DeviceConfig.NAMESPACE_SYSTEMUI;
import static android.view.View.VISIBLE;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
@@ -31,14 +29,10 @@ import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.annotation.Nullable;
-import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.Notification;
-import android.app.NotificationManager;
import android.app.PendingIntent;
-import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
@@ -55,7 +49,6 @@ import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
-import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.DeviceConfig;
import android.util.DisplayMetrics;
@@ -74,20 +67,13 @@ import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.systemui.R;
-import com.android.systemui.SystemUI;
-import com.android.systemui.SystemUIFactory;
-import com.android.systemui.dagger.qualifiers.MainResources;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.statusbar.phone.StatusBar;
-import com.android.systemui.util.NotificationChannels;
-import java.util.Collections;
import java.util.List;
import java.util.Optional;
-import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@@ -108,29 +94,20 @@ public class GlobalScreenshot {
* POD used in the AsyncTask which saves an image in the background.
*/
static class SaveImageInBackgroundData {
- public Context context;
public Bitmap image;
public Uri imageUri;
public Consumer<Uri> finisher;
public GlobalScreenshot.ActionsReadyListener mActionsReadyListener;
- public int iconSize;
- public int previewWidth;
- public int previewheight;
public int errorMsgResId;
void clearImage() {
image = null;
imageUri = null;
- iconSize = 0;
- }
-
- void clearContext() {
- context = null;
}
}
abstract static class ActionsReadyListener {
- abstract void onActionsReady(PendingIntent shareAction, PendingIntent editAction);
+ abstract void onActionsReady(Uri imageUri, List<Notification.Action> actions);
}
// These strings are used for communicating the action invoked to
@@ -165,13 +142,12 @@ public class GlobalScreenshot {
private static final float SCREENSHOT_CORNER_MIN_SCALE_OFFSET = .1f;
private static final long SCREENSHOT_CORNER_TIMEOUT_MILLIS = 8000;
private static final int MESSAGE_CORNER_TIMEOUT = 2;
- private final int mPreviewWidth;
- private final int mPreviewHeight;
+
+ private final ScreenshotNotificationsController mNotificationsController;
private Context mContext;
private WindowManager mWindowManager;
private WindowManager.LayoutParams mWindowLayoutParams;
- private NotificationManager mNotificationManager;
private Display mDisplay;
private DisplayMetrics mDisplayMetrics;
@@ -182,13 +158,9 @@ public class GlobalScreenshot {
private ImageView mScreenshotView;
private ImageView mScreenshotFlash;
private LinearLayout mActionsView;
- private TextView mShareAction;
- private TextView mEditAction;
- private TextView mScrollAction;
private AnimatorSet mScreenshotAnimation;
- private int mNotificationIconSize;
private float mBgPadding;
private float mBgPaddingScale;
@@ -213,9 +185,11 @@ public class GlobalScreenshot {
* @param context everything needs a context :(
*/
@Inject
- public GlobalScreenshot(Context context, @MainResources Resources resources,
- LayoutInflater layoutInflater) {
+ public GlobalScreenshot(
+ Context context, @Main Resources resources, LayoutInflater layoutInflater,
+ ScreenshotNotificationsController screenshotNotificationsController) {
mContext = context;
+ mNotificationsController = screenshotNotificationsController;
// Inflate the screenshot layout
mScreenshotLayout = layoutInflater.inflate(R.layout.global_screenshot, null);
@@ -223,21 +197,6 @@ public class GlobalScreenshot {
mScreenshotView = mScreenshotLayout.findViewById(R.id.global_screenshot);
mActionsView = mScreenshotLayout.findViewById(R.id.global_screenshot_actions);
- mShareAction = (TextView) layoutInflater.inflate(
- R.layout.global_screenshot_action_chip, mActionsView, false);
- mEditAction = (TextView) layoutInflater.inflate(
- R.layout.global_screenshot_action_chip, mActionsView, false);
- mScrollAction = (TextView) layoutInflater.inflate(
- R.layout.global_screenshot_action_chip, mActionsView, false);
-
- mShareAction.setText(com.android.internal.R.string.share);
- mEditAction.setText(com.android.internal.R.string.screenshot_edit);
- mScrollAction.setText("Scroll"); // TODO (mkephart): Add to resources and translate
-
- mActionsView.addView(mShareAction);
- mActionsView.addView(mEditAction);
- mActionsView.addView(mScrollAction);
-
mScreenshotFlash = mScreenshotLayout.findViewById(R.id.global_screenshot_flash);
mScreenshotSelectorView = mScreenshotLayout.findViewById(R.id.global_screenshot_selector);
mScreenshotLayout.setFocusable(true);
@@ -260,32 +219,14 @@ public class GlobalScreenshot {
mWindowLayoutParams.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
mWindowLayoutParams.setFitWindowInsetsTypes(0 /* types */);
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
- mNotificationManager =
- (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
mDisplay = mWindowManager.getDefaultDisplay();
mDisplayMetrics = new DisplayMetrics();
mDisplay.getRealMetrics(mDisplayMetrics);
- // Get the various target sizes
- mNotificationIconSize =
- resources.getDimensionPixelSize(android.R.dimen.notification_large_icon_height);
-
// Scale has to account for both sides of the bg
mBgPadding = (float) resources.getDimensionPixelSize(R.dimen.global_screenshot_bg_padding);
mBgPaddingScale = mBgPadding / mDisplayMetrics.widthPixels;
- // determine the optimal preview size
- int panelWidth = 0;
- try {
- panelWidth = resources.getDimensionPixelSize(R.dimen.notification_panel_width);
- } catch (Resources.NotFoundException e) {
- }
- if (panelWidth <= 0) {
- // includes notification_panel_width==match_parent (-1)
- panelWidth = mDisplayMetrics.widthPixels;
- }
- mPreviewWidth = panelWidth;
- mPreviewHeight = resources.getDimensionPixelSize(R.dimen.notification_max_height);
// Setup the Camera shutter sound
mCameraSound = new MediaActionSound();
@@ -298,22 +239,20 @@ public class GlobalScreenshot {
private void saveScreenshotInWorkerThread(
Consumer<Uri> finisher, @Nullable ActionsReadyListener actionsReadyListener) {
SaveImageInBackgroundData data = new SaveImageInBackgroundData();
- data.context = mContext;
data.image = mScreenBitmap;
- data.iconSize = mNotificationIconSize;
data.finisher = finisher;
data.mActionsReadyListener = actionsReadyListener;
- data.previewWidth = mPreviewWidth;
- data.previewheight = mPreviewHeight;
if (mSaveInBgTask != null) {
mSaveInBgTask.cancel(false);
}
- mSaveInBgTask = new SaveImageInBackgroundTask(mContext, data, mNotificationManager)
- .execute();
- }
- private void saveScreenshotInWorkerThread(Consumer<Uri> finisher) {
- saveScreenshotInWorkerThread(finisher, null);
+ if (!DeviceConfig.getBoolean(
+ NAMESPACE_SYSTEMUI, SCREENSHOT_CORNER_FLOW, false)) {
+ mNotificationsController.reset();
+ mNotificationsController.setImage(mScreenBitmap);
+ mNotificationsController.showSavingScreenshotNotification();
+ }
+ mSaveInBgTask = new SaveImageInBackgroundTask(mContext, data).execute();
}
/**
@@ -328,7 +267,7 @@ public class GlobalScreenshot {
// Take the screenshot
mScreenBitmap = SurfaceControl.screenshot(crop, width, height, rot);
if (mScreenBitmap == null) {
- notifyScreenshotError(mContext, mNotificationManager,
+ mNotificationsController.notifyScreenshotError(
R.string.screenshot_failed_to_capture_text);
finisher.accept(null);
return;
@@ -373,12 +312,8 @@ public class GlobalScreenshot {
if (rect != null) {
if (rect.width() != 0 && rect.height() != 0) {
// Need mScreenshotLayout to handle it after the view disappears
- mScreenshotLayout.post(new Runnable() {
- public void run() {
- takeScreenshot(finisher, statusBarVisible, navBarVisible,
- rect);
- }
- });
+ mScreenshotLayout.post(() -> takeScreenshot(
+ finisher, statusBarVisible, navBarVisible, rect));
}
}
@@ -464,15 +399,30 @@ public class GlobalScreenshot {
public void onAnimationEnd(Animator animation) {
// Save the screenshot once we have a bit of time now
if (!useCornerFlow) {
- saveScreenshotInWorkerThread(finisher);
+ saveScreenshotInWorkerThread(finisher, new ActionsReadyListener() {
+ @Override
+ void onActionsReady(Uri uri, List<Notification.Action> actions) {
+ if (uri == null) {
+ mNotificationsController.notifyScreenshotError(
+ R.string.screenshot_failed_to_capture_text);
+ } else {
+ mNotificationsController
+ .showScreenshotActionsNotification(uri, actions);
+ }
+ }
+ });
clearScreenshot();
} else {
saveScreenshotInWorkerThread(finisher, new ActionsReadyListener() {
@Override
- void onActionsReady(PendingIntent shareAction, PendingIntent editAction) {
- mScreenshotHandler.post(() ->
- createScreenshotActionsShadeAnimation(shareAction, editAction)
- .start());
+ void onActionsReady(Uri uri, List<Notification.Action> actions) {
+ if (uri == null) {
+ mNotificationsController.notifyScreenshotError(
+ R.string.screenshot_failed_to_capture_text);
+ } else {
+ mScreenshotHandler.post(() ->
+ createScreenshotActionsShadeAnimation(actions).start());
+ }
}
});
mScreenshotHandler.sendMessageDelayed(
@@ -679,8 +629,33 @@ public class GlobalScreenshot {
return anim;
}
- private ValueAnimator createScreenshotActionsShadeAnimation(
- PendingIntent shareAction, PendingIntent editAction) {
+ private ValueAnimator createScreenshotActionsShadeAnimation(List<Notification.Action> actions) {
+ LayoutInflater inflater = LayoutInflater.from(mContext);
+ mActionsView.removeAllViews();
+
+ for (Notification.Action action : actions) {
+ TextView actionChip = (TextView) inflater.inflate(
+ R.layout.global_screenshot_action_chip, mActionsView, false);
+ actionChip.setText(action.title);
+ actionChip.setOnClickListener(v -> {
+ try {
+ action.actionIntent.send();
+ clearScreenshot();
+ } catch (PendingIntent.CanceledException e) {
+ Log.e(TAG,
+ String.format("Intent cancelled (title: %s)", action.title), e);
+ }
+ });
+ mActionsView.addView(actionChip);
+ }
+ TextView scrollChip = (TextView) inflater.inflate(
+ R.layout.global_screenshot_action_chip, mActionsView, false);
+ Toast scrollNotImplemented = Toast.makeText(
+ mContext, "Not implemented", Toast.LENGTH_SHORT);
+ scrollChip.setText("Scroll"); // TODO (mkephart): add resource and translate
+ scrollChip.setOnClickListener(v -> scrollNotImplemented.show());
+ mActionsView.addView(scrollChip);
+
ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
mActionsView.setY(mDisplayMetrics.heightPixels);
mActionsView.setVisibility(VISIBLE);
@@ -698,158 +673,11 @@ public class GlobalScreenshot {
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
mScreenshotView.requestFocus();
- mShareAction.setOnClickListener(v -> {
- try {
- shareAction.send();
- clearScreenshot();
- } catch (PendingIntent.CanceledException e) {
- Log.e(TAG, "Share intent cancelled", e);
- }
- });
- mEditAction.setOnClickListener(v -> {
- try {
- editAction.send();
- clearScreenshot();
- } catch (PendingIntent.CanceledException e) {
- Log.e(TAG, "Edit intent cancelled", e);
- }
- });
- Toast scrollNotImplemented = Toast.makeText(
- mContext, "Not implemented", Toast.LENGTH_SHORT);
- mScrollAction.setOnClickListener(v -> scrollNotImplemented.show());
}
});
return animator;
}
- static void notifyScreenshotError(Context context, NotificationManager nManager, int msgResId) {
- Resources r = context.getResources();
- String errorMsg = r.getString(msgResId);
-
- // Repurpose the existing notification to notify the user of the error
- Notification.Builder b = new Notification.Builder(context, NotificationChannels.ALERTS)
- .setTicker(r.getString(R.string.screenshot_failed_title))
- .setContentTitle(r.getString(R.string.screenshot_failed_title))
- .setContentText(errorMsg)
- .setSmallIcon(R.drawable.stat_notify_image_error)
- .setWhen(System.currentTimeMillis())
- .setVisibility(Notification.VISIBILITY_PUBLIC) // ok to show outside lockscreen
- .setCategory(Notification.CATEGORY_ERROR)
- .setAutoCancel(true)
- .setColor(context.getColor(
- com.android.internal.R.color.system_notification_accent_color));
- final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
- Context.DEVICE_POLICY_SERVICE);
- final Intent intent = dpm.createAdminSupportIntent(
- DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE);
- if (intent != null) {
- final PendingIntent pendingIntent = PendingIntent.getActivityAsUser(
- context, 0, intent, 0, null, UserHandle.CURRENT);
- b.setContentIntent(pendingIntent);
- }
-
- SystemUI.overrideNotificationAppName(context, b, true);
-
- Notification n = new Notification.BigTextStyle(b)
- .bigText(errorMsg)
- .build();
- nManager.notify(SystemMessage.NOTE_GLOBAL_SCREENSHOT, n);
- }
-
- @VisibleForTesting
- static CompletableFuture<List<Notification.Action>> getSmartActionsFuture(String screenshotId,
- Bitmap image, ScreenshotNotificationSmartActionsProvider smartActionsProvider,
- boolean smartActionsEnabled, boolean isManagedProfile) {
- if (!smartActionsEnabled) {
- Slog.i(TAG, "Screenshot Intelligence not enabled, returning empty list.");
- return CompletableFuture.completedFuture(Collections.emptyList());
- }
- if (image.getConfig() != Bitmap.Config.HARDWARE) {
- Slog.w(TAG, String.format(
- "Bitmap expected: Hardware, Bitmap found: %s. Returning empty list.",
- image.getConfig()));
- return CompletableFuture.completedFuture(Collections.emptyList());
- }
-
- Slog.d(TAG, "Screenshot from a managed profile: " + isManagedProfile);
- CompletableFuture<List<Notification.Action>> smartActionsFuture;
- long startTimeMs = SystemClock.uptimeMillis();
- try {
- ActivityManager.RunningTaskInfo runningTask =
- ActivityManagerWrapper.getInstance().getRunningTask();
- ComponentName componentName =
- (runningTask != null && runningTask.topActivity != null)
- ? runningTask.topActivity
- : new ComponentName("", "");
- smartActionsFuture = smartActionsProvider.getActions(screenshotId, image,
- componentName,
- isManagedProfile);
- } catch (Throwable e) {
- long waitTimeMs = SystemClock.uptimeMillis() - startTimeMs;
- smartActionsFuture = CompletableFuture.completedFuture(Collections.emptyList());
- Slog.e(TAG, "Failed to get future for screenshot notification smart actions.", e);
- notifyScreenshotOp(screenshotId, smartActionsProvider,
- ScreenshotNotificationSmartActionsProvider.ScreenshotOp.REQUEST_SMART_ACTIONS,
- ScreenshotNotificationSmartActionsProvider.ScreenshotOpStatus.ERROR,
- waitTimeMs);
- }
- return smartActionsFuture;
- }
-
- @VisibleForTesting
- static List<Notification.Action> getSmartActions(String screenshotId,
- CompletableFuture<List<Notification.Action>> smartActionsFuture, int timeoutMs,
- ScreenshotNotificationSmartActionsProvider smartActionsProvider) {
- long startTimeMs = SystemClock.uptimeMillis();
- try {
- List<Notification.Action> actions = smartActionsFuture.get(timeoutMs,
- TimeUnit.MILLISECONDS);
- long waitTimeMs = SystemClock.uptimeMillis() - startTimeMs;
- Slog.d(TAG, String.format("Got %d smart actions. Wait time: %d ms",
- actions.size(), waitTimeMs));
- notifyScreenshotOp(screenshotId, smartActionsProvider,
- ScreenshotNotificationSmartActionsProvider.ScreenshotOp.WAIT_FOR_SMART_ACTIONS,
- ScreenshotNotificationSmartActionsProvider.ScreenshotOpStatus.SUCCESS,
- waitTimeMs);
- return actions;
- } catch (Throwable e) {
- long waitTimeMs = SystemClock.uptimeMillis() - startTimeMs;
- Slog.e(TAG, String.format("Error getting smart actions. Wait time: %d ms", waitTimeMs),
- e);
- ScreenshotNotificationSmartActionsProvider.ScreenshotOpStatus status =
- (e instanceof TimeoutException)
- ? ScreenshotNotificationSmartActionsProvider.ScreenshotOpStatus.TIMEOUT
- : ScreenshotNotificationSmartActionsProvider.ScreenshotOpStatus.ERROR;
- notifyScreenshotOp(screenshotId, smartActionsProvider,
- ScreenshotNotificationSmartActionsProvider.ScreenshotOp.WAIT_FOR_SMART_ACTIONS,
- status, waitTimeMs);
- return Collections.emptyList();
- }
- }
-
- static void notifyScreenshotOp(String screenshotId,
- ScreenshotNotificationSmartActionsProvider smartActionsProvider,
- ScreenshotNotificationSmartActionsProvider.ScreenshotOp op,
- ScreenshotNotificationSmartActionsProvider.ScreenshotOpStatus status, long durationMs) {
- try {
- smartActionsProvider.notifyOp(screenshotId, op, status, durationMs);
- } catch (Throwable e) {
- Slog.e(TAG, "Error in notifyScreenshotOp: ", e);
- }
- }
-
- static void notifyScreenshotAction(Context context, String screenshotId, String action,
- boolean isSmartAction) {
- try {
- ScreenshotNotificationSmartActionsProvider provider =
- SystemUIFactory.getInstance().createScreenshotNotificationSmartActionsProvider(
- context, THREAD_POOL_EXECUTOR, new Handler());
- provider.notifyAction(screenshotId, action, isSmartAction);
- } catch (Throwable e) {
- Slog.e(TAG, "Error in notifyScreenshotAction: ", e);
- }
- }
-
/**
* Receiver to proxy the share or edit intent, used to clean up the notification and send
* appropriate signals to the system (ie. to dismiss the keyguard if necessary).
@@ -878,7 +706,7 @@ public class GlobalScreenshot {
Intent actionIntent = intent.getParcelableExtra(EXTRA_ACTION_INTENT);
if (intent.getBooleanExtra(EXTRA_CANCEL_NOTIFICATION, false)) {
- cancelScreenshotNotification(context);
+ ScreenshotNotificationsController.cancelScreenshotNotification(context);
}
ActivityOptions opts = ActivityOptions.makeBasic();
opts.setDisallowEnterPictureInPictureWhileLaunching(
@@ -897,8 +725,8 @@ public class GlobalScreenshot {
if (intent.getBooleanExtra(EXTRA_SMART_ACTIONS_ENABLED, false)) {
String actionType = Intent.ACTION_EDIT.equals(intent.getAction()) ? ACTION_TYPE_EDIT
: ACTION_TYPE_SHARE;
- notifyScreenshotAction(context, intent.getStringExtra(EXTRA_ID),
- actionType, false);
+ ScreenshotSmartActions.notifyScreenshotAction(
+ context, intent.getStringExtra(EXTRA_ID), actionType, false);
}
}
}
@@ -910,7 +738,7 @@ public class GlobalScreenshot {
@Override
public void onReceive(Context context, Intent intent) {
// Clear the notification only after the user has chosen a share action
- cancelScreenshotNotification(context);
+ ScreenshotNotificationsController.cancelScreenshotNotification(context);
}
}
@@ -925,15 +753,14 @@ public class GlobalScreenshot {
}
// Clear the notification when the image is deleted
- cancelScreenshotNotification(context);
+ ScreenshotNotificationsController.cancelScreenshotNotification(context);
// And delete the image from the media store
final Uri uri = Uri.parse(intent.getStringExtra(SCREENSHOT_URI_ID));
new DeleteImageInBackgroundTask(context).execute(uri);
if (intent.getBooleanExtra(EXTRA_SMART_ACTIONS_ENABLED, false)) {
- notifyScreenshotAction(context, intent.getStringExtra(EXTRA_ID),
- ACTION_TYPE_DELETE,
- false);
+ ScreenshotSmartActions.notifyScreenshotAction(
+ context, intent.getStringExtra(EXTRA_ID), ACTION_TYPE_DELETE, false);
}
}
}
@@ -952,15 +779,8 @@ public class GlobalScreenshot {
context.startActivityAsUser(actionIntent, opts.toBundle(),
UserHandle.CURRENT);
- notifyScreenshotAction(context, intent.getStringExtra(EXTRA_ID),
- actionType,
- true);
+ ScreenshotSmartActions.notifyScreenshotAction(
+ context, intent.getStringExtra(EXTRA_ID), actionType, true);
}
}
-
- private static void cancelScreenshotNotification(Context context) {
- final NotificationManager nm =
- (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
- nm.cancel(SystemMessage.NOTE_GLOBAL_SCREENSHOT);
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
index 2f401e5271d8..6bad15caf9da 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
@@ -18,7 +18,6 @@ package com.android.systemui.screenshot;
import android.app.ActivityTaskManager;
import android.app.Notification;
-import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ClipData;
import android.content.ClipDescription;
@@ -30,12 +29,7 @@ import android.content.Intent;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.ColorMatrix;
-import android.graphics.ColorMatrixColorFilter;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.Picture;
+import android.graphics.drawable.Icon;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.AsyncTask;
@@ -57,13 +51,8 @@ import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
-import com.android.internal.messages.nano.SystemMessageProto;
import com.android.systemui.R;
-import com.android.systemui.SystemUI;
import com.android.systemui.SystemUIFactory;
-import com.android.systemui.util.NotificationChannels;
-
-import libcore.io.IoUtils;
import java.io.File;
import java.io.IOException;
@@ -76,6 +65,7 @@ import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Objects;
@@ -93,22 +83,17 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
private static final String SCREENSHOT_ID_TEMPLATE = "Screenshot_%s";
private static final String SCREENSHOT_SHARE_SUBJECT_TEMPLATE = "Screenshot (%s)";
+ private final Context mContext;
private final GlobalScreenshot.SaveImageInBackgroundData mParams;
- private final NotificationManager mNotificationManager;
- private final Notification.Builder mNotificationBuilder, mPublicNotificationBuilder;
private final String mImageFileName;
private final long mImageTime;
- private final Notification.BigPictureStyle mNotificationStyle;
- private final int mImageWidth;
- private final int mImageHeight;
private final ScreenshotNotificationSmartActionsProvider mSmartActionsProvider;
private final String mScreenshotId;
private final boolean mSmartActionsEnabled;
private final Random mRandom = new Random();
- SaveImageInBackgroundTask(Context context, GlobalScreenshot.SaveImageInBackgroundData data,
- NotificationManager nManager) {
- Resources r = context.getResources();
+ SaveImageInBackgroundTask(Context context, GlobalScreenshot.SaveImageInBackgroundData data) {
+ mContext = context;
// Prepare all the output metadata
mParams = data;
@@ -129,143 +114,6 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
// If smart actions is not enabled use empty implementation.
mSmartActionsProvider = new ScreenshotNotificationSmartActionsProvider();
}
-
- // Create the large notification icon
- mImageWidth = data.image.getWidth();
- mImageHeight = data.image.getHeight();
- int iconSize = data.iconSize;
- int previewWidth = data.previewWidth;
- int previewHeight = data.previewheight;
-
- Paint paint = new Paint();
- ColorMatrix desat = new ColorMatrix();
- desat.setSaturation(0.25f);
- paint.setColorFilter(new ColorMatrixColorFilter(desat));
- Matrix matrix = new Matrix();
- int overlayColor = 0x40FFFFFF;
-
- matrix.setTranslate((previewWidth - mImageWidth) / 2,
- (previewHeight - mImageHeight) / 2);
- Bitmap picture = generateAdjustedHwBitmap(data.image, previewWidth, previewHeight,
- matrix, paint, overlayColor);
-
- // Note, we can't use the preview for the small icon, since it is non-square
- float scale = (float) iconSize / Math.min(mImageWidth, mImageHeight);
- matrix.setScale(scale, scale);
- matrix.postTranslate((iconSize - (scale * mImageWidth)) / 2,
- (iconSize - (scale * mImageHeight)) / 2);
- Bitmap icon = generateAdjustedHwBitmap(data.image, iconSize, iconSize, matrix, paint,
- overlayColor);
-
- mNotificationManager = nManager;
- final long now = System.currentTimeMillis();
-
- // Setup the notification
- mNotificationStyle = new Notification.BigPictureStyle()
- .bigPicture(picture.createAshmemBitmap());
-
- // The public notification will show similar info but with the actual screenshot omitted
- mPublicNotificationBuilder =
- new Notification.Builder(context, NotificationChannels.SCREENSHOTS_HEADSUP)
- .setContentTitle(r.getString(R.string.screenshot_saving_title))
- .setSmallIcon(R.drawable.stat_notify_image)
- .setCategory(Notification.CATEGORY_PROGRESS)
- .setWhen(now)
- .setShowWhen(true)
- .setColor(r.getColor(
- com.android.internal.R.color.system_notification_accent_color));
- SystemUI.overrideNotificationAppName(context, mPublicNotificationBuilder, true);
-
- mNotificationBuilder = new Notification.Builder(context,
- NotificationChannels.SCREENSHOTS_HEADSUP)
- .setContentTitle(r.getString(R.string.screenshot_saving_title))
- .setSmallIcon(R.drawable.stat_notify_image)
- .setWhen(now)
- .setShowWhen(true)
- .setColor(r.getColor(
- com.android.internal.R.color.system_notification_accent_color))
- .setStyle(mNotificationStyle)
- .setPublicVersion(mPublicNotificationBuilder.build());
- mNotificationBuilder.setFlag(Notification.FLAG_NO_CLEAR, true);
- SystemUI.overrideNotificationAppName(context, mNotificationBuilder, true);
-
- mNotificationManager.notify(SystemMessageProto.SystemMessage.NOTE_GLOBAL_SCREENSHOT,
- mNotificationBuilder.build());
-
- /**
- * NOTE: The following code prepares the notification builder for updating the
- * notification after the screenshot has been written to disk.
- */
-
- // On the tablet, the large icon makes the notification appear as if it is clickable
- // (and on small devices, the large icon is not shown) so defer showing the large icon
- // until we compose the final post-save notification below.
- mNotificationBuilder.setLargeIcon(icon.createAshmemBitmap());
- // But we still don't set it for the expanded view, allowing the smallIcon to show here.
- mNotificationStyle.bigLargeIcon((Bitmap) null);
- }
-
- private int getUserHandleOfForegroundApplication(Context context) {
- // This logic matches
- // com.android.systemui.statusbar.phone.PhoneStatusBarPolicy#updateManagedProfile
- try {
- return ActivityTaskManager.getService().getLastResumedActivityUserId();
- } catch (RemoteException e) {
- Slog.w(TAG, "getUserHandleOfForegroundApplication: ", e);
- return context.getUserId();
- }
- }
-
- private boolean isManagedProfile(Context context) {
- UserManager manager = UserManager.get(context);
- UserInfo info = manager.getUserInfo(getUserHandleOfForegroundApplication(context));
- return info.isManagedProfile();
- }
-
- private List<Notification.Action> buildSmartActions(
- List<Notification.Action> actions, Context context) {
- List<Notification.Action> broadcastActions = new ArrayList<>();
- for (Notification.Action action : actions) {
- // Proxy smart actions through {@link GlobalScreenshot.SmartActionsReceiver}
- // for logging smart actions.
- Bundle extras = action.getExtras();
- String actionType = extras.getString(
- ScreenshotNotificationSmartActionsProvider.ACTION_TYPE,
- ScreenshotNotificationSmartActionsProvider.DEFAULT_ACTION_TYPE);
- Intent intent = new Intent(context,
- GlobalScreenshot.SmartActionsReceiver.class).putExtra(
- GlobalScreenshot.EXTRA_ACTION_INTENT, action.actionIntent);
- addIntentExtras(mScreenshotId, intent, actionType, mSmartActionsEnabled);
- PendingIntent broadcastIntent = PendingIntent.getBroadcast(context,
- mRandom.nextInt(),
- intent,
- PendingIntent.FLAG_CANCEL_CURRENT);
- broadcastActions.add(new Notification.Action.Builder(action.getIcon(), action.title,
- broadcastIntent).setContextual(true).addExtras(extras).build());
- }
- return broadcastActions;
- }
-
- private static void addIntentExtras(String screenshotId, Intent intent, String actionType,
- boolean smartActionsEnabled) {
- intent
- .putExtra(GlobalScreenshot.EXTRA_ACTION_TYPE, actionType)
- .putExtra(GlobalScreenshot.EXTRA_ID, screenshotId)
- .putExtra(GlobalScreenshot.EXTRA_SMART_ACTIONS_ENABLED, smartActionsEnabled);
- }
-
- /**
- * Generates a new hardware bitmap with specified values, copying the content from the
- * passed in bitmap.
- */
- private Bitmap generateAdjustedHwBitmap(Bitmap bitmap, int width, int height, Matrix matrix,
- Paint paint, int color) {
- Picture picture = new Picture();
- Canvas canvas = picture.beginRecording(width, height);
- canvas.drawColor(color);
- canvas.drawBitmap(bitmap, matrix, paint);
- picture.endRecording();
- return Bitmap.createBitmap(picture);
}
@Override
@@ -278,15 +126,15 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
// so bump it back up so that we save a little quicker.
Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND);
- Context context = mParams.context;
- ContentResolver resolver = context.getContentResolver();
+ ContentResolver resolver = mContext.getContentResolver();
Bitmap image = mParams.image;
- Resources r = context.getResources();
+ Resources r = mContext.getResources();
try {
CompletableFuture<List<Notification.Action>> smartActionsFuture =
- GlobalScreenshot.getSmartActionsFuture(mScreenshotId, image,
- mSmartActionsProvider, mSmartActionsEnabled, isManagedProfile(context));
+ ScreenshotSmartActions.getSmartActionsFuture(
+ mScreenshotId, image, mSmartActionsProvider,
+ mSmartActionsEnabled, isManagedProfile(mContext));
// Save the screenshot to the MediaStore
final ContentValues values = new ContentValues();
@@ -347,8 +195,9 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
throw e;
}
- populateNotificationActions(context, r, uri, smartActionsFuture, mNotificationBuilder);
-
+ List<Notification.Action> actions =
+ populateNotificationActions(mContext, r, uri, smartActionsFuture);
+ mParams.mActionsReadyListener.onActionsReady(uri, actions);
mParams.imageUri = uri;
mParams.image = null;
mParams.errorMsgResId = 0;
@@ -358,6 +207,7 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
Slog.e(TAG, "unable to save screenshot", e);
mParams.clearImage();
mParams.errorMsgResId = R.string.screenshot_failed_to_save_text;
+ mParams.mActionsReadyListener.onActionsReady(null, null);
}
// Recycle the bitmap data
@@ -368,10 +218,24 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
return null;
}
+ @Override
+ protected void onPostExecute(Void params) {
+ mParams.finisher.accept(mParams.imageUri);
+ }
+
+ @Override
+ protected void onCancelled(Void params) {
+ // If we are cancelled while the task is running in the background, we may get null
+ // params. The finisher is expected to always be called back, so just use the baked-in
+ // params from the ctor in any case.
+ mParams.mActionsReadyListener.onActionsReady(null, null);
+ mParams.finisher.accept(null);
+ mParams.clearImage();
+ }
+
@VisibleForTesting
- void populateNotificationActions(Context context, Resources r, Uri uri,
- CompletableFuture<List<Notification.Action>> smartActionsFuture,
- Notification.Builder notificationBuilder) {
+ List<Notification.Action> populateNotificationActions(Context context, Resources r, Uri uri,
+ CompletableFuture<List<Notification.Action>> smartActionsFuture) {
// Note: Both the share and edit actions are proxied through ActionProxyReceiver in
// order to do some common work like dismissing the keyguard and sending
// closeSystemWindows
@@ -399,10 +263,10 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
PendingIntent chooserAction = PendingIntent.getBroadcast(context, requestCode,
new Intent(context, GlobalScreenshot.TargetChosenReceiver.class),
PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
- Intent sharingChooserIntent = Intent.createChooser(sharingIntent, null,
- chooserAction.getIntentSender())
- .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK)
- .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ Intent sharingChooserIntent =
+ Intent.createChooser(sharingIntent, null, chooserAction.getIntentSender())
+ .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK)
+ .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
// Create a share action for the notification
PendingIntent shareAction = PendingIntent.getBroadcastAsUser(context, requestCode,
@@ -414,10 +278,10 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
mSmartActionsEnabled)
.setAction(Intent.ACTION_SEND),
PendingIntent.FLAG_CANCEL_CURRENT, UserHandle.SYSTEM);
+
Notification.Action.Builder shareActionBuilder = new Notification.Action.Builder(
- R.drawable.ic_screenshot_share,
+ Icon.createWithResource(r, R.drawable.ic_screenshot_share),
r.getString(com.android.internal.R.string.share), shareAction);
- notificationBuilder.addAction(shareActionBuilder.build());
// Create an edit intent, if a specific package is provided as the editor, then
// launch that directly
@@ -443,12 +307,8 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
.setAction(Intent.ACTION_EDIT),
PendingIntent.FLAG_CANCEL_CURRENT, UserHandle.SYSTEM);
Notification.Action.Builder editActionBuilder = new Notification.Action.Builder(
- R.drawable.ic_screenshot_edit,
+ Icon.createWithResource(r, R.drawable.ic_screenshot_edit),
r.getString(com.android.internal.R.string.screenshot_edit), editAction);
- notificationBuilder.addAction(editActionBuilder.build());
- if (mParams.mActionsReadyListener != null) {
- mParams.mActionsReadyListener.onActionsReady(shareAction, editAction);
- }
// Create a delete action for the notification
PendingIntent deleteAction = PendingIntent.getBroadcast(context, requestCode,
@@ -459,88 +319,73 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
mSmartActionsEnabled),
PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
Notification.Action.Builder deleteActionBuilder = new Notification.Action.Builder(
- R.drawable.ic_screenshot_delete,
+ Icon.createWithResource(r, R.drawable.ic_screenshot_delete),
r.getString(com.android.internal.R.string.delete), deleteAction);
- notificationBuilder.addAction(deleteActionBuilder.build());
+ ArrayList<Notification.Action> actions = new ArrayList<>(
+ Arrays.asList(shareActionBuilder.build(), editActionBuilder.build(),
+ deleteActionBuilder.build()));
if (mSmartActionsEnabled) {
- int timeoutMs = DeviceConfig.getInt(DeviceConfig.NAMESPACE_SYSTEMUI,
- SystemUiDeviceConfigFlags
- .SCREENSHOT_NOTIFICATION_SMART_ACTIONS_TIMEOUT_MS,
+ int timeoutMs = DeviceConfig.getInt(
+ DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags.SCREENSHOT_NOTIFICATION_SMART_ACTIONS_TIMEOUT_MS,
1000);
- List<Notification.Action> smartActions = GlobalScreenshot.getSmartActions(mScreenshotId,
- smartActionsFuture, timeoutMs, mSmartActionsProvider);
- smartActions = buildSmartActions(smartActions, context);
- for (Notification.Action action : smartActions) {
- notificationBuilder.addAction(action);
- }
+ actions.addAll(buildSmartActions(
+ ScreenshotSmartActions.getSmartActions(
+ mScreenshotId, smartActionsFuture, timeoutMs, mSmartActionsProvider),
+ context));
}
+ return actions;
}
- @Override
- protected void onPostExecute(Void params) {
- if (mParams.errorMsgResId != 0) {
- // Show a message that we've failed to save the image to disk
- GlobalScreenshot.notifyScreenshotError(mParams.context, mNotificationManager,
- mParams.errorMsgResId);
- } else {
- if (mParams.mActionsReadyListener != null) {
- // Cancel the "saving screenshot" notification
- mNotificationManager.cancel(
- SystemMessageProto.SystemMessage.NOTE_GLOBAL_SCREENSHOT);
- } else {
- // Show the final notification to indicate screenshot saved
- Context context = mParams.context;
- Resources r = context.getResources();
-
- // Create the intent to show the screenshot in gallery
- Intent launchIntent = new Intent(Intent.ACTION_VIEW);
- launchIntent.setDataAndType(mParams.imageUri, "image/png");
- launchIntent.setFlags(
- Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_GRANT_READ_URI_PERMISSION);
-
- final long now = System.currentTimeMillis();
-
- // Update the text and the icon for the existing notification
- mPublicNotificationBuilder
- .setContentTitle(r.getString(R.string.screenshot_saved_title))
- .setContentText(r.getString(R.string.screenshot_saved_text))
- .setContentIntent(
- PendingIntent.getActivity(mParams.context, 0, launchIntent, 0))
- .setWhen(now)
- .setAutoCancel(true)
- .setColor(context.getColor(
- com.android.internal.R.color.system_notification_accent_color));
- mNotificationBuilder
- .setContentTitle(r.getString(R.string.screenshot_saved_title))
- .setContentText(r.getString(R.string.screenshot_saved_text))
- .setContentIntent(PendingIntent.getActivity(mParams.context, 0,
- launchIntent, 0))
- .setWhen(now)
- .setAutoCancel(true)
- .setColor(context.getColor(
- com.android.internal.R.color.system_notification_accent_color))
- .setPublicVersion(mPublicNotificationBuilder.build())
- .setFlag(Notification.FLAG_NO_CLEAR, false);
-
- mNotificationManager.notify(SystemMessageProto.SystemMessage.NOTE_GLOBAL_SCREENSHOT,
- mNotificationBuilder.build());
- }
+ private int getUserHandleOfForegroundApplication(Context context) {
+ // This logic matches
+ // com.android.systemui.statusbar.phone.PhoneStatusBarPolicy#updateManagedProfile
+ try {
+ return ActivityTaskManager.getService().getLastResumedActivityUserId();
+ } catch (RemoteException e) {
+ Slog.w(TAG, "getUserHandleOfForegroundApplication: ", e);
+ return context.getUserId();
}
- mParams.finisher.accept(mParams.imageUri);
- mParams.clearContext();
}
- @Override
- protected void onCancelled(Void params) {
- // If we are cancelled while the task is running in the background, we may get null
- // params. The finisher is expected to always be called back, so just use the baked-in
- // params from the ctor in any case.
- mParams.finisher.accept(null);
- mParams.clearImage();
- mParams.clearContext();
+ private boolean isManagedProfile(Context context) {
+ UserManager manager = UserManager.get(context);
+ UserInfo info = manager.getUserInfo(getUserHandleOfForegroundApplication(context));
+ return info.isManagedProfile();
+ }
- // Cancel the posted notification
- mNotificationManager.cancel(SystemMessageProto.SystemMessage.NOTE_GLOBAL_SCREENSHOT);
+ private List<Notification.Action> buildSmartActions(
+ List<Notification.Action> actions, Context context) {
+ List<Notification.Action> broadcastActions = new ArrayList<>();
+ for (Notification.Action action : actions) {
+ // Proxy smart actions through {@link GlobalScreenshot.SmartActionsReceiver}
+ // for logging smart actions.
+ Bundle extras = action.getExtras();
+ String actionType = extras.getString(
+ ScreenshotNotificationSmartActionsProvider.ACTION_TYPE,
+ ScreenshotNotificationSmartActionsProvider.DEFAULT_ACTION_TYPE);
+ Intent intent = new Intent(context,
+ GlobalScreenshot.SmartActionsReceiver.class).putExtra(
+ GlobalScreenshot.EXTRA_ACTION_INTENT, action.actionIntent);
+ addIntentExtras(mScreenshotId, intent, actionType, mSmartActionsEnabled);
+ PendingIntent broadcastIntent = PendingIntent.getBroadcast(context,
+ mRandom.nextInt(),
+ intent,
+ PendingIntent.FLAG_CANCEL_CURRENT);
+ broadcastActions.add(new Notification.Action.Builder(action.getIcon(), action.title,
+ broadcastIntent).setContextual(true).addExtras(extras).build());
+ }
+ return broadcastActions;
+ }
+
+ private static void addIntentExtras(String screenshotId, Intent intent, String actionType,
+ boolean smartActionsEnabled) {
+ intent
+ .putExtra(GlobalScreenshot.EXTRA_ACTION_TYPE, actionType)
+ .putExtra(GlobalScreenshot.EXTRA_ID, screenshotId)
+ .putExtra(GlobalScreenshot.EXTRA_SMART_ACTIONS_ENABLED, smartActionsEnabled);
}
+
+
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationsController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationsController.java
new file mode 100644
index 000000000000..42fca9413afd
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationsController.java
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot;
+
+import static android.content.Context.NOTIFICATION_SERVICE;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.ColorMatrix;
+import android.graphics.ColorMatrixColorFilter;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Picture;
+import android.net.Uri;
+import android.os.UserHandle;
+import android.util.DisplayMetrics;
+import android.view.WindowManager;
+
+import com.android.internal.messages.nano.SystemMessageProto;
+import com.android.systemui.R;
+import com.android.systemui.SystemUI;
+import com.android.systemui.util.NotificationChannels;
+
+import java.util.List;
+
+import javax.inject.Inject;
+
+/**
+ * Convenience class to handle showing and hiding notifications while taking a screenshot.
+ */
+public class ScreenshotNotificationsController {
+ private static final String TAG = "ScreenshotNotificationManager";
+
+ private final Context mContext;
+ private final Resources mResources;
+ private final NotificationManager mNotificationManager;
+ private final Notification.BigPictureStyle mNotificationStyle;
+
+ private int mIconSize;
+ private int mPreviewWidth, mPreviewHeight;
+ private Notification.Builder mNotificationBuilder, mPublicNotificationBuilder;
+
+ @Inject
+ ScreenshotNotificationsController(Context context, WindowManager windowManager) {
+ mContext = context;
+ mResources = context.getResources();
+
+ mNotificationManager =
+ (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
+
+ mIconSize = mResources.getDimensionPixelSize(
+ android.R.dimen.notification_large_icon_height);
+
+ DisplayMetrics displayMetrics = new DisplayMetrics();
+ windowManager.getDefaultDisplay().getRealMetrics(displayMetrics);
+
+
+ // determine the optimal preview size
+ int panelWidth = 0;
+ try {
+ panelWidth = mResources.getDimensionPixelSize(R.dimen.notification_panel_width);
+ } catch (Resources.NotFoundException e) {
+ }
+ if (panelWidth <= 0) {
+ // includes notification_panel_width==match_parent (-1)
+ panelWidth = displayMetrics.widthPixels;
+ }
+ mPreviewWidth = panelWidth;
+ mPreviewHeight = mResources.getDimensionPixelSize(R.dimen.notification_max_height);
+
+ // Setup the notification
+ mNotificationStyle = new Notification.BigPictureStyle();
+ }
+
+ /**
+ * Resets the notification builders.
+ */
+ public void reset() {
+ // The public notification will show similar info but with the actual screenshot omitted
+ mPublicNotificationBuilder =
+ new Notification.Builder(mContext, NotificationChannels.SCREENSHOTS_HEADSUP);
+ mNotificationBuilder =
+ new Notification.Builder(mContext, NotificationChannels.SCREENSHOTS_HEADSUP);
+ }
+
+ /**
+ * Sets the current screenshot bitmap.
+ *
+ * @param image the bitmap of the current screenshot (used for preview)
+ */
+ public void setImage(Bitmap image) {
+ // Create the large notification icon
+ int imageWidth = image.getWidth();
+ int imageHeight = image.getHeight();
+
+ Paint paint = new Paint();
+ ColorMatrix desat = new ColorMatrix();
+ desat.setSaturation(0.25f);
+ paint.setColorFilter(new ColorMatrixColorFilter(desat));
+ Matrix matrix = new Matrix();
+ int overlayColor = 0x40FFFFFF;
+
+ matrix.setTranslate((mPreviewWidth - imageWidth) / 2f, (mPreviewHeight - imageHeight) / 2f);
+
+ Bitmap picture = generateAdjustedHwBitmap(
+ image, mPreviewWidth, mPreviewHeight, matrix, paint, overlayColor);
+
+ mNotificationStyle.bigPicture(picture.createAshmemBitmap());
+
+ // Note, we can't use the preview for the small icon, since it is non-square
+ float scale = (float) mIconSize / Math.min(imageWidth, imageHeight);
+ matrix.setScale(scale, scale);
+ matrix.postTranslate(
+ (mIconSize - (scale * imageWidth)) / 2,
+ (mIconSize - (scale * imageHeight)) / 2);
+ Bitmap icon =
+ generateAdjustedHwBitmap(image, mIconSize, mIconSize, matrix, paint, overlayColor);
+
+ /**
+ * NOTE: The following code prepares the notification builder for updating the
+ * notification after the screenshot has been written to disk.
+ */
+
+ // On the tablet, the large icon makes the notification appear as if it is clickable
+ // (and on small devices, the large icon is not shown) so defer showing the large icon
+ // until we compose the final post-save notification below.
+ mNotificationBuilder.setLargeIcon(icon.createAshmemBitmap());
+ // But we still don't set it for the expanded view, allowing the smallIcon to show here.
+ mNotificationStyle.bigLargeIcon((Bitmap) null);
+ }
+
+ /**
+ * Shows a notification to inform the user that a screenshot is currently being saved.
+ */
+ public void showSavingScreenshotNotification() {
+ final long now = System.currentTimeMillis();
+
+ mPublicNotificationBuilder
+ .setContentTitle(mResources.getString(R.string.screenshot_saving_title))
+ .setSmallIcon(R.drawable.stat_notify_image)
+ .setCategory(Notification.CATEGORY_PROGRESS)
+ .setWhen(now)
+ .setShowWhen(true)
+ .setColor(mResources.getColor(
+ com.android.internal.R.color.system_notification_accent_color));
+ SystemUI.overrideNotificationAppName(mContext, mPublicNotificationBuilder, true);
+
+ mNotificationBuilder
+ .setContentTitle(mResources.getString(R.string.screenshot_saving_title))
+ .setSmallIcon(R.drawable.stat_notify_image)
+ .setWhen(now)
+ .setShowWhen(true)
+ .setColor(mResources.getColor(
+ com.android.internal.R.color.system_notification_accent_color))
+ .setStyle(mNotificationStyle)
+ .setPublicVersion(mPublicNotificationBuilder.build());
+ mNotificationBuilder.setFlag(Notification.FLAG_NO_CLEAR, true);
+ SystemUI.overrideNotificationAppName(mContext, mNotificationBuilder, true);
+
+ mNotificationManager.notify(SystemMessageProto.SystemMessage.NOTE_GLOBAL_SCREENSHOT,
+ mNotificationBuilder.build());
+ }
+
+ /**
+ * Shows a notification with the saved screenshot and actions that can be taken with it.
+ *
+ * @param imageUri URI for the saved image
+ * @param actions a list of notification actions which can be taken
+ */
+ public void showScreenshotActionsNotification(
+ Uri imageUri,
+ List<Notification.Action> actions) {
+ for (Notification.Action action : actions) {
+ mNotificationBuilder.addAction(action);
+ }
+
+ // Create the intent to show the screenshot in gallery
+ Intent launchIntent = new Intent(Intent.ACTION_VIEW);
+ launchIntent.setDataAndType(imageUri, "image/png");
+ launchIntent.setFlags(
+ Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_GRANT_READ_URI_PERMISSION);
+
+ final long now = System.currentTimeMillis();
+
+ // Update the text and the icon for the existing notification
+ mPublicNotificationBuilder
+ .setContentTitle(mResources.getString(R.string.screenshot_saved_title))
+ .setContentText(mResources.getString(R.string.screenshot_saved_text))
+ .setContentIntent(PendingIntent.getActivity(mContext, 0, launchIntent, 0))
+ .setWhen(now)
+ .setAutoCancel(true)
+ .setColor(mContext.getColor(
+ com.android.internal.R.color.system_notification_accent_color));
+ mNotificationBuilder
+ .setContentTitle(mResources.getString(R.string.screenshot_saved_title))
+ .setContentText(mResources.getString(R.string.screenshot_saved_text))
+ .setContentIntent(PendingIntent.getActivity(mContext, 0, launchIntent, 0))
+ .setWhen(now)
+ .setAutoCancel(true)
+ .setColor(mContext.getColor(
+ com.android.internal.R.color.system_notification_accent_color))
+ .setPublicVersion(mPublicNotificationBuilder.build())
+ .setFlag(Notification.FLAG_NO_CLEAR, false);
+
+ mNotificationManager.notify(SystemMessageProto.SystemMessage.NOTE_GLOBAL_SCREENSHOT,
+ mNotificationBuilder.build());
+ }
+
+ /**
+ * Sends a notification that the screenshot capture has failed.
+ */
+ public void notifyScreenshotError(int msgResId) {
+ Resources res = mContext.getResources();
+ String errorMsg = res.getString(msgResId);
+
+ // Repurpose the existing notification to notify the user of the error
+ Notification.Builder b = new Notification.Builder(mContext, NotificationChannels.ALERTS)
+ .setTicker(res.getString(R.string.screenshot_failed_title))
+ .setContentTitle(res.getString(R.string.screenshot_failed_title))
+ .setContentText(errorMsg)
+ .setSmallIcon(R.drawable.stat_notify_image_error)
+ .setWhen(System.currentTimeMillis())
+ .setVisibility(Notification.VISIBILITY_PUBLIC) // ok to show outside lockscreen
+ .setCategory(Notification.CATEGORY_ERROR)
+ .setAutoCancel(true)
+ .setColor(mContext.getColor(
+ com.android.internal.R.color.system_notification_accent_color));
+ final DevicePolicyManager dpm =
+ (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
+ final Intent intent =
+ dpm.createAdminSupportIntent(DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE);
+ if (intent != null) {
+ final PendingIntent pendingIntent = PendingIntent.getActivityAsUser(
+ mContext, 0, intent, 0, null, UserHandle.CURRENT);
+ b.setContentIntent(pendingIntent);
+ }
+
+ SystemUI.overrideNotificationAppName(mContext, b, true);
+
+ Notification n = new Notification.BigTextStyle(b)
+ .bigText(errorMsg)
+ .build();
+ mNotificationManager.notify(SystemMessageProto.SystemMessage.NOTE_GLOBAL_SCREENSHOT, n);
+ }
+
+ /**
+ * Cancels the current screenshot notification.
+ */
+ public void cancelNotification() {
+ mNotificationManager.cancel(SystemMessageProto.SystemMessage.NOTE_GLOBAL_SCREENSHOT);
+ }
+
+ /**
+ * Generates a new hardware bitmap with specified values, copying the content from the
+ * passed in bitmap.
+ */
+ private Bitmap generateAdjustedHwBitmap(Bitmap bitmap, int width, int height, Matrix matrix,
+ Paint paint, int color) {
+ Picture picture = new Picture();
+ Canvas canvas = picture.beginRecording(width, height);
+ canvas.drawColor(color);
+ canvas.drawBitmap(bitmap, matrix, paint);
+ picture.endRecording();
+ return Bitmap.createBitmap(picture);
+ }
+
+ static void cancelScreenshotNotification(Context context) {
+ final NotificationManager nm =
+ (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
+ nm.cancel(SystemMessageProto.SystemMessage.NOTE_GLOBAL_SCREENSHOT);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotServiceErrorReceiver.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotServiceErrorReceiver.java
index fc2a1e47253c..522f729a25d6 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotServiceErrorReceiver.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotServiceErrorReceiver.java
@@ -16,10 +16,10 @@
package com.android.systemui.screenshot;
-import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
+import android.view.WindowManager;
import com.android.systemui.R;
@@ -32,9 +32,9 @@ public class ScreenshotServiceErrorReceiver extends BroadcastReceiver {
@Override
public void onReceive(final Context context, Intent intent) {
// Show a message that we've failed to save the image to disk
- NotificationManager nm = (NotificationManager)
- context.getSystemService(Context.NOTIFICATION_SERVICE);
- GlobalScreenshot.notifyScreenshotError(context, nm,
- R.string.screenshot_failed_to_save_unknown_text);
+ WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+ ScreenshotNotificationsController controller =
+ new ScreenshotNotificationsController(context, wm);
+ controller.notifyScreenshotError(R.string.screenshot_failed_to_save_unknown_text);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSmartActions.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSmartActions.java
new file mode 100644
index 000000000000..e76e37e5c608
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSmartActions.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot;
+
+import static android.os.AsyncTask.THREAD_POOL_EXECUTOR;
+
+import android.app.ActivityManager;
+import android.app.Notification;
+import android.content.ComponentName;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.os.Handler;
+import android.os.SystemClock;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.SystemUIFactory;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * Collects the static functions for retrieving and acting on smart actions.
+ */
+public class ScreenshotSmartActions {
+ private static final String TAG = "ScreenshotSmartActions";
+
+ @VisibleForTesting
+ static CompletableFuture<List<Notification.Action>> getSmartActionsFuture(String screenshotId,
+ Bitmap image, ScreenshotNotificationSmartActionsProvider smartActionsProvider,
+ boolean smartActionsEnabled, boolean isManagedProfile) {
+ if (!smartActionsEnabled) {
+ Slog.i(TAG, "Screenshot Intelligence not enabled, returning empty list.");
+ return CompletableFuture.completedFuture(Collections.emptyList());
+ }
+ if (image.getConfig() != Bitmap.Config.HARDWARE) {
+ Slog.w(TAG, String.format(
+ "Bitmap expected: Hardware, Bitmap found: %s. Returning empty list.",
+ image.getConfig()));
+ return CompletableFuture.completedFuture(Collections.emptyList());
+ }
+
+ Slog.d(TAG, "Screenshot from a managed profile: " + isManagedProfile);
+ CompletableFuture<List<Notification.Action>> smartActionsFuture;
+ long startTimeMs = SystemClock.uptimeMillis();
+ try {
+ ActivityManager.RunningTaskInfo runningTask =
+ ActivityManagerWrapper.getInstance().getRunningTask();
+ ComponentName componentName =
+ (runningTask != null && runningTask.topActivity != null)
+ ? runningTask.topActivity
+ : new ComponentName("", "");
+ smartActionsFuture = smartActionsProvider.getActions(screenshotId, image,
+ componentName,
+ isManagedProfile);
+ } catch (Throwable e) {
+ long waitTimeMs = SystemClock.uptimeMillis() - startTimeMs;
+ smartActionsFuture = CompletableFuture.completedFuture(Collections.emptyList());
+ Slog.e(TAG, "Failed to get future for screenshot notification smart actions.", e);
+ notifyScreenshotOp(screenshotId, smartActionsProvider,
+ ScreenshotNotificationSmartActionsProvider.ScreenshotOp.REQUEST_SMART_ACTIONS,
+ ScreenshotNotificationSmartActionsProvider.ScreenshotOpStatus.ERROR,
+ waitTimeMs);
+ }
+ return smartActionsFuture;
+ }
+
+ @VisibleForTesting
+ static List<Notification.Action> getSmartActions(String screenshotId,
+ CompletableFuture<List<Notification.Action>> smartActionsFuture, int timeoutMs,
+ ScreenshotNotificationSmartActionsProvider smartActionsProvider) {
+ long startTimeMs = SystemClock.uptimeMillis();
+ try {
+ List<Notification.Action> actions = smartActionsFuture.get(timeoutMs,
+ TimeUnit.MILLISECONDS);
+ long waitTimeMs = SystemClock.uptimeMillis() - startTimeMs;
+ Slog.d(TAG, String.format("Got %d smart actions. Wait time: %d ms",
+ actions.size(), waitTimeMs));
+ notifyScreenshotOp(screenshotId, smartActionsProvider,
+ ScreenshotNotificationSmartActionsProvider.ScreenshotOp.WAIT_FOR_SMART_ACTIONS,
+ ScreenshotNotificationSmartActionsProvider.ScreenshotOpStatus.SUCCESS,
+ waitTimeMs);
+ return actions;
+ } catch (Throwable e) {
+ long waitTimeMs = SystemClock.uptimeMillis() - startTimeMs;
+ Slog.e(TAG, String.format("Error getting smart actions. Wait time: %d ms", waitTimeMs),
+ e);
+ ScreenshotNotificationSmartActionsProvider.ScreenshotOpStatus status =
+ (e instanceof TimeoutException)
+ ? ScreenshotNotificationSmartActionsProvider.ScreenshotOpStatus.TIMEOUT
+ : ScreenshotNotificationSmartActionsProvider.ScreenshotOpStatus.ERROR;
+ notifyScreenshotOp(screenshotId, smartActionsProvider,
+ ScreenshotNotificationSmartActionsProvider.ScreenshotOp.WAIT_FOR_SMART_ACTIONS,
+ status, waitTimeMs);
+ return Collections.emptyList();
+ }
+ }
+
+ static void notifyScreenshotOp(String screenshotId,
+ ScreenshotNotificationSmartActionsProvider smartActionsProvider,
+ ScreenshotNotificationSmartActionsProvider.ScreenshotOp op,
+ ScreenshotNotificationSmartActionsProvider.ScreenshotOpStatus status, long durationMs) {
+ try {
+ smartActionsProvider.notifyOp(screenshotId, op, status, durationMs);
+ } catch (Throwable e) {
+ Slog.e(TAG, "Error in notifyScreenshotOp: ", e);
+ }
+ }
+
+ static void notifyScreenshotAction(Context context, String screenshotId, String action,
+ boolean isSmartAction) {
+ try {
+ ScreenshotNotificationSmartActionsProvider provider =
+ SystemUIFactory.getInstance().createScreenshotNotificationSmartActionsProvider(
+ context, THREAD_POOL_EXECUTOR, new Handler());
+ provider.notifyAction(screenshotId, action, isSmartAction);
+ } catch (Throwable e) {
+ Slog.e(TAG, "Error in notifyScreenshotAction: ", e);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
index 6243b4b41e73..29b96a90a734 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
@@ -42,14 +42,11 @@ public class TakeScreenshotService extends Service {
@Override
public void handleMessage(Message msg) {
final Messenger callback = msg.replyTo;
- Consumer<Uri> finisher = new Consumer<Uri>() {
- @Override
- public void accept(Uri uri) {
- Message reply = Message.obtain(null, 1, uri);
- try {
- callback.send(reply);
- } catch (RemoteException e) {
- }
+ Consumer<Uri> finisher = uri -> {
+ Message reply = Message.obtain(null, 1, uri);
+ try {
+ callback.send(reply);
+ } catch (RemoteException e) {
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerModule.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerModule.java
new file mode 100644
index 000000000000..49f4d5e91659
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerModule.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.stackdivider;
+
+import android.content.Context;
+
+import com.android.systemui.recents.Recents;
+
+import java.util.Optional;
+
+import javax.inject.Singleton;
+
+import dagger.Lazy;
+import dagger.Module;
+import dagger.Provides;
+
+/**
+ * Module which provides a Divider.
+ */
+@Module
+public class DividerModule {
+ @Singleton
+ @Provides
+ static Divider provideDivider(Context context, Optional<Lazy<Recents>> recentsOptionalLazy) {
+ return new Divider(context, recentsOptionalLazy);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index f2b4ad85b0c3..325af2424b2f 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -295,7 +295,7 @@ public class DividerView extends FrameLayout implements OnTouchListener,
R.integer.long_press_dock_anim_duration);
mGrowRecents = getResources().getBoolean(R.bool.recents_grow_in_multiwindow);
mTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
- mFlingAnimationUtils = new FlingAnimationUtils(getContext(), 0.3f);
+ mFlingAnimationUtils = new FlingAnimationUtils(getResources().getDisplayMetrics(), 0.3f);
updateDisplayInfo();
boolean landscape = getResources().getConfiguration().orientation
== Configuration.ORIENTATION_LANDSCAPE;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
index e24a3625769c..b846aa08c33b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
@@ -28,7 +28,7 @@ import android.view.accessibility.AccessibilityEvent;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
+import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag;
import java.util.stream.Stream;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/FlingAnimationUtils.java b/packages/SystemUI/src/com/android/systemui/statusbar/FlingAnimationUtils.java
index d4272605924f..525b5b795a03 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/FlingAnimationUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/FlingAnimationUtils.java
@@ -17,7 +17,7 @@
package com.android.systemui.statusbar;
import android.animation.Animator;
-import android.content.Context;
+import android.util.DisplayMetrics;
import android.util.Log;
import android.view.ViewPropertyAnimator;
import android.view.animation.Interpolator;
@@ -25,7 +25,8 @@ import android.view.animation.PathInterpolator;
import com.android.systemui.Interpolators;
import com.android.systemui.statusbar.notification.NotificationUtils;
-import com.android.systemui.statusbar.phone.StatusBar;
+
+import javax.inject.Inject;
/**
* Utility class to calculate general fling animation when the finger is released.
@@ -56,8 +57,8 @@ public class FlingAnimationUtils {
private float mCachedStartGradient = -1;
private float mCachedVelocityFactor = -1;
- public FlingAnimationUtils(Context ctx, float maxLengthSeconds) {
- this(ctx, maxLengthSeconds, 0.0f);
+ public FlingAnimationUtils(DisplayMetrics displayMetrics, float maxLengthSeconds) {
+ this(displayMetrics, maxLengthSeconds, 0.0f);
}
/**
@@ -66,8 +67,9 @@ public class FlingAnimationUtils {
* the end of the animation. 0 means it's at the beginning and no
* acceleration will take place.
*/
- public FlingAnimationUtils(Context ctx, float maxLengthSeconds, float speedUpFactor) {
- this(ctx, maxLengthSeconds, speedUpFactor, -1.0f, 1.0f);
+ public FlingAnimationUtils(DisplayMetrics displayMetrics, float maxLengthSeconds,
+ float speedUpFactor) {
+ this(displayMetrics, maxLengthSeconds, speedUpFactor, -1.0f, 1.0f);
}
/**
@@ -79,8 +81,8 @@ public class FlingAnimationUtils {
* is provided, the value is automatically calculated.
* @param y2 the y value to take for the second point of the bezier spline
*/
- public FlingAnimationUtils(Context ctx, float maxLengthSeconds, float speedUpFactor, float x2,
- float y2) {
+ public FlingAnimationUtils(DisplayMetrics displayMetrics, float maxLengthSeconds,
+ float speedUpFactor, float x2, float y2) {
mMaxLengthSeconds = maxLengthSeconds;
mSpeedUpFactor = speedUpFactor;
if (x2 < 0) {
@@ -92,10 +94,8 @@ public class FlingAnimationUtils {
}
mY2 = y2;
- mMinVelocityPxPerSecond
- = MIN_VELOCITY_DP_PER_SECOND * ctx.getResources().getDisplayMetrics().density;
- mHighVelocityPxPerSecond
- = HIGH_VELOCITY_DP_PER_SECOND * ctx.getResources().getDisplayMetrics().density;
+ mMinVelocityPxPerSecond = MIN_VELOCITY_DP_PER_SECOND * displayMetrics.density;
+ mHighVelocityPxPerSecond = HIGH_VELOCITY_DP_PER_SECOND * displayMetrics.density;
}
/**
@@ -365,4 +365,41 @@ public class FlingAnimationUtils {
long duration;
}
+ public static class Builder {
+ private final DisplayMetrics mDisplayMetrics;
+ float mMaxLengthSeconds;
+ float mSpeedUpFactor = 0.0f;
+ float mX2 = -1.0f;
+ float mY2 = 1.0f;
+
+ @Inject
+ public Builder(DisplayMetrics displayMetrics) {
+ mDisplayMetrics = displayMetrics;
+ }
+
+ public Builder setMaxLengthSeconds(float maxLengthSeconds) {
+ mMaxLengthSeconds = maxLengthSeconds;
+ return this;
+ }
+
+ public Builder setSpeedUpFactor(float speedUpFactor) {
+ mSpeedUpFactor = speedUpFactor;
+ return this;
+ }
+
+ public Builder setX2(float x2) {
+ mX2 = x2;
+ return this;
+ }
+
+ public Builder setY2(float y2) {
+ mY2 = y2;
+ return this;
+ }
+
+ public FlingAnimationUtils build() {
+ return new FlingAnimationUtils(mDisplayMetrics, mMaxLengthSeconds, mSpeedUpFactor,
+ mX2, mY2);
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
index 6adaa0ddbfd2..2c296353bd14 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
@@ -138,7 +138,8 @@ public class KeyguardAffordanceView extends ImageView {
mMinBackgroundRadius = mContext.getResources().getDimensionPixelSize(
R.dimen.keyguard_affordance_min_background_radius);
mColorInterpolator = new ArgbEvaluator();
- mFlingAnimationUtils = new FlingAnimationUtils(mContext, 0.3f);
+ mFlingAnimationUtils = new FlingAnimationUtils(mContext.getResources().getDisplayMetrics(),
+ 0.3f);
a.recycle();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
index 61043fbc1bc9..a8188b3ca35c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
@@ -35,7 +35,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.statusbar.RegisterStatusBarResult;
import com.android.systemui.Dependency;
import com.android.systemui.assist.AssistHandleViewController;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.statusbar.CommandQueue.Callbacks;
@@ -65,7 +65,7 @@ public class NavigationBarController implements Callbacks {
SparseArray<NavigationBarFragment> mNavigationBars = new SparseArray<>();
@Inject
- public NavigationBarController(Context context, @MainHandler Handler handler,
+ public NavigationBarController(Context context, @Main Handler handler,
CommandQueue commandQueue) {
mContext = context;
mHandler = handler;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
index 97dd3daae341..8dd801b0484f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
@@ -30,7 +30,7 @@ import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
import android.util.Log;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.statusbar.phone.NotificationListenerWithPlugins;
import java.util.ArrayList;
@@ -58,7 +58,7 @@ public class NotificationListener extends NotificationListenerWithPlugins {
public NotificationListener(
Context context,
NotificationManager notificationManager,
- @MainHandler Handler mainHandler) {
+ @Main Handler mainHandler) {
mContext = context;
mNotificationManager = notificationManager;
mMainHandler = mainHandler;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
index 0f3f6b7d9222..2e369b3295b8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
@@ -48,7 +48,7 @@ import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.recents.OverviewProxyService;
@@ -190,7 +190,7 @@ public class NotificationLockscreenUserManagerImpl implements
IStatusBarService iStatusBarService,
KeyguardManager keyguardManager,
StatusBarStateController statusBarStateController,
- @MainHandler Handler mainHandler,
+ @Main Handler mainHandler,
DeviceProvisionedController deviceProvisionedController,
KeyguardStateController keyguardStateController) {
mContext = context;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
index f6f3ac1b5aaf..43d0399c6d62 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
@@ -50,7 +50,7 @@ import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -263,7 +263,7 @@ public class NotificationRemoteInputManager implements Dumpable {
NotificationEntryManager notificationEntryManager,
Lazy<StatusBar> statusBarLazy,
StatusBarStateController statusBarStateController,
- @MainHandler Handler mainHandler,
+ @Main Handler mainHandler,
RemoteInputUriController remoteInputUriController) {
mContext = context;
mLockscreenUserManager = lockscreenUserManager;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
index 1648196ec0ea..6b0b5dfeaf40 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
@@ -27,7 +27,7 @@ import android.view.ViewGroup;
import com.android.systemui.R;
import com.android.systemui.bubbles.BubbleController;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -93,7 +93,7 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
private boolean mIsHandleDynamicPrivacyChangeScheduled;
@Inject
- public NotificationViewHierarchyManager(Context context, @MainHandler Handler mainHandler,
+ public NotificationViewHierarchyManager(Context context, @Main Handler mainHandler,
NotificationLockscreenUserManager notificationLockscreenUserManager,
NotificationGroupManager groupManager,
VisualStabilityManager visualStabilityManager,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
index 49bed15c79a8..93f58053f486 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
@@ -54,12 +54,13 @@ import com.android.systemui.Dependency;
import com.android.systemui.DockedStackExistsListener;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
-import com.android.systemui.UiOffloadThread;
+import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.NotificationChannels;
import java.util.List;
+import java.util.concurrent.Executor;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -74,16 +75,18 @@ public class InstantAppNotifier extends SystemUI
public static final int NUM_TASKS_FOR_INSTANT_APP_INFO = 5;
private final Handler mHandler = new Handler();
- private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
+ private final Executor mUiBgExecutor;
private final ArraySet<Pair<String, Integer>> mCurrentNotifs = new ArraySet<>();
private final CommandQueue mCommandQueue;
private boolean mDockedStackExists;
private KeyguardStateController mKeyguardStateController;
@Inject
- public InstantAppNotifier(Context context, CommandQueue commandQueue) {
+ public InstantAppNotifier(Context context, CommandQueue commandQueue,
+ @UiBackground Executor uiBgExecutor) {
super(context);
mCommandQueue = commandQueue;
+ mUiBgExecutor = uiBgExecutor;
}
@Override
@@ -151,7 +154,7 @@ public class InstantAppNotifier extends SystemUI
private void updateForegroundInstantApps() {
NotificationManager noMan = mContext.getSystemService(NotificationManager.class);
IPackageManager pm = AppGlobals.getPackageManager();
- mUiOffloadThread.submit(
+ mUiBgExecutor.execute(
() -> {
ArraySet<Pair<String, Integer>> notifs = new ArraySet<>(mCurrentNotifs);
try {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java
index 31b7cb0fb5a0..81833a4022a9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java
@@ -17,7 +17,7 @@
package com.android.systemui.statusbar.notification;
import static com.android.systemui.statusbar.NotificationRemoteInputManager.FORCE_REMOTE_INPUT_HISTORY;
-import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_HEADS_UP;
+import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP;
import android.app.Notification;
import android.service.notification.StatusBarNotification;
@@ -28,7 +28,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
+import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import javax.inject.Inject;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java
index 06949208c2bb..f6b55838989c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java
@@ -24,7 +24,7 @@ import androidx.annotation.NonNull;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
+import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag;
/**
* Listener interface for changes sent by NotificationEntryManager.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
index 43b9fbc909dc..b8afb78119de 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -18,6 +18,8 @@ package com.android.systemui.statusbar.notification;
import static android.service.notification.NotificationListenerService.REASON_CANCEL;
import static android.service.notification.NotificationListenerService.REASON_ERROR;
+import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationCallback;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Notification;
@@ -45,8 +47,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationRowBin
import com.android.systemui.statusbar.notification.logging.NotifEvent;
import com.android.systemui.statusbar.notification.logging.NotifLog;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
-import com.android.systemui.statusbar.notification.row.NotificationContentInflater;
-import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
+import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.policy.HeadsUpManager;
@@ -94,7 +95,7 @@ import javax.inject.Singleton;
@Singleton
public class NotificationEntryManager implements
Dumpable,
- NotificationContentInflater.InflationCallback,
+ InflationCallback,
VisualStabilityManager.Callback {
private static final String TAG = "NotificationEntryMgr";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
index 1b57308f1c0f..99718abb6492 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
@@ -23,7 +23,7 @@ import android.view.View;
import androidx.collection.ArraySet;
import com.android.systemui.Dumpable;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -62,7 +62,7 @@ public class VisualStabilityManager implements OnHeadsUpChangedListener, Dumpabl
@Inject
public VisualStabilityManager(
- NotificationEntryManager notificationEntryManager, @MainHandler Handler handler) {
+ NotificationEntryManager notificationEntryManager, @Main Handler handler) {
mHandler = handler;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java
index 052473ae21d9..601b3e053e8e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java
@@ -18,7 +18,6 @@ package com.android.systemui.statusbar.notification.collection;
import android.annotation.Nullable;
-import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Dependency;
import com.android.systemui.statusbar.notification.collection.provider.DerivedMember;
import com.android.systemui.statusbar.notification.collection.provider.IsHighPriorityProvider;
@@ -68,8 +67,7 @@ public abstract class ListEntry {
return mParent;
}
- @VisibleForTesting
- public void setParent(@Nullable GroupEntry parent) {
+ void setParent(@Nullable GroupEntry parent) {
if (!Objects.equals(mParent, parent)) {
invalidateParent();
mParent = parent;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImpl.java
index a1cfb5424c08..f0a003f2ff5e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImpl.java
@@ -20,9 +20,12 @@ import static com.android.systemui.statusbar.notification.collection.GroupEntry.
import static com.android.systemui.statusbar.notification.collection.ListDumper.dumpList;
import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_BUILD_PENDING;
import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_BUILD_STARTED;
-import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_FILTERING;
import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_FINALIZING;
+import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_GROUPING;
import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_IDLE;
+import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_PRE_GROUP_FILTERING;
+import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_PRE_RENDER_FILTERING;
+import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_RESETTING;
import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_SORTING;
import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_TRANSFORMING;
@@ -63,16 +66,17 @@ public class NotifListBuilderImpl implements NotifListBuilder {
private final SystemClock mSystemClock;
private final NotifLog mNotifLog;
- private final List<ListEntry> mNotifList = new ArrayList<>();
+ private List<ListEntry> mNotifList = new ArrayList<>();
+ private List<ListEntry> mNewNotifList = new ArrayList<>();
private final PipelineState mPipelineState = new PipelineState();
private final Map<String, GroupEntry> mGroups = new ArrayMap<>();
private Collection<NotificationEntry> mAllEntries = Collections.emptyList();
- private final List<ListEntry> mNewEntries = new ArrayList<>();
private int mIterationCount = 0;
- private final List<NotifFilter> mNotifFilters = new ArrayList<>();
+ private final List<NotifFilter> mNotifPreGroupFilters = new ArrayList<>();
private final List<NotifPromoter> mNotifPromoters = new ArrayList<>();
+ private final List<NotifFilter> mNotifPreRenderFilters = new ArrayList<>();
private final List<NotifComparator> mNotifComparators = new ArrayList<>();
private SectionsProvider mSectionsProvider = new DefaultSectionsProvider();
@@ -138,12 +142,21 @@ public class NotifListBuilderImpl implements NotifListBuilder {
}
@Override
- public void addFilter(NotifFilter filter) {
+ public void addPreGroupFilter(NotifFilter filter) {
Assert.isMainThread();
mPipelineState.requireState(STATE_IDLE);
- mNotifFilters.add(filter);
- filter.setInvalidationListener(this::onFilterInvalidated);
+ mNotifPreGroupFilters.add(filter);
+ filter.setInvalidationListener(this::onPreGroupFilterInvalidated);
+ }
+
+ @Override
+ public void addPreRenderFilter(NotifFilter filter) {
+ Assert.isMainThread();
+ mPipelineState.requireState(STATE_IDLE);
+
+ mNotifPreRenderFilters.add(filter);
+ filter.setInvalidationListener(this::onPreRenderFilterInvalidated);
}
@Override
@@ -202,15 +215,15 @@ public class NotifListBuilderImpl implements NotifListBuilder {
}
};
- private void onFilterInvalidated(NotifFilter filter) {
+ private void onPreGroupFilterInvalidated(NotifFilter filter) {
Assert.isMainThread();
- mNotifLog.log(NotifEvent.FILTER_INVALIDATED, String.format(
+ mNotifLog.log(NotifEvent.PRE_GROUP_FILTER_INVALIDATED, String.format(
"Filter \"%s\" invalidated; pipeline state is %d",
filter.getName(),
mPipelineState.getState()));
- rebuildListIfBefore(STATE_FILTERING);
+ rebuildListIfBefore(STATE_PRE_GROUP_FILTERING);
}
private void onPromoterInvalidated(NotifPromoter filter) {
@@ -235,6 +248,17 @@ public class NotifListBuilderImpl implements NotifListBuilder {
rebuildListIfBefore(STATE_SORTING);
}
+ private void onPreRenderFilterInvalidated(NotifFilter filter) {
+ Assert.isMainThread();
+
+ mNotifLog.log(NotifEvent.PRE_RENDER_FILTER_INVALIDATED, String.format(
+ "Filter \"%s\" invalidated; pipeline state is %d",
+ filter.getName(),
+ mPipelineState.getState()));
+
+ rebuildListIfBefore(STATE_PRE_RENDER_FILTERING);
+ }
+
private void onNotifComparatorInvalidated(NotifComparator comparator) {
Assert.isMainThread();
@@ -247,6 +271,17 @@ public class NotifListBuilderImpl implements NotifListBuilder {
}
/**
+ * Points mNotifList to the list stored in mNewNotifList.
+ * Reuses the (emptied) mNotifList as mNewNotifList.
+ */
+ private void applyNewNotifList() {
+ mNotifList.clear();
+ List<ListEntry> emptyList = mNotifList;
+ mNotifList = mNewNotifList;
+ mNewNotifList = emptyList;
+ }
+
+ /**
* The core algorithm of the pipeline. See the top comment in {@link NotifListBuilder} for
* details on our contracts with other code.
*
@@ -261,35 +296,47 @@ public class NotifListBuilderImpl implements NotifListBuilder {
mPipelineState.requireIsBefore(STATE_BUILD_STARTED);
mPipelineState.setState(STATE_BUILD_STARTED);
- // Step 1: Filtering and initial grouping
- // Filter out any notifs that shouldn't be shown right now and cluster any that are part of
- // a group
- mPipelineState.incrementTo(STATE_FILTERING);
- mNotifList.clear();
- mNewEntries.clear();
- filterAndGroup(mAllEntries, mNotifList, mNewEntries);
- pruneIncompleteGroups(mNotifList, mNewEntries);
+ // Step 1: Reset notification states
+ mPipelineState.incrementTo(STATE_RESETTING);
+ resetNotifs();
+
+ // Step 2: Filter out any notifications that shouldn't be shown right now
+ mPipelineState.incrementTo(STATE_PRE_GROUP_FILTERING);
+ filterNotifs(mAllEntries, mNotifList, mNotifPreGroupFilters);
- // Step 2: Group transforming
+ // Step 3: Group notifications with the same group key and set summaries
+ mPipelineState.incrementTo(STATE_GROUPING);
+ groupNotifs(mNotifList, mNewNotifList);
+ applyNewNotifList();
+ pruneIncompleteGroups(mNotifList);
+
+ // Step 4: Group transforming
// Move some notifs out of their groups and up to top-level (mostly used for heads-upping)
- dispatchOnBeforeTransformGroups(mReadOnlyNotifList, mNewEntries);
+ dispatchOnBeforeTransformGroups(mReadOnlyNotifList);
mPipelineState.incrementTo(STATE_TRANSFORMING);
promoteNotifs(mNotifList);
- pruneIncompleteGroups(mNotifList, mNewEntries);
+ pruneIncompleteGroups(mNotifList);
- // Step 3: Sort
+ // Step 5: Sort
// Assign each top-level entry a section, then sort the list by section and then within
// section by our list of custom comparators
dispatchOnBeforeSort(mReadOnlyNotifList);
mPipelineState.incrementTo(STATE_SORTING);
sortList();
- // Step 4: Lock in our group structure and log anything that's changed since the last run
+ // Step 6: Filter out entries after pre-group filtering, grouping, promoting and sorting
+ // Now filters can see grouping information to determine whether to filter or not
+ mPipelineState.incrementTo(STATE_PRE_RENDER_FILTERING);
+ filterNotifs(mNotifList, mNewNotifList, mNotifPreRenderFilters);
+ applyNewNotifList();
+ pruneIncompleteGroups(mNotifList);
+
+ // Step 7: Lock in our group structure and log anything that's changed since the last run
mPipelineState.incrementTo(STATE_FINALIZING);
logParentingChanges();
freeEmptyGroups();
- // Step 5: Dispatch the new list, first to any listeners and then to the view layer
+ // Step 6: Dispatch the new list, first to any listeners and then to the view layer
mNotifLog.log(NotifEvent.DISPATCH_FINAL_LIST, "List finalized, is:\n"
+ dumpList(mNotifList));
dispatchOnBeforeRenderList(mReadOnlyNotifList);
@@ -297,20 +344,14 @@ public class NotifListBuilderImpl implements NotifListBuilder {
mOnRenderListListener.onRenderList(mReadOnlyNotifList);
}
- // Step 6: We're done!
+ // Step 7: We're done!
mNotifLog.log(NotifEvent.LIST_BUILD_COMPLETE,
"Notif list build #" + mIterationCount + " completed");
mPipelineState.setState(STATE_IDLE);
mIterationCount++;
}
- private void filterAndGroup(
- Collection<NotificationEntry> entries,
- List<ListEntry> out,
- List<ListEntry> newlyVisibleEntries) {
-
- long now = mSystemClock.uptimeMillis();
-
+ private void resetNotifs() {
for (GroupEntry group : mGroups.values()) {
group.setPreviousParent(group.getParent());
group.setParent(null);
@@ -318,22 +359,57 @@ public class NotifListBuilderImpl implements NotifListBuilder {
group.setSummary(null);
}
- for (NotificationEntry entry : entries) {
+ for (NotificationEntry entry : mAllEntries) {
entry.setPreviousParent(entry.getParent());
entry.setParent(null);
- // See if we should filter out this notification
- boolean shouldFilterOut = applyFilters(entry, now);
- if (shouldFilterOut) {
- continue;
- }
-
if (entry.mFirstAddedIteration == -1) {
entry.mFirstAddedIteration = mIterationCount;
- newlyVisibleEntries.add(entry);
}
+ }
+
+ mNotifList.clear();
+ }
+
+ private void filterNotifs(Collection<? extends ListEntry> entries,
+ List<ListEntry> out, List<NotifFilter> filters) {
+ final long now = mSystemClock.uptimeMillis();
+ for (ListEntry entry : entries) {
+ if (entry instanceof GroupEntry) {
+ final GroupEntry groupEntry = (GroupEntry) entry;
+
+ // apply filter on its summary
+ final NotificationEntry summary = groupEntry.getRepresentativeEntry();
+ if (applyFilters(summary, now, filters)) {
+ groupEntry.setSummary(null);
+ annulAddition(summary);
+ }
+
+ // apply filter on its children
+ final List<NotificationEntry> children = groupEntry.getRawChildren();
+ for (int j = children.size() - 1; j >= 0; j--) {
+ final NotificationEntry child = children.get(j);
+ if (applyFilters(child, now, filters)) {
+ children.remove(child);
+ annulAddition(child);
+ }
+ }
- // Otherwise, group it
+ out.add(groupEntry);
+ } else {
+ if (applyFilters((NotificationEntry) entry, now, filters)) {
+ annulAddition(entry);
+ } else {
+ out.add(entry);
+ }
+ }
+ }
+ }
+
+ private void groupNotifs(List<ListEntry> entries, List<ListEntry> out) {
+ for (ListEntry listEntry : entries) {
+ // since grouping hasn't happened yet, all notifs are NotificationEntries
+ NotificationEntry entry = (NotificationEntry) listEntry;
if (entry.getSbn().isGroup()) {
final String topLevelKey = entry.getSbn().getGroupKey();
@@ -341,7 +417,6 @@ public class NotifListBuilderImpl implements NotifListBuilder {
if (group == null) {
group = new GroupEntry(topLevelKey);
group.mFirstAddedIteration = mIterationCount;
- newlyVisibleEntries.add(group);
mGroups.put(topLevelKey, group);
}
if (group.getParent() == null) {
@@ -367,9 +442,9 @@ public class NotifListBuilderImpl implements NotifListBuilder {
if (entry.getSbn().getPostTime()
> existingSummary.getSbn().getPostTime()) {
group.setSummary(entry);
- annulAddition(existingSummary, out, newlyVisibleEntries);
+ annulAddition(existingSummary, out);
} else {
- annulAddition(entry, out, newlyVisibleEntries);
+ annulAddition(entry, out);
}
}
} else {
@@ -411,10 +486,7 @@ public class NotifListBuilderImpl implements NotifListBuilder {
}
}
- private void pruneIncompleteGroups(
- List<ListEntry> shadeList,
- List<ListEntry> newlyVisibleEntries) {
-
+ private void pruneIncompleteGroups(List<ListEntry> shadeList) {
for (int i = 0; i < shadeList.size(); i++) {
final ListEntry tle = shadeList.get(i);
@@ -431,7 +503,7 @@ public class NotifListBuilderImpl implements NotifListBuilder {
shadeList.add(summary);
group.setSummary(null);
- annulAddition(group, shadeList, newlyVisibleEntries);
+ annulAddition(group, shadeList);
} else if (group.getSummary() == null
|| children.size() < MIN_CHILDREN_FOR_GROUP) {
@@ -444,7 +516,7 @@ public class NotifListBuilderImpl implements NotifListBuilder {
if (group.getSummary() != null) {
final NotificationEntry summary = group.getSummary();
group.setSummary(null);
- annulAddition(summary, shadeList, newlyVisibleEntries);
+ annulAddition(summary, shadeList);
}
for (int j = 0; j < children.size(); j++) {
@@ -454,7 +526,7 @@ public class NotifListBuilderImpl implements NotifListBuilder {
}
children.clear();
- annulAddition(group, shadeList, newlyVisibleEntries);
+ annulAddition(group, shadeList);
}
}
}
@@ -468,10 +540,7 @@ public class NotifListBuilderImpl implements NotifListBuilder {
* Before calling this method, the entry must already have been removed from its parent. If
* it's a group, its summary must be null and its children must be empty.
*/
- private void annulAddition(
- ListEntry entry,
- List<ListEntry> shadeList,
- List<ListEntry> newlyVisibleEntries) {
+ private void annulAddition(ListEntry entry, List<ListEntry> shadeList) {
// This function does very little, but if any of its assumptions are violated (and it has a
// lot of them), it will put the system into an inconsistent state. So we check all of them
@@ -508,13 +577,18 @@ public class NotifListBuilderImpl implements NotifListBuilder {
}
}
+ annulAddition(entry);
+
+ }
+
+ /**
+ * Erases bookkeeping traces stored on an entry when it is removed from the notif list.
+ * This can happen if the entry is removed from a group that was broken up or if the entry was
+ * filtered out during any of the filtering steps.
+ */
+ private void annulAddition(ListEntry entry) {
entry.setParent(null);
if (entry.mFirstAddedIteration == mIterationCount) {
- if (!newlyVisibleEntries.remove(entry)) {
- throw new IllegalStateException("Cannot late-filter entry " + entry.getKey() + " "
- + entry + " from " + newlyVisibleEntries + " "
- + entry.mFirstAddedIteration);
- }
entry.mFirstAddedIteration = -1;
}
}
@@ -606,8 +680,8 @@ public class NotifListBuilderImpl implements NotifListBuilder {
return cmp;
};
- private boolean applyFilters(NotificationEntry entry, long now) {
- NotifFilter filter = findRejectingFilter(entry, now);
+ private boolean applyFilters(NotificationEntry entry, long now, List<NotifFilter> filters) {
+ NotifFilter filter = findRejectingFilter(entry, now, filters);
if (filter != entry.mExcludingFilter) {
if (entry.mExcludingFilter == null) {
@@ -637,9 +711,12 @@ public class NotifListBuilderImpl implements NotifListBuilder {
return filter != null;
}
- @Nullable private NotifFilter findRejectingFilter(NotificationEntry entry, long now) {
- for (int i = 0; i < mNotifFilters.size(); i++) {
- NotifFilter filter = mNotifFilters.get(i);
+ @Nullable private static NotifFilter findRejectingFilter(NotificationEntry entry, long now,
+ List<NotifFilter> filters) {
+ final int size = filters.size();
+
+ for (int i = 0; i < size; i++) {
+ NotifFilter filter = filters.get(i);
if (filter.shouldFilterOut(entry, now)) {
return filter;
}
@@ -691,12 +768,9 @@ public class NotifListBuilderImpl implements NotifListBuilder {
}
}
- private void dispatchOnBeforeTransformGroups(
- List<ListEntry> entries,
- List<ListEntry> newlyVisibleEntries) {
+ private void dispatchOnBeforeTransformGroups(List<ListEntry> entries) {
for (int i = 0; i < mOnBeforeTransformGroupsListeners.size(); i++) {
- mOnBeforeTransformGroupsListeners.get(i)
- .onBeforeTransformGroups(entries, newlyVisibleEntries);
+ mOnBeforeTransformGroupsListeners.get(i).onBeforeTransformGroups(entries);
}
}
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 de16ef5a6d40..dd3a3e0b1505 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
@@ -61,8 +61,8 @@ import com.android.systemui.statusbar.notification.InflationException;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
import com.android.systemui.statusbar.notification.row.NotificationGuts;
+import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag;
import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager;
import java.util.ArrayList;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java
index 1c0a9d4f14af..8afbc27589d8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java
@@ -18,7 +18,7 @@ package com.android.systemui.statusbar.notification.collection;
import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.systemui.statusbar.NotificationRemoteInputManager.ENABLE_REMOTE_INPUT;
-import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_HEADS_UP;
+import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP;
import android.annotation.Nullable;
import android.content.Context;
@@ -258,7 +258,7 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
row.setEntry(entry);
if (mNotificationInterruptionStateProvider.shouldHeadsUp(entry)) {
- row.updateInflationFlag(FLAG_CONTENT_VIEW_HEADS_UP, true /* shouldInflate */);
+ row.setInflationFlags(FLAG_CONTENT_VIEW_HEADS_UP);
}
row.setNeedsRedaction(
Dependency.get(NotificationLockscreenUserManager.class).needsRedaction(entry));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinator.java
index b68cb0dd3320..5e7dd98fa9da 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinator.java
@@ -55,7 +55,7 @@ public class DeviceProvisionedCoordinator implements Coordinator {
public void attach(NotifCollection notifCollection, NotifListBuilder notifListBuilder) {
mDeviceProvisionedController.addCallback(mDeviceProvisionedListener);
- notifListBuilder.addFilter(mNotifFilter);
+ notifListBuilder.addPreGroupFilter(mNotifFilter);
}
private final NotifFilter mNotifFilter = new NotifFilter(TAG) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinator.java
index 378599b79cc0..62342b13f9cf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinator.java
@@ -24,7 +24,7 @@ import android.util.ArraySet;
import com.android.systemui.ForegroundServiceController;
import com.android.systemui.appops.AppOpsController;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifCollectionListener;
import com.android.systemui.statusbar.notification.collection.NotifLifetimeExtender;
@@ -63,7 +63,7 @@ public class ForegroundCoordinator implements Coordinator {
public ForegroundCoordinator(
ForegroundServiceController foregroundServiceController,
AppOpsController appOpsController,
- @MainHandler Handler mainHandler) {
+ @Main Handler mainHandler) {
mForegroundServiceController = foregroundServiceController;
mAppOpsController = appOpsController;
mMainHandler = mainHandler;
@@ -83,7 +83,7 @@ public class ForegroundCoordinator implements Coordinator {
mAppOpsController.addCallback(ForegroundServiceController.APP_OPS, this::onAppOpsChanged);
// filter out foreground service notifications that aren't necessary anymore
- notifListBuilder.addFilter(mNotifFilter);
+ notifListBuilder.addPreGroupFilter(mNotifFilter);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java
index 232246e4f704..9312c2260d46 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java
@@ -85,7 +85,7 @@ public class KeyguardCoordinator implements Coordinator {
@Override
public void attach(NotifCollection notifCollection, NotifListBuilder notifListBuilder) {
setupInvalidateNotifListCallbacks();
- notifListBuilder.addFilter(mNotifFilter);
+ notifListBuilder.addPreRenderFilter(mNotifFilter);
}
private final NotifFilter mNotifFilter = new NotifFilter(TAG) {
@@ -131,9 +131,8 @@ public class KeyguardCoordinator implements Coordinator {
}
}
- // ... neither this notification nor its summary have high enough priority
+ // ... neither this notification nor its group have high enough priority
// to be shown on the lockscreen
- // TODO: grouping hasn't happened yet (b/145134683)
if (entry.getParent() != null) {
final GroupEntry parent = entry.getParent();
if (priorityExceedsLockscreenShowingThreshold(parent)) {
@@ -152,11 +151,10 @@ public class KeyguardCoordinator implements Coordinator {
}
if (NotificationUtils.useNewInterruptionModel(mContext)
&& hideSilentNotificationsOnLockscreen()) {
- // TODO: make sure in the NewNotifPipeline that entry.isHighPriority() has been
- // correctly updated before reaching this point (b/145134683)
return entry.isHighPriority();
} else {
- return !entry.getRepresentativeEntry().getRanking().isAmbient();
+ return entry.getRepresentativeEntry() != null
+ && !entry.getRepresentativeEntry().getRanking().isAmbient();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java
index 24e7a79e9588..0751aa814215 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java
@@ -46,7 +46,7 @@ public class RankingCoordinator implements Coordinator {
public void attach(NotifCollection notifCollection, NotifListBuilder notifListBuilder) {
mStatusBarStateController.addCallback(mStatusBarStateCallback);
- notifListBuilder.addFilter(mNotifFilter);
+ notifListBuilder.addPreGroupFilter(mNotifFilter);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/NotifListBuilder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/NotifListBuilder.java
index 15d3b9222cd2..758092417ae0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/NotifListBuilder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/NotifListBuilder.java
@@ -59,11 +59,12 @@ import java.util.List;
public interface NotifListBuilder {
/**
- * Registers a filter with the pipeline. Filters are called on each notification in the order
- * that they were registered. If any filter returns true, the notification is removed from the
- * pipeline (and no other filters are called on that notif).
+ * Registers a filter with the pipeline before grouping, promoting and sorting occurs. Filters
+ * are called on each notification in the order that they were registered. If any filter
+ * returns true, the notification is removed from the pipeline (and no other filters are
+ * called on that notif).
*/
- void addFilter(NotifFilter filter);
+ void addPreGroupFilter(NotifFilter filter);
/**
* Registers a promoter with the pipeline. Promoters are able to promote child notifications to
@@ -91,6 +92,15 @@ public interface NotifListBuilder {
void setComparators(List<NotifComparator> comparators);
/**
+ * Registers a filter with the pipeline to filter right before rendering the list (after
+ * pre-group filtering, grouping, promoting and sorting occurs). Filters are
+ * called on each notification in the order that they were registered. If any filter returns
+ * true, the notification is removed from the pipeline (and no other filters are called on that
+ * notif).
+ */
+ void addPreRenderFilter(NotifFilter filter);
+
+ /**
* Called after notifications have been filtered and after the initial grouping has been
* performed but before NotifPromoters have had a chance to promote children out of groups.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeTransformGroupsListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeTransformGroupsListener.java
index 170ff48ad7f1..d7a081510655 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeTransformGroupsListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeTransformGroupsListener.java
@@ -33,8 +33,6 @@ public interface OnBeforeTransformGroupsListener {
* @param list The current filtered and grouped list of (top-level) entries. Note that this is
* a live view into the current notif list and will change as the list moves through
* the pipeline.
- * @param newlyVisibleEntries The list of all entries (both top-level and children) who have
- * been added to the list for the first time.
*/
- void onBeforeTransformGroups(List<ListEntry> list, List<ListEntry> newlyVisibleEntries);
+ void onBeforeTransformGroups(List<ListEntry> list);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/PipelineState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/PipelineState.java
index ad4bbd915787..85f828d9e3c7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/PipelineState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/PipelineState.java
@@ -78,18 +78,24 @@ public class PipelineState {
public static final int STATE_IDLE = 0;
public static final int STATE_BUILD_PENDING = 1;
public static final int STATE_BUILD_STARTED = 2;
- public static final int STATE_FILTERING = 3;
- public static final int STATE_TRANSFORMING = 4;
- public static final int STATE_SORTING = 5;
- public static final int STATE_FINALIZING = 6;
+ public static final int STATE_RESETTING = 3;
+ public static final int STATE_PRE_GROUP_FILTERING = 4;
+ public static final int STATE_GROUPING = 5;
+ public static final int STATE_TRANSFORMING = 6;
+ public static final int STATE_SORTING = 7;
+ public static final int STATE_PRE_RENDER_FILTERING = 8;
+ public static final int STATE_FINALIZING = 9;
@IntDef(prefix = { "STATE_" }, value = {
STATE_IDLE,
STATE_BUILD_PENDING,
STATE_BUILD_STARTED,
- STATE_FILTERING,
+ STATE_RESETTING,
+ STATE_PRE_GROUP_FILTERING,
+ STATE_GROUPING,
STATE_TRANSFORMING,
STATE_SORTING,
+ STATE_PRE_RENDER_FILTERING,
STATE_FINALIZING,
})
@Retention(RetentionPolicy.SOURCE)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifFilter.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifFilter.java
index 685eac88de34..e6189edc2f3b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifFilter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifFilter.java
@@ -20,8 +20,8 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
/**
- * Pluggable for participating in notif filtering. See
- * {@link NotifListBuilder#addFilter(NotifFilter)}.
+ * Pluggable for participating in notif filtering.
+ * See {@link NotifListBuilder#addPreGroupFilter} and {@link NotifListBuilder#addPreRenderFilter}.
*/
public abstract class NotifFilter extends Pluggable<NotifFilter> {
protected NotifFilter(String name) {
@@ -34,7 +34,11 @@ public abstract class NotifFilter extends Pluggable<NotifFilter> {
* This doesn't necessarily mean that your filter will get called on every notification,
* however. If another filter returns true before yours, we'll skip straight to the next notif.
*
- * @param entry The entry in question
+ * @param entry The entry in question.
+ * If this filter is registered via {@link NotifListBuilder#addPreGroupFilter},
+ * this entry will not have any grouping nor sorting information.
+ * If this filter is registered via {@link NotifListBuilder#addPreRenderFilter},
+ * this entry will have grouping and sorting information.
* @param now A timestamp in SystemClock.uptimeMillis that represents "now" for the purposes of
* pipeline execution. This value will be the same for all pluggable calls made
* during this pipeline run, giving pluggables a stable concept of "now" to compare
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifEvent.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifEvent.java
index 3b06220c7c9c..c18af800e183 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifEvent.java
@@ -88,13 +88,14 @@ public class NotifEvent extends RichEvent {
START_BUILD_LIST,
DISPATCH_FINAL_LIST,
LIST_BUILD_COMPLETE,
- FILTER_INVALIDATED,
+ PRE_GROUP_FILTER_INVALIDATED,
PROMOTER_INVALIDATED,
SECTIONS_PROVIDER_INVALIDATED,
COMPARATOR_INVALIDATED,
PARENT_CHANGED,
FILTER_CHANGED,
PROMOTER_CHANGED,
+ PRE_RENDER_FILTER_INVALIDATED,
// NotificationEntryManager events:
NOTIF_ADDED,
@@ -127,6 +128,7 @@ public class NotifEvent extends RichEvent {
"ParentChanged",
"FilterChanged",
"PromoterChanged",
+ "FinalFilterInvalidated",
// NEM event labels:
"NotifAdded",
@@ -152,14 +154,15 @@ public class NotifEvent extends RichEvent {
public static final int START_BUILD_LIST = 2;
public static final int DISPATCH_FINAL_LIST = 3;
public static final int LIST_BUILD_COMPLETE = 4;
- public static final int FILTER_INVALIDATED = 5;
+ public static final int PRE_GROUP_FILTER_INVALIDATED = 5;
public static final int PROMOTER_INVALIDATED = 6;
public static final int SECTIONS_PROVIDER_INVALIDATED = 7;
public static final int COMPARATOR_INVALIDATED = 8;
public static final int PARENT_CHANGED = 9;
public static final int FILTER_CHANGED = 10;
public static final int PROMOTER_CHANGED = 11;
- private static final int TOTAL_LIST_BUILDER_EVENT_TYPES = 12;
+ public static final int PRE_RENDER_FILTER_INVALIDATED = 12;
+ private static final int TOTAL_LIST_BUILDER_EVENT_TYPES = 13;
/**
* Events related to {@link NotificationEntryManager}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
index 77ccf19f65ee..3e1b5bd0571e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
package com.android.systemui.statusbar.notification.logging;
@@ -32,7 +32,7 @@ import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
-import com.android.systemui.UiOffloadThread;
+import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.statusbar.NotificationListener;
@@ -47,6 +47,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.Executor;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -68,7 +69,7 @@ public class NotificationLogger implements StateListener {
// Dependencies:
private final NotificationListenerService mNotificationListener;
- private final UiOffloadThread mUiOffloadThread;
+ private final Executor mUiBgExecutor;
private final NotificationEntryManager mEntryManager;
private HeadsUpManager mHeadsUpManager;
private final ExpansionStateLogger mExpansionStateLogger;
@@ -193,12 +194,12 @@ public class NotificationLogger implements StateListener {
@Inject
public NotificationLogger(NotificationListener notificationListener,
- UiOffloadThread uiOffloadThread,
+ @UiBackground Executor uiBgExecutor,
NotificationEntryManager entryManager,
StatusBarStateController statusBarStateController,
ExpansionStateLogger expansionStateLogger) {
mNotificationListener = notificationListener;
- mUiOffloadThread = uiOffloadThread;
+ mUiBgExecutor = uiBgExecutor;
mEntryManager = entryManager;
mBarService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
@@ -319,7 +320,7 @@ public class NotificationLogger implements StateListener {
final NotificationVisibility[] newlyVisibleAr = cloneVisibilitiesAsArr(newlyVisible);
final NotificationVisibility[] noLongerVisibleAr = cloneVisibilitiesAsArr(noLongerVisible);
- mUiOffloadThread.submit(() -> {
+ mUiBgExecutor.execute(() -> {
try {
mBarService.onNotificationVisibilityChanged(newlyVisibleAr, noLongerVisibleAr);
} catch (RemoteException e) {
@@ -429,13 +430,13 @@ public class NotificationLogger implements StateListener {
* Notification key -> last logged expansion state, should be accessed in UI thread only.
*/
private final Map<String, Boolean> mLoggedExpansionState = new ArrayMap<>();
- private final UiOffloadThread mUiOffloadThread;
+ private final Executor mUiBgExecutor;
@VisibleForTesting
IStatusBarService mBarService;
@Inject
- public ExpansionStateLogger(UiOffloadThread uiOffloadThread) {
- mUiOffloadThread = uiOffloadThread;
+ public ExpansionStateLogger(@UiBackground Executor uiBgExecutor) {
+ mUiBgExecutor = uiBgExecutor;
mBarService =
IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
@@ -513,7 +514,7 @@ public class NotificationLogger implements StateListener {
}
mLoggedExpansionState.put(key, state.mIsExpanded);
final State stateToBeLogged = new State(state);
- mUiOffloadThread.submit(() -> {
+ mUiBgExecutor.execute(() -> {
try {
mBarService.onNotificationExpansionChanged(key, stateToBeLogged.mIsUserAction,
stateToBeLogged.mIsExpanded, stateToBeLogged.mLocation.ordinal());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt
index e9d6a0fcde83..ec1d6deb1b8f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt
@@ -23,7 +23,7 @@ import android.os.Handler
import android.os.UserHandle
import android.provider.Settings
import android.view.View
-import com.android.systemui.dagger.qualifiers.MainHandler
+import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager
import javax.inject.Inject
@@ -164,7 +164,7 @@ private class PeopleHubViewModelFactoryImpl(
@Singleton
class PeopleHubSettingChangeDataSourceImpl @Inject constructor(
- @MainHandler private val handler: Handler,
+ @Main private val handler: Handler,
context: Context
) : DataSource<Boolean> {
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 65423e970cf1..3c247df692f4 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
@@ -17,11 +17,12 @@
package com.android.systemui.statusbar.notification.row;
import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator.ExpandAnimationParameters;
-import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_HEADS_UP;
-import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_PUBLIC;
-import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationCallback;
import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_CONTRACTED;
import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_HEADSUP;
+import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_CONTRACTED;
+import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_EXPANDED;
+import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP;
+import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -88,7 +89,9 @@ import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.logging.NotificationCounters;
-import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
+import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.BindParams;
+import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationCallback;
+import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag;
import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
import com.android.systemui.statusbar.notification.stack.AmbientState;
import com.android.systemui.statusbar.notification.stack.AnimationProperties;
@@ -124,8 +127,18 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
private static final String TAG = "ExpandableNotifRow";
public static final float DEFAULT_HEADER_VISIBLE_AMOUNT = 1.0f;
private static final long RECENTLY_ALERTED_THRESHOLD_MS = TimeUnit.SECONDS.toMillis(30);
+
+ /**
+ * Content views that must be inflated at all times.
+ */
+ @InflationFlag
+ static final int REQUIRED_INFLATION_FLAGS =
+ FLAG_CONTENT_VIEW_CONTRACTED
+ | FLAG_CONTENT_VIEW_EXPANDED;
+
private boolean mUpdateBackgroundOnUpdate;
private boolean mNotificationTranslationFinished = false;
+
/**
* Listener for when {@link ExpandableNotificationRow} is laid out.
*/
@@ -232,6 +245,10 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
private ExpandableNotificationRow mNotificationParent;
private OnExpandClickListener mOnExpandClickListener;
private View.OnClickListener mOnAppOpsClickListener;
+ private InflationCallback mInflationCallback;
+ private boolean mIsChildInGroup;
+ private @InflationFlag int mInflationFlags = REQUIRED_INFLATION_FLAGS;
+ private final BindParams mBindParams = new BindParams();
// Listener will be called when receiving a long click event.
// Use #setLongPressPosition to optionally assign positional data with the long press.
@@ -447,7 +464,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
* Inflate views based off the inflation flags set. Inflation happens asynchronously.
*/
public void inflateViews() {
- mNotificationInflater.inflateNotificationViews();
+ mNotificationInflater.bindContent(mEntry, this, mInflationFlags, mBindParams,
+ false /* forceInflate */, mInflationCallback);
}
/**
@@ -458,9 +476,9 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
*/
public void freeContentViewWhenSafe(@InflationFlag int inflationFlag) {
// View should not be reinflated in the future
- updateInflationFlag(inflationFlag, false);
- Runnable freeViewRunnable = () ->
- mNotificationInflater.freeNotificationView(inflationFlag);
+ clearInflationFlags(inflationFlag);
+ Runnable freeViewRunnable =
+ () -> mNotificationInflater.unbindContent(mEntry, this, inflationFlag);
switch (inflationFlag) {
case FLAG_CONTENT_VIEW_HEADS_UP:
getPrivateLayout().performWhenContentInactive(VISIBLE_TYPE_HEADSUP,
@@ -475,13 +493,22 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
/**
- * Update whether or not a content view should be inflated.
+ * Set flags for content views that should be inflated
*
- * @param flag the flag corresponding to the content view
- * @param shouldInflate true if it should be inflated, false if it should not
+ * @param flags flags to inflate
*/
- public void updateInflationFlag(@InflationFlag int flag, boolean shouldInflate) {
- mNotificationInflater.updateInflationFlag(flag, shouldInflate);
+ public void setInflationFlags(@InflationFlag int flags) {
+ mInflationFlags |= flags;
+ }
+
+ /**
+ * Clear flags for content views that should not be inflated
+ *
+ * @param flags flags that should not be inflated
+ */
+ public void clearInflationFlags(@InflationFlag int flags) {
+ mInflationFlags &= ~flags;
+ mInflationFlags |= REQUIRED_INFLATION_FLAGS;
}
/**
@@ -491,7 +518,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
* @return true if the flag is set, false otherwise
*/
public boolean isInflationFlagSet(@InflationFlag int flag) {
- return mNotificationInflater.isInflationFlagSet(flag);
+ return ((mInflationFlags & flag) != 0);
}
/**
@@ -820,7 +847,15 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
mNotificationParent = isChildInGroup ? parent : null;
mPrivateLayout.setIsChildInGroup(isChildInGroup);
- mNotificationInflater.setIsChildInGroup(isChildInGroup);
+ mBindParams.isChildInGroup = isChildInGroup;
+ if (mIsChildInGroup != isChildInGroup) {
+ mIsChildInGroup = isChildInGroup;
+ if (mIsLowPriority) {
+ int flags = FLAG_CONTENT_VIEW_CONTRACTED | FLAG_CONTENT_VIEW_EXPANDED;
+ mNotificationInflater.bindContent(mEntry, this, flags, mBindParams,
+ false /* forceInflate */, mInflationCallback);
+ }
+ }
resetBackgroundAlpha();
updateBackgroundForGroupState();
updateClickAndFocus();
@@ -1224,7 +1259,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
l.reInflateViews();
}
mEntry.getSbn().clearPackageContext();
- mNotificationInflater.clearCachesAndReInflate();
+ mNotificationInflater.bindContent(mEntry, this, mInflationFlags, mBindParams,
+ true /* forceInflate */, mInflationCallback);
}
@Override
@@ -1578,7 +1614,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
public void setIsLowPriority(boolean isLowPriority) {
mIsLowPriority = isLowPriority;
mPrivateLayout.setIsLowPriority(isLowPriority);
- mNotificationInflater.setIsLowPriority(mIsLowPriority);
+ mBindParams.isLowPriority = mIsLowPriority;
if (mChildrenContainer != null) {
mChildrenContainer.setIsLowPriority(isLowPriority);
}
@@ -1590,28 +1626,36 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
public void setUseIncreasedCollapsedHeight(boolean use) {
mUseIncreasedCollapsedHeight = use;
- mNotificationInflater.setUsesIncreasedHeight(use);
+ mBindParams.usesIncreasedHeight = use;
}
public void setUseIncreasedHeadsUpHeight(boolean use) {
mUseIncreasedHeadsUpHeight = use;
- mNotificationInflater.setUsesIncreasedHeadsUpHeight(use);
+ mBindParams.usesIncreasedHeadsUpHeight = use;
}
public void setRemoteViewClickHandler(RemoteViews.OnClickHandler remoteViewClickHandler) {
mNotificationInflater.setRemoteViewClickHandler(remoteViewClickHandler);
}
+ /**
+ * Set callback for notification content inflation
+ *
+ * @param callback inflation callback
+ */
public void setInflationCallback(InflationCallback callback) {
- mNotificationInflater.setInflationCallback(callback);
+ mInflationCallback = callback;
}
public void setNeedsRedaction(boolean needsRedaction) {
if (mNeedsRedaction != needsRedaction) {
mNeedsRedaction = needsRedaction;
- updateInflationFlag(FLAG_CONTENT_VIEW_PUBLIC, needsRedaction /* shouldInflate */);
- mNotificationInflater.updateNeedsRedaction(needsRedaction);
- if (!needsRedaction) {
+ if (needsRedaction) {
+ setInflationFlags(FLAG_CONTENT_VIEW_PUBLIC);
+ mNotificationInflater.bindContent(mEntry, this, FLAG_CONTENT_VIEW_PUBLIC,
+ mBindParams, false /* forceInflate */, mInflationCallback);
+ } else {
+ clearInflationFlags(FLAG_CONTENT_VIEW_PUBLIC);
freeContentViewWhenSafe(FLAG_CONTENT_VIEW_PUBLIC);
}
}
@@ -1628,7 +1672,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
public ExpandableNotificationRow(Context context, AttributeSet attrs) {
super(context, attrs);
- mNotificationInflater = new NotificationContentInflater(this);
+ mNotificationInflater = new NotificationContentInflater();
mMenuRow = new NotificationMenuRow(mContext);
mImageResolver = new NotificationInlineImageResolver(context,
new NotificationInlineImageCache());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
index 54dee8c32940..172b72e9b0fc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
@@ -19,7 +19,7 @@ package com.android.systemui.statusbar.notification.row;
import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_CONTRACTED;
import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_HEADSUP;
-import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Notification;
import android.content.Context;
@@ -47,205 +47,55 @@ import com.android.systemui.statusbar.policy.InflatedSmartReplies.SmartRepliesAn
import com.android.systemui.statusbar.policy.SmartReplyConstants;
import com.android.systemui.util.Assert;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
import java.util.HashMap;
/**
- * A utility that inflates the right kind of contentView based on the state
+ * {@link NotificationContentInflater} binds content to a {@link ExpandableNotificationRow} by
+ * asynchronously building the content's {@link RemoteViews} and applying it to the row.
*/
-public class NotificationContentInflater {
+public class NotificationContentInflater implements NotificationRowContentBinder {
public static final String TAG = "NotifContentInflater";
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(flag = true,
- prefix = {"FLAG_CONTENT_VIEW_"},
- value = {
- FLAG_CONTENT_VIEW_CONTRACTED,
- FLAG_CONTENT_VIEW_EXPANDED,
- FLAG_CONTENT_VIEW_HEADS_UP,
- FLAG_CONTENT_VIEW_PUBLIC,
- FLAG_CONTENT_VIEW_ALL})
- public @interface InflationFlag {}
- /**
- * The default, contracted view. Seen when the shade is pulled down and in the lock screen
- * if there is no worry about content sensitivity.
- */
- public static final int FLAG_CONTENT_VIEW_CONTRACTED = 1;
-
- /**
- * The expanded view. Seen when the user expands a notification.
- */
- public static final int FLAG_CONTENT_VIEW_EXPANDED = 1 << 1;
-
- /**
- * The heads up view. Seen when a high priority notification peeks in from the top.
- */
- public static final int FLAG_CONTENT_VIEW_HEADS_UP = 1 << 2;
-
- /**
- * The public view. This is a version of the contracted view that hides sensitive
- * information and is used on the lock screen if we determine that the notification's
- * content should be hidden.
- */
- public static final int FLAG_CONTENT_VIEW_PUBLIC = 1 << 3;
-
- public static final int FLAG_CONTENT_VIEW_ALL = ~0;
-
- /**
- * Content views that must be inflated at all times.
- */
- @InflationFlag
- private static final int REQUIRED_INFLATION_FLAGS =
- FLAG_CONTENT_VIEW_CONTRACTED
- | FLAG_CONTENT_VIEW_EXPANDED;
-
- /**
- * The set of content views to inflate.
- */
- @InflationFlag
- private int mInflationFlags = REQUIRED_INFLATION_FLAGS;
-
- private final ExpandableNotificationRow mRow;
- private boolean mIsLowPriority;
- private boolean mUsesIncreasedHeight;
- private boolean mUsesIncreasedHeadsUpHeight;
private RemoteViews.OnClickHandler mRemoteViewClickHandler;
- private boolean mIsChildInGroup;
- private InflationCallback mCallback;
private boolean mInflateSynchronously = false;
private final ArrayMap<Integer, RemoteViews> mCachedContentViews = new ArrayMap<>();
- public NotificationContentInflater(ExpandableNotificationRow row) {
- mRow = row;
- }
-
- public void setIsLowPriority(boolean isLowPriority) {
- mIsLowPriority = isLowPriority;
- }
-
- /**
- * Set whether the notification is a child in a group
- *
- * @return whether the view was re-inflated
- */
- public void setIsChildInGroup(boolean childInGroup) {
- if (childInGroup != mIsChildInGroup) {
- mIsChildInGroup = childInGroup;
- if (mIsLowPriority) {
- int flags = FLAG_CONTENT_VIEW_CONTRACTED | FLAG_CONTENT_VIEW_EXPANDED;
- inflateNotificationViews(flags);
- }
- }
- }
-
- public void setUsesIncreasedHeight(boolean usesIncreasedHeight) {
- mUsesIncreasedHeight = usesIncreasedHeight;
- }
-
- public void setUsesIncreasedHeadsUpHeight(boolean usesIncreasedHeight) {
- mUsesIncreasedHeadsUpHeight = usesIncreasedHeight;
- }
-
- public void setRemoteViewClickHandler(RemoteViews.OnClickHandler remoteViewClickHandler) {
- mRemoteViewClickHandler = remoteViewClickHandler;
- }
-
- /**
- * Update whether or not the notification is redacted on the lock screen. If the notification
- * is now redacted, we should inflate the public contracted view to now show on the lock screen.
- *
- * @param needsRedaction true if the notification should now be redacted on the lock screen
- */
- public void updateNeedsRedaction(boolean needsRedaction) {
- if (mRow.getEntry() == null) {
- return;
- }
- if (needsRedaction) {
- int flags = FLAG_CONTENT_VIEW_PUBLIC;
- inflateNotificationViews(flags);
- }
- }
-
- /**
- * Set whether or not a particular content view is needed and whether or not it should be
- * inflated. These flags will be used when we inflate or reinflate.
- *
- * @param flag the {@link InflationFlag} corresponding to the view that should/should not be
- * inflated
- * @param shouldInflate true if the view should be inflated, false otherwise
- */
- public void updateInflationFlag(@InflationFlag int flag, boolean shouldInflate) {
- if (shouldInflate) {
- mInflationFlags |= flag;
- } else if ((REQUIRED_INFLATION_FLAGS & flag) == 0) {
- mInflationFlags &= ~flag;
- }
- }
-
- /**
- * Convenience method for setting multiple flags at once.
- *
- * @param flags a set of {@link InflationFlag} corresponding to content views that should be
- * inflated
- */
- @VisibleForTesting
- public void addInflationFlags(@InflationFlag int flags) {
- mInflationFlags |= flags;
- }
-
- /**
- * Whether or not the view corresponding to the flag is set to be inflated currently.
- *
- * @param flag the {@link InflationFlag} corresponding to the view
- * @return true if the flag is set and view will be inflated, false o/w
- */
- public boolean isInflationFlagSet(@InflationFlag int flag) {
- return ((mInflationFlags & flag) != 0);
- }
-
- /**
- * Inflate views for set flags on a background thread. This is asynchronous and will
- * notify the callback once it's finished.
- */
- public void inflateNotificationViews() {
- inflateNotificationViews(mInflationFlags);
- }
-
- /**
- * Inflate all views for the specified flags on a background thread. This is asynchronous and
- * will notify the callback once it's finished. If the content view is already inflated, this
- * will reinflate it.
- *
- * @param reInflateFlags flags which views should be inflated. Should be a subset of
- * {@link #mInflationFlags} as only those will be inflated/reinflated.
- */
- private void inflateNotificationViews(@InflationFlag int reInflateFlags) {
- if (mRow.isRemoved()) {
+ @Override
+ public void bindContent(
+ NotificationEntry entry,
+ ExpandableNotificationRow row,
+ @InflationFlag int contentToBind,
+ BindParams bindParams,
+ boolean forceInflate,
+ @Nullable InflationCallback callback) {
+ if (row.isRemoved()) {
// We don't want to reinflate anything for removed notifications. Otherwise views might
// be readded to the stack, leading to leaks. This may happen with low-priority groups
// where the removal of already removed children can lead to a reinflation.
return;
}
- // Only inflate the ones that are set.
- reInflateFlags &= mInflationFlags;
- StatusBarNotification sbn = mRow.getEntry().getSbn();
+
+ StatusBarNotification sbn = row.getEntry().getSbn();
// To check if the notification has inline image and preload inline image if necessary.
- mRow.getImageResolver().preloadImages(sbn.getNotification());
+ row.getImageResolver().preloadImages(sbn.getNotification());
+
+ if (forceInflate) {
+ mCachedContentViews.clear();
+ }
AsyncInflationTask task = new AsyncInflationTask(
sbn,
mInflateSynchronously,
- reInflateFlags,
+ contentToBind,
mCachedContentViews,
- mRow,
- mIsLowPriority,
- mIsChildInGroup,
- mUsesIncreasedHeight,
- mUsesIncreasedHeadsUpHeight,
- mCallback,
+ row,
+ bindParams.isLowPriority,
+ bindParams.isChildInGroup,
+ bindParams.usesIncreasedHeight,
+ bindParams.usesIncreasedHeadsUpHeight,
+ callback,
mRemoteViewClickHandler);
if (mInflateSynchronously) {
task.onPostExecute(task.doInBackground());
@@ -256,49 +106,84 @@ public class NotificationContentInflater {
@VisibleForTesting
InflationProgress inflateNotificationViews(
+ NotificationEntry entry,
+ ExpandableNotificationRow row,
+ BindParams bindParams,
boolean inflateSynchronously,
@InflationFlag int reInflateFlags,
Notification.Builder builder,
Context packageContext) {
- InflationProgress result = createRemoteViews(reInflateFlags, builder, mIsLowPriority,
- mIsChildInGroup, mUsesIncreasedHeight, mUsesIncreasedHeadsUpHeight,
+ InflationProgress result = createRemoteViews(reInflateFlags,
+ builder,
+ bindParams.isLowPriority,
+ bindParams.isChildInGroup,
+ bindParams.usesIncreasedHeight,
+ bindParams.usesIncreasedHeadsUpHeight,
packageContext);
- result = inflateSmartReplyViews(result, reInflateFlags, mRow.getEntry(),
- mRow.getContext(), packageContext, mRow.getHeadsUpManager(),
- mRow.getExistingSmartRepliesAndActions());
+ result = inflateSmartReplyViews(result, reInflateFlags, entry,
+ row.getContext(), packageContext, row.getHeadsUpManager(),
+ row.getExistingSmartRepliesAndActions());
apply(
inflateSynchronously,
result,
reInflateFlags,
mCachedContentViews,
- mRow,
+ row,
mRemoteViewClickHandler,
null);
return result;
}
+ @Override
+ public void cancelBind(
+ @NonNull NotificationEntry entry,
+ @NonNull ExpandableNotificationRow row) {
+ entry.abortTask();
+ }
+
+ @Override
+ public void unbindContent(
+ @NonNull NotificationEntry entry,
+ @NonNull ExpandableNotificationRow row,
+ @InflationFlag int contentToUnbind) {
+ int curFlag = 1;
+ while (contentToUnbind != 0) {
+ if ((contentToUnbind & curFlag) != 0) {
+ freeNotificationView(row, curFlag);
+ }
+ contentToUnbind &= ~curFlag;
+ curFlag = curFlag << 1;
+ }
+ }
+
+ /**
+ * Set click handler for notification remote views
+ *
+ * @param remoteViewClickHandler click handler for remote views
+ */
+ public void setRemoteViewClickHandler(RemoteViews.OnClickHandler remoteViewClickHandler) {
+ mRemoteViewClickHandler = remoteViewClickHandler;
+ }
+
/**
* Frees the content view associated with the inflation flag. Will only succeed if the
* view is safe to remove.
*
* @param inflateFlag the flag corresponding to the content view which should be freed
*/
- public void freeNotificationView(@InflationFlag int inflateFlag) {
- if ((mInflationFlags & inflateFlag) != 0) {
- // The view should still be inflated.
- return;
- }
+ private void freeNotificationView(ExpandableNotificationRow row,
+ @InflationFlag int inflateFlag) {
switch (inflateFlag) {
case FLAG_CONTENT_VIEW_HEADS_UP:
- if (mRow.getPrivateLayout().isContentViewInactive(VISIBLE_TYPE_HEADSUP)) {
- mRow.getPrivateLayout().setHeadsUpChild(null);
+ if (row.getPrivateLayout().isContentViewInactive(VISIBLE_TYPE_HEADSUP)) {
+ row.getPrivateLayout().setHeadsUpChild(null);
mCachedContentViews.remove(FLAG_CONTENT_VIEW_HEADS_UP);
- mRow.getPrivateLayout().setHeadsUpInflatedSmartReplies(null);
+ row.getPrivateLayout().setHeadsUpInflatedSmartReplies(null);
}
break;
case FLAG_CONTENT_VIEW_PUBLIC:
- if (mRow.getPublicLayout().isContentViewInactive(VISIBLE_TYPE_CONTRACTED)) {
- mRow.getPublicLayout().setContractedChild(null);
+ if (row.getPublicLayout().isContentViewInactive(VISIBLE_TYPE_CONTRACTED)) {
+ row.getPublicLayout().setContractedChild(null);
mCachedContentViews.remove(FLAG_CONTENT_VIEW_PUBLIC);
}
break;
@@ -718,33 +603,12 @@ public class NotificationContentInflater {
&& !oldView.hasFlags(RemoteViews.FLAG_REAPPLY_DISALLOWED));
}
- public void setInflationCallback(InflationCallback callback) {
- mCallback = callback;
- }
-
- public interface InflationCallback {
- void handleInflationException(StatusBarNotification notification, Exception e);
-
- /**
- * Callback for after the content views finish inflating.
- *
- * @param entry the entry with the content views set
- * @param inflatedFlags the flags associated with the content views that were inflated
- */
- void onAsyncInflationFinished(NotificationEntry entry, @InflationFlag int inflatedFlags);
- }
-
- public void clearCachesAndReInflate() {
- mCachedContentViews.clear();
- inflateNotificationViews();
- }
-
/**
* Sets whether to perform inflation on the same thread as the caller. This method should only
* be used in tests, not in production.
*/
@VisibleForTesting
- void setInflateSynchronously(boolean inflateSynchronously) {
+ public void setInflateSynchronously(boolean inflateSynchronously) {
mInflateSynchronously = inflateSynchronously;
}
@@ -842,8 +706,10 @@ public class NotificationContentInflater {
final String ident = sbn.getPackageName() + "/0x"
+ Integer.toHexString(sbn.getId());
Log.e(StatusBar.TAG, "couldn't inflate view for notification " + ident, e);
- mCallback.handleInflationException(sbn,
- new InflationException("Couldn't inflate contentViews" + e));
+ if (mCallback != null) {
+ mCallback.handleInflationException(sbn,
+ new InflationException("Couldn't inflate contentViews" + e));
+ }
}
@Override
@@ -872,7 +738,9 @@ public class NotificationContentInflater {
@InflationFlag int inflatedFlags) {
mRow.getEntry().onInflationTaskFinished();
mRow.onNotificationUpdated();
- mCallback.onAsyncInflationFinished(mRow.getEntry(), inflatedFlags);
+ if (mCallback != null) {
+ mCallback.onAsyncInflationFinished(mRow.getEntry(), inflatedFlags);
+ }
// Notify the resolver that the inflation task has finished,
// try to purge unnecessary cached entries.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index 9dd7f48086c9..6f2abba128d6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -42,7 +42,7 @@ import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationLifetimeExtender;
@@ -108,7 +108,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
@Inject
public NotificationGutsManager(Context context, VisualStabilityManager visualStabilityManager,
- Lazy<StatusBar> statusBarLazy, @MainHandler Handler mainHandler,
+ Lazy<StatusBar> statusBarLazy, @Main Handler mainHandler,
AccessibilityManager accessibilityManager) {
mContext = context;
mVisualStabilityManager = visualStabilityManager;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinder.java
new file mode 100644
index 000000000000..2fe54c00bb06
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinder.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.row;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.service.notification.StatusBarNotification;
+
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Binder that takes a notifications {@link ExpandableNotificationRow} and binds the appropriate
+ * content to it based off the bind parameters passed to it.
+ */
+public interface NotificationRowContentBinder {
+
+ /**
+ * Inflate notification content views and bind to the row.
+ *
+ * @param entry notification
+ * @param row notification row to bind views to
+ * @param contentToBind content views that should be inflated and bound
+ * @param bindParams parameters for binding content views
+ * @param forceInflate true to force reinflation even if views are cached
+ * @param callback callback after inflation is finished
+ */
+ void bindContent(
+ @NonNull NotificationEntry entry,
+ @NonNull ExpandableNotificationRow row,
+ @InflationFlag int contentToBind,
+ BindParams bindParams,
+ boolean forceInflate,
+ @Nullable InflationCallback callback);
+
+ /**
+ * Cancel any on-going bind operation.
+ *
+ * @param entry notification
+ * @param row notification row to cancel bind on
+ */
+ void cancelBind(
+ @NonNull NotificationEntry entry,
+ @NonNull ExpandableNotificationRow row);
+
+ /**
+ * Unbind content views from the row.
+ *
+ * @param entry notification
+ * @param row notification row to unbind content views from
+ * @param contentToUnbind content views that should be unbound
+ */
+ void unbindContent(
+ @NonNull NotificationEntry entry,
+ @NonNull ExpandableNotificationRow row,
+ @InflationFlag int contentToUnbind);
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = true,
+ prefix = {"FLAG_CONTENT_VIEW_"},
+ value = {
+ FLAG_CONTENT_VIEW_CONTRACTED,
+ FLAG_CONTENT_VIEW_EXPANDED,
+ FLAG_CONTENT_VIEW_HEADS_UP,
+ FLAG_CONTENT_VIEW_PUBLIC,
+ FLAG_CONTENT_VIEW_ALL})
+ @interface InflationFlag {}
+ /**
+ * The default, contracted view. Seen when the shade is pulled down and in the lock screen
+ * if there is no worry about content sensitivity.
+ */
+ int FLAG_CONTENT_VIEW_CONTRACTED = 1;
+ /**
+ * The expanded view. Seen when the user expands a notification.
+ */
+ int FLAG_CONTENT_VIEW_EXPANDED = 1 << 1;
+ /**
+ * The heads up view. Seen when a high priority notification peeks in from the top.
+ */
+ int FLAG_CONTENT_VIEW_HEADS_UP = 1 << 2;
+ /**
+ * The public view. This is a version of the contracted view that hides sensitive
+ * information and is used on the lock screen if we determine that the notification's
+ * content should be hidden.
+ */
+ int FLAG_CONTENT_VIEW_PUBLIC = 1 << 3;
+
+ int FLAG_CONTENT_VIEW_ALL = ~0;
+
+ /**
+ * Parameters for content view binding
+ */
+ class BindParams {
+
+ /**
+ * Bind a low priority version of the content views.
+ */
+ public boolean isLowPriority;
+
+ /**
+ * Bind child version of content views.
+ */
+ public boolean isChildInGroup;
+
+ /**
+ * Use increased height when binding contracted view.
+ */
+ public boolean usesIncreasedHeight;
+
+ /**
+ * Use increased height when binding heads up views.
+ */
+ public boolean usesIncreasedHeadsUpHeight;
+ }
+
+ /**
+ * Callback for inflation finishing
+ */
+ interface InflationCallback {
+
+ /**
+ * Callback for when there is an inflation exception
+ *
+ * @param notification notification which failed to inflate content
+ * @param e exception
+ */
+ void handleInflationException(StatusBarNotification notification, Exception e);
+
+ /**
+ * Callback for after the content views finish inflating.
+ *
+ * @param entry the entry with the content views set
+ * @param inflatedFlags the flags associated with the content views that were inflated
+ */
+ void onAsyncInflationFinished(NotificationEntry entry,
+ @InflationFlag int inflatedFlags);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java
index 90ea6e344226..0a1a2fe3ee54 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
package com.android.systemui.statusbar.notification.row.wrapper;
@@ -244,17 +244,18 @@ public class NotificationTemplateViewWrapper extends NotificationHeaderViewWrapp
mUiOffloadThread = Dependency.get(UiOffloadThread.class);
}
if (view.isAttachedToWindow()) {
- mUiOffloadThread.submit(() -> pendingIntent.registerCancelListener(listener));
+ mUiOffloadThread.execute(() -> pendingIntent.registerCancelListener(listener));
}
view.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
@Override
public void onViewAttachedToWindow(View v) {
- mUiOffloadThread.submit(() -> pendingIntent.registerCancelListener(listener));
+ mUiOffloadThread.execute(() -> pendingIntent.registerCancelListener(listener));
}
@Override
public void onViewDetachedFromWindow(View v) {
- mUiOffloadThread.submit(() -> pendingIntent.unregisterCancelListener(listener));
+ mUiOffloadThread.execute(
+ () -> pendingIntent.unregisterCancelListener(listener));
}
});
}
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 f9b936763308..3165597d4b9b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java
@@ -23,7 +23,7 @@ import android.util.Log;
import android.view.IWindowManager;
import android.view.MotionEvent;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import javax.inject.Inject;
@@ -52,7 +52,7 @@ public class AutoHideController {
};
@Inject
- public AutoHideController(Context context, @MainHandler Handler handler,
+ public AutoHideController(Context context, @Main Handler handler,
NotificationRemoteInputManager notificationRemoteInputManager,
IWindowManager iWindowManager) {
mHandler = handler;
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 837517e2cc9b..0680c7f70b97 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
@@ -21,7 +21,7 @@ import android.os.Handler;
import android.provider.Settings.Secure;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.dagger.qualifiers.BgHandler;
+import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.qs.AutoAddTracker;
import com.android.systemui.qs.QSTileHost;
import com.android.systemui.qs.SecureSetting;
@@ -57,7 +57,7 @@ public class AutoTileManager {
@Inject
public AutoTileManager(Context context, AutoAddTracker autoAddTracker, QSTileHost host,
- @BgHandler Handler handler,
+ @Background Handler handler,
HotspotController hotspotController,
DataSaverController dataSaverController,
ManagedProfileController managedProfileController,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
index 250f7300ba56..48805204160f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -37,7 +37,7 @@ import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.Dependency;
import com.android.systemui.DumpController;
import com.android.systemui.Dumpable;
-import com.android.systemui.dagger.qualifiers.MainResources;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.keyguard.WakefulnessLifecycle;
@@ -165,7 +165,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
StatusBarWindowController statusBarWindowController,
KeyguardStateController keyguardStateController, Handler handler,
KeyguardUpdateMonitor keyguardUpdateMonitor,
- @MainResources Resources resources,
+ @Main Resources resources,
KeyguardBypassController keyguardBypassController, DozeParameters dozeParameters,
MetricsLogger metricsLogger, DumpController dumpController) {
mContext = context;
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 bc482353753d..f5999f5c8294 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -25,7 +25,7 @@ import android.provider.Settings;
import android.util.MathUtils;
import com.android.systemui.R;
-import com.android.systemui.dagger.qualifiers.MainResources;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.doze.AlwaysOnDisplayPolicy;
import com.android.systemui.doze.DozeScreenState;
import com.android.systemui.tuner.TunerService;
@@ -58,7 +58,7 @@ public class DozeParameters implements TunerService.Tunable,
@Inject
protected DozeParameters(
- @MainResources Resources resources,
+ @Main Resources resources,
AmbientDisplayConfiguration ambientDisplayConfiguration,
AlwaysOnDisplayPolicy alwaysOnDisplayPolicy,
PowerManager powerManager,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
index 66b1dd8db123..858023dc6c62 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
@@ -101,7 +101,8 @@ public class KeyguardAffordanceHelper {
R.dimen.keyguard_affordance_touch_target_size);
mHintGrowAmount =
mContext.getResources().getDimensionPixelSize(R.dimen.hint_grow_amount_sideways);
- mFlingAnimationUtils = new FlingAnimationUtils(mContext, 0.4f);
+ mFlingAnimationUtils = new FlingAnimationUtils(mContext.getResources().getDisplayMetrics(),
+ 0.4f);
}
private void initIcons() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java
index 12819535cfb6..8c3420a522ec 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java
@@ -35,8 +35,6 @@ import javax.inject.Singleton;
@Singleton
public class LockscreenGestureLogger {
private ArrayMap<Integer, Integer> mLegacyMap;
- private LogMaker mLogMaker = new LogMaker(MetricsEvent.VIEW_UNKNOWN)
- .setType(MetricsEvent.TYPE_ACTION);
private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
@Inject
@@ -48,7 +46,7 @@ public class LockscreenGestureLogger {
}
public void write(int gesture, int length, int velocity) {
- mMetricsLogger.write(mLogMaker.setCategory(gesture)
+ mMetricsLogger.write(new LogMaker(gesture)
.setType(MetricsEvent.TYPE_ACTION)
.addTaggedData(MetricsEvent.FIELD_GESTURE_LENGTH, length)
.addTaggedData(MetricsEvent.FIELD_GESTURE_VELOCITY, velocity));
@@ -64,7 +62,7 @@ public class LockscreenGestureLogger {
*/
public void writeAtFractionalPosition(
int category, int xPercent, int yPercent, int rotation) {
- mMetricsLogger.write(mLogMaker.setCategory(category)
+ mMetricsLogger.write(new LogMaker(category)
.setType(MetricsEvent.TYPE_ACTION)
.addTaggedData(MetricsEvent.FIELD_GESTURE_X_PERCENT, xPercent)
.addTaggedData(MetricsEvent.FIELD_GESTURE_Y_PERCENT, yPercent)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
index 183adeb037d6..4ee13bf754dd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
@@ -43,7 +43,7 @@ import com.android.internal.util.IndentingPrintWriter;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.DumpController;
import com.android.systemui.Dumpable;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.statusbar.NotificationMediaManager;
import libcore.io.IoUtils;
@@ -83,7 +83,7 @@ public class LockscreenWallpaper extends IWallpaperManagerCallback.Stub implemen
KeyguardUpdateMonitor keyguardUpdateMonitor,
DumpController dumpController,
NotificationMediaManager mediaManager,
- @MainHandler Handler mainHandler) {
+ @Main Handler mainHandler) {
dumpController.registerDumpable(getClass().getSimpleName(), this);
mWallpaperManager = wallpaperManager;
mCurrentUserId = ActivityManager.getCurrentUser();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index ebe211754b2b..d4cf272e8077 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -93,7 +93,7 @@ import com.android.systemui.R;
import com.android.systemui.assist.AssistHandleViewController;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
import com.android.systemui.model.SysUiState;
@@ -274,7 +274,7 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
CommandQueue commandQueue, Divider divider,
Optional<Recents> recentsOptional, Lazy<StatusBar> statusBarLazy,
ShadeController shadeController,
- @MainHandler Handler mainHandler) {
+ @Main Handler mainHandler) {
mAccessibilityManagerWrapper = accessibilityManagerWrapper;
mDeviceProvisionedController = deviceProvisionedController;
mStatusBarStateController = statusBarStateController;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java
index 1df9411019d2..d6336ed3e18a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java
@@ -53,7 +53,7 @@ import android.util.Log;
import android.util.SparseBooleanArray;
import com.android.systemui.Dumpable;
-import com.android.systemui.UiOffloadThread;
+import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
@@ -61,6 +61,7 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.concurrent.Executor;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -82,7 +83,7 @@ public class NavigationModeController implements Dumpable {
private Context mCurrentUserContext;
private final IOverlayManager mOverlayManager;
private final DeviceProvisionedController mDeviceProvisionedController;
- private final UiOffloadThread mUiOffloadThread;
+ private final Executor mUiBgExecutor;
private SparseBooleanArray mRestoreGesturalNavBarMode = new SparseBooleanArray();
@@ -146,12 +147,12 @@ public class NavigationModeController implements Dumpable {
@Inject
public NavigationModeController(Context context,
DeviceProvisionedController deviceProvisionedController,
- UiOffloadThread uiOffloadThread) {
+ @UiBackground Executor uiBgExecutor) {
mContext = context;
mCurrentUserContext = context;
mOverlayManager = IOverlayManager.Stub.asInterface(
ServiceManager.getService(Context.OVERLAY_SERVICE));
- mUiOffloadThread = uiOffloadThread;
+ mUiBgExecutor = uiBgExecutor;
mDeviceProvisionedController = deviceProvisionedController;
mDeviceProvisionedController.addCallback(mDeviceProvisionedCallback);
@@ -242,7 +243,7 @@ public class NavigationModeController implements Dumpable {
mCurrentUserContext = getCurrentUserContext();
int mode = getCurrentInteractionMode(mCurrentUserContext);
mMode = mode;
- mUiOffloadThread.submit(() -> {
+ mUiBgExecutor.execute(() -> {
Settings.Secure.putString(mCurrentUserContext.getContentResolver(),
Secure.NAVIGATION_MODE, String.valueOf(mode));
});
@@ -379,7 +380,7 @@ public class NavigationModeController implements Dumpable {
}
public void setModeOverlay(String overlayPkg, int userId) {
- mUiOffloadThread.submit(() -> {
+ mUiBgExecutor.execute(() -> {
try {
mOverlayManager.setEnabledExclusiveInCategory(overlayPkg, userId);
if (DEBUG) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java
index 2798285c073d..fe0739f9088c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java
@@ -33,7 +33,7 @@ import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.NotificationContentInflater.AsyncInflationTask;
-import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
+import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag;
import com.android.systemui.statusbar.phone.NotificationGroupManager.NotificationGroup;
import com.android.systemui.statusbar.phone.NotificationGroupManager.OnGroupChangeListener;
import com.android.systemui.statusbar.policy.HeadsUpManager;
@@ -395,7 +395,7 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis
@InflationFlag int contentFlag = alertManager.getContentFlag();
if (!entry.getRow().isInflationFlagSet(contentFlag)) {
mPendingAlerts.put(entry.getKey(), new PendingAlertInfo(entry));
- entry.getRow().updateInflationFlag(contentFlag, true /* shouldInflate */);
+ entry.getRow().setInflationFlags(contentFlag);
entry.getRow().inflateViews();
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index ed2fb0fdcb1a..199d52f76c93 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -609,7 +609,7 @@ public class NotificationPanelView extends PanelView implements
@Override
protected void loadDimens() {
super.loadDimens();
- mFlingAnimationUtils = new FlingAnimationUtils(getContext(), 0.4f);
+ mFlingAnimationUtils = new FlingAnimationUtils(getResources().getDisplayMetrics(), 0.4f);
mStatusBarMinHeight = getResources().getDimensionPixelSize(
com.android.internal.R.dimen.status_bar_height);
mQsPeekHeight = getResources().getDimensionPixelSize(R.dimen.qs_peek_height);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index e8e5e1f60c51..78a5eb237297 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -26,6 +26,7 @@ import android.content.res.Resources;
import android.os.SystemClock;
import android.os.VibrationEffect;
import android.util.AttributeSet;
+import android.util.DisplayMetrics;
import android.util.Log;
import android.view.InputDevice;
import android.view.MotionEvent;
@@ -208,11 +209,12 @@ public abstract class PanelView extends FrameLayout {
super(context, attrs);
mKeyguardStateController = keyguardStateController;
mStatusBarStateController = statusBarStateController;
- mFlingAnimationUtils = new FlingAnimationUtils(context, 0.6f /* maxLengthSeconds */,
- 0.6f /* speedUpFactor */);
- mFlingAnimationUtilsClosing = new FlingAnimationUtils(context, 0.5f /* maxLengthSeconds */,
- 0.6f /* speedUpFactor */);
- mFlingAnimationUtilsDismissing = new FlingAnimationUtils(context,
+ DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
+ mFlingAnimationUtils = new FlingAnimationUtils(displayMetrics,
+ 0.6f /* maxLengthSeconds */, 0.6f /* speedUpFactor */);
+ mFlingAnimationUtilsClosing = new FlingAnimationUtils(displayMetrics,
+ 0.5f /* maxLengthSeconds */, 0.6f /* speedUpFactor */);
+ mFlingAnimationUtilsDismissing = new FlingAnimationUtils(displayMetrics,
0.5f /* maxLengthSeconds */, 0.2f /* speedUpFactor */, 0.6f /* x2 */,
0.84f /* y2 */);
mBounceInterpolator = new BounceInterpolator();
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 8d43c6666773..5b34aa7781c1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -37,12 +37,11 @@ import android.telephony.TelephonyManager;
import android.text.format.DateFormat;
import android.util.Log;
-import com.android.internal.telephony.IccCardConstants;
import com.android.internal.telephony.TelephonyIntents;
import com.android.systemui.Dependency;
import com.android.systemui.R;
-import com.android.systemui.UiOffloadThread;
import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.qs.tiles.DndTile;
import com.android.systemui.qs.tiles.RotationLockTile;
import com.android.systemui.statusbar.CommandQueue;
@@ -64,6 +63,7 @@ import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.ZenModeController;
import java.util.Locale;
+import java.util.concurrent.Executor;
/**
* This class contains all of the policy about which icons are installed in the status bar at boot
@@ -115,7 +115,7 @@ public class PhoneStatusBarPolicy
private final DeviceProvisionedController mProvisionedController;
private final KeyguardStateController mKeyguardStateController;
private final LocationController mLocationController;
- private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
+ private final Executor mUiBgExecutor;
private final SensorPrivacyController mSensorPrivacyController;
// Assume it's all good unless we hear otherwise. We don't always seem
@@ -132,7 +132,8 @@ public class PhoneStatusBarPolicy
private AlarmManager.AlarmClockInfo mNextAlarm;
public PhoneStatusBarPolicy(Context context, StatusBarIconController iconController,
- CommandQueue commandQueue, BroadcastDispatcher broadcastDispatcher) {
+ CommandQueue commandQueue, BroadcastDispatcher broadcastDispatcher,
+ @UiBackground Executor uiBgExecutor) {
mContext = context;
mIconController = iconController;
mCast = Dependency.get(CastController.class);
@@ -149,6 +150,7 @@ public class PhoneStatusBarPolicy
mKeyguardStateController = Dependency.get(KeyguardStateController.class);
mLocationController = Dependency.get(LocationController.class);
mSensorPrivacyController = Dependency.get(SensorPrivacyController.class);
+ mUiBgExecutor = uiBgExecutor;
mSlotCast = context.getString(com.android.internal.R.string.status_bar_cast);
mSlotHotspot = context.getString(com.android.internal.R.string.status_bar_hotspot);
@@ -289,21 +291,21 @@ public class PhoneStatusBarPolicy
}
private final void updateSimState(Intent intent) {
- String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
- if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
+ String stateExtra = intent.getStringExtra(Intent.EXTRA_SIM_STATE);
+ if (Intent.SIM_STATE_ABSENT.equals(stateExtra)) {
mSimState = TelephonyManager.SIM_STATE_READY;
- } else if (IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR.equals(stateExtra)) {
+ } else if (Intent.SIM_STATE_CARD_IO_ERROR.equals(stateExtra)) {
mSimState = TelephonyManager.SIM_STATE_CARD_IO_ERROR;
- } else if (IccCardConstants.INTENT_VALUE_ICC_CARD_RESTRICTED.equals(stateExtra)) {
+ } else if (Intent.SIM_STATE_CARD_RESTRICTED.equals(stateExtra)) {
mSimState = TelephonyManager.SIM_STATE_CARD_RESTRICTED;
- } else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
+ } else if (Intent.SIM_STATE_READY.equals(stateExtra)) {
mSimState = TelephonyManager.SIM_STATE_READY;
- } else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
+ } else if (Intent.SIM_STATE_LOCKED.equals(stateExtra)) {
final String lockedReason =
- intent.getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
- if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
+ intent.getStringExtra(Intent.EXTRA_SIM_LOCKED_REASON);
+ if (Intent.SIM_LOCKED_ON_PIN.equals(lockedReason)) {
mSimState = TelephonyManager.SIM_STATE_PIN_REQUIRED;
- } else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
+ } else if (Intent.SIM_LOCKED_ON_PUK.equals(lockedReason)) {
mSimState = TelephonyManager.SIM_STATE_PUK_REQUIRED;
} else {
mSimState = TelephonyManager.SIM_STATE_NETWORK_LOCKED;
@@ -385,8 +387,11 @@ public class PhoneStatusBarPolicy
mContext.getString(R.string.accessibility_quick_settings_bluetooth_on);
boolean bluetoothVisible = false;
if (mBluetooth != null) {
- if (mBluetooth.isBluetoothConnected()) {
- contentDescription = mContext.getString(R.string.accessibility_bluetooth_connected);
+ if (mBluetooth.isBluetoothConnected()
+ && (mBluetooth.isBluetoothAudioActive()
+ || !mBluetooth.isBluetoothAudioProfileOnly())) {
+ contentDescription = mContext.getString(
+ R.string.accessibility_bluetooth_connected);
bluetoothVisible = mBluetooth.isBluetoothEnabled();
}
}
@@ -450,7 +455,7 @@ public class PhoneStatusBarPolicy
// getLastResumedActivityUserId needds 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.
- mUiOffloadThread.submit(() -> {
+ mUiBgExecutor.execute(() -> {
final int userId;
try {
userId = ActivityTaskManager.getService().getLastResumedActivityUserId();
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 4c5bbce05261..2b9fc8d3bfbe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -45,7 +45,7 @@ import com.android.systemui.DejankUtils;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.colorextraction.SysuiColorExtractor;
-import com.android.systemui.dagger.qualifiers.MainResources;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dock.DockManager;
import com.android.systemui.statusbar.ScrimView;
import com.android.systemui.statusbar.notification.stack.ViewState;
@@ -192,7 +192,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
@Inject
public ScrimController(LightBarController lightBarController, DozeParameters dozeParameters,
AlarmManager alarmManager, KeyguardStateController keyguardStateController,
- @MainResources Resources resources,
+ @Main Resources resources,
DelayedWakeLock.Builder delayedWakeLockBuilder, Handler handler,
KeyguardUpdateMonitor keyguardUpdateMonitor, SysuiColorExtractor sysuiColorExtractor,
DockManager dockManager) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index f4c7e23f9cda..a6a734a542f0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -30,6 +30,7 @@ import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_STATUS_BARS;
import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
+import static com.android.systemui.Dependency.TIME_TICK_HANDLER_NAME;
import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP;
import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE;
import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_WAKING;
@@ -124,11 +125,9 @@ import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.ActivityIntentHelper;
-import com.android.systemui.ActivityStarterDelegate;
import com.android.systemui.AutoReinflateContainer;
import com.android.systemui.DejankUtils;
import com.android.systemui.DemoMode;
-import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
import com.android.systemui.EventLogTags;
import com.android.systemui.InitController;
@@ -137,13 +136,13 @@ import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
import com.android.systemui.SystemUIFactory;
-import com.android.systemui.UiOffloadThread;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.charging.WirelessChargingAnimation;
import com.android.systemui.classifier.FalsingLog;
import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.fragments.ExtensionFragmentListener;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.keyguard.DismissCallbackRegistry;
@@ -223,7 +222,6 @@ import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
import com.android.systemui.statusbar.policy.RemoteInputUriController;
-import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.volume.VolumeComponent;
@@ -233,6 +231,7 @@ import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Map;
import java.util.Optional;
+import java.util.concurrent.Executor;
import javax.inject.Named;
import javax.inject.Provider;
@@ -384,6 +383,12 @@ public class StatusBar extends SystemUI implements DemoMode,
private final ShadeController mShadeController;
private final SuperStatusBarViewFactory mSuperStatusBarViewFactory;
private final LightsOutNotifController mLightsOutNotifController;
+ private final InitController mInitController;
+ private final DarkIconDispatcher mDarkIconDispatcher;
+ private final PluginDependencyProvider mPluginDependencyProvider;
+ private final KeyguardDismissUtil mKeyguardDismissUtil;
+ private final ExtensionController mExtensionController;
+ private final UserInfoControllerImpl mUserInfoControllerImpl;
private final DismissCallbackRegistry mDismissCallbackRegistry;
// expanded notifications
@@ -472,7 +477,7 @@ public class StatusBar extends SystemUI implements DemoMode,
private ViewMediatorCallback mKeyguardViewMediatorCallback;
private final ScrimController mScrimController;
protected DozeScrimController mDozeScrimController;
- private final UiOffloadThread mUiOffloadThread;
+ private final Executor mUiBgExecutor;
protected boolean mDozing;
@@ -635,7 +640,7 @@ public class StatusBar extends SystemUI implements DemoMode,
NotificationAlertingManager notificationAlertingManager,
DisplayMetrics displayMetrics,
MetricsLogger metricsLogger,
- UiOffloadThread uiOffloadThread,
+ @UiBackground Executor uiBgExecutor,
NotificationMediaManager notificationMediaManager,
NotificationLockscreenUserManager lockScreenUserManager,
NotificationRemoteInputManager remoteInputManager,
@@ -681,6 +686,13 @@ public class StatusBar extends SystemUI implements DemoMode,
SuperStatusBarViewFactory superStatusBarViewFactory,
StatusBarKeyguardViewManager statusBarKeyguardViewManager,
ViewMediatorCallback viewMediatorCallback,
+ InitController initController,
+ DarkIconDispatcher darkIconDispatcher,
+ @Named(TIME_TICK_HANDLER_NAME) Handler timeTickHandler,
+ PluginDependencyProvider pluginDependencyProvider,
+ KeyguardDismissUtil keyguardDismissUtil,
+ ExtensionController extensionController,
+ UserInfoControllerImpl userInfoControllerImpl,
DismissCallbackRegistry dismissCallbackRegistry) {
super(context);
mFeatureFlags = featureFlags;
@@ -709,7 +721,7 @@ public class StatusBar extends SystemUI implements DemoMode,
mNotificationAlertingManager = notificationAlertingManager;
mDisplayMetrics = displayMetrics;
mMetricsLogger = metricsLogger;
- mUiOffloadThread = uiOffloadThread;
+ mUiBgExecutor = uiBgExecutor;
mMediaManager = notificationMediaManager;
mLockscreenUserManager = lockScreenUserManager;
mRemoteInputManager = remoteInputManager;
@@ -754,6 +766,12 @@ public class StatusBar extends SystemUI implements DemoMode,
mLightsOutNotifController = lightsOutNotifController;
mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
mKeyguardViewMediatorCallback = viewMediatorCallback;
+ mInitController = initController;
+ mDarkIconDispatcher = darkIconDispatcher;
+ mPluginDependencyProvider = pluginDependencyProvider;
+ mKeyguardDismissUtil = keyguardDismissUtil;
+ mExtensionController = extensionController;
+ mUserInfoControllerImpl = userInfoControllerImpl;
mDismissCallbackRegistry = dismissCallbackRegistry;
mBubbleExpandListener =
@@ -761,6 +779,9 @@ public class StatusBar extends SystemUI implements DemoMode,
mEntryManager.updateNotifications("onBubbleExpandChanged");
updateScrimController();
};
+
+
+ DateTimeView.setReceiverHandler(timeTickHandler);
}
@Override
@@ -795,8 +816,6 @@ public class StatusBar extends SystemUI implements DemoMode,
mVibrateOnOpening = mContext.getResources().getBoolean(
R.bool.config_vibrateOnIconAnimation);
- DateTimeView.setReceiverHandler(Dependency.get(Dependency.TIME_TICK_HANDLER));
-
// start old BaseStatusBar.start().
mWindowManagerService = WindowManagerGlobal.getWindowManagerService();
mDevicePolicyManager = (DevicePolicyManager) mContext.getSystemService(
@@ -886,7 +905,7 @@ public class StatusBar extends SystemUI implements DemoMode,
// Lastly, call to the icon policy to install/update all the icons.
mIconPolicy = new PhoneStatusBarPolicy(mContext, mIconController, mCommandQueue,
- mBroadcastDispatcher);
+ mBroadcastDispatcher, mUiBgExecutor);
mSignalPolicy = new StatusBarSignalPolicy(mContext, mIconController);
mKeyguardStateController.addCallback(this);
@@ -898,14 +917,12 @@ public class StatusBar extends SystemUI implements DemoMode,
mStatusBarWindowViewController,
mNotificationPanel, mAmbientIndicationContainer);
- Dependency.get(ActivityStarterDelegate.class).setActivityStarterImpl(this);
-
mConfigurationController.addCallback(this);
// set the initial view visibility
int disabledFlags1 = result.mDisabledFlags1;
int disabledFlags2 = result.mDisabledFlags2;
- Dependency.get(InitController.class).addPostInitTask(
+ mInitController.addPostInitTask(
() -> setUpDisableFlags(disabledFlags1, disabledFlags2));
mPluginManager.addPluginListener(
@@ -986,12 +1003,10 @@ public class StatusBar extends SystemUI implements DemoMode,
mNotificationPanel.setOnReinflationListener(mNotificationIconAreaController::initAodIcons);
mNotificationPanel.addExpansionListener(mWakeUpCoordinator);
- Dependency.get(DarkIconDispatcher.class).addDarkReceiver(mNotificationIconAreaController);
+ mDarkIconDispatcher.addDarkReceiver(mNotificationIconAreaController);
// Allow plugins to reference DarkIconDispatcher and StatusBarStateController
- Dependency.get(PluginDependencyProvider.class)
- .allowPluginDependency(DarkIconDispatcher.class);
- Dependency.get(PluginDependencyProvider.class)
- .allowPluginDependency(StatusBarStateController.class);
+ mPluginDependencyProvider.allowPluginDependency(DarkIconDispatcher.class);
+ mPluginDependencyProvider.allowPluginDependency(StatusBarStateController.class);
FragmentHostManager.get(mStatusBarWindow)
.addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> {
CollapsedStatusBarFragment statusBarFragment =
@@ -1118,7 +1133,7 @@ public class StatusBar extends SystemUI implements DemoMode,
if (container != null) {
FragmentHostManager fragmentHostManager = FragmentHostManager.get(container);
ExtensionFragmentListener.attachExtensonToFragment(container, QS.TAG, R.id.qs_frame,
- Dependency.get(ExtensionController.class)
+ mExtensionController
.newExtension(QS.class)
.withPlugin(QS.class)
.withDefault(this::createDefaultQSFragment)
@@ -1234,7 +1249,7 @@ public class StatusBar extends SystemUI implements DemoMode,
mScrimController, mActivityLaunchAnimator, mDynamicPrivacyController,
mNotificationAlertingManager, rowBinder, mKeyguardStateController,
mKeyguardIndicationController,
- this /* statusBar */, mShadeController, mCommandQueue);
+ this /* statusBar */, mShadeController, mCommandQueue, mInitController);
mNotificationListController =
new NotificationListController(
@@ -1332,9 +1347,8 @@ public class StatusBar extends SystemUI implements DemoMode,
mBrightnessMirrorController.onDensityOrFontScaleChanged();
}
// TODO: Bring these out of StatusBar.
- ((UserInfoControllerImpl) Dependency.get(UserInfoController.class))
- .onDensityOrFontScaleChanged();
- Dependency.get(UserSwitcherController.class).onDensityOrFontScaleChanged();
+ mUserInfoControllerImpl.onDensityOrFontScaleChanged();
+ mUserSwitcherController.onDensityOrFontScaleChanged();
if (mKeyguardUserSwitcher != null) {
mKeyguardUserSwitcher.onDensityOrFontScaleChanged();
}
@@ -1402,7 +1416,7 @@ public class StatusBar extends SystemUI implements DemoMode,
mLightBarController.setBiometricUnlockController(mBiometricUnlockController);
mMediaManager.setBiometricUnlockController(mBiometricUnlockController);
- Dependency.get(KeyguardDismissUtil.class).setDismissHandler(this::executeWhenUnlocked);
+ mKeyguardDismissUtil.setDismissHandler(this::executeWhenUnlocked);
Trace.endSection();
}
@@ -2843,7 +2857,7 @@ public class StatusBar extends SystemUI implements DemoMode,
notificationLoad = 1;
}
final int finalNotificationLoad = notificationLoad;
- mUiOffloadThread.submit(() -> {
+ mUiBgExecutor.execute(() -> {
try {
mBarService.onPanelRevealed(clearNotificationEffects,
finalNotificationLoad);
@@ -2852,7 +2866,7 @@ public class StatusBar extends SystemUI implements DemoMode,
}
});
} else {
- mUiOffloadThread.submit(() -> {
+ mUiBgExecutor.execute(() -> {
try {
mBarService.onPanelHidden();
} catch (RemoteException ex) {
@@ -3426,8 +3440,7 @@ public class StatusBar extends SystemUI implements DemoMode,
// ringing.
// Other transitions are covered in handleVisibleToUserChanged().
if (mVisible && (newState == StatusBarState.SHADE_LOCKED
- || (((SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class))
- .goingToFullShade()))) {
+ || mStatusBarStateController.goingToFullShade())) {
clearNotificationEffects();
}
if (newState == StatusBarState.KEYGUARD) {
@@ -4022,7 +4035,7 @@ public class StatusBar extends SystemUI implements DemoMode,
}
void awakenDreams() {
- Dependency.get(UiOffloadThread.class).submit(() -> {
+ mUiBgExecutor.execute(() -> {
try {
mDreamManager.awaken();
} catch (RemoteException e) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java
index e31c53abe988..12033de10cb8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java
@@ -17,8 +17,10 @@
package com.android.systemui.statusbar.phone;
import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
+import static com.android.systemui.Dependency.TIME_TICK_HANDLER_NAME;
import android.content.Context;
+import android.os.Handler;
import android.os.PowerManager;
import android.util.DisplayMetrics;
@@ -27,16 +29,19 @@ import androidx.annotation.Nullable;
import com.android.internal.logging.MetricsLogger;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.ViewMediatorCallback;
-import com.android.systemui.UiOffloadThread;
+import com.android.systemui.InitController;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.plugins.PluginDependencyProvider;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.ScreenPinningRequest;
import com.android.systemui.shared.plugins.PluginManager;
@@ -67,14 +72,17 @@ import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.ExtensionController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
import com.android.systemui.statusbar.policy.RemoteInputUriController;
+import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.volume.VolumeComponent;
import java.util.Optional;
+import java.util.concurrent.Executor;
import javax.inject.Named;
import javax.inject.Provider;
@@ -122,7 +130,7 @@ public class StatusBarModule {
NotificationAlertingManager notificationAlertingManager,
DisplayMetrics displayMetrics,
MetricsLogger metricsLogger,
- UiOffloadThread uiOffloadThread,
+ @UiBackground Executor uiBgExecutor,
NotificationMediaManager notificationMediaManager,
NotificationLockscreenUserManager lockScreenUserManager,
NotificationRemoteInputManager remoteInputManager,
@@ -168,6 +176,13 @@ public class StatusBarModule {
SuperStatusBarViewFactory superStatusBarViewFactory,
StatusBarKeyguardViewManager statusBarKeyguardViewManager,
ViewMediatorCallback viewMediatorCallback,
+ InitController initController,
+ DarkIconDispatcher darkIconDispatcher,
+ @Named(TIME_TICK_HANDLER_NAME) Handler timeTickHandler,
+ PluginDependencyProvider pluginDependencyProvider,
+ KeyguardDismissUtil keyguardDismissUtil,
+ ExtensionController extensionController,
+ UserInfoControllerImpl userInfoControllerImpl,
DismissCallbackRegistry dismissCallbackRegistry) {
return new StatusBar(
context,
@@ -197,7 +212,7 @@ public class StatusBarModule {
notificationAlertingManager,
displayMetrics,
metricsLogger,
- uiOffloadThread,
+ uiBgExecutor,
notificationMediaManager,
lockScreenUserManager,
remoteInputManager,
@@ -242,6 +257,13 @@ public class StatusBarModule {
superStatusBarViewFactory,
statusBarKeyguardViewManager,
viewMediatorCallback,
+ initController,
+ darkIconDispatcher,
+ timeTickHandler,
+ pluginDependencyProvider,
+ keyguardDismissUtil,
+ extensionController,
+ userInfoControllerImpl,
dismissCallbackRegistry);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index 3123f8dacada..661a7b1319a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -47,13 +47,12 @@ import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.ActivityIntentHelper;
-import com.android.systemui.Dependency;
import com.android.systemui.EventLogTags;
-import com.android.systemui.UiOffloadThread;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.bubbles.BubbleController;
-import com.android.systemui.dagger.qualifiers.BgHandler;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.CommandQueue;
@@ -74,6 +73,8 @@ import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.policy.HeadsUpUtil;
import com.android.systemui.statusbar.policy.KeyguardStateController;
+import java.util.concurrent.Executor;
+
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -115,6 +116,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
private final Handler mBackgroundHandler;
private final ActivityIntentHelper mActivityIntentHelper;
private final BubbleController mBubbleController;
+ private final Executor mUiBgExecutor;
private boolean mIsCollapsingToShowActivityOverLockscreen;
@@ -133,7 +135,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
KeyguardStateController keyguardStateController,
NotificationInterruptionStateProvider notificationInterruptionStateProvider,
MetricsLogger metricsLogger, LockPatternUtils lockPatternUtils,
- Handler mainThreadHandler, Handler backgroundHandler,
+ Handler mainThreadHandler, Handler backgroundHandler, Executor uiBgExecutor,
ActivityIntentHelper activityIntentHelper, BubbleController bubbleController) {
mContext = context;
mNotificationPanel = panel;
@@ -160,6 +162,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
mGroupManager = groupManager;
mLockPatternUtils = lockPatternUtils;
mBackgroundHandler = backgroundHandler;
+ mUiBgExecutor = uiBgExecutor;
mEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
@Override
public void onPendingEntryAdded(NotificationEntry entry) {
@@ -418,7 +421,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
} else {
// Stop screensaver if the notification has a fullscreen intent.
// (like an incoming phone call)
- Dependency.get(UiOffloadThread.class).submit(() -> {
+ mUiBgExecutor.execute(() -> {
try {
mDreamManager.awaken();
} catch (RemoteException e) {
@@ -521,6 +524,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
private final LockPatternUtils mLockPatternUtils;
private final Handler mMainThreadHandler;
private final Handler mBackgroundHandler;
+ private final Executor mUiBgExecutor;
private final ActivityIntentHelper mActivityIntentHelper;
private final BubbleController mBubbleController;
private final SuperStatusBarViewFactory mSuperStatusBarViewFactory;
@@ -549,8 +553,9 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
NotificationInterruptionStateProvider notificationInterruptionStateProvider,
MetricsLogger metricsLogger,
LockPatternUtils lockPatternUtils,
- @MainHandler Handler mainThreadHandler,
- @BgHandler Handler backgroundHandler,
+ @Main Handler mainThreadHandler,
+ @Background Handler backgroundHandler,
+ @UiBackground Executor uiBgExecutor,
ActivityIntentHelper activityIntentHelper,
BubbleController bubbleController,
ShadeController shadeController,
@@ -576,6 +581,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
mLockPatternUtils = lockPatternUtils;
mMainThreadHandler = mainThreadHandler;
mBackgroundHandler = backgroundHandler;
+ mUiBgExecutor = uiBgExecutor;
mActivityIntentHelper = activityIntentHelper;
mBubbleController = bubbleController;
mShadeController = shadeController;
@@ -624,6 +630,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
mLockPatternUtils,
mMainThreadHandler,
mBackgroundHandler,
+ mUiBgExecutor,
mActivityIntentHelper,
mBubbleController);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
index 8fc624dc9096..beb4579abe23 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -146,7 +146,8 @@ public class StatusBarNotificationPresenter implements NotificationPresenter,
KeyguardIndicationController keyguardIndicationController,
StatusBar statusBar,
ShadeController shadeController,
- CommandQueue commandQueue) {
+ CommandQueue commandQueue,
+ InitController initController) {
mContext = context;
mKeyguardStateController = keyguardStateController;
mNotificationPanel = panel;
@@ -193,7 +194,7 @@ public class StatusBarNotificationPresenter implements NotificationPresenter,
Dependency.get(StatusBarWindowController.class));
NotificationListContainer notifListContainer = (NotificationListContainer) stackScroller;
- Dependency.get(InitController.class).addPostInitTask(() -> {
+ initController.addPostInitTask(() -> {
NotificationEntryListener notificationEntryListener = new NotificationEntryListener() {
@Override
public void onEntryRemoved(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
index f94b2eea8154..ce498a39d941 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
@@ -41,7 +41,7 @@ import android.view.WindowManager.LayoutParams;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.colorextraction.SysuiColorExtractor;
-import com.android.systemui.dagger.qualifiers.MainResources;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
@@ -105,7 +105,7 @@ public class StatusBarWindowController implements Callback, Dumpable, Configurat
ConfigurationController configurationController,
KeyguardBypassController keyguardBypassController, SysuiColorExtractor colorExtractor,
SuperStatusBarViewFactory superStatusBarViewFactory,
- @MainResources Resources resources) {
+ @Main Resources resources) {
mContext = context;
mWindowManager = windowManager;
mActivityManager = activityManager;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
index dc809066524f..f132058b5329 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
@@ -34,8 +34,8 @@ import com.android.settingslib.fuelgauge.BatterySaverUtils;
import com.android.settingslib.fuelgauge.Estimate;
import com.android.settingslib.utils.PowerUtil;
import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dagger.qualifiers.BgHandler;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.power.EnhancedEstimates;
import java.io.FileDescriptor;
@@ -82,7 +82,7 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC
@Inject
BatteryControllerImpl(Context context, EnhancedEstimates enhancedEstimates,
PowerManager powerManager, BroadcastDispatcher broadcastDispatcher,
- @MainHandler Handler mainHandler, @BgHandler Handler bgHandler) {
+ @Main Handler mainHandler, @Background Handler bgHandler) {
mContext = context;
mMainHandler = mainHandler;
mBgHandler = bgHandler;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothController.java
index 42e02d5846bc..0c5b8515071d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothController.java
@@ -31,6 +31,8 @@ public interface BluetoothController extends CallbackController<Callback>, Dumpa
boolean isBluetoothConnected();
boolean isBluetoothConnecting();
+ boolean isBluetoothAudioProfileOnly();
+ boolean isBluetoothAudioActive();
String getConnectedDeviceName();
void setBluetoothEnabled(boolean enabled);
Collection<CachedBluetoothDevice> getDevices();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
index 76683b6a5e6a..0fc3d8481907 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
@@ -32,9 +32,10 @@ import android.util.Log;
import com.android.settingslib.bluetooth.BluetoothCallback;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.settingslib.bluetooth.LocalBluetoothProfile;
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
-import com.android.systemui.dagger.qualifiers.BgLooper;
-import com.android.systemui.dagger.qualifiers.MainLooper;
+import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Main;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -65,6 +66,8 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa
private boolean mEnabled;
private int mConnectionState = BluetoothAdapter.STATE_DISCONNECTED;
+ private boolean mAudioProfileOnly;
+ private boolean mIsActive;
private final H mHandler;
private int mState;
@@ -72,8 +75,8 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa
/**
*/
@Inject
- public BluetoothControllerImpl(Context context, @BgLooper Looper bgLooper,
- @MainLooper Looper mainLooper, @Nullable LocalBluetoothManager localBluetoothManager) {
+ public BluetoothControllerImpl(Context context, @Background Looper bgLooper,
+ @Main Looper mainLooper, @Nullable LocalBluetoothManager localBluetoothManager) {
mLocalBluetoothManager = localBluetoothManager;
mBgHandler = new Handler(bgLooper);
mHandler = new H(mainLooper);
@@ -103,6 +106,8 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa
}
pw.print(" mEnabled="); pw.println(mEnabled);
pw.print(" mConnectionState="); pw.println(stateToString(mConnectionState));
+ pw.print(" mAudioProfileOnly="); pw.println(mAudioProfileOnly);
+ pw.print(" mIsActive="); pw.println(mIsActive);
pw.print(" mConnectedDevices="); pw.println(mConnectedDevices);
pw.print(" mCallbacks.size="); pw.println(mHandler.mCallbacks.size());
pw.println(" Bluetooth Devices:");
@@ -176,6 +181,16 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa
}
@Override
+ public boolean isBluetoothAudioProfileOnly() {
+ return mAudioProfileOnly;
+ }
+
+ @Override
+ public boolean isBluetoothAudioActive() {
+ return mIsActive;
+ }
+
+ @Override
public void setBluetoothEnabled(boolean enabled) {
if (mLocalBluetoothManager != null) {
mLocalBluetoothManager.getBluetoothAdapter().setBluetoothEnabled(enabled);
@@ -239,6 +254,48 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa
mConnectionState = state;
mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED);
}
+ updateAudioProfile();
+ }
+
+ private void updateActive() {
+ boolean isActive = false;
+
+ for (CachedBluetoothDevice device : getDevices()) {
+ isActive |= device.isActiveDevice(BluetoothProfile.HEADSET)
+ || device.isActiveDevice(BluetoothProfile.A2DP)
+ || device.isActiveDevice(BluetoothProfile.HEARING_AID);
+ }
+
+ if (mIsActive != isActive) {
+ mIsActive = isActive;
+ mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED);
+ }
+ }
+
+ private void updateAudioProfile() {
+ boolean audioProfileConnected = false;
+ boolean otherProfileConnected = false;
+
+ for (CachedBluetoothDevice device : getDevices()) {
+ for (LocalBluetoothProfile profile : device.getProfiles()) {
+ int profileId = profile.getProfileId();
+ boolean isConnected = device.isConnectedProfile(profile);
+ if (profileId == BluetoothProfile.HEADSET
+ || profileId == BluetoothProfile.A2DP
+ || profileId == BluetoothProfile.HEARING_AID) {
+ audioProfileConnected |= isConnected;
+ } else {
+ otherProfileConnected |= isConnected;
+ }
+ }
+ }
+
+ boolean audioProfileOnly = (audioProfileConnected && !otherProfileConnected);
+ if (audioProfileOnly != mAudioProfileOnly) {
+ mAudioProfileOnly = audioProfileOnly;
+ mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED);
+ }
+
}
@Override
@@ -306,6 +363,16 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa
}
@Override
+ public void onActiveDeviceChanged(CachedBluetoothDevice activeDevice, int bluetoothProfile) {
+ if (DEBUG) {
+ Log.d(TAG, "ActiveDeviceChanged=" + activeDevice.getAddress()
+ + " profileId=" + bluetoothProfile);
+ }
+ updateActive();
+ mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED);
+ }
+
+ @Override
public void onAclConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) {
if (DEBUG) {
Log.d(TAG, "ACLConnectionStateChanged=" + cachedDevice.getAddress() + " "
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java
index b6ffd58be816..a3e2e7619bac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java
@@ -25,7 +25,7 @@ import android.provider.Settings.Secure;
import android.util.Log;
import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.settings.CurrentUserTracker;
import java.util.ArrayList;
@@ -40,7 +40,7 @@ public class DeviceProvisionedControllerImpl extends CurrentUserTracker implemen
DeviceProvisionedController {
protected static final String TAG = DeviceProvisionedControllerImpl.class.getSimpleName();
- private final ArrayList<DeviceProvisionedListener> mListeners = new ArrayList<>();
+ protected final ArrayList<DeviceProvisionedListener> mListeners = new ArrayList<>();
private final ContentResolver mContentResolver;
private final Context mContext;
private final Uri mDeviceProvisionedUri;
@@ -50,7 +50,7 @@ public class DeviceProvisionedControllerImpl extends CurrentUserTracker implemen
/**
*/
@Inject
- public DeviceProvisionedControllerImpl(Context context, @MainHandler Handler mainHandler,
+ public DeviceProvisionedControllerImpl(Context context, @Main Handler mainHandler,
BroadcastDispatcher broadcastDispatcher) {
super(broadcastDispatcher);
mContext = context;
@@ -104,7 +104,7 @@ public class DeviceProvisionedControllerImpl extends CurrentUserTracker implemen
}
}
- private void startListening(int user) {
+ protected void startListening(int user) {
mContentResolver.registerContentObserver(mDeviceProvisionedUri, true,
mSettingsObserver, 0);
mContentResolver.registerContentObserver(mUserSetupUri, true,
@@ -112,7 +112,7 @@ public class DeviceProvisionedControllerImpl extends CurrentUserTracker implemen
startTracking();
}
- private void stopListening() {
+ protected void stopListening() {
stopTracking();
mContentResolver.unregisterContentObserver(mSettingsObserver);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
index 6828c322dea2..66a1d3ff756a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
@@ -16,7 +16,7 @@
package com.android.systemui.statusbar.policy;
-import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_HEADS_UP;
+import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -33,7 +33,7 @@ import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.statusbar.AlertingNotificationManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
+import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag;
import java.io.FileDescriptor;
import java.io.PrintWriter;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
index cd6ec05d90ec..df9c3f4d6e26 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
@@ -26,7 +26,7 @@ import android.os.HandlerExecutor;
import android.os.UserManager;
import android.util.Log;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -59,7 +59,7 @@ public class HotspotControllerImpl implements HotspotController, WifiManager.Sof
* Controller used to retrieve information related to a hotspot.
*/
@Inject
- public HotspotControllerImpl(Context context, @MainHandler Handler mainHandler) {
+ public HotspotControllerImpl(Context context, @Main Handler mainHandler) {
mContext = context;
mConnectivityManager =
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
index d36bd75dfdba..570f153a62c0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
@@ -37,7 +37,7 @@ import androidx.annotation.VisibleForTesting;
import com.android.systemui.BootCompleteCache;
import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dagger.qualifiers.BgLooper;
+import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.util.Utils;
import java.util.ArrayList;
@@ -69,7 +69,7 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio
private final H mHandler = new H();
@Inject
- public LocationControllerImpl(Context context, @BgLooper Looper bgLooper,
+ public LocationControllerImpl(Context context, @Background Looper bgLooper,
BroadcastDispatcher broadcastDispatcher, BootCompleteCache bootCompleteCache) {
mContext = context;
mBroadcastDispatcher = broadcastDispatcher;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index a6108a490331..6759020376c5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -699,8 +699,8 @@ public class MobileSignalController extends SignalController<
@Override
public void onServiceStateChanged(ServiceState state) {
if (DEBUG) {
- Log.d(mTag, "onServiceStateChanged voiceState=" + state.getVoiceRegState()
- + " dataState=" + state.getDataRegState());
+ Log.d(mTag, "onServiceStateChanged voiceState=" + state.getState()
+ + " dataState=" + state.getDataRegistrationState());
}
mServiceState = state;
if (mServiceState != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 24492bf3ca5b..f20a47babe5d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -64,7 +64,7 @@ import com.android.systemui.DemoMode;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dagger.qualifiers.BgLooper;
+import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.settings.CurrentUserTracker;
import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
import com.android.systemui.statusbar.policy.MobileSignalController.MobileIconGroup;
@@ -177,7 +177,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
* Construct this controller object and register for updates.
*/
@Inject
- public NetworkControllerImpl(Context context, @BgLooper Looper bgLooper,
+ public NetworkControllerImpl(Context context, @Background Looper bgLooper,
DeviceProvisionedController deviceProvisionedController,
BroadcastDispatcher broadcastDispatcher) {
this(context, (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
index c1614587ea35..019ef3bca709 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
@@ -49,7 +49,7 @@ import com.android.internal.net.LegacyVpnInfo;
import com.android.internal.net.VpnConfig;
import com.android.systemui.R;
import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dagger.qualifiers.BgHandler;
+import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.settings.CurrentUserTracker;
import java.io.FileDescriptor;
@@ -101,7 +101,7 @@ public class SecurityControllerImpl extends CurrentUserTracker implements Securi
/**
*/
@Inject
- public SecurityControllerImpl(Context context, @BgHandler Handler bgHandler,
+ public SecurityControllerImpl(Context context, @Background Handler bgHandler,
BroadcastDispatcher broadcastDispatcher) {
this(context, bgHandler, broadcastDispatcher, null);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java
index 347d3009c3ec..86fe300820a3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java
@@ -28,7 +28,7 @@ import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.systemui.R;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -65,7 +65,7 @@ public final class SmartReplyConstants {
private final KeyValueListParser mParser = new KeyValueListParser(',');
@Inject
- public SmartReplyConstants(@MainHandler Handler handler, Context context) {
+ public SmartReplyConstants(@Main Handler handler, Context context) {
mHandler = handler;
mContext = context;
final Resources resources = mContext.getResources();
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 13c0db938ca0..2907cd41a0db 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -60,7 +60,7 @@ import com.android.systemui.Prefs.Key;
import com.android.systemui.R;
import com.android.systemui.SystemUISecondaryUserService;
import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.qs.tiles.UserDetailView;
@@ -113,7 +113,7 @@ public class UserSwitcherController implements Dumpable {
@Inject
public UserSwitcherController(Context context, KeyguardStateController keyguardStateController,
- @MainHandler Handler handler, ActivityStarter activityStarter,
+ @Main Handler handler, ActivityStarter activityStarter,
BroadcastDispatcher broadcastDispatcher) {
mContext = context;
mBroadcastDispatcher = broadcastDispatcher;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
index a2028e6c0c33..4376a0145826 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
@@ -40,7 +40,7 @@ import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Dumpable;
import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.qs.GlobalSetting;
import com.android.systemui.settings.CurrentUserTracker;
import com.android.systemui.util.Utils;
@@ -78,7 +78,7 @@ public class ZenModeControllerImpl extends CurrentUserTracker
private NotificationManager.Policy mConsolidatedNotificationPolicy;
@Inject
- public ZenModeControllerImpl(Context context, @MainHandler Handler handler,
+ public ZenModeControllerImpl(Context context, @Main Handler handler,
BroadcastDispatcher broadcastDispatcher) {
super(broadcastDispatcher);
mContext = context;
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
index f9d39b0e6f96..7758aba52918 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
@@ -36,7 +36,7 @@ import android.util.Log;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dagger.qualifiers.BgHandler;
+import com.android.systemui.dagger.qualifiers.Background;
import com.google.android.collect.Sets;
@@ -70,7 +70,7 @@ public class ThemeOverlayController extends SystemUI {
@Inject
public ThemeOverlayController(Context context, BroadcastDispatcher broadcastDispatcher,
- @BgHandler Handler bgHandler) {
+ @Background Handler bgHandler) {
super(context);
mBroadcastDispatcher = broadcastDispatcher;
mBgHandler = bgHandler;
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
index ce0032e619e7..19f0ba24b0fd 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
@@ -35,7 +35,7 @@ import com.android.internal.util.ArrayUtils;
import com.android.systemui.DejankUtils;
import com.android.systemui.DemoMode;
import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.qs.QSTileHost;
import com.android.systemui.settings.CurrentUserTracker;
import com.android.systemui.statusbar.phone.StatusBarIconController;
@@ -82,7 +82,7 @@ public class TunerServiceImpl extends TunerService {
/**
*/
@Inject
- public TunerServiceImpl(Context context, @MainHandler Handler mainHandler,
+ public TunerServiceImpl(Context context, @Main Handler mainHandler,
LeakDetector leakDetector, BroadcastDispatcher broadcastDispatcher) {
mContext = context;
mContentResolver = mContext.getContentResolver();
diff --git a/packages/SystemUI/src/com/android/systemui/util/animation/PhysicsAnimator.kt b/packages/SystemUI/src/com/android/systemui/util/animation/PhysicsAnimator.kt
index 62ae7b9d620f..cca76bd173c7 100644
--- a/packages/SystemUI/src/com/android/systemui/util/animation/PhysicsAnimator.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/animation/PhysicsAnimator.kt
@@ -679,6 +679,7 @@ class PhysicsAnimator<T> private constructor (val target: T) {
internal var instanceConstructor: (Any) -> PhysicsAnimator<*> = ::PhysicsAnimator
@JvmStatic
+ @Suppress("UNCHECKED_CAST")
fun <T : Any> getInstance(target: T): PhysicsAnimator<T> {
if (!animators.containsKey(target)) {
animators[target] = instanceConstructor(target)
diff --git a/packages/SystemUI/src/com/android/systemui/util/animation/PhysicsAnimatorTestUtils.kt b/packages/SystemUI/src/com/android/systemui/util/animation/PhysicsAnimatorTestUtils.kt
index a1f74eb40cad..e86970c117cc 100644
--- a/packages/SystemUI/src/com/android/systemui/util/animation/PhysicsAnimatorTestUtils.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/animation/PhysicsAnimatorTestUtils.kt
@@ -142,6 +142,7 @@ object PhysicsAnimatorTestUtils {
*/
@JvmStatic
@Throws(InterruptedException::class)
+ @Suppress("UNCHECKED_CAST")
fun <T : Any> blockUntilAnimationsEnd(
properties: FloatPropertyCompat<in T>
) {
@@ -236,6 +237,14 @@ object PhysicsAnimatorTestUtils {
vararg additionalUpdateMatchers: UpdateMatcher
) {
val updateFrames: UpdateFramesPerProperty<T> = getAnimationUpdateFrames(animator)
+
+ if (!updateFrames.containsKey(property)) {
+ error("No frames for given target object and property.")
+ }
+
+ // Copy the frames to avoid a ConcurrentModificationException if the animation update
+ // listeners attempt to add a new frame while we're verifying these.
+ val framesForProperty = ArrayList(updateFrames[property]!!)
val matchers = ArrayDeque<UpdateMatcher>(
additionalUpdateMatchers.toList())
val frameTraceMessage = StringBuilder()
@@ -243,8 +252,7 @@ object PhysicsAnimatorTestUtils {
var curMatcher = firstUpdateMatcher
// Loop through the updates from the testable animator.
- for (update in updateFrames[property]
- ?: error("No frames for given target object and property.")) {
+ for (update in framesForProperty) {
// Check whether this frame satisfies the current matcher.
if (curMatcher(update)) {
@@ -320,6 +328,7 @@ object PhysicsAnimatorTestUtils {
/**
* Returns all of the values that have ever been reported to update listeners, per property.
*/
+ @Suppress("UNCHECKED_CAST")
fun <T : Any> getAnimationUpdateFrames(animator: PhysicsAnimator<T>):
UpdateFramesPerProperty<T> {
return animatorTestHelpers[animator]?.getUpdates() as UpdateFramesPerProperty<T>
@@ -333,6 +342,7 @@ object PhysicsAnimatorTestUtils {
animatorTestHelpers[animator]?.clearUpdates()
}
+ @Suppress("UNCHECKED_CAST")
private fun <T> getAnimationTestHelper(animator: PhysicsAnimator<T>): AnimatorTestHelper<T> {
return animatorTestHelpers[animator] as AnimatorTestHelper<T>
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/concurrency/ConcurrencyModule.java b/packages/SystemUI/src/com/android/systemui/util/concurrency/ConcurrencyModule.java
index 3e90581292ce..7cdba8607d86 100644
--- a/packages/SystemUI/src/com/android/systemui/util/concurrency/ConcurrencyModule.java
+++ b/packages/SystemUI/src/com/android/systemui/util/concurrency/ConcurrencyModule.java
@@ -18,14 +18,18 @@ package com.android.systemui.util.concurrency;
import android.content.Context;
import android.os.Handler;
+import android.os.HandlerThread;
import android.os.Looper;
+import android.os.Process;
import com.android.systemui.dagger.qualifiers.Background;
-import com.android.systemui.dagger.qualifiers.BgLooper;
import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.dagger.qualifiers.MainLooper;
+import com.android.systemui.dagger.qualifiers.UiBackground;
import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@@ -35,11 +39,51 @@ import dagger.Provides;
*/
@Module
public abstract class ConcurrencyModule {
+ /** Background Looper */
+ @Provides
+ @Singleton
+ @Background
+ public static Looper provideBgLooper() {
+ HandlerThread thread = new HandlerThread("SysUiBg",
+ Process.THREAD_PRIORITY_BACKGROUND);
+ thread.start();
+ return thread.getLooper();
+ }
+
+ /** Main Looper */
+ @Provides
+ @Main
+ public static Looper provideMainLooper() {
+ return Looper.getMainLooper();
+ }
+
+ /**
+ * Background Handler.
+ *
+ * Prefer the Background Executor when possible.
+ */
+ @Provides
+ @Background
+ public static Handler provideBgHandler(@Background Looper bgLooper) {
+ return new Handler(bgLooper);
+ }
+
+ /**
+ * Main Handler.
+ *
+ * Prefer the Main Executor when possible.
+ */
+ @Provides
+ @Main
+ public static Handler provideMainHandler(@Main Looper mainLooper) {
+ return new Handler(mainLooper);
+ }
+
/**
* Provide a Background-Thread Executor by default.
*/
@Provides
- public static Executor provideExecutor(@BgLooper Looper looper) {
+ public static Executor provideExecutor(@Background Looper looper) {
return new ExecutorImpl(new Handler(looper));
}
@@ -48,7 +92,7 @@ public abstract class ConcurrencyModule {
*/
@Provides
@Background
- public static Executor provideBackgroundExecutor(@BgLooper Looper looper) {
+ public static Executor provideBackgroundExecutor(@Background Looper looper) {
return new ExecutorImpl(new Handler(looper));
}
@@ -65,7 +109,7 @@ public abstract class ConcurrencyModule {
* Provide a Background-Thread Executor by default.
*/
@Provides
- public static DelayableExecutor provideDelayableExecutor(@BgLooper Looper looper) {
+ public static DelayableExecutor provideDelayableExecutor(@Background Looper looper) {
return new ExecutorImpl(new Handler(looper));
}
@@ -74,7 +118,7 @@ public abstract class ConcurrencyModule {
*/
@Provides
@Background
- public static DelayableExecutor provideBackgroundDelayableExecutor(@BgLooper Looper looper) {
+ public static DelayableExecutor provideBackgroundDelayableExecutor(@Background Looper looper) {
return new ExecutorImpl(new Handler(looper));
}
@@ -83,7 +127,19 @@ public abstract class ConcurrencyModule {
*/
@Provides
@Main
- public static DelayableExecutor provideMainDelayableExecutor(@MainLooper Looper looper) {
+ public static DelayableExecutor provideMainDelayableExecutor(@Main Looper looper) {
return new ExecutorImpl(new Handler(looper));
}
+
+ /**
+ * Provide an Executor specifically for running UI operations on a separate thread.
+ *
+ * Keep submitted runnables short and to the point, just as with any other UI code.
+ */
+ @Provides
+ @Singleton
+ @UiBackground
+ public static Executor provideUiBackgroundExecutor() {
+ return Executors.newSingleThreadExecutor();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
index bff405c0bee6..2c7c52e1c51f 100644
--- a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
@@ -47,7 +47,7 @@ import android.util.LongSparseArray;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
-import com.android.systemui.dagger.qualifiers.BgLooper;
+import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.qs.QSHost;
@@ -109,7 +109,7 @@ public class GarbageMonitor implements Dumpable {
@Inject
public GarbageMonitor(
Context context,
- @BgLooper Looper bgLooper,
+ @Background Looper bgLooper,
LeakDetector leakDetector,
LeakReporter leakReporter) {
mContext = context.getApplicationContext();
diff --git a/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java
index a96977a338a9..b5bede4ad31c 100644
--- a/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java
+++ b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java
@@ -26,7 +26,7 @@ import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.R;
-import com.android.systemui.dagger.qualifiers.MainResources;
+import com.android.systemui.dagger.qualifiers.Main;
import java.util.ArrayList;
import java.util.List;
@@ -65,7 +65,7 @@ public class ProximitySensor {
};
@Inject
- public ProximitySensor(@MainResources Resources resources,
+ public ProximitySensor(@Main Resources resources,
AsyncSensorManager sensorManager) {
mSensorManager = sensorManager;
Sensor sensor = findBrightnessSensor(resources);
diff --git a/packages/SystemUI/src/com/android/systemui/util/time/SystemClock.java b/packages/SystemUI/src/com/android/systemui/util/time/SystemClock.java
index 4316df1ced04..6fef59f6b995 100644
--- a/packages/SystemUI/src/com/android/systemui/util/time/SystemClock.java
+++ b/packages/SystemUI/src/com/android/systemui/util/time/SystemClock.java
@@ -37,10 +37,4 @@ public interface SystemClock {
/** @see android.os.SystemClock#currentThreadTimeMillis() */
long currentThreadTimeMillis();
-
- /** @see android.os.SystemClock#currentThreadTimeMicro() */
- long currentThreadTimeMicro();
-
- /** @see android.os.SystemClock#currentTimeMicro() */
- long currentTimeMicro();
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/time/SystemClockImpl.java b/packages/SystemUI/src/com/android/systemui/util/time/SystemClockImpl.java
index 532ea050bfdd..f0c701490f13 100644
--- a/packages/SystemUI/src/com/android/systemui/util/time/SystemClockImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/util/time/SystemClockImpl.java
@@ -42,14 +42,4 @@ public class SystemClockImpl implements SystemClock {
public long currentThreadTimeMillis() {
return android.os.SystemClock.currentThreadTimeMillis();
}
-
- @Override
- public long currentThreadTimeMicro() {
- return android.os.SystemClock.currentThreadTimeMicro();
- }
-
- @Override
- public long currentTimeMicro() {
- return android.os.SystemClock.currentTimeMicro();
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index f5c158734fcc..af218c499d62 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -160,6 +160,7 @@ public class VolumeDialogImpl implements VolumeDialog,
private boolean mHovering = false;
private boolean mShowActiveStreamOnly;
private boolean mConfigChanged = false;
+ private boolean mIsAnimatingDismiss = false;
private boolean mHasSeenODICaptionsTooltip;
private ViewStub mODICaptionsTooltipViewStub;
private View mODICaptionsTooltipView = null;
@@ -693,6 +694,7 @@ public class VolumeDialogImpl implements VolumeDialog,
initSettingsH();
mShowing = true;
+ mIsAnimatingDismiss = false;
mDialog.show();
Events.writeEvent(Events.EVENT_SHOW_DIALOG, reason, mKeyguard.isKeyguardLocked());
mController.notifyVisible(true);
@@ -737,6 +739,10 @@ public class VolumeDialogImpl implements VolumeDialog,
}
mHandler.removeMessages(H.DISMISS);
mHandler.removeMessages(H.SHOW);
+ if (mIsAnimatingDismiss) {
+ return;
+ }
+ mIsAnimatingDismiss = true;
mDialogView.animate().cancel();
if (mShowing) {
mShowing = false;
@@ -752,6 +758,7 @@ public class VolumeDialogImpl implements VolumeDialog,
.withEndAction(() -> mHandler.postDelayed(() -> {
mDialog.dismiss();
tryToRemoveCaptionsTooltip();
+ mIsAnimatingDismiss = false;
}, 50));
if (!isLandscape()) animator.translationX(mDialogView.getWidth() / 2.0f);
animator.start();
diff --git a/packages/SystemUI/src/com/android/systemui/wm/DisplayWindowController.java b/packages/SystemUI/src/com/android/systemui/wm/DisplayWindowController.java
index ae82115ca37e..951d6dd4c3a3 100644
--- a/packages/SystemUI/src/com/android/systemui/wm/DisplayWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/wm/DisplayWindowController.java
@@ -31,7 +31,7 @@ import android.view.IDisplayWindowRotationController;
import android.view.IWindowManager;
import android.view.WindowContainerTransaction;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import java.util.ArrayList;
@@ -99,9 +99,14 @@ public class DisplayWindowController {
if (mDisplays.get(displayId) != null) {
return;
}
+ Display display = getDisplay(displayId);
+ if (display == null) {
+ // It's likely that the display is private to some app and thus not
+ // accessible by system-ui.
+ return;
+ }
DisplayRecord record = new DisplayRecord();
record.mDisplayId = displayId;
- Display display = getDisplay(displayId);
record.mContext = (displayId == Display.DEFAULT_DISPLAY) ? mContext
: mContext.createDisplayContext(display);
record.mDisplayLayout = new DisplayLayout(record.mContext, display);
@@ -142,6 +147,9 @@ public class DisplayWindowController {
public void onDisplayRemoved(int displayId) {
mHandler.post(() -> {
synchronized (mDisplays) {
+ if (mDisplays.get(displayId) == null) {
+ return;
+ }
for (int i = mDisplayChangedListeners.size() - 1; i >= 0; --i) {
mDisplayChangedListeners.get(i).onDisplayRemoved(displayId);
}
@@ -152,7 +160,7 @@ public class DisplayWindowController {
};
@Inject
- public DisplayWindowController(Context context, @MainHandler Handler mainHandler,
+ public DisplayWindowController(Context context, @Main Handler mainHandler,
IWindowManager wmService) {
mHandler = mainHandler;
mContext = context;
diff --git a/packages/SystemUI/src/com/android/systemui/wm/SystemWindows.java b/packages/SystemUI/src/com/android/systemui/wm/SystemWindows.java
index 5ec61c3313f0..02c7857f0cfd 100644
--- a/packages/SystemUI/src/com/android/systemui/wm/SystemWindows.java
+++ b/packages/SystemUI/src/com/android/systemui/wm/SystemWindows.java
@@ -42,7 +42,7 @@ import android.view.SurfaceControl;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
-import android.view.WindowlessViewRoot;
+import android.view.SurfaceControlViewHost;
import android.view.WindowlessWindowManager;
import com.android.internal.os.IResultReceiver;
@@ -61,7 +61,7 @@ public class SystemWindows {
private static final String TAG = "SystemWindows";
private final SparseArray<PerDisplay> mPerDisplay = new SparseArray<>();
- final HashMap<View, WindowlessViewRoot> mViewRoots = new HashMap<>();
+ final HashMap<View, SurfaceControlViewHost> mViewRoots = new HashMap<>();
Context mContext;
IWindowSession mSession;
DisplayWindowController mDisplayController;
@@ -121,7 +121,7 @@ public class SystemWindows {
* @param view
*/
public void removeView(View view) {
- WindowlessViewRoot root = mViewRoots.remove(view);
+ SurfaceControlViewHost root = mViewRoots.remove(view);
root.die();
}
@@ -129,7 +129,7 @@ public class SystemWindows {
* Updates the layout params of a view.
*/
public void updateViewLayout(@NonNull View view, ViewGroup.LayoutParams params) {
- WindowlessViewRoot root = mViewRoots.get(view);
+ SurfaceControlViewHost root = mViewRoots.get(view);
if (root == null || !(params instanceof WindowManager.LayoutParams)) {
return;
}
@@ -177,7 +177,7 @@ public class SystemWindows {
return;
}
final Display display = mDisplayController.getDisplay(mDisplayId);
- WindowlessViewRoot viewRoot = new WindowlessViewRoot(mContext, display, wwm);
+ SurfaceControlViewHost viewRoot = new SurfaceControlViewHost(mContext, display, wwm);
attrs.flags |= FLAG_HARDWARE_ACCELERATED;
viewRoot.addView(view, attrs);
mViewRoots.put(view, viewRoot);
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
index 1a1b67945c97..b70fdbd4a2d8 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
@@ -375,7 +375,7 @@ public class CarrierTextControllerTest extends SysuiTestCase {
mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
ServiceState ss = mock(ServiceState.class);
- when(ss.getDataRegState()).thenReturn(ServiceState.STATE_IN_SERVICE);
+ when(ss.getDataRegistrationState()).thenReturn(ServiceState.STATE_IN_SERVICE);
mKeyguardUpdateMonitor.mServiceStates.put(TEST_SUBSCRIPTION_NULL.getSubscriptionId(), ss);
ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 7be3e2b28489..4bf1e1c0920d 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -57,7 +57,6 @@ import android.testing.AndroidTestingRunner;
import android.testing.TestableContext;
import android.testing.TestableLooper;
-import com.android.internal.telephony.IccCardConstants;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.TelephonyIntents;
import com.android.systemui.DumpController;
@@ -183,8 +182,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
@Test
public void testTelephonyCapable_SimState_Absent() {
Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
- intent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE,
- IccCardConstants.INTENT_VALUE_ICC_ABSENT);
+ intent.putExtra(Intent.EXTRA_SIM_STATE,
+ Intent.SIM_STATE_ABSENT);
mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext(),
putPhoneInfo(intent, null, false));
mTestableLooper.processAllMessages();
@@ -194,8 +193,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
@Test
public void testTelephonyCapable_SimState_CardIOError() {
Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
- intent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE,
- IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR);
+ intent.putExtra(Intent.EXTRA_SIM_STATE,
+ Intent.SIM_STATE_CARD_IO_ERROR);
mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext(),
putPhoneInfo(intent, null, false));
mTestableLooper.processAllMessages();
@@ -221,8 +220,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
// Simulate AirplaneMode case, SERVICE_STATE - POWER_OFF, check TelephonyCapable False
// Only receive ServiceState callback IN_SERVICE -> OUT_OF_SERVICE -> POWER_OFF
Intent intent = new Intent(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
- intent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE
- , IccCardConstants.INTENT_VALUE_ICC_LOADED);
+ intent.putExtra(Intent.EXTRA_SIM_STATE
+ , Intent.SIM_STATE_LOADED);
Bundle data = new Bundle();
ServiceState state = new ServiceState();
state.setState(ServiceState.STATE_POWER_OFF);
@@ -261,8 +260,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
state.setState(ServiceState.STATE_OUT_OF_SERVICE);
state.fillInNotifierBundle(data);
Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
- intent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE
- , IccCardConstants.INTENT_VALUE_ICC_NOT_READY);
+ intent.putExtra(Intent.EXTRA_SIM_STATE
+ , Intent.SIM_STATE_NOT_READY);
mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext()
, putPhoneInfo(intent, data, false));
mTestableLooper.processAllMessages();
@@ -276,8 +275,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
state.setState(ServiceState.STATE_OUT_OF_SERVICE);
state.fillInNotifierBundle(data);
Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
- intent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE
- , IccCardConstants.INTENT_VALUE_ICC_READY);
+ intent.putExtra(Intent.EXTRA_SIM_STATE
+ , Intent.SIM_STATE_READY);
mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext()
, putPhoneInfo(intent, data, false));
mTestableLooper.processAllMessages();
@@ -317,8 +316,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
state.setState(ServiceState.STATE_IN_SERVICE);
state.fillInNotifierBundle(data);
Intent intentSimState = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
- intentSimState.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE
- , IccCardConstants.INTENT_VALUE_ICC_LOADED);
+ intentSimState.putExtra(Intent.EXTRA_SIM_STATE
+ , Intent.SIM_STATE_LOADED);
mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext()
, putPhoneInfo(intentSimState, data, true));
mTestableLooper.processAllMessages();
@@ -326,8 +325,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
assertThat(mKeyguardUpdateMonitor.mTelephonyCapable).isFalse();
Intent intentServiceState = new Intent(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
- intentSimState.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE
- , IccCardConstants.INTENT_VALUE_ICC_LOADED);
+ intentSimState.putExtra(Intent.EXTRA_SIM_STATE
+ , Intent.SIM_STATE_LOADED);
mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext()
, putPhoneInfo(intentServiceState, data, true));
mTestableLooper.processAllMessages();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
index 4cb54728a64c..9c9a627fa6e0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
@@ -46,11 +46,11 @@ import androidx.test.filters.SmallTest;
import com.android.internal.messages.nano.SystemMessageProto;
import com.android.systemui.appops.AppOpsController;
-import com.android.systemui.statusbar.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import junit.framework.Assert;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceNotificationListenerTest.java b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceNotificationListenerTest.java
index 212c93dc576d..46a473bd6543 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceNotificationListenerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceNotificationListenerTest.java
@@ -27,8 +27,8 @@ import android.app.Notification;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
-import com.android.systemui.statusbar.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import org.junit.Before;
import org.junit.Test;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
index 819a7f6fde1a..c85d600e8447 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
@@ -117,7 +117,7 @@ public abstract class SysuiTestCase {
}
protected void waitForUiOffloadThread() {
- Future<?> future = Dependency.get(UiOffloadThread.class).submit(() -> {});
+ Future<?> future = Dependency.get(UiOffloadThread.class).execute(() -> { });
try {
future.get();
} catch (InterruptedException | ExecutionException e) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
index 2bf855a27cc4..e0b4b81c368d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -45,9 +45,7 @@ import android.app.IActivityManager;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.Context;
-import android.content.Intent;
import android.content.res.Resources;
-import android.graphics.drawable.Icon;
import android.hardware.face.FaceManager;
import android.service.notification.ZenModeConfig;
import android.testing.AndroidTestingRunner;
@@ -57,7 +55,6 @@ import android.view.WindowManager;
import androidx.test.filters.SmallTest;
import com.android.internal.colorextraction.ColorExtractor;
-import com.android.systemui.R;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.colorextraction.SysuiColorExtractor;
@@ -731,6 +728,7 @@ public class BubbleControllerTest extends SysuiTestCase {
data, Runnable::run, configurationController, interruptionStateProvider,
zenModeController, lockscreenUserManager, groupManager, entryManager,
remoteInputUriController);
+ setInflateSynchronously(true);
}
}
@@ -746,17 +744,6 @@ public class BubbleControllerTest extends SysuiTestCase {
}
/**
- * @return basic {@link android.app.Notification.BubbleMetadata.Builder}
- */
- private Notification.BubbleMetadata.Builder getBuilder() {
- Intent target = new Intent(mContext, BubblesTestActivity.class);
- PendingIntent bubbleIntent = PendingIntent.getActivity(mContext, 0, target, 0);
- return new Notification.BubbleMetadata.Builder()
- .setIntent(bubbleIntent)
- .setIcon(Icon.createWithResource(mContext, R.drawable.android));
- }
-
- /**
* Sets the bubble metadata flags for this entry. These flags are normally set by
* NotificationManagerService when the notification is sent, however, these tests do not
* go through that path so we set them explicitly when testing.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java
index 1554abcec3b2..c4ae4093b680 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java
@@ -39,9 +39,9 @@ import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.bubbles.BubbleData.TimeSource;
-import com.android.systemui.statusbar.NotificationEntryBuilder;
import com.android.systemui.statusbar.NotificationTestHelper;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.google.common.collect.ImmutableList;
@@ -85,6 +85,8 @@ public class BubbleDataTest extends SysuiTestCase {
private Bubble mBubbleB2;
private Bubble mBubbleB3;
private Bubble mBubbleC1;
+ private Bubble mBubbleInterruptive;
+ private Bubble mBubbleDismissed;
private BubbleData mBubbleData;
@@ -119,18 +121,20 @@ public class BubbleDataTest extends SysuiTestCase {
modifyRanking(mEntryInterruptive)
.setVisuallyInterruptive(true)
.build();
+ mBubbleInterruptive = new Bubble(mEntryInterruptive);
ExpandableNotificationRow row = mNotificationTestHelper.createBubble();
mEntryDismissed = createBubbleEntry(1, "dismissed", "package.d");
mEntryDismissed.setRow(row);
+ mBubbleDismissed = new Bubble(mEntryDismissed);
- mBubbleA1 = new Bubble(mContext, mEntryA1);
- mBubbleA2 = new Bubble(mContext, mEntryA2);
- mBubbleA3 = new Bubble(mContext, mEntryA3);
- mBubbleB1 = new Bubble(mContext, mEntryB1);
- mBubbleB2 = new Bubble(mContext, mEntryB2);
- mBubbleB3 = new Bubble(mContext, mEntryB3);
- mBubbleC1 = new Bubble(mContext, mEntryC1);
+ mBubbleA1 = new Bubble(mEntryA1);
+ mBubbleA2 = new Bubble(mEntryA2);
+ mBubbleA3 = new Bubble(mEntryA3);
+ mBubbleB1 = new Bubble(mEntryB1);
+ mBubbleB2 = new Bubble(mEntryB2);
+ mBubbleB3 = new Bubble(mEntryB3);
+ mBubbleC1 = new Bubble(mEntryC1);
mBubbleData = new BubbleData(getContext());
@@ -180,7 +184,7 @@ public class BubbleDataTest extends SysuiTestCase {
mBubbleData.setListener(mListener);
// Test
- mBubbleData.notificationEntryUpdated(mEntryC1, /* suppressFlyout */ true, /* showInShade */
+ mBubbleData.notificationEntryUpdated(mBubbleC1, /* suppressFlyout */ true, /* showInShade */
true);
// Verify
@@ -195,7 +199,7 @@ public class BubbleDataTest extends SysuiTestCase {
mBubbleData.setListener(mListener);
// Test
- mBubbleData.notificationEntryUpdated(mEntryInterruptive,
+ mBubbleData.notificationEntryUpdated(mBubbleInterruptive,
false /* suppressFlyout */, true /* showInShade */);
// Verify
@@ -210,11 +214,11 @@ public class BubbleDataTest extends SysuiTestCase {
mBubbleData.setListener(mListener);
// Test
- mBubbleData.notificationEntryUpdated(mEntryC1, false /* suppressFlyout */,
+ mBubbleData.notificationEntryUpdated(mBubbleC1, false /* suppressFlyout */,
true /* showInShade */);
verifyUpdateReceived();
- mBubbleData.notificationEntryUpdated(mEntryC1, false /* suppressFlyout */,
+ mBubbleData.notificationEntryUpdated(mBubbleC1, false /* suppressFlyout */,
true /* showInShade */);
verifyUpdateReceived();
@@ -229,16 +233,16 @@ public class BubbleDataTest extends SysuiTestCase {
mBubbleData.setListener(mListener);
// Test
- mBubbleData.notificationEntryUpdated(mEntryDismissed, false /* suppressFlyout */,
- false /* showInShade */);
+ mBubbleData.notificationEntryUpdated(mBubbleDismissed, false /* suppressFlyout */,
+ true /* showInShade */);
verifyUpdateReceived();
// Make it look like user swiped away row
mEntryDismissed.getRow().dismiss(false /* refocusOnDismiss */);
- assertThat(mBubbleData.getBubbleWithKey(mEntryDismissed.getKey()).showInShade()).isFalse();
+ assertThat(mBubbleData.getBubbleWithKey(mBubbleDismissed.getKey()).showInShade()).isFalse();
- mBubbleData.notificationEntryUpdated(mEntryDismissed, false /* suppressFlyout */,
- false /* showInShade */);
+ mBubbleData.notificationEntryUpdated(mBubbleDismissed, false /* suppressFlyout */,
+ true /* showInShade */);
verifyUpdateReceived();
// Verify
@@ -974,7 +978,10 @@ public class BubbleDataTest extends SysuiTestCase {
private void sendUpdatedEntryAtTime(NotificationEntry entry, long postTime) {
setPostTime(entry, postTime);
- mBubbleData.notificationEntryUpdated(entry, false /* suppressFlyout*/,
+ // BubbleController calls this:
+ Bubble b = mBubbleData.getOrCreateBubble(entry);
+ // And then this
+ mBubbleData.notificationEntryUpdated(b, false /* suppressFlyout*/,
true /* showInShade */);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleTest.java
index 57578611e3f2..3c42fd1cb48d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleTest.java
@@ -28,8 +28,8 @@ import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import org.junit.Before;
import org.junit.Test;
@@ -58,7 +58,7 @@ public class BubbleTest extends SysuiTestCase {
mEntry = new NotificationEntryBuilder()
.setNotification(mNotif)
.build();
- mBubble = new Bubble(mContext, mEntry);
+ mBubble = new Bubble(mEntry);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java
index 3561e3465898..a19d1df8a713 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java
@@ -34,7 +34,9 @@ import com.android.systemui.classifier.brightline.BrightLineFalsingManager;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.util.DeviceConfigProxy;
import com.android.systemui.util.DeviceConfigProxyFake;
+import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.sensors.ProximitySensor;
+import com.android.systemui.util.time.FakeSystemClock;
import org.junit.After;
import org.junit.Before;
@@ -55,6 +57,7 @@ public class FalsingManagerProxyTest extends SysuiTestCase {
private FalsingManagerProxy mProxy;
private DeviceConfigProxy mDeviceConfig;
private TestableLooper mTestableLooper;
+ private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
@Before
public void setup() {
@@ -77,7 +80,7 @@ public class FalsingManagerProxyTest extends SysuiTestCase {
@Test
public void test_brightLineFalsingManagerDisabled() {
mProxy = new FalsingManagerProxy(getContext(), mPluginManager, mHandler, mProximitySensor,
- mDeviceConfig);
+ mDeviceConfig, mUiBgExecutor);
assertThat(mProxy.getInternalFalsingManager(), instanceOf(FalsingManagerImpl.class));
}
@@ -87,14 +90,14 @@ public class FalsingManagerProxyTest extends SysuiTestCase {
BRIGHTLINE_FALSING_MANAGER_ENABLED, "true", false);
mTestableLooper.processAllMessages();
mProxy = new FalsingManagerProxy(getContext(), mPluginManager, mHandler, mProximitySensor,
- mDeviceConfig);
+ mDeviceConfig, mUiBgExecutor);
assertThat(mProxy.getInternalFalsingManager(), instanceOf(BrightLineFalsingManager.class));
}
@Test
public void test_brightLineFalsingManagerToggled() throws InterruptedException {
mProxy = new FalsingManagerProxy(getContext(), mPluginManager, mHandler, mProximitySensor,
- mDeviceConfig);
+ mDeviceConfig, mUiBgExecutor);
assertThat(mProxy.getInternalFalsingManager(), instanceOf(FalsingManagerImpl.class));
mDeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/glwallpaper/EglHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/glwallpaper/EglHelperTest.java
index b4a60d642cb0..a5722e211f98 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/glwallpaper/EglHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/glwallpaper/EglHelperTest.java
@@ -52,7 +52,7 @@ public class EglHelperTest extends SysuiTestCase {
@Test
public void testInit_finish() {
- mEglHelper.init(mSurfaceHolder);
+ mEglHelper.init(mSurfaceHolder, false /* wideColorGamut */);
mEglHelper.finish();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/DismissCallbackRegistryTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/DismissCallbackRegistryTest.java
index 7fa1dbeafced..a00cabc71a0c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/DismissCallbackRegistryTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/DismissCallbackRegistryTest.java
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
package com.android.systemui.keyguard;
@@ -24,6 +24,8 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.time.FakeSystemClock;
import org.junit.Before;
import org.junit.Test;
@@ -41,10 +43,11 @@ public class DismissCallbackRegistryTest extends SysuiTestCase {
private DismissCallbackRegistry mDismissCallbackRegistry;
private @Mock IKeyguardDismissCallback mMockCallback;
private @Mock IKeyguardDismissCallback mMockCallback2;
+ private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
@Before
public void setUp() throws Exception {
- mDismissCallbackRegistry = new DismissCallbackRegistry();
+ mDismissCallbackRegistry = new DismissCallbackRegistry(mUiBgExecutor);
MockitoAnnotations.initMocks(this);
}
@@ -52,7 +55,7 @@ public class DismissCallbackRegistryTest extends SysuiTestCase {
public void testCancelled() throws Exception {
mDismissCallbackRegistry.addCallback(mMockCallback);
mDismissCallbackRegistry.notifyDismissCancelled();
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
verify(mMockCallback).onDismissCancelled();
}
@@ -61,7 +64,7 @@ public class DismissCallbackRegistryTest extends SysuiTestCase {
mDismissCallbackRegistry.addCallback(mMockCallback);
mDismissCallbackRegistry.addCallback(mMockCallback2);
mDismissCallbackRegistry.notifyDismissCancelled();
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
verify(mMockCallback).onDismissCancelled();
verify(mMockCallback2).onDismissCancelled();
}
@@ -70,7 +73,7 @@ public class DismissCallbackRegistryTest extends SysuiTestCase {
public void testSucceeded() throws Exception {
mDismissCallbackRegistry.addCallback(mMockCallback);
mDismissCallbackRegistry.notifyDismissSucceeded();
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
verify(mMockCallback).onDismissSucceeded();
}
@@ -79,7 +82,7 @@ public class DismissCallbackRegistryTest extends SysuiTestCase {
mDismissCallbackRegistry.addCallback(mMockCallback);
mDismissCallbackRegistry.addCallback(mMockCallback2);
mDismissCallbackRegistry.notifyDismissSucceeded();
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
verify(mMockCallback).onDismissSucceeded();
verify(mMockCallback2).onDismissSucceeded();
}
@@ -89,7 +92,7 @@ public class DismissCallbackRegistryTest extends SysuiTestCase {
mDismissCallbackRegistry.addCallback(mMockCallback);
mDismissCallbackRegistry.notifyDismissSucceeded();
mDismissCallbackRegistry.notifyDismissSucceeded();
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
verify(mMockCallback, times(1)).onDismissSucceeded();
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
index a8a2b33215e5..64fbc1bac658 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -38,6 +38,8 @@ import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.phone.StatusBarWindowController;
+import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.time.FakeSystemClock;
import org.junit.Before;
import org.junit.Test;
@@ -58,6 +60,7 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
private @Mock StatusBarWindowController mStatusBarWindowController;
private @Mock BroadcastDispatcher mBroadcastDispatcher;
private @Mock DismissCallbackRegistry mDismissCallbackRegistry;
+ private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
private FalsingManagerFake mFalsingManager;
@@ -75,7 +78,7 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
mViewMediator = new KeyguardViewMediator(
mContext, mFalsingManager, mLockPatternUtils, mBroadcastDispatcher,
mStatusBarWindowController, () -> mStatusBarKeyguardViewManager,
- mDismissCallbackRegistry);
+ mDismissCallbackRegistry, mUiBgExecutor);
});
}
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 800456228e84..b7e9f074ad9a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
@@ -31,6 +31,7 @@ import android.view.View;
import android.widget.FrameLayout;
import androidx.test.filters.SmallTest;
+import androidx.test.filters.Suppress;
import com.android.internal.logging.MetricsLogger;
import com.android.keyguard.CarrierText;
@@ -64,7 +65,7 @@ import java.util.Optional;
@RunWith(AndroidTestingRunner.class)
@RunWithLooper
@SmallTest
-@Ignore
+@Suppress
public class QSFragmentTest extends SysuiBaseFragmentTest {
private MetricsLogger mMockMetricsLogger;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
index 49b47c5c72d4..6bd24b954bda 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
@@ -47,6 +47,7 @@ import androidx.test.filters.SmallTest;
import com.android.internal.logging.MetricsLogger;
import com.android.systemui.Dependency;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.qs.QSHost;
@@ -83,6 +84,7 @@ public class QSTileImplTest extends SysuiTestCase {
String spec = "spec";
mTestableLooper = TestableLooper.get(this);
mDependency.injectTestDependency(Dependency.BG_LOOPER, mTestableLooper.getLooper());
+ mDependency.injectMockDependency(ActivityStarter.class);
mMetricsLogger = mDependency.injectMockDependency(MetricsLogger.class);
mStatusBarStateController =
mDependency.injectMockDependency(StatusBarStateController.class);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java
index 6d85d37537ea..2c7cee3e2be1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java
@@ -16,8 +16,6 @@
package com.android.systemui.screenshot;
-import static android.content.Context.NOTIFICATION_SERVICE;
-
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
@@ -29,7 +27,6 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Notification;
-import android.app.NotificationManager;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
@@ -42,7 +39,6 @@ import androidx.test.filters.SmallTest;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.util.NotificationChannels;
import org.junit.Assert;
import org.junit.Before;
@@ -84,7 +80,7 @@ public class ScreenshotNotificationSmartActionsTest extends SysuiTestCase {
eq(false))).thenThrow(
RuntimeException.class);
CompletableFuture<List<Notification.Action>> smartActionsFuture =
- GlobalScreenshot.getSmartActionsFuture("", bitmap,
+ ScreenshotSmartActions.getSmartActionsFuture("", bitmap,
smartActionsProvider, true, false);
Assert.assertNotNull(smartActionsFuture);
List<Notification.Action> smartActions = smartActionsFuture.get(5, TimeUnit.MILLISECONDS);
@@ -101,7 +97,7 @@ public class ScreenshotNotificationSmartActionsTest extends SysuiTestCase {
int timeoutMs = 1000;
when(smartActionsFuture.get(timeoutMs, TimeUnit.MILLISECONDS)).thenThrow(
RuntimeException.class);
- List<Notification.Action> actions = GlobalScreenshot.getSmartActions(
+ List<Notification.Action> actions = ScreenshotSmartActions.getSmartActions(
"", smartActionsFuture, timeoutMs, mSmartActionsProvider);
Assert.assertEquals(Collections.emptyList(), actions);
}
@@ -112,7 +108,7 @@ public class ScreenshotNotificationSmartActionsTest extends SysuiTestCase {
throws Exception {
doThrow(RuntimeException.class).when(mSmartActionsProvider).notifyOp(any(), any(), any(),
anyLong());
- GlobalScreenshot.notifyScreenshotOp(null, mSmartActionsProvider, null, null, -1);
+ ScreenshotSmartActions.notifyScreenshotOp(null, mSmartActionsProvider, null, null, -1);
}
// Tests for a non-hardware bitmap, ScreenshotNotificationSmartActionsProvider is never invoked
@@ -123,7 +119,7 @@ public class ScreenshotNotificationSmartActionsTest extends SysuiTestCase {
Bitmap bitmap = mock(Bitmap.class);
when(bitmap.getConfig()).thenReturn(Bitmap.Config.RGB_565);
CompletableFuture<List<Notification.Action>> smartActionsFuture =
- GlobalScreenshot.getSmartActionsFuture("", bitmap,
+ ScreenshotSmartActions.getSmartActionsFuture("", bitmap,
mSmartActionsProvider, true, true);
verify(mSmartActionsProvider, never()).getActions(any(), any(), any(),
eq(false));
@@ -137,7 +133,7 @@ public class ScreenshotNotificationSmartActionsTest extends SysuiTestCase {
public void testScreenshotNotificationSmartActionsProviderInvokedOnce() {
Bitmap bitmap = mock(Bitmap.class);
when(bitmap.getConfig()).thenReturn(Bitmap.Config.HARDWARE);
- GlobalScreenshot.getSmartActionsFuture("", bitmap, mSmartActionsProvider,
+ ScreenshotSmartActions.getSmartActionsFuture("", bitmap, mSmartActionsProvider,
true, true);
verify(mSmartActionsProvider, times(1))
.getActions(any(), any(), any(), eq(true));
@@ -153,7 +149,7 @@ public class ScreenshotNotificationSmartActionsTest extends SysuiTestCase {
SystemUIFactory.getInstance().createScreenshotNotificationSmartActionsProvider(
mContext, null, mHandler);
CompletableFuture<List<Notification.Action>> smartActionsFuture =
- GlobalScreenshot.getSmartActionsFuture("", bitmap,
+ ScreenshotSmartActions.getSmartActionsFuture("", bitmap,
actionsProvider,
true, true);
Assert.assertNotNull(smartActionsFuture);
@@ -167,31 +163,23 @@ public class ScreenshotNotificationSmartActionsTest extends SysuiTestCase {
if (Looper.myLooper() == null) {
Looper.prepare();
}
- NotificationManager notificationManager =
- (NotificationManager) mContext.getSystemService(NOTIFICATION_SERVICE);
+
GlobalScreenshot.SaveImageInBackgroundData
data = new GlobalScreenshot.SaveImageInBackgroundData();
- data.context = mContext;
data.image = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
- data.iconSize = 10;
data.finisher = null;
data.mActionsReadyListener = null;
- data.previewWidth = 10;
- data.previewheight = 10;
- SaveImageInBackgroundTask task = new SaveImageInBackgroundTask(mContext, data,
- notificationManager);
- Notification.Builder notificationBuilder = new Notification.Builder(mContext,
- NotificationChannels.SCREENSHOTS_HEADSUP);
- task.populateNotificationActions(mContext, mContext.getResources(),
+ SaveImageInBackgroundTask task = new SaveImageInBackgroundTask(mContext, data);
+ List<Notification.Action> actions = task.populateNotificationActions(
+ mContext, mContext.getResources(),
Uri.parse("Screenshot_123.png"),
- CompletableFuture.completedFuture(Collections.emptyList()), notificationBuilder);
+ CompletableFuture.completedFuture(Collections.emptyList()));
- Notification notification = notificationBuilder.build();
- Assert.assertEquals(notification.actions.length, 3);
+ Assert.assertEquals(actions.size(), 3);
boolean isShareFound = false;
boolean isEditFound = false;
boolean isDeleteFound = false;
- for (Notification.Action action : notification.actions) {
+ for (Notification.Action action : actions) {
Intent intent = action.actionIntent.getIntent();
Assert.assertNotNull(intent);
Bundle bundle = intent.getExtras();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java
index c6dd23262b85..402a99d4c23d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java
@@ -17,7 +17,7 @@
package com.android.systemui.statusbar;
-import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_CONTRACTED;
+import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_CONTRACTED;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
@@ -40,6 +40,7 @@ import androidx.test.filters.SmallTest;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import org.junit.Before;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java
index e67aa69d48ce..bb9c14bbb2a3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java
@@ -26,7 +26,6 @@ import androidx.test.filters.SmallTest;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.Dependency;
-import com.android.systemui.InitController;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -86,7 +85,6 @@ public class NonPhoneDependencyTest extends SysuiTestCase {
Dependency.get(NotificationLockscreenUserManager.class);
NotificationViewHierarchyManager viewHierarchyManager =
Dependency.get(NotificationViewHierarchyManager.class);
- Dependency.get(InitController.class).executePostInitTasks();
entryManager.setUpWithPresenter(mPresenter, mListContainer, mHeadsUpManager);
entryManager.addNotificationEntryListener(mEntryListener);
gutsManager.setUpWithPresenter(mPresenter, mListContainer,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInterruptionStateProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInterruptionStateProviderTest.java
index 9b860c9e0ba7..677a6fc6b46e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInterruptionStateProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInterruptionStateProviderTest.java
@@ -52,6 +52,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.NotificationFilter;
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
index cef210cef19a..3a6accea2b54 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
@@ -56,6 +56,7 @@ import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java
index 8aac1891a5e4..64b10c816da7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java
@@ -29,6 +29,7 @@ import com.android.systemui.statusbar.NotificationRemoteInputManager.RemoteInput
import com.android.systemui.statusbar.NotificationRemoteInputManager.SmartReplyHistoryExtender;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.RemoteInputUriController;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
index 88546b9b31a7..40b0ba9bf633 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
@@ -22,6 +22,7 @@ import static android.app.NotificationManager.IMPORTANCE_HIGH;
import static com.android.systemui.statusbar.NotificationEntryHelper.modifyRanking;
+import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import android.annotation.Nullable;
@@ -44,15 +45,19 @@ import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.bubbles.BubblesTestActivity;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
-import com.android.systemui.statusbar.notification.row.NotificationContentInflaterTest;
+import com.android.systemui.statusbar.notification.row.NotificationContentInflater;
+import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag;
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.StatusBarWindowController;
import com.android.systemui.tests.R;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
/**
* A helper class to create {@link ExpandableNotificationRow} (for both individual and group
* notifications).
@@ -324,10 +329,8 @@ public class NotificationTestHelper {
entry.setRow(row);
entry.createIcons(mContext, entry.getSbn());
row.setEntry(entry);
- row.getNotificationInflater().addInflationFlags(extraInflationFlags);
- NotificationContentInflaterTest.runThenWaitForInflation(
- () -> row.inflateViews(),
- row.getNotificationInflater());
+ row.setInflationFlags(extraInflationFlags);
+ inflateAndWait(row);
// This would be done as part of onAsyncInflationFinished, but we skip large amounts of
// the callback chain, so we need to make up for not adding it to the group manager
@@ -336,6 +339,28 @@ public class NotificationTestHelper {
return row;
}
+ private static void inflateAndWait(ExpandableNotificationRow row) throws Exception {
+ CountDownLatch countDownLatch = new CountDownLatch(1);
+ row.getNotificationInflater().setInflateSynchronously(true);
+ NotificationContentInflater.InflationCallback callback =
+ new NotificationContentInflater.InflationCallback() {
+ @Override
+ public void handleInflationException(StatusBarNotification notification,
+ Exception e) {
+ countDownLatch.countDown();
+ }
+
+ @Override
+ public void onAsyncInflationFinished(NotificationEntry entry,
+ int inflatedFlags) {
+ countDownLatch.countDown();
+ }
+ };
+ row.setInflationCallback(callback);
+ row.inflateViews();
+ assertTrue(countDownLatch.await(500, TimeUnit.MILLISECONDS));
+ }
+
private BubbleMetadata makeBubbleMetadata(PendingIntent deleteIntent) {
Intent target = new Intent(mContext, BubblesTestActivity.class);
PendingIntent bubbleIntent = PendingIntent.getActivity(mContext, 0, target, 0);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
index 07d2e3128d87..c97813de8c0c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
@@ -38,8 +38,6 @@ import android.widget.LinearLayout;
import androidx.test.filters.SmallTest;
-import com.android.systemui.Dependency;
-import com.android.systemui.InitController;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
@@ -47,6 +45,7 @@ import com.android.systemui.statusbar.notification.DynamicPrivacyController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableView;
@@ -106,7 +105,6 @@ public class NotificationViewHierarchyManagerTest extends SysuiTestCase {
mock(KeyguardBypassController.class),
mock(BubbleController.class),
mock(DynamicPrivacyController.class));
- Dependency.get(InitController.class).executePostInitTasks();
mViewHierarchyManager.setUpWithPresenter(mPresenter, mListContainer);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java
index 3f624128ac2c..22dc0803339c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java
@@ -41,6 +41,7 @@ import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.RemoteInputUriController;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
index e0dfe7e66ad5..f55ea4ff8ef2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
@@ -62,11 +62,9 @@ import com.android.internal.logging.MetricsLogger;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.Dependency;
import com.android.systemui.ForegroundServiceController;
-import com.android.systemui.InitController;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.NotificationEntryBuilder;
import com.android.systemui.statusbar.NotificationLifetimeExtender;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
@@ -80,6 +78,7 @@ import com.android.systemui.statusbar.SmartReplyController;
import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.notification.NotificationEntryManager.KeyguardEnvironment;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
import com.android.systemui.statusbar.notification.collection.NotificationRowBinder;
import com.android.systemui.statusbar.notification.collection.NotificationRowBinderImpl;
@@ -233,7 +232,6 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
mock(PeopleNotificationIdentifier.class)),
mEnvironment
);
- Dependency.get(InitController.class).executePostInitTasks();
mEntryManager.setUpWithPresenter(mPresenter, mListContainer, mHeadsUpManager);
mEntryManager.addNotificationEntryListener(mEntryListener);
mEntryManager.setNotificationRemoveInterceptor(mRemoveInterceptor);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java
index 7fabb0fee8e2..5aed61b98ad9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java
@@ -41,11 +41,11 @@ import androidx.test.filters.SmallTest;
import com.android.systemui.ForegroundServiceController;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.NotificationEntryBuilder;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationTestHelper;
import com.android.systemui.statusbar.notification.NotificationEntryManager.KeyguardEnvironment;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.ShadeController;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java
index 133d52b4f946..7343e5e9e07d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java
@@ -30,9 +30,9 @@ import androidx.test.filters.SmallTest;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.NotificationEntryBuilder;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/VisualStabilityManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/VisualStabilityManagerTest.java
index 6a4ddc7ec202..9079223649ff 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/VisualStabilityManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/VisualStabilityManagerTest.java
@@ -31,9 +31,9 @@ import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.NotificationEntryBuilder;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import org.junit.Before;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/GroupEntryTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/GroupEntryTest.java
index 721bbdc1f700..a06d6c1e593b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/GroupEntryTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/GroupEntryTest.java
@@ -27,7 +27,6 @@ import android.testing.AndroidTestingRunner;
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.NotificationEntryBuilder;
import com.android.systemui.statusbar.RankingBuilder;
import org.junit.Test;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
index 8d9537d9afc3..0dcd25300633 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
@@ -48,7 +48,6 @@ import androidx.test.filters.SmallTest;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.NotificationEntryBuilder;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationListener.NotifServiceListener;
import com.android.systemui.statusbar.RankingBuilder;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImplTest.java
index bbabb1154e03..6e9c2c8adb4a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImplTest.java
@@ -28,6 +28,7 @@ import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -38,7 +39,6 @@ import android.util.ArrayMap;
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.NotifListBuilderImpl.OnRenderListListener;
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener;
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeSortListener;
@@ -336,7 +336,7 @@ public class NotifListBuilderImplTest extends SysuiTestCase {
// GIVEN a notification that is initially added to the list
PackageFilter filter = new PackageFilter(PACKAGE_2);
filter.setEnabled(false);
- mListBuilder.addFilter(filter);
+ mListBuilder.addPreGroupFilter(filter);
addNotif(0, PACKAGE_1);
addNotif(1, PACKAGE_2);
@@ -373,24 +373,54 @@ public class NotifListBuilderImplTest extends SysuiTestCase {
notif(2)
);
- // THEN the list of newly visible entries doesn't contain the summary or the group
- assertEquals(
- Arrays.asList(
- mEntrySet.get(0),
- mEntrySet.get(2)),
- listener.newlyVisibleEntries
- );
-
// THEN the summary has a null parent and an unset firstAddedIteration
assertNull(mEntrySet.get(1).getParent());
assertEquals(-1, mEntrySet.get(1).mFirstAddedIteration);
}
@Test
- public void testNotifsAreFiltered() {
+ public void testPreGroupNotifsAreFiltered() {
+ // GIVEN a PreGroupNotifFilter and PreRenderFilter that filters out the same package
+ NotifFilter preGroupFilter = spy(new PackageFilter(PACKAGE_2));
+ NotifFilter preRenderFilter = spy(new PackageFilter(PACKAGE_2));
+ mListBuilder.addPreGroupFilter(preGroupFilter);
+ mListBuilder.addPreRenderFilter(preRenderFilter);
+
+ // WHEN the pipeline is kicked off on a list of notifs
+ addNotif(0, PACKAGE_1);
+ addNotif(1, PACKAGE_2);
+ addNotif(2, PACKAGE_3);
+ addNotif(3, PACKAGE_2);
+ dispatchBuild();
+
+ // THEN the preGroupFilter is called on each notif in the original set
+ verify(preGroupFilter).shouldFilterOut(eq(mEntrySet.get(0)), anyLong());
+ verify(preGroupFilter).shouldFilterOut(eq(mEntrySet.get(1)), anyLong());
+ verify(preGroupFilter).shouldFilterOut(eq(mEntrySet.get(2)), anyLong());
+ verify(preGroupFilter).shouldFilterOut(eq(mEntrySet.get(3)), anyLong());
+
+ // THEN the preRenderFilter is only called on the notifications not already filtered out
+ verify(preRenderFilter).shouldFilterOut(eq(mEntrySet.get(0)), anyLong());
+ verify(preRenderFilter, never()).shouldFilterOut(eq(mEntrySet.get(1)), anyLong());
+ verify(preRenderFilter).shouldFilterOut(eq(mEntrySet.get(2)), anyLong());
+ verify(preRenderFilter, never()).shouldFilterOut(eq(mEntrySet.get(3)), anyLong());
+
+ // THEN the final list doesn't contain any filtered-out notifs
+ verifyBuiltList(
+ notif(0),
+ notif(2)
+ );
+
+ // THEN each filtered notif records the NotifFilter that did it
+ assertEquals(preGroupFilter, mEntrySet.get(1).mExcludingFilter);
+ assertEquals(preGroupFilter, mEntrySet.get(3).mExcludingFilter);
+ }
+
+ @Test
+ public void testPreRenderNotifsAreFiltered() {
// GIVEN a NotifFilter that filters out a specific package
NotifFilter filter1 = spy(new PackageFilter(PACKAGE_2));
- mListBuilder.addFilter(filter1);
+ mListBuilder.addPreRenderFilter(filter1);
// WHEN the pipeline is kicked off on a list of notifs
addNotif(0, PACKAGE_1);
@@ -421,8 +451,8 @@ public class NotifListBuilderImplTest extends SysuiTestCase {
// GIVEN two notif filters
NotifFilter filter1 = spy(new PackageFilter(PACKAGE_2));
NotifFilter filter2 = spy(new PackageFilter(PACKAGE_5));
- mListBuilder.addFilter(filter1);
- mListBuilder.addFilter(filter2);
+ mListBuilder.addPreGroupFilter(filter1);
+ mListBuilder.addPreGroupFilter(filter2);
// WHEN the pipeline is kicked off on a list of notifs
addNotif(0, PACKAGE_1);
@@ -522,7 +552,7 @@ public class NotifListBuilderImplTest extends SysuiTestCase {
public void testNotifsAreSectioned() {
// GIVEN a filter that removes all PACKAGE_4 notifs and a SectionsProvider that divides
// notifs based on package name
- mListBuilder.addFilter(new PackageFilter(PACKAGE_4));
+ mListBuilder.addPreGroupFilter(new PackageFilter(PACKAGE_4));
final SectionsProvider sectionsProvider = spy(new PackageSectioner());
mListBuilder.setSectionsProvider(sectionsProvider);
@@ -596,17 +626,19 @@ public class NotifListBuilderImplTest extends SysuiTestCase {
@Test
public void testListenersAndPluggablesAreFiredInOrder() {
// GIVEN a bunch of registered listeners and pluggables
- NotifFilter filter = spy(new PackageFilter(PACKAGE_1));
+ NotifFilter preGroupFilter = spy(new PackageFilter(PACKAGE_1));
NotifPromoter promoter = spy(new IdPromoter(3));
PackageSectioner sectioner = spy(new PackageSectioner());
NotifComparator comparator = spy(new HypeComparator(PACKAGE_4));
- mListBuilder.addFilter(filter);
+ NotifFilter preRenderFilter = spy(new PackageFilter(PACKAGE_5));
+ mListBuilder.addPreGroupFilter(preGroupFilter);
mListBuilder.addOnBeforeTransformGroupsListener(mOnBeforeTransformGroupsListener);
mListBuilder.addPromoter(promoter);
mListBuilder.addOnBeforeSortListener(mOnBeforeSortListener);
mListBuilder.setComparators(Collections.singletonList(comparator));
mListBuilder.setSectionsProvider(sectioner);
mListBuilder.addOnBeforeRenderListListener(mOnBeforeRenderListListener);
+ mListBuilder.addPreRenderFilter(preRenderFilter);
// WHEN a few new notifs are added
addNotif(0, PACKAGE_1);
@@ -620,25 +652,28 @@ public class NotifListBuilderImplTest extends SysuiTestCase {
// THEN the pluggables and listeners are called in order
InOrder inOrder = inOrder(
- filter,
+ preGroupFilter,
mOnBeforeTransformGroupsListener,
promoter,
mOnBeforeSortListener,
sectioner,
comparator,
+ preRenderFilter,
mOnBeforeRenderListListener,
mOnRenderListListener);
- inOrder.verify(filter, atLeastOnce())
+ inOrder.verify(preGroupFilter, atLeastOnce())
.shouldFilterOut(any(NotificationEntry.class), anyLong());
inOrder.verify(mOnBeforeTransformGroupsListener)
- .onBeforeTransformGroups(anyList(), anyList());
+ .onBeforeTransformGroups(anyList());
inOrder.verify(promoter, atLeastOnce())
.shouldPromoteToTopLevel(any(NotificationEntry.class));
inOrder.verify(mOnBeforeSortListener).onBeforeSort(anyList());
inOrder.verify(sectioner, atLeastOnce()).getSection(any(ListEntry.class));
inOrder.verify(comparator, atLeastOnce())
.compare(any(ListEntry.class), any(ListEntry.class));
+ inOrder.verify(preRenderFilter, atLeastOnce())
+ .shouldFilterOut(any(NotificationEntry.class), anyLong());
inOrder.verify(mOnBeforeRenderListListener).onBeforeRenderList(anyList());
inOrder.verify(mOnRenderListListener).onRenderList(anyList());
}
@@ -651,7 +686,7 @@ public class NotifListBuilderImplTest extends SysuiTestCase {
SectionsProvider sectionsProvider = new PackageSectioner();
NotifComparator hypeComparator = new HypeComparator(PACKAGE_2);
- mListBuilder.addFilter(packageFilter);
+ mListBuilder.addPreGroupFilter(packageFilter);
mListBuilder.addPromoter(idPromoter);
mListBuilder.setSectionsProvider(sectionsProvider);
mListBuilder.setComparators(Collections.singletonList(hypeComparator));
@@ -687,12 +722,12 @@ public class NotifListBuilderImplTest extends SysuiTestCase {
NotifFilter filter1 = spy(new PackageFilter(PACKAGE_5));
NotifFilter filter2 = spy(new PackageFilter(PACKAGE_5));
NotifFilter filter3 = spy(new PackageFilter(PACKAGE_5));
- mListBuilder.addFilter(filter1);
- mListBuilder.addFilter(filter2);
- mListBuilder.addFilter(filter3);
+ mListBuilder.addPreGroupFilter(filter1);
+ mListBuilder.addPreGroupFilter(filter2);
+ mListBuilder.addPreGroupFilter(filter3);
// GIVEN the SystemClock is set to a particular time:
- mSystemClock.setUptimeMillis(47);
+ mSystemClock.setUptimeMillis(10047);
// WHEN the pipeline is kicked off on a list of notifs
addNotif(0, PACKAGE_1);
@@ -700,22 +735,22 @@ public class NotifListBuilderImplTest extends SysuiTestCase {
dispatchBuild();
// THEN the value of `now` is the same for all calls to shouldFilterOut
- verify(filter1).shouldFilterOut(mEntrySet.get(0), 47);
- verify(filter2).shouldFilterOut(mEntrySet.get(0), 47);
- verify(filter3).shouldFilterOut(mEntrySet.get(0), 47);
- verify(filter1).shouldFilterOut(mEntrySet.get(1), 47);
- verify(filter2).shouldFilterOut(mEntrySet.get(1), 47);
- verify(filter3).shouldFilterOut(mEntrySet.get(1), 47);
+ verify(filter1).shouldFilterOut(mEntrySet.get(0), 10047);
+ verify(filter2).shouldFilterOut(mEntrySet.get(0), 10047);
+ verify(filter3).shouldFilterOut(mEntrySet.get(0), 10047);
+ verify(filter1).shouldFilterOut(mEntrySet.get(1), 10047);
+ verify(filter2).shouldFilterOut(mEntrySet.get(1), 10047);
+ verify(filter3).shouldFilterOut(mEntrySet.get(1), 10047);
}
@Test
- public void testNewlyAddedEntries() {
+ public void testGroupTransformEntries() {
// GIVEN a registered OnBeforeTransformGroupsListener
RecordingOnBeforeTransformGroupsListener listener =
spy(new RecordingOnBeforeTransformGroupsListener());
mListBuilder.addOnBeforeTransformGroupsListener(listener);
- // Given some new notifs
+ // GIVEN some new notifs
addNotif(0, PACKAGE_1);
addGroupChild(1, PACKAGE_2, GROUP_1);
addGroupSummary(2, PACKAGE_2, GROUP_1);
@@ -743,27 +778,18 @@ public class NotifListBuilderImplTest extends SysuiTestCase {
mEntrySet.get(0),
mBuiltList.get(1),
mEntrySet.get(4)
- ),
- Arrays.asList(
- mEntrySet.get(0),
- mEntrySet.get(1),
- mBuiltList.get(1),
- mEntrySet.get(2),
- mEntrySet.get(3),
- mEntrySet.get(4),
- mEntrySet.get(5)
)
);
}
@Test
- public void testNewlyAddedEntriesOnSecondRun() {
+ public void testGroupTransformEntriesOnSecondRun() {
// GIVEN a registered OnBeforeTransformGroupsListener
RecordingOnBeforeTransformGroupsListener listener =
spy(new RecordingOnBeforeTransformGroupsListener());
mListBuilder.addOnBeforeTransformGroupsListener(listener);
- // Given some notifs that have already been added (two of which are in malformed groups)
+ // GIVEN some notifs that have already been added (two of which are in malformed groups)
addNotif(0, PACKAGE_1);
addGroupChild(1, PACKAGE_2, GROUP_1);
addGroupChild(2, PACKAGE_3, GROUP_2);
@@ -799,13 +825,6 @@ public class NotifListBuilderImplTest extends SysuiTestCase {
mEntrySet.get(1),
mBuiltList.get(2),
mEntrySet.get(7)
- ),
- Arrays.asList(
- mBuiltList.get(2),
- mEntrySet.get(4),
- mEntrySet.get(5),
- mEntrySet.get(6),
- mEntrySet.get(7)
)
);
}
@@ -842,19 +861,18 @@ public class NotifListBuilderImplTest extends SysuiTestCase {
}
@Test(expected = IllegalStateException.class)
- public void testOutOfOrderFilterInvalidationThrows() {
- // GIVEN a NotifFilter that gets invalidated during the grouping stage
+ public void testOutOfOrderPreGroupFilterInvalidationThrows() {
+ // GIVEN a PreGroupNotifFilter that gets invalidated during the grouping stage
NotifFilter filter = new PackageFilter(PACKAGE_5);
- OnBeforeTransformGroupsListener listener =
- (list, newlyVisibleEntries) -> filter.invalidateList();
- mListBuilder.addFilter(filter);
+ OnBeforeTransformGroupsListener listener = (list) -> filter.invalidateList();
+ mListBuilder.addPreGroupFilter(filter);
mListBuilder.addOnBeforeTransformGroupsListener(listener);
// WHEN we try to run the pipeline and the filter is invalidated
addNotif(0, PACKAGE_1);
dispatchBuild();
- // Then an exception is thrown
+ // THEN an exception is thrown
}
@Test(expected = IllegalStateException.class)
@@ -870,7 +888,7 @@ public class NotifListBuilderImplTest extends SysuiTestCase {
addNotif(0, PACKAGE_1);
dispatchBuild();
- // Then an exception is thrown
+ // THEN an exception is thrown
}
@Test(expected = IllegalStateException.class)
@@ -886,7 +904,37 @@ public class NotifListBuilderImplTest extends SysuiTestCase {
addNotif(0, PACKAGE_1);
dispatchBuild();
- // Then an exception is thrown
+ // THEN an exception is thrown
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testOutOfOrderPreRenderFilterInvalidationThrows() {
+ // GIVEN a PreRenderNotifFilter that gets invalidated during the finalizing stage
+ NotifFilter filter = new PackageFilter(PACKAGE_5);
+ OnBeforeRenderListListener listener = (list) -> filter.invalidateList();
+ mListBuilder.addPreRenderFilter(filter);
+ mListBuilder.addOnBeforeRenderListListener(listener);
+
+ // WHEN we try to run the pipeline and the PreRenderFilter is invalidated
+ addNotif(0, PACKAGE_1);
+ dispatchBuild();
+
+ // THEN an exception is thrown
+ }
+
+ @Test
+ public void testInOrderPreRenderFilter() {
+ // GIVEN a PreRenderFilter that gets invalidated during the grouping stage
+ NotifFilter filter = new PackageFilter(PACKAGE_5);
+ OnBeforeTransformGroupsListener listener = (list) -> filter.invalidateList();
+ mListBuilder.addPreRenderFilter(filter);
+ mListBuilder.addOnBeforeTransformGroupsListener(listener);
+
+ // WHEN we try to run the pipeline and the filter is invalidated
+ addNotif(0, PACKAGE_1);
+ dispatchBuild();
+
+ // THEN no exception thrown
}
/**
@@ -1178,13 +1226,9 @@ public class NotifListBuilderImplTest extends SysuiTestCase {
private static class RecordingOnBeforeTransformGroupsListener
implements OnBeforeTransformGroupsListener {
- public List<ListEntry> newlyVisibleEntries;
@Override
- public void onBeforeTransformGroups(List<ListEntry> list,
- List<ListEntry> newlyVisibleEntries) {
- this.newlyVisibleEntries = newlyVisibleEntries;
- }
+ public void onBeforeTransformGroups(List<ListEntry> list) { }
}
private static final String PACKAGE_1 = "com.test1";
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryBuilder.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryBuilder.java
index d18b16be33d6..e6a61d62a5b4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryBuilder.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryBuilder.java
@@ -14,18 +14,19 @@
* limitations under the License.
*/
-package com.android.systemui.statusbar;
+package com.android.systemui.statusbar.notification.collection;
import android.annotation.Nullable;
import android.app.Notification;
import android.app.NotificationChannel;
-import android.app.NotificationManager.Importance;
+import android.app.NotificationManager;
import android.content.Context;
import android.os.UserHandle;
import android.service.notification.SnoozeCriterion;
import android.service.notification.StatusBarNotification;
-import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.RankingBuilder;
+import com.android.systemui.statusbar.SbnBuilder;
import java.util.ArrayList;
@@ -34,6 +35,8 @@ import java.util.ArrayList;
* and Ranking. Is largely a proxy for the SBN and Ranking builders, but does a little extra magic
* to make sure the keys match between the two, etc.
*
+ * Has the ability to set ListEntry properties as well.
+ *
* Only for use in tests.
*/
public class NotificationEntryBuilder {
@@ -41,10 +44,35 @@ public class NotificationEntryBuilder {
private final RankingBuilder mRankingBuilder = new RankingBuilder();
private StatusBarNotification mSbn = null;
+ /* ListEntry properties */
+ private GroupEntry mParent;
+ private int mSection;
+
public NotificationEntry build() {
StatusBarNotification sbn = mSbn != null ? mSbn : mSbnBuilder.build();
mRankingBuilder.setKey(sbn.getKey());
- return new NotificationEntry(sbn, mRankingBuilder.build());
+ final NotificationEntry entry = new NotificationEntry(sbn, mRankingBuilder.build());
+
+ /* ListEntry properties */
+ entry.setParent(mParent);
+ entry.setSection(mSection);
+ return entry;
+ }
+
+ /**
+ * Sets the parent.
+ */
+ public NotificationEntryBuilder setParent(@Nullable GroupEntry parent) {
+ mParent = parent;
+ return this;
+ }
+
+ /**
+ * Sets the section.
+ */
+ public NotificationEntryBuilder setSection(int section) {
+ mSection = section;
+ return this;
}
/**
@@ -176,7 +204,7 @@ public class NotificationEntryBuilder {
return this;
}
- public NotificationEntryBuilder setImportance(@Importance int importance) {
+ public NotificationEntryBuilder setImportance(@NotificationManager.Importance int importance) {
mRankingBuilder.setImportance(importance);
return this;
}
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 17d556dbd201..39ae68a40291 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
@@ -52,7 +52,6 @@ import androidx.test.filters.SmallTest;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.NotificationEntryBuilder;
import com.android.systemui.statusbar.RankingBuilder;
import com.android.systemui.statusbar.SbnBuilder;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt
index 1764bef57d27..10450fa82cde 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt
@@ -24,7 +24,6 @@ import android.service.notification.NotificationListenerService.RankingMap
import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
-import com.android.systemui.statusbar.NotificationEntryBuilder
import com.android.systemui.statusbar.NotificationEntryHelper.modifyRanking
import com.android.systemui.statusbar.NotificationMediaManager
import com.android.systemui.statusbar.notification.NotificationFilter
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinatorTest.java
index a9413c78d770..ea6c70a6e142 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinatorTest.java
@@ -35,10 +35,10 @@ import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.NotificationEntryBuilder;
import com.android.systemui.statusbar.RankingBuilder;
import com.android.systemui.statusbar.notification.collection.NotifListBuilderImpl;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
@@ -85,7 +85,7 @@ public class DeviceProvisionedCoordinatorTest extends SysuiTestCase {
ArgumentCaptor<NotifFilter> filterCaptor = ArgumentCaptor.forClass(NotifFilter.class);
mDeviceProvisionedCoordinator.attach(null, mNotifListBuilder);
- verify(mNotifListBuilder, times(1)).addFilter(filterCaptor.capture());
+ verify(mNotifListBuilder, times(1)).addPreGroupFilter(filterCaptor.capture());
mDeviceProvisionedFilter = filterCaptor.getValue();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinatorTest.java
index ffaa335f91bc..01bca0dc1078 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinatorTest.java
@@ -36,11 +36,11 @@ import androidx.test.filters.SmallTest;
import com.android.systemui.ForegroundServiceController;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.appops.AppOpsController;
-import com.android.systemui.statusbar.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifLifetimeExtender;
import com.android.systemui.statusbar.notification.collection.NotifListBuilderImpl;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import org.junit.Before;
@@ -85,7 +85,7 @@ public class ForegroundCoordinatorTest extends SysuiTestCase {
ArgumentCaptor.forClass(NotifLifetimeExtender.class);
mForegroundCoordinator.attach(mNotifCollection, mNotifListBuilder);
- verify(mNotifListBuilder, times(1)).addFilter(filterCaptor.capture());
+ verify(mNotifListBuilder, times(1)).addPreGroupFilter(filterCaptor.capture());
verify(mNotifCollection, times(1)).addNotificationLifetimeExtender(
lifetimeExtenderCaptor.capture());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java
index 527370e46b6e..979b8a906ef0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java
@@ -38,12 +38,12 @@ import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.NotificationEntryBuilder;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.RankingBuilder;
import com.android.systemui.statusbar.notification.collection.GroupEntry;
import com.android.systemui.statusbar.notification.collection.NotifListBuilderImpl;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -86,14 +86,14 @@ public class KeyguardCoordinatorTest extends SysuiTestCase {
ArgumentCaptor<NotifFilter> filterCaptor = ArgumentCaptor.forClass(NotifFilter.class);
mKeyguardCoordinator.attach(null, mNotifListBuilder);
- verify(mNotifListBuilder, times(1)).addFilter(filterCaptor.capture());
+ verify(mNotifListBuilder, times(1)).addPreRenderFilter(filterCaptor.capture());
mKeyguardFilter = filterCaptor.getValue();
}
@Test
public void unfilteredState() {
// GIVEN an 'unfiltered-keyguard-showing' state
- setupUnfilteredState();
+ setupUnfilteredState(mEntry);
// THEN don't filter out the entry
assertFalse(mKeyguardFilter.shouldFilterOut(mEntry, 0));
@@ -102,7 +102,7 @@ public class KeyguardCoordinatorTest extends SysuiTestCase {
@Test
public void notificationNotForCurrentProfile() {
// GIVEN the notification isn't for the given user
- setupUnfilteredState();
+ setupUnfilteredState(mEntry);
when(mLockscreenUserManager.isCurrentProfile(NOTIF_USER_ID)).thenReturn(false);
// THEN filter out the entry
@@ -112,7 +112,7 @@ public class KeyguardCoordinatorTest extends SysuiTestCase {
@Test
public void keyguardNotShowing() {
// GIVEN the lockscreen isn't showing
- setupUnfilteredState();
+ setupUnfilteredState(mEntry);
when(mKeyguardStateController.isShowing()).thenReturn(false);
// THEN don't filter out the entry
@@ -122,7 +122,7 @@ public class KeyguardCoordinatorTest extends SysuiTestCase {
@Test
public void doNotShowLockscreenNotifications() {
// GIVEN an 'unfiltered-keyguard-showing' state
- setupUnfilteredState();
+ setupUnfilteredState(mEntry);
// WHEN we shouldn't show any lockscreen notifications
when(mLockscreenUserManager.shouldShowLockscreenNotifications()).thenReturn(false);
@@ -134,7 +134,7 @@ public class KeyguardCoordinatorTest extends SysuiTestCase {
@Test
public void lockdown() {
// GIVEN an 'unfiltered-keyguard-showing' state
- setupUnfilteredState();
+ setupUnfilteredState(mEntry);
// WHEN the notification's user is in lockdown:
when(mKeyguardUpdateMonitor.isUserInLockdown(NOTIF_USER_ID)).thenReturn(true);
@@ -146,7 +146,7 @@ public class KeyguardCoordinatorTest extends SysuiTestCase {
@Test
public void publicMode_settingsDisallow() {
// GIVEN an 'unfiltered-keyguard-showing' state
- setupUnfilteredState();
+ setupUnfilteredState(mEntry);
// WHEN the notification's user is in public mode and settings are configured to disallow
// notifications in public mode
@@ -161,7 +161,7 @@ public class KeyguardCoordinatorTest extends SysuiTestCase {
@Test
public void publicMode_notifDisallowed() {
// GIVEN an 'unfiltered-keyguard-showing' state
- setupUnfilteredState();
+ setupUnfilteredState(mEntry);
// WHEN the notification's user is in public mode and settings are configured to disallow
// notifications in public mode
@@ -177,7 +177,7 @@ public class KeyguardCoordinatorTest extends SysuiTestCase {
@Test
public void doesNotExceedThresholdToShow() {
// GIVEN an 'unfiltered-keyguard-showing' state
- setupUnfilteredState();
+ setupUnfilteredState(mEntry);
// WHEN the notification doesn't exceed the threshold to show on the lockscreen
mEntry.setRanking(new RankingBuilder()
@@ -191,34 +191,42 @@ public class KeyguardCoordinatorTest extends SysuiTestCase {
@Test
public void summaryExceedsThresholdToShow() {
- // GIVEN an 'unfiltered-keyguard-showing' state
- setupUnfilteredState();
+ // GIVEN the notification doesn't exceed the threshold to show on the lockscreen
+ // but it's part of a group (has a parent)
+ final GroupEntry parent = new GroupEntry("test_group_key");
+ final NotificationEntry entryWithParent = new NotificationEntryBuilder()
+ .setParent(parent)
+ .setUser(new UserHandle(NOTIF_USER_ID))
+ .build();
- // WHEN the notification doesn't exceed the threshold to show on the lockscreen
- // but its summary does
- mEntry.setRanking(new RankingBuilder()
- .setKey(mEntry.getKey())
+ setupUnfilteredState(entryWithParent);
+ entryWithParent.setRanking(new RankingBuilder()
+ .setKey(entryWithParent.getKey())
.setImportance(IMPORTANCE_MIN)
.build());
- final NotificationEntry summary = new NotificationEntryBuilder().build();
- summary.setRanking(new RankingBuilder()
- .setKey(summary.getKey())
+ // WHEN its parent has a summary that exceeds threshold to show on lockscreen
+ parent.setSummary(new NotificationEntryBuilder()
.setImportance(IMPORTANCE_HIGH)
.build());
- final GroupEntry group = new GroupEntry(mEntry.getSbn().getGroupKey());
- group.setSummary(summary);
- mEntry.setParent(group);
// THEN don't filter out the entry
- assertFalse(mKeyguardFilter.shouldFilterOut(mEntry, 0));
+ assertFalse(mKeyguardFilter.shouldFilterOut(entryWithParent, 0));
+
+ // WHEN its parent has a summary that doesn't exceed threshold to show on lockscreen
+ parent.setSummary(new NotificationEntryBuilder()
+ .setImportance(IMPORTANCE_MIN)
+ .build());
+
+ // THEN filter out the entry
+ assertTrue(mKeyguardFilter.shouldFilterOut(entryWithParent, 0));
}
/**
* setup a state where the notification will not be filtered by the
* KeyguardNotificationCoordinator when the keyguard is showing.
*/
- private void setupUnfilteredState() {
+ private void setupUnfilteredState(NotificationEntry entry) {
// notification is for current profile
when(mLockscreenUserManager.isCurrentProfile(NOTIF_USER_ID)).thenReturn(true);
@@ -239,7 +247,7 @@ public class KeyguardCoordinatorTest extends SysuiTestCase {
// entry's ranking - should show on all lockscreens
// + priority of the notification exceeds the threshold to be shown on the lockscreen
- mEntry.setRanking(new RankingBuilder()
+ entry.setRanking(new RankingBuilder()
.setKey(mEntry.getKey())
.setVisibilityOverride(VISIBILITY_PUBLIC)
.setImportance(IMPORTANCE_HIGH)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java
index 182e86667c63..d3b16c319692 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java
@@ -32,10 +32,10 @@ import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.NotificationEntryBuilder;
import com.android.systemui.statusbar.RankingBuilder;
import com.android.systemui.statusbar.notification.collection.NotifListBuilderImpl;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import org.junit.Before;
@@ -63,7 +63,7 @@ public class RankingCoordinatorTest extends SysuiTestCase {
ArgumentCaptor<NotifFilter> filterCaptor = ArgumentCaptor.forClass(NotifFilter.class);
mRankingCoordinator.attach(null, mNotifListBuilder);
- verify(mNotifListBuilder, times(1)).addFilter(filterCaptor.capture());
+ verify(mNotifListBuilder, times(1)).addPreGroupFilter(filterCaptor.capture());
mRankingFilter = filterCaptor.getValue();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/provider/IsHighPriorityProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/provider/IsHighPriorityProviderTest.java
index 11488a0b699e..6fa1a89515c3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/provider/IsHighPriorityProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/provider/IsHighPriorityProviderTest.java
@@ -33,8 +33,8 @@ import android.testing.AndroidTestingRunner;
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import org.junit.Before;
import org.junit.Test;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/ExpansionStateLoggerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/ExpansionStateLoggerTest.java
index 4f1ffbe50fc1..2662c80dce1d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/ExpansionStateLoggerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/ExpansionStateLoggerTest.java
@@ -29,10 +29,10 @@ import androidx.test.filters.SmallTest;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
-import com.android.systemui.Dependency;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.UiOffloadThread;
import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
+import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.time.FakeSystemClock;
import org.junit.Before;
import org.junit.Test;
@@ -52,12 +52,12 @@ public class ExpansionStateLoggerTest extends SysuiTestCase {
private NotificationLogger.ExpansionStateLogger mLogger;
@Mock
private IStatusBarService mBarService;
+ private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mLogger = new NotificationLogger.ExpansionStateLogger(
- Dependency.get(UiOffloadThread.class));
+ mLogger = new NotificationLogger.ExpansionStateLogger(mUiBgExecutor);
mLogger.mBarService = mBarService;
}
@@ -66,7 +66,7 @@ public class ExpansionStateLoggerTest extends SysuiTestCase {
mLogger.onVisibilityChanged(
Collections.singletonList(createNotificationVisibility(NOTIFICATION_KEY, true)),
Collections.emptyList());
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
verify(mBarService, Mockito.never()).onNotificationExpansionChanged(
eq(NOTIFICATION_KEY), anyBoolean(), anyBoolean(), anyInt());
@@ -76,7 +76,7 @@ public class ExpansionStateLoggerTest extends SysuiTestCase {
public void testExpanded() throws RemoteException {
mLogger.onExpansionChanged(NOTIFICATION_KEY, false, true,
NotificationVisibility.NotificationLocation.LOCATION_UNKNOWN);
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
verify(mBarService, Mockito.never()).onNotificationExpansionChanged(
eq(NOTIFICATION_KEY), anyBoolean(), anyBoolean(), anyInt());
@@ -89,7 +89,7 @@ public class ExpansionStateLoggerTest extends SysuiTestCase {
mLogger.onVisibilityChanged(
Collections.singletonList(createNotificationVisibility(NOTIFICATION_KEY, true)),
Collections.emptyList());
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
verify(mBarService, Mockito.never()).onNotificationExpansionChanged(
eq(NOTIFICATION_KEY), anyBoolean(), anyBoolean(), anyInt());
@@ -102,7 +102,7 @@ public class ExpansionStateLoggerTest extends SysuiTestCase {
mLogger.onVisibilityChanged(
Collections.singletonList(createNotificationVisibility(NOTIFICATION_KEY, true)),
Collections.emptyList());
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
verify(mBarService).onNotificationExpansionChanged(
NOTIFICATION_KEY, true, true,
@@ -117,7 +117,7 @@ public class ExpansionStateLoggerTest extends SysuiTestCase {
Collections.singletonList(createNotificationVisibility(NOTIFICATION_KEY, true,
NotificationVisibility.NotificationLocation.LOCATION_MAIN_AREA)),
Collections.emptyList());
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
verify(mBarService).onNotificationExpansionChanged(
NOTIFICATION_KEY, false, true,
@@ -133,7 +133,7 @@ public class ExpansionStateLoggerTest extends SysuiTestCase {
Collections.emptyList());
mLogger.onExpansionChanged(NOTIFICATION_KEY, false, true,
NotificationVisibility.NotificationLocation.LOCATION_FIRST_HEADS_UP);
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
verify(mBarService).onNotificationExpansionChanged(
NOTIFICATION_KEY, false, true,
@@ -150,7 +150,7 @@ public class ExpansionStateLoggerTest extends SysuiTestCase {
NotificationVisibility.NotificationLocation.LOCATION_UNKNOWN);
mLogger.onExpansionChanged(NOTIFICATION_KEY, false, true,
NotificationVisibility.NotificationLocation.LOCATION_UNKNOWN);
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
verify(mBarService).onNotificationExpansionChanged(
NOTIFICATION_KEY, false, true,
@@ -164,7 +164,7 @@ public class ExpansionStateLoggerTest extends SysuiTestCase {
mLogger.onVisibilityChanged(
Collections.singletonList(createNotificationVisibility(NOTIFICATION_KEY, true)),
Collections.emptyList());
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
verify(mBarService).onNotificationExpansionChanged(
NOTIFICATION_KEY, true, true, ExpandableViewState.LOCATION_UNKNOWN);
@@ -172,7 +172,7 @@ public class ExpansionStateLoggerTest extends SysuiTestCase {
mLogger.onVisibilityChanged(
Collections.singletonList(createNotificationVisibility(NOTIFICATION_KEY, true)),
Collections.emptyList());
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
// onNotificationExpansionChanged is called the second time.
verify(mBarService, times(2)).onNotificationExpansionChanged(
NOTIFICATION_KEY, true, true, ExpandableViewState.LOCATION_UNKNOWN);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
index d1398667f497..d826ce1bbdd8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
package com.android.systemui.statusbar.notification.logging;
@@ -36,17 +36,17 @@ import androidx.test.filters.SmallTest;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
-import com.android.systemui.Dependency;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.UiOffloadThread;
-import com.android.systemui.statusbar.NotificationEntryBuilder;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.StatusBarStateControllerImpl;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
+import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.time.FakeSystemClock;
import com.google.android.collect.Lists;
@@ -60,6 +60,7 @@ import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.Executor;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@@ -82,6 +83,7 @@ public class NotificationLoggerTest extends SysuiTestCase {
private TestableNotificationLogger mLogger;
private NotificationEntryListener mNotificationEntryListener;
private ConcurrentLinkedQueue<AssertionError> mErrorQueue = new ConcurrentLinkedQueue<>();
+ private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
@Before
public void setUp() {
@@ -98,7 +100,7 @@ public class NotificationLoggerTest extends SysuiTestCase {
.build();
mEntry.setRow(mRow);
- mLogger = new TestableNotificationLogger(mListener, Dependency.get(UiOffloadThread.class),
+ mLogger = new TestableNotificationLogger(mListener, mUiBgExecutor,
mEntryManager, mock(StatusBarStateControllerImpl.class), mBarService,
mExpansionStateLogger);
mLogger.setUpWithContainer(mListContainer);
@@ -130,7 +132,7 @@ public class NotificationLoggerTest extends SysuiTestCase {
when(mEntryManager.getVisibleNotifications()).thenReturn(Lists.newArrayList(mEntry));
mLogger.getChildLocationsChangedListenerForTest().onChildLocationsChanged();
TestableLooper.get(this).processAllMessages();
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
if(!mErrorQueue.isEmpty()) {
throw mErrorQueue.poll();
@@ -140,7 +142,7 @@ public class NotificationLoggerTest extends SysuiTestCase {
Mockito.reset(mBarService);
mLogger.getChildLocationsChangedListenerForTest().onChildLocationsChanged();
TestableLooper.get(this).processAllMessages();
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
verify(mBarService, never()).onNotificationVisibilityChanged(any(), any());
}
@@ -152,11 +154,11 @@ public class NotificationLoggerTest extends SysuiTestCase {
when(mEntryManager.getVisibleNotifications()).thenReturn(Lists.newArrayList(mEntry));
mLogger.getChildLocationsChangedListenerForTest().onChildLocationsChanged();
TestableLooper.get(this).processAllMessages();
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
Mockito.reset(mBarService);
mLogger.stopNotificationLogging();
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
// The visibility objects are recycled by NotificationLogger, so we can't use specific
// matchers here.
verify(mBarService, times(1)).onNotificationVisibilityChanged(any(), any());
@@ -165,12 +167,12 @@ public class NotificationLoggerTest extends SysuiTestCase {
private class TestableNotificationLogger extends NotificationLogger {
TestableNotificationLogger(NotificationListener notificationListener,
- UiOffloadThread uiOffloadThread,
+ Executor uiBgExecutor,
NotificationEntryManager entryManager,
StatusBarStateControllerImpl statusBarStateController,
IStatusBarService barService,
ExpansionStateLogger expansionStateLogger) {
- super(notificationListener, uiOffloadThread, entryManager, statusBarStateController,
+ super(notificationListener, uiBgExecutor, entryManager, statusBarStateController,
expansionStateLogger);
mBarService = barService;
// Make this on the current thread so we can wait for it during tests.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
index d17c573515f5..3d79ce15bfb6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
@@ -19,9 +19,9 @@ package com.android.systemui.statusbar.notification.row;
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
import static com.android.systemui.statusbar.NotificationEntryHelper.modifyRanking;
-import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_ALL;
-import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_HEADS_UP;
-import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_PUBLIC;
+import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_ALL;
+import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP;
+import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -152,7 +152,7 @@ public class ExpandableNotificationRowTest extends SysuiTestCase {
row.setNeedsRedaction(true);
- assertTrue(row.getNotificationInflater().isInflationFlagSet(FLAG_CONTENT_VIEW_PUBLIC));
+ assertTrue(row.isInflationFlagSet(FLAG_CONTENT_VIEW_PUBLIC));
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java
index 27e3a6699571..dc4e4980e443 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java
@@ -16,10 +16,10 @@
package com.android.systemui.statusbar.notification.row;
-import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_ALL;
-import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_EXPANDED;
-import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_HEADS_UP;
-import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_PUBLIC;
+import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_ALL;
+import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_CONTRACTED;
+import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_EXPANDED;
+import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -42,12 +42,15 @@ import android.view.ViewGroup;
import android.widget.RemoteViews;
import androidx.test.filters.SmallTest;
+import androidx.test.filters.Suppress;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.InflationTask;
import com.android.systemui.statusbar.NotificationTestHelper;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationCallback;
+import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.BindParams;
+import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationCallback;
+import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag;
import com.android.systemui.tests.R;
import org.junit.Assert;
@@ -64,7 +67,7 @@ import java.util.concurrent.TimeUnit;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@RunWithLooper(setAsMainLooper = true)
-@Ignore
+@Suppress
public class NotificationContentInflaterTest extends SysuiTestCase {
private NotificationContentInflater mNotificationInflater;
@@ -81,25 +84,17 @@ public class NotificationContentInflaterTest extends SysuiTestCase {
ExpandableNotificationRow row = new NotificationTestHelper(mContext, mDependency).createRow(
mBuilder.build());
mRow = spy(row);
- mNotificationInflater = new NotificationContentInflater(mRow);
- mNotificationInflater.setInflationCallback(new InflationCallback() {
- @Override
- public void handleInflationException(StatusBarNotification notification,
- Exception e) {
- }
-
- @Override
- public void onAsyncInflationFinished(NotificationEntry entry,
- @NotificationContentInflater.InflationFlag int inflatedFlags) {
- }
- });
+ mNotificationInflater = new NotificationContentInflater();
}
@Test
public void testIncreasedHeadsUpBeingUsed() {
- mNotificationInflater.setUsesIncreasedHeadsUpHeight(true);
+ BindParams params = new BindParams();
+ params.usesIncreasedHeadsUpHeight = true;
Notification.Builder builder = spy(mBuilder);
- mNotificationInflater.inflateNotificationViews(
+ mNotificationInflater.inflateNotificationViews(mRow.getEntry(),
+ mRow,
+ params,
true /* inflateSynchronously */,
FLAG_CONTENT_VIEW_ALL,
builder,
@@ -109,9 +104,12 @@ public class NotificationContentInflaterTest extends SysuiTestCase {
@Test
public void testIncreasedHeightBeingUsed() {
- mNotificationInflater.setUsesIncreasedHeight(true);
+ BindParams params = new BindParams();
+ params.usesIncreasedHeight = true;
Notification.Builder builder = spy(mBuilder);
- mNotificationInflater.inflateNotificationViews(
+ mNotificationInflater.inflateNotificationViews(mRow.getEntry(),
+ mRow,
+ params,
true /* inflateSynchronously */,
FLAG_CONTENT_VIEW_ALL,
builder,
@@ -121,17 +119,13 @@ public class NotificationContentInflaterTest extends SysuiTestCase {
@Test
public void testInflationCallsUpdated() throws Exception {
- runThenWaitForInflation(() -> mNotificationInflater.inflateNotificationViews(),
- mNotificationInflater);
+ inflateAndWait(mNotificationInflater, FLAG_CONTENT_VIEW_ALL, mRow);
verify(mRow).onNotificationUpdated();
}
@Test
public void testInflationOnlyInflatesSetFlags() throws Exception {
- mNotificationInflater.updateInflationFlag(FLAG_CONTENT_VIEW_HEADS_UP,
- true /* shouldInflate */);
- runThenWaitForInflation(() -> mNotificationInflater.inflateNotificationViews(),
- mNotificationInflater);
+ inflateAndWait(mNotificationInflater, FLAG_CONTENT_VIEW_HEADS_UP, mRow);
assertNotNull(mRow.getPrivateLayout().getHeadsUpChild());
verify(mRow).onNotificationUpdated();
@@ -142,8 +136,8 @@ public class NotificationContentInflaterTest extends SysuiTestCase {
mRow.getPrivateLayout().removeAllViews();
mRow.getEntry().getSbn().getNotification().contentView
= new RemoteViews(mContext.getPackageName(), R.layout.status_bar);
- runThenWaitForInflation(() -> mNotificationInflater.inflateNotificationViews(),
- true /* expectingException */, mNotificationInflater);
+ inflateAndWait(true /* expectingException */, mNotificationInflater, FLAG_CONTENT_VIEW_ALL,
+ mRow);
assertTrue(mRow.getPrivateLayout().getChildCount() == 0);
verify(mRow, times(0)).onNotificationUpdated();
}
@@ -151,8 +145,7 @@ public class NotificationContentInflaterTest extends SysuiTestCase {
@Test
public void testAsyncTaskRemoved() throws Exception {
mRow.getEntry().abortTask();
- runThenWaitForInflation(() -> mNotificationInflater.inflateNotificationViews(),
- mNotificationInflater);
+ inflateAndWait(mNotificationInflater, FLAG_CONTENT_VIEW_ALL, mRow);
verify(mRow).onNotificationUpdated();
}
@@ -160,7 +153,13 @@ public class NotificationContentInflaterTest extends SysuiTestCase {
public void testRemovedNotInflated() throws Exception {
mRow.setRemoved();
mNotificationInflater.setInflateSynchronously(true);
- mNotificationInflater.inflateNotificationViews();
+ mNotificationInflater.bindContent(
+ mRow.getEntry(),
+ mRow,
+ FLAG_CONTENT_VIEW_ALL,
+ new BindParams(),
+ false /* forceInflate */,
+ null /* callback */);
Assert.assertNull(mRow.getEntry().getRunningTask());
}
@@ -188,7 +187,7 @@ public class NotificationContentInflaterTest extends SysuiTestCase {
@Override
public void onAsyncInflationFinished(NotificationEntry entry,
- @NotificationContentInflater.InflationFlag int inflatedFlags) {
+ @InflationFlag int inflatedFlags) {
countDownLatch.countDown();
}
}, mRow.getPrivateLayout(), null, null, new HashMap<>(),
@@ -206,26 +205,25 @@ public class NotificationContentInflaterTest extends SysuiTestCase {
assertTrue(countDownLatch.await(500, TimeUnit.MILLISECONDS));
}
- @Test
- public void testUpdateNeedsRedactionReinflatesChangedContentViews() {
- mNotificationInflater.updateInflationFlag(FLAG_CONTENT_VIEW_PUBLIC, true);
- mNotificationInflater.updateNeedsRedaction(true);
-
- NotificationContentInflater.AsyncInflationTask asyncInflationTask =
- (NotificationContentInflater.AsyncInflationTask) mRow.getEntry().getRunningTask();
- assertEquals(FLAG_CONTENT_VIEW_PUBLIC, asyncInflationTask.getReInflateFlags());
- asyncInflationTask.abort();
- }
-
/* Cancelling requires us to be on the UI thread otherwise we might have a race */
@Test
public void testSupersedesExistingTask() {
- mNotificationInflater.addInflationFlags(FLAG_CONTENT_VIEW_ALL);
- mNotificationInflater.inflateNotificationViews();
-
- // Trigger inflation of content and expanded only.
- mNotificationInflater.setIsLowPriority(true);
- mNotificationInflater.setIsChildInGroup(true);
+ mNotificationInflater.bindContent(
+ mRow.getEntry(),
+ mRow,
+ FLAG_CONTENT_VIEW_ALL,
+ new BindParams(),
+ false /* forceInflate */,
+ null /* callback */);
+
+ // Trigger inflation of contracted only.
+ mNotificationInflater.bindContent(
+ mRow.getEntry(),
+ mRow,
+ FLAG_CONTENT_VIEW_CONTRACTED,
+ new BindParams(),
+ false /* forceInflate */,
+ null /* callback */);
InflationTask runningTask = mRow.getEntry().getRunningTask();
NotificationContentInflater.AsyncInflationTask asyncInflationTask =
@@ -247,17 +245,21 @@ public class NotificationContentInflaterTest extends SysuiTestCase {
NotificationContentInflater.canReapplyRemoteView(mediaView, decoratedMediaView));
}
- public static void runThenWaitForInflation(Runnable block,
- NotificationContentInflater inflater) throws Exception {
- runThenWaitForInflation(block, false /* expectingException */, inflater);
+ private static void inflateAndWait(NotificationContentInflater inflater,
+ @InflationFlag int contentToInflate,
+ ExpandableNotificationRow row)
+ throws Exception {
+ inflateAndWait(false /* expectingException */, inflater, contentToInflate, row);
}
- private static void runThenWaitForInflation(Runnable block, boolean expectingException,
- NotificationContentInflater inflater) throws Exception {
+ private static void inflateAndWait(boolean expectingException,
+ NotificationContentInflater inflater,
+ @InflationFlag int contentToInflate,
+ ExpandableNotificationRow row) throws Exception {
CountDownLatch countDownLatch = new CountDownLatch(1);
final ExceptionHolder exceptionHolder = new ExceptionHolder();
inflater.setInflateSynchronously(true);
- inflater.setInflationCallback(new InflationCallback() {
+ InflationCallback callback = new InflationCallback() {
@Override
public void handleInflationException(StatusBarNotification notification,
Exception e) {
@@ -269,15 +271,21 @@ public class NotificationContentInflaterTest extends SysuiTestCase {
@Override
public void onAsyncInflationFinished(NotificationEntry entry,
- @NotificationContentInflater.InflationFlag int inflatedFlags) {
+ @InflationFlag int inflatedFlags) {
if (expectingException) {
exceptionHolder.setException(new RuntimeException(
"Inflation finished even though there should be an error"));
}
countDownLatch.countDown();
}
- });
- block.run();
+ };
+ inflater.bindContent(
+ row.getEntry(),
+ row,
+ contentToInflate,
+ new BindParams(),
+ false /* forceInflate */,
+ callback /* callback */);
assertTrue(countDownLatch.await(500, TimeUnit.MILLISECONDS));
if (exceptionHolder.mException != null) {
throw exceptionHolder.mException;
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 bdca7efeb608..f513c2d1513b 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
@@ -78,10 +78,10 @@ import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.bubbles.BubblesTestActivity;
-import com.android.systemui.statusbar.NotificationEntryBuilder;
import com.android.systemui.statusbar.SbnBuilder;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import org.junit.After;
import org.junit.Before;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java
index 9eba4ebeb994..f48c40c3b941 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java
@@ -38,8 +38,8 @@ import android.view.ViewGroup;
import androidx.test.filters.SmallTest;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
-import com.android.systemui.statusbar.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.utils.leaks.LeakCheckedTest;
import org.junit.After;
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 d2b4a20ca3a9..77a6a2602d8e 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
@@ -47,15 +47,12 @@ import androidx.test.filters.SmallTest;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
import com.android.systemui.ActivityStarterDelegate;
-import com.android.systemui.Dependency;
import com.android.systemui.ExpandHelper;
-import com.android.systemui.InitController;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.statusbar.EmptyShadeView;
-import com.android.systemui.statusbar.NotificationEntryBuilder;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.NotificationPresenter;
@@ -71,6 +68,7 @@ import com.android.systemui.statusbar.notification.NotificationSectionsFeatureMa
import com.android.systemui.statusbar.notification.TestableNotificationEntryManager;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
import com.android.systemui.statusbar.notification.logging.NotifLog;
import com.android.systemui.statusbar.notification.people.PeopleHubSectionFooterViewAdapter;
@@ -170,7 +168,6 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
),
mock(NotificationEntryManager.KeyguardEnvironment.class));
mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager);
- Dependency.get(InitController.class).executePostInitTasks();
mEntryManager.setUpForTest(mock(NotificationPresenter.class), null, mHeadsUpManager);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java
index dfd994139af8..7fa69018b496 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java
@@ -33,9 +33,9 @@ import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.AlertingNotificationManager;
import com.android.systemui.statusbar.AlertingNotificationManagerTest;
-import com.android.systemui.statusbar.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
import com.android.systemui.statusbar.policy.ConfigurationController;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupTestHelper.java
index 3ad1e39f441e..54dc728e0c8b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupTestHelper.java
@@ -26,8 +26,8 @@ import android.content.Context;
import android.os.UserHandle;
import com.android.systemui.R;
-import com.android.systemui.statusbar.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
/**
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
index 532192ba97ae..86b2a44a1acb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
@@ -72,6 +72,8 @@ import com.android.systemui.statusbar.notification.NotificationInterruptionState
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.time.FakeSystemClock;
import org.junit.Before;
import org.junit.Test;
@@ -126,6 +128,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
private SuperStatusBarViewFactory mSuperStatusBarViewFactory;
@Mock
private NotificationPanelView mNotificationPanelView;
+ private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
private NotificationTestHelper mNotificationTestHelper;
private ExpandableNotificationRow mNotificationRow;
@@ -178,8 +181,9 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
mock(NotificationLockscreenUserManager.class),
mKeyguardStateController,
mock(NotificationInterruptionStateProvider.class), mock(MetricsLogger.class),
- mock(LockPatternUtils.class), mHandler, mHandler, mActivityIntentHelper,
- mBubbleController, mShadeController, mSuperStatusBarViewFactory))
+ mock(LockPatternUtils.class), mHandler, mHandler, mUiBgExecutor,
+ mActivityIntentHelper, mBubbleController, mShadeController,
+ mSuperStatusBarViewFactory))
.setStatusBar(mStatusBar)
.setNotificationPresenter(mock(NotificationPresenter.class))
.setActivityLaunchAnimator(mock(ActivityLaunchAnimator.class))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
index 575f145bcc63..1296a973b50f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
@@ -40,7 +40,6 @@ import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.KeyguardIndicationController;
-import com.android.systemui.statusbar.NotificationEntryBuilder;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
@@ -54,6 +53,7 @@ import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.NotificationRowBinderImpl;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
@@ -77,6 +77,7 @@ public class StatusBarNotificationPresenterTest extends SysuiTestCase {
private FakeMetricsLogger mMetricsLogger;
private ShadeController mShadeController = mock(ShadeController.class);
private StatusBar mStatusBar = mock(StatusBar.class);
+ private InitController mInitController = new InitController();
@Before
public void setup() {
@@ -100,7 +101,6 @@ public class StatusBarNotificationPresenterTest extends SysuiTestCase {
mDependency.injectMockDependency(VisualStabilityManager.class);
mDependency.injectMockDependency(NotificationGutsManager.class);
mDependency.injectMockDependency(StatusBarWindowController.class);
- mDependency.injectMockDependency(InitController.class);
NotificationEntryManager entryManager =
mDependency.injectMockDependency(NotificationEntryManager.class);
when(entryManager.getActiveNotificationsForCurrentUser()).thenReturn(new ArrayList<>());
@@ -115,7 +115,7 @@ public class StatusBarNotificationPresenterTest extends SysuiTestCase {
mock(NotificationAlertingManager.class),
mock(NotificationRowBinderImpl.class), mock(KeyguardStateController.class),
mock(KeyguardIndicationController.class),
- mStatusBar, mock(ShadeControllerImpl.class), mCommandQueue);
+ mStatusBar, mock(ShadeControllerImpl.class), mCommandQueue, mInitController);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index d3fce567714d..1cdba472a085 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -74,11 +74,9 @@ import com.android.internal.logging.testing.FakeMetricsLogger;
import com.android.internal.statusbar.IStatusBarService;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.ViewMediatorCallback;
-import com.android.systemui.Dependency;
import com.android.systemui.InitController;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.UiOffloadThread;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.bubbles.BubbleController;
@@ -89,6 +87,8 @@ import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
+import com.android.systemui.plugins.DarkIconDispatcher;
+import com.android.systemui.plugins.PluginDependencyProvider;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.ScreenPinningRequest;
@@ -98,7 +98,6 @@ import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.KeyguardIndicationController;
import com.android.systemui.statusbar.NavigationBarController;
-import com.android.systemui.statusbar.NotificationEntryBuilder;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationMediaManager;
@@ -120,6 +119,7 @@ import com.android.systemui.statusbar.notification.NotificationInterruptionState
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.init.NewNotifPipeline;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
@@ -127,12 +127,16 @@ import com.android.systemui.statusbar.notification.stack.NotificationStackScroll
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.ExtensionController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
import com.android.systemui.statusbar.policy.RemoteInputUriController;
+import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.policy.ZenModeController;
+import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.time.FakeSystemClock;
import com.android.systemui.volume.VolumeComponent;
import org.junit.Before;
@@ -244,13 +248,19 @@ public class StatusBarTest extends SysuiTestCase {
@Mock private LockscreenLockIconController mLockscreenLockIconController;
@Mock private StatusBarNotificationActivityStarter.Builder
mStatusBarNotificationActivityStarterBuilder;
+ @Mock private DarkIconDispatcher mDarkIconDispatcher;
+ @Mock private PluginDependencyProvider mPluginDependencyProvider;
+ @Mock private KeyguardDismissUtil mKeyguardDismissUtil;
+ @Mock private ExtensionController mExtensionController;
+ @Mock private UserInfoControllerImpl mUserInfoControllerImpl;
private ShadeController mShadeController;
+ private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
+ private InitController mInitController = new InitController();
@Before
public void setup() throws Exception {
MockitoAnnotations.initMocks(this);
mDependency.injectTestDependency(NotificationFilter.class, mNotificationFilter);
- mDependency.injectMockDependency(KeyguardDismissUtil.class);
IPowerManager powerManagerService = mock(IPowerManager.class);
mPowerManager = new PowerManager(mContext, powerManagerService,
@@ -266,7 +276,7 @@ public class StatusBarTest extends SysuiTestCase {
mMetricsLogger = new FakeMetricsLogger();
NotificationLogger notificationLogger = new NotificationLogger(mNotificationListener,
- Dependency.get(UiOffloadThread.class), mEntryManager, mStatusBarStateController,
+ mUiBgExecutor, mEntryManager, mStatusBarStateController,
mExpansionStateLogger);
notificationLogger.setVisibilityReporter(mock(Runnable.class));
@@ -349,7 +359,7 @@ public class StatusBarTest extends SysuiTestCase {
mNotificationAlertingManager,
new DisplayMetrics(),
mMetricsLogger,
- Dependency.get(UiOffloadThread.class),
+ mUiBgExecutor,
mNotificationMediaManager,
mLockscreenUserManager,
mRemoteInputManager,
@@ -393,6 +403,13 @@ public class StatusBarTest extends SysuiTestCase {
mSuperStatusBarViewFactory,
mStatusBarKeyguardViewManager,
mViewMediatorCallback,
+ mInitController,
+ mDarkIconDispatcher,
+ new Handler(TestableLooper.get(this).getLooper()),
+ mPluginDependencyProvider,
+ mKeyguardDismissUtil,
+ mExtensionController,
+ mUserInfoControllerImpl,
mDismissCallbackRegistry);
when(mStatusBarWindowView.findViewById(R.id.lock_icon_container)).thenReturn(
@@ -417,7 +434,7 @@ public class StatusBarTest extends SysuiTestCase {
mStatusBar.mBarService = mBarService;
mStatusBar.mStackScroller = mStackScroller;
mStatusBar.startKeyguard();
- Dependency.get(InitController.class).executePostInitTasks();
+ mInitController.executePostInitTasks();
notificationLogger.setUpWithContainer(mStackScroller);
}
@@ -641,7 +658,7 @@ public class StatusBarTest extends SysuiTestCase {
public void testLogHidden() {
try {
mStatusBar.handleVisibleToUserChanged(false);
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
verify(mBarService, times(1)).onPanelHidden();
verify(mBarService, never()).onPanelRevealed(anyBoolean(), anyInt());
} catch (RemoteException e) {
@@ -659,7 +676,7 @@ public class StatusBarTest extends SysuiTestCase {
try {
mStatusBar.handleVisibleToUserChanged(true);
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
verify(mBarService, never()).onPanelHidden();
verify(mBarService, times(1)).onPanelRevealed(false, 1);
} catch (RemoteException e) {
@@ -678,7 +695,7 @@ public class StatusBarTest extends SysuiTestCase {
try {
mStatusBar.handleVisibleToUserChanged(true);
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
verify(mBarService, never()).onPanelHidden();
verify(mBarService, times(1)).onPanelRevealed(true, 5);
} catch (RemoteException e) {
@@ -696,7 +713,7 @@ public class StatusBarTest extends SysuiTestCase {
try {
mStatusBar.handleVisibleToUserChanged(true);
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
verify(mBarService, never()).onPanelHidden();
verify(mBarService, times(1)).onPanelRevealed(false, 5);
} catch (RemoteException e) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java
index e629a4f03586..fbbfa9611217 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java
@@ -38,6 +38,7 @@ import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.settingslib.bluetooth.LocalBluetoothProfile;
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
import com.android.systemui.SysuiTestCase;
@@ -204,4 +205,28 @@ public class BluetoothControllerImplTest extends SysuiTestCase {
assertTrue(mBluetoothControllerImpl.isBluetoothConnected());
verify(callback, atLeastOnce()).onBluetoothStateChange(anyBoolean());
}
+
+ @Test
+ public void testOnActiveDeviceChanged_updatesAudioActive() {
+ assertFalse(mBluetoothControllerImpl.isBluetoothAudioActive());
+ assertFalse(mBluetoothControllerImpl.isBluetoothAudioProfileOnly());
+
+ CachedBluetoothDevice device = mock(CachedBluetoothDevice.class);
+ mDevices.add(device);
+ when(device.isActiveDevice(BluetoothProfile.HEADSET)).thenReturn(true);
+
+ List<LocalBluetoothProfile> profiles = new ArrayList<>();
+ LocalBluetoothProfile profile = mock(LocalBluetoothProfile.class);
+ profiles.add(profile);
+ when(profile.getProfileId()).thenReturn(BluetoothProfile.HEADSET);
+ when(device.getProfiles()).thenReturn(profiles);
+ when(device.isConnectedProfile(profile)).thenReturn(true);
+
+ mBluetoothControllerImpl.onAclConnectionStateChanged(device,
+ BluetoothProfile.STATE_CONNECTED);
+ mBluetoothControllerImpl.onActiveDeviceChanged(device, BluetoothProfile.HEADSET);
+
+ assertTrue(mBluetoothControllerImpl.isBluetoothAudioActive());
+ assertTrue(mBluetoothControllerImpl.isBluetoothAudioProfileOnly());
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/InflatedSmartRepliesTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/InflatedSmartRepliesTest.java
index c1f376bee525..53d8e5866347 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/InflatedSmartRepliesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/InflatedSmartRepliesTest.java
@@ -42,9 +42,9 @@ import com.android.systemui.SysuiTestCase;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.DevicePolicyManagerWrapper;
import com.android.systemui.shared.system.PackageManagerWrapper;
-import com.android.systemui.statusbar.NotificationEntryBuilder;
import com.android.systemui.statusbar.NotificationEntryHelper;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.policy.InflatedSmartReplies.SmartRepliesAndActions;
import com.android.systemui.statusbar.policy.SmartReplyView.SmartActions;
import com.android.systemui.statusbar.policy.SmartReplyView.SmartReplies;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index 61a7cc752c70..c4caeb3ac531 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -309,12 +309,12 @@ public class NetworkControllerBaseTest extends SysuiTestCase {
}
public void setVoiceRegState(int voiceRegState) {
- when(mServiceState.getVoiceRegState()).thenReturn(voiceRegState);
+ when(mServiceState.getState()).thenReturn(voiceRegState);
updateServiceState();
}
public void setDataRegState(int dataRegState) {
- when(mServiceState.getDataRegState()).thenReturn(dataRegState);
+ when(mServiceState.getDataRegistrationState()).thenReturn(dataRegState);
updateServiceState();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
index b5e4cb965de8..f1a6e67edb43 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
@@ -51,10 +51,10 @@ import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
-import com.android.systemui.statusbar.NotificationEntryBuilder;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.SmartReplyController;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
import com.android.systemui.statusbar.phone.ShadeController;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/animation/PhysicsAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/util/animation/PhysicsAnimatorTest.kt
index a39fbc4c232e..709a1a813596 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/animation/PhysicsAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/animation/PhysicsAnimatorTest.kt
@@ -280,7 +280,12 @@ class PhysicsAnimatorTest : SysuiTestCase() {
// Spring TRANSLATION_X to 100f, with an update and end listener provided.
animator
- .spring(DynamicAnimation.TRANSLATION_X, 100f, springConfig)
+ .spring(
+ DynamicAnimation.TRANSLATION_X,
+ 100f,
+ // Use very low stiffness to ensure that all of the keyframes we're testing
+ // for are reported to the update listener.
+ springConfig.apply { stiffness = SpringForce.STIFFNESS_VERY_LOW })
.addUpdateListener(mockUpdateListener)
.addEndListener(mockEndListener)
.start()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/concurrency/FakeExecutor.java b/packages/SystemUI/tests/src/com/android/systemui/util/concurrency/FakeExecutor.java
index f3c053058468..7c7ad5322d48 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/concurrency/FakeExecutor.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/concurrency/FakeExecutor.java
@@ -17,7 +17,6 @@
package com.android.systemui.util.concurrency;
import com.android.systemui.util.time.FakeSystemClock;
-import com.android.systemui.util.time.FakeSystemClock.ClockTickListener;
import java.util.Collections;
import java.util.PriorityQueue;
@@ -29,15 +28,6 @@ public class FakeExecutor implements DelayableExecutor {
private PriorityQueue<QueuedRunnable> mQueuedRunnables = new PriorityQueue<>();
private boolean mIgnoreClockUpdates;
- private ClockTickListener mClockTickListener = new ClockTickListener() {
- @Override
- public void onUptimeMillis(long uptimeMillis) {
- if (!mIgnoreClockUpdates) {
- runAllReady();
- }
- }
- };
-
/**
* Initializes a fake executor.
*
@@ -47,7 +37,11 @@ public class FakeExecutor implements DelayableExecutor {
*/
public FakeExecutor(FakeSystemClock clock) {
mClock = clock;
- mClock.addListener(mClockTickListener);
+ mClock.addListener(() -> {
+ if (!mIgnoreClockUpdates) {
+ runAllReady();
+ }
+ });
}
/**
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/concurrency/FakeExecutorTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/concurrency/FakeExecutorTest.java
index bd641243be12..abc283f40b1c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/concurrency/FakeExecutorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/concurrency/FakeExecutorTest.java
@@ -52,28 +52,28 @@ public class FakeExecutorTest extends SysuiTestCase {
FakeExecutor fakeExecutor = new FakeExecutor(clock);
RunnableImpl runnable = new RunnableImpl();
- assertEquals(0, clock.uptimeMillis());
+ assertEquals(10000, clock.uptimeMillis());
assertEquals(0, runnable.mRunCount);
// Execute two runnables. They should not run and should be left pending.
fakeExecutor.execute(runnable);
assertEquals(0, runnable.mRunCount);
- assertEquals(0, clock.uptimeMillis());
+ assertEquals(10000, clock.uptimeMillis());
assertEquals(1, fakeExecutor.numPending());
fakeExecutor.execute(runnable);
assertEquals(0, runnable.mRunCount);
- assertEquals(0, clock.uptimeMillis());
+ assertEquals(10000, clock.uptimeMillis());
assertEquals(2, fakeExecutor.numPending());
// Run one pending runnable.
assertTrue(fakeExecutor.runNextReady());
assertEquals(1, runnable.mRunCount);
- assertEquals(0, clock.uptimeMillis());
+ assertEquals(10000, clock.uptimeMillis());
assertEquals(1, fakeExecutor.numPending());
// Run a second pending runnable.
assertTrue(fakeExecutor.runNextReady());
assertEquals(2, runnable.mRunCount);
- assertEquals(0, clock.uptimeMillis());
+ assertEquals(10000, clock.uptimeMillis());
assertEquals(0, fakeExecutor.numPending());
// No more runnables to run.
@@ -83,12 +83,12 @@ public class FakeExecutorTest extends SysuiTestCase {
fakeExecutor.execute(runnable);
fakeExecutor.execute(runnable);
assertEquals(2, runnable.mRunCount);
- assertEquals(0, clock.uptimeMillis());
+ assertEquals(10000, clock.uptimeMillis());
assertEquals(2, fakeExecutor.numPending());
// Execute all pending runnables in batch.
assertEquals(2, fakeExecutor.runAllReady());
assertEquals(4, runnable.mRunCount);
- assertEquals(0, clock.uptimeMillis());
+ assertEquals(10000, clock.uptimeMillis());
assertEquals(0, fakeExecutor.runAllReady());
}
@@ -106,7 +106,7 @@ public class FakeExecutorTest extends SysuiTestCase {
fakeExecutor.executeDelayed(runnable, 50);
fakeExecutor.executeDelayed(runnable, 100);
assertEquals(0, runnable.mRunCount);
- assertEquals(0, clock.uptimeMillis());
+ assertEquals(10000, clock.uptimeMillis());
assertEquals(3, fakeExecutor.numPending());
// Delayed runnables should not advance the clock and therefore should not run.
assertFalse(fakeExecutor.runNextReady());
@@ -140,7 +140,7 @@ public class FakeExecutorTest extends SysuiTestCase {
fakeExecutor.executeDelayed(runnable, 50);
fakeExecutor.executeDelayed(runnable, 100);
assertEquals(0, runnable.mRunCount);
- assertEquals(0, clock.uptimeMillis());
+ assertEquals(10000, clock.uptimeMillis());
assertEquals(3, fakeExecutor.numPending());
// Delayed runnables should not advance the clock and therefore should not run.
assertFalse(fakeExecutor.runNextReady());
@@ -150,24 +150,24 @@ public class FakeExecutorTest extends SysuiTestCase {
// Advance the clock to the next runnable. Check that it is run.
assertEquals(1, fakeExecutor.advanceClockToNext());
assertEquals(1, fakeExecutor.runAllReady());
- assertEquals(1, clock.uptimeMillis());
+ assertEquals(10001, clock.uptimeMillis());
assertEquals(2, fakeExecutor.numPending());
assertEquals(1, runnable.mRunCount);
assertEquals(49, fakeExecutor.advanceClockToNext());
assertEquals(1, fakeExecutor.runAllReady());
- assertEquals(50, clock.uptimeMillis());
+ assertEquals(10050, clock.uptimeMillis());
assertEquals(1, fakeExecutor.numPending());
assertEquals(2, runnable.mRunCount);
assertEquals(50, fakeExecutor.advanceClockToNext());
assertEquals(1, fakeExecutor.runAllReady());
- assertEquals(100, clock.uptimeMillis());
+ assertEquals(10100, clock.uptimeMillis());
assertEquals(0, fakeExecutor.numPending());
assertEquals(3, runnable.mRunCount);
// Nothing left to do
assertEquals(0, fakeExecutor.advanceClockToNext());
assertEquals(0, fakeExecutor.runAllReady());
- assertEquals(100, clock.uptimeMillis());
+ assertEquals(10100, clock.uptimeMillis());
assertEquals(0, fakeExecutor.numPending());
assertEquals(3, runnable.mRunCount);
}
@@ -193,7 +193,7 @@ public class FakeExecutorTest extends SysuiTestCase {
return null;
};
- assertEquals(0, clock.uptimeMillis());
+ assertEquals(10000, clock.uptimeMillis());
checkRunCounts.invoke(0, 0, 0, 0);
fakeExecutor.execute(runnableA);
@@ -227,8 +227,8 @@ public class FakeExecutorTest extends SysuiTestCase {
fakeExecutor.execute(runnableA);
fakeExecutor.executeAtTime(runnableB, 0); // this is in the past!
- fakeExecutor.executeAtTime(runnableC, 1000);
- fakeExecutor.executeAtTime(runnableD, 500);
+ fakeExecutor.executeAtTime(runnableC, 11000);
+ fakeExecutor.executeAtTime(runnableD, 10500);
fakeExecutor.advanceClockToNext();
fakeExecutor.runAllReady();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/time/FakeSystemClock.java b/packages/SystemUI/tests/src/com/android/systemui/util/time/FakeSystemClock.java
index e94eaafdb692..601f88e0a9c6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/time/FakeSystemClock.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/time/FakeSystemClock.java
@@ -16,94 +16,70 @@
package com.android.systemui.util.time;
+import com.android.systemui.util.concurrency.FakeExecutor;
+
import java.util.ArrayList;
import java.util.List;
+/**
+ * A fake {@link SystemClock} for use with {@link FakeExecutor}.
+ *
+ * Attempts to simulate the behavior of a real system clock. Time can be moved forward but not
+ * backwards. uptimeMillis, elapsedRealtime, and currentThreadTimeMillis are all kept in sync.
+ *
+ * Unless otherwise specified, uptimeMillis and elapsedRealtime will advance the same amount with
+ * every call to {@link #advanceTime(long)}. Thread time always lags by 50% of the uptime
+ * advancement to simulate time loss due to scheduling.
+ */
public class FakeSystemClock implements SystemClock {
- private long mUptimeMillis;
- private long mElapsedRealtime;
- private long mElapsedRealtimeNanos;
- private long mCurrentThreadTimeMillis;
- private long mCurrentThreadTimeMicro;
- private long mCurrentTimeMicro;
+ private long mUptimeMillis = 10000;
+ private long mElapsedRealtime = 10000;
+ private long mCurrentThreadTimeMillis = 10000;
- List<ClockTickListener> mListeners = new ArrayList<>();
+ private final List<ClockTickListener> mListeners = new ArrayList<>();
@Override
public long uptimeMillis() {
- long value = mUptimeMillis;
- return value;
+ return mUptimeMillis;
}
@Override
public long elapsedRealtime() {
- long value = mElapsedRealtime;
- return value;
+ return mElapsedRealtime;
}
@Override
public long elapsedRealtimeNanos() {
- long value = mElapsedRealtimeNanos;
- return value;
+ return mElapsedRealtime * 1000000 + 447;
}
@Override
public long currentThreadTimeMillis() {
- long value = mCurrentThreadTimeMillis;
- return value;
- }
-
- @Override
- public long currentThreadTimeMicro() {
- long value = mCurrentThreadTimeMicro;
- return value;
+ return mCurrentThreadTimeMillis;
}
- @Override
- public long currentTimeMicro() {
- long value = mCurrentTimeMicro;
- return value;
+ public void setUptimeMillis(long uptime) {
+ advanceTime(uptime - mUptimeMillis);
}
- public void setUptimeMillis(long uptimeMillis) {
- mUptimeMillis = uptimeMillis;
- for (ClockTickListener listener : mListeners) {
- listener.onUptimeMillis(mUptimeMillis);
- }
+ public void advanceTime(long uptime) {
+ advanceTime(uptime, 0);
}
- public void setElapsedRealtime(long elapsedRealtime) {
- mElapsedRealtime = elapsedRealtime;
- for (ClockTickListener listener : mListeners) {
- listener.onElapsedRealtime(mElapsedRealtime);
+ public void advanceTime(long uptime, long sleepTime) {
+ if (uptime < 0 || sleepTime < 0) {
+ throw new IllegalArgumentException("Time cannot go backwards");
}
- }
- public void setElapsedRealtimeNanos(long elapsedRealtimeNanos) {
- mElapsedRealtimeNanos = elapsedRealtimeNanos;
- for (ClockTickListener listener : mListeners) {
- listener.onElapsedRealtimeNanos(mElapsedRealtimeNanos);
- }
- }
+ if (uptime > 0 || sleepTime > 0) {
+ mUptimeMillis += uptime;
+ mElapsedRealtime += uptime + sleepTime;
- public void setCurrentThreadTimeMillis(long currentThreadTimeMillis) {
- mCurrentThreadTimeMillis = currentThreadTimeMillis;
- for (ClockTickListener listener : mListeners) {
- listener.onCurrentThreadTimeMillis(mCurrentThreadTimeMillis);
- }
- }
+ mCurrentThreadTimeMillis += Math.ceil(uptime * 0.5);
- public void setCurrentThreadTimeMicro(long currentThreadTimeMicro) {
- mCurrentThreadTimeMicro = currentThreadTimeMicro;
- for (ClockTickListener listener : mListeners) {
- listener.onCurrentThreadTimeMicro(mCurrentThreadTimeMicro);
- }
- }
-
- public void setCurrentTimeMicro(long currentTimeMicro) {
- mCurrentTimeMicro = currentTimeMicro;
- for (ClockTickListener listener : mListeners) {
- listener.onCurrentTimeMicro(mCurrentTimeMicro);
+ for (ClockTickListener listener : mListeners) {
+ listener.onClockTick();
+ }
}
}
@@ -115,30 +91,9 @@ public class FakeSystemClock implements SystemClock {
mListeners.remove(listener);
}
- /** Alert all the listeners about the current time. */
- public void synchronizeListeners() {
- for (ClockTickListener listener : mListeners) {
- listener.onUptimeMillis(mUptimeMillis);
- listener.onElapsedRealtime(mElapsedRealtime);
- listener.onElapsedRealtimeNanos(mElapsedRealtimeNanos);
- listener.onCurrentThreadTimeMillis(mCurrentThreadTimeMillis);
- listener.onCurrentThreadTimeMicro(mCurrentThreadTimeMicro);
- listener.onCurrentTimeMicro(mCurrentTimeMicro);
- }
- }
-
-
public interface ClockTickListener {
- default void onUptimeMillis(long uptimeMillis) {}
-
- default void onElapsedRealtime(long elapsedRealtime) {}
-
- default void onElapsedRealtimeNanos(long elapsedRealtimeNanos) {}
-
- default void onCurrentThreadTimeMillis(long currentThreadTimeMillis) {}
-
- default void onCurrentThreadTimeMicro(long currentThreadTimeMicro) {}
-
- default void onCurrentTimeMicro(long currentTimeMicro) {}
+ void onClockTick();
}
+
+ private static final long START_TIME = 10000;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeBluetoothController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeBluetoothController.java
index cac6bf7ca3f0..6cbd175c1084 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeBluetoothController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeBluetoothController.java
@@ -57,6 +57,16 @@ public class FakeBluetoothController extends BaseLeakChecker<Callback> implement
}
@Override
+ public boolean isBluetoothAudioProfileOnly() {
+ return false;
+ }
+
+ @Override
+ public boolean isBluetoothAudioActive() {
+ return false;
+ }
+
+ @Override
public String getConnectedDeviceName() {
return null;
}
diff --git a/packages/Tethering/Android.bp b/packages/Tethering/Android.bp
index 3c953b348ed9..08552cbfd394 100644
--- a/packages/Tethering/Android.bp
+++ b/packages/Tethering/Android.bp
@@ -29,9 +29,11 @@ java_defaults {
"netlink-client",
"networkstack-aidl-interfaces-unstable-java",
"android.hardware.tetheroffload.control-V1.0-java",
- "tethering-client",
],
- libs: ["unsupportedappusage"],
+ libs: [
+ "framework-tethering",
+ ],
+
manifest: "AndroidManifestBase.xml",
}
@@ -90,6 +92,10 @@ java_defaults {
resource_dirs: [
"res",
],
+ libs: [
+ "framework-tethering",
+ ],
+ jarjar_rules: "jarjar-rules.txt",
optimize: {
proguard_flags_files: ["proguard.flags"],
},
@@ -104,7 +110,6 @@ android_app {
manifest: "AndroidManifest_InProcess.xml",
// InProcessTethering is a replacement for Tethering
overrides: ["Tethering"],
- // TODO: use PlatformNetworkPermissionConfig.
}
// Updatable tethering packaged as an application
diff --git a/packages/Tethering/AndroidManifest.xml b/packages/Tethering/AndroidManifest.xml
index 1430ed00aa91..87a8c3f5c68a 100644
--- a/packages/Tethering/AndroidManifest.xml
+++ b/packages/Tethering/AndroidManifest.xml
@@ -17,10 +17,25 @@
*/
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.tethering"
+ package="com.android.networkstack.tethering"
android:sharedUserId="android.uid.networkstack">
<uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29" />
+ <!-- Permissions must be defined here, and not in the base manifest, as the tethering
+ running in the system server process does not need any permission, and having
+ privileged permissions added would cause crashes on startup unless they are also
+ added to the privileged permissions whitelist for that package. -->
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+ <uses-permission android:name="android.permission.BLUETOOTH" />
+ <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
+ <uses-permission android:name="android.permission.BROADCAST_STICKY" />
+ <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
+ <uses-permission android:name="android.permission.MANAGE_USB" />
+ <uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
+ <uses-permission android:name="android.permission.READ_NETWORK_USAGE_HISTORY" />
+ <uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS" />
+ <uses-permission android:name="android.permission.WRITE_SETTINGS" />
+
<application
android:process="com.android.networkstack.process"
android:extractNativeLibs="false"
diff --git a/packages/Tethering/AndroidManifestBase.xml b/packages/Tethering/AndroidManifestBase.xml
index dc013da33869..fa85f66489d7 100644
--- a/packages/Tethering/AndroidManifestBase.xml
+++ b/packages/Tethering/AndroidManifestBase.xml
@@ -17,7 +17,7 @@
*/
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.tethering"
+ package="com.android.networkstack.tethering"
android:versionCode="1"
android:versionName="R-initial">
<application
diff --git a/packages/Tethering/AndroidManifest_InProcess.xml b/packages/Tethering/AndroidManifest_InProcess.xml
index 28d405c3133a..02ea551254b9 100644
--- a/packages/Tethering/AndroidManifest_InProcess.xml
+++ b/packages/Tethering/AndroidManifest_InProcess.xml
@@ -17,16 +17,14 @@
*/
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.tethering.inprocess"
+ package="com.android.networkstack.tethering.inprocess"
android:sharedUserId="android.uid.system"
android:process="system">
<uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29" />
<application>
- <!-- TODO: Using MAINLINE_NETWORK_STACK instead of NETWORK_STACK when tethering run in the
- same process with networkstack -->
<service android:name="com.android.server.connectivity.tethering.TetheringService"
android:process="system"
- android:permission="android.permission.NETWORK_STACK">
+ android:permission="android.permission.MAINLINE_NETWORK_STACK">
<intent-filter>
<action android:name="android.net.ITetheringConnector.InProcess"/>
</intent-filter>
diff --git a/packages/Tethering/apex/Android.bp b/packages/Tethering/apex/Android.bp
index bca01ebdf819..94ef11cc127a 100644
--- a/packages/Tethering/apex/Android.bp
+++ b/packages/Tethering/apex/Android.bp
@@ -15,21 +15,22 @@
//
apex {
- name: "com.android.tethering.apex",
+ name: "com.android.tethering",
+ java_libs: ["framework-tethering"],
apps: ["Tethering"],
manifest: "manifest.json",
- key: "com.android.tethering.apex.key",
+ key: "com.android.tethering.key",
androidManifest: "AndroidManifest.xml",
}
apex_key {
- name: "com.android.tethering.apex.key",
- public_key: "com.android.tethering.apex.avbpubkey",
- private_key: "com.android.tethering.apex.pem",
+ name: "com.android.tethering.key",
+ public_key: "com.android.tethering.avbpubkey",
+ private_key: "com.android.tethering.pem",
}
android_app_certificate {
- name: "com.android.tethering.apex.certificate",
- certificate: "com.android.tethering.apex",
+ name: "com.android.tethering.certificate",
+ certificate: "com.android.tethering",
}
diff --git a/packages/Tethering/apex/AndroidManifest.xml b/packages/Tethering/apex/AndroidManifest.xml
index 7769b799b6f9..5c35c51dc77f 100644
--- a/packages/Tethering/apex/AndroidManifest.xml
+++ b/packages/Tethering/apex/AndroidManifest.xml
@@ -15,7 +15,7 @@
* limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.tethering.apex">
+ package="com.android.tethering">
<!-- APEX does not have classes.dex -->
<application android:hasCode="false" />
<!-- b/145383354: Current minSdk is locked to Q for development cycle, lock it to next version
diff --git a/packages/Tethering/apex/com.android.tethering.apex.avbpubkey b/packages/Tethering/apex/com.android.tethering.apex.avbpubkey
deleted file mode 100644
index 9c8711161547..000000000000
--- a/packages/Tethering/apex/com.android.tethering.apex.avbpubkey
+++ /dev/null
Binary files differ
diff --git a/packages/Tethering/apex/com.android.tethering.apex.pem b/packages/Tethering/apex/com.android.tethering.apex.pem
deleted file mode 100644
index a8cd12e92e8d..000000000000
--- a/packages/Tethering/apex/com.android.tethering.apex.pem
+++ /dev/null
@@ -1,51 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIJKQIBAAKCAgEAwloHpMmwszNBEgUVion141BTvF/oJ5g5DlQIYBtmht4tSpc3
-6elWXd+dhMzFxf/RkxSNRsU+dhD11cPKGp9nUYQQGrHEf3xEKwAHJKRMq26TkJ3o
-1TwOO70TaRKKA4ThNiM3VFDX2vy1ijArhZDIBTGVJCUl9HOHiO+ZJG5DKCx3KXbO
-QWz3c+Lbprr1L76dwIsl5kuoAFwgG0J+9BZhHEzIG1lVpGG7RRLxc8eDIxNN/oKT
-gPYBcOxFYqOECKGBBvElf6MxdRv6xG7gooALY2/HDMYUjAJSOosfwzeymugCzMhK
-e+6CSTAaEfUzuVZvMc2qnd1ly7zpLo9x+TOdH5LEVZpSwqmu2n5bqrUnSEAJUvMz
-SSw0YbsLWJZuTiTV7lecSITgqsmwuZyDexDmUkDQChzrTixsQV6S8vsh/FanjWoi
-zBlPneX8Q7/LME3hxHyLbrabxX0zWiyj8iM9h/8Y4mpO/MjEmmavglTAP4J8zrKD
-FBsntCoch9I49IpYBuO6NfKw1h7AUpLf8gARAjFjRxiJVcSgGY/Wt4/pBzJ57T5g
-xPvqxfpPQP0OA2CT8LqqzZIR8jXs8/TquvwLkkY2kRRPXx+azd5oU2A0uonrUY31
-Bc1obfmWPuEMz9bO/i06ETHuWPd4RiUNaB8qEmjYuKJfhv72YNcRwhrAYJECAwEA
-AQKCAgAaQn3b5yCH5fn5zFQPxvpBP35A6ph8mRXEeNg03B7rRCPMe0gjw9JWlrs6
-0Uw7p4gSnmlEUaxR2ZLN0kmBdV5JZlWitbg+HXU8diGA8u4lD6jCloN6JEYsDi0M
-OmQJe6/OV83HB7FStmh1BnMq9dgA06U6IAbT07RRbUY85OUQDYoAQTw3HNkGgHV7
-PrGYROIdvO9fAYPuoIP6Cu8KXee7Iii7gUOQFWBvQdL7+M4gNCCKrevuNc8WCeaK
-IFvbqq67WGPfrhYlo6UrW2vgqPpg8h5r/GuUS0/+9wNQpjrssUKHltxxiFV0PBqZ
-qI7XkPUvPoG6GMsDT0AWeW1F5ZJqEGPN67Xek0BCD0cpUli+nHD0yWGVHtkpHU2D
-qUOZdB2COfBuXRdW1LsYNPg8YjTCPsmGhISLTwiTNcZJeTxoK1y0CcVW9d7Af2aD
-lYzCegscQlXkSZiFj9s90Vd3KdD2XKrH/ADxzsOxQJ89ka004efdQa5/MKs9aChG
-/5XrwBEfN4O92OjY7KqXUAwB7CcVzNymOjD6r07LM24zbkRpwwXlkP0wmjsHBXkh
-8p0ISmY9QRdvhBgYmFmoPWZncM0zym9LI8atBs4CijQ7JjuOQ8HgHg+Se2eppWfe
-t8r6TVkDB8JeNAMxjX9q0G7icf3JjlIrgERZfyXLmpduR9NdkQKCAQEA5rp2fSKh
-RwihHNtJhNktFJuLR9OA++vyfjqhWnB8CrLPo3//LGWW/+WBr8EwXi/76hQpeKlf
-u8SmkTtxIHlTP2Brh2koh1Qf8HKzPHGjZeDFOoVPKHPqe3nV+cv3srd1mS0Eq3BA
-ZFQq+l61f2iiTZKxDroCahNEa8VMzirW6nKb5xhyMPHXgncCUdphHbwAGatas6be
-RUFg4ChH8BwX6jYw7leRUy2K6OqEl0fckT4Laitlb/ezKtwmD4PPE95q5hH0v3SO
-wetHWafiNrOXPn2wQqBrI2y+AfbTjNmQiaIPgcFKAQ7V3n+c3XfGZ9Xfv4L8m/wo
-RZ4ika1zur021QKCAQEA16OUBPA7BnWd+RJFri2kJBG5JZElaV9chO2ZHcXUbFR9
-HIPkWN19bJbki8Ca0w8FUQuS/M7JeeFjoZ194NlczbR899GVmb0X2AUKXilMacs3
-IONxIDczx3KFtsge8ewXRAjQvgE7M3NpmmJfPLPog7spMCbUIxbc3jzjiZgB/J1s
-WytlUTUY/Zy4V1wujkoydgK2KcHcEWG2oIy7EP0RwnL1NhTksXOtBH6+MoRMAT+H
-fcBK6yfJBNBRQzJ0PdkCCLdQPN1VtwRlWjPXZ3ey4fWvZ399wSLUkM2V1jB4GcOZ
-+DAgtwFKs9+HfOdV42GgFWFcjP+bkM3bcdrQFnmYzQKCAQAQnf1KpePXqddwrJpu
-5vVINquhUKpJeoTMcoyMZu2IF7i8nctS9z4Yz/63GcLSBcKu6STTe99ZNqCIdS+A
-lzxXpCoaZoh0tqpWNuyRvd12yOlrfY5l63NH0U6H3xjH1k6x6XwcnMkGcMlnnsqT
-koWd8KKv3NWvrhOPb3ZIou03lWmFC02uGLzcuJWCL6gu7AtVzfGKXspDUqIXgs8r
-i9ptE9oSUFw3EWCfxcQm4RYRn9ZSny1/EufkflZ/Z47Sb4Jjb4ehAlQFw1wwKNcx
-+V07MvIu2j7dHkfQ/GXgDwtJ3lIfljwuN1NP4wD5Mlcnw0+KC3UGBvMfkHQM6eEb
-4eTBAoIBAQDWfZsqHlpX3n431XkB+9wdFJP5ThrMaVJ51mxLNRBKgO/BgV+NFSNA
-9AZ5DCf0cCh1qPGYDYhSd2LGywT+trac1j7Hse0AcxpYgQsDBkk/oic/y3wm80HJ
-zZw7Z2uAb7nkrnATzt24G8CbE+ZvVvScs3oQr06raH5hgGdD4bN4No4lUVECKbKl
-8VFbdBHK7vqqb6AKgQ4JLAygPduE1nTn2bkXBklESS98HSXK0dVYGH0JFFBw/63v
-39Y05ObC7iwbx1tEb1RnKzQ1OQO1o1aHc/35ENNhXOfa8ONtneCYn/ty50xjPCG2
-MU1vbBv+hIjbO3D3vvhaXKk+4svAz0qxAoIBAQC84FJEjKHJHx17jLeoTuDfuxwX
-6bOQrI3nHbtnFRvPrMryWRDtHLv89Zma3o68/n4vTn5+AnvgYMZifOYlTlIPxinH
-tlE+qCD8KBXUlZdrc+5GGM18lp5tF3Ro4LireH+OhiOAWawaSzDIDYdiR6Kz9NU+
-SjcHKjDObeM6iMEukoaRsufMedpUSrnbzMraAJgBZGay1NZs/o8Icl3OySYPZWEK
-MJxVBMXU9QcUp2GEioYd/eNuP9rwyjq/EIUDJbP2vESAe6+FdGbIgvyYTV/gnKaH
-GcvyMNVZbCMp/wCYNonjlu+18m2w+pVs2uuZLqORkrKYhisK83TKxh4YOWJh
------END RSA PRIVATE KEY-----
diff --git a/packages/Tethering/apex/com.android.tethering.apex.pk8 b/packages/Tethering/apex/com.android.tethering.apex.pk8
deleted file mode 100644
index 56632462941f..000000000000
--- a/packages/Tethering/apex/com.android.tethering.apex.pk8
+++ /dev/null
Binary files differ
diff --git a/packages/Tethering/apex/com.android.tethering.apex.x509.pem b/packages/Tethering/apex/com.android.tethering.apex.x509.pem
deleted file mode 100644
index a5e94011f7c5..000000000000
--- a/packages/Tethering/apex/com.android.tethering.apex.x509.pem
+++ /dev/null
@@ -1,36 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIGMzCCBBugAwIBAgIUXVtoDaXanhs7ma8VIICambMkj5UwDQYJKoZIhvcNAQEL
-BQAwgacxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH
-DA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQLDAdBbmRy
-b2lkMSMwIQYDVQQDDBpjb20uYW5kcm9pZC50ZXRoZXJpbmcuYXBleDEiMCAGCSqG
-SIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTAgFw0xOTExMjgwNjU4MTRaGA80
-NzU3MTAyNDA2NTgxNFowgacxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9y
-bmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAw
-DgYDVQQLDAdBbmRyb2lkMSMwIQYDVQQDDBpjb20uYW5kcm9pZC50ZXRoZXJpbmcu
-YXBleDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTCCAiIwDQYJ
-KoZIhvcNAQEBBQADggIPADCCAgoCggIBANwzufMBdOj9XlNwiX+bXl/94G0DklWW
-nzob0jPlubCFfRqYkjCf2eOd28Mu/O1pOBcvobnrs9OTpGzcHkz2h58L5/0UMVTS
-tBugwCE49XF5FHawqVHNZE+s5tDmnp2cufhNc5HXHY4oZKh80/WVdbcKxiLjSY2T
-PgRAfB6E6XByKD3t1cSsc3liRVKADoJOVDvmF+xnyvSV/SN38bvTQk9aVs95mj0W
-yov6gzXBnqN7iQlvkhcijZBnFWxvoNbJ5KFy1abYOrm+ueXje4BcNhVOeRMb4E9N
-eo7+9k1GEI7TYG7laNNcp7UJ1IXCJzv/wBFKRg3f1HB3unKfx2rtKerDnVsr3o7V
-KProkgRNKNhhQ6opNguiH1YMzKpWMaC988n4AQPryPdIOmVIxIC5jJrixdxgzDXT
-qeiwFiXis291uyls08B03PQFlY9oWaY9P8s+4hIUjB6rLl+XZXsLDtDFxXeJ97NB
-8XZN1gBJoBoLknFs0C4LKpmJZB/EBao9tXV9dL/5lydRo6HzQDpjW8QX06CTUM6z
-Lr3LVelhqbsuZsV42yBKl+/LfrvNjBLEPdSevt2oMrlJW7m4iSNaMtDtJ2Oy8fA5
-WSIgLWuMbkaFDza3JzwiMzxbtbJHYiy6rY7aVywo3Vqwr1+KO3cq4eLQq62zUjRY
-e6KJwvgE2YmpAgMBAAGjUzBRMB0GA1UdDgQWBBQ8h1oF5JfKFmJCN8nfimbUK+IR
-wjAfBgNVHSMEGDAWgBQ8h1oF5JfKFmJCN8nfimbUK+IRwjAPBgNVHRMBAf8EBTAD
-AQH/MA0GCSqGSIb3DQEBCwUAA4ICAQAP5hIkAxSyt9hRafMKiFlmXcL277bgoxNd
-qGZYbdcCFjfvM2r0QQcM/K7x2ZslFe7mJSzcyMifpm4YQTEo2yYbzKItXQV+eV1K
-9RNksRGFG9umsdWaSHhfQmcmxtr2nu9rGAgxy5OQFtyXmJPUPEM2cb/YeILwYhuQ
-Ux3kaj/fxGltX1JBag7HnMzCTZK++fRo5nqFVOJQgJH8ZpuzGeM9kZvP1+b55046
-PhSnlqmZoKhG4i5POPvvZvaakh/lM3x/N7lIlSaQpCGf7jmldni4L0/GenULVKzH
-iN73aBfh4GEvE0HRcOoH3L7V6kc3WMMLve0chZBHpoVYbzUJEJOUL4yrmwEehqtf
-xm4vlYg3vqtcE3UnU/UGdMb16t77Nz88LlpBY5ierIt0jZMU0M81ppRhr1uiD2Lj
-091sEA0Bxcw/6Q8QNF2eR7SG7Qwipnms+lw6Vcxve+7DdTrdEA0k3XgpdXp8Ya+2
-PAp9SLVp1UHiGq3qD9Jvm34QmlUWAIUTHZs3DSgs1y3K5eyw/cnzTvUUOljc/n2y
-VF0FFZtJ1dVLrzQ80Ik7apEXpBqkgBGV04/L3QYk4C0/sP+1yk6zjeeeAvDtUcHS
-gLtjAfacQl/kwfVQWfrF7VByLcivApC6EUdvT3cURM5DfZRQ4RcKr1D61VYPnNRH
-+/NVbMObwQ==
------END CERTIFICATE-----
diff --git a/packages/Tethering/apex/com.android.tethering.avbpubkey b/packages/Tethering/apex/com.android.tethering.avbpubkey
new file mode 100644
index 000000000000..9a2c0174e496
--- /dev/null
+++ b/packages/Tethering/apex/com.android.tethering.avbpubkey
Binary files differ
diff --git a/packages/Tethering/apex/com.android.tethering.pem b/packages/Tethering/apex/com.android.tethering.pem
new file mode 100644
index 000000000000..d4f39abd3bb2
--- /dev/null
+++ b/packages/Tethering/apex/com.android.tethering.pem
@@ -0,0 +1,51 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIJKgIBAAKCAgEA+AWTp03PBRMGt4mVNLt5PDoFFSfmFOVTM7jt5AJXnQMIDsAM
+1cyWGWRridGIpoHAaCALVgW5aRySgi8yV5xP4w0YHcKbfh9M6I9oz4RUo4GQBZfX
++lFIGaLjb6I3tEJxPuxps4sW26Io63ihwTnKeGyADHdHGWDUs9WU0Ml+QTvKrdjy
+qC03M0dehYXILGiA9m+UXwKoKxhWgfDUhWLhDBUtLJLPL4WeqKc9sG9h+zzVqE+8
+LzJsfrodKhTTrLpWOXi6YLRTk8dzsuPz/Nu98sJd1w3fHd20DrmkqsxVhgN1h+nk
+zcPpxyGYIP6qYVZCmIXCwZZNtPeb7y/tOs967VHoZ4Qj7p2tE0CAWFMZFGjA/pcZ
+7fi6CsIuMOYBbj4+wRlJwpG1g5zSJBCjzhv7dZp8S5oXmLShNYOMYEdsPfaZbm08
+3pVY+k8DVf7idcANXNw1lM+sPbE2hp5VuEuVpK+ca5x8hIMpTqJ84wDAjnC1kCwm
+X2xfNvYPKNF58SvqlNCPN8X7hQjoeaEb7w24vCdZMRqeGBmu1GNQvCyzbBO0huQm
+f5CQPrZjPcnoImlP879VPxY4YB6tAjsA/ZLiub9VdT108lCjb5r8criMzpMAA/AQ
+NqQLWFI3M43xPemGBTiIguTYgpRgGcdRZf7XuTgTY5qzQZZuZMVuwaqSD2cCAwEA
+AQKCAgEA0jMvw3BPTrakT7Lb8JgelKt7mUV6WyVMUZ6eh0pw5JIoJxAfEKfWYmjY
+NzKNRMjcv6LA2MP7MplTld/YI6ZHkl+Lm9VOISL39HVuV8mIThbFb+gT1INEvu1t
+IjRyT2SsQ67rmo377mLNmVtgg7mt3kfecjI44MpPGqad/CF4zmKVUKd4aI4BpYUM
+F8+dKf3bpoBEWA2RZwy2bGQmSXHW132vDoLR8y2knL04rCqJ+PrC/WWuULXEe9bS
+VtLV3yMBZq3qD4Fk/+7fILLPGvNFVdPi4htQiChYrM4rP9HzfaO63VieYMF0hR70
+pqoOznXj9Q4QVC9FZmUgFCQjQ1+KhqJw3OldIo0SnvpsLdTO/inKkhQWKC5HlPyh
+/rqvro2j3pTHWPAziuBr+oQPcdVCOlCBZ+B99L1tO7aGktVPEIVQG7G7jlFMBiJ1
+j/kRGk2RTX8RaPQJTnwUqp8mWUV2fwxHiXNadjejA5ZU3eQT2eAOhXl1w6Lv2jEl
+0wMOwPMJGcF77CcqnnWHON8fkxCbAfyy5Uo6Pm9g/Zzecn+ji2sabG7Ge5t0gzdL
+LKRcGoyakN2CrbQ8pxlCTgE4HX5oPY+VuqOf8L3AIWIJBsyLbXHVkL1mqQ/Ed2uz
+zaaSFYUZw81+m/5bl8JLPaIFNPyikZrXTD0YRer3V06XiyP/kYECggEBAP033xeF
+OhgRwkRTjd68hwRJpyHsZDWxHiUqQf6l6yFv5mEE355G2IGI7cZmR2+tUDjQdxLv
+tAZIszTK4PFCdVTeWfGVFbVF84eNWLB124pHDMM79GN/AMcuHnQPR756a8IO1hIy
+4KxIUE1a1PKN5b9IgE5Lu4TZM96HDpFcUAmCT5urdYDmg3++IWT9PYQlGS7Hhiar
+r+Hh646waM8Qx619CwXBqy+Y37+WHVbYqJClr6AcpVMrGA+6cgpskFpZAPLsoy7G
+RSsVfyV8pH2JKm/hzk7XCwIpczxeWQSfpJWZ+oOPFHu+zM60Cdj2UrQyKrNHwew8
++WYe9eCA+MiNBcECggEBAPq/F1vdqROiLv9uzhKb8ybgdL7CmREELiqwK+MvNE9t
+W7lQz7lcWzav+b2n0M+VJBxUWB3XClgoIvA/AllgTgsYXfKAxNakhKLSBoMmvKCW
+HtWcGr/D3RcmacK+DTMWlVS/LuueAFLuH6UmBIUFKc+qA5x7oQecAFALBFupE3G4
+LtAspLBI6P8gRtRav5p2whs9H8qjYcyf2f6liWpkmFITcXvPvAxFHicR6ZJdwZ/S
+PiX2LJQnOpT7L3+2PWnYwzFStb4MkMGlFKcscU9CvS53JcP/J4Asjk0I4zDB2gri
+xzFHPlVzCr2IVVGptKCQ3sdYiMIzQKzEXQHCU8h37ycCggEBAJu8aC48Fz3Edlm1
+ldS+2L9vWSaJEBzhoSu0cMBgZVu8SdGzwKDE69XHVI4oS5lI28UFmaaA3JTc07MN
+cAmSGT2oP2NQkPhbXGsrKLfm1K6YAiZ1Ulp7OwxFth8lYreo7Wt92nV46yuqkhDx
+Y3UGhp39xkPhWiRbvgYHxJLsVqFyjumsK2mq3IeNdVZ6VgJXGsTlnAFeqJ7hZxHs
+N5natSRjeosA0PtGJ57agZLvT8Ue0gREef3LzFGoFwmIOcQHZ4kAt2BGOzZDU17H
+6Rb4bKxBEbT1l2St/5zKXi90zDHicOvG7Q8qiyY6HrBc1wLSs+ZtpLxZx/3h3tFE
+IT6fVUECggEBAMSAQm8Ey76OJ+SXUjk1K50442SnHcs/Cmr7urkEQitImUwl71Pk
+87pst/uP6szypOTqmE9yOTIS6iZ6Sn3+QcriIqWrkhZfwW3Tx7S6A7KZUrq15iSH
++thsiw9JXxC9TvOmC8AsBzb2U6hZncsc28JZCxFztSNAduJDb/vhCVLiMxWDFuDr
+kmR1R+yc3XDQRpeQFDz6QudYEj9EPOc6xD/16sZLaqP2+oVFvVSt0tJLsdaQECle
+gMNGAdhE2eX8MCOUHMc+E6cdlozYAEhMFfO2/cqWR79jq3TlVR3dnOFRDScqHMhc
+KnuTvsELjHkUbvGsCSiff7yk+fop7vy4OJsCggEAPemJdItO2rhib8EofrZdY72I
+oifX1jhPZ1BWD2GKgcx+eVyJGbONBbJVexvvskTfZBvCcAegmgp+sngP6MO6yZkr
+cHMfAJeApYZnshsgXksHGMDtSB50/w1JLrc/nqpxdpy/aTazt0Eu1pLWpze1HFZ/
+Xyu4PcmrU+4P1vN7c396slHMktEvly6QqOn4nfBbGDJ17Ow6X1XFvGjAxQPIDTB+
+6loV14AHymwmqwMrGn84O72rzqyw+41GxW5+oXhOZ4MeXF3u89TBLWvXDpPy/YQU
+EiKpodN0YeEn6Ghzplan8rUha+7TP7AYnS5pCszsCHKd03Py0lMLkF+uAfVsDA==
+-----END RSA PRIVATE KEY-----
diff --git a/packages/Tethering/apex/com.android.tethering.pk8 b/packages/Tethering/apex/com.android.tethering.pk8
new file mode 100644
index 000000000000..3b94405945cb
--- /dev/null
+++ b/packages/Tethering/apex/com.android.tethering.pk8
Binary files differ
diff --git a/packages/Tethering/apex/com.android.tethering.x509.pem b/packages/Tethering/apex/com.android.tethering.x509.pem
new file mode 100644
index 000000000000..a1786e35e854
--- /dev/null
+++ b/packages/Tethering/apex/com.android.tethering.x509.pem
@@ -0,0 +1,35 @@
+-----BEGIN CERTIFICATE-----
+MIIGKTCCBBGgAwIBAgIUNiSs5EMqxCZ31gWWCcRJVp9HffAwDQYJKoZIhvcNAQEL
+BQAwgaIxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH
+DA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQLDAdBbmRy
+b2lkMR4wHAYDVQQDDBVjb20uYW5kcm9pZC50ZXRoZXJpbmcxIjAgBgkqhkiG9w0B
+CQEWE2FuZHJvaWRAYW5kcm9pZC5jb20wIBcNMTkxMjE4MDcwMDQ4WhgPNDc1NzEx
+MTMwNzAwNDhaMIGiMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEW
+MBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UE
+CwwHQW5kcm9pZDEeMBwGA1UEAwwVY29tLmFuZHJvaWQudGV0aGVyaW5nMSIwIAYJ
+KoZIhvcNAQkBFhNhbmRyb2lkQGFuZHJvaWQuY29tMIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEAxvTUA4seblYjZLfTVNwZuJH914QVNFTj+vD94pWmt5Aq
+sH1DVTpBvpXXegc/P5HI2XF/71poSBib1WaQSuXG0fU5K75T18bOGL0qF+fhMtBO
+wUyvulcjO0h4XE/xf0txY54exUjAA4JS9ERGJOgb4GOwSbPyzekfmzIyCZ2Yawwu
++oGwD2ZNzZRaPOoWxjwohBWQ6mySuvF9RRRb300qmxxUGFM9Ki3aqrWlYlHEOwOC
+M+gIXxYFO7S+yUzf6/gMZLOz2YqfcTOup4hAxtExR7niutxJSsRLPBL237exAJoz
+OupoXjtWAlPK4ZwZ/Nl1jdTWauJ+Kv3WqzhHGEb2gn3ZpeO3IdOjJhDgFJ6m1OT/
+kjRbW1LCuKGrKaoqsEDT2X3a7Izfripn65hSNTfR5gNLtgELaI3/vXi8Fmzw1AfH
++qi6ulElZvSwx0qm+S0QiPyGFlxrsdnHoGJl1tzjJW8KdNZRvzRLUQtbphPp+VkL
+5i0bNKum+AwbfdUkLkNLfw9XdbujgBkZTZDQbZGsNjgrvyXcPO2KiJee0hVCZRs0
+rhDi5Pfm7BnN/I2vaTRz/W4mdct9H2RWMuqlSH90JvmKtWcND8ahmOJ3sggrvzfO
+QNs3k4JTRecamMzqIkylhlnEC4FjWc6Bx4wsEpwBMZOkF/tGGMZYf2C09a8tpP0C
+AwEAAaNTMFEwHQYDVR0OBBYEFNP5gIpNWmq0xa411M1GaRPbEijvMB8GA1UdIwQY
+MBaAFNP5gIpNWmq0xa411M1GaRPbEijvMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI
+hvcNAQELBQADggIBADJGmU3QP4EGbt6eBhVPeo/efsqrHsuB2fvFzvIobJbfkSob
+cmvjbzIikOlPAgFWj8lT5SDcIWRorFf1u2JylClJ0nSDcqJMHVKmT7wseV/KtX//
+1yUyJFRQVzmjC89dp8OIc00GmItivKLer3NbJdkR3rTUjg7+bNUO27Qp3AFREmiJ
+P+M7ouvcQRvByUWbp/LOrJpMdJLysRBO562RwrtwTjltdvufyYswbBZOKEiUh1Jc
+Ged+3+SJdhwq3Wy+R3Uj7YE7mUMu1QNbANIMrwF8W93EA53eoL2+cKmuaVU6ZURL
+xgSJaY6TrunnSI9XTROLtjsFlJorYWy2tvG7Q5Hw3OkO2Xdz/mm85VTkiusg9DMB
+WWTv607YtsIO0FhKmcV4bp3q/EkRj3t/zLvL9uFJrWDGkuShZq6fQvqbCvaokOPY
++M0ZRIwgwa9UpEE0BMklVWqR6BGyap614gOgcOjYM70WRNl59Qne+g128ZN7g9nz
+61F70i7kUngV0ZUz1/Fu/NCG+6wGF85ZbFmQl60YHPDw1FtjVUuKyBblaDzdJunx
+yQr2t9RUokzFBFK0lGW3+yf0WDQ5fqTMs5h8bz1FCq8/HzWmpdOfqePLe4zsld3b
+1nFuSohaIfbn/HDdTNtTBGQPgz8ZswQ6ejJJqTLz9D/odbqn9LeIhDZXcQTf
+-----END CERTIFICATE-----
diff --git a/packages/Tethering/apex/manifest.json b/packages/Tethering/apex/manifest.json
index 078302ac51a4..538ffb3ad6e4 100644
--- a/packages/Tethering/apex/manifest.json
+++ b/packages/Tethering/apex/manifest.json
@@ -1,4 +1,4 @@
{
- "name": "com.android.tethering.apex",
+ "name": "com.android.tethering",
"version": 300000000
}
diff --git a/packages/Tethering/common/TetheringLib/Android.bp b/packages/Tethering/common/TetheringLib/Android.bp
index adc5a723a960..5785707cb9c5 100644
--- a/packages/Tethering/common/TetheringLib/Android.bp
+++ b/packages/Tethering/common/TetheringLib/Android.bp
@@ -12,7 +12,6 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-//
// AIDL interfaces between the core system and the tethering mainline module.
aidl_interface {
@@ -20,10 +19,7 @@ aidl_interface {
local_include_dir: "src",
include_dirs: ["frameworks/base/core/java"], // For framework parcelables.
srcs: [
- "src/android/net/ITetherInternalCallback.aidl",
- "src/android/net/ITetheringConnector.aidl",
- "src/android/net/TetheringConfigurationParcel.aidl",
- "src/android/net/TetherStatesParcel.aidl",
+ "src/android/net/*.aidl",
],
backend: {
ndk: {
@@ -36,16 +32,32 @@ aidl_interface {
}
java_library {
- name: "tethering-client",
+ name: "framework-tethering",
sdk_version: "system_current",
+ srcs: [
+ "src/android/net/TetheringManager.java",
+ ":framework-tethering-annotations",
+ ],
static_libs: [
"tethering-aidl-interfaces-java",
],
+ jarjar_rules: "jarjar-rules.txt",
+ installable: true,
+
+ libs: [
+ "android_system_stubs_current",
+ ],
}
-// This is temporary file group which would be removed after TetheringManager is built
-// into tethering-client. Will be done by aosp/1156906.
filegroup {
- name: "tethering-manager",
- srcs: ["src/android/net/TetheringManager.java"],
+ name: "framework-tethering-srcs",
+ srcs: [
+ "src/android/net/TetheringManager.java",
+ "src/android/net/IIntResultListener.aidl",
+ "src/android/net/ITetheringEventCallback.aidl",
+ "src/android/net/ITetheringConnector.aidl",
+ "src/android/net/TetheringConfigurationParcel.aidl",
+ "src/android/net/TetherStatesParcel.aidl",
+ ],
+ path: "src"
}
diff --git a/packages/Tethering/common/TetheringLib/jarjar-rules.txt b/packages/Tethering/common/TetheringLib/jarjar-rules.txt
new file mode 100644
index 000000000000..35e0f88e70fa
--- /dev/null
+++ b/packages/Tethering/common/TetheringLib/jarjar-rules.txt
@@ -0,0 +1 @@
+rule android.annotation.** com.android.networkstack.tethering.annotation.@1
diff --git a/core/java/android/net/ITetheringEventCallback.aidl b/packages/Tethering/common/TetheringLib/src/android/net/IIntResultListener.aidl
index d502088542a6..c3d66ee14526 100644
--- a/core/java/android/net/ITetheringEventCallback.aidl
+++ b/packages/Tethering/common/TetheringLib/src/android/net/IIntResultListener.aidl
@@ -16,13 +16,10 @@
package android.net;
-import android.net.Network;
-
/**
- * Callback class for receiving tethering changed events
- * @hide
+ * Listener interface allowing objects to listen to various module event.
+ * {@hide}
*/
-oneway interface ITetheringEventCallback
-{
- void onUpstreamChanged(in Network network);
+oneway interface IIntResultListener {
+ void onResult(int resultCode);
}
diff --git a/packages/Tethering/common/TetheringLib/src/android/net/ITetheringConnector.aidl b/packages/Tethering/common/TetheringLib/src/android/net/ITetheringConnector.aidl
index bfe502fbeb11..d30c39986984 100644
--- a/packages/Tethering/common/TetheringLib/src/android/net/ITetheringConnector.aidl
+++ b/packages/Tethering/common/TetheringLib/src/android/net/ITetheringConnector.aidl
@@ -15,23 +15,31 @@
*/
package android.net;
-import android.net.ITetherInternalCallback;
+import android.net.IIntResultListener;
+import android.net.ITetheringEventCallback;
import android.os.ResultReceiver;
/** @hide */
oneway interface ITetheringConnector {
- void tether(String iface);
+ void tether(String iface, String callerPkg, IIntResultListener receiver);
- void untether(String iface);
+ void untether(String iface, String callerPkg, IIntResultListener receiver);
- void setUsbTethering(boolean enable);
+ void setUsbTethering(boolean enable, String callerPkg, IIntResultListener receiver);
- void startTethering(int type, in ResultReceiver receiver, boolean showProvisioningUi);
+ void startTethering(int type, in ResultReceiver receiver, boolean showProvisioningUi,
+ String callerPkg);
- void stopTethering(int type);
+ void stopTethering(int type, String callerPkg, IIntResultListener receiver);
void requestLatestTetheringEntitlementResult(int type, in ResultReceiver receiver,
- boolean showEntitlementUi);
+ boolean showEntitlementUi, String callerPkg);
- void registerTetherInternalCallback(ITetherInternalCallback callback);
+ void registerTetheringEventCallback(ITetheringEventCallback callback, String callerPkg);
+
+ void unregisterTetheringEventCallback(ITetheringEventCallback callback, String callerPkg);
+
+ void isTetheringSupported(String callerPkg, IIntResultListener receiver);
+
+ void stopAllTethering(String callerPkg, IIntResultListener receiver);
}
diff --git a/packages/Tethering/common/TetheringLib/src/android/net/ITetherInternalCallback.aidl b/packages/Tethering/common/TetheringLib/src/android/net/ITetheringEventCallback.aidl
index abb00e819f50..28361954e11e 100644
--- a/packages/Tethering/common/TetheringLib/src/android/net/ITetherInternalCallback.aidl
+++ b/packages/Tethering/common/TetheringLib/src/android/net/ITetheringEventCallback.aidl
@@ -21,14 +21,15 @@ import android.net.TetheringConfigurationParcel;
import android.net.TetherStatesParcel;
/**
- * Callback class for receiving tethering changed events
+ * Callback class for receiving tethering changed events.
* @hide
*/
-oneway interface ITetherInternalCallback
+oneway interface ITetheringEventCallback
{
+ void onCallbackStarted(in Network network, in TetheringConfigurationParcel config,
+ in TetherStatesParcel states);
+ void onCallbackStopped(int errorCode);
void onUpstreamChanged(in Network network);
void onConfigurationChanged(in TetheringConfigurationParcel config);
void onTetherStatesChanged(in TetherStatesParcel states);
- void onCallbackCreated(in Network network, in TetheringConfigurationParcel config,
- in TetherStatesParcel states);
}
diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java b/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
index 7fb286b5fa11..a49ab85d2faf 100644
--- a/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
+++ b/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
@@ -15,147 +15,155 @@
*/
package android.net;
-import static android.Manifest.permission.NETWORK_STACK;
import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
-import static android.net.ConnectivityManager.TETHER_ERROR_SERVICE_UNAVAIL;
import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.net.util.SharedLog;
+import android.content.Context;
+import android.net.ConnectivityManager.OnTetheringEventCallback;
import android.os.ConditionVariable;
import android.os.IBinder;
-import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ResultReceiver;
-import android.util.Slog;
+import android.util.ArrayMap;
+import android.util.Log;
-import com.android.internal.annotations.GuardedBy;
-
-import java.io.PrintWriter;
-import java.util.StringJoiner;
+import java.util.concurrent.Executor;
/**
- * Service used to communicate with the tethering, which is running in a separate module.
+ * This class provides the APIs to control the tethering service.
+ * <p> The primary responsibilities of this class are to provide the APIs for applications to
+ * start tethering, stop tethering, query configuration and query status.
+ *
* @hide
*/
+// TODO: make it @SystemApi
public class TetheringManager {
private static final String TAG = TetheringManager.class.getSimpleName();
+ private static final int DEFAULT_TIMEOUT_MS = 60_000;
private static TetheringManager sInstance;
- @Nullable
- private ITetheringConnector mConnector;
- private TetherInternalCallback mCallback;
- private Network mTetherUpstream;
+ private final ITetheringConnector mConnector;
+ private final TetheringCallbackInternal mCallback;
+ private final Context mContext;
+ private final ArrayMap<OnTetheringEventCallback, ITetheringEventCallback>
+ mTetheringEventCallbacks = new ArrayMap<>();
+
private TetheringConfigurationParcel mTetheringConfiguration;
private TetherStatesParcel mTetherStatesParcel;
- private final RemoteCallbackList<ITetheringEventCallback> mTetheringEventCallbacks =
- new RemoteCallbackList<>();
- @GuardedBy("mLog")
- private final SharedLog mLog = new SharedLog(TAG);
-
- private TetheringManager() { }
+ public static final int TETHER_ERROR_NO_ERROR = 0;
+ public static final int TETHER_ERROR_UNKNOWN_IFACE = 1;
+ public static final int TETHER_ERROR_SERVICE_UNAVAIL = 2;
+ public static final int TETHER_ERROR_UNSUPPORTED = 3;
+ public static final int TETHER_ERROR_UNAVAIL_IFACE = 4;
+ public static final int TETHER_ERROR_MASTER_ERROR = 5;
+ public static final int TETHER_ERROR_TETHER_IFACE_ERROR = 6;
+ public static final int TETHER_ERROR_UNTETHER_IFACE_ERROR = 7;
+ public static final int TETHER_ERROR_ENABLE_NAT_ERROR = 8;
+ public static final int TETHER_ERROR_DISABLE_NAT_ERROR = 9;
+ public static final int TETHER_ERROR_IFACE_CFG_ERROR = 10;
+ public static final int TETHER_ERROR_PROVISION_FAILED = 11;
+ public static final int TETHER_ERROR_DHCPSERVER_ERROR = 12;
+ public static final int TETHER_ERROR_ENTITLEMENT_UNKONWN = 13;
+ public static final int TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION = 14;
+ public static final int TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION = 15;
/**
- * Get the TetheringManager singleton instance.
+ * Create a TetheringManager object for interacting with the tethering service.
*/
- public static synchronized TetheringManager getInstance() {
- if (sInstance == null) {
- sInstance = new TetheringManager();
+ public TetheringManager(@NonNull final Context context, @NonNull final IBinder service) {
+ mContext = context;
+ mConnector = ITetheringConnector.Stub.asInterface(service);
+ mCallback = new TetheringCallbackInternal();
+
+ final String pkgName = mContext.getOpPackageName();
+ Log.i(TAG, "registerTetheringEventCallback:" + pkgName);
+ try {
+ mConnector.registerTetheringEventCallback(mCallback, pkgName);
+ } catch (RemoteException e) {
+ throw new IllegalStateException(e);
}
- return sInstance;
}
- private class TetheringConnection implements
- ConnectivityModuleConnector.ModuleServiceCallback {
- @Override
- public void onModuleServiceConnected(@NonNull IBinder service) {
- logi("Tethering service connected");
- registerTetheringService(service);
- }
+ private interface RequestHelper {
+ void runRequest(IIntResultListener listener);
}
- private void registerTetheringService(@NonNull IBinder service) {
- final ITetheringConnector connector = ITetheringConnector.Stub.asInterface(service);
+ private class RequestDispatcher {
+ private final ConditionVariable mWaiting;
+ public int mRemoteResult;
- log("Tethering service registered");
+ private final IIntResultListener mListener = new IIntResultListener.Stub() {
+ @Override
+ public void onResult(final int resultCode) {
+ mRemoteResult = resultCode;
+ mWaiting.open();
+ }
+ };
- // Currently TetheringManager instance is only used by ConnectivityService and mConnector
- // only expect to assign once when system server start and bind tethering service.
- // STOPSHIP: Change mConnector to final before TetheringManager put into boot classpath.
- mConnector = connector;
- mCallback = new TetherInternalCallback();
- try {
- mConnector.registerTetherInternalCallback(mCallback);
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ RequestDispatcher() {
+ mWaiting = new ConditionVariable();
}
- }
- private class TetherInternalCallback extends ITetherInternalCallback.Stub {
- private final ConditionVariable mWaitForCallback = new ConditionVariable(false);
- private static final int EVENT_CALLBACK_TIMEOUT_MS = 60_000;
+ int waitForResult(final RequestHelper request) {
+ request.runRequest(mListener);
+ if (!mWaiting.block(DEFAULT_TIMEOUT_MS)) {
+ throw new IllegalStateException("Callback timeout");
+ }
- @Override
- public void onUpstreamChanged(Network network) {
- mTetherUpstream = network;
- reportUpstreamChanged(network);
- }
+ throwIfPermissionFailure(mRemoteResult);
- @Override
- public void onConfigurationChanged(TetheringConfigurationParcel config) {
- mTetheringConfiguration = config;
+ return mRemoteResult;
}
+ }
- @Override
- public void onTetherStatesChanged(TetherStatesParcel states) {
- mTetherStatesParcel = states;
+ private void throwIfPermissionFailure(final int errorCode) {
+ switch (errorCode) {
+ case TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION:
+ throw new SecurityException("No android.permission.TETHER_PRIVILEGED"
+ + " or android.permission.WRITE_SETTINGS permission");
+ case TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION:
+ throw new SecurityException(
+ "No android.permission.ACCESS_NETWORK_STATE permission");
}
+ }
+
+ private class TetheringCallbackInternal extends ITetheringEventCallback.Stub {
+ private int mError = TETHER_ERROR_NO_ERROR;
+ private final ConditionVariable mWaitForCallback = new ConditionVariable();
@Override
- public void onCallbackCreated(Network network, TetheringConfigurationParcel config,
+ public void onCallbackStarted(Network network, TetheringConfigurationParcel config,
TetherStatesParcel states) {
- mTetherUpstream = network;
mTetheringConfiguration = config;
mTetherStatesParcel = states;
mWaitForCallback.open();
}
- boolean awaitCallbackCreation() {
- return mWaitForCallback.block(EVENT_CALLBACK_TIMEOUT_MS);
+ @Override
+ public void onCallbackStopped(int errorCode) {
+ mError = errorCode;
+ mWaitForCallback.open();
}
- }
- private void reportUpstreamChanged(Network network) {
- final int length = mTetheringEventCallbacks.beginBroadcast();
- try {
- for (int i = 0; i < length; i++) {
- try {
- mTetheringEventCallbacks.getBroadcastItem(i).onUpstreamChanged(network);
- } catch (RemoteException e) {
- // Not really very much to do here.
- }
- }
- } finally {
- mTetheringEventCallbacks.finishBroadcast();
+ @Override
+ public void onUpstreamChanged(Network network) { }
+
+ @Override
+ public void onConfigurationChanged(TetheringConfigurationParcel config) {
+ mTetheringConfiguration = config;
}
- }
- /**
- * Start the tethering service. Should be called only once on device startup.
- *
- * <p>This method will start the tethering service either in the network stack process,
- * or inside the system server on devices that do not support the tethering module.
- *
- * {@hide}
- */
- public void start() {
- // Using MAINLINE_NETWORK_STACK permission after cutting off the dpendency of system server.
- ConnectivityModuleConnector.getInstance().startModuleService(
- ITetheringConnector.class.getName(), NETWORK_STACK,
- new TetheringConnection());
- log("Tethering service start requested");
+ @Override
+ public void onTetherStatesChanged(TetherStatesParcel states) {
+ mTetherStatesParcel = states;
+ }
+
+ public void waitForStarted() {
+ mWaitForCallback.block(DEFAULT_TIMEOUT_MS);
+ throwIfPermissionFailure(mError);
+ }
}
/**
@@ -165,108 +173,110 @@ public class TetheringManager {
* IP network interface is available, dhcp will still run and traffic will be
* allowed between the tethered devices and this device, though upstream net
* access will of course fail until an upstream network interface becomes
- * active. Note: return value do not have any meaning. It is better to use
- * #getTetherableIfaces() to ensure corresponding interface is available for
- * tethering before calling #tether().
+ * active.
*
- * @deprecated The only usages should be in PanService and Wifi P2P which
- * need direct access.
+ * @deprecated The only usages is PanService. It uses this for legacy reasons
+ * and will migrate away as soon as possible.
*
- * {@hide}
+ * @param iface the interface name to tether.
+ * @return error a {@code TETHER_ERROR} value indicating success or failure type
*/
@Deprecated
- public int tether(@NonNull String iface) {
- if (mConnector == null) {
- Slog.wtf(TAG, "Tethering not ready yet");
- return TETHER_ERROR_SERVICE_UNAVAIL;
- }
- try {
- mConnector.tether(iface);
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- }
- return TETHER_ERROR_NO_ERROR;
+ public int tether(@NonNull final String iface) {
+ final String callerPkg = mContext.getOpPackageName();
+ Log.i(TAG, "tether caller:" + callerPkg);
+ final RequestDispatcher dispatcher = new RequestDispatcher();
+
+ return dispatcher.waitForResult(listener -> {
+ try {
+ mConnector.tether(iface, callerPkg, listener);
+ } catch (RemoteException e) {
+ throw new IllegalStateException(e);
+ }
+ });
}
/**
* Stop tethering the named interface.
*
- * @deprecated
- * {@hide}
+ * @deprecated The only usages is PanService. It uses this for legacy reasons
+ * and will migrate away as soon as possible.
*/
@Deprecated
- public int untether(@NonNull String iface) {
- if (mConnector == null) {
- Slog.wtf(TAG, "Tethering not ready yet");
- return TETHER_ERROR_SERVICE_UNAVAIL;
- }
- try {
- mConnector.untether(iface);
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- }
- return TETHER_ERROR_NO_ERROR;
+ public int untether(@NonNull final String iface) {
+ final String callerPkg = mContext.getOpPackageName();
+ Log.i(TAG, "untether caller:" + callerPkg);
+
+ final RequestDispatcher dispatcher = new RequestDispatcher();
+
+ return dispatcher.waitForResult(listener -> {
+ try {
+ mConnector.untether(iface, callerPkg, listener);
+ } catch (RemoteException e) {
+ throw new IllegalStateException(e);
+ }
+ });
}
/**
- * Attempt to both alter the mode of USB and Tethering of USB. WARNING: New client should not
- * use this API anymore. All clients should use #startTethering or #stopTethering which
- * encapsulate proper entitlement logic. If the API is used and an entitlement check is needed,
- * downstream USB tethering will be enabled but will not have any upstream.
+ * Attempt to both alter the mode of USB and Tethering of USB.
*
- * @deprecated
- * {@hide}
+ * @deprecated New client should not use this API anymore. All clients should use
+ * #startTethering or #stopTethering which encapsulate proper entitlement logic. If the API is
+ * used and an entitlement check is needed, downstream USB tethering will be enabled but will
+ * not have any upstream.
*/
@Deprecated
- public int setUsbTethering(boolean enable) {
- if (mConnector == null) {
- Slog.wtf(TAG, "Tethering not ready yet");
- return TETHER_ERROR_SERVICE_UNAVAIL;
- }
- try {
- mConnector.setUsbTethering(enable);
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- }
- return TETHER_ERROR_NO_ERROR;
+ public int setUsbTethering(final boolean enable) {
+ final String callerPkg = mContext.getOpPackageName();
+ Log.i(TAG, "setUsbTethering caller:" + callerPkg);
+
+ final RequestDispatcher dispatcher = new RequestDispatcher();
+
+ return dispatcher.waitForResult(listener -> {
+ try {
+ mConnector.setUsbTethering(enable, callerPkg, listener);
+ } catch (RemoteException e) {
+ throw new IllegalStateException(e);
+ }
+ });
}
/**
* Starts tethering and runs tether provisioning for the given type if needed. If provisioning
* fails, stopTethering will be called automatically.
*
- * {@hide}
*/
// TODO: improve the usage of ResultReceiver, b/145096122
- public void startTethering(int type, @NonNull ResultReceiver receiver,
- boolean showProvisioningUi) {
- if (mConnector == null) {
- Slog.wtf(TAG, "Tethering not ready yet");
- return;
- }
+ public void startTethering(final int type, @NonNull final ResultReceiver receiver,
+ final boolean showProvisioningUi) {
+ final String callerPkg = mContext.getOpPackageName();
+ Log.i(TAG, "startTethering caller:" + callerPkg);
+
try {
- mConnector.startTethering(type, receiver, showProvisioningUi);
+ mConnector.startTethering(type, receiver, showProvisioningUi, callerPkg);
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ throw new IllegalStateException(e);
}
}
/**
* Stops tethering for the given type. Also cancels any provisioning rechecks for that type if
* applicable.
- *
- * {@hide}
*/
- public void stopTethering(int type) {
- if (mConnector == null) {
- Slog.wtf(TAG, "Tethering not ready yet");
- return;
- }
- try {
- mConnector.stopTethering(type);
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- }
+ public void stopTethering(final int type) {
+ final String callerPkg = mContext.getOpPackageName();
+ Log.i(TAG, "stopTethering caller:" + callerPkg);
+
+ final RequestDispatcher dispatcher = new RequestDispatcher();
+
+ dispatcher.waitForResult(listener -> {
+ try {
+ mConnector.stopTethering(type, callerPkg, listener);
+ } catch (RemoteException e) {
+ throw new IllegalStateException(e);
+ }
+ });
}
/**
@@ -277,47 +287,109 @@ public class TetheringManager {
* if it's really needed.
*/
// TODO: improve the usage of ResultReceiver, b/145096122
- public void requestLatestTetheringEntitlementResult(int type, @NonNull ResultReceiver receiver,
- boolean showEntitlementUi) {
- if (mConnector == null) {
- Slog.wtf(TAG, "Tethering not ready yet");
- return;
- }
+ public void requestLatestTetheringEntitlementResult(final int type,
+ @NonNull final ResultReceiver receiver, final boolean showEntitlementUi) {
+ final String callerPkg = mContext.getOpPackageName();
+ Log.i(TAG, "getLatestTetheringEntitlementResult caller:" + callerPkg);
+
try {
- mConnector.requestLatestTetheringEntitlementResult(type, receiver, showEntitlementUi);
+ mConnector.requestLatestTetheringEntitlementResult(type, receiver, showEntitlementUi,
+ callerPkg);
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ throw new IllegalStateException(e);
}
}
/**
- * Register tethering event callback.
+ * Start listening to tethering change events. Any new added callback will receive the last
+ * tethering status right away. If callback is registered,
+ * {@link OnTetheringEventCallback#onUpstreamChanged} will immediately be called. If tethering
+ * has no upstream or disabled, the argument of callback will be null. The same callback object
+ * cannot be registered twice.
*
- * {@hide}
+ * @param executor the executor on which callback will be invoked.
+ * @param callback the callback to be called when tethering has change events.
*/
- public void registerTetheringEventCallback(@NonNull ITetheringEventCallback callback) {
- mTetheringEventCallbacks.register(callback);
+ public void registerTetheringEventCallback(@NonNull Executor executor,
+ @NonNull OnTetheringEventCallback callback) {
+ final String callerPkg = mContext.getOpPackageName();
+ Log.i(TAG, "registerTetheringEventCallback caller:" + callerPkg);
+
+ synchronized (mTetheringEventCallbacks) {
+ if (!mTetheringEventCallbacks.containsKey(callback)) {
+ throw new IllegalArgumentException("callback was already registered.");
+ }
+ final ITetheringEventCallback remoteCallback = new ITetheringEventCallback.Stub() {
+ @Override
+ public void onUpstreamChanged(Network network) throws RemoteException {
+ executor.execute(() -> {
+ callback.onUpstreamChanged(network);
+ });
+ }
+
+ @Override
+ public void onCallbackStarted(Network network, TetheringConfigurationParcel config,
+ TetherStatesParcel states) {
+ executor.execute(() -> {
+ callback.onUpstreamChanged(network);
+ });
+ }
+
+ @Override
+ public void onCallbackStopped(int errorCode) {
+ executor.execute(() -> {
+ throwIfPermissionFailure(errorCode);
+ });
+ }
+
+ @Override
+ public void onConfigurationChanged(TetheringConfigurationParcel config) { }
+
+ @Override
+ public void onTetherStatesChanged(TetherStatesParcel states) { }
+ };
+ try {
+ mConnector.registerTetheringEventCallback(remoteCallback, callerPkg);
+ } catch (RemoteException e) {
+ throw new IllegalStateException(e);
+ }
+ mTetheringEventCallbacks.put(callback, remoteCallback);
+ }
}
/**
- * Unregister tethering event callback.
+ * Remove tethering event callback previously registered with
+ * {@link #registerTetheringEventCallback}.
*
- * {@hide}
+ * @param callback previously registered callback.
*/
- public void unregisterTetheringEventCallback(@NonNull ITetheringEventCallback callback) {
- mTetheringEventCallbacks.unregister(callback);
+ public void unregisterTetheringEventCallback(@NonNull final OnTetheringEventCallback callback) {
+ final String callerPkg = mContext.getOpPackageName();
+ Log.i(TAG, "unregisterTetheringEventCallback caller:" + callerPkg);
+
+ synchronized (mTetheringEventCallbacks) {
+ ITetheringEventCallback remoteCallback = mTetheringEventCallbacks.remove(callback);
+ if (remoteCallback == null) {
+ throw new IllegalArgumentException("callback was not registered.");
+ }
+ try {
+ mConnector.unregisterTetheringEventCallback(remoteCallback, callerPkg);
+ } catch (RemoteException e) {
+ throw new IllegalStateException(e);
+ }
+ }
}
/**
* Get a more detailed error code after a Tethering or Untethering
* request asynchronously failed.
*
- * {@hide}
+ * @param iface The name of the interface of interest
+ * @return error The error code of the last error tethering or untethering the named
+ * interface
*/
- public int getLastTetherError(@NonNull String iface) {
- if (!mCallback.awaitCallbackCreation()) {
- throw new NullPointerException("callback was not ready yet");
- }
+ public int getLastTetherError(@NonNull final String iface) {
+ mCallback.waitForStarted();
if (mTetherStatesParcel == null) return TETHER_ERROR_NO_ERROR;
int i = 0;
@@ -334,12 +406,11 @@ public class TetheringManager {
* USB network interfaces. If USB tethering is not supported by the
* device, this list should be empty.
*
- * {@hide}
+ * @return an array of 0 or more regular expression Strings defining
+ * what interfaces are considered tetherable usb interfaces.
*/
public @NonNull String[] getTetherableUsbRegexs() {
- if (!mCallback.awaitCallbackCreation()) {
- throw new NullPointerException("callback was not ready yet");
- }
+ mCallback.waitForStarted();
return mTetheringConfiguration.tetherableUsbRegexs;
}
@@ -348,12 +419,11 @@ public class TetheringManager {
* Wifi network interfaces. If Wifi tethering is not supported by the
* device, this list should be empty.
*
- * {@hide}
+ * @return an array of 0 or more regular expression Strings defining
+ * what interfaces are considered tetherable wifi interfaces.
*/
public @NonNull String[] getTetherableWifiRegexs() {
- if (!mCallback.awaitCallbackCreation()) {
- throw new NullPointerException("callback was not ready yet");
- }
+ mCallback.waitForStarted();
return mTetheringConfiguration.tetherableWifiRegexs;
}
@@ -362,12 +432,11 @@ public class TetheringManager {
* Bluetooth network interfaces. If Bluetooth tethering is not supported by the
* device, this list should be empty.
*
- * {@hide}
+ * @return an array of 0 or more regular expression Strings defining
+ * what interfaces are considered tetherable bluetooth interfaces.
*/
public @NonNull String[] getTetherableBluetoothRegexs() {
- if (!mCallback.awaitCallbackCreation()) {
- throw new NullPointerException("callback was not ready yet");
- }
+ mCallback.waitForStarted();
return mTetheringConfiguration.tetherableBluetoothRegexs;
}
@@ -375,40 +444,42 @@ public class TetheringManager {
* Get the set of tetherable, available interfaces. This list is limited by
* device configuration and current interface existence.
*
- * {@hide}
+ * @return an array of 0 or more Strings of tetherable interface names.
*/
public @NonNull String[] getTetherableIfaces() {
- if (!mCallback.awaitCallbackCreation()) {
- throw new NullPointerException("callback was not ready yet");
- }
+ mCallback.waitForStarted();
if (mTetherStatesParcel == null) return new String[0];
+
return mTetherStatesParcel.availableList;
}
/**
* Get the set of tethered interfaces.
*
- * {@hide}
+ * @return an array of 0 or more String of currently tethered interface names.
*/
public @NonNull String[] getTetheredIfaces() {
- if (!mCallback.awaitCallbackCreation()) {
- throw new NullPointerException("callback was not ready yet");
- }
+ mCallback.waitForStarted();
if (mTetherStatesParcel == null) return new String[0];
+
return mTetherStatesParcel.tetheredList;
}
/**
* Get the set of interface names which attempted to tether but
- * failed.
+ * failed. Re-attempting to tether may cause them to reset to the Tethered
+ * state. Alternatively, causing the interface to be destroyed and recreated
+ * may cause them to reset to the available state.
+ * {@link ConnectivityManager#getLastTetherError} can be used to get more
+ * information on the cause of the errors.
*
- * {@hide}
+ * @return an array of 0 or more String indicating the interface names
+ * which failed to tether.
*/
public @NonNull String[] getTetheringErroredIfaces() {
- if (!mCallback.awaitCallbackCreation()) {
- throw new NullPointerException("callback was not ready yet");
- }
+ mCallback.waitForStarted();
if (mTetherStatesParcel == null) return new String[0];
+
return mTetherStatesParcel.erroredIfaceList;
}
@@ -416,123 +487,49 @@ public class TetheringManager {
* Get the set of tethered dhcp ranges.
*
* @deprecated This API just return the default value which is not used in DhcpServer.
- * {@hide}
*/
@Deprecated
public @NonNull String[] getTetheredDhcpRanges() {
- if (!mCallback.awaitCallbackCreation()) {
- throw new NullPointerException("callback was not ready yet");
- }
+ mCallback.waitForStarted();
return mTetheringConfiguration.legacyDhcpRanges;
}
/**
- * Check if the device allows for tethering.
+ * Check if the device allows for tethering. It may be disabled via
+ * {@code ro.tether.denied} system property, Settings.TETHER_SUPPORTED or
+ * due to device configuration.
*
- * {@hide}
- */
- public boolean hasTetherableConfiguration() {
- if (!mCallback.awaitCallbackCreation()) {
- throw new NullPointerException("callback was not ready yet");
- }
- final boolean hasDownstreamConfiguration =
- (mTetheringConfiguration.tetherableUsbRegexs.length != 0)
- || (mTetheringConfiguration.tetherableWifiRegexs.length != 0)
- || (mTetheringConfiguration.tetherableBluetoothRegexs.length != 0);
- final boolean hasUpstreamConfiguration =
- (mTetheringConfiguration.preferredUpstreamIfaceTypes.length != 0)
- || mTetheringConfiguration.chooseUpstreamAutomatically;
-
- return hasDownstreamConfiguration && hasUpstreamConfiguration;
- }
-
- /**
- * Log a message in the local log.
- */
- private void log(@NonNull String message) {
- synchronized (mLog) {
- mLog.log(message);
- }
- }
-
- /**
- * Log a condition that should never happen.
+ * @return a boolean - {@code true} indicating Tethering is supported.
*/
- private void logWtf(@NonNull String message, @Nullable Throwable e) {
- Slog.wtf(TAG, message);
- synchronized (mLog) {
- mLog.e(message, e);
- }
- }
+ public boolean isTetheringSupported() {
+ final String callerPkg = mContext.getOpPackageName();
+
+ final RequestDispatcher dispatcher = new RequestDispatcher();
+ final int ret = dispatcher.waitForResult(listener -> {
+ try {
+ mConnector.isTetheringSupported(callerPkg, listener);
+ } catch (RemoteException e) {
+ throw new IllegalStateException(e);
+ }
+ });
- /**
- * Log a ERROR level message in the local and system logs.
- */
- private void loge(@NonNull String message, @Nullable Throwable e) {
- synchronized (mLog) {
- mLog.e(message, e);
- }
+ return ret == TETHER_ERROR_NO_ERROR;
}
/**
- * Log a INFO level message in the local and system logs.
+ * Stop all active tethering.
*/
- private void logi(@NonNull String message) {
- synchronized (mLog) {
- mLog.i(message);
- }
- }
-
- /**
- * Dump TetheringManager logs to the specified {@link PrintWriter}.
- */
- public void dump(@NonNull PrintWriter pw) {
- // dump is thread-safe on SharedLog
- mLog.dump(null, pw, null);
-
- pw.print("subId: ");
- pw.println(mTetheringConfiguration.subId);
-
- dumpStringArray(pw, "tetherableUsbRegexs",
- mTetheringConfiguration.tetherableUsbRegexs);
- dumpStringArray(pw, "tetherableWifiRegexs",
- mTetheringConfiguration.tetherableWifiRegexs);
- dumpStringArray(pw, "tetherableBluetoothRegexs",
- mTetheringConfiguration.tetherableBluetoothRegexs);
-
- pw.print("isDunRequired: ");
- pw.println(mTetheringConfiguration.isDunRequired);
-
- pw.print("chooseUpstreamAutomatically: ");
- pw.println(mTetheringConfiguration.chooseUpstreamAutomatically);
-
- dumpStringArray(pw, "legacyDhcpRanges", mTetheringConfiguration.legacyDhcpRanges);
- dumpStringArray(pw, "defaultIPv4DNS", mTetheringConfiguration.defaultIPv4DNS);
-
- dumpStringArray(pw, "provisioningApp", mTetheringConfiguration.provisioningApp);
- pw.print("provisioningAppNoUi: ");
- pw.println(mTetheringConfiguration.provisioningAppNoUi);
-
- pw.print("enableLegacyDhcpServer: ");
- pw.println(mTetheringConfiguration.enableLegacyDhcpServer);
-
- pw.println();
- }
-
- private static void dumpStringArray(@NonNull PrintWriter pw, @NonNull String label,
- @Nullable String[] values) {
- pw.print(label);
- pw.print(": ");
-
- if (values != null) {
- final StringJoiner sj = new StringJoiner(", ", "[", "]");
- for (String value : values) sj.add(value);
-
- pw.print(sj.toString());
- } else {
- pw.print("null");
- }
-
- pw.println();
+ public void stopAllTethering() {
+ final String callerPkg = mContext.getOpPackageName();
+ Log.i(TAG, "stopAllTethering caller:" + callerPkg);
+
+ final RequestDispatcher dispatcher = new RequestDispatcher();
+ dispatcher.waitForResult(listener -> {
+ try {
+ mConnector.stopAllTethering(callerPkg, listener);
+ } catch (RemoteException e) {
+ throw new IllegalStateException(e);
+ }
+ });
}
}
diff --git a/packages/Tethering/jarjar-rules.txt b/packages/Tethering/jarjar-rules.txt
new file mode 100644
index 000000000000..dd9eab74e851
--- /dev/null
+++ b/packages/Tethering/jarjar-rules.txt
@@ -0,0 +1,15 @@
+# These must be kept in sync with the framework-tethering-shared-srcs filegroup.
+# If there are files in that filegroup that do not appear here, the classes in the
+# module will be overwritten by the ones in the framework.
+# Don't jar-jar the entire package because tethering still use some internal classes
+# (like TrafficStatsConstants in com.android.internal.util)
+# TODO: simply these when tethering is built as system_current.
+rule com.android.internal.util.BitUtils* com.android.networkstack.tethering.util.BitUtils@1
+rule com.android.internal.util.IndentingPrintWriter.java* com.android.networkstack.tethering.util.IndentingPrintWriter.java@1
+rule com.android.internal.util.IState.java* com.android.networkstack.tethering.util.IState.java@1
+rule com.android.internal.util.MessageUtils* com.android.networkstack.tethering.util.MessageUtils@1
+rule com.android.internal.util.Preconditions* com.android.networkstack.tethering.util.Preconditions@1
+rule com.android.internal.util.State* com.android.networkstack.tethering.util.State@1
+rule com.android.internal.util.StateMachine* com.android.networkstack.tethering.util.StateMachine@1
+
+rule android.net.LocalLog* com.android.networkstack.tethering.LocalLog@1
diff --git a/packages/Tethering/proguard.flags b/packages/Tethering/proguard.flags
index 77fc024a8755..1f83a663827c 100644
--- a/packages/Tethering/proguard.flags
+++ b/packages/Tethering/proguard.flags
@@ -1 +1,9 @@
-#TBD
+# Keep class's integer static field for MessageUtils to parsing their name.
+-keep class com.android.server.connectivity.tethering.Tethering$TetherMasterSM {
+ static final int CMD_*;
+ static final int EVENT_*;
+}
+
+-keepclassmembers class android.net.ip.IpServer {
+ static final int CMD_*;
+}
diff --git a/packages/Tethering/src/android/net/ip/IpServer.java b/packages/Tethering/src/android/net/ip/IpServer.java
index ff3d7bc6fd35..8fde52040ecc 100644
--- a/packages/Tethering/src/android/net/ip/IpServer.java
+++ b/packages/Tethering/src/android/net/ip/IpServer.java
@@ -30,7 +30,6 @@ import android.net.InterfaceConfiguration;
import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.LinkProperties;
-import android.net.NetworkStackClient;
import android.net.RouteInfo;
import android.net.dhcp.DhcpServerCallbacks;
import android.net.dhcp.DhcpServingParamsParcel;
@@ -122,7 +121,7 @@ public class IpServer extends StateMachine {
* @param state one of STATE_*
* @param lastError one of ConnectivityManager.TETHER_ERROR_*
*/
- public void updateInterfaceState(IpServer who, int state, int lastError) {}
+ public void updateInterfaceState(IpServer who, int state, int lastError) { }
/**
* Notify that |who| has new LinkProperties.
@@ -130,11 +129,11 @@ public class IpServer extends StateMachine {
* @param who the calling instance of IpServer
* @param newLp the new LinkProperties to report
*/
- public void updateLinkProperties(IpServer who, LinkProperties newLp) {}
+ public void updateLinkProperties(IpServer who, LinkProperties newLp) { }
}
/** Capture IpServer dependencies, for injection. */
- public static class Dependencies {
+ public abstract static class Dependencies {
/** Create a RouterAdvertisementDaemon instance to be used by IpServer.*/
public RouterAdvertisementDaemon getRouterAdvertisementDaemon(InterfaceParams ifParams) {
return new RouterAdvertisementDaemon(ifParams);
@@ -149,13 +148,9 @@ public class IpServer extends StateMachine {
return NetdService.getInstance();
}
- /**
- * Create a DhcpServer instance to be used by IpServer.
- */
- public void makeDhcpServer(String ifName, DhcpServingParamsParcel params,
- DhcpServerCallbacks cb) {
- NetworkStackClient.getInstance().makeDhcpServer(ifName, params, cb);
- }
+ /** Create a DhcpServer instance to be used by IpServer. */
+ public abstract void makeDhcpServer(String ifName, DhcpServingParamsParcel params,
+ DhcpServerCallbacks cb);
}
private static final int BASE_IFACE = Protocol.BASE_TETHERING + 100;
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java b/packages/Tethering/src/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java
index edfe3cad9039..93054140213d 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java
@@ -21,7 +21,6 @@ import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
-import android.net.NetworkState;
import android.net.RouteInfo;
import android.net.ip.IpServer;
import android.net.util.NetworkConstants;
@@ -72,7 +71,7 @@ public class IPv6TetheringCoordinator {
private final LinkedList<Downstream> mActiveDownstreams;
private final byte[] mUniqueLocalPrefix;
private short mNextSubnetId;
- private NetworkState mUpstreamNetworkState;
+ private UpstreamNetworkState mUpstreamNetworkState;
public IPv6TetheringCoordinator(ArrayList<IpServer> notifyList, SharedLog log) {
mNotifyList = notifyList;
@@ -115,11 +114,11 @@ public class IPv6TetheringCoordinator {
}
/**
- * Call when upstream NetworkState may be changed.
- * If upstream has ipv6 for tethering, update this new NetworkState
+ * Call when UpstreamNetworkState may be changed.
+ * If upstream has ipv6 for tethering, update this new UpstreamNetworkState
* to IpServer. Otherwise stop ipv6 tethering on downstream interfaces.
*/
- public void updateUpstreamNetworkState(NetworkState ns) {
+ public void updateUpstreamNetworkState(UpstreamNetworkState ns) {
if (VDBG) {
Log.d(TAG, "updateUpstreamNetworkState: " + toDebugString(ns));
}
@@ -144,18 +143,15 @@ public class IPv6TetheringCoordinator {
}
}
- private void setUpstreamNetworkState(NetworkState ns) {
+ private void setUpstreamNetworkState(UpstreamNetworkState ns) {
if (ns == null) {
mUpstreamNetworkState = null;
} else {
// Make a deep copy of the parts we need.
- mUpstreamNetworkState = new NetworkState(
- null,
+ mUpstreamNetworkState = new UpstreamNetworkState(
new LinkProperties(ns.linkProperties),
new NetworkCapabilities(ns.networkCapabilities),
- new Network(ns.network),
- null,
- null);
+ new Network(ns.network));
}
mLog.log("setUpstreamNetworkState: " + toDebugString(mUpstreamNetworkState));
@@ -295,14 +291,11 @@ public class IPv6TetheringCoordinator {
return in6addr;
}
- private static String toDebugString(NetworkState ns) {
+ private static String toDebugString(UpstreamNetworkState ns) {
if (ns == null) {
- return "NetworkState{null}";
+ return "UpstreamNetworkState{null}";
}
- return String.format("NetworkState{%s, %s, %s}",
- ns.network,
- ns.networkCapabilities,
- ns.linkProperties);
+ return ns.toString();
}
private static void stopIPv6TetheringOn(IpServer ipServer) {
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
index 743fd6a63217..3d414eefbc04 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
@@ -16,6 +16,7 @@
package com.android.server.connectivity.tethering;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.hardware.usb.UsbManager.USB_CONFIGURED;
import static android.hardware.usb.UsbManager.USB_CONNECTED;
import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS;
@@ -63,13 +64,12 @@ import android.hardware.usb.UsbManager;
import android.net.INetd;
import android.net.INetworkPolicyManager;
import android.net.INetworkStatsService;
-import android.net.ITetherInternalCallback;
+import android.net.ITetheringEventCallback;
import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkInfo;
-import android.net.NetworkState;
import android.net.NetworkUtils;
import android.net.TetherStatesParcel;
import android.net.TetheringConfigurationParcel;
@@ -89,6 +89,7 @@ import android.os.Handler;
import android.os.INetworkManagementService;
import android.os.Looper;
import android.os.Message;
+import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.UserHandle;
@@ -103,13 +104,12 @@ import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.notification.SystemNotificationChannels;
-import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.MessageUtils;
import com.android.internal.util.Protocol;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
-import com.android.tethering.R;
+import com.android.networkstack.tethering.R;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -162,6 +162,8 @@ public class Tethering {
}
private final SharedLog mLog = new SharedLog(TAG);
+ private final RemoteCallbackList<ITetheringEventCallback> mTetheringEventCallbacks =
+ new RemoteCallbackList<>();
// used to synchronize public access to members
private final Object mPublicSync;
@@ -188,8 +190,8 @@ public class Tethering {
private final NetdCallback mNetdCallback;
private final UserRestrictionActionListener mTetheringRestriction;
private int mActiveDataSubId = INVALID_SUBSCRIPTION_ID;
- // All the usage of mTetherInternalCallback should run in the same thread.
- private ITetherInternalCallback mTetherInternalCallback = null;
+ // All the usage of mTetheringEventCallback should run in the same thread.
+ private ITetheringEventCallback mTetheringEventCallback = null;
private volatile TetheringConfiguration mConfig;
private InterfaceSet mCurrentUpstreamIfaceSet;
@@ -573,6 +575,11 @@ public class Tethering {
}
}
+ boolean isTetherProvisioningRequired() {
+ final TetheringConfiguration cfg = mConfig;
+ return mEntitlementMgr.isTetherProvisioningRequired(cfg);
+ }
+
// TODO: Figure out how to update for local hotspot mode interfaces.
private void sendTetherStateChangedBroadcast() {
if (!mDeps.isTetheringSupported()) return;
@@ -588,7 +595,7 @@ public class Tethering {
boolean bluetoothTethered = false;
final TetheringConfiguration cfg = mConfig;
- final TetherStatesParcel mTetherStatesParcel = new TetherStatesParcel();
+ mTetherStatesParcel = new TetherStatesParcel();
synchronized (mPublicSync) {
for (int i = 0; i < mTetherStates.size(); i++) {
@@ -1144,7 +1151,7 @@ public class Tethering {
// Needed because the canonical source of upstream truth is just the
// upstream interface set, |mCurrentUpstreamIfaceSet|.
- private boolean pertainsToCurrentUpstream(NetworkState ns) {
+ private boolean pertainsToCurrentUpstream(UpstreamNetworkState ns) {
if (ns != null && ns.linkProperties != null && mCurrentUpstreamIfaceSet != null) {
for (String ifname : ns.linkProperties.getAllInterfaceNames()) {
if (mCurrentUpstreamIfaceSet.ifnames.contains(ifname)) {
@@ -1312,7 +1319,7 @@ public class Tethering {
maybeDunSettingChanged();
final TetheringConfiguration config = mConfig;
- final NetworkState ns = (config.chooseUpstreamAutomatically)
+ final UpstreamNetworkState ns = (config.chooseUpstreamAutomatically)
? mUpstreamNetworkMonitor.getCurrentPreferredUpstream()
: mUpstreamNetworkMonitor.selectPreferredUpstreamType(
config.preferredUpstreamIfaceTypes);
@@ -1333,7 +1340,7 @@ public class Tethering {
}
}
- protected void setUpstreamNetwork(NetworkState ns) {
+ protected void setUpstreamNetwork(UpstreamNetworkState ns) {
InterfaceSet ifaces = null;
if (ns != null) {
// Find the interface with the default IPv4 route. It may be the
@@ -1349,7 +1356,7 @@ public class Tethering {
}
notifyDownstreamsOfNewUpstreamIface(ifaces);
if (ns != null && pertainsToCurrentUpstream(ns)) {
- // If we already have NetworkState for this network update it immediately.
+ // If we already have UpstreamNetworkState for this network update it immediately.
handleNewUpstreamNetworkState(ns);
} else if (mCurrentUpstreamIfaceSet == null) {
// There are no available upstream networks.
@@ -1386,7 +1393,7 @@ public class Tethering {
}
}
- protected void handleNewUpstreamNetworkState(NetworkState ns) {
+ protected void handleNewUpstreamNetworkState(UpstreamNetworkState ns) {
mIPv6TetheringCoordinator.updateUpstreamNetworkState(ns);
mOffload.updateUpstreamNetworkState(ns);
}
@@ -1450,7 +1457,7 @@ public class Tethering {
return;
}
- final NetworkState ns = (NetworkState) o;
+ final UpstreamNetworkState ns = (UpstreamNetworkState) o;
if (ns == null || !pertainsToCurrentUpstream(ns)) {
// TODO: In future, this is where upstream evaluation and selection
@@ -1720,7 +1727,7 @@ public class Tethering {
mOffloadController.stop();
}
- public void updateUpstreamNetworkState(NetworkState ns) {
+ public void updateUpstreamNetworkState(UpstreamNetworkState ns) {
mOffloadController.setUpstreamLinkProperties(
(ns != null) ? ns.linkProperties : null);
}
@@ -1796,47 +1803,67 @@ public class Tethering {
}
/** Register tethering event callback */
- void registerTetherInternalCallback(ITetherInternalCallback callback) {
+ void registerTetheringEventCallback(ITetheringEventCallback callback) {
mHandler.post(() -> {
- mTetherInternalCallback = callback;
+ mTetheringEventCallbacks.register(callback);
try {
- mTetherInternalCallback.onCallbackCreated(mTetherUpstream,
- mConfig.toStableParcelable(), mTetherStatesParcel);
+ callback.onCallbackStarted(mTetherUpstream, mConfig.toStableParcelable(),
+ mTetherStatesParcel);
} catch (RemoteException e) {
// Not really very much to do here.
}
});
}
- private void reportUpstreamChanged(Network network) {
- // Don't need to synchronized mTetherInternalCallback because all the usage of this variable
- // should run at the same thread.
- if (mTetherInternalCallback == null) return;
+ /** Unregister tethering event callback */
+ void unregisterTetheringEventCallback(ITetheringEventCallback callback) {
+ mHandler.post(() -> {
+ mTetheringEventCallbacks.unregister(callback);
+ });
+ }
+ private void reportUpstreamChanged(Network network) {
+ final int length = mTetheringEventCallbacks.beginBroadcast();
try {
- mTetherInternalCallback.onUpstreamChanged(network);
- } catch (RemoteException e) {
- // Not really very much to do here.
+ for (int i = 0; i < length; i++) {
+ try {
+ mTetheringEventCallbacks.getBroadcastItem(i).onUpstreamChanged(network);
+ } catch (RemoteException e) {
+ // Not really very much to do here.
+ }
+ }
+ } finally {
+ mTetheringEventCallbacks.finishBroadcast();
}
}
private void reportConfigurationChanged(TetheringConfigurationParcel config) {
- if (mTetherInternalCallback == null) return;
-
+ final int length = mTetheringEventCallbacks.beginBroadcast();
try {
- mTetherInternalCallback.onConfigurationChanged(config);
- } catch (RemoteException e) {
- // Not really very much to do here.
+ for (int i = 0; i < length; i++) {
+ try {
+ mTetheringEventCallbacks.getBroadcastItem(i).onConfigurationChanged(config);
+ } catch (RemoteException e) {
+ // Not really very much to do here.
+ }
+ }
+ } finally {
+ mTetheringEventCallbacks.finishBroadcast();
}
}
private void reportTetherStateChanged(TetherStatesParcel states) {
- if (mTetherInternalCallback == null) return;
-
+ final int length = mTetheringEventCallbacks.beginBroadcast();
try {
- mTetherInternalCallback.onTetherStatesChanged(states);
- } catch (RemoteException e) {
- // Not really very much to do here.
+ for (int i = 0; i < length; i++) {
+ try {
+ mTetheringEventCallbacks.getBroadcastItem(i).onTetherStatesChanged(states);
+ } catch (RemoteException e) {
+ // Not really very much to do here.
+ }
+ }
+ } finally {
+ mTetheringEventCallbacks.finishBroadcast();
}
}
@@ -1844,7 +1871,11 @@ public class Tethering {
// Binder.java closes the resource for us.
@SuppressWarnings("resource")
final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
- if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
+ if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+ != PERMISSION_GRANTED) {
+ pw.println("Permission Denial: can't dump.");
+ return;
+ }
pw.println("Tethering:");
pw.increaseIndent();
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringDependencies.java b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringDependencies.java
index 0ba84127d8da..b16b3294a112 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringDependencies.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringDependencies.java
@@ -39,7 +39,7 @@ import java.util.ArrayList;
*
* @hide
*/
-public class TetheringDependencies {
+public abstract class TetheringDependencies {
/**
* Get a reference to the offload hardware interface to be used by tethering.
*/
@@ -66,9 +66,7 @@ public class TetheringDependencies {
/**
* Get dependencies to be used by IpServer.
*/
- public IpServer.Dependencies getIpServerDependencies() {
- return new IpServer.Dependencies();
- }
+ public abstract IpServer.Dependencies getIpServerDependencies();
/**
* Indicates whether tethering is supported on the device.
@@ -80,9 +78,7 @@ public class TetheringDependencies {
/**
* Get the NetworkRequest that should be fulfilled by the default network.
*/
- public NetworkRequest getDefaultNetworkRequest() {
- return null;
- }
+ public abstract NetworkRequest getDefaultNetworkRequest();
/**
* Get a reference to the EntitlementManager to be used by tethering.
@@ -138,14 +134,10 @@ public class TetheringDependencies {
/**
* Get tethering thread looper.
*/
- public Looper getTetheringLooper() {
- return null;
- }
+ public abstract Looper getTetheringLooper();
/**
* Get Context of TetheringSerice.
*/
- public Context getContext() {
- return null;
- }
+ public abstract Context getContext();
}
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringInterfaceUtils.java b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringInterfaceUtils.java
index 0ef3805ff7c0..6334c20c2acc 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringInterfaceUtils.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringInterfaceUtils.java
@@ -19,7 +19,6 @@ package com.android.server.connectivity.tethering;
import android.annotation.Nullable;
import android.net.LinkProperties;
import android.net.NetworkCapabilities;
-import android.net.NetworkState;
import android.net.RouteInfo;
import android.net.util.InterfaceSet;
@@ -35,7 +34,7 @@ public final class TetheringInterfaceUtils {
* Get upstream interfaces for tethering based on default routes for IPv4/IPv6.
* @return null if there is no usable interface, or a set of at least one interface otherwise.
*/
- public static @Nullable InterfaceSet getTetheringInterfaces(NetworkState ns) {
+ public static @Nullable InterfaceSet getTetheringInterfaces(UpstreamNetworkState ns) {
if (ns == null) {
return null;
}
@@ -51,7 +50,7 @@ public final class TetheringInterfaceUtils {
* Get the upstream interface for IPv6 tethering.
* @return null if there is no usable interface, or the interface name otherwise.
*/
- public static @Nullable String getIPv6Interface(NetworkState ns) {
+ public static @Nullable String getIPv6Interface(UpstreamNetworkState ns) {
// Broadly speaking:
//
// [1] does the upstream have an IPv6 default route?
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java
index 456f2f7f27f5..ba30845e6348 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java
@@ -16,20 +16,36 @@
package com.android.server.connectivity.tethering;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.net.TetheringManager.TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION;
+import static android.net.TetheringManager.TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION;
+import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
+import static android.net.TetheringManager.TETHER_ERROR_UNSUPPORTED;
+
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
-import android.net.ITetherInternalCallback;
+import android.net.IIntResultListener;
+import android.net.INetworkStackConnector;
import android.net.ITetheringConnector;
+import android.net.ITetheringEventCallback;
import android.net.NetworkRequest;
+import android.net.dhcp.DhcpServerCallbacks;
+import android.net.dhcp.DhcpServingParamsParcel;
+import android.net.ip.IpServer;
import android.net.util.SharedLog;
+import android.os.Binder;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
+import android.os.RemoteException;
import android.os.ResultReceiver;
+import android.os.ServiceManager;
import android.os.SystemProperties;
+import android.os.UserManager;
import android.provider.Settings;
+import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -52,6 +68,7 @@ public class TetheringService extends Service {
private Context mContext;
private TetheringDependencies mDeps;
private Tethering mTethering;
+ private UserManager mUserManager;
@Override
public void onCreate() {
@@ -59,6 +76,7 @@ public class TetheringService extends Service {
mDeps = getTetheringDependencies();
mContext = mDeps.getContext();
mTethering = makeTethering(mDeps);
+ mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
}
/**
@@ -74,7 +92,7 @@ public class TetheringService extends Service {
*/
private synchronized IBinder makeConnector() {
if (mConnector == null) {
- mConnector = new TetheringConnector(mTethering);
+ mConnector = new TetheringConnector(mTethering, TetheringService.this);
}
return mConnector;
}
@@ -87,55 +105,197 @@ public class TetheringService extends Service {
}
private static class TetheringConnector extends ITetheringConnector.Stub {
- private final Tethering mService;
+ private final TetheringService mService;
+ private final Tethering mTethering;
- TetheringConnector(Tethering tether) {
- mService = tether;
+ TetheringConnector(Tethering tether, TetheringService service) {
+ mTethering = tether;
+ mService = service;
}
@Override
- public void tether(String iface) {
- mService.tether(iface);
+ public void tether(String iface, String callerPkg, IIntResultListener listener) {
+ if (checkAndNotifyCommonError(callerPkg, listener)) return;
+
+ try {
+ listener.onResult(mTethering.tether(iface));
+ } catch (RemoteException e) { }
}
@Override
- public void untether(String iface) {
- mService.untether(iface);
+ public void untether(String iface, String callerPkg, IIntResultListener listener) {
+ if (checkAndNotifyCommonError(callerPkg, listener)) return;
+
+ try {
+ listener.onResult(mTethering.untether(iface));
+ } catch (RemoteException e) { }
}
@Override
- public void setUsbTethering(boolean enable) {
- mService.setUsbTethering(enable);
+ public void setUsbTethering(boolean enable, String callerPkg, IIntResultListener listener) {
+ if (checkAndNotifyCommonError(callerPkg, listener)) return;
+
+ try {
+ listener.onResult(mTethering.setUsbTethering(enable));
+ } catch (RemoteException e) { }
}
@Override
- public void startTethering(int type, ResultReceiver receiver, boolean showProvisioningUi) {
- mService.startTethering(type, receiver, showProvisioningUi);
+ public void startTethering(int type, ResultReceiver receiver, boolean showProvisioningUi,
+ String callerPkg) {
+ if (checkAndNotifyCommonError(callerPkg, receiver)) return;
+
+ mTethering.startTethering(type, receiver, showProvisioningUi);
}
@Override
- public void stopTethering(int type) {
- mService.stopTethering(type);
+ public void stopTethering(int type, String callerPkg, IIntResultListener listener) {
+ if (checkAndNotifyCommonError(callerPkg, listener)) return;
+
+ try {
+ mTethering.stopTethering(type);
+ listener.onResult(TETHER_ERROR_NO_ERROR);
+ } catch (RemoteException e) { }
}
@Override
public void requestLatestTetheringEntitlementResult(int type, ResultReceiver receiver,
- boolean showEntitlementUi) {
- mService.requestLatestTetheringEntitlementResult(type, receiver, showEntitlementUi);
+ boolean showEntitlementUi, String callerPkg) {
+ if (checkAndNotifyCommonError(callerPkg, receiver)) return;
+
+ mTethering.requestLatestTetheringEntitlementResult(type, receiver, showEntitlementUi);
+ }
+
+ @Override
+ public void registerTetheringEventCallback(ITetheringEventCallback callback,
+ String callerPkg) {
+ try {
+ if (!mService.hasTetherAccessPermission()) {
+ callback.onCallbackStopped(TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION);
+ return;
+ }
+ mTethering.registerTetheringEventCallback(callback);
+ } catch (RemoteException e) { }
+ }
+
+ @Override
+ public void unregisterTetheringEventCallback(ITetheringEventCallback callback,
+ String callerPkg) {
+ try {
+ if (!mService.hasTetherAccessPermission()) {
+ callback.onCallbackStopped(TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION);
+ return;
+ }
+ mTethering.unregisterTetheringEventCallback(callback);
+ } catch (RemoteException e) { }
+ }
+
+ @Override
+ public void stopAllTethering(String callerPkg, IIntResultListener listener) {
+ if (checkAndNotifyCommonError(callerPkg, listener)) return;
+
+ try {
+ mTethering.untetherAll();
+ listener.onResult(TETHER_ERROR_NO_ERROR);
+ } catch (RemoteException e) { }
+ }
+
+ @Override
+ public void isTetheringSupported(String callerPkg, IIntResultListener listener) {
+ if (checkAndNotifyCommonError(callerPkg, listener)) return;
+
+ try {
+ listener.onResult(TETHER_ERROR_NO_ERROR);
+ } catch (RemoteException e) { }
}
@Override
- public void registerTetherInternalCallback(ITetherInternalCallback callback) {
- mService.registerTetherInternalCallback(callback);
+ protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer,
+ @Nullable String[] args) {
+ mTethering.dump(fd, writer, args);
+ }
+
+ private boolean checkAndNotifyCommonError(String callerPkg, IIntResultListener listener) {
+ try {
+ if (!mService.hasTetherChangePermission(callerPkg)) {
+ listener.onResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
+ return true;
+ }
+ if (!mService.isTetheringSupported()) {
+ listener.onResult(TETHER_ERROR_UNSUPPORTED);
+ return true;
+ }
+ } catch (RemoteException e) {
+ return true;
+ }
+
+ return false;
}
+
+ private boolean checkAndNotifyCommonError(String callerPkg, ResultReceiver receiver) {
+ if (!mService.hasTetherChangePermission(callerPkg)) {
+ receiver.send(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION, null);
+ return true;
+ }
+ if (!mService.isTetheringSupported()) {
+ receiver.send(TETHER_ERROR_UNSUPPORTED, null);
+ return true;
+ }
+
+ return false;
+ }
+
}
- @Override
- protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer,
- @Nullable String[] args) {
- mTethering.dump(fd, writer, args);
+ // if ro.tether.denied = true we default to no tethering
+ // gservices could set the secure setting to 1 though to enable it on a build where it
+ // had previously been turned off.
+ private boolean isTetheringSupported() {
+ final int defaultVal =
+ SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1;
+ final boolean tetherSupported = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.TETHER_SUPPORTED, defaultVal) != 0;
+ final boolean tetherEnabledInSettings = tetherSupported
+ && !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING);
+
+ return tetherEnabledInSettings && mTethering.hasTetherableConfiguration();
+ }
+
+ private boolean hasTetherChangePermission(String callerPkg) {
+ if (checkCallingOrSelfPermission(
+ android.Manifest.permission.TETHER_PRIVILEGED) == PERMISSION_GRANTED) {
+ return true;
+ }
+
+ if (mTethering.isTetherProvisioningRequired()) return false;
+
+
+ int uid = Binder.getCallingUid();
+ // If callerPkg's uid is not same as Binder.getCallingUid(),
+ // checkAndNoteWriteSettingsOperation will return false and the operation will be denied.
+ if (Settings.checkAndNoteWriteSettingsOperation(mContext, uid, callerPkg,
+ false /* throwException */)) {
+ return true;
+ }
+
+ return false;
}
+ private boolean hasTetherAccessPermission() {
+ if (checkCallingOrSelfPermission(
+ android.Manifest.permission.TETHER_PRIVILEGED) == PERMISSION_GRANTED) {
+ return true;
+ }
+
+ if (checkCallingOrSelfPermission(
+ android.Manifest.permission.ACCESS_NETWORK_STATE) == PERMISSION_GRANTED) {
+ return true;
+ }
+
+ return false;
+ }
+
+
/**
* An injection method for testing.
*/
@@ -159,20 +319,55 @@ public class TetheringService extends Service {
@Override
public boolean isTetheringSupported() {
- int defaultVal =
- SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1;
- boolean tetherSupported = Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.TETHER_SUPPORTED, defaultVal) != 0;
- return tetherSupported;
+ return TetheringService.this.isTetheringSupported();
}
@Override
public Context getContext() {
return TetheringService.this;
}
+
+ @Override
+ public IpServer.Dependencies getIpServerDependencies() {
+ return new IpServer.Dependencies() {
+ @Override
+ public void makeDhcpServer(String ifName, DhcpServingParamsParcel params,
+ DhcpServerCallbacks cb) {
+ try {
+ final INetworkStackConnector service = getNetworkStackConnector();
+ if (service == null) return;
+
+ service.makeDhcpServer(ifName, params, cb);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
+ };
+ }
+
+ // TODO: replace this by NetworkStackClient#getRemoteConnector after refactoring
+ // networkStackClient.
+ static final int NETWORKSTACK_TIMEOUT_MS = 60_000;
+ private INetworkStackConnector getNetworkStackConnector() {
+ IBinder connector;
+ try {
+ final long before = System.currentTimeMillis();
+ while ((connector = ServiceManager.getService(
+ Context.NETWORK_STACK_SERVICE)) == null) {
+ if (System.currentTimeMillis() - before > NETWORKSTACK_TIMEOUT_MS) {
+ Log.wtf(TAG, "Timeout, fail to get INetworkStackConnector");
+ return null;
+ }
+ Thread.sleep(200);
+ }
+ } catch (InterruptedException e) {
+ Log.wtf(TAG, "Interrupted, fail to get INetworkStackConnector");
+ return null;
+ }
+ return INetworkStackConnector.Stub.asInterface(connector);
+ }
};
}
-
return mDeps;
}
}
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java b/packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
index 9769596ab1d0..dc38c49a0c12 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
@@ -32,7 +32,6 @@ import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
-import android.net.NetworkState;
import android.net.util.PrefixUtils;
import android.net.util.SharedLog;
import android.os.Handler;
@@ -90,7 +89,7 @@ public class UpstreamNetworkMonitor {
private final StateMachine mTarget;
private final Handler mHandler;
private final int mWhat;
- private final HashMap<Network, NetworkState> mNetworkMap = new HashMap<>();
+ private final HashMap<Network, UpstreamNetworkState> mNetworkMap = new HashMap<>();
private HashSet<IpPrefix> mLocalPrefixes;
private ConnectivityManager mCM;
private EntitlementManager mEntitlementMgr;
@@ -236,7 +235,7 @@ public class UpstreamNetworkMonitor {
/**
* Select the first available network from |perferredTypes|.
*/
- public NetworkState selectPreferredUpstreamType(Iterable<Integer> preferredTypes) {
+ public UpstreamNetworkState selectPreferredUpstreamType(Iterable<Integer> preferredTypes) {
final TypeStatePair typeStatePair = findFirstAvailableUpstreamByType(
mNetworkMap.values(), preferredTypes, isCellularUpstreamPermitted());
@@ -274,8 +273,8 @@ public class UpstreamNetworkMonitor {
* preferred upstream would be DUN otherwise preferred upstream is the same as default network.
* Returns null if no current upstream is available.
*/
- public NetworkState getCurrentPreferredUpstream() {
- final NetworkState dfltState = (mDefaultInternetNetwork != null)
+ public UpstreamNetworkState getCurrentPreferredUpstream() {
+ final UpstreamNetworkState dfltState = (mDefaultInternetNetwork != null)
? mNetworkMap.get(mDefaultInternetNetwork)
: null;
if (isNetworkUsableAndNotCellular(dfltState)) return dfltState;
@@ -312,11 +311,11 @@ public class UpstreamNetworkMonitor {
if (mNetworkMap.containsKey(network)) return;
if (VDBG) Log.d(TAG, "onAvailable for " + network);
- mNetworkMap.put(network, new NetworkState(null, null, null, network, null, null));
+ mNetworkMap.put(network, new UpstreamNetworkState(null, null, network));
}
private void handleNetCap(Network network, NetworkCapabilities newNc) {
- final NetworkState prev = mNetworkMap.get(network);
+ final UpstreamNetworkState prev = mNetworkMap.get(network);
if (prev == null || newNc.equals(prev.networkCapabilities)) {
// Ignore notifications about networks for which we have not yet
// received onAvailable() (should never happen) and any duplicate
@@ -336,15 +335,15 @@ public class UpstreamNetworkMonitor {
mLog.logf("upstream network signal strength: %s -> %s", prevSignal, newSignal);
}
- mNetworkMap.put(network, new NetworkState(
- null, prev.linkProperties, newNc, network, null, null));
+ mNetworkMap.put(network, new UpstreamNetworkState(
+ prev.linkProperties, newNc, network));
// TODO: If sufficient information is available to select a more
// preferable upstream, do so now and notify the target.
notifyTarget(EVENT_ON_CAPABILITIES, network);
}
private void handleLinkProp(Network network, LinkProperties newLp) {
- final NetworkState prev = mNetworkMap.get(network);
+ final UpstreamNetworkState prev = mNetworkMap.get(network);
if (prev == null || newLp.equals(prev.linkProperties)) {
// Ignore notifications about networks for which we have not yet
// received onAvailable() (should never happen) and any duplicate
@@ -357,8 +356,8 @@ public class UpstreamNetworkMonitor {
network, newLp));
}
- mNetworkMap.put(network, new NetworkState(
- null, newLp, prev.networkCapabilities, network, null, null));
+ mNetworkMap.put(network, new UpstreamNetworkState(
+ newLp, prev.networkCapabilities, network));
// TODO: If sufficient information is available to select a more
// preferable upstream, do so now and notify the target.
notifyTarget(EVENT_ON_LINKPROPERTIES, network);
@@ -509,11 +508,11 @@ public class UpstreamNetworkMonitor {
private static class TypeStatePair {
public int type = TYPE_NONE;
- public NetworkState ns = null;
+ public UpstreamNetworkState ns = null;
}
private static TypeStatePair findFirstAvailableUpstreamByType(
- Iterable<NetworkState> netStates, Iterable<Integer> preferredTypes,
+ Iterable<UpstreamNetworkState> netStates, Iterable<Integer> preferredTypes,
boolean isCellularUpstreamPermitted) {
final TypeStatePair result = new TypeStatePair();
@@ -532,7 +531,7 @@ public class UpstreamNetworkMonitor {
nc.setSingleUid(Process.myUid());
- for (NetworkState value : netStates) {
+ for (UpstreamNetworkState value : netStates) {
if (!nc.satisfiedByNetworkCapabilities(value.networkCapabilities)) {
continue;
}
@@ -546,10 +545,10 @@ public class UpstreamNetworkMonitor {
return result;
}
- private static HashSet<IpPrefix> allLocalPrefixes(Iterable<NetworkState> netStates) {
+ private static HashSet<IpPrefix> allLocalPrefixes(Iterable<UpstreamNetworkState> netStates) {
final HashSet<IpPrefix> prefixSet = new HashSet<>();
- for (NetworkState ns : netStates) {
+ for (UpstreamNetworkState ns : netStates) {
final LinkProperties lp = ns.linkProperties;
if (lp == null) continue;
prefixSet.addAll(PrefixUtils.localPrefixesFrom(lp));
@@ -563,7 +562,7 @@ public class UpstreamNetworkMonitor {
return Integer.toString(nc.getSignalStrength());
}
- private static boolean isCellular(NetworkState ns) {
+ private static boolean isCellular(UpstreamNetworkState ns) {
return (ns != null) && isCellular(ns.networkCapabilities);
}
@@ -572,18 +571,19 @@ public class UpstreamNetworkMonitor {
&& nc.hasCapability(NET_CAPABILITY_NOT_VPN);
}
- private static boolean hasCapability(NetworkState ns, int netCap) {
+ private static boolean hasCapability(UpstreamNetworkState ns, int netCap) {
return (ns != null) && (ns.networkCapabilities != null)
&& ns.networkCapabilities.hasCapability(netCap);
}
- private static boolean isNetworkUsableAndNotCellular(NetworkState ns) {
+ private static boolean isNetworkUsableAndNotCellular(UpstreamNetworkState ns) {
return (ns != null) && (ns.networkCapabilities != null) && (ns.linkProperties != null)
&& !isCellular(ns.networkCapabilities);
}
- private static NetworkState findFirstDunNetwork(Iterable<NetworkState> netStates) {
- for (NetworkState ns : netStates) {
+ private static UpstreamNetworkState findFirstDunNetwork(
+ Iterable<UpstreamNetworkState> netStates) {
+ for (UpstreamNetworkState ns : netStates) {
if (isCellular(ns) && hasCapability(ns, NET_CAPABILITY_DUN)) return ns;
}
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkState.java b/packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkState.java
new file mode 100644
index 000000000000..68bb83759368
--- /dev/null
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkState.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.connectivity.tethering;
+
+import android.net.LinkProperties;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+
+import androidx.annotation.NonNull;
+
+/**
+ * Snapshot of tethering upstream network state.
+ */
+public class UpstreamNetworkState {
+ /** {@link LinkProperties}. */
+ public final LinkProperties linkProperties;
+ /** {@link NetworkCapabilities}. */
+ public final NetworkCapabilities networkCapabilities;
+ /** {@link Network}. */
+ public final Network network;
+
+ /** Constructs a new UpstreamNetworkState. */
+ public UpstreamNetworkState(LinkProperties linkProperties,
+ NetworkCapabilities networkCapabilities, Network network) {
+ this.linkProperties = linkProperties;
+ this.networkCapabilities = networkCapabilities;
+ this.network = network;
+ }
+
+ @NonNull
+ @Override
+ public String toString() {
+ return String.format("UpstreamNetworkState{%s, %s, %s}",
+ network == null ? "null" : network,
+ networkCapabilities == null ? "null" : networkCapabilities,
+ linkProperties == null ? "null" : linkProperties);
+ }
+}
diff --git a/packages/Tethering/tests/unit/Android.bp b/packages/Tethering/tests/unit/Android.bp
index 5b018df21aaf..81a0548cd718 100644
--- a/packages/Tethering/tests/unit/Android.bp
+++ b/packages/Tethering/tests/unit/Android.bp
@@ -33,10 +33,12 @@ android_test {
"android.test.runner",
"android.test.base",
"android.test.mock",
+ "framework-tethering",
],
jni_libs: [
// For mockito extended
"libdexmakerjvmtiagent",
"libstaticjvmtiagent",
],
+ jarjar_rules: "jarjar-rules.txt",
}
diff --git a/packages/Tethering/tests/unit/AndroidManifest.xml b/packages/Tethering/tests/unit/AndroidManifest.xml
index 049ff6d415f3..0a1cdd35b10c 100644
--- a/packages/Tethering/tests/unit/AndroidManifest.xml
+++ b/packages/Tethering/tests/unit/AndroidManifest.xml
@@ -14,13 +14,13 @@
limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.tethering.tests.unit">
+ package="com.android.networkstack.tethering.tests.unit">
<application android:debuggable="true">
<uses-library android:name="android.test.runner" />
</application>
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.tethering.tests.unit"
+ android:targetPackage="com.android.networkstack.tethering.tests.unit"
android:label="Tethering service tests">
</instrumentation>
</manifest>
diff --git a/packages/Tethering/tests/unit/jarjar-rules.txt b/packages/Tethering/tests/unit/jarjar-rules.txt
new file mode 100644
index 000000000000..64fdebd92726
--- /dev/null
+++ b/packages/Tethering/tests/unit/jarjar-rules.txt
@@ -0,0 +1,11 @@
+# Don't jar-jar the entire package because this test use some
+# internal classes (like ArrayUtils in com.android.internal.util)
+rule com.android.internal.util.BitUtils* com.android.networkstack.tethering.util.BitUtils@1
+rule com.android.internal.util.IndentingPrintWriter.java* com.android.networkstack.tethering.util.IndentingPrintWriter.java@1
+rule com.android.internal.util.IState.java* com.android.networkstack.tethering.util.IState.java@1
+rule com.android.internal.util.MessageUtils* com.android.networkstack.tethering.util.MessageUtils@1
+rule com.android.internal.util.Preconditions* com.android.networkstack.tethering.util.Preconditions@1
+rule com.android.internal.util.State* com.android.networkstack.tethering.util.State@1
+rule com.android.internal.util.StateMachine* com.android.networkstack.tethering.util.StateMachine@1
+
+rule android.net.LocalLog* com.android.networkstack.tethering.LocalLog@1
diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
index cdbc54106ce8..9d9ad10af5b3 100644
--- a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
@@ -27,7 +27,6 @@ import static android.net.ConnectivityManager.TETHERING_USB;
import static android.net.ConnectivityManager.TETHERING_WIFI;
import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
import static android.net.ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
-import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_WIFI_P2P;
import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
@@ -72,7 +71,7 @@ import android.hardware.usb.UsbManager;
import android.net.INetd;
import android.net.INetworkPolicyManager;
import android.net.INetworkStatsService;
-import android.net.ITetherInternalCallback;
+import android.net.ITetheringEventCallback;
import android.net.InterfaceConfiguration;
import android.net.IpPrefix;
import android.net.LinkAddress;
@@ -81,7 +80,7 @@ import android.net.MacAddress;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
-import android.net.NetworkState;
+import android.net.NetworkRequest;
import android.net.NetworkUtils;
import android.net.RouteInfo;
import android.net.TetherStatesParcel;
@@ -167,6 +166,7 @@ public class TetheringTest {
@Mock private IDhcpServer mDhcpServer;
@Mock private INetd mNetd;
@Mock private UserManager mUserManager;
+ @Mock private NetworkRequest mNetworkRequest;
private final MockIpServerDependencies mIpServerDependencies =
spy(new MockIpServerDependencies());
@@ -311,6 +311,11 @@ public class TetheringTest {
}
@Override
+ public NetworkRequest getDefaultNetworkRequest() {
+ return mNetworkRequest;
+ }
+
+ @Override
public boolean isTetheringSupported() {
mIsTetheringSupportedCalls++;
return true;
@@ -353,10 +358,8 @@ public class TetheringTest {
}
}
- private static NetworkState buildMobileUpstreamState(boolean withIPv4, boolean withIPv6,
- boolean with464xlat) {
- final NetworkInfo info = new NetworkInfo(TYPE_MOBILE, 0, null, null);
- info.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
+ private static UpstreamNetworkState buildMobileUpstreamState(boolean withIPv4,
+ boolean withIPv6, boolean with464xlat) {
final LinkProperties prop = new LinkProperties();
prop.setInterfaceName(TEST_MOBILE_IFNAME);
@@ -386,22 +389,22 @@ public class TetheringTest {
final NetworkCapabilities capabilities = new NetworkCapabilities()
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
- return new NetworkState(info, prop, capabilities, new Network(100), null, "netid");
+ return new UpstreamNetworkState(prop, capabilities, new Network(100));
}
- private static NetworkState buildMobileIPv4UpstreamState() {
+ private static UpstreamNetworkState buildMobileIPv4UpstreamState() {
return buildMobileUpstreamState(true, false, false);
}
- private static NetworkState buildMobileIPv6UpstreamState() {
+ private static UpstreamNetworkState buildMobileIPv6UpstreamState() {
return buildMobileUpstreamState(false, true, false);
}
- private static NetworkState buildMobileDualStackUpstreamState() {
+ private static UpstreamNetworkState buildMobileDualStackUpstreamState() {
return buildMobileUpstreamState(true, true, false);
}
- private static NetworkState buildMobile464xlatUpstreamState() {
+ private static UpstreamNetworkState buildMobile464xlatUpstreamState() {
return buildMobileUpstreamState(false, true, true);
}
@@ -555,7 +558,7 @@ public class TetheringTest {
verifyNoMoreInteractions(mWifiManager);
}
- private void prepareUsbTethering(NetworkState upstreamState) {
+ private void prepareUsbTethering(UpstreamNetworkState upstreamState) {
when(mUpstreamNetworkMonitor.getCurrentPreferredUpstream()).thenReturn(upstreamState);
when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any()))
.thenReturn(upstreamState);
@@ -570,7 +573,7 @@ public class TetheringTest {
@Test
public void testUsbConfiguredBroadcastStartsTethering() throws Exception {
- NetworkState upstreamState = buildMobileIPv4UpstreamState();
+ UpstreamNetworkState upstreamState = buildMobileIPv4UpstreamState();
prepareUsbTethering(upstreamState);
// This should produce no activity of any kind.
@@ -650,14 +653,14 @@ public class TetheringTest {
/**
* Send CMD_IPV6_TETHER_UPDATE to IpServers as would be done by IPv6TetheringCoordinator.
*/
- private void sendIPv6TetherUpdates(NetworkState upstreamState) {
+ private void sendIPv6TetherUpdates(UpstreamNetworkState upstreamState) {
// IPv6TetheringCoordinator must have been notified of downstream
verify(mIPv6TetheringCoordinator, times(1)).addActiveDownstream(
argThat(sm -> sm.linkProperties().getInterfaceName().equals(TEST_USB_IFNAME)),
eq(IpServer.STATE_TETHERED));
for (IpServer ipSrv : mTetheringDependencies.mIpv6CoordinatorNotifyList) {
- NetworkState ipv6OnlyState = buildMobileUpstreamState(false, true, false);
+ UpstreamNetworkState ipv6OnlyState = buildMobileUpstreamState(false, true, false);
ipSrv.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, 0, 0,
upstreamState.linkProperties.isIpv6Provisioned()
? ipv6OnlyState.linkProperties
@@ -666,7 +669,7 @@ public class TetheringTest {
mLooper.dispatchAll();
}
- private void runUsbTethering(NetworkState upstreamState) {
+ private void runUsbTethering(UpstreamNetworkState upstreamState) {
prepareUsbTethering(upstreamState);
sendUsbBroadcast(true, true, true);
mLooper.dispatchAll();
@@ -674,7 +677,7 @@ public class TetheringTest {
@Test
public void workingMobileUsbTethering_IPv4() throws Exception {
- NetworkState upstreamState = buildMobileIPv4UpstreamState();
+ UpstreamNetworkState upstreamState = buildMobileIPv4UpstreamState();
runUsbTethering(upstreamState);
verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
@@ -689,7 +692,7 @@ public class TetheringTest {
public void workingMobileUsbTethering_IPv4LegacyDhcp() {
Settings.Global.putInt(mContentResolver, TETHER_ENABLE_LEGACY_DHCP_SERVER, 1);
sendConfigurationChanged();
- final NetworkState upstreamState = buildMobileIPv4UpstreamState();
+ final UpstreamNetworkState upstreamState = buildMobileIPv4UpstreamState();
runUsbTethering(upstreamState);
sendIPv6TetherUpdates(upstreamState);
@@ -698,7 +701,7 @@ public class TetheringTest {
@Test
public void workingMobileUsbTethering_IPv6() throws Exception {
- NetworkState upstreamState = buildMobileIPv6UpstreamState();
+ UpstreamNetworkState upstreamState = buildMobileIPv6UpstreamState();
runUsbTethering(upstreamState);
verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
@@ -711,7 +714,7 @@ public class TetheringTest {
@Test
public void workingMobileUsbTethering_DualStack() throws Exception {
- NetworkState upstreamState = buildMobileDualStackUpstreamState();
+ UpstreamNetworkState upstreamState = buildMobileDualStackUpstreamState();
runUsbTethering(upstreamState);
verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
@@ -726,7 +729,7 @@ public class TetheringTest {
@Test
public void workingMobileUsbTethering_MultipleUpstreams() throws Exception {
- NetworkState upstreamState = buildMobile464xlatUpstreamState();
+ UpstreamNetworkState upstreamState = buildMobile464xlatUpstreamState();
runUsbTethering(upstreamState);
verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME);
@@ -744,7 +747,7 @@ public class TetheringTest {
@Test
public void workingMobileUsbTethering_v6Then464xlat() throws Exception {
// Setup IPv6
- NetworkState upstreamState = buildMobileIPv6UpstreamState();
+ UpstreamNetworkState upstreamState = buildMobileIPv6UpstreamState();
runUsbTethering(upstreamState);
verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
@@ -782,7 +785,7 @@ public class TetheringTest {
sendConfigurationChanged();
// Setup IPv6
- final NetworkState upstreamState = buildMobileIPv6UpstreamState();
+ final UpstreamNetworkState upstreamState = buildMobileIPv6UpstreamState();
runUsbTethering(upstreamState);
// UpstreamNetworkMonitor should choose upstream automatically
@@ -1039,7 +1042,7 @@ public class TetheringTest {
expectedInteractionsWithShowNotification);
}
- private class TestTetherInternalCallback extends ITetherInternalCallback.Stub {
+ private class TestTetheringEventCallback extends ITetheringEventCallback.Stub {
private final ArrayList<Network> mActualUpstreams = new ArrayList<>();
private final ArrayList<TetheringConfigurationParcel> mTetheringConfigs =
new ArrayList<>();
@@ -1100,13 +1103,16 @@ public class TetheringTest {
}
@Override
- public void onCallbackCreated(Network network, TetheringConfigurationParcel config,
+ public void onCallbackStarted(Network network, TetheringConfigurationParcel config,
TetherStatesParcel states) {
mActualUpstreams.add(network);
mTetheringConfigs.add(config);
mTetherStates.add(states);
}
+ @Override
+ public void onCallbackStopped(int errorCode) { }
+
public void assertNoUpstreamChangeCallback() {
assertTrue(mActualUpstreams.isEmpty());
}
@@ -1115,10 +1121,20 @@ public class TetheringTest {
assertTrue(mTetheringConfigs.isEmpty());
}
+ public void assertNoStateChangeCallback() {
+ assertTrue(mTetherStates.isEmpty());
+ }
+
public void assertStateChangeCallback() {
assertFalse(mTetherStates.isEmpty());
}
+ public void assertNoCallback() {
+ assertNoUpstreamChangeCallback();
+ assertNoConfigChangeCallback();
+ assertNoStateChangeCallback();
+ }
+
private void assertTetherConfigParcelEqual(@NonNull TetheringConfigurationParcel actual,
@NonNull TetheringConfigurationParcel expect) {
assertEquals(actual.subId, expect.subId);
@@ -1139,19 +1155,20 @@ public class TetheringTest {
}
@Test
- public void testRegisterTetherInternalCallback() throws Exception {
- TestTetherInternalCallback callback = new TestTetherInternalCallback();
+ public void testRegisterTetheringEventCallback() throws Exception {
+ TestTetheringEventCallback callback = new TestTetheringEventCallback();
+ TestTetheringEventCallback callback2 = new TestTetheringEventCallback();
// 1. Register one callback before running any tethering.
- mTethering.registerTetherInternalCallback(callback);
+ mTethering.registerTetheringEventCallback(callback);
mLooper.dispatchAll();
callback.expectUpstreamChanged(new Network[] {null});
callback.expectConfigurationChanged(
mTethering.getTetheringConfiguration().toStableParcelable());
TetherStatesParcel tetherState = callback.pollTetherStatesChanged();
assertEquals(tetherState, null);
- // 2. Enable wifi tethering
- NetworkState upstreamState = buildMobileDualStackUpstreamState();
+ // 2. Enable wifi tethering.
+ UpstreamNetworkState upstreamState = buildMobileDualStackUpstreamState();
when(mUpstreamNetworkMonitor.getCurrentPreferredUpstream()).thenReturn(upstreamState);
when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any()))
.thenReturn(upstreamState);
@@ -1168,14 +1185,26 @@ public class TetheringTest {
assertArrayEquals(tetherState.tetheredList, new String[] {TEST_WLAN_IFNAME});
callback.expectUpstreamChanged(upstreamState.network);
- // 3. Disable wifi tethering.
+ // 3. Register second callback.
+ mTethering.registerTetheringEventCallback(callback2);
+ mLooper.dispatchAll();
+ callback2.expectUpstreamChanged(upstreamState.network);
+ callback2.expectConfigurationChanged(
+ mTethering.getTetheringConfiguration().toStableParcelable());
+ tetherState = callback2.pollTetherStatesChanged();
+ assertEquals(tetherState.tetheredList, new String[] {TEST_WLAN_IFNAME});
+
+ // 4. Unregister first callback and disable wifi tethering
+ mTethering.unregisterTetheringEventCallback(callback);
+ mLooper.dispatchAll();
mTethering.stopTethering(TETHERING_WIFI);
sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLED);
mLooper.dispatchAll();
- tetherState = callback.pollTetherStatesChanged();
+ tetherState = callback2.pollTetherStatesChanged();
assertArrayEquals(tetherState.availableList, new String[] {TEST_WLAN_IFNAME});
mLooper.dispatchAll();
- callback.expectUpstreamChanged(new Network[] {null});
+ callback2.expectUpstreamChanged(new Network[] {null});
+ callback.assertNoCallback();
}
@Test
diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
index c028d6d9cadc..c90abbbedb5f 100644
--- a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
@@ -50,7 +50,6 @@ import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
-import android.net.NetworkState;
import android.net.util.SharedLog;
import android.os.Handler;
import android.os.Message;
@@ -539,7 +538,7 @@ public class UpstreamNetworkMonitorTest {
mUNM.selectPreferredUpstreamType(preferredTypes));
verify(mEntitleMgr, times(1)).maybeRunProvisioning();
}
- private void assertSatisfiesLegacyType(int legacyType, NetworkState ns) {
+ private void assertSatisfiesLegacyType(int legacyType, UpstreamNetworkState ns) {
if (legacyType == TYPE_NONE) {
assertTrue(ns == null);
return;
diff --git a/packages/VpnDialogs/res/values-am/strings.xml b/packages/VpnDialogs/res/values-am/strings.xml
index 103f101b8262..ad9773b248a4 100644
--- a/packages/VpnDialogs/res/values-am/strings.xml
+++ b/packages/VpnDialogs/res/values-am/strings.xml
@@ -30,7 +30,7 @@
<string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string>
<string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"የቪፒኤን ቅንብሮችን ይቀይሩ"</string>
<string name="configure" msgid="4905518375574791375">"አዋቅር"</string>
- <string name="disconnect" msgid="971412338304200056">"አለያይ"</string>
+ <string name="disconnect" msgid="971412338304200056">"ግንኙነት አቋርጥ"</string>
<string name="open_app" msgid="3717639178595958667">"መተግበሪያን ክፈት"</string>
<string name="dismiss" msgid="6192859333764711227">"አሰናብት"</string>
</resources>
diff --git a/packages/WAPPushManager/Android.bp b/packages/WAPPushManager/Android.bp
index c3913698022d..083dac944936 100644
--- a/packages/WAPPushManager/Android.bp
+++ b/packages/WAPPushManager/Android.bp
@@ -10,5 +10,5 @@ android_app {
proguard_flags_files: ["proguard.flags"],
},
- product_specific: true,
+ system_ext_specific: true,
}
diff --git a/packages/WAPPushManager/CleanSpec.mk b/packages/WAPPushManager/CleanSpec.mk
index 2dcbb1034622..f4e316c56bbf 100644
--- a/packages/WAPPushManager/CleanSpec.mk
+++ b/packages/WAPPushManager/CleanSpec.mk
@@ -49,3 +49,5 @@
# ************************************************
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/WAPPushManager)
+$(call add-clean-step, rm -rf $(TARGET_OUT_PRODUCT)/app/WAPPushManager)
+
diff --git a/packages/WallpaperCropper/Android.bp b/packages/WallpaperCropper/Android.bp
index 40c423520081..ac38b271395c 100644
--- a/packages/WallpaperCropper/Android.bp
+++ b/packages/WallpaperCropper/Android.bp
@@ -3,7 +3,7 @@ android_app {
srcs: ["src/**/*.java"],
platform_apis: true,
certificate: "platform",
- product_specific: true,
+ system_ext_specific: true,
privileged: true,
optimize: {
proguard_flags_files: ["proguard.flags"],
diff --git a/packages/WallpaperCropper/CleanSpec.mk b/packages/WallpaperCropper/CleanSpec.mk
index e6d8d5a774f1..f08c3430756a 100644
--- a/packages/WallpaperCropper/CleanSpec.mk
+++ b/packages/WallpaperCropper/CleanSpec.mk
@@ -44,6 +44,7 @@
#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/priv-app/WallpaperCropper)
+$(call add-clean-step, rm -rf $(TARGET_OUT_PRODUCT)/priv-app/WallpaperCropper)
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
diff --git a/packages/WindowManager/OWNERS b/packages/WindowManager/OWNERS
new file mode 100644
index 000000000000..063d4594f2fa
--- /dev/null
+++ b/packages/WindowManager/OWNERS
@@ -0,0 +1,3 @@
+set noparent
+
+include ../../services/core/java/com/android/server/wm/OWNERS \ No newline at end of file
diff --git a/packages/WindowManager/Shell/Android.bp b/packages/WindowManager/Shell/Android.bp
new file mode 100644
index 000000000000..b8934dc8c583
--- /dev/null
+++ b/packages/WindowManager/Shell/Android.bp
@@ -0,0 +1,29 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_library {
+ name: "WindowManager-Shell",
+ srcs: [
+ "src/**/*.java",
+ "src/**/I*.aidl",
+ ],
+ resource_dirs: [
+ "res",
+ ],
+ manifest: "AndroidManifest.xml",
+
+ platform_apis: true,
+ sdk_version: "current",
+ min_sdk_version: "system_current",
+}
diff --git a/packages/WindowManager/Shell/AndroidManifest.xml b/packages/WindowManager/Shell/AndroidManifest.xml
new file mode 100644
index 000000000000..ea8a5c305029
--- /dev/null
+++ b/packages/WindowManager/Shell/AndroidManifest.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.wm.shell">
+</manifest>
diff --git a/packages/WindowManager/Shell/OWNERS b/packages/WindowManager/Shell/OWNERS
new file mode 100644
index 000000000000..4390004f5f93
--- /dev/null
+++ b/packages/WindowManager/Shell/OWNERS
@@ -0,0 +1,4 @@
+# sysui owners
+hwwang@google.com
+mrenouf@google.com
+winsonc@google.com \ No newline at end of file
diff --git a/packages/WindowManager/Shell/res/values/config.xml b/packages/WindowManager/Shell/res/values/config.xml
new file mode 100644
index 000000000000..c894eb0133b5
--- /dev/null
+++ b/packages/WindowManager/Shell/res/values/config.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2019, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources>
+</resources> \ No newline at end of file
diff --git a/packages/WindowManager/Shell/src/com/android/wm/shell/WindowManagerShell.java b/packages/WindowManager/Shell/src/com/android/wm/shell/WindowManagerShell.java
new file mode 100644
index 000000000000..273bd27a221b
--- /dev/null
+++ b/packages/WindowManager/Shell/src/com/android/wm/shell/WindowManagerShell.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell;
+
+/**
+ * Interface for the shell.
+ */
+public class WindowManagerShell {
+}
diff --git a/packages/WindowManager/Shell/tests/Android.bp b/packages/WindowManager/Shell/tests/Android.bp
new file mode 100644
index 000000000000..78fa45ebdf94
--- /dev/null
+++ b/packages/WindowManager/Shell/tests/Android.bp
@@ -0,0 +1,45 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_test {
+ name: "WindowManagerShellTests",
+
+ srcs: ["**/*.java"],
+
+ static_libs: [
+ "WindowManager-Shell",
+ "junit",
+ "androidx.test.runner",
+ "androidx.test.rules",
+ "androidx.test.ext.junit",
+ "mockito-target-extended-minus-junit4",
+ "truth-prebuilt",
+ ],
+ libs: [
+ "android.test.mock",
+ "android.test.base",
+ "android.test.runner",
+ ],
+ jni_libs: [
+ "libdexmakerjvmtiagent",
+ "libstaticjvmtiagent",
+ ],
+
+ sdk_version: "current",
+ platform_apis: true,
+
+ optimize: {
+ enabled: false,
+ },
+}
diff --git a/packages/WindowManager/Shell/tests/AndroidManifest.xml b/packages/WindowManager/Shell/tests/AndroidManifest.xml
new file mode 100644
index 000000000000..a8f795ec8a8d
--- /dev/null
+++ b/packages/WindowManager/Shell/tests/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ package="com.android.wm.shell.tests">
+
+ <application android:debuggable="true" android:largeHeap="true">
+ <uses-library android:name="android.test.mock" />
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:label="Tests for WindowManager-Shell"
+ android:targetPackage="com.android.wm.shell.tests">
+ </instrumentation>
+</manifest>
diff --git a/packages/WindowManager/Shell/tests/AndroidTest.xml b/packages/WindowManager/Shell/tests/AndroidTest.xml
new file mode 100644
index 000000000000..4dce4db360e4
--- /dev/null
+++ b/packages/WindowManager/Shell/tests/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Runs Tests for WindowManagerShellLib">
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="install-arg" value="-t" />
+ <option name="test-file-name" value="WindowManagerShellTests.apk" />
+ </target_preparer>
+
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="framework-base-presubmit" />
+ <option name="test-tag" value="WindowManagerShellTests" />
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="com.android.wm.shell.tests" />
+ <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+ <option name="hidden-api-checks" value="false"/>
+ </test>
+</configuration>
diff --git a/packages/WindowManager/Shell/tests/res/values/config.xml b/packages/WindowManager/Shell/tests/res/values/config.xml
new file mode 100644
index 000000000000..c894eb0133b5
--- /dev/null
+++ b/packages/WindowManager/Shell/tests/res/values/config.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2019, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources>
+</resources> \ No newline at end of file
diff --git a/packages/WindowManager/Shell/tests/src/com/android/wm/shell/tests/WindowManagerShellTest.java b/packages/WindowManager/Shell/tests/src/com/android/wm/shell/tests/WindowManagerShellTest.java
new file mode 100644
index 000000000000..376875b143a1
--- /dev/null
+++ b/packages/WindowManager/Shell/tests/src/com/android/wm/shell/tests/WindowManagerShellTest.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.tests;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.wm.shell.WindowManagerShell;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests for the shell.
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class WindowManagerShellTest {
+
+ WindowManagerShell mShell;
+
+ @Test
+ public void testNothing() {
+ // Do nothing
+ }
+}
diff --git a/packages/overlays/Android.mk b/packages/overlays/Android.mk
index 3eb90491f902..8a3ac9404408 100644
--- a/packages/overlays/Android.mk
+++ b/packages/overlays/Android.mk
@@ -42,7 +42,7 @@ LOCAL_REQUIRED_MODULES := \
IconPackRoundedLauncherOverlay \
IconPackRoundedSettingsOverlay \
IconPackRoundedSystemUIOverlay \
- IconPackRoundedThemePickerUIOverlay \
+ IconPackRoundedThemePickerOverlay \
IconShapeRoundedRectOverlay \
IconShapeSquircleOverlay \
IconShapeTeardropOverlay \
@@ -51,7 +51,8 @@ LOCAL_REQUIRED_MODULES := \
NavigationBarModeGesturalOverlay \
NavigationBarModeGesturalOverlayNarrowBack \
NavigationBarModeGesturalOverlayWideBack \
- NavigationBarModeGesturalOverlayExtraWideBack
+ NavigationBarModeGesturalOverlayExtraWideBack \
+ preinstalled-packages-platform-overlays.xml
include $(BUILD_PHONY_PACKAGE)
include $(CLEAR_VARS)
diff --git a/services/Android.bp b/services/Android.bp
index 8376d2bcc0f5..ede4c3e7a6be 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -73,6 +73,7 @@ java_library {
libs: [
"android.hidl.manager-V1.0-java",
+ "framework-tethering"
],
plugins: [
@@ -111,16 +112,19 @@ droidstubs {
srcs: [":services-sources"],
installable: false,
// TODO: remove the --hide options below
- args: " --show-single-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.INTERNAL,process=android.annotation.SystemApi.Process.SYSTEM_SERVER\\)" +
+ args: " --show-single-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.MODULE_LIBRARIES,process=android.annotation.SystemApi.Process.SYSTEM_SERVER\\)" +
" --hide-annotation android.annotation.Hide" +
" --hide-package com.google.android.startop.iorap" +
" --hide ReferencesHidden" +
" --hide DeprecationMismatch" +
" --hide HiddenTypedefConstant",
- libs: [
- "framework-all",
- ],
visibility: ["//visibility:private"],
+ check_api: {
+ current: {
+ api_file: "api/current.txt",
+ removed_api_file: "api/removed.txt",
+ },
+ },
}
java_library {
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/GestureManifold.java b/services/accessibility/java/com/android/server/accessibility/gestures/GestureManifold.java
index 9b7adc883dee..50d21ba59996 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/GestureManifold.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/GestureManifold.java
@@ -77,6 +77,8 @@ class GestureManifold implements GestureMatcher.StateChangeListener {
// Start with double tap.
mGestures.add(new MultiTap(context, 2, GESTURE_DOUBLE_TAP, this));
mGestures.add(new MultiTapAndHold(context, 2, GESTURE_DOUBLE_TAP_AND_HOLD, this));
+ // Second-finger double tap.
+ mGestures.add(new SecondFingerMultiTap(context, 2, GESTURE_DOUBLE_TAP, this));
// One-direction swipes.
mGestures.add(new Swipe(context, RIGHT, GESTURE_SWIPE_RIGHT, this));
mGestures.add(new Swipe(context, LEFT, GESTURE_SWIPE_LEFT, this));
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/SecondFingerMultiTap.java b/services/accessibility/java/com/android/server/accessibility/gestures/SecondFingerMultiTap.java
new file mode 100644
index 000000000000..eb38b53dc52a
--- /dev/null
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/SecondFingerMultiTap.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.accessibility.gestures;
+
+import static android.view.MotionEvent.INVALID_POINTER_ID;
+
+import android.content.Context;
+import android.os.Handler;
+import android.view.MotionEvent;
+import android.view.ViewConfiguration;
+
+/**
+ * This class matches second-finger multi-tap gestures. A second-finger multi-tap gesture is where
+ * one finger is held down and a second finger executes the taps. The number of taps for each
+ * instance is specified in the constructor.
+ */
+class SecondFingerMultiTap extends GestureMatcher {
+ final int mTargetTaps;
+ int mDoubleTapSlop;
+ int mTouchSlop;
+ int mTapTimeout;
+ int mDoubleTapTimeout;
+ int mCurrentTaps;
+ int mSecondFingerPointerId;
+ float mBaseX;
+ float mBaseY;
+
+ SecondFingerMultiTap(
+ Context context, int taps, int gesture, GestureMatcher.StateChangeListener listener) {
+ super(gesture, new Handler(context.getMainLooper()), listener);
+ mTargetTaps = taps;
+ mDoubleTapSlop = ViewConfiguration.get(context).getScaledDoubleTapSlop();
+ mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
+ mTapTimeout = ViewConfiguration.getTapTimeout();
+ mDoubleTapTimeout = ViewConfiguration.getDoubleTapTimeout();
+ clear();
+ }
+
+ @Override
+ protected void clear() {
+ mCurrentTaps = 0;
+ mBaseX = Float.NaN;
+ mBaseY = Float.NaN;
+ mSecondFingerPointerId = INVALID_POINTER_ID;
+ super.clear();
+ }
+
+ @Override
+ protected void onPointerDown(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
+ if (event.getPointerCount() > 2) {
+ cancelGesture(event, rawEvent, policyFlags);
+ return;
+ }
+ // Second finger has gone down.
+ int index = getActionIndex(event);
+ mSecondFingerPointerId = event.getPointerId(index);
+ cancelAfterTapTimeout(event, rawEvent, policyFlags);
+ if (Float.isNaN(mBaseX) && Float.isNaN(mBaseY)) {
+ mBaseX = event.getX();
+ mBaseY = event.getY();
+ }
+ if (!isSecondFingerInsideSlop(rawEvent, mDoubleTapSlop)) {
+ cancelGesture(event, rawEvent, policyFlags);
+ }
+ mBaseX = event.getX();
+ mBaseY = event.getY();
+ }
+
+ @Override
+ protected void onPointerUp(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
+ if (event.getPointerCount() > 2) {
+ cancelGesture(event, rawEvent, policyFlags);
+ return;
+ }
+ cancelAfterDoubleTapTimeout(event, rawEvent, policyFlags);
+ if (!isSecondFingerInsideSlop(rawEvent, mTouchSlop)) {
+ cancelGesture(event, rawEvent, policyFlags);
+ }
+ if (getState() == STATE_GESTURE_STARTED || getState() == STATE_CLEAR) {
+ mCurrentTaps++;
+ if (mCurrentTaps == mTargetTaps) {
+ // Done.
+ completeGesture(event, rawEvent, policyFlags);
+ return;
+ }
+ // Needs more taps.
+ cancelAfterDoubleTapTimeout(event, rawEvent, policyFlags);
+ } else {
+ // Nonsensical event stream.
+ cancelGesture(event, rawEvent, policyFlags);
+ }
+ }
+
+ @Override
+ protected void onMove(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
+ switch (event.getPointerCount()) {
+ case 1:
+ // We don't need to track anything about one-finger movements.
+ break;
+ case 2:
+ if (!isSecondFingerInsideSlop(rawEvent, mTouchSlop)) {
+ cancelGesture(event, rawEvent, policyFlags);
+ }
+ break;
+ default:
+ // More than two fingers means we stop tracking.
+ cancelGesture(event, rawEvent, policyFlags);
+ break;
+ }
+ }
+
+ @Override
+ public String getGestureName() {
+ switch (mTargetTaps) {
+ case 2:
+ return "Second Finger Double Tap";
+ case 3:
+ return "Second Finger Triple Tap";
+ default:
+ return "Second Finger " + Integer.toString(mTargetTaps) + " Taps";
+ }
+ }
+
+ private boolean isSecondFingerInsideSlop(MotionEvent rawEvent, int slop) {
+ int pointerIndex = rawEvent.findPointerIndex(mSecondFingerPointerId);
+ if (pointerIndex == -1) {
+ return false;
+ }
+ final float deltaX = mBaseX - rawEvent.getX(pointerIndex);
+ final float deltaY = mBaseY - rawEvent.getY(pointerIndex);
+ if (deltaX == 0 && deltaY == 0) {
+ return true;
+ }
+ final double moveDelta = Math.hypot(deltaX, deltaY);
+ return moveDelta <= slop;
+ }
+
+ private int getActionIndex(MotionEvent event) {
+ return event.getAction()
+ & MotionEvent.ACTION_POINTER_INDEX_MASK << MotionEvent.ACTION_POINTER_INDEX_SHIFT;
+ }
+
+ @Override
+ public String toString() {
+ return super.toString()
+ + ", Taps:"
+ + mCurrentTaps
+ + ", mBaseX: "
+ + Float.toString(mBaseX)
+ + ", mBaseY: "
+ + Float.toString(mBaseY);
+ }
+}
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/Swipe.java b/services/accessibility/java/com/android/server/accessibility/gestures/Swipe.java
index b246c67944c7..a285c10cc6ff 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/Swipe.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/Swipe.java
@@ -26,6 +26,7 @@ import android.util.DisplayMetrics;
import android.util.Slog;
import android.util.TypedValue;
import android.view.MotionEvent;
+import android.view.ViewConfiguration;
import java.util.ArrayList;
@@ -85,6 +86,10 @@ class Swipe extends GestureMatcher {
private static final float MIN_CM_BETWEEN_SAMPLES = 0.25f;
private final float mMinPixelsBetweenSamplesX;
private final float mMinPixelsBetweenSamplesY;
+ // The minmimum distance the finger must travel before we evaluate the initial direction of the
+ // swipe.
+ // Anything less is still considered a touch.
+ private int mTouchSlop;
// Constants for separating gesture segments
private static final float ANGLE_THRESHOLD = 0.0f;
@@ -122,6 +127,7 @@ class Swipe extends GestureMatcher {
final float pixelsPerCmY = displayMetrics.ydpi / 2.54f;
mMinPixelsBetweenSamplesX = MIN_CM_BETWEEN_SAMPLES * pixelsPerCmX;
mMinPixelsBetweenSamplesY = MIN_CM_BETWEEN_SAMPLES * pixelsPerCmY;
+ mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
clear();
}
@@ -165,7 +171,10 @@ class Swipe extends GestureMatcher {
+ Float.toString(mGestureDetectionThreshold));
}
if (getState() == STATE_CLEAR) {
- if (mStrokeBuffer.size() == 0) {
+ if (moveDelta < mTouchSlop) {
+ // This still counts as a touch not a swipe.
+ return;
+ } else if (mStrokeBuffer.size() == 0) {
// First, make sure the pointer is going in the right direction.
cancelAfterDelay(event, rawEvent, policyFlags);
int direction = toDirection(x - mBaseX, y - mBaseY);
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
index 5f4163880366..f6eb31b93f06 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
@@ -286,11 +286,6 @@ public class TouchExplorer extends BaseEventStreamTransformation
@Override
public void onDoubleTapAndHold() {
- // Ignore the event if we aren't touch interacting.
- if (!mState.isTouchInteracting()) {
- return;
- }
-
// Pointers should not be zero when running this command.
if (mState.getLastReceivedEvent().getPointerCount() == 0) {
return;
@@ -304,10 +299,6 @@ public class TouchExplorer extends BaseEventStreamTransformation
@Override
public boolean onDoubleTap() {
- if (!mState.isTouchInteracting()) {
- return false;
- }
-
mAms.onTouchInteractionEnd();
// Remove pending event deliveries.
mSendHoverEnterAndMoveDelayed.cancel();
@@ -454,7 +445,7 @@ public class TouchExplorer extends BaseEventStreamTransformation
handleActionDown(event, rawEvent, policyFlags);
break;
case MotionEvent.ACTION_POINTER_DOWN:
- handleActionPointerDown();
+ handleActionPointerDown(event, rawEvent, policyFlags);
break;
case MotionEvent.ACTION_MOVE:
handleActionMoveStateTouchInteracting(event, rawEvent, policyFlags);
@@ -479,7 +470,7 @@ public class TouchExplorer extends BaseEventStreamTransformation
// We should have already received ACTION_DOWN. Ignore.
break;
case MotionEvent.ACTION_POINTER_DOWN:
- handleActionPointerDown();
+ handleActionPointerDown(event, rawEvent, policyFlags);
break;
case MotionEvent.ACTION_MOVE:
handleActionMoveStateTouchExploring(event, rawEvent, policyFlags);
@@ -496,12 +487,19 @@ public class TouchExplorer extends BaseEventStreamTransformation
* Handles ACTION_POINTER_DOWN when in the touch exploring state. This event represents an
* additional finger touching the screen.
*/
- private void handleActionPointerDown() {
+ private void handleActionPointerDown(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
// Another finger down means that if we have not started to deliver
// hover events, we will not have to. The code for ACTION_MOVE will
// decide what we will actually do next.
- mSendHoverEnterAndMoveDelayed.cancel();
- mSendHoverExitDelayed.cancel();
+
+ if (mSendHoverEnterAndMoveDelayed.isPending()) {
+ mSendHoverEnterAndMoveDelayed.cancel();
+ mSendHoverExitDelayed.cancel();
+ } else {
+ // We have already delivered at least one hover event, so send hover exit to keep the
+ // stream consistent.
+ sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags);
+ }
}
/**
* Handles ACTION_MOVE while in the touch interacting state. This is where transitions to
diff --git a/services/api/current.txt b/services/api/current.txt
new file mode 100644
index 000000000000..d802177e249b
--- /dev/null
+++ b/services/api/current.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/services/api/removed.txt b/services/api/removed.txt
new file mode 100644
index 000000000000..d802177e249b
--- /dev/null
+++ b/services/api/removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 81ce359cc078..26245b15f92b 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -635,7 +635,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
mPackageManagerInternal.getSuspendedDialogInfo(providerPackage,
suspendingPackage, providerUserId);
onClickIntent = SuspendedAppActivity.createSuspendedAppInterceptIntent(
- providerPackage, suspendingPackage, dialogInfo, providerUserId);
+ providerPackage, suspendingPackage, dialogInfo, null, providerUserId);
}
} else if (provider.maskedByQuietProfile) {
showBadge = true;
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index c689ed1c64c7..03d9626cab91 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -288,7 +288,14 @@ public final class AutofillManagerService
boolean isTemporary) {
mAugmentedAutofillState.setServiceInfo(userId, serviceName, isTemporary);
synchronized (mLock) {
- getServiceForUserLocked(userId).updateRemoteAugmentedAutofillService();
+ final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
+ if (service == null) {
+ // If we cannot get the service from the services cache, it will call
+ // updateRemoteAugmentedAutofillService() finally. Skip call this update again.
+ getServiceForUserLocked(userId);
+ } else {
+ service.updateRemoteAugmentedAutofillService();
+ }
}
}
diff --git a/services/autofill/java/com/android/server/autofill/FieldClassificationStrategy.java b/services/autofill/java/com/android/server/autofill/FieldClassificationStrategy.java
index 9db6254a8baa..36a450920373 100644
--- a/services/autofill/java/com/android/server/autofill/FieldClassificationStrategy.java
+++ b/services/autofill/java/com/android/server/autofill/FieldClassificationStrategy.java
@@ -121,7 +121,12 @@ final class FieldClassificationStrategy {
synchronized (mLock) {
if (mServiceConnection != null) {
if (sDebug) Slog.d(TAG, "reset(): unbinding service.");
- mContext.unbindService(mServiceConnection);
+ try {
+ mContext.unbindService(mServiceConnection);
+ } catch (IllegalArgumentException e) {
+ // no-op, just log the error message.
+ Slog.w(TAG, "reset(): " + e.getMessage());
+ }
mServiceConnection = null;
} else {
if (sDebug) Slog.d(TAG, "reset(): service is not bound. Do nothing.");
diff --git a/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
index 3d7738e69e43..c5011b343b88 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
@@ -36,6 +36,7 @@ import android.os.IBinder;
import android.os.ICancellationSignal;
import android.os.RemoteException;
import android.os.SystemClock;
+import android.service.autofill.Dataset;
import android.service.autofill.augmented.AugmentedAutofillService;
import android.service.autofill.augmented.IAugmentedAutofillService;
import android.service.autofill.augmented.IFillCallback;
@@ -152,7 +153,8 @@ final class RemoteAugmentedAutofillService
service.onFillRequest(sessionId, realClient, taskId, activityComponent,
focusedId, focusedValue, requestTime, new IFillCallback.Stub() {
@Override
- public void onSuccess() {
+ public void onSuccess(@Nullable Dataset[] inlineSuggestionsData) {
+ // TODO(b/146453195): handle non-null inline suggestions data.
requestAutofill.complete(null);
}
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 67bcccd1d7de..5af43994775a 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -2563,7 +2563,9 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
return;
}
- if ((flags & FLAG_MANUAL_REQUEST) == 0 && mAugmentedAutofillableIds != null
+ if (!isSameViewEntered
+ && (flags & FLAG_MANUAL_REQUEST) == 0
+ && mAugmentedAutofillableIds != null
&& mAugmentedAutofillableIds.contains(id)) {
// View was already reported when server could not handle a response, but it
// triggered augmented autofill
@@ -2577,13 +2579,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
requestNewFillResponseOnViewEnteredIfNecessaryLocked(id, viewState, flags);
- // Remove the UI if the ViewState has changed.
- if (!Objects.equals(mCurrentViewId, viewState.id)) {
- mUi.hideFillUi(this);
- mCurrentViewId = viewState.id;
- hideAugmentedAutofillLocked(viewState);
- }
-
if (isSameViewEntered) {
return;
}
diff --git a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
index eadfd31c27bf..e57b7b3d6d32 100644
--- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
@@ -40,8 +40,8 @@ import android.text.TextUtils;
import android.util.Slog;
import android.view.KeyEvent;
import android.view.SurfaceControl;
+import android.view.SurfaceControlViewHost;
import android.view.WindowManager;
-import android.view.WindowlessViewRoot;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillManager;
import android.view.autofill.AutofillValue;
@@ -217,14 +217,12 @@ public final class AutoFillUI {
}
final AutofillValue datasetValue = dataset.getFieldValues().get(index);
- final SurfaceControl sc = new SurfaceControl.Builder()
- // TODO(b/137800469): sanitize name
- .setName("af suggestion")
- .build();
-
//TODO(b/137800469): Pass in inputToken from IME.
- final WindowlessViewRoot wvr = new WindowlessViewRoot(context, context.getDisplay(), sc,
- null);
+ final SurfaceControlViewHost wvr = new SurfaceControlViewHost(context, context.getDisplay(),
+ (IBinder) null);
+ // TODO(b/134365580): Use the package instead of the SurfaceControl itself
+ // for accessibility support.
+ final SurfaceControl sc = wvr.getSurfacePackage().getSurfaceControl();
TextView textView = new TextView(context);
textView.setText(datasetValue.getTextValue());
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
index 56b345bb1324..2799f122038c 100644
--- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@@ -2409,7 +2409,7 @@ public class UserBackupManagerService {
/** Run an initialize operation for the given transport. */
public void initializeTransports(String[] transportNames, IBackupObserver observer) {
- mContext.enforceCallingPermission(android.Manifest.permission.BACKUP,
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
"initializeTransport");
Slog.v(TAG, "initializeTransport(): " + Arrays.asList(transportNames));
@@ -2431,7 +2431,6 @@ public class UserBackupManagerService {
mContext.enforceCallingPermission(android.Manifest.permission.BACKUP,
"setAncestralSerialNumber");
Slog.v(TAG, "Setting ancestral work profile id to " + ancestralSerialNumber);
- // TODO (b/124359804)
try (RandomAccessFile af = getAncestralSerialNumberFile()) {
af.writeLong(ancestralSerialNumber);
} catch (IOException e) {
@@ -2444,7 +2443,6 @@ public class UserBackupManagerService {
* {@link #setAncestralSerialNumber(long)}. Will return {@code -1} if not set.
*/
public long getAncestralSerialNumber() {
- // TODO (b/124359804)
try (RandomAccessFile af = getAncestralSerialNumberFile()) {
return af.readLong();
} catch (IOException e) {
@@ -2570,7 +2568,6 @@ public class UserBackupManagerService {
mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "adbBackup");
final int callingUserHandle = UserHandle.getCallingUserId();
- // TODO: http://b/22388012
if (callingUserHandle != UserHandle.USER_SYSTEM) {
throw new IllegalStateException("Backup supported only for the device owner");
}
@@ -2708,7 +2705,6 @@ public class UserBackupManagerService {
mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "adbRestore");
final int callingUserHandle = UserHandle.getCallingUserId();
- // TODO: http://b/22388012
if (callingUserHandle != UserHandle.USER_SYSTEM) {
throw new IllegalStateException("Restore supported only for the device owner");
}
diff --git a/services/backup/java/com/android/server/backup/internal/RunInitializeReceiver.java b/services/backup/java/com/android/server/backup/internal/RunInitializeReceiver.java
index 96d61e5755c8..160124b6f1d3 100644
--- a/services/backup/java/com/android/server/backup/internal/RunInitializeReceiver.java
+++ b/services/backup/java/com/android/server/backup/internal/RunInitializeReceiver.java
@@ -53,21 +53,8 @@ public class RunInitializeReceiver extends BroadcastReceiver {
if (pendingInits.size() > 0) {
String[] transports = pendingInits.toArray(new String[pendingInits.size()]);
-
mUserBackupManagerService.clearPendingInits();
-
- UserBackupManagerService.BackupWakeLock wakelock =
- mUserBackupManagerService.getWakelock();
- wakelock.acquire();
- OnTaskFinishedListener listener = caller -> wakelock.release();
-
- Runnable task =
- new PerformInitializeTask(
- mUserBackupManagerService,
- transports,
- /* observer */ null,
- listener);
- mUserBackupManagerService.getBackupHandler().post(task);
+ mUserBackupManagerService.initializeTransports(transports, null);
}
}
}
diff --git a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
index ac006df7f475..94921186441a 100644
--- a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
+++ b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
@@ -57,7 +57,6 @@ import com.android.server.backup.BackupAgentTimeoutParameters;
import com.android.server.backup.BackupRestoreTask;
import com.android.server.backup.DataChangedJournal;
import com.android.server.backup.KeyValueBackupJob;
-import com.android.server.backup.TransportManager;
import com.android.server.backup.UserBackupManagerService;
import com.android.server.backup.fullbackup.PerformFullTransportBackupTask;
import com.android.server.backup.internal.OnTaskFinishedListener;
@@ -233,7 +232,6 @@ public class KeyValueBackupTask implements BackupRestoreTask, Runnable {
private final UserBackupManagerService mBackupManagerService;
private final PackageManager mPackageManager;
- private final TransportManager mTransportManager;
private final TransportClient mTransportClient;
private final BackupAgentTimeoutParameters mAgentTimeoutParameters;
private final KeyValueBackupReporter mReporter;
@@ -300,7 +298,6 @@ public class KeyValueBackupTask implements BackupRestoreTask, Runnable {
boolean userInitiated,
boolean nonIncremental) {
mBackupManagerService = backupManagerService;
- mTransportManager = backupManagerService.getTransportManager();
mPackageManager = backupManagerService.getPackageManager();
mTransportClient = transportClient;
mOriginalQueue = queue;
diff --git a/services/backup/java/com/android/server/backup/utils/TarBackupReader.java b/services/backup/java/com/android/server/backup/utils/TarBackupReader.java
index f3b80988fef3..d2d382dfc14d 100644
--- a/services/backup/java/com/android/server/backup/utils/TarBackupReader.java
+++ b/services/backup/java/com/android/server/backup/utils/TarBackupReader.java
@@ -775,17 +775,17 @@ public class TarBackupReader {
private static void hexLog(byte[] block) {
int offset = 0;
- int todo = block.length;
+ int remaining = block.length;
StringBuilder buf = new StringBuilder(64);
- while (todo > 0) {
+ while (remaining > 0) {
buf.append(String.format("%04x ", offset));
- int numThisLine = (todo > 16) ? 16 : todo;
+ int numThisLine = (remaining > 16) ? 16 : remaining;
for (int i = 0; i < numThisLine; i++) {
buf.append(String.format("%02x ", block[offset + i]));
}
Slog.i("hexdump", buf.toString());
buf.setLength(0);
- todo -= numThisLine;
+ remaining -= numThisLine;
offset += numThisLine;
}
}
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index 8f1e1568ead6..e976811a3094 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -18,6 +18,7 @@
package com.android.server.companion;
import static com.android.internal.util.CollectionUtils.size;
+import static com.android.internal.util.FunctionalUtils.uncheckExceptions;
import static com.android.internal.util.Preconditions.checkArgument;
import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.internal.util.Preconditions.checkState;
@@ -26,16 +27,15 @@ import static com.android.internal.util.function.pooled.PooledLambda.obtainRunna
import android.annotation.CheckResult;
import android.annotation.Nullable;
import android.app.PendingIntent;
+import android.companion.Association;
import android.companion.AssociationRequest;
import android.companion.CompanionDeviceManager;
import android.companion.ICompanionDeviceDiscoveryService;
-import android.companion.ICompanionDeviceDiscoveryServiceCallback;
import android.companion.ICompanionDeviceManager;
import android.companion.IFindDeviceCallback;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.content.ServiceConnection;
import android.content.pm.FeatureInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageItemInfo;
@@ -67,6 +67,9 @@ import android.util.Xml;
import com.android.internal.app.IAppOpsService;
import com.android.internal.content.PackageMonitor;
+import com.android.internal.infra.AndroidFuture;
+import com.android.internal.infra.PerUser;
+import com.android.internal.infra.ServiceConnector;
import com.android.internal.notification.NotificationAccessConfirmationActivityContract;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.CollectionUtils;
@@ -118,12 +121,13 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
private final CompanionDeviceManagerImpl mImpl;
private final ConcurrentMap<Integer, AtomicFile> mUidToStorage = new ConcurrentHashMap<>();
private IDeviceIdleController mIdleController;
- private ServiceConnection mServiceConnection;
+ private PerUser<ServiceConnector<ICompanionDeviceDiscoveryService>> mServiceConnectors;
private IAppOpsService mAppOpsManager;
private IFindDeviceCallback mFindDeviceCallback;
private AssociationRequest mRequest;
private String mCallingPackage;
+ private AndroidFuture<Association> mOngoingDeviceDiscovery;
private final Object mLock = new Object();
@@ -134,6 +138,19 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
mAppOpsManager = IAppOpsService.Stub.asInterface(
ServiceManager.getService(Context.APP_OPS_SERVICE));
+
+ Intent serviceIntent = new Intent().setComponent(SERVICE_TO_BIND_TO);
+ mServiceConnectors = new PerUser<ServiceConnector<ICompanionDeviceDiscoveryService>>() {
+ @Override
+ protected ServiceConnector<ICompanionDeviceDiscoveryService> create(int userId) {
+ return new ServiceConnector.Impl<>(
+ getContext(),
+ serviceIntent, 0/* bindingFlags */, userId,
+ ICompanionDeviceDiscoveryService.Stub::asInterface);
+ }
+ };
+
+
registerPackageMonitor();
}
@@ -187,7 +204,10 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
private void cleanup() {
synchronized (mLock) {
- mServiceConnection = unbind(mServiceConnection);
+ AndroidFuture<Association> ongoingDeviceDiscovery = mOngoingDeviceDiscovery;
+ if (ongoingDeviceDiscovery != null && !ongoingDeviceDiscovery.isDone()) {
+ ongoingDeviceDiscovery.cancel(true);
+ }
mFindDeviceCallback = unlinkToDeath(mFindDeviceCallback, this, 0);
mRequest = null;
mCallingPackage = null;
@@ -207,15 +227,6 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
return null;
}
- @Nullable
- @CheckResult
- private ServiceConnection unbind(@Nullable ServiceConnection conn) {
- if (conn != null) {
- getContext().unbindService(conn);
- }
- return null;
- }
-
class CompanionDeviceManagerImpl extends ICompanionDeviceManager.Stub {
@Override
@@ -243,13 +254,27 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
checkCallerIsSystemOr(callingPackage);
int userId = getCallingUserId();
checkUsesFeature(callingPackage, userId);
+
+ mFindDeviceCallback = callback;
+ mRequest = request;
+ mCallingPackage = callingPackage;
+ callback.asBinder().linkToDeath(CompanionDeviceManagerService.this /* recipient */, 0);
+
final long callingIdentity = Binder.clearCallingIdentity();
try {
- getContext().bindServiceAsUser(
- new Intent().setComponent(SERVICE_TO_BIND_TO),
- createServiceConnection(request, callback, callingPackage),
- Context.BIND_AUTO_CREATE,
- UserHandle.of(userId));
+ mOngoingDeviceDiscovery = mServiceConnectors.forUser(userId).postAsync(service -> {
+ AndroidFuture<Association> future = new AndroidFuture<>();
+ service.startDiscovery(request, callingPackage, callback, future);
+ return future;
+ }).whenComplete(uncheckExceptions((association, err) -> {
+ if (err == null) {
+ addAssociation(association);
+ } else {
+ Log.e(LOG_TAG, "Failed to discover device(s)", err);
+ callback.onFailure("No devices found: " + err.getMessage());
+ }
+ cleanup();
+ }));
} finally {
Binder.restoreCallingIdentity(callingIdentity);
}
@@ -386,82 +411,14 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
return Binder.getCallingUid() == Process.SYSTEM_UID;
}
- private ServiceConnection createServiceConnection(
- final AssociationRequest request,
- final IFindDeviceCallback findDeviceCallback,
- final String callingPackage) {
- mServiceConnection = new ServiceConnection() {
- @Override
- public void onServiceConnected(ComponentName name, IBinder service) {
- if (DEBUG) {
- Slog.i(LOG_TAG,
- "onServiceConnected(name = " + name + ", service = "
- + service + ")");
- }
-
- mFindDeviceCallback = findDeviceCallback;
- mRequest = request;
- mCallingPackage = callingPackage;
-
- try {
- mFindDeviceCallback.asBinder().linkToDeath(
- CompanionDeviceManagerService.this, 0);
- } catch (RemoteException e) {
- cleanup();
- return;
- }
-
- try {
- ICompanionDeviceDiscoveryService.Stub
- .asInterface(service)
- .startDiscovery(
- request,
- callingPackage,
- findDeviceCallback,
- getServiceCallback());
- } catch (RemoteException e) {
- Log.e(LOG_TAG, "Error while initiating device discovery", e);
- }
- }
-
- @Override
- public void onServiceDisconnected(ComponentName name) {
- if (DEBUG) Slog.i(LOG_TAG, "onServiceDisconnected(name = " + name + ")");
- }
- };
- return mServiceConnection;
- }
-
- private ICompanionDeviceDiscoveryServiceCallback.Stub getServiceCallback() {
- return new ICompanionDeviceDiscoveryServiceCallback.Stub() {
-
- @Override
- public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
- throws RemoteException {
- try {
- return super.onTransact(code, data, reply, flags);
- } catch (Throwable e) {
- Slog.e(LOG_TAG, "Error during IPC", e);
- throw ExceptionUtils.propagate(e, RemoteException.class);
- }
- }
-
- @Override
- public void onDeviceSelected(String packageName, int userId, String deviceAddress) {
- addAssociation(userId, packageName, deviceAddress);
- cleanup();
- }
-
- @Override
- public void onDeviceSelectionCancel() {
- cleanup();
- }
- };
+ void addAssociation(int userId, String packageName, String deviceAddress) {
+ addAssociation(new Association(userId, deviceAddress, packageName));
}
- void addAssociation(int userId, String packageName, String deviceAddress) {
- updateSpecialAccessPermissionForAssociatedPackage(packageName, userId);
- recordAssociation(packageName, deviceAddress);
+ void addAssociation(Association association) {
+ updateSpecialAccessPermissionForAssociatedPackage(
+ association.companionAppPackage, association.userId);
+ recordAssociation(association);
}
void removeAssociation(int userId, String pkg, String deviceMacAddress) {
@@ -525,14 +482,15 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
}, getContext(), packageName, userId).recycleOnUse());
}
- private void recordAssociation(String priviledgedPackage, String deviceAddress) {
+ private void recordAssociation(Association association) {
if (DEBUG) {
- Log.i(LOG_TAG, "recordAssociation(priviledgedPackage = " + priviledgedPackage
- + ", deviceAddress = " + deviceAddress + ")");
+ Log.i(LOG_TAG, "recordAssociation(" + association + ")");
}
- int userId = getCallingUserId();
- updateAssociations(associations -> CollectionUtils.add(associations,
- new Association(userId, deviceAddress, priviledgedPackage)));
+ updateAssociations(associations -> CollectionUtils.add(associations, association));
+ }
+
+ private void recordAssociation(String privilegedPackage, String deviceAddress) {
+ recordAssociation(new Association(getCallingUserId(), deviceAddress, privilegedPackage));
}
private void updateAssociations(Function<Set<Association>, Set<Association>> update) {
@@ -629,41 +587,6 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
}
}
-
-
- private class Association {
- public final int uid;
- public final String deviceAddress;
- public final String companionAppPackage;
-
- private Association(int uid, String deviceAddress, String companionAppPackage) {
- this.uid = uid;
- this.deviceAddress = checkNotNull(deviceAddress);
- this.companionAppPackage = checkNotNull(companionAppPackage);
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- Association that = (Association) o;
-
- if (uid != that.uid) return false;
- if (!deviceAddress.equals(that.deviceAddress)) return false;
- return companionAppPackage.equals(that.companionAppPackage);
-
- }
-
- @Override
- public int hashCode() {
- int result = uid;
- result = 31 * result + deviceAddress.hashCode();
- result = 31 * result + companionAppPackage.hashCode();
- return result;
- }
- }
-
private class ShellCmd extends ShellCommand {
public static final String USAGE = "help\n"
+ "list USER_ID\n"
diff --git a/services/core/Android.bp b/services/core/Android.bp
index b7adfa4a3ff1..5b98f06cea2b 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -96,6 +96,7 @@ java_library_static {
"android.hardware.tv.cec-V1.0-java",
"app-compat-annotations",
"vintf-vibrator-java",
+ "framework-tethering",
],
required: [
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index 49046b244bb4..40a7dfcfc18d 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -63,6 +63,30 @@ public abstract class PackageManagerInternal {
public static final int PACKAGE_INCIDENT_REPORT_APPROVER = 10;
public static final int PACKAGE_APP_PREDICTOR = 11;
public static final int PACKAGE_TELEPHONY = 12;
+ public static final int PACKAGE_WIFI = 13;
+ public static final int PACKAGE_COMPANION = 14;
+
+ @IntDef(value = {
+ INTEGRITY_VERIFICATION_ALLOW,
+ INTEGRITY_VERIFICATION_REJECT,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface IntegrityVerificationResult {}
+
+ /**
+ * Used as the {@code verificationCode} argument for
+ * {@link PackageManagerInternal#setIntegrityVerificationResult(int, int)} to indicate that the
+ * integrity component allows the install to proceed.
+ */
+ public static final int INTEGRITY_VERIFICATION_ALLOW = 1;
+
+ /**
+ * Used as the {@code verificationCode} argument for
+ * {@link PackageManagerInternal#setIntegrityVerificationResult(int, int)} to indicate that the
+ * integrity component does not allow install to proceed.
+ */
+ public static final int INTEGRITY_VERIFICATION_REJECT = 0;
+
@IntDef(value = {
PACKAGE_SYSTEM,
PACKAGE_SETUP_WIZARD,
@@ -77,6 +101,8 @@ public abstract class PackageManagerInternal {
PACKAGE_INCIDENT_REPORT_APPROVER,
PACKAGE_APP_PREDICTOR,
PACKAGE_TELEPHONY,
+ PACKAGE_WIFI,
+ PACKAGE_COMPANION,
})
@Retention(RetentionPolicy.SOURCE)
public @interface KnownPackage {}
@@ -133,6 +159,12 @@ public abstract class PackageManagerInternal {
@PackageInfoFlags int flags, int filterCallingUid, int userId);
/**
+ * Retrieve CE data directory inode number of an application.
+ * Return 0 if there's error.
+ */
+ public abstract long getCeDataInode(String packageName, int userId);
+
+ /**
* Return a List of all application packages that are installed on the
* device, for a specific user. If flag GET_UNINSTALLED_PACKAGES has been
* set, a list of all applications including those deleted with
@@ -640,16 +672,12 @@ public abstract class PackageManagerInternal {
public abstract SparseArray<String> getAppsWithSharedUserIds();
/**
- * Get the value of attribute android:sharedUserId for the given packageName if specified,
- * otherwise {@code null}.
+ * Get all packages which share the same userId as the specified package, or an empty array
+ * if the package does not have a shared userId.
*/
- public abstract String getSharedUserIdForPackage(@NonNull String packageName);
-
- /**
- * Get all packages which specified the given sharedUserId as android:sharedUserId attribute
- * or an empty array if no package specified it.
- */
- public abstract String[] getPackagesForSharedUserId(@NonNull String sharedUserId, int userId);
+ @NonNull
+ public abstract String[] getSharedUserPackagesForPackage(@NonNull String packageName,
+ int userId);
/**
* Return if device is currently in a "core" boot environment, typically
@@ -835,13 +863,13 @@ public abstract class PackageManagerInternal {
* {@link Intent#ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION package verification
* broadcast} to respond to the package manager. The response must include
* the {@code verificationCode} which is one of
- * {@link PackageManager#VERIFICATION_ALLOW} or
- * {@link PackageManager#VERIFICATION_REJECT}.
+ * {@link #INTEGRITY_VERIFICATION_ALLOW} and {@link #INTEGRITY_VERIFICATION_REJECT}.
*
* @param verificationId pending package identifier as passed via the
* {@link PackageManager#EXTRA_VERIFICATION_ID} Intent extra.
- * @param verificationResult either {@link PackageManager#VERIFICATION_ALLOW}
- * or {@link PackageManager#VERIFICATION_REJECT}.
+ * @param verificationResult either {@link #INTEGRITY_VERIFICATION_ALLOW}
+ * or {@link #INTEGRITY_VERIFICATION_REJECT}.
*/
- public abstract void setIntegrityVerificationResult(int verificationId, int verificationResult);
+ public abstract void setIntegrityVerificationResult(int verificationId,
+ @IntegrityVerificationResult int verificationResult);
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index b71943504bf6..bb78aceb3b5f 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -77,7 +77,6 @@ import android.net.INetworkPolicyListener;
import android.net.INetworkPolicyManager;
import android.net.INetworkStatsService;
import android.net.ISocketKeepaliveCallback;
-import android.net.ITetheringEventCallback;
import android.net.InetAddresses;
import android.net.IpMemoryStore;
import android.net.IpPrefix;
@@ -278,8 +277,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
private MockableSystemProperties mSystemProperties;
- private TetheringManager mTetheringManager;
-
@VisibleForTesting
protected final PermissionMonitor mPermissionMonitor;
@@ -867,13 +864,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
/**
- * Get a reference to the TetheringManager.
- */
- public TetheringManager getTetheringManager() {
- return TetheringManager.getInstance();
- }
-
- /**
* @see ProxyTracker
*/
public ProxyTracker makeProxyTracker(@NonNull Context context,
@@ -1072,8 +1062,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
- mTetheringManager = mDeps.getTetheringManager();
-
mPermissionMonitor = new PermissionMonitor(mContext, mNetd);
// Set up the listener for user state for creating user VPNs.
@@ -1887,14 +1875,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
mHandler.sendMessage(mHandler.obtainMessage(
EVENT_DATA_SAVER_CHANGED, restrictBackground ? 1 : 0, 0));
-
- // TODO: relocate this specific callback in Tethering.
- if (restrictBackground) {
- log("onRestrictBackgroundChanged(true): disabling tethering");
- mTetheringManager.stopTethering(ConnectivityManager.TETHERING_WIFI);
- mTetheringManager.stopTethering(ConnectivityManager.TETHERING_USB);
- mTetheringManager.stopTethering(ConnectivityManager.TETHERING_BLUETOOTH);
- }
}
};
@@ -2024,12 +2004,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, pid, uid);
}
- private void enforceTetherAccessPermission() {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.ACCESS_NETWORK_STATE,
- "ConnectivityService");
- }
-
private void enforceControlAlwaysOnVpnPermission() {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.CONTROL_ALWAYS_ON_VPN,
@@ -2463,12 +2437,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
mKeepaliveTracker.dump(pw);
pw.println();
- pw.println("TetheringManager logs:");
- pw.increaseIndent();
- TetheringManager.getInstance().dump(pw);
- pw.decreaseIndent();
-
- pw.println();
dumpAvoidBadWifiSettings(pw);
pw.println();
@@ -3993,183 +3961,55 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
}
- // javadoc from interface
- @Override
- public int tether(String iface, String callerPkg) {
- ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
- if (isTetheringSupported()) {
- return mTetheringManager.tether(iface);
- } else {
- return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
- }
- }
-
- // javadoc from interface
- @Override
- public int untether(String iface, String callerPkg) {
- ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
-
- if (isTetheringSupported()) {
- return mTetheringManager.untether(iface);
- } else {
- return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
- }
- }
-
- // javadoc from interface
@Override
+ @Deprecated
public int getLastTetherError(String iface) {
- enforceTetherAccessPermission();
-
- if (isTetheringSupported()) {
- return mTetheringManager.getLastTetherError(iface);
- } else {
- return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
- }
- }
-
- // TODO - proper iface API for selection by property, inspection, etc
- @Override
- public String[] getTetherableUsbRegexs() {
- enforceTetherAccessPermission();
- if (isTetheringSupported()) {
- return mTetheringManager.getTetherableUsbRegexs();
- } else {
- return new String[0];
- }
- }
-
- @Override
- public String[] getTetherableWifiRegexs() {
- enforceTetherAccessPermission();
- if (isTetheringSupported()) {
- return mTetheringManager.getTetherableWifiRegexs();
- } else {
- return new String[0];
- }
- }
-
- @Override
- public String[] getTetherableBluetoothRegexs() {
- enforceTetherAccessPermission();
- if (isTetheringSupported()) {
- return mTetheringManager.getTetherableBluetoothRegexs();
- } else {
- return new String[0];
- }
- }
-
- @Override
- public int setUsbTethering(boolean enable, String callerPkg) {
- ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
- if (isTetheringSupported()) {
- return mTetheringManager.setUsbTethering(enable);
- } else {
- return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
- }
+ final TetheringManager tm = (TetheringManager) mContext.getSystemService(
+ Context.TETHERING_SERVICE);
+ return tm.getLastTetherError(iface);
}
- // TODO - move iface listing, queries, etc to new module
- // javadoc from interface
@Override
+ @Deprecated
public String[] getTetherableIfaces() {
- enforceTetherAccessPermission();
- return mTetheringManager.getTetherableIfaces();
+ final TetheringManager tm = (TetheringManager) mContext.getSystemService(
+ Context.TETHERING_SERVICE);
+ return tm.getTetherableIfaces();
}
@Override
+ @Deprecated
public String[] getTetheredIfaces() {
- enforceTetherAccessPermission();
- return mTetheringManager.getTetheredIfaces();
+ final TetheringManager tm = (TetheringManager) mContext.getSystemService(
+ Context.TETHERING_SERVICE);
+ return tm.getTetheredIfaces();
}
- @Override
- public String[] getTetheringErroredIfaces() {
- enforceTetherAccessPermission();
- return mTetheringManager.getTetheringErroredIfaces();
- }
-
- @Override
- public String[] getTetheredDhcpRanges() {
- enforceSettingsPermission();
- return mTetheringManager.getTetheredDhcpRanges();
- }
@Override
- public boolean isTetheringSupported(String callerPkg) {
- ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
- return isTetheringSupported();
- }
-
- // if ro.tether.denied = true we default to no tethering
- // gservices could set the secure setting to 1 though to enable it on a build where it
- // had previously been turned off.
- private boolean isTetheringSupported() {
- int defaultVal = encodeBool(!mSystemProperties.get("ro.tether.denied").equals("true"));
- boolean tetherSupported = toBool(Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.TETHER_SUPPORTED, defaultVal));
- boolean tetherEnabledInSettings = tetherSupported
- && !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING);
-
- // Elevate to system UID to avoid caller requiring MANAGE_USERS permission.
- boolean adminUser = false;
- final long token = Binder.clearCallingIdentity();
- try {
- adminUser = mUserManager.isAdminUser();
- } finally {
- Binder.restoreCallingIdentity(token);
- }
-
- return tetherEnabledInSettings && adminUser
- && mTetheringManager.hasTetherableConfiguration();
- }
-
- @Override
- public void startTethering(int type, ResultReceiver receiver, boolean showProvisioningUi,
- String callerPkg) {
- ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
- if (!isTetheringSupported()) {
- receiver.send(ConnectivityManager.TETHER_ERROR_UNSUPPORTED, null);
- return;
- }
- mTetheringManager.startTethering(type, receiver, showProvisioningUi);
- }
+ @Deprecated
+ public String[] getTetheringErroredIfaces() {
+ final TetheringManager tm = (TetheringManager) mContext.getSystemService(
+ Context.TETHERING_SERVICE);
- @Override
- public void stopTethering(int type, String callerPkg) {
- ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
- mTetheringManager.stopTethering(type);
+ return tm.getTetheringErroredIfaces();
}
- /**
- * Get the latest value of the tethering entitlement check.
- *
- * Note: Allow privileged apps who have TETHER_PRIVILEGED permission to access. If it turns
- * out some such apps are observed to abuse this API, change to per-UID limits on this API
- * if it's really needed.
- */
@Override
- public void getLatestTetheringEntitlementResult(int type, ResultReceiver receiver,
- boolean showEntitlementUi, String callerPkg) {
- ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
- mTetheringManager.requestLatestTetheringEntitlementResult(
- type, receiver, showEntitlementUi);
- }
+ @Deprecated
+ public String[] getTetherableUsbRegexs() {
+ final TetheringManager tm = (TetheringManager) mContext.getSystemService(
+ Context.TETHERING_SERVICE);
- /** Register tethering event callback. */
- @Override
- public void registerTetheringEventCallback(ITetheringEventCallback callback,
- String callerPkg) {
- ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
- mTetheringManager.registerTetheringEventCallback(callback);
+ return tm.getTetherableUsbRegexs();
}
- /** Unregister tethering event callback. */
@Override
- public void unregisterTetheringEventCallback(ITetheringEventCallback callback,
- String callerPkg) {
- ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
- mTetheringManager.unregisterTetheringEventCallback(callback);
+ @Deprecated
+ public String[] getTetherableWifiRegexs() {
+ final TetheringManager tm = (TetheringManager) mContext.getSystemService(
+ Context.TETHERING_SERVICE);
+ return tm.getTetherableWifiRegexs();
}
// Called when we lose the default network and have no replacement yet.
@@ -7050,14 +6890,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
// Turn airplane mode off
setAirplaneMode(false);
- if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING)) {
- // Untether
- String pkgName = mContext.getOpPackageName();
- for (String tether : getTetheredIfaces()) {
- untether(tether, pkgName);
- }
- }
-
if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN)) {
// Remove always-on package
synchronized (mVpns) {
diff --git a/services/core/java/com/android/server/CountryDetectorService.java b/services/core/java/com/android/server/CountryDetectorService.java
index d8a2fe35c7e8..861c731c69e0 100644
--- a/services/core/java/com/android/server/CountryDetectorService.java
+++ b/services/core/java/com/android/server/CountryDetectorService.java
@@ -16,14 +16,6 @@
package com.android.server;
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.HashMap;
-
-import com.android.internal.os.BackgroundThread;
-import com.android.internal.util.DumpUtils;
-import com.android.server.location.ComprehensiveCountryDetector;
-
import android.content.Context;
import android.location.Country;
import android.location.CountryListener;
@@ -36,17 +28,25 @@ import android.util.PrintWriterPrinter;
import android.util.Printer;
import android.util.Slog;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.DumpUtils;
+import com.android.server.location.ComprehensiveCountryDetector;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.HashMap;
+
/**
- * This class detects the country that the user is in through
- * {@link ComprehensiveCountryDetector}.
+ * This class detects the country that the user is in through {@link ComprehensiveCountryDetector}.
*
* @hide
*/
-public class CountryDetectorService extends ICountryDetector.Stub implements Runnable {
+public class CountryDetectorService extends ICountryDetector.Stub {
/**
- * The class represents the remote listener, it will also removes itself
- * from listener list when the remote process was died.
+ * The class represents the remote listener, it will also removes itself from listener list when
+ * the remote process was died.
*/
private final class Receiver implements IBinder.DeathRecipient {
private final ICountryListener mListener;
@@ -79,9 +79,11 @@ public class CountryDetectorService extends ICountryDetector.Stub implements Run
}
}
- private final static String TAG = "CountryDetector";
+ private static final String TAG = "CountryDetector";
- /** Whether to dump the state of the country detector service to bugreports */
+ /**
+ * Whether to dump the state of the country detector service to bugreports
+ */
private static final boolean DEBUG = false;
private final HashMap<IBinder, Receiver> mReceivers;
@@ -92,15 +94,21 @@ public class CountryDetectorService extends ICountryDetector.Stub implements Run
private CountryListener mLocationBasedDetectorListener;
public CountryDetectorService(Context context) {
+ this(context, BackgroundThread.getHandler());
+ }
+
+ @VisibleForTesting
+ CountryDetectorService(Context context, Handler handler) {
super();
- mReceivers = new HashMap<IBinder, Receiver>();
+ mReceivers = new HashMap<>();
mContext = context;
+ mHandler = handler;
}
@Override
public Country detectCountry() {
if (!mSystemReady) {
- return null; // server not yet active
+ return null; // server not yet active
} else {
return mCountryDetector.detectCountry();
}
@@ -154,9 +162,8 @@ public class CountryDetectorService extends ICountryDetector.Stub implements Run
}
}
-
protected void notifyReceivers(Country country) {
- synchronized(mReceivers) {
+ synchronized (mReceivers) {
for (Receiver receiver : mReceivers.values()) {
try {
receiver.getListener().onCountryDetected(country);
@@ -170,38 +177,23 @@ public class CountryDetectorService extends ICountryDetector.Stub implements Run
void systemRunning() {
// Shall we wait for the initialization finish.
- BackgroundThread.getHandler().post(this);
+ mHandler.post(
+ () -> {
+ initialize();
+ mSystemReady = true;
+ });
}
private void initialize() {
mCountryDetector = new ComprehensiveCountryDetector(mContext);
- mLocationBasedDetectorListener = new CountryListener() {
- public void onCountryDetected(final Country country) {
- mHandler.post(new Runnable() {
- public void run() {
- notifyReceivers(country);
- }
- });
- }
- };
- }
-
- public void run() {
- mHandler = new Handler();
- initialize();
- mSystemReady = true;
+ mLocationBasedDetectorListener = country -> mHandler.post(() -> notifyReceivers(country));
}
protected void setCountryListener(final CountryListener listener) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- mCountryDetector.setCountryListener(listener);
- }
- });
+ mHandler.post(() -> mCountryDetector.setCountryListener(listener));
}
- // For testing
+ @VisibleForTesting
boolean isSystemReady() {
return mSystemReady;
}
diff --git a/services/core/java/com/android/server/DynamicSystemService.java b/services/core/java/com/android/server/DynamicSystemService.java
index 7b02b6e0ac11..7909e3096cbe 100644
--- a/services/core/java/com/android/server/DynamicSystemService.java
+++ b/services/core/java/com/android/server/DynamicSystemService.java
@@ -179,18 +179,7 @@ public class DynamicSystemService extends IDynamicSystemService.Stub implements
@Override
public boolean isInUse() throws RemoteException {
- boolean gsidWasRunning = "running".equals(SystemProperties.get("init.svc.gsid"));
- boolean isInUse = false;
-
- try {
- isInUse = getGsiService().isGsiRunning();
- } finally {
- if (!gsidWasRunning && !isInUse) {
- mGsiService = null;
- }
- }
-
- return isInUse;
+ return SystemProperties.getBoolean("ro.gsid.image_running", false);
}
@Override
diff --git a/services/core/java/com/android/server/MmsServiceBroker.java b/services/core/java/com/android/server/MmsServiceBroker.java
index c0f10a3c86e1..92d1da5be7a2 100644
--- a/services/core/java/com/android/server/MmsServiceBroker.java
+++ b/services/core/java/com/android/server/MmsServiceBroker.java
@@ -16,6 +16,8 @@
package com.android.server;
+import static android.telephony.SubscriptionManager.INVALID_SIM_SLOT_INDEX;
+
import android.Manifest;
import android.app.AppOpsManager;
import android.app.PendingIntent;
@@ -37,6 +39,7 @@ import android.os.SystemClock;
import android.os.UserHandle;
import android.service.carrier.CarrierMessagingService;
import android.telephony.SmsManager;
+import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.util.Slog;
@@ -523,11 +526,11 @@ public class MmsServiceBroker extends SystemService {
// Grant permission for the carrier app.
Intent intent = new Intent(action);
- TelephonyManager telephonyManager =
- (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
- List<String> carrierPackages =
- telephonyManager.getCarrierPackageNamesForIntentAndPhone(
- intent, SubscriptionManager.getPhoneId(subId));
+ TelephonyManager telephonyManager = (TelephonyManager)
+ mContext.getSystemService(Context.TELEPHONY_SERVICE);
+ List<String> carrierPackages = telephonyManager
+ .getCarrierPackageNamesForIntentAndPhone(
+ intent, getPhoneIdFromSubId(subId));
if (carrierPackages != null && carrierPackages.size() == 1) {
LocalServices.getService(UriGrantsManagerInternal.class)
.grantUriPermissionFromIntent(callingUid, carrierPackages.get(0),
@@ -539,4 +542,13 @@ public class MmsServiceBroker extends SystemService {
return contentUri;
}
}
+
+ private int getPhoneIdFromSubId(int subId) {
+ SubscriptionManager subManager = (SubscriptionManager)
+ mContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
+ if (subManager == null) return INVALID_SIM_SLOT_INDEX;
+ SubscriptionInfo info = subManager.getActiveSubscriptionInfo(subId);
+ if (info == null) return INVALID_SIM_SLOT_INDEX;
+ return info.getSimSlotIndex();
+ }
}
diff --git a/services/core/java/com/android/server/NetworkTimeUpdateServiceImpl.java b/services/core/java/com/android/server/NetworkTimeUpdateServiceImpl.java
index b0b45f411d34..39be311e902d 100644
--- a/services/core/java/com/android/server/NetworkTimeUpdateServiceImpl.java
+++ b/services/core/java/com/android/server/NetworkTimeUpdateServiceImpl.java
@@ -35,11 +35,11 @@ import android.os.Message;
import android.os.PowerManager;
import android.os.SystemClock;
import android.provider.Settings;
+import android.telephony.TelephonyManager;
import android.util.Log;
import android.util.NtpTrustedTime;
import android.util.TimeUtils;
-import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.util.DumpUtils;
import java.io.FileDescriptor;
@@ -137,7 +137,7 @@ public class NetworkTimeUpdateServiceImpl extends Binder implements NetworkTimeU
private void registerForTelephonyIntents() {
IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction(TelephonyIntents.ACTION_NETWORK_SET_TIME);
+ intentFilter.addAction(TelephonyManager.ACTION_NETWORK_SET_TIME);
mContext.registerReceiver(mNitzReceiver, intentFilter);
}
@@ -247,7 +247,7 @@ public class NetworkTimeUpdateServiceImpl extends Binder implements NetworkTimeU
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (DBG) Log.d(TAG, "Received " + action);
- if (TelephonyIntents.ACTION_NETWORK_SET_TIME.equals(action)) {
+ if (TelephonyManager.ACTION_NETWORK_SET_TIME.equals(action)) {
mNitzTimeSetTime = SystemClock.elapsedRealtime();
}
}
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 5a78036911a8..22fa8ff4a0fa 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -144,6 +144,7 @@ import com.android.internal.util.HexDump;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
import com.android.internal.widget.LockPatternUtils;
+import com.android.server.pm.Installer;
import com.android.server.storage.AppFuseBridge;
import com.android.server.storage.StorageSessionController;
import com.android.server.storage.StorageSessionController.ExternalStorageServiceException;
@@ -367,6 +368,8 @@ class StorageManagerService extends IStorageManager.Stub
private volatile int mCurrentUserId = UserHandle.USER_SYSTEM;
+ private final Installer mInstaller;
+
/** Holding lock for AppFuse business */
private final Object mAppFuseLock = new Object();
@@ -1245,6 +1248,13 @@ class StorageManagerService extends IStorageManager.Stub
vol.state = newState;
onVolumeStateChangedLocked(vol, oldState, newState);
}
+ try {
+ if (vol.type == VolumeInfo.TYPE_PRIVATE && state == VolumeInfo.STATE_MOUNTED) {
+ mInstaller.onPrivateVolumeMounted(vol.getFsUuid());
+ }
+ } catch (Installer.InstallerException e) {
+ Slog.i(TAG, "Failed when private volume mounted " + vol, e);
+ }
}
}
@@ -1290,6 +1300,13 @@ class StorageManagerService extends IStorageManager.Stub
if (vol != null) {
mStorageSessionController.onVolumeRemove(vol);
+ try {
+ if (vol.type == VolumeInfo.TYPE_PRIVATE) {
+ mInstaller.onPrivateVolumeRemoved(vol.getFsUuid());
+ }
+ } catch (Installer.InstallerException e) {
+ Slog.i(TAG, "Failed when private volume unmounted " + vol, e);
+ }
}
}
};
@@ -1601,6 +1618,9 @@ class StorageManagerService extends IStorageManager.Stub
mStorageSessionController = new StorageSessionController(mContext, mIsFuseEnabled);
+ mInstaller = new Installer(mContext);
+ mInstaller.onStart();
+
// Initialize the last-fstrim tracking if necessary
File dataDir = Environment.getDataDirectory();
File systemDir = new File(dataDir, "system");
@@ -1974,6 +1994,13 @@ class StorageManagerService extends IStorageManager.Stub
try {
mVold.unmount(vol.id);
mStorageSessionController.onVolumeUnmount(vol);
+ try {
+ if (vol.type == VolumeInfo.TYPE_PRIVATE) {
+ mInstaller.onPrivateVolumeRemoved(vol.getFsUuid());
+ }
+ } catch (Installer.InstallerException e) {
+ Slog.e(TAG, "Failed unmount mirror data", e);
+ }
} catch (Exception e) {
Slog.wtf(TAG, e);
}
diff --git a/services/core/java/com/android/server/SystemService.java b/services/core/java/com/android/server/SystemService.java
index 5e659b64dbbe..c5409f85bde3 100644
--- a/services/core/java/com/android/server/SystemService.java
+++ b/services/core/java/com/android/server/SystemService.java
@@ -29,6 +29,10 @@ import android.os.UserManager;
import com.android.server.pm.UserManagerService;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* The base class for services running in the system process. Override and implement
* the lifecycle event callback methods as needed.
@@ -164,6 +168,25 @@ public abstract class SystemService {
}
/**
+ * Helper method used to dump which users are {@link #onStartUser(UserInfo) supported}.
+ */
+ protected void dumpSupportedUsers(@NonNull PrintWriter pw, @NonNull String prefix) {
+ final List<UserInfo> allUsers = UserManager.get(mContext).getUsers();
+ final List<Integer> supportedUsers = new ArrayList<>(allUsers.size());
+ for (UserInfo user : allUsers) {
+ supportedUsers.add(user.id);
+ }
+ if (allUsers.isEmpty()) {
+ pw.print(prefix); pw.println("No supported users");
+ } else {
+ final int size = supportedUsers.size();
+ pw.print(prefix); pw.print(size); pw.print(" supported user");
+ if (size > 1) pw.print("s");
+ pw.print(": "); pw.println(supportedUsers);
+ }
+ }
+
+ /**
* @deprecated subclasses should extend {@link #onStartUser(UserInfo)} instead (which by default
* calls this method).
*/
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 0e144ed19520..783715cd84bc 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -16,6 +16,7 @@
package com.android.server;
+import static android.telephony.SubscriptionManager.INVALID_SIM_SLOT_INDEX;
import static android.telephony.TelephonyManager.ACTION_MULTI_SIM_CONFIG_CHANGED;
import static android.telephony.TelephonyRegistryManager.SIM_ACTIVATION_TYPE_DATA;
import static android.telephony.TelephonyRegistryManager.SIM_ACTIVATION_TYPE_VOICE;
@@ -45,6 +46,7 @@ import android.telephony.Annotation.RadioPowerState;
import android.telephony.Annotation.SrvccState;
import android.telephony.CallAttributes;
import android.telephony.CallQuality;
+import android.telephony.CellIdentity;
import android.telephony.CellInfo;
import android.telephony.CellLocation;
import android.telephony.DataFailCause;
@@ -58,6 +60,7 @@ import android.telephony.PreciseDisconnectCause;
import android.telephony.Rlog;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
+import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.data.ApnSetting;
@@ -96,7 +99,7 @@ import java.util.NoSuchElementException;
* and 15973975 by saving the phoneId of the registrant and then using the
* phoneId when deciding to to make a callback. This is necessary because
* a subId changes from to a dummy value when a SIM is removed and thus won't
- * compare properly. Because SubscriptionManager.getPhoneId(int subId) handles
+ * compare properly. Because getPhoneIdFromSubId(int subId) handles
* the dummy value conversion we properly do the callbacks.
*
* Eventually we may want to remove the notion of dummy value but for now this
@@ -130,7 +133,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
- int phoneId = SubscriptionManager.INVALID_PHONE_INDEX;
+ int phoneId = SubscriptionManager.INVALID_SIM_SLOT_INDEX;
boolean matchPhoneStateListenerEvent(int events) {
return (callback != null) && ((events & this.events) != 0);
@@ -205,7 +208,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
// Connection state of default APN type data (i.e. internet) of phones
private int[] mDataConnectionState;
- private Bundle[] mCellLocation;
+ private CellIdentity[] mCellIdentity;
private int[] mDataConnectionNetworkType;
@@ -228,7 +231,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
private int mDefaultSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
- private int mDefaultPhoneId = SubscriptionManager.INVALID_PHONE_INDEX;
+ private int mDefaultPhoneId = SubscriptionManager.INVALID_SIM_SLOT_INDEX;
private int[] mRingingCallState;
@@ -293,7 +296,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
int numPhones = getTelephonyManager().getPhoneCount();
for (int sub = 0; sub < numPhones; sub++) {
TelephonyRegistry.this.notifyCellLocationForSubscriber(sub,
- mCellLocation[sub]);
+ mCellIdentity[sub]);
}
break;
}
@@ -357,7 +360,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
SubscriptionManager.getDefaultSubscriptionId());
int newDefaultPhoneId = intent.getIntExtra(
SubscriptionManager.EXTRA_SLOT_INDEX,
- SubscriptionManager.getPhoneId(newDefaultSubId));
+ getPhoneIdFromSubId(newDefaultSubId));
if (DBG) {
log("onReceive:current mDefaultSubId=" + mDefaultSubId
+ " current mDefaultPhoneId=" + mDefaultPhoneId
@@ -402,7 +405,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mSignalStrength = copyOf(mSignalStrength, mNumPhones);
mMessageWaiting = copyOf(mMessageWaiting, mNumPhones);
mCallForwarding = copyOf(mCallForwarding, mNumPhones);
- mCellLocation = copyOf(mCellLocation, mNumPhones);
+ mCellIdentity = copyOf(mCellIdentity, mNumPhones);
mSrvccState = copyOf(mSrvccState, mNumPhones);
mPreciseCallState = copyOf(mPreciseCallState, mNumPhones);
mForegroundCallState = copyOf(mForegroundCallState, mNumPhones);
@@ -437,31 +440,22 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mUserMobileDataState[i] = false;
mMessageWaiting[i] = false;
mCallForwarding[i] = false;
- mCellLocation[i] = new Bundle();
+ mCellIdentity[i] = null;
mCellInfo.add(i, null);
mImsReasonInfo.add(i, null);
mSrvccState[i] = TelephonyManager.SRVCC_STATE_HANDOVER_NONE;
mCallDisconnectCause[i] = DisconnectCause.NOT_VALID;
mCallPreciseDisconnectCause[i] = PreciseDisconnectCause.NOT_VALID;
mCallQuality[i] = createCallQuality();
- mCallAttributes[i] = new CallAttributes(new PreciseCallState(),
+ mCallAttributes[i] = new CallAttributes(createPreciseCallState(),
TelephonyManager.NETWORK_TYPE_UNKNOWN, createCallQuality());
mCallNetworkType[i] = TelephonyManager.NETWORK_TYPE_UNKNOWN;
- mPreciseCallState[i] = new PreciseCallState();
+ mPreciseCallState[i] = createPreciseCallState();
mRingingCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE;
mForegroundCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE;
mBackgroundCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE;
mPreciseDataConnectionStates.add(new HashMap<String, PreciseDataConnectionState>());
}
-
- // Note that location can be null for non-phone builds like
- // like the generic one.
- CellLocation location = CellLocation.getEmpty();
- if (location != null) {
- for (int i = oldNumPhones; i < mNumPhones; i++) {
- location.fillInNotifierBundle(mCellLocation[i]);
- }
- }
}
private void cutListToSize(List list, int size) {
@@ -501,7 +495,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mSignalStrength = new SignalStrength[numPhones];
mMessageWaiting = new boolean[numPhones];
mCallForwarding = new boolean[numPhones];
- mCellLocation = new Bundle[numPhones];
+ mCellIdentity = new CellIdentity[numPhones];
mSrvccState = new int[numPhones];
mPreciseCallState = new PreciseCallState[numPhones];
mForegroundCallState = new int[numPhones];
@@ -530,31 +524,23 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mUserMobileDataState[i] = false;
mMessageWaiting[i] = false;
mCallForwarding[i] = false;
- mCellLocation[i] = new Bundle();
+ mCellIdentity[i] = null;
mCellInfo.add(i, null);
mImsReasonInfo.add(i, null);
mSrvccState[i] = TelephonyManager.SRVCC_STATE_HANDOVER_NONE;
mCallDisconnectCause[i] = DisconnectCause.NOT_VALID;
mCallPreciseDisconnectCause[i] = PreciseDisconnectCause.NOT_VALID;
mCallQuality[i] = createCallQuality();
- mCallAttributes[i] = new CallAttributes(new PreciseCallState(),
+ mCallAttributes[i] = new CallAttributes(createPreciseCallState(),
TelephonyManager.NETWORK_TYPE_UNKNOWN, createCallQuality());
mCallNetworkType[i] = TelephonyManager.NETWORK_TYPE_UNKNOWN;
- mPreciseCallState[i] = new PreciseCallState();
+ mPreciseCallState[i] = createPreciseCallState();
mRingingCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE;
mForegroundCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE;
mBackgroundCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE;
mPreciseDataConnectionStates.add(new HashMap<String, PreciseDataConnectionState>());
}
- // Note that location can be null for non-phone builds like
- // like the generic one.
- if (location != null) {
- for (int i = 0; i < numPhones; i++) {
- location.fillInNotifierBundle(mCellLocation[i]);
- }
- }
-
mAppOps = mContext.getSystemService(AppOpsManager.class);
}
@@ -763,7 +749,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
return;
}
- int phoneId = SubscriptionManager.getPhoneId(subId);
+ int phoneId = getPhoneIdFromSubId(subId);
synchronized (mRecords) {
// register
IBinder b = callback.asBinder();
@@ -799,9 +785,11 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
r.callback.onServiceStateChanged(rawSs);
} else if (checkCoarseLocationAccess(r, Build.VERSION_CODES.Q)) {
- r.callback.onServiceStateChanged(rawSs.sanitizeLocationInfo(false));
+ r.callback.onServiceStateChanged(
+ rawSs.createLocationInfoSanitizedCopy(false));
} else {
- r.callback.onServiceStateChanged(rawSs.sanitizeLocationInfo(true));
+ r.callback.onServiceStateChanged(
+ rawSs.createLocationInfoSanitizedCopy(true));
}
} catch (RemoteException ex) {
remove(r.binder);
@@ -835,11 +823,10 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION)) {
try {
- if (DBG_LOC) log("listen: mCellLocation = "
- + mCellLocation[phoneId]);
+ if (DBG_LOC) log("listen: mCellIdentity = " + mCellIdentity[phoneId]);
if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
- r.callback.onCellLocationChanged(
- new Bundle(mCellLocation[phoneId]));
+ // null will be translated to empty CellLocation object in client.
+ r.callback.onCellLocationChanged(mCellIdentity[phoneId]);
}
} catch (RemoteException ex) {
remove(r.binder);
@@ -1090,7 +1077,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
// Called only by Telecomm to communicate call state across different phone accounts. So
// there is no need to add a valid subId or slotId.
broadcastCallStateChanged(state, phoneNumber,
- SubscriptionManager.INVALID_PHONE_INDEX,
+ SubscriptionManager.INVALID_SIM_SLOT_INDEX,
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
}
@@ -1157,9 +1144,9 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
stateToSend = new ServiceState(state);
} else if (checkCoarseLocationAccess(r, Build.VERSION_CODES.Q)) {
- stateToSend = state.sanitizeLocationInfo(false);
+ stateToSend = state.createLocationInfoSanitizedCopy(false);
} else {
- stateToSend = state.sanitizeLocationInfo(true);
+ stateToSend = state.createLocationInfoSanitizedCopy(true);
}
if (DBG) {
log("notifyServiceStateForSubscriber: callback.onSSC r=" + r
@@ -1315,7 +1302,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
synchronized (mRecords) {
mCarrierNetworkChangeState = active;
for (int subId : subIds) {
- int phoneId = SubscriptionManager.getPhoneId(subId);
+ int phoneId = getPhoneIdFromSubId(subId);
if (VDBG) {
log("notifyCarrierNetworkChange: active=" + active + "subId: " + subId);
@@ -1348,7 +1335,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
log("notifyCellInfoForSubscriber: subId=" + subId
+ " cellInfo=" + cellInfo);
}
- int phoneId = SubscriptionManager.getPhoneId(subId);
+ int phoneId = getPhoneIdFromSubId(subId);
synchronized (mRecords) {
if (validatePhoneId(phoneId)) {
mCellInfo.set(phoneId, cellInfo);
@@ -1439,7 +1426,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
log("notifyCallForwardingChangedForSubscriber: subId=" + subId
+ " cfi=" + cfi);
}
- int phoneId = SubscriptionManager.getPhoneId(subId);
+ int phoneId = getPhoneIdFromSubId(subId);
synchronized (mRecords) {
if (validatePhoneId(phoneId)) {
mCallForwarding[phoneId] = cfi;
@@ -1467,7 +1454,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
if (!checkNotifyPermission("notifyDataActivity()" )) {
return;
}
- int phoneId = SubscriptionManager.getPhoneId(subId);
+ int phoneId = getPhoneIdFromSubId(subId);
synchronized (mRecords) {
if (validatePhoneId(phoneId)) {
mDataActivity[phoneId] = state;
@@ -1607,7 +1594,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
TelephonyManager.DATA_UNKNOWN,
TelephonyManager.NETWORK_TYPE_UNKNOWN,
ApnSetting.getApnTypesBitmaskFromString(apnType), null, null,
- DataFailCause.NONE));
+ DataFailCause.NONE, null));
for (Record r : mRecords) {
if (r.matchPhoneStateListenerEvent(
PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE)
@@ -1624,14 +1611,15 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
handleRemoveListLocked();
}
- broadcastDataConnectionFailed(apnType, subId);
}
- public void notifyCellLocation(Bundle cellLocation) {
- notifyCellLocationForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, cellLocation);
+ @Override
+ public void notifyCellLocation(CellIdentity cellLocation) {
+ notifyCellLocationForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, cellLocation);
}
- public void notifyCellLocationForSubscriber(int subId, Bundle cellLocation) {
+ @Override
+ public void notifyCellLocationForSubscriber(int subId, CellIdentity cellLocation) {
log("notifyCellLocationForSubscriber: subId=" + subId
+ " cellLocation=" + cellLocation);
if (!checkNotifyPermission("notifyCellLocation()")) {
@@ -1641,10 +1629,10 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
log("notifyCellLocationForSubscriber: subId=" + subId
+ " cellLocation=" + cellLocation);
}
- int phoneId = SubscriptionManager.getPhoneId(subId);
+ int phoneId = getPhoneIdFromSubId(subId);
synchronized (mRecords) {
if (validatePhoneId(phoneId)) {
- mCellLocation[phoneId] = cellLocation;
+ mCellIdentity[phoneId] = cellLocation;
for (Record r : mRecords) {
if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION) &&
idMatch(r.subId, subId, phoneId) &&
@@ -1654,7 +1642,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
log("notifyCellLocation: cellLocation=" + cellLocation
+ " r=" + r);
}
- r.callback.onCellLocationChanged(new Bundle(cellLocation));
+ r.callback.onCellLocationChanged(cellLocation);
} catch (RemoteException ex) {
mRemoveList.add(r.binder);
}
@@ -1750,7 +1738,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
if (!checkNotifyPermission("notifyImsCallDisconnectCause()")) {
return;
}
- int phoneId = SubscriptionManager.getPhoneId(subId);
+ int phoneId = getPhoneIdFromSubId(subId);
synchronized (mRecords) {
if (validatePhoneId(phoneId)) {
mImsReasonInfo.set(phoneId, imsReasonInfo);
@@ -1791,7 +1779,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
TelephonyManager.DATA_UNKNOWN,
TelephonyManager.NETWORK_TYPE_UNKNOWN,
ApnSetting.getApnTypesBitmaskFromString(apnType), null, null,
- failCause));
+ failCause, null));
for (Record r : mRecords) {
if (r.matchPhoneStateListenerEvent(
PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE)
@@ -1817,7 +1805,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
if (VDBG) {
log("notifySrvccStateChanged: subId=" + subId + " srvccState=" + state);
}
- int phoneId = SubscriptionManager.getPhoneId(subId);
+ int phoneId = getPhoneIdFromSubId(subId);
synchronized (mRecords) {
if (validatePhoneId(phoneId)) {
mSrvccState[phoneId] = state;
@@ -2091,7 +2079,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
pw.println("mCallForwarding=" + mCallForwarding[i]);
pw.println("mDataActivity=" + mDataActivity[i]);
pw.println("mDataConnectionState=" + mDataConnectionState[i]);
- pw.println("mCellLocation=" + mCellLocation[i]);
+ pw.println("mCellIdentity=" + mCellIdentity[i]);
pw.println("mCellInfo=" + mCellInfo.get(i));
pw.println("mImsCallDisconnectCause=" + mImsReasonInfo.get(i));
pw.println("mSrvccState=" + mSrvccState[i]);
@@ -2223,7 +2211,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
}
// If the phoneId is invalid, the broadcast is for overall call state.
- if (phoneId != SubscriptionManager.INVALID_PHONE_INDEX) {
+ if (phoneId != SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
intent.putExtra(PHONE_CONSTANTS_SLOT_KEY, phoneId);
intent.putExtra(SubscriptionManager.EXTRA_SLOT_INDEX, phoneId);
}
@@ -2273,13 +2261,6 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
}
- private void broadcastDataConnectionFailed(String apnType, int subId) {
- Intent intent = new Intent(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED);
- intent.putExtra(PhoneConstants.DATA_APN_TYPE_KEY, apnType);
- intent.putExtra(PHONE_CONSTANTS_SUBSCRIPTION_KEY, subId);
- mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
- }
-
private void enforceNotifyPermissionOrCarrierPrivilege(String method) {
if (checkNotifyPermission()) {
return;
@@ -2581,10 +2562,13 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION)) {
try {
- if (DBG_LOC) log("checkPossibleMissNotify: onCellLocationChanged mCellLocation = "
- + mCellLocation[phoneId]);
+ if (DBG_LOC) {
+ log("checkPossibleMissNotify: onCellLocationChanged mCellIdentity = "
+ + mCellIdentity[phoneId]);
+ }
if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
- r.callback.onCellLocationChanged(new Bundle(mCellLocation[phoneId]));
+ // null will be translated to empty CellLocation object in client.
+ r.callback.onCellLocationChanged(mCellIdentity[phoneId]);
}
} catch (RemoteException ex) {
mRemoveList.add(r.binder);
@@ -2676,8 +2660,31 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
}
+ /** Returns a new PreciseCallState object with default values. */
+ private static PreciseCallState createPreciseCallState() {
+ return new PreciseCallState(PreciseCallState.PRECISE_CALL_STATE_NOT_VALID,
+ PreciseCallState.PRECISE_CALL_STATE_NOT_VALID,
+ PreciseCallState.PRECISE_CALL_STATE_NOT_VALID,
+ DisconnectCause.NOT_VALID,
+ PreciseDisconnectCause.NOT_VALID);
+ }
+
/** Returns a new CallQuality object with default values. */
private static CallQuality createCallQuality() {
return new CallQuality(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
+
+ private int getPhoneIdFromSubId(int subId) {
+ SubscriptionManager subManager = (SubscriptionManager)
+ mContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
+ if (subManager == null) return INVALID_SIM_SLOT_INDEX;
+
+ if (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
+ subId = SubscriptionManager.getDefaultSubscriptionId();
+ }
+
+ SubscriptionInfo info = subManager.getActiveSubscriptionInfo(subId);
+ if (info == null) return INVALID_SIM_SLOT_INDEX;
+ return info.getSimSlotIndex();
+ }
}
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index 5bec7a3f4a39..2091c2a0c694 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -551,16 +551,13 @@ final class UiModeManagerService extends SystemService {
if (mNightMode == UiModeManager.MODE_NIGHT_AUTO) {
unregisterScreenOffEvent();
}
- // Only persist setting if not in car mode
- if (!mCarModeEnabled) {
- Secure.putIntForUser(getContext().getContentResolver(),
- Secure.UI_NIGHT_MODE, mode, user);
- Secure.putIntForUser(getContext().getContentResolver(),
- OVERRIDE_NIGHT_MODE, mNightModeOverride, user);
- }
mNightMode = mode;
mNightModeOverride = mode;
+ // Only persist setting if not in car mode
+ if (!mCarModeEnabled) {
+ persistNightMode(user);
+ }
// on screen off will update configuration instead
if (mNightMode != UiModeManager.MODE_NIGHT_AUTO || mCar) {
updateLocked(0, 0);
@@ -610,6 +607,7 @@ final class UiModeManagerService extends SystemService {
@Override
public boolean setNightModeActivated(boolean active) {
synchronized (mLock) {
+ final int user = UserHandle.getCallingUserId();
final long ident = Binder.clearCallingIdentity();
try {
if (mNightMode == UiModeManager.MODE_NIGHT_AUTO) {
@@ -625,6 +623,7 @@ final class UiModeManagerService extends SystemService {
}
updateConfigurationLocked();
applyConfigurationExternallyLocked();
+ persistNightMode(user);
return true;
} finally {
Binder.restoreCallingIdentity(ident);
@@ -834,6 +833,13 @@ final class UiModeManagerService extends SystemService {
}
}
+ private void persistNightMode(int user) {
+ Secure.putIntForUser(getContext().getContentResolver(),
+ Secure.UI_NIGHT_MODE, mNightMode, user);
+ Secure.putIntForUser(getContext().getContentResolver(),
+ OVERRIDE_NIGHT_MODE, mNightModeOverride, user);
+ }
+
private void updateConfigurationLocked() {
int uiMode = mDefaultUiModeType;
if (mUiModeLocked) {
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index f6c11cd1d0d6..76a8f92312ae 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -61,6 +61,7 @@ import android.provider.DeviceConfig;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.util.DebugUtils;
+import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.util.StatsLog;
@@ -162,6 +163,8 @@ public class VibratorService extends IVibratorService.Stub
private int mHapticFeedbackIntensity;
private int mNotificationIntensity;
private int mRingIntensity;
+ private SparseArray<Pair<VibrationEffect, AudioAttributes>> mAlwaysOnEffects =
+ new SparseArray<>();
static native boolean vibratorExists();
static native void vibratorInit();
@@ -173,6 +176,8 @@ public class VibratorService extends IVibratorService.Stub
static native boolean vibratorSupportsExternalControl();
static native void vibratorSetExternalControl(boolean enabled);
static native long vibratorGetCapabilities();
+ static native void vibratorAlwaysOnEnable(long id, long effect, long strength);
+ static native void vibratorAlwaysOnDisable(long id);
private final IUidObserver mUidObserver = new IUidObserver.Stub() {
@Override public void onUidStateChanged(int uid, int procState, long procStateSeq,
@@ -522,6 +527,41 @@ public class VibratorService extends IVibratorService.Stub
}
}
+ @Override // Binder call
+ public boolean setAlwaysOnEffect(int id, VibrationEffect effect, AudioAttributes attrs) {
+ if (!hasPermission(android.Manifest.permission.VIBRATE_ALWAYS_ON)) {
+ throw new SecurityException("Requires VIBRATE_ALWAYS_ON permission");
+ }
+ if ((mCapabilities & IVibrator.CAP_ALWAYS_ON_CONTROL) == 0) {
+ Slog.e(TAG, "Always-on effects not supported.");
+ return false;
+ }
+ if (effect == null) {
+ synchronized (mLock) {
+ mAlwaysOnEffects.delete(id);
+ vibratorAlwaysOnDisable(id);
+ }
+ } else {
+ if (!verifyVibrationEffect(effect)) {
+ return false;
+ }
+ if (!(effect instanceof VibrationEffect.Prebaked)) {
+ Slog.e(TAG, "Only prebaked effects supported for always-on.");
+ return false;
+ }
+ if (attrs == null) {
+ attrs = new AudioAttributes.Builder()
+ .setUsage(AudioAttributes.USAGE_UNKNOWN)
+ .build();
+ }
+ synchronized (mLock) {
+ mAlwaysOnEffects.put(id, Pair.create(effect, attrs));
+ updateAlwaysOnLocked(id, effect, attrs);
+ }
+ }
+ return true;
+ }
+
private void verifyIncomingUid(int uid) {
if (uid == Binder.getCallingUid()) {
return;
@@ -992,6 +1032,8 @@ public class VibratorService extends IVibratorService.Stub
// If the state changes out from under us then just reset.
doCancelVibrateLocked();
}
+
+ updateAlwaysOnLocked();
}
}
@@ -1058,6 +1100,27 @@ public class VibratorService extends IVibratorService.Stub
mVibrator.getDefaultRingVibrationIntensity(), UserHandle.USER_CURRENT);
}
+ private void updateAlwaysOnLocked(int id, VibrationEffect effect, AudioAttributes attrs) {
+ // TODO: Check DND and LowPower settings
+ final Vibration vib = new Vibration(null, effect, attrs, 0, null, null);
+ final int intensity = getCurrentIntensityLocked(vib);
+ if (intensity == Vibrator.VIBRATION_INTENSITY_OFF) {
+ vibratorAlwaysOnDisable(id);
+ } else {
+ final VibrationEffect.Prebaked prebaked = (VibrationEffect.Prebaked) effect;
+ final int strength = intensityToEffectStrength(intensity);
+ vibratorAlwaysOnEnable(id, prebaked.getId(), strength);
+ }
+ }
+
+ private void updateAlwaysOnLocked() {
+ for (int i = 0; i < mAlwaysOnEffects.size(); i++) {
+ int id = mAlwaysOnEffects.keyAt(i);
+ Pair<VibrationEffect, AudioAttributes> pair = mAlwaysOnEffects.valueAt(i);
+ updateAlwaysOnLocked(id, pair.first, pair.second);
+ }
+ }
+
@Override
public void onInputDeviceAdded(int deviceId) {
updateVibrators();
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index dab928a58011..154d16f013db 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -2960,7 +2960,9 @@ public final class ActiveServices {
} catch (Exception e) {
Slog.w(TAG, "Exception when unbinding service "
+ r.shortInstanceName, e);
+ needOomAdj = false;
serviceProcessGoneLocked(r);
+ break;
}
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index f1cee0348832..d7a46fec7767 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -158,7 +158,6 @@ import android.app.ApplicationErrorReport;
import android.app.ApplicationThreadConstants;
import android.app.BroadcastOptions;
import android.app.ContentProviderHolder;
-import android.app.Dialog;
import android.app.IActivityController;
import android.app.IActivityManager;
import android.app.IApplicationThread;
@@ -957,10 +956,12 @@ public class ActivityManagerService extends IActivityManager.Stub
new DeviceConfig.OnPropertiesChangedListener() {
@Override
public void onPropertiesChanged(Properties properties) {
- mPssDeferralTime = properties.getLong(ACTIVITY_START_PSS_DEFER_CONFIG, 0);
- if (DEBUG_PSS) {
- Slog.d(TAG_PSS, "Activity-start PSS delay now "
- + mPssDeferralTime + " ms");
+ if (properties.getKeyset().contains(ACTIVITY_START_PSS_DEFER_CONFIG)) {
+ mPssDeferralTime = properties.getLong(ACTIVITY_START_PSS_DEFER_CONFIG, 0);
+ if (DEBUG_PSS) {
+ Slog.d(TAG_PSS, "Activity-start PSS delay now "
+ + mPssDeferralTime + " ms");
+ }
}
}
};
@@ -1619,82 +1620,72 @@ public class ActivityManagerService extends IActivityManager.Stub
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
- case SHOW_ERROR_UI_MSG: {
- mAppErrors.handleShowAppErrorUi(msg);
- ensureBootCompleted();
- } break;
- case SHOW_NOT_RESPONDING_UI_MSG: {
- mAppErrors.handleShowAnrUi(msg);
- ensureBootCompleted();
- } break;
- case SHOW_STRICT_MODE_VIOLATION_UI_MSG: {
- HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
- synchronized (ActivityManagerService.this) {
- ProcessRecord proc = (ProcessRecord) data.get("app");
- if (proc == null) {
- Slog.e(TAG, "App not found when showing strict mode dialog.");
- break;
- }
- if (proc.crashDialog != null) {
- Slog.e(TAG, "App already has strict mode dialog: " + proc);
- return;
- }
- AppErrorResult res = (AppErrorResult) data.get("result");
- if (mAtmInternal.showStrictModeViolationDialog()) {
- Dialog d = new StrictModeViolationDialog(mUiContext,
- ActivityManagerService.this, res, proc);
- d.show();
- proc.crashDialog = d;
- } else {
- // The device is asleep, so just pretend that the user
- // saw a crash dialog and hit "force quit".
- res.set(0);
- }
- }
- ensureBootCompleted();
- } break;
- case WAIT_FOR_DEBUGGER_UI_MSG: {
- synchronized (ActivityManagerService.this) {
- ProcessRecord app = (ProcessRecord)msg.obj;
- if (msg.arg1 != 0) {
- if (!app.waitedForDebugger) {
- Dialog d = new AppWaitingForDebuggerDialog(
- ActivityManagerService.this,
- mUiContext, app);
- app.waitDialog = d;
- app.waitedForDebugger = true;
- d.show();
+ case SHOW_ERROR_UI_MSG: {
+ mAppErrors.handleShowAppErrorUi(msg);
+ ensureBootCompleted();
+ } break;
+ case SHOW_NOT_RESPONDING_UI_MSG: {
+ mAppErrors.handleShowAnrUi(msg);
+ ensureBootCompleted();
+ } break;
+ case SHOW_STRICT_MODE_VIOLATION_UI_MSG: {
+ HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
+ synchronized (ActivityManagerService.this) {
+ ProcessRecord proc = (ProcessRecord) data.get("app");
+ if (proc == null) {
+ Slog.e(TAG, "App not found when showing strict mode dialog.");
+ break;
}
- } else {
- if (app.waitDialog != null) {
- app.waitDialog.dismiss();
- app.waitDialog = null;
+ if (proc.getDialogController().hasViolationDialogs()) {
+ Slog.e(TAG, "App already has strict mode dialog: " + proc);
+ return;
+ }
+ AppErrorResult res = (AppErrorResult) data.get("result");
+ if (mAtmInternal.showStrictModeViolationDialog()) {
+ proc.getDialogController().showViolationDialogs(res);
+ } else {
+ // The device is asleep, so just pretend that the user
+ // saw a crash dialog and hit "force quit".
+ res.set(0);
+ }
+ }
+ ensureBootCompleted();
+ } break;
+ case WAIT_FOR_DEBUGGER_UI_MSG: {
+ synchronized (ActivityManagerService.this) {
+ ProcessRecord app = (ProcessRecord) msg.obj;
+ if (msg.arg1 != 0) {
+ if (!app.waitedForDebugger) {
+ app.getDialogController().showDebugWaitingDialogs();
+ app.waitedForDebugger = true;
+ }
+ } else {
+ app.getDialogController().clearWaitingDialog();
}
}
+ } break;
+ case DISPATCH_PROCESSES_CHANGED_UI_MSG: {
+ dispatchProcessesChanged();
+ break;
}
- } break;
- case DISPATCH_PROCESSES_CHANGED_UI_MSG: {
- dispatchProcessesChanged();
- break;
- }
- case DISPATCH_PROCESS_DIED_UI_MSG: {
- final int pid = msg.arg1;
- final int uid = msg.arg2;
- dispatchProcessDied(pid, uid);
- break;
- }
- case DISPATCH_UIDS_CHANGED_UI_MSG: {
- if (false) { // DO NOT SUBMIT WITH TRUE
- maybeTriggerWatchdog();
+ case DISPATCH_PROCESS_DIED_UI_MSG: {
+ final int pid = msg.arg1;
+ final int uid = msg.arg2;
+ dispatchProcessDied(pid, uid);
+ break;
}
- dispatchUidsChanged();
- } break;
- case DISPATCH_OOM_ADJ_OBSERVER_MSG: {
- dispatchOomAdjObserver((String)msg.obj);
- } break;
- case PUSH_TEMP_WHITELIST_UI_MSG: {
- pushTempWhitelist();
- } break;
+ case DISPATCH_UIDS_CHANGED_UI_MSG: {
+ if (false) { // DO NOT SUBMIT WITH TRUE
+ maybeTriggerWatchdog();
+ }
+ dispatchUidsChanged();
+ } break;
+ case DISPATCH_OOM_ADJ_OBSERVER_MSG: {
+ dispatchOomAdjObserver((String) msg.obj);
+ } break;
+ case PUSH_TEMP_WHITELIST_UI_MSG: {
+ pushTempWhitelist();
+ } break;
}
}
}
@@ -7567,6 +7558,26 @@ public class ActivityManagerService extends IActivityManager.Stub
});
}
+ @Override
+ public void appNotResponding(final String reason) {
+ final int callingPid = Binder.getCallingPid();
+
+ synchronized (mPidsSelfLocked) {
+ final ProcessRecord app = mPidsSelfLocked.get(callingPid);
+ if (app == null) {
+ throw new SecurityException("Unknown process: " + callingPid);
+ }
+
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ app.appNotResponding(
+ null, app.info, null, null, false, "App requested: " + reason);
+ }
+ });
+ }
+ }
+
public final void installSystemProviders() {
List<ProviderInfo> providers;
synchronized (this) {
@@ -9379,9 +9390,9 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
- void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
+ void killAppAtUsersRequest(ProcessRecord app) {
synchronized (this) {
- mAppErrors.killAppAtUserRequestLocked(app, fromDialog);
+ mAppErrors.killAppAtUserRequestLocked(app);
}
}
@@ -13060,14 +13071,31 @@ public class ActivityManagerService extends IActivityManager.Stub
pw.println(totalPss - cachedPss);
}
}
- long lostRAM = memInfo.getTotalSizeKb() - (totalPss - totalSwapPss)
+ long kernelUsed = memInfo.getKernelUsedSizeKb();
+ final long ionHeap = Debug.getIonHeapsSizeKb();
+ if (ionHeap > 0) {
+ final long ionMapped = Debug.getIonMappedSizeKb();
+ final long ionUnmapped = ionHeap - ionMapped;
+ final long ionPool = Debug.getIonPoolsSizeKb();
+ pw.print(" ION: ");
+ pw.print(stringifyKBSize(ionHeap + ionPool));
+ pw.print(" (");
+ pw.print(stringifyKBSize(ionMapped));
+ pw.print(" mapped + ");
+ pw.print(stringifyKBSize(ionUnmapped));
+ pw.print(" unmapped + ");
+ pw.print(stringifyKBSize(ionPool));
+ pw.println(" pools)");
+ kernelUsed += ionUnmapped;
+ }
+ final long lostRAM = memInfo.getTotalSizeKb() - (totalPss - totalSwapPss)
- memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()
- - memInfo.getKernelUsedSizeKb() - memInfo.getZramTotalSizeKb();
+ - kernelUsed - memInfo.getZramTotalSizeKb();
if (!opts.isCompact) {
pw.print(" Used RAM: "); pw.print(stringifyKBSize(totalPss - cachedPss
- + memInfo.getKernelUsedSizeKb())); pw.print(" (");
+ + kernelUsed)); pw.print(" (");
pw.print(stringifyKBSize(totalPss - cachedPss)); pw.print(" used pss + ");
- pw.print(stringifyKBSize(memInfo.getKernelUsedSizeKb())); pw.print(" kernel)\n");
+ pw.print(stringifyKBSize(kernelUsed)); pw.print(" kernel)\n");
pw.print(" Lost RAM: "); pw.println(stringifyKBSize(lostRAM));
} else {
pw.print("lostram,"); pw.println(lostRAM);
@@ -13833,14 +13861,25 @@ public class ActivityManagerService extends IActivityManager.Stub
memInfoBuilder.append(stringifyKBSize(cachedPss + memInfo.getCachedSizeKb()
+ memInfo.getFreeSizeKb()));
memInfoBuilder.append("\n");
+ long kernelUsed = memInfo.getKernelUsedSizeKb();
+ final long ionHeap = Debug.getIonHeapsSizeKb();
+ if (ionHeap > 0) {
+ final long ionMapped = Debug.getIonMappedSizeKb();
+ final long ionUnmapped = ionHeap - ionMapped;
+ final long ionPool = Debug.getIonPoolsSizeKb();
+ memInfoBuilder.append(" ION: ");
+ memInfoBuilder.append(stringifyKBSize(ionHeap + ionPool));
+ memInfoBuilder.append("\n");
+ kernelUsed += ionUnmapped;
+ }
memInfoBuilder.append(" Used RAM: ");
memInfoBuilder.append(stringifyKBSize(
- totalPss - cachedPss + memInfo.getKernelUsedSizeKb()));
+ totalPss - cachedPss + kernelUsed));
memInfoBuilder.append("\n");
memInfoBuilder.append(" Lost RAM: ");
memInfoBuilder.append(stringifyKBSize(memInfo.getTotalSizeKb()
- (totalPss - totalSwapPss) - memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()
- - memInfo.getKernelUsedSizeKb() - memInfo.getZramTotalSizeKb()));
+ - kernelUsed - memInfo.getZramTotalSizeKb()));
memInfoBuilder.append("\n");
Slog.i(TAG, "Low on memory:");
Slog.i(TAG, shortNativeBuilder.toString());
@@ -14006,18 +14045,7 @@ public class ActivityManagerService extends IActivityManager.Stub
ProcessList.abortNextPssTime(app.procStateMemTracker);
// Dismiss any open dialogs.
- if (app.crashDialog != null && !app.forceCrashReport) {
- app.crashDialog.dismiss();
- app.crashDialog = null;
- }
- if (app.anrDialog != null) {
- app.anrDialog.dismiss();
- app.anrDialog = null;
- }
- if (app.waitDialog != null) {
- app.waitDialog.dismiss();
- app.waitDialog = null;
- }
+ app.getDialogController().clearAllErrorDialogs();
app.setCrashing(false);
app.setNotResponding(false);
diff --git a/services/core/java/com/android/server/am/AppErrorDialog.java b/services/core/java/com/android/server/am/AppErrorDialog.java
index 852c9b65e3c0..d76e2d712ad9 100644
--- a/services/core/java/com/android/server/am/AppErrorDialog.java
+++ b/services/core/java/com/android/server/am/AppErrorDialog.java
@@ -167,8 +167,10 @@ final class AppErrorDialog extends BaseErrorDialog implements View.OnClickListen
private void setResult(int result) {
synchronized (mService) {
- if (mProc != null && mProc.crashDialog == AppErrorDialog.this) {
- mProc.crashDialog = null;
+ if (mProc != null) {
+ // Don't dismiss again since it leads to recursive call between dismiss and this
+ // method.
+ mProc.getDialogController().clearCrashDialogs(false /* needDismiss */);
}
}
mResult.set(result);
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index 83a7341923fa..c38072661cee 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -29,7 +29,6 @@ import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_N
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.ApplicationErrorReport;
-import android.app.Dialog;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
@@ -313,13 +312,8 @@ class AppErrors {
}
}
- void killAppAtUserRequestLocked(ProcessRecord app, Dialog fromDialog) {
- if (app.anrDialog == fromDialog) {
- app.anrDialog = null;
- }
- if (app.waitDialog == fromDialog) {
- app.waitDialog = null;
- }
+ void killAppAtUserRequestLocked(ProcessRecord app) {
+ app.getDialogController().clearAllErrorDialogs();
killAppImmediateLocked(app, "user-terminated", "user request after error");
}
@@ -795,7 +789,6 @@ class AppErrors {
boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
- AppErrorDialog dialogToShow = null;
final String packageName;
final int userId;
synchronized (mService) {
@@ -807,7 +800,7 @@ class AppErrors {
}
packageName = proc.info.packageName;
userId = proc.userId;
- if (proc.crashDialog != null) {
+ if (proc.getDialogController().hasCrashDialogs()) {
Slog.e(TAG, "App already has crash dialog: " + proc);
if (res != null) {
res.set(AppErrorDialog.ALREADY_SHOWING);
@@ -840,7 +833,7 @@ class AppErrors {
if ((mService.mAtmInternal.canShowErrorDialogs() || showBackground)
&& !crashSilenced
&& (showFirstCrash || showFirstCrashDevOption || data.repeating)) {
- proc.crashDialog = dialogToShow = new AppErrorDialog(mContext, mService, data);
+ proc.getDialogController().showCrashDialogs(data);
} else {
// The device is asleep, so just pretend that the user
// saw a crash dialog and hit "force quit".
@@ -849,11 +842,6 @@ class AppErrors {
}
}
}
- // If we've created a crash dialog, show it without the lock held
- if (dialogToShow != null) {
- Slog.i(TAG, "Showing crash dialog for package " + packageName + " u" + userId);
- dialogToShow.show();
- }
}
private void stopReportingCrashesLocked(ProcessRecord proc) {
@@ -864,7 +852,6 @@ class AppErrors {
}
void handleShowAnrUi(Message msg) {
- Dialog dialogToShow = null;
List<VersionedPackage> packageList = null;
synchronized (mService) {
AppNotRespondingDialog.Data data = (AppNotRespondingDialog.Data) msg.obj;
@@ -876,7 +863,7 @@ class AppErrors {
if (!proc.isPersistent()) {
packageList = proc.getPackageListWithVersionCode();
}
- if (proc.anrDialog != null) {
+ if (proc.getDialogController().hasAnrDialogs()) {
Slog.e(TAG, "App already has anr dialog: " + proc);
MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR,
AppNotRespondingDialog.ALREADY_SHOWING);
@@ -886,19 +873,14 @@ class AppErrors {
boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
if (mService.mAtmInternal.canShowErrorDialogs() || showBackground) {
- dialogToShow = new AppNotRespondingDialog(mService, mContext, data);
- proc.anrDialog = dialogToShow;
+ proc.getDialogController().showAnrDialogs(data);
} else {
MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR,
AppNotRespondingDialog.CANT_SHOW);
// Just kill the app if there is no dialog to be shown.
- mService.killAppAtUsersRequest(proc, null);
+ mService.killAppAtUsersRequest(proc);
}
}
- // If we've created a crash dialog, show it without the lock held
- if (dialogToShow != null) {
- dialogToShow.show();
- }
// Notify PackageWatchdog without the lock held
if (packageList != null) {
mPackageWatchdog.onPackageFailure(packageList,
diff --git a/services/core/java/com/android/server/am/AppNotRespondingDialog.java b/services/core/java/com/android/server/am/AppNotRespondingDialog.java
index 65d7e01a3e0c..dac5325f239d 100644
--- a/services/core/java/com/android/server/am/AppNotRespondingDialog.java
+++ b/services/core/java/com/android/server/am/AppNotRespondingDialog.java
@@ -16,13 +16,10 @@
package com.android.server.am;
-import android.content.pm.ApplicationInfo;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto;
-
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ApplicationInfo;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.Handler;
@@ -35,6 +32,9 @@ import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.TextView;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto;
+
final class AppNotRespondingDialog extends BaseErrorDialog implements View.OnClickListener {
private static final String TAG = "AppNotRespondingDialog";
@@ -145,7 +145,7 @@ final class AppNotRespondingDialog extends BaseErrorDialog implements View.OnCli
switch (msg.what) {
case FORCE_CLOSE:
// Kill the application.
- mService.killAppAtUsersRequest(mProc, AppNotRespondingDialog.this);
+ mService.killAppAtUsersRequest(mProc);
break;
case WAIT_AND_REPORT:
case WAIT:
@@ -160,9 +160,7 @@ final class AppNotRespondingDialog extends BaseErrorDialog implements View.OnCli
app.setNotResponding(false);
app.notRespondingReport = null;
- if (app.anrDialog == AppNotRespondingDialog.this) {
- app.anrDialog = null;
- }
+ app.getDialogController().clearAnrDialogs();
mService.mServices.scheduleServiceTimeoutLocked(app);
}
break;
diff --git a/services/core/java/com/android/server/am/AppWaitingForDebuggerDialog.java b/services/core/java/com/android/server/am/AppWaitingForDebuggerDialog.java
index 27865a88da99..3ce24712b42f 100644
--- a/services/core/java/com/android/server/am/AppWaitingForDebuggerDialog.java
+++ b/services/core/java/com/android/server/am/AppWaitingForDebuggerDialog.java
@@ -66,7 +66,7 @@ final class AppWaitingForDebuggerDialog extends BaseErrorDialog {
switch (msg.what) {
case 1:
// Kill the application.
- mService.killAppAtUsersRequest(mProc, AppWaitingForDebuggerDialog.this);
+ mService.killAppAtUsersRequest(mProc);
break;
}
}
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 5378f438fea5..a1e1f29016c2 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -59,6 +59,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
+import android.content.pm.PackageManagerInternal;
import android.content.res.Resources;
import android.graphics.Point;
import android.os.AppZygote;
@@ -78,6 +79,7 @@ import android.os.Trace;
import android.os.UserHandle;
import android.os.storage.StorageManager;
import android.os.storage.StorageManagerInternal;
+import android.provider.DeviceConfig;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
@@ -85,6 +87,7 @@ import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.EventLog;
import android.util.LongSparseArray;
+import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
@@ -117,6 +120,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.List;
+import java.util.Map;
/**
* Activity manager code dealing with processes.
@@ -124,6 +128,13 @@ import java.util.List;
public final class ProcessList {
static final String TAG = TAG_WITH_CLASS_NAME ? "ProcessList" : TAG_AM;
+ // A device config to control the minimum target SDK to enable app data isolation
+ static final String ANDROID_APP_DATA_ISOLATION_ENABLED_PROPERTY =
+ "persist.zygote.app_data_isolation";
+
+ // A device config to control the minimum target SDK to enable app data isolation
+ static final String ANDROID_APP_DATA_ISOLATION_MIN_SDK = "android_app_data_isolation_min_sdk";
+
// The minimum time we allow between crashes, for us to consider this
// application to be bad and stop and its services and reject broadcasts.
static final int MIN_CRASH_INTERVAL = 60 * 1000;
@@ -271,20 +282,27 @@ public final class ProcessList {
"persist.device_config.runtime_native.use_app_image_startup_cache";
// Low Memory Killer Daemon command codes.
- // These must be kept in sync with the definitions in lmkd.c
+ // These must be kept in sync with lmk_cmd definitions in lmkd.h
//
// LMK_TARGET <minfree> <minkillprio> ... (up to 6 pairs)
// LMK_PROCPRIO <pid> <uid> <prio>
// LMK_PROCREMOVE <pid>
// LMK_PROCPURGE
// LMK_GETKILLCNT
+ // LMK_SUBSCRIBE
// LMK_PROCKILL
static final byte LMK_TARGET = 0;
static final byte LMK_PROCPRIO = 1;
static final byte LMK_PROCREMOVE = 2;
static final byte LMK_PROCPURGE = 3;
static final byte LMK_GETKILLCNT = 4;
- static final byte LMK_PROCKILL = 5; // Note: this is an unsolicated command
+ static final byte LMK_SUBSCRIBE = 5;
+ static final byte LMK_PROCKILL = 6; // Note: this is an unsolicated command
+
+ // Low Memory Killer Daemon command codes.
+ // These must be kept in sync with async_event_type definitions in lmkd.h
+ //
+ static final int LMK_ASYNC_EVENT_KILL = 0;
// lmkd reconnect delay in msecs
private static final long LMKD_RECONNECT_DELAY_MS = 1000;
@@ -337,6 +355,8 @@ public final class ProcessList {
private boolean mOomLevelsSet = false;
+ private boolean mAppDataIsolationEnabled = false;
+
/**
* Temporary to avoid allocations. Protected by main lock.
*/
@@ -461,9 +481,7 @@ public final class ProcessList {
@GuardedBy("ProcessList.this.mService")
void freeIsolatedUidLocked(int uid) {
- // Strip out userId
- final int appId = UserHandle.getAppId(uid);
- mUidUsed.delete(appId);
+ mUidUsed.delete(uid);
}
};
@@ -623,6 +641,10 @@ public final class ProcessList {
mService = service;
mActiveUids = activeUids;
mPlatformCompat = platformCompat;
+ // Get this after boot, and won't be changed until it's rebooted, as we don't
+ // want some apps enabled while some apps disabled
+ mAppDataIsolationEnabled =
+ SystemProperties.getBoolean(ANDROID_APP_DATA_ISOLATION_ENABLED_PROPERTY, false);
if (sKillHandler == null) {
sKillThread = new ServiceThread(TAG + ":kill",
@@ -1339,6 +1361,11 @@ public final class ProcessList {
}
ostream.write(buf.array(), 0, buf.position());
}
+ // Subscribe for kill event notifications
+ buf = ByteBuffer.allocate(4 * 2);
+ buf.putInt(LMK_SUBSCRIBE);
+ buf.putInt(LMK_ASYNC_EVENT_KILL);
+ ostream.write(buf.array(), 0, buf.position());
} catch (IOException ex) {
return false;
}
@@ -1855,6 +1882,32 @@ public final class ProcessList {
}
}
+ private boolean shouldIsolateAppData(ProcessRecord app) {
+ if (!mAppDataIsolationEnabled) {
+ return false;
+ }
+ if (!UserHandle.isApp(app.uid)) {
+ return false;
+ }
+ final int minTargetSdk = DeviceConfig.getInt(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+ ANDROID_APP_DATA_ISOLATION_MIN_SDK, Build.VERSION_CODES.R);
+ return app.info.targetSdkVersion >= minTargetSdk;
+ }
+
+ private Map<String, Pair<String, Long>> getPackageAppDataInfoMap(PackageManagerInternal pmInt,
+ String[] packages, int uid) {
+ Map<String, Pair<String, Long>> result = new ArrayMap<>(packages.length);
+ int userId = UserHandle.getUserId(uid);
+ for (String packageName : packages) {
+ String volumeUuid = pmInt.getPackage(packageName).getVolumeUuid();
+ long inode = pmInt.getCeDataInode(packageName, userId);
+ if (inode != 0) {
+ result.put(packageName, Pair.create(volumeUuid, inode));
+ }
+ }
+ return result;
+ }
+
private Process.ProcessStartResult startProcess(HostingRecord hostingRecord, String entryPoint,
ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
String seInfo, String requiredAbi, String instructionSet, String invokeWith,
@@ -1871,6 +1924,20 @@ public final class ProcessList {
app.setHasForegroundActivities(true);
}
+ final Map<String, Pair<String, Long>> pkgDataInfoMap;
+
+ if (shouldIsolateAppData(app)) {
+ // Get all packages belongs to the same shared uid. sharedPackages is empty array
+ // if it doesn't have shared uid.
+ final PackageManagerInternal pmInt = mService.getPackageManagerInternalLocked();
+ final String[] sharedPackages = pmInt.getSharedUserPackagesForPackage(
+ app.info.packageName, app.userId);
+ pkgDataInfoMap = getPackageAppDataInfoMap(pmInt, sharedPackages.length == 0
+ ? new String[]{app.info.packageName} : sharedPackages, uid);
+ } else {
+ pkgDataInfoMap = null;
+ }
+
final Process.ProcessStartResult startResult;
if (hostingRecord.usesWebviewZygote()) {
startResult = startWebView(entryPoint,
@@ -1886,13 +1953,13 @@ public final class ProcessList {
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, null, app.info.packageName,
/*useUsapPool=*/ false, isTopApp, app.mDisabledCompatChanges,
- new String[]{PROC_START_SEQ_IDENT + app.startSeq});
+ pkgDataInfoMap, new String[]{PROC_START_SEQ_IDENT + app.startSeq});
} else {
startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, invokeWith, app.info.packageName, isTopApp,
- app.mDisabledCompatChanges,
+ app.mDisabledCompatChanges, pkgDataInfoMap,
new String[]{PROC_START_SEQ_IDENT + app.startSeq});
}
checkSlow(startTime, "startProcess: returned from zygote!");
@@ -2034,6 +2101,10 @@ public final class ProcessList {
*/
@GuardedBy("mService")
private boolean isProcessAliveLiteLocked(ProcessRecord app) {
+ // If somehow the pid is invalid, let's think it's dead.
+ if (app.pid <= 0) {
+ return false;
+ }
try {
Os.kill(app.pid, 0);
} catch (ErrnoException e) {
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 24fc743e0a08..1fef3538165a 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -62,6 +62,8 @@ import com.android.internal.app.procstats.ProcessStats;
import com.android.internal.os.BatteryStatsImpl;
import com.android.internal.os.ProcessCpuTracker;
import com.android.internal.os.Zygote;
+import com.android.server.LocalServices;
+import com.android.server.wm.WindowManagerInternal;
import com.android.server.wm.WindowProcessController;
import com.android.server.wm.WindowProcessListener;
@@ -70,6 +72,7 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.function.Consumer;
/**
* Full information about a particular process that
@@ -246,6 +249,8 @@ class ProcessRecord implements WindowProcessListener {
Debug.MemoryInfo lastMemInfo;
long lastMemInfoTime;
+ // Controller for error dialogs
+ private final ErrorDialogController mDialogController = new ErrorDialogController();
// Controller for driving the process state on the window manager side.
final private WindowProcessController mWindowProcessController;
// all ServiceRecord running in this process
@@ -272,16 +277,13 @@ class ProcessRecord implements WindowProcessListener {
boolean execServicesFg; // do we need to be executing services in the foreground?
private boolean mPersistent;// always keep this application running?
private boolean mCrashing; // are we in the process of crashing?
- Dialog crashDialog; // dialog being displayed due to crash.
boolean forceCrashReport; // suppress normal auto-dismiss of crash dialog & report UI?
private boolean mNotResponding; // does the app have a not responding dialog?
- Dialog anrDialog; // dialog being displayed due to app not resp.
volatile boolean removed; // Whether this process should be killed and removed from process
// list. It is set when the package is force-stopped or the process
// has crashed too many times.
private boolean mDebugging; // was app launched for debugging?
boolean waitedForDebugger; // has process show wait for debugger dialog?
- Dialog waitDialog; // current wait for debugger dialog
String shortStringName; // caching of toShortString() result.
String stringName; // caching of toString() result.
@@ -518,21 +520,21 @@ class ProcessRecord implements WindowProcessListener {
pw.print(" killedByAm="); pw.print(killedByAm);
pw.print(" waitingToKill="); pw.println(waitingToKill);
}
- if (mDebugging || mCrashing || crashDialog != null || mNotResponding
- || anrDialog != null || bad) {
+ if (mDebugging || mCrashing || mDialogController.hasCrashDialogs() || mNotResponding
+ || mDialogController.hasAnrDialogs() || bad) {
pw.print(prefix); pw.print("mDebugging="); pw.print(mDebugging);
- pw.print(" mCrashing="); pw.print(mCrashing);
- pw.print(" "); pw.print(crashDialog);
- pw.print(" mNotResponding="); pw.print(mNotResponding);
- pw.print(" " ); pw.print(anrDialog);
- pw.print(" bad="); pw.print(bad);
-
- // mCrashing or mNotResponding is always set before errorReportReceiver
- if (errorReportReceiver != null) {
- pw.print(" errorReportReceiver=");
- pw.print(errorReportReceiver.flattenToShortString());
- }
- pw.println();
+ pw.print(" mCrashing=" + mCrashing);
+ pw.print(" " + mDialogController.mCrashDialogs);
+ pw.print(" mNotResponding=" + mNotResponding);
+ pw.print(" " + mDialogController.mAnrDialogs);
+ pw.print(" bad=" + bad);
+
+ // mCrashing or mNotResponding is always set before errorReportReceiver
+ if (errorReportReceiver != null) {
+ pw.print(" errorReportReceiver=");
+ pw.print(errorReportReceiver.flattenToShortString());
+ }
+ pw.println();
}
if (whitelistManager) {
pw.print(prefix); pw.print("whitelistManager="); pw.println(whitelistManager);
@@ -1775,4 +1777,153 @@ class ProcessRecord implements WindowProcessListener {
mCachedAdj += minLayer;
}
}
+
+ ErrorDialogController getDialogController() {
+ return mDialogController;
+ }
+
+ /** A controller to generate error dialogs in {@link ProcessRecord} */
+ class ErrorDialogController {
+ /** dialogs being displayed due to crash */
+ private List<AppErrorDialog> mCrashDialogs;
+ /** dialogs being displayed due to app not responding */
+ private List<AppNotRespondingDialog> mAnrDialogs;
+ /** dialogs displayed due to strict mode violation */
+ private List<StrictModeViolationDialog> mViolationDialogs;
+ /** current wait for debugger dialog */
+ private AppWaitingForDebuggerDialog mWaitDialog;
+
+ private final WindowManagerInternal mWmInternal =
+ LocalServices.getService(WindowManagerInternal.class);
+
+ boolean hasCrashDialogs() {
+ return mCrashDialogs != null;
+ }
+
+ boolean hasAnrDialogs() {
+ return mAnrDialogs != null;
+ }
+
+ boolean hasViolationDialogs() {
+ return mViolationDialogs != null;
+ }
+
+ boolean hasDebugWaitingDialog() {
+ return mWaitDialog != null;
+ }
+
+ void clearAllErrorDialogs() {
+ clearCrashDialogs();
+ clearAnrDialogs();
+ clearViolationDialogs();
+ clearWaitingDialog();
+ }
+
+ void clearCrashDialogs() {
+ clearCrashDialogs(true /* needDismiss */);
+ }
+
+ void clearCrashDialogs(boolean needDismiss) {
+ if (mCrashDialogs == null) {
+ return;
+ }
+ if (needDismiss) {
+ forAllDialogs(mCrashDialogs, Dialog::dismiss);
+ }
+ mCrashDialogs = null;
+ }
+
+ void clearAnrDialogs() {
+ if (mAnrDialogs == null) {
+ return;
+ }
+ forAllDialogs(mAnrDialogs, Dialog::dismiss);
+ mAnrDialogs = null;
+ }
+
+ void clearViolationDialogs() {
+ if (mViolationDialogs == null) {
+ return;
+ }
+ forAllDialogs(mViolationDialogs, Dialog::dismiss);
+ mViolationDialogs = null;
+ }
+
+ void clearWaitingDialog() {
+ if (mWaitDialog == null) {
+ return;
+ }
+ mWaitDialog.dismiss();
+ mWaitDialog = null;
+ }
+
+ void forAllDialogs(List<? extends BaseErrorDialog> dialogs,
+ Consumer<BaseErrorDialog> c) {
+ for (int i = dialogs.size() - 1; i >= 0; i--) {
+ c.accept(dialogs.get(i));
+ }
+ }
+
+ void showCrashDialogs(AppErrorDialog.Data data) {
+ List<Context> contexts = getDisplayContexts(false /* lastUsedOnly */);
+ mCrashDialogs = new ArrayList<>();
+
+ for (int i = contexts.size() - 1; i >= 0; i--) {
+ final Context c = contexts.get(i);
+ mCrashDialogs.add(new AppErrorDialog(c, mService, data));
+ }
+ mService.mUiHandler.post(() -> mCrashDialogs.forEach(Dialog::show));
+ }
+
+ void showAnrDialogs(AppNotRespondingDialog.Data data) {
+ List<Context> contexts = getDisplayContexts(isSilentAnr() /* lastUsedOnly */);
+ mAnrDialogs = new ArrayList<>();
+
+ for (int i = contexts.size() - 1; i >= 0; i--) {
+ final Context c = contexts.get(i);
+ mAnrDialogs.add(new AppNotRespondingDialog(mService, c, data));
+ }
+ mService.mUiHandler.post(() -> mAnrDialogs.forEach(Dialog::show));
+ }
+
+ void showViolationDialogs(AppErrorResult res) {
+ List<Context> contexts = getDisplayContexts(false /* lastUsedOnly */);
+ mViolationDialogs = new ArrayList<>();
+
+ for (int i = contexts.size() - 1; i >= 0; i--) {
+ final Context c = contexts.get(i);
+ mViolationDialogs.add(
+ new StrictModeViolationDialog(c, mService, res, ProcessRecord.this));
+ }
+ mService.mUiHandler.post(() -> mViolationDialogs.forEach(Dialog::show));
+ }
+
+ void showDebugWaitingDialogs() {
+ List<Context> contexts = getDisplayContexts(true /* lastUsedOnly */);
+ final Context c = contexts.get(0);
+ mWaitDialog = new AppWaitingForDebuggerDialog(mService, c, ProcessRecord.this);
+ mService.mUiHandler.post(() -> mWaitDialog.show());
+ }
+
+ /**
+ * Helper function to collect contexts from crashed app located displays
+ *
+ * @param lastUsedOnly Sets to {@code true} to indicate to only get last used context.
+ * Sets to {@code false} to collect contexts from crashed app located
+ * displays.
+ *
+ * @return display context list
+ */
+ private List<Context> getDisplayContexts(boolean lastUsedOnly) {
+ List<Context> displayContexts = new ArrayList<>();
+ if (!lastUsedOnly) {
+ mWindowProcessController.getDisplayContextsWithErrorDialogs(displayContexts);
+ }
+ // If there is no foreground window display, fallback to last used display.
+ if (displayContexts.isEmpty() || lastUsedOnly) {
+ displayContexts.add(mWmInternal.getTopFocusedDisplayUiContext());
+ }
+ return displayContexts;
+ }
+ }
}
diff --git a/services/core/java/com/android/server/am/StrictModeViolationDialog.java b/services/core/java/com/android/server/am/StrictModeViolationDialog.java
index 6da84bd589fc..783f150a5e94 100644
--- a/services/core/java/com/android/server/am/StrictModeViolationDialog.java
+++ b/services/core/java/com/android/server/am/StrictModeViolationDialog.java
@@ -85,8 +85,8 @@ final class StrictModeViolationDialog extends BaseErrorDialog {
private final Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
synchronized (mService) {
- if (mProc != null && mProc.crashDialog == StrictModeViolationDialog.this) {
- mProc.crashDialog = null;
+ if (mProc != null) {
+ mProc.getDialogController().clearViolationDialogs();
}
}
mResult.set(msg.what);
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 728291d6c785..f9730a9cc3f5 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -407,6 +407,7 @@ class UserController implements Handler.Callback {
*/
private boolean finishUserUnlocking(final UserState uss) {
final int userId = uss.mHandle.getIdentifier();
+ Slog.d(TAG, "UserController event: finishUserUnlocking(" + userId + ")");
// Only keep marching forward if user is actually unlocked
if (!StorageManager.isUserKeyUnlocked(userId)) return false;
synchronized (mLock) {
@@ -451,6 +452,7 @@ class UserController implements Handler.Callback {
*/
void finishUserUnlocked(final UserState uss) {
final int userId = uss.mHandle.getIdentifier();
+ Slog.d(TAG, "UserController event: finishUserUnlocked(" + userId + ")");
// Only keep marching forward if user is actually unlocked
if (!StorageManager.isUserKeyUnlocked(userId)) return;
synchronized (mLock) {
@@ -521,6 +523,7 @@ class UserController implements Handler.Callback {
private void finishUserUnlockedCompleted(UserState uss) {
final int userId = uss.mHandle.getIdentifier();
+ Slog.d(TAG, "UserController event: finishUserUnlockedCompleted(" + userId + ")");
synchronized (mLock) {
// Bail if we ended up with a stale user
if (mStartedUsers.get(uss.mHandle.getIdentifier()) != uss) return;
@@ -730,6 +733,7 @@ class UserController implements Handler.Callback {
}
void finishUserStopping(final int userId, final UserState uss) {
+ Slog.d(TAG, "UserController event: finishUserStopping(" + userId + ")");
// On to the next.
final Intent shutdownIntent = new Intent(Intent.ACTION_SHUTDOWN);
// This is the result receiver for the final shutdown broadcast.
@@ -769,6 +773,7 @@ class UserController implements Handler.Callback {
void finishUserStopped(UserState uss) {
final int userId = uss.mHandle.getIdentifier();
+ Slog.d(TAG, "UserController event: finishUserStopped(" + userId + ")");
final boolean stopped;
boolean lockUser = true;
final ArrayList<IStopUserCallback> stopCallbacks;
@@ -1280,6 +1285,7 @@ class UserController implements Handler.Callback {
boolean unlockUser(final @UserIdInt int userId, byte[] token, byte[] secret,
IProgressListener listener) {
checkCallingPermission(INTERACT_ACROSS_USERS_FULL, "unlockUser");
+ Slog.i(TAG, "unlocking user " + userId);
final long binderToken = Binder.clearCallingIdentity();
try {
return unlockUserCleared(userId, token, secret, listener);
@@ -1364,6 +1370,7 @@ class UserController implements Handler.Callback {
boolean switchUser(final int targetUserId) {
enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, targetUserId);
+ Slog.i(TAG, "switching to user " + targetUserId);
int currentUserId = getCurrentUserId();
UserInfo targetUserInfo = getUserInfo(targetUserId);
if (targetUserId == currentUserId) {
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 14f96540bc6a..8c9bff937831 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -17,11 +17,12 @@
package com.android.server.appop;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION;
-import static android.app.AppOpsManager.MAX_PRIORITY_UID_STATE;
-import static android.app.AppOpsManager.MIN_PRIORITY_UID_STATE;
+import static android.app.AppOpsManager.NoteOpEvent;
+import static android.app.AppOpsManager.OpEventProxyInfo;
import static android.app.AppOpsManager.OP_CAMERA;
import static android.app.AppOpsManager.OP_COARSE_LOCATION;
import static android.app.AppOpsManager.OP_FLAGS_ALL;
+import static android.app.AppOpsManager.OP_FLAG_SELF;
import static android.app.AppOpsManager.OP_NONE;
import static android.app.AppOpsManager.OP_PLAY_AUDIO;
import static android.app.AppOpsManager.OP_RECORD_AUDIO;
@@ -33,6 +34,9 @@ import static android.app.AppOpsManager.UID_STATE_MAX_LAST_NON_RESTRICTED;
import static android.app.AppOpsManager.UID_STATE_PERSISTENT;
import static android.app.AppOpsManager.UID_STATE_TOP;
import static android.app.AppOpsManager._NUM_OP;
+import static android.app.AppOpsManager.extractFlagsFromKey;
+import static android.app.AppOpsManager.extractUidStateFromKey;
+import static android.app.AppOpsManager.makeKey;
import static android.app.AppOpsManager.modeToName;
import static android.app.AppOpsManager.opToName;
import static android.app.AppOpsManager.resolveFirstUnrestrictedUidState;
@@ -93,7 +97,6 @@ import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.KeyValueListParser;
import android.util.LongSparseArray;
-import android.util.LongSparseLongArray;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
@@ -365,8 +368,6 @@ public class AppOpsService extends IAppOpsService.Stub {
public long pendingStateCommitTime;
public int capability;
public int pendingCapability;
- // For all features combined
- public int startNesting;
public ArrayMap<String, Ops> pkgOps;
public SparseIntArray opModes;
@@ -474,126 +475,324 @@ public class AppOpsService extends IAppOpsService.Stub {
}
}
- private static final class FeatureOp {
+ /** A in progress startOp->finishOp event */
+ private static final class InProgressStartOpEvent implements IBinder.DeathRecipient {
+ /** Wall clock time of startOp event (not monotonic) */
+ final long startTime;
+
+ /** Elapsed time since boot of startOp event */
+ final long startElapsedTime;
+
+ /** Id of the client that started the event */
+ final @NonNull IBinder clientId;
+
+ /** To call when client dies */
+ final @NonNull Runnable onDeath;
+
+ /** uidstate used when calling startOp */
+ final @AppOpsManager.UidState int uidState;
+
+ /** How many times the op was started but not finished yet */
+ int numUnfinishedStarts;
+
+ private InProgressStartOpEvent(long startTime, long startElapsedTime,
+ @NonNull IBinder clientId, @NonNull Runnable onDeath, int uidState)
+ throws RemoteException {
+ this.startTime = startTime;
+ this.startElapsedTime = startElapsedTime;
+ this.clientId = clientId;
+ this.onDeath = onDeath;
+ this.uidState = uidState;
+
+ clientId.linkToDeath(this, 0);
+ }
+
+ /** Clean up event */
+ public void finish() {
+ clientId.unlinkToDeath(this, 0);
+ }
+
+ @Override
+ public void binderDied() {
+ onDeath.run();
+ }
+ }
+
+ private final class FeatureOp {
public final @NonNull Op parent;
- public boolean running;
+ /**
+ * Last successful accesses (noteOp + finished startOp) for each uidState/opFlag combination
+ *
+ * <p>Key is {@link AppOpsManager#makeKey}
+ */
+ @GuardedBy("AppOpsService.this")
+ private @Nullable LongSparseArray<AppOpsManager.NoteOpEvent> mAccessEvents;
- private @Nullable LongSparseLongArray mAccessTimes;
- private @Nullable LongSparseLongArray mRejectTimes;
- private @Nullable LongSparseLongArray mDurations;
- private @Nullable LongSparseLongArray mProxyUids;
- private @Nullable LongSparseArray<String> mProxyFeatureIds;
- private @Nullable LongSparseArray<String> mProxyPackageNames;
+ /**
+ * Last rejected accesses for each uidState/opFlag combination
+ *
+ * <p>Key is {@link AppOpsManager#makeKey}
+ */
+ @GuardedBy("AppOpsService.this")
+ private @Nullable LongSparseArray<AppOpsManager.NoteOpEvent> mRejectEvents;
- public int startNesting;
- public long startRealtime;
+ /**
+ * Currently in progress startOp events
+ *
+ * <p>Key is clientId
+ */
+ @GuardedBy("AppOpsService.this")
+ private @Nullable ArrayMap<IBinder, InProgressStartOpEvent> mInProgressEvents;
FeatureOp(@NonNull Op parent) {
this.parent = parent;
}
- public void accessed(long time, int proxyUid, @Nullable String proxyPackageName,
+ /**
+ * Update state when noteOp was rejected or startOp->finishOp event finished
+ *
+ * @param proxyUid The uid of the proxy
+ * @param proxyPackageName The package name of the proxy
+ * @param proxyFeatureId the featureId in the proxies package
+ * @param uidState UID state of the app noteOp/startOp was called for
+ * @param flags OpFlags of the call
+ */
+ public void accessed(int proxyUid, @Nullable String proxyPackageName,
@Nullable String proxyFeatureId, @AppOpsManager.UidState int uidState,
@OpFlags int flags) {
- final long key = AppOpsManager.makeKey(uidState, flags);
- if (mAccessTimes == null) {
- mAccessTimes = new LongSparseLongArray();
- }
- mAccessTimes.put(key, time);
- updateProxyState(key, proxyUid, proxyPackageName, proxyFeatureId);
- if (mDurations != null) {
- mDurations.delete(key);
- }
+ accessed(System.currentTimeMillis(), -1, proxyUid, proxyPackageName,
+ proxyFeatureId, uidState, flags);
}
- public void rejected(long time, int proxyUid, @Nullable String proxyPackageName,
- @Nullable String proxyFeatureId, @AppOpsManager.UidState int uidState,
- @OpFlags int flags) {
- final long key = AppOpsManager.makeKey(uidState, flags);
- if (mRejectTimes == null) {
- mRejectTimes = new LongSparseLongArray();
+ /**
+ * Add an access that was previously collected.
+ *
+ * @param noteTime The time of the event
+ * @param duration The duration of the event
+ * @param proxyUid The uid of the proxy
+ * @param proxyPackageName The package name of the proxy
+ * @param proxyFeatureId the featureId in the proxies package
+ * @param uidState UID state of the app noteOp/startOp was called for
+ * @param flags OpFlags of the call
+ */
+ public void accessed(long noteTime, long duration, int proxyUid,
+ @Nullable String proxyPackageName, @Nullable String proxyFeatureId,
+ @AppOpsManager.UidState int uidState, @OpFlags int flags) {
+ long key = makeKey(uidState, flags);
+
+ if (mAccessEvents == null) {
+ mAccessEvents = new LongSparseArray<>(1);
}
- mRejectTimes.put(key, time);
- updateProxyState(key, proxyUid, proxyPackageName, proxyFeatureId);
- if (mDurations != null) {
- mDurations.delete(key);
+
+ OpEventProxyInfo proxyInfo = null;
+ if (proxyUid != Process.INVALID_UID) {
+ proxyInfo = new OpEventProxyInfo(proxyUid, proxyPackageName, proxyFeatureId);
}
+ mAccessEvents.put(key, new NoteOpEvent(noteTime, duration, proxyInfo));
}
- public void started(long time, @AppOpsManager.UidState int uidState, @OpFlags int flags) {
- updateAccessTimeAndDuration(time, -1 /*duration*/, uidState, flags);
- running = true;
+ /**
+ * Update state when noteOp/startOp was rejected.
+ *
+ * @param uidState UID state of the app noteOp is called for
+ * @param flags OpFlags of the call
+ */
+ public void rejected(@AppOpsManager.UidState int uidState, @OpFlags int flags) {
+ rejected(System.currentTimeMillis(), uidState, flags);
}
- public void finished(long time, long duration, @AppOpsManager.UidState int uidState,
+ /**
+ * Add an rejection that was previously collected
+ *
+ * @param noteTime The time of the event
+ * @param uidState UID state of the app noteOp/startOp was called for
+ * @param flags OpFlags of the call
+ */
+ public void rejected(long noteTime, @AppOpsManager.UidState int uidState,
@OpFlags int flags) {
- updateAccessTimeAndDuration(time, duration, uidState, flags);
- running = false;
- }
+ long key = makeKey(uidState, flags);
- public void running(long time, long duration, @AppOpsManager.UidState int uidState,
- @OpFlags int flags) {
- updateAccessTimeAndDuration(time, duration, uidState, flags);
+ if (mRejectEvents == null) {
+ mRejectEvents = new LongSparseArray<>(1);
+ }
+
+ // We do not collect proxy information for rejections yet
+ mRejectEvents.put(key, new NoteOpEvent(noteTime, -1, null));
}
- public void continuing(long duration, @AppOpsManager.UidState int uidState,
- @OpFlags int flags) {
- final long key = AppOpsManager.makeKey(uidState, flags);
- if (mDurations == null) {
- mDurations = new LongSparseLongArray();
+ /**
+ * Update state when start was called
+ *
+ * @param clientId Id of the startOp caller
+ * @param uidState UID state of the app startOp is called for
+ */
+ public void started(@NonNull IBinder clientId, @AppOpsManager.UidState int uidState)
+ throws RemoteException {
+ if (!parent.isRunning()) {
+ scheduleOpActiveChangedIfNeededLocked(parent.op, parent.uid,
+ parent.packageName, true);
}
- mDurations.put(key, duration);
- }
- private void updateAccessTimeAndDuration(long time, long duration,
- @AppOpsManager.UidState int uidState, @OpFlags int flags) {
- final long key = AppOpsManager.makeKey(uidState, flags);
- if (mAccessTimes == null) {
- mAccessTimes = new LongSparseLongArray();
+ if (mInProgressEvents == null) {
+ mInProgressEvents = new ArrayMap<>(1);
}
- mAccessTimes.put(key, time);
- if (mDurations == null) {
- mDurations = new LongSparseLongArray();
+
+
+ InProgressStartOpEvent event = mInProgressEvents.get(clientId);
+ if (event == null) {
+ event = new InProgressStartOpEvent(System.currentTimeMillis(),
+ SystemClock.elapsedRealtime(), clientId, () -> {
+ // In the case the client dies without calling finish first
+ synchronized (AppOpsService.this) {
+ if (mInProgressEvents == null) {
+ return;
+ }
+
+ InProgressStartOpEvent deadEvent = mInProgressEvents.get(clientId);
+ if (deadEvent != null) {
+ deadEvent.numUnfinishedStarts = 1;
+ }
+
+ finished(clientId);
+ }
+ }, uidState);
+ mInProgressEvents.put(clientId, event);
+ } else {
+ if (uidState != event.uidState) {
+ onUidStateChanged(uidState);
+ }
}
- mDurations.put(key, duration);
+
+ event.numUnfinishedStarts++;
+
+ // startOp events don't support proxy, hence use flags==SELF
+ mHistoricalRegistry.incrementOpAccessedCount(parent.op, parent.uid, parent.packageName,
+ uidState, OP_FLAG_SELF);
+ }
+
+ /**
+ * Update state when finishOp was called
+ *
+ * @param clientId Id of the finishOp caller
+ */
+ public void finished(@NonNull IBinder clientId) {
+ finished(clientId, true);
}
- private void updateProxyState(long key, int proxyUid,
- @Nullable String proxyPackageName, @Nullable String featureId) {
- if (proxyUid == Process.INVALID_UID) {
+ private void finished(@NonNull IBinder clientId, boolean triggerCallbackIfNeeded) {
+ if (mInProgressEvents == null) {
+ Slog.wtf(TAG, "No ops running");
return;
}
- if (mProxyUids == null) {
- mProxyUids = new LongSparseLongArray();
+ int indexOfToken = mInProgressEvents.indexOfKey(clientId);
+ if (indexOfToken < 0) {
+ Slog.wtf(TAG, "No op running for the client");
+ return;
}
- mProxyUids.put(key, proxyUid);
- if (mProxyPackageNames == null) {
- mProxyPackageNames = new LongSparseArray<>();
+ InProgressStartOpEvent event = mInProgressEvents.valueAt(indexOfToken);
+ event.numUnfinishedStarts--;
+ if (event.numUnfinishedStarts == 0) {
+ event.finish();
+ mInProgressEvents.removeAt(indexOfToken);
+
+ if (mAccessEvents == null) {
+ mAccessEvents = new LongSparseArray<>(1);
+ }
+
+ // startOp events don't support proxy, hence use flags==SELF
+ NoteOpEvent finishedEvent = new NoteOpEvent(event.startTime,
+ SystemClock.elapsedRealtime() - event.startElapsedTime, null);
+ mAccessEvents.put(makeKey(event.uidState, OP_FLAG_SELF), finishedEvent);
+
+ mHistoricalRegistry.increaseOpAccessDuration(parent.op, parent.uid,
+ parent.packageName, event.uidState, AppOpsManager.OP_FLAG_SELF,
+ finishedEvent.duration);
+
+ if (mInProgressEvents.isEmpty()) {
+ mInProgressEvents = null;
+
+ // TODO moltmann: Also callback for single feature activity changes
+ if (triggerCallbackIfNeeded && !parent.isRunning()) {
+ scheduleOpActiveChangedIfNeededLocked(parent.op, parent.uid,
+ parent.packageName, false);
+ }
+ }
+ }
+ }
+
+ /**
+ * Notify that the state of the uid changed
+ *
+ * @param newState The new state
+ */
+ public void onUidStateChanged(@AppOpsManager.UidState int newState) {
+ if (mInProgressEvents == null) {
+ return;
}
- mProxyPackageNames.put(key, proxyPackageName);
- if (mProxyFeatureIds == null) {
- mProxyFeatureIds = new LongSparseArray<>();
+ int numInProgressEvents = mInProgressEvents.size();
+ for (int i = 0; i < numInProgressEvents; i++) {
+ InProgressStartOpEvent event = mInProgressEvents.valueAt(i);
+
+ if (event.uidState != newState) {
+ try {
+ finished(event.clientId, false);
+ started(event.clientId, newState);
+ } catch (RemoteException e) {
+ if (DEBUG) Slog.e(TAG, "Cannot switch to new uidState " + newState);
+ }
+ }
}
- mProxyFeatureIds.put(key, featureId);
+ }
+
+ public boolean isRunning() {
+ return mInProgressEvents != null;
}
boolean hasAnyTime() {
- return (mAccessTimes != null && mAccessTimes.size() > 0)
- || (mRejectTimes != null && mRejectTimes.size() > 0);
+ return (mAccessEvents != null && mAccessEvents.size() > 0)
+ || (mRejectEvents != null && mRejectEvents.size() > 0);
}
- @NonNull OpFeatureEntry.Builder createFeatureEntryBuilderLocked() {
- return new OpFeatureEntry.Builder(running, mAccessTimes, mRejectTimes, mDurations,
- mProxyUids, mProxyPackageNames, mProxyFeatureIds);
+ @NonNull OpFeatureEntry createFeatureEntryLocked() {
+ LongSparseArray<NoteOpEvent> accessEvents = null;
+ if (mAccessEvents != null) {
+ accessEvents = mAccessEvents.clone();
+ }
+
+ // Add in progress events as access events
+ if (mInProgressEvents != null) {
+ long now = SystemClock.elapsedRealtime();
+ int numInProgressEvents = mInProgressEvents.size();
+
+ if (accessEvents == null) {
+ accessEvents = new LongSparseArray<>(numInProgressEvents);
+ }
+
+ for (int i = 0; i < numInProgressEvents; i++) {
+ InProgressStartOpEvent event = mInProgressEvents.valueAt(i);
+
+ // startOp events don't support proxy
+ accessEvents.append(makeKey(event.uidState, OP_FLAG_SELF),
+ new NoteOpEvent(event.startTime, now - event.startElapsedTime, null));
+ }
+ }
+
+ LongSparseArray<NoteOpEvent> rejectEvents = null;
+ if (mRejectEvents != null) {
+ rejectEvents = mRejectEvents.clone();
+ }
+
+ return new OpFeatureEntry(parent.op, isRunning(), accessEvents, rejectEvents);
}
}
- final static class Op {
+ final class Op {
int op;
+ int uid;
final UidState uidState;
final @NonNull String packageName;
@@ -602,8 +801,9 @@ public class AppOpsService extends IAppOpsService.Stub {
/** featureId -> FeatureOp */
final ArrayMap<String, FeatureOp> mFeatures = new ArrayMap<>(1);
- Op(UidState uidState, String packageName, int op) {
+ Op(UidState uidState, String packageName, int op, int uid) {
this.op = op;
+ this.uid = uid;
this.uidState = uidState;
this.packageName = packageName;
this.mode = AppOpsManager.opToDefaultMode(op);
@@ -641,11 +841,10 @@ public class AppOpsService extends IAppOpsService.Stub {
@NonNull OpEntry createEntryLocked() {
final int numFeatures = mFeatures.size();
- final Pair<String, OpFeatureEntry.Builder>[] featureEntries =
- new Pair[numFeatures];
+ final ArrayMap<String, OpFeatureEntry> featureEntries = new ArrayMap<>(numFeatures);
for (int i = 0; i < numFeatures; i++) {
- featureEntries[i] = new Pair<>(mFeatures.keyAt(i),
- mFeatures.valueAt(i).createFeatureEntryBuilderLocked());
+ featureEntries.put(mFeatures.keyAt(i),
+ mFeatures.valueAt(i).createFeatureEntryLocked());
}
return new OpEntry(op, mode, featureEntries);
@@ -654,18 +853,28 @@ public class AppOpsService extends IAppOpsService.Stub {
@NonNull OpEntry createSingleFeatureEntryLocked(@Nullable String featureId) {
final int numFeatures = mFeatures.size();
- final Pair<String, AppOpsManager.OpFeatureEntry.Builder>[] featureEntries =
- new Pair[1];
+ final ArrayMap<String, OpFeatureEntry> featureEntries = new ArrayMap<>(1);
for (int i = 0; i < numFeatures; i++) {
if (Objects.equals(mFeatures.keyAt(i), featureId)) {
- featureEntries[0] = new Pair<>(mFeatures.keyAt(i),
- mFeatures.valueAt(i).createFeatureEntryBuilderLocked());
+ featureEntries.put(mFeatures.keyAt(i),
+ mFeatures.valueAt(i).createFeatureEntryLocked());
break;
}
}
return new OpEntry(op, mode, featureEntries);
}
+
+ boolean isRunning() {
+ final int numFeatures = mFeatures.size();
+ for (int i = 0; i < numFeatures; i++) {
+ if (mFeatures.valueAt(i).isRunning()) {
+ return true;
+ }
+ }
+
+ return false;
+ }
}
final SparseArray<ArraySet<ModeCallback>> mOpModeWatchers = new SparseArray<>();
@@ -815,53 +1024,6 @@ public class AppOpsService extends IAppOpsService.Stub {
}
}
- final ArrayMap<IBinder, ClientState> mClients = new ArrayMap<>();
-
- final class ClientState extends Binder implements DeathRecipient {
- final ArrayList<Pair<Op, String>> mStartedOps = new ArrayList<>();
- final IBinder mAppToken;
- final int mPid;
-
- ClientState(IBinder appToken) {
- mAppToken = appToken;
- mPid = Binder.getCallingPid();
- // Watch only for remote processes dying
- if (!(appToken instanceof Binder)) {
- try {
- mAppToken.linkToDeath(this, 0);
- } catch (RemoteException e) {
- /* do nothing */
- }
- }
- }
-
- @Override
- public String toString() {
- return "ClientState{" +
- "mAppToken=" + mAppToken +
- ", " + "pid=" + mPid +
- '}';
- }
-
- @Override
- public void binderDied() {
- synchronized (AppOpsService.this) {
- for (int i=mStartedOps.size()-1; i>=0; i--) {
- final Pair<Op, String> startedOp = mStartedOps.get(i);
- final Op op = startedOp.first;
- final String featureId = startedOp.second;
-
- finishOperationLocked(op, featureId, /*finishNested*/ true);
- if (op.mFeatures.get(featureId).startNesting <= 0) {
- scheduleOpActiveChangedIfNeededLocked(op.op, op.uidState.uid,
- op.packageName, false);
- }
- }
- mClients.remove(mAppToken);
- }
- }
- }
-
public AppOpsService(File storagePath, Handler handler) {
LockGuard.installLock(this, LockGuard.INDEX_APP_OPS);
mFile = new AtomicFile(storagePath, "appops");
@@ -1024,43 +1186,19 @@ public class AppOpsService extends IAppOpsService.Stub {
mUidStates.remove(uid);
}
- // Finish ops other packages started on behalf of the package.
- final int clientCount = mClients.size();
- for (int i = 0; i < clientCount; i++) {
- final ClientState client = mClients.valueAt(i);
- if (client.mStartedOps == null) {
- continue;
- }
- final int startedOpCount = client.mStartedOps.size();
- for (int j = startedOpCount - 1; j >= 0; j--) {
- final Pair<Op, String> startedOp = client.mStartedOps.get(j);
- final Op op = startedOp.first;
- final String featureId = startedOp.second;
-
- if (uid == op.uidState.uid && packageName.equals(op.packageName)) {
- finishOperationLocked(op, featureId, /*finishNested*/ true);
- client.mStartedOps.remove(j);
- if (op.mFeatures.get(featureId).startNesting <= 0) {
- scheduleOpActiveChangedIfNeededLocked(op.op,
- uid, packageName, false);
- }
- }
- }
- }
-
if (ops != null) {
scheduleFastWriteLocked();
- final int opCount = ops.size();
- for (int opNum = 0; opNum < opCount; opNum++) {
+ final int numOps = ops.size();
+ for (int opNum = 0; opNum < numOps; opNum++) {
final Op op = ops.valueAt(opNum);
final int numFeatures = op.mFeatures.size();
for (int featureNum = 0; featureNum < numFeatures; featureNum++) {
- if (op.mFeatures.valueAt(featureNum).running) {
- scheduleOpActiveChangedIfNeededLocked(
- op.op, op.uidState.uid, op.packageName, false);
- break;
+ FeatureOp featureOp = op.mFeatures.valueAt(featureNum);
+
+ while (featureOp.mInProgressEvents != null) {
+ featureOp.mInProgressEvents.valueAt(0).onDeath.run();
}
}
}
@@ -1112,35 +1250,21 @@ public class AppOpsService extends IAppOpsService.Stub {
}
uidState.pendingStateCommitTime = SystemClock.elapsedRealtime() + settleTime;
}
- if (uidState.startNesting != 0) {
- // There is some actively running operation... need to find it
- // and appropriately update its state.
- final long now = System.currentTimeMillis();
- final long nowElapsed = SystemClock.elapsedRealtime();
- for (int i = uidState.pkgOps.size() - 1; i >= 0; i--) {
- final Ops ops = uidState.pkgOps.valueAt(i);
- for (int j = ops.size() - 1; j >= 0; j--) {
- final Op op = ops.valueAt(j);
+
+ if (uidState.pkgOps != null) {
+ int numPkgs = uidState.pkgOps.size();
+ for (int pkgNum = 0; pkgNum < numPkgs; pkgNum++) {
+ Ops ops = uidState.pkgOps.valueAt(pkgNum);
+
+ int numOps = ops.size();
+ for (int opNum = 0; opNum < numOps; opNum++) {
+ Op op = ops.valueAt(opNum);
int numFeatures = op.mFeatures.size();
- for (int featureNum = 0; featureNum < numFeatures;
- featureNum++) {
- final FeatureOp featureOp = op.mFeatures.valueAt(
- featureNum);
- if (featureOp.startNesting > 0) {
- final long duration = SystemClock.elapsedRealtime()
- - featureOp.startRealtime;
- // We don't support proxy long running ops (start/stop)
- mHistoricalRegistry.increaseOpAccessDuration(op.op,
- op.uidState.uid, op.packageName, oldPendingState,
- AppOpsManager.OP_FLAG_SELF, duration);
- // Finish the op in the old state
- featureOp.finished(now, duration, oldPendingState,
- AppOpsManager.OP_FLAG_SELF);
- // Start the op in the new state
- featureOp.startRealtime = nowElapsed;
- featureOp.started(now, newState, AppOpsManager.OP_FLAG_SELF);
- }
+ for (int featureNum = 0; featureNum < numFeatures; featureNum++) {
+ FeatureOp featureOp = op.mFeatures.valueAt(featureNum);
+
+ featureOp.onUidStateChanged(newState);
}
}
}
@@ -1202,7 +1326,7 @@ public class AppOpsService extends IAppOpsService.Stub {
resOps = new ArrayList<>();
for (int i = 0; i < opModeCount; i++) {
int code = uidState.opModes.keyAt(i);
- resOps.add(new OpEntry(code, uidState.opModes.get(code), new Pair[0]));
+ resOps.add(new OpEntry(code, uidState.opModes.get(code), Collections.emptyMap()));
}
} else {
for (int j=0; j<ops.length; j++) {
@@ -1211,7 +1335,8 @@ public class AppOpsService extends IAppOpsService.Stub {
if (resOps == null) {
resOps = new ArrayList<>();
}
- resOps.add(new OpEntry(code, uidState.opModes.get(code), new Pair[0]));
+ resOps.add(new OpEntry(code, uidState.opModes.get(code),
+ Collections.emptyMap()));
}
}
}
@@ -1219,16 +1344,6 @@ public class AppOpsService extends IAppOpsService.Stub {
}
private static @NonNull OpEntry getOpEntryForResult(@NonNull Op op, long elapsedNow) {
- final int numFeatures = op.mFeatures.size();
-
- for (int i = 0; i < numFeatures; i++) {
- final FeatureOp featureOp = op.mFeatures.valueAt(i);
- if (featureOp.running) {
- featureOp.continuing(elapsedNow - featureOp.startRealtime,
- op.uidState.state, AppOpsManager.OP_FLAG_SELF);
- }
- }
-
return op.createEntryLocked();
}
@@ -1962,18 +2077,6 @@ public class AppOpsService extends IAppOpsService.Stub {
}
}
- @Override
- public IBinder getToken(IBinder clientToken) {
- synchronized (this) {
- ClientState cs = mClients.get(clientToken);
- if (cs == null) {
- cs = new ClientState(clientToken);
- mClients.put(clientToken, cs);
- }
- return cs;
- }
- }
-
public CheckOpsDelegate getAppOpsServiceDelegate() {
synchronized (this) {
return mCheckOpsDelegate;
@@ -2214,15 +2317,10 @@ public class AppOpsService extends IAppOpsService.Stub {
return AppOpsManager.MODE_IGNORED;
}
final UidState uidState = ops.uidState;
- if (featureOp.running) {
- final OpFeatureEntry entry = getOpLocked(ops, code,
- false).createSingleFeatureEntryLocked(featureId).getFeatures().get(
- featureId);
-
- Slog.w(TAG, "Noting op not finished: uid " + uid + " pkg " + packageName
- + " code " + code + " time=" + entry.getLastAccessTime(uidState.state,
- uidState.state, flags) + " duration=" + entry.getLastDuration(
- uidState.state, uidState.state, flags));
+ if (featureOp.isRunning()) {
+ Slog.w(TAG, "Noting op not finished: uid " + uid + " pkg " + packageName + " code "
+ + code + " startTime of in progress event="
+ + featureOp.mInProgressEvents.valueAt(0).startTime);
}
final int switchCode = AppOpsManager.opToSwitch(code);
@@ -2234,8 +2332,7 @@ public class AppOpsService extends IAppOpsService.Stub {
if (DEBUG) Slog.d(TAG, "noteOperation: uid reject #" + uidMode + " for code "
+ switchCode + " (" + code + ") uid " + uid + " package "
+ packageName);
- featureOp.rejected(System.currentTimeMillis(), proxyUid, proxyPackageName,
- proxyFeatureId, uidState.state, flags);
+ featureOp.rejected(uidState.state, flags);
mHistoricalRegistry.incrementOpRejected(code, uid, packageName,
uidState.state, flags);
scheduleOpNotedIfNeededLocked(code, uid, packageName, uidMode);
@@ -2244,12 +2341,11 @@ public class AppOpsService extends IAppOpsService.Stub {
} else {
final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
final int mode = switchOp.evalMode();
- if (switchOp.mode != AppOpsManager.MODE_ALLOWED) {
+ if (mode != AppOpsManager.MODE_ALLOWED) {
if (DEBUG) Slog.d(TAG, "noteOperation: reject #" + mode + " for code "
+ switchCode + " (" + code + ") uid " + uid + " package "
+ packageName);
- featureOp.rejected(System.currentTimeMillis(), proxyUid, proxyPackageName,
- proxyFeatureId, uidState.state, flags);
+ featureOp.rejected(uidState.state, flags);
mHistoricalRegistry.incrementOpRejected(code, uid, packageName,
uidState.state, flags);
scheduleOpNotedIfNeededLocked(code, uid, packageName, mode);
@@ -2258,8 +2354,7 @@ public class AppOpsService extends IAppOpsService.Stub {
}
if (DEBUG) Slog.d(TAG, "noteOperation: allowing code " + code + " uid " + uid
+ " package " + packageName + (featureId == null ? "" : "." + featureId));
- featureOp.accessed(System.currentTimeMillis(), proxyUid, proxyPackageName,
- proxyFeatureId, uidState.state, flags);
+ featureOp.accessed(proxyUid, proxyPackageName, proxyFeatureId, uidState.state, flags);
// TODO moltmann: Add features to historical app-ops
mHistoricalRegistry.incrementOpAccessedCount(op.op, uid, packageName,
uidState.state, flags);
@@ -2496,7 +2591,7 @@ public class AppOpsService extends IAppOpsService.Stub {
}
@Override
- public int startOperation(IBinder token, int code, int uid, String packageName,
+ public int startOperation(IBinder clientId, int code, int uid, String packageName,
String featureId, boolean startIfModeDefault) {
verifyIncomingUid(uid);
verifyIncomingOp(code);
@@ -2504,7 +2599,6 @@ public class AppOpsService extends IAppOpsService.Stub {
if (resolvedPackageName == null) {
return AppOpsManager.MODE_IGNORED;
}
- ClientState client = (ClientState)token;
boolean isPrivileged;
try {
@@ -2539,10 +2633,7 @@ public class AppOpsService extends IAppOpsService.Stub {
if (DEBUG) Slog.d(TAG, "noteOperation: uid reject #" + uidMode + " for code "
+ switchCode + " (" + code + ") uid " + uid + " package "
+ resolvedPackageName);
- // We don't support proxy long running ops (start/stop)
- featureOp.rejected(System.currentTimeMillis(), -1 /*proxyUid*/,
- null /*proxyPackage*/, null, uidState.state,
- AppOpsManager.OP_FLAG_SELF);
+ featureOp.rejected(uidState.state, AppOpsManager.OP_FLAG_SELF);
mHistoricalRegistry.incrementOpRejected(opCode, uid, packageName,
uidState.state, AppOpsManager.OP_FLAG_SELF);
return uidMode;
@@ -2555,10 +2646,7 @@ public class AppOpsService extends IAppOpsService.Stub {
if (DEBUG) Slog.d(TAG, "startOperation: reject #" + mode + " for code "
+ switchCode + " (" + code + ") uid " + uid + " package "
+ resolvedPackageName);
- // We don't support proxy long running ops (start/stop)
- featureOp.rejected(System.currentTimeMillis(), -1 /*proxyUid*/,
- null /*proxyPackage*/, null, uidState.state,
- AppOpsManager.OP_FLAG_SELF);
+ featureOp.rejected(uidState.state, AppOpsManager.OP_FLAG_SELF);
mHistoricalRegistry.incrementOpRejected(opCode, uid, packageName,
uidState.state, AppOpsManager.OP_FLAG_SELF);
return mode;
@@ -2566,29 +2654,19 @@ public class AppOpsService extends IAppOpsService.Stub {
}
if (DEBUG) Slog.d(TAG, "startOperation: allowing code " + code + " uid " + uid
+ " package " + resolvedPackageName);
- if (featureOp.startNesting == 0) {
- featureOp.startRealtime = SystemClock.elapsedRealtime();
- // We don't support proxy long running ops (start/stop)
- featureOp.started(System.currentTimeMillis(), uidState.state,
- AppOpsManager.OP_FLAG_SELF);
- mHistoricalRegistry.incrementOpAccessedCount(opCode, uid, packageName,
- uidState.state, AppOpsManager.OP_FLAG_SELF);
-
- // TODO moltmann: call back when a feature became inactive
- if (uidState.startNesting == 0) {
- scheduleOpActiveChangedIfNeededLocked(code, uid, packageName, true);
- }
+
+ try {
+ featureOp.started(clientId, uidState.state);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
}
- featureOp.startNesting++;
- uidState.startNesting++;
- client.mStartedOps.add(new Pair<>(op, featureId));
}
return AppOpsManager.MODE_ALLOWED;
}
@Override
- public void finishOperation(IBinder token, int code, int uid, String packageName,
+ public void finishOperation(IBinder clientId, int code, int uid, String packageName,
String featureId) {
verifyIncomingUid(uid);
verifyIncomingOp(code);
@@ -2596,10 +2674,6 @@ public class AppOpsService extends IAppOpsService.Stub {
if (resolvedPackageName == null) {
return;
}
- if (!(token instanceof ClientState)) {
- return;
- }
- ClientState client = (ClientState) token;
boolean isPrivileged;
try {
@@ -2619,36 +2693,13 @@ public class AppOpsService extends IAppOpsService.Stub {
return;
}
- if (client.mStartedOps.remove(new Pair<>(op, featureId))) {
- finishOperationLocked(op, featureId, /*finishNested*/ false);
-
- // TODO moltmann: call back when a feature became inactive
- if (op.uidState.startNesting <= 0) {
- scheduleOpActiveChangedIfNeededLocked(code, uid, packageName, false);
- }
-
- return;
- }
- }
-
- // We finish ops when packages get removed to guarantee no dangling
- // started ops. However, some part of the system may asynchronously
- // finish ops for an already gone package. Hence, finishing an op
- // for a non existing package is fine and we don't log as a wtf.
- final long identity = Binder.clearCallingIdentity();
- try {
- if (LocalServices.getService(PackageManagerInternal.class).getPackageUid(
- resolvedPackageName, 0, UserHandle.getUserId(uid)) < 0) {
- Slog.i(TAG, "Finishing op=" + AppOpsManager.opToName(code)
- + " for non-existing package=" + resolvedPackageName
- + " in uid=" + uid);
- return;
+ try {
+ featureOp.finished(clientId);
+ } catch (IllegalStateException e) {
+ Slog.e(TAG, "Operation not started: uid=" + uid + " pkg="
+ + packageName + " op=" + AppOpsManager.opToName(code), e);
}
- } finally {
- Binder.restoreCallingIdentity(identity);
}
- Slog.wtf(TAG, "Operation not started: uid=" + uid + " pkg="
- + packageName + " op=" + AppOpsManager.opToName(code));
}
private void scheduleOpActiveChangedIfNeededLocked(int code, int uid, String packageName,
@@ -2769,38 +2820,6 @@ public class AppOpsService extends IAppOpsService.Stub {
return permInfo.getProtection() == PROTECTION_DANGEROUS;
}
- void finishOperationLocked(@NonNull Op op, @Nullable String featureId, boolean finishNested) {
- final FeatureOp featureOp = op.mFeatures.get(featureId);
- final int opCode = featureOp.parent.op;
- final int uid = featureOp.parent.uidState.uid;
- if (featureOp.startNesting <= 1 || finishNested) {
- if (featureOp.startNesting == 1 || finishNested) {
- // We don't support proxy long running ops (start/stop)
- final long duration = SystemClock.elapsedRealtime() - featureOp.startRealtime;
- featureOp.finished(System.currentTimeMillis(), duration, op.uidState.state,
- AppOpsManager.OP_FLAG_SELF);
- mHistoricalRegistry.increaseOpAccessDuration(opCode, uid, op.packageName,
- op.uidState.state, AppOpsManager.OP_FLAG_SELF, duration);
- } else {
- final OpFeatureEntry entry = op.createSingleFeatureEntryLocked(
- featureId).getFeatures().get(featureId);
- Slog.w(TAG, "Finishing op nesting under-run: uid " + uid + " pkg "
- + op.packageName + " code " + opCode + " time="
- + entry.getLastAccessTime(OP_FLAGS_ALL)
- + " duration=" + entry.getLastDuration(MAX_PRIORITY_UID_STATE,
- MIN_PRIORITY_UID_STATE, OP_FLAGS_ALL) + " nesting="
- + featureOp.startNesting);
- }
- if (featureOp.startNesting >= 1) {
- op.uidState.startNesting -= featureOp.startNesting;
- }
- featureOp.startNesting = 0;
- } else {
- featureOp.startNesting--;
- op.uidState.startNesting--;
- }
- }
-
private void verifyIncomingUid(int uid) {
if (uid == Binder.getCallingUid()) {
return;
@@ -3064,7 +3083,7 @@ public class AppOpsService extends IAppOpsService.Stub {
if (!edit) {
return null;
}
- op = new Op(ops.uidState, ops.packageName, code);
+ op = new Op(ops.uidState, ops.packageName, code, ops.uidState.uid);
ops.put(code, op);
}
if (edit) {
@@ -3208,7 +3227,7 @@ public class AppOpsService extends IAppOpsService.Stub {
final Op op = ops.get(AppOpsManager.OP_RUN_IN_BACKGROUND);
if (op != null && op.mode != AppOpsManager.opToDefaultMode(op.op)) {
final Op copy = new Op(op.uidState, op.packageName,
- AppOpsManager.OP_RUN_ANY_IN_BACKGROUND);
+ AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, uidState.uid);
copy.mode = op.mode;
ops.put(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, copy);
changed = true;
@@ -3336,25 +3355,22 @@ public class AppOpsService extends IAppOpsService.Stub {
final FeatureOp featureOp = parent.getOrCreateFeature(parent, feature);
final long key = XmlUtils.readLongAttribute(parser, "n");
-
- final int flags = AppOpsManager.extractFlagsFromKey(key);
- final int state = AppOpsManager.extractUidStateFromKey(key);
+ final int uidState = extractUidStateFromKey(key);
+ final int opFlags = extractFlagsFromKey(key);
final long accessTime = XmlUtils.readLongAttribute(parser, "t", 0);
final long rejectTime = XmlUtils.readLongAttribute(parser, "r", 0);
- final long accessDuration = XmlUtils.readLongAttribute(parser, "d", 0);
+ final long accessDuration = XmlUtils.readLongAttribute(parser, "d", -1);
final String proxyPkg = XmlUtils.readStringAttribute(parser, "pp");
- final int proxyUid = XmlUtils.readIntAttribute(parser, "pu", 0);
+ final int proxyUid = XmlUtils.readIntAttribute(parser, "pu", Process.INVALID_UID);
final String proxyFeatureId = XmlUtils.readStringAttribute(parser, "pc");
if (accessTime > 0) {
- featureOp.accessed(accessTime, proxyUid, proxyPkg, proxyFeatureId, state, flags);
+ featureOp.accessed(accessTime, accessDuration, proxyUid, proxyPkg, proxyFeatureId,
+ uidState, opFlags);
}
if (rejectTime > 0) {
- featureOp.rejected(rejectTime, proxyUid, proxyPkg, proxyFeatureId, state, flags);
- }
- if (accessDuration > 0) {
- featureOp.running(accessTime, accessDuration, state, flags);
+ featureOp.rejected(rejectTime, uidState, opFlags);
}
}
@@ -3362,7 +3378,8 @@ public class AppOpsService extends IAppOpsService.Stub {
@NonNull String pkgName, boolean isPrivileged) throws NumberFormatException,
XmlPullParserException, IOException {
Op op = new Op(uidState, pkgName,
- Integer.parseInt(parser.getAttributeValue(null, "n")));
+ Integer.parseInt(parser.getAttributeValue(null, "n")),
+ uidState.uid);
final int mode = XmlUtils.readIntAttribute(parser, "m",
AppOpsManager.opToDefaultMode(op.op));
@@ -3496,35 +3513,39 @@ public class AppOpsService extends IAppOpsService.Stub {
final OpFeatureEntry feature = op.getFeatures().get(
featureId);
- final LongSparseArray keys = feature.collectKeys();
- if (keys == null || keys.size() <= 0) {
- continue;
- }
- final int keyCount = keys.size();
+ final ArraySet<Long> keys = feature.collectKeys();
+ final int keyCount = keys.size();
for (int k = 0; k < keyCount; k++) {
- final long key = keys.keyAt(k);
+ final long key = keys.valueAt(k);
final int uidState = AppOpsManager.extractUidStateFromKey(key);
final int flags = AppOpsManager.extractFlagsFromKey(key);
- final long accessTime = feature.getLastAccessTime(
- uidState, uidState, flags);
- final long rejectTime = feature.getLastRejectTime(
- uidState, uidState, flags);
- final long accessDuration = feature.getLastDuration(
- uidState, uidState, flags);
- final String proxyPkg = feature.getProxyPackageName(uidState,
- flags);
- final String proxyFeatureId = feature.getProxyFeatureId(
+ final long accessTime = feature.getLastAccessTime(uidState,
+ uidState, flags);
+ final long rejectTime = feature.getLastRejectTime(uidState,
+ uidState, flags);
+ final long accessDuration = feature.getLastDuration(uidState,
uidState, flags);
- final int proxyUid = feature.getProxyUid(uidState, flags);
+ // Proxy information for rejections is not backed up
+ final OpEventProxyInfo proxy = feature.getLastProxyInfo(
+ uidState, uidState, flags);
if (accessTime <= 0 && rejectTime <= 0 && accessDuration <= 0
- && proxyPkg == null && proxyUid < 0) {
+ && proxy == null) {
continue;
}
+ String proxyPkg = null;
+ String proxyFeatureId = null;
+ int proxyUid = Process.INVALID_UID;
+ if (proxy != null) {
+ proxyPkg = proxy.getPackageName();
+ proxyFeatureId = proxy.getFeatureId();
+ proxyUid = proxy.getUid();
+ }
+
out.startTag(null, "st");
if (featureId != null) {
out.attribute(null, "id", featureId);
@@ -3591,10 +3612,7 @@ public class AppOpsService extends IAppOpsService.Stub {
Shell(IAppOpsService iface, AppOpsService internal) {
mInterface = iface;
mInternal = internal;
- try {
- mToken = mInterface.getToken(sBinder);
- } catch (RemoteException e) {
- }
+ mToken = AppOpsManager.getClientId();
}
@Override
@@ -3889,42 +3907,48 @@ public class AppOpsService extends IAppOpsService.Stub {
pw.print(": ");
pw.print(AppOpsManager.modeToName(ent.getMode()));
if (shell.featureId == null) {
- if (ent.getTime() != 0) {
+ if (ent.getLastAccessTime(OP_FLAGS_ALL) != -1) {
pw.print("; time=");
- TimeUtils.formatDuration(now - ent.getTime(), pw);
+ TimeUtils.formatDuration(
+ now - ent.getLastAccessTime(OP_FLAGS_ALL), pw);
pw.print(" ago");
}
- if (ent.getRejectTime() != 0) {
+ if (ent.getLastRejectTime(OP_FLAGS_ALL) != -1) {
pw.print("; rejectTime=");
- TimeUtils.formatDuration(now - ent.getRejectTime(), pw);
+ TimeUtils.formatDuration(
+ now - ent.getLastRejectTime(OP_FLAGS_ALL), pw);
pw.print(" ago");
}
- if (ent.getDuration() == -1) {
+ if (ent.isRunning()) {
pw.print(" (running)");
- } else if (ent.getDuration() != 0) {
+ } else if (ent.getLastDuration(OP_FLAGS_ALL) != -1) {
pw.print("; duration=");
- TimeUtils.formatDuration(ent.getDuration(), pw);
+ TimeUtils.formatDuration(ent.getLastDuration(OP_FLAGS_ALL), pw);
}
} else {
final OpFeatureEntry featureEnt = ent.getFeatures().get(
shell.featureId);
if (featureEnt != null) {
- if (featureEnt.getTime() != 0) {
+ if (featureEnt.getLastAccessTime(OP_FLAGS_ALL) != -1) {
pw.print("; time=");
- TimeUtils.formatDuration(now - featureEnt.getTime(), pw);
+ TimeUtils.formatDuration(now - featureEnt.getLastAccessTime(
+ OP_FLAGS_ALL), pw);
pw.print(" ago");
}
- if (featureEnt.getRejectTime() != 0) {
+ if (featureEnt.getLastRejectTime(OP_FLAGS_ALL) != -1) {
pw.print("; rejectTime=");
- TimeUtils.formatDuration(now - featureEnt.getRejectTime(),
+ TimeUtils.formatDuration(
+ now - featureEnt.getLastRejectTime(OP_FLAGS_ALL),
pw);
pw.print(" ago");
}
- if (featureEnt.getDuration() == -1) {
+ if (featureEnt.isRunning()) {
pw.print(" (running)");
- } else if (featureEnt.getDuration() != 0) {
+ } else if (featureEnt.getLastDuration(OP_FLAGS_ALL)
+ != -1) {
pw.print("; duration=");
- TimeUtils.formatDuration(featureEnt.getDuration(), pw);
+ TimeUtils.formatDuration(
+ featureEnt.getLastDuration(OP_FLAGS_ALL), pw);
}
}
}
@@ -4095,27 +4119,28 @@ public class AppOpsService extends IAppOpsService.Stub {
final OpFeatureEntry entry = op.createSingleFeatureEntryLocked(
featureId).getFeatures().get(featureId);
- final LongSparseArray keys = entry.collectKeys();
- if (keys == null || keys.size() <= 0) {
- return;
- }
+ final ArraySet<Long> keys = entry.collectKeys();
final int keyCount = keys.size();
for (int k = 0; k < keyCount; k++) {
- final long key = keys.keyAt(k);
+ final long key = keys.valueAt(k);
final int uidState = AppOpsManager.extractUidStateFromKey(key);
final int flags = AppOpsManager.extractFlagsFromKey(key);
- final long accessTime = entry.getLastAccessTime(
- uidState, uidState, flags);
- final long rejectTime = entry.getLastRejectTime(
- uidState, uidState, flags);
- final long accessDuration = entry.getLastDuration(
- uidState, uidState, flags);
- final String proxyPkg = entry.getProxyPackageName(uidState, flags);
- final String proxyFeatureId = entry.getProxyFeatureId(uidState, flags);
- final int proxyUid = entry.getProxyUid(uidState, flags);
+ final long accessTime = entry.getLastAccessTime(uidState, uidState, flags);
+ final long rejectTime = entry.getLastRejectTime(uidState, uidState, flags);
+ final long accessDuration = entry.getLastDuration(uidState, uidState, flags);
+ final OpEventProxyInfo proxy = entry.getLastProxyInfo(uidState, uidState, flags);
+
+ String proxyPkg = null;
+ String proxyFeatureId = null;
+ int proxyUid = Process.INVALID_UID;
+ if (proxy != null) {
+ proxyPkg = proxy.getPackageName();
+ proxyFeatureId = proxy.getFeatureId();
+ proxyUid = proxy.getUid();
+ }
if (accessTime > 0) {
pw.print(prefix);
@@ -4168,14 +4193,25 @@ public class AppOpsService extends IAppOpsService.Stub {
}
final FeatureOp featureOp = op.mFeatures.get(featureId);
- if (featureOp.running) {
+ if (featureOp.isRunning()) {
+ long earliestElapsedTime = Long.MAX_VALUE;
+ long maxNumStarts = 0;
+ int numInProgressEvents = featureOp.mInProgressEvents.size();
+ for (int i = 0; i < numInProgressEvents; i++) {
+ InProgressStartOpEvent event = featureOp.mInProgressEvents.valueAt(i);
+
+ earliestElapsedTime = Math.min(earliestElapsedTime, event.startElapsedTime);
+ maxNumStarts = Math.max(maxNumStarts, event.numUnfinishedStarts);
+ }
+
pw.print(prefix + "Running start at: ");
- TimeUtils.formatDuration(nowElapsed - featureOp.startRealtime, pw);
+ TimeUtils.formatDuration(nowElapsed - earliestElapsedTime, pw);
pw.println();
- }
- if (featureOp.startNesting != 0) {
- pw.print(prefix + "startNesting=");
- pw.println(featureOp.startNesting);
+
+ if (maxNumStarts > 1) {
+ pw.print(prefix + "startNesting=");
+ pw.println(maxNumStarts);
+ }
}
}
@@ -4423,44 +4459,6 @@ public class AppOpsService extends IAppOpsService.Stub {
pw.println(cb);
}
}
- if (mClients.size() > 0 && dumpMode < 0 && !dumpWatchers && !dumpHistory) {
- needSep = true;
- boolean printedHeader = false;
- for (int i=0; i<mClients.size(); i++) {
- boolean printedClient = false;
- ClientState cs = mClients.valueAt(i);
- if (cs.mStartedOps.size() > 0) {
- boolean printedStarted = false;
- for (int j=0; j<cs.mStartedOps.size(); j++) {
- final Pair<Op, String> startedOp = cs.mStartedOps.get(j);
- final Op op = startedOp.first;
- if (dumpOp >= 0 && op.op != dumpOp) {
- continue;
- }
- if (dumpPackage != null && !dumpPackage.equals(op.packageName)) {
- continue;
- }
- if (!printedHeader) {
- pw.println(" Clients:");
- printedHeader = true;
- }
- if (!printedClient) {
- pw.print(" "); pw.print(mClients.keyAt(i)); pw.println(":");
- pw.print(" "); pw.println(cs);
- printedClient = true;
- }
- if (!printedStarted) {
- pw.println(" Started ops:");
- printedStarted = true;
- }
- pw.print(" "); pw.print("uid="); pw.print(op.uidState.uid);
- pw.print(" pkg="); pw.print(op.packageName);
- pw.print(" featureId="); pw.print(startedOp.second);
- pw.print(" op="); pw.println(AppOpsManager.opToName(op.op));
- }
- }
- }
- }
if (mAudioRestrictionManager.hasActiveRestrictions() && dumpOp < 0
&& dumpPackage != null && dumpMode < 0 && !dumpWatchers && !dumpWatchers) {
needSep = mAudioRestrictionManager.dump(pw) | needSep ;
@@ -4479,7 +4477,7 @@ public class AppOpsService extends IAppOpsService.Stub {
if (dumpOp >= 0 || dumpPackage != null || dumpMode >= 0) {
boolean hasOp = dumpOp < 0 || (uidState.opModes != null
&& uidState.opModes.indexOfKey(dumpOp) >= 0);
- boolean hasPackage = dumpPackage == null;
+ boolean hasPackage = dumpPackage == null || dumpUid == mUidStates.keyAt(i);
boolean hasMode = dumpMode < 0;
if (!hasMode && opModes != null) {
for (int opi = 0; !hasMode && opi < opModes.size(); opi++) {
@@ -4536,10 +4534,6 @@ public class AppOpsService extends IAppOpsService.Stub {
TimeUtils.formatDuration(uidState.pendingStateCommitTime, nowElapsed, pw);
pw.println();
}
- if (uidState.startNesting != 0) {
- pw.print(" startNesting=");
- pw.println(uidState.startNesting);
- }
if (uidState.foregroundOps != null && (dumpMode < 0
|| dumpMode == AppOpsManager.MODE_FOREGROUND)) {
pw.println(" foregroundOps:");
@@ -4813,17 +4807,18 @@ public class AppOpsService extends IAppOpsService.Stub {
}
// TODO moltmann: Allow to check for feature op activeness
synchronized (AppOpsService.this) {
- for (int i = mClients.size() - 1; i >= 0; i--) {
- final ClientState client = mClients.valueAt(i);
- for (int j = client.mStartedOps.size() - 1; j >= 0; j--) {
- final Pair<Op, String> startedOp = client.mStartedOps.get(j);
- if (startedOp.first.op == code && startedOp.first.uidState.uid == uid) {
- return true;
- }
- }
+ Ops pkgOps = getOpsRawLocked(uid, resolvedPackageName, false, false);
+ if (pkgOps == null) {
+ return false;
}
+
+ Op op = pkgOps.get(code);
+ if (op == null) {
+ return false;
+ }
+
+ return op.isRunning();
}
- return false;
}
@Override
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index df5600473024..75d9dd817487 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -77,6 +77,9 @@ public class AudioDeviceInventory {
// List of preferred devices for strategies
private final ArrayMap<Integer, AudioDeviceAddress> mPreferredDevices = new ArrayMap<>();
+ // the wrapper for AudioSystem static methods, allows us to spy AudioSystem
+ private final @NonNull AudioSystemAdapter mAudioSystem;
+
private @NonNull AudioDeviceBroker mDeviceBroker;
// Monitoring of audio routes. Protected by mAudioRoutes.
@@ -86,12 +89,14 @@ public class AudioDeviceInventory {
/*package*/ AudioDeviceInventory(@NonNull AudioDeviceBroker broker) {
mDeviceBroker = broker;
+ mAudioSystem = AudioSystemAdapter.getDefaultAdapter();
}
//-----------------------------------------------------------
- /** for mocking only */
- /*package*/ AudioDeviceInventory() {
+ /** for mocking only, allows to inject AudioSystem adapter */
+ /*package*/ AudioDeviceInventory(@NonNull AudioSystemAdapter audioSystem) {
mDeviceBroker = null;
+ mAudioSystem = audioSystem;
}
/*package*/ void setDeviceBroker(@NonNull AudioDeviceBroker broker) {
@@ -125,7 +130,7 @@ public class AudioDeviceInventory {
+ " codec: " + Integer.toHexString(mDeviceCodecFormat) + "]";
}
- String getKey() {
+ @NonNull String getKey() {
return makeDeviceListKey(mDeviceType, mDeviceAddress);
}
@@ -133,7 +138,7 @@ public class AudioDeviceInventory {
* Generate a unique key for the mConnectedDevices List by composing the device "type"
* and the "address" associated with a specific instance of that device type
*/
- private static String makeDeviceListKey(int device, String deviceAddress) {
+ @NonNull private static String makeDeviceListKey(int device, String deviceAddress) {
return "0x" + Integer.toHexString(device) + ":" + deviceAddress;
}
}
@@ -185,7 +190,7 @@ public class AudioDeviceInventory {
synchronized (mDevicesLock) {
//TODO iterate on mApmConnectedDevices instead once it handles all device types
for (DeviceInfo di : mConnectedDevices.values()) {
- AudioSystem.setDeviceConnectionState(
+ mAudioSystem.setDeviceConnectionState(
di.mDeviceType,
AudioSystem.DEVICE_STATE_AVAILABLE,
di.mDeviceAddress,
@@ -195,7 +200,7 @@ public class AudioDeviceInventory {
}
synchronized (mPreferredDevices) {
mPreferredDevices.forEach((strategy, device) -> {
- AudioSystem.setPreferredDeviceForStrategy(strategy, device); });
+ mAudioSystem.setPreferredDeviceForStrategy(strategy, device); });
}
}
@@ -241,15 +246,17 @@ public class AudioDeviceInventory {
} else {
makeA2dpDeviceUnavailableNow(address, di.mDeviceCodecFormat);
}
+ } else if (state == BluetoothProfile.STATE_CONNECTED) {
+ // device is not already connected
+ if (a2dpVolume != -1) {
+ mDeviceBroker.postSetVolumeIndexOnDevice(AudioSystem.STREAM_MUSIC,
+ // convert index to internal representation in VolumeStreamState
+ a2dpVolume * 10,
+ AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, "onSetA2dpSinkConnectionState");
+ }
+ makeA2dpDeviceAvailable(address, BtHelper.getName(btDevice),
+ "onSetA2dpSinkConnectionState", a2dpCodec);
}
- if (a2dpVolume != -1) {
- mDeviceBroker.postSetVolumeIndexOnDevice(AudioSystem.STREAM_MUSIC,
- // convert index to internal representation in VolumeStreamState
- a2dpVolume * 10,
- AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, "onSetA2dpSinkConnectionState");
- }
- makeA2dpDeviceAvailable(address, BtHelper.getName(btDevice),
- "onSetA2dpSinkConnectionState", a2dpCodec);
}
}
@@ -353,8 +360,15 @@ public class AudioDeviceInventory {
mConnectedDevices.replace(key, di);
}
}
- if (AudioSystem.handleDeviceConfigChange(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address,
- BtHelper.getName(btDevice), a2dpCodec) != AudioSystem.AUDIO_STATUS_OK) {
+ final int res = mAudioSystem.handleDeviceConfigChange(
+ AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address,
+ BtHelper.getName(btDevice), a2dpCodec);
+
+ if (res != AudioSystem.AUDIO_STATUS_OK) {
+ AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
+ "APM handleDeviceConfigChange failed for A2DP device addr="
+ + address + " codec=" + a2dpCodec).printLog(TAG));
+
int musicDevice = mDeviceBroker.getDeviceForStream(AudioSystem.STREAM_MUSIC);
// force A2DP device disconnection in case of error so that AudioService state is
// consistent with audio policy manager state
@@ -362,6 +376,10 @@ public class AudioDeviceInventory {
btDevice, BluetoothA2dp.STATE_DISCONNECTED, BluetoothProfile.A2DP,
false /* suppressNoisyIntent */, musicDevice,
-1 /* a2dpVolume */);
+ } else {
+ AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
+ "APM handleDeviceConfigChange success for A2DP device addr="
+ + address + " codec=" + a2dpCodec).printLog(TAG));
}
}
}
@@ -464,7 +482,7 @@ public class AudioDeviceInventory {
/*package*/ int setPreferredDeviceForStrategySync(int strategy,
@NonNull AudioDeviceAddress device) {
final long identity = Binder.clearCallingIdentity();
- final int status = AudioSystem.setPreferredDeviceForStrategy(strategy, device);
+ final int status = mAudioSystem.setPreferredDeviceForStrategy(strategy, device);
Binder.restoreCallingIdentity(identity);
if (status == AudioSystem.SUCCESS) {
@@ -475,7 +493,7 @@ public class AudioDeviceInventory {
/*package*/ int removePreferredDeviceForStrategySync(int strategy) {
final long identity = Binder.clearCallingIdentity();
- final int status = AudioSystem.removePreferredDeviceForStrategy(strategy);
+ final int status = mAudioSystem.removePreferredDeviceForStrategy(strategy);
Binder.restoreCallingIdentity(identity);
if (status == AudioSystem.SUCCESS) {
@@ -510,7 +528,7 @@ public class AudioDeviceInventory {
Slog.i(TAG, "deviceInfo:" + di + " is(already)Connected:" + isConnected);
}
if (connect && !isConnected) {
- final int res = AudioSystem.setDeviceConnectionState(device,
+ final int res = mAudioSystem.setDeviceConnectionState(device,
AudioSystem.DEVICE_STATE_AVAILABLE, address, deviceName,
AudioSystem.AUDIO_FORMAT_DEFAULT);
if (res != AudioSystem.AUDIO_STATUS_OK) {
@@ -523,7 +541,7 @@ public class AudioDeviceInventory {
mDeviceBroker.postAccessoryPlugMediaUnmute(device);
return true;
} else if (!connect && isConnected) {
- AudioSystem.setDeviceConnectionState(device,
+ mAudioSystem.setDeviceConnectionState(device,
AudioSystem.DEVICE_STATE_UNAVAILABLE, address, deviceName,
AudioSystem.AUDIO_FORMAT_DEFAULT);
// always remove even if disconnection failed
@@ -700,10 +718,22 @@ public class AudioDeviceInventory {
mDeviceBroker.setBluetoothA2dpOnInt(true, eventSource);
// at this point there could be another A2DP device already connected in APM, but it
// doesn't matter as this new one will overwrite the previous one
- AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
+ final int res = mAudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
AudioSystem.DEVICE_STATE_AVAILABLE, address, name, a2dpCodec);
+
+ if (res != AudioSystem.AUDIO_STATUS_OK) {
+ AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
+ "APM failed to make available A2DP device addr=" + address
+ + " error=" + res).printLog(TAG));
+ // TODO: connection failed, stop here
+ // TODO: return;
+ } else {
+ AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
+ "A2DP device addr=" + address + " now available").printLog(TAG));
+ }
+
// Reset A2DP suspend state each time a new sink is connected
- AudioSystem.setParameters("A2dpSuspended=false");
+ mAudioSystem.setParameters("A2dpSuspended=false");
final DeviceInfo di = new DeviceInfo(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, name,
address, a2dpCodec);
@@ -726,8 +756,8 @@ public class AudioDeviceInventory {
DeviceInfo.makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address);
mConnectedDevices.remove(deviceToRemoveKey);
- if (!mApmConnectedDevices.get(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP)
- .equals(deviceToRemoveKey)) {
+ if (!deviceToRemoveKey
+ .equals(mApmConnectedDevices.get(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP))) {
// removing A2DP device not currently used by AudioPolicy, log but don't act on it
AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
"A2DP device " + address + " made unavailable, was not used")).printLog(TAG));
@@ -736,8 +766,19 @@ public class AudioDeviceInventory {
// device to remove was visible by APM, update APM
mDeviceBroker.setAvrcpAbsoluteVolumeSupported(false);
- AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
+ final int res = mAudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
AudioSystem.DEVICE_STATE_UNAVAILABLE, address, "", a2dpCodec);
+
+ if (res != AudioSystem.AUDIO_STATUS_OK) {
+ AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
+ "APM failed to make unavailable A2DP device addr=" + address
+ + " error=" + res).printLog(TAG));
+ // TODO: failed to disconnect, stop here
+ // TODO: return;
+ } else {
+ AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
+ "A2DP device addr=" + address + " made unavailable")).printLog(TAG));
+ }
mApmConnectedDevices.remove(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP);
// Remove A2DP routes as well
setCurrentAudioRouteNameIfPossible(null);
@@ -747,7 +788,7 @@ public class AudioDeviceInventory {
private void makeA2dpDeviceUnavailableLater(String address, int delayMs) {
// prevent any activity on the A2DP audio output to avoid unwanted
// reconnection of the sink.
- AudioSystem.setParameters("A2dpSuspended=true");
+ mAudioSystem.setParameters("A2dpSuspended=true");
// retrieve DeviceInfo before removing device
final String deviceKey =
DeviceInfo.makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address);
@@ -763,7 +804,7 @@ public class AudioDeviceInventory {
@GuardedBy("mDevicesLock")
private void makeA2dpSrcAvailable(String address) {
- AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP,
+ mAudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP,
AudioSystem.DEVICE_STATE_AVAILABLE, address, "",
AudioSystem.AUDIO_FORMAT_DEFAULT);
mConnectedDevices.put(
@@ -774,7 +815,7 @@ public class AudioDeviceInventory {
@GuardedBy("mDevicesLock")
private void makeA2dpSrcUnavailable(String address) {
- AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP,
+ mAudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP,
AudioSystem.DEVICE_STATE_UNAVAILABLE, address, "",
AudioSystem.AUDIO_FORMAT_DEFAULT);
mConnectedDevices.remove(
@@ -788,7 +829,7 @@ public class AudioDeviceInventory {
AudioSystem.DEVICE_OUT_HEARING_AID);
mDeviceBroker.postSetHearingAidVolumeIndex(hearingAidVolIndex, streamType);
- AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_HEARING_AID,
+ mAudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_HEARING_AID,
AudioSystem.DEVICE_STATE_AVAILABLE, address, name,
AudioSystem.AUDIO_FORMAT_DEFAULT);
mConnectedDevices.put(
@@ -803,7 +844,7 @@ public class AudioDeviceInventory {
@GuardedBy("mDevicesLock")
private void makeHearingAidDeviceUnavailable(String address) {
- AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_HEARING_AID,
+ mAudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_HEARING_AID,
AudioSystem.DEVICE_STATE_UNAVAILABLE, address, "",
AudioSystem.AUDIO_FORMAT_DEFAULT);
mConnectedDevices.remove(
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 335cac86b543..114aac91fbfa 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -310,7 +310,8 @@ public class AudioService extends IAudioService.Stub
7, // STREAM_SYSTEM_ENFORCED
15, // STREAM_DTMF
15, // STREAM_TTS
- 15 // STREAM_ACCESSIBILITY
+ 15, // STREAM_ACCESSIBILITY
+ 15 // STREAM_ASSISTANT
};
/** Minimum volume index values for audio streams */
@@ -325,7 +326,8 @@ public class AudioService extends IAudioService.Stub
0, // STREAM_SYSTEM_ENFORCED
0, // STREAM_DTMF
0, // STREAM_TTS
- 1 // STREAM_ACCESSIBILITY
+ 1, // STREAM_ACCESSIBILITY
+ 0 // STREAM_ASSISTANT
};
/* mStreamVolumeAlias[] indicates for each stream if it uses the volume settings
@@ -348,7 +350,8 @@ public class AudioService extends IAudioService.Stub
AudioSystem.STREAM_RING, // STREAM_SYSTEM_ENFORCED
AudioSystem.STREAM_RING, // STREAM_DTMF
AudioSystem.STREAM_MUSIC, // STREAM_TTS
- AudioSystem.STREAM_MUSIC // STREAM_ACCESSIBILITY
+ AudioSystem.STREAM_MUSIC, // STREAM_ACCESSIBILITY
+ AudioSystem.STREAM_MUSIC // STREAM_ASSISTANT
};
private final int[] STREAM_VOLUME_ALIAS_TELEVISION = new int[] {
AudioSystem.STREAM_MUSIC, // STREAM_VOICE_CALL
@@ -361,7 +364,8 @@ public class AudioService extends IAudioService.Stub
AudioSystem.STREAM_MUSIC, // STREAM_SYSTEM_ENFORCED
AudioSystem.STREAM_MUSIC, // STREAM_DTMF
AudioSystem.STREAM_MUSIC, // STREAM_TTS
- AudioSystem.STREAM_MUSIC // STREAM_ACCESSIBILITY
+ AudioSystem.STREAM_MUSIC, // STREAM_ACCESSIBILITY
+ AudioSystem.STREAM_MUSIC // STREAM_ASSISTANT
};
private final int[] STREAM_VOLUME_ALIAS_DEFAULT = new int[] {
AudioSystem.STREAM_VOICE_CALL, // STREAM_VOICE_CALL
@@ -374,7 +378,8 @@ public class AudioService extends IAudioService.Stub
AudioSystem.STREAM_RING, // STREAM_SYSTEM_ENFORCED
AudioSystem.STREAM_RING, // STREAM_DTMF
AudioSystem.STREAM_MUSIC, // STREAM_TTS
- AudioSystem.STREAM_MUSIC // STREAM_ACCESSIBILITY
+ AudioSystem.STREAM_MUSIC, // STREAM_ACCESSIBILITY
+ AudioSystem.STREAM_MUSIC // STREAM_ASSISTANT
};
protected static int[] mStreamVolumeAlias;
@@ -394,6 +399,7 @@ public class AudioService extends IAudioService.Stub
AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_DTMF
AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_TTS
AppOpsManager.OP_AUDIO_ACCESSIBILITY_VOLUME, // STREAM_ACCESSIBILITY
+ AppOpsManager.OP_AUDIO_MEDIA_VOLUME // STREAM_ASSISTANT
};
private final boolean mUseFixedVolume;
@@ -409,8 +415,10 @@ public class AudioService extends IAudioService.Stub
public void onError(int error) {
switch (error) {
case AudioSystem.AUDIO_STATUS_SERVER_DIED:
- mRecordMonitor.onAudioServerDied();
-
+ // check for null in case error callback is called during instance creation
+ if (mRecordMonitor != null) {
+ mRecordMonitor.onAudioServerDied();
+ }
sendMsg(mAudioHandler, MSG_AUDIO_SERVER_DIED,
SENDMSG_NOOP, 0, 0, null, 0);
sendMsg(mAudioHandler, MSG_DISPATCH_AUDIO_SERVER_STATE,
@@ -1253,6 +1261,9 @@ public class AudioService extends IAudioService.Stub
int dtmfStreamAlias;
final int a11yStreamAlias = sIndependentA11yVolume ?
AudioSystem.STREAM_ACCESSIBILITY : AudioSystem.STREAM_MUSIC;
+ final int assistantStreamAlias = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_useAssistantVolume) ?
+ AudioSystem.STREAM_ASSISTANT : AudioSystem.STREAM_MUSIC;
if (mIsSingleVolume) {
mStreamVolumeAlias = STREAM_VOLUME_ALIAS_TELEVISION;
@@ -1282,6 +1293,7 @@ public class AudioService extends IAudioService.Stub
mStreamVolumeAlias[AudioSystem.STREAM_DTMF] = dtmfStreamAlias;
mStreamVolumeAlias[AudioSystem.STREAM_ACCESSIBILITY] = a11yStreamAlias;
+ mStreamVolumeAlias[AudioSystem.STREAM_ASSISTANT] = assistantStreamAlias;
if (updateVolumes && mStreamStates != null) {
updateDefaultVolumes();
@@ -1808,6 +1820,17 @@ public class AudioService extends IAudioService.Stub
return;
}
+ // If the stream is STREAM_ASSISTANT,
+ // make sure that the calling app have the MODIFY_AUDIO_ROUTING permission.
+ if (streamType == AudioSystem.STREAM_ASSISTANT &&
+ mContext.checkCallingOrSelfPermission(
+ android.Manifest.permission.MODIFY_AUDIO_ROUTING)
+ != PackageManager.PERMISSION_GRANTED) {
+ Log.w(TAG, "MODIFY_AUDIO_ROUTING Permission Denial: adjustStreamVolume from pid="
+ + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
+ return;
+ }
+
// use stream type alias here so that streams with same alias have the same behavior,
// including with regard to silent mode control (e.g the use of STREAM_RING below and in
// checkForRingerModeChange() in place of STREAM_RING or STREAM_NOTIFICATION)
@@ -2244,6 +2267,14 @@ public class AudioService extends IAudioService.Stub
+ " MODIFY_PHONE_STATE callingPackage=" + callingPackage);
return;
}
+ if ((streamType == AudioManager.STREAM_ASSISTANT)
+ && (mContext.checkCallingOrSelfPermission(
+ android.Manifest.permission.MODIFY_AUDIO_ROUTING)
+ != PackageManager.PERMISSION_GRANTED)) {
+ Log.w(TAG, "Trying to call setStreamVolume() for STREAM_ASSISTANT without"
+ + " MODIFY_AUDIO_ROUTING callingPackage=" + callingPackage);
+ return;
+ }
sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_SET_STREAM_VOL, streamType,
index/*val1*/, flags/*val2*/, callingPackage));
setStreamVolume(streamType, index, flags, callingPackage, callingPackage,
diff --git a/services/core/java/com/android/server/audio/AudioSystemAdapter.java b/services/core/java/com/android/server/audio/AudioSystemAdapter.java
new file mode 100644
index 000000000000..9d06b4257b62
--- /dev/null
+++ b/services/core/java/com/android/server/audio/AudioSystemAdapter.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.audio;
+
+import android.annotation.NonNull;
+import android.media.AudioDeviceAddress;
+import android.media.AudioSystem;
+import android.util.Log;
+
+/**
+ * Provides an adapter to access functionality of the android.media.AudioSystem class for device
+ * related functionality.
+ * Use the "real" AudioSystem through the default adapter.
+ * Use the "always ok" adapter to avoid dealing with the APM behaviors during a test.
+ */
+public class AudioSystemAdapter {
+
+ /**
+ * Create a wrapper around the {@link AudioSystem} static methods, all functions are directly
+ * forwarded to the AudioSystem class.
+ * @return an adapter around AudioSystem
+ */
+ static final @NonNull AudioSystemAdapter getDefaultAdapter() {
+ return new AudioSystemAdapter();
+ }
+
+ /**
+ * Create an adapter for AudioSystem that always succeeds, and does nothing.
+ * @return a no-op AudioSystem adapter
+ */
+ static final @NonNull AudioSystemAdapter getAlwaysOkAdapter() {
+ return new AudioSystemOkAdapter();
+ }
+
+ /**
+ * Same as {@link AudioSystem#setDeviceConnectionState(int, int, String, String, int)}
+ * @param device
+ * @param state
+ * @param deviceAddress
+ * @param deviceName
+ * @param codecFormat
+ * @return
+ */
+ public int setDeviceConnectionState(int device, int state, String deviceAddress,
+ String deviceName, int codecFormat) {
+ return AudioSystem.setDeviceConnectionState(device, state, deviceAddress, deviceName,
+ codecFormat);
+ }
+
+ /**
+ * Same as {@link AudioSystem#getDeviceConnectionState(int, String)}
+ * @param device
+ * @param deviceAddress
+ * @return
+ */
+ public int getDeviceConnectionState(int device, String deviceAddress) {
+ return AudioSystem.getDeviceConnectionState(device, deviceAddress);
+ }
+
+ /**
+ * Same as {@link AudioSystem#handleDeviceConfigChange(int, String, String, int)}
+ * @param device
+ * @param deviceAddress
+ * @param deviceName
+ * @param codecFormat
+ * @return
+ */
+ public int handleDeviceConfigChange(int device, String deviceAddress,
+ String deviceName, int codecFormat) {
+ return AudioSystem.handleDeviceConfigChange(device, deviceAddress, deviceName,
+ codecFormat);
+ }
+
+ /**
+ * Same as {@link AudioSystem#setPreferredDeviceForStrategy(int, AudioDeviceAddress)}
+ * @param strategy
+ * @param device
+ * @return
+ */
+ public int setPreferredDeviceForStrategy(int strategy, @NonNull AudioDeviceAddress device) {
+ return AudioSystem.setPreferredDeviceForStrategy(strategy, device);
+ }
+
+ /**
+ * Same as {@link AudioSystem#removePreferredDeviceForStrategy(int)}
+ * @param strategy
+ * @return
+ */
+ public int removePreferredDeviceForStrategy(int strategy) {
+ return AudioSystem.removePreferredDeviceForStrategy(strategy);
+ }
+
+ /**
+ * Same as {@link AudioSystem#setParameters(String)}
+ * @param keyValuePairs
+ * @return
+ */
+ public int setParameters(String keyValuePairs) {
+ return AudioSystem.setParameters(keyValuePairs);
+ }
+
+ //--------------------------------------------------------------------
+ protected static class AudioSystemOkAdapter extends AudioSystemAdapter {
+ private static final String TAG = "ASA";
+
+ @Override
+ public int setDeviceConnectionState(int device, int state, String deviceAddress,
+ String deviceName, int codecFormat) {
+ Log.i(TAG, String.format("setDeviceConnectionState(0x%s, %s, %s, 0x%s",
+ Integer.toHexString(device), state, deviceAddress, deviceName,
+ Integer.toHexString(codecFormat)));
+ return AudioSystem.AUDIO_STATUS_OK;
+ }
+
+ @Override
+ public int getDeviceConnectionState(int device, String deviceAddress) {
+ return AudioSystem.AUDIO_STATUS_OK;
+ }
+
+ @Override
+ public int handleDeviceConfigChange(int device, String deviceAddress,
+ String deviceName, int codecFormat) {
+ return AudioSystem.AUDIO_STATUS_OK;
+ }
+
+ @Override
+ public int setPreferredDeviceForStrategy(int strategy, @NonNull AudioDeviceAddress device) {
+ return AudioSystem.AUDIO_STATUS_OK;
+ }
+
+ @Override
+ public int removePreferredDeviceForStrategy(int strategy) {
+ return AudioSystem.AUDIO_STATUS_OK;
+ }
+
+ @Override
+ public int setParameters(String keyValuePairs) {
+ return AudioSystem.AUDIO_STATUS_OK;
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index 0f51e39d128a..e1a9f3b97e9a 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -28,6 +28,7 @@ import static android.hardware.biometrics.BiometricManager.Authenticators;
import android.app.ActivityManager;
import android.app.IActivityManager;
import android.app.UserSwitchObserver;
+import android.app.admin.DevicePolicyManager;
import android.app.trust.ITrustManager;
import android.content.ContentResolver;
import android.content.Context;
@@ -210,6 +211,7 @@ public class BiometricService extends SystemService {
}
private final Injector mInjector;
+ private final DevicePolicyManager mDevicePolicyManager;
@VisibleForTesting
final IBiometricService.Stub mImpl;
@VisibleForTesting
@@ -648,6 +650,10 @@ public class BiometricService extends SystemService {
throw new SecurityException("Invalid authenticator configuration");
}
+ if (bundle.getBoolean(BiometricPrompt.EXTRA_DISALLOW_BIOMETRICS_IF_POLICY_EXISTS)) {
+ checkInternalPermission();
+ }
+
Utils.combineAuthenticatorBundles(bundle);
// Check the usage of this in system server. Need to remove this check if it becomes a
@@ -712,8 +718,8 @@ public class BiometricService extends SystemService {
int biometricConstantsResult = BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE;
final long ident = Binder.clearCallingIdentity();
try {
- biometricConstantsResult =
- checkAndGetAuthenticators(userId, bundle, opPackageName).second;
+ biometricConstantsResult = checkAndGetAuthenticators(userId, bundle, opPackageName,
+ false /* checkDevicePolicyManager */).second;
if (biometricConstantsResult != BiometricConstants.BIOMETRIC_SUCCESS
&& Utils.isDeviceCredentialAllowed(bundle)) {
// If there's an issue with biometrics, but device credential is allowed and
@@ -947,6 +953,8 @@ public class BiometricService extends SystemService {
super(context);
mInjector = injector;
+ mDevicePolicyManager = (DevicePolicyManager) context
+ .getSystemService(context.DEVICE_POLICY_SERVICE);
mImpl = new BiometricServiceWrapper();
mEnabledOnKeyguardCallbacks = new ArrayList<>();
mSettingObserver = mInjector.getSettingObserver(context, mHandler,
@@ -978,6 +986,42 @@ public class BiometricService extends SystemService {
}
/**
+ * @param modality one of {@link BiometricAuthenticator#TYPE_FINGERPRINT},
+ * {@link BiometricAuthenticator#TYPE_IRIS} or {@link BiometricAuthenticator#TYPE_FACE}
+ * @return
+ */
+ private int mapModalityToDevicePolicyType(int modality) {
+ switch (modality) {
+ case TYPE_FINGERPRINT:
+ return DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT;
+ case TYPE_IRIS:
+ return DevicePolicyManager.KEYGUARD_DISABLE_IRIS;
+ case TYPE_FACE:
+ return DevicePolicyManager.KEYGUARD_DISABLE_FACE;
+ default:
+ Slog.e(TAG, "Error modality=" + modality);
+ return DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE;
+ }
+ }
+
+ // TODO(joshmccloskey): Update this to throw an error if a new modality is added and this
+ // logic is not updated.
+ private boolean isBiometricDisabledByDevicePolicy(int modality, int effectiveUserId) {
+ final int biometricToCheck = mapModalityToDevicePolicyType(modality);
+ if (biometricToCheck == DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE) {
+ Slog.e(TAG, "Allowing unknown modality " + modality + " to pass Device Policy check");
+ return false;
+ }
+ final int devicePolicyDisabledFeatures =
+ mDevicePolicyManager.getKeyguardDisabledFeatures(null, effectiveUserId);
+ final boolean isBiometricDisabled =
+ (biometricToCheck & devicePolicyDisabledFeatures) != 0;
+ Slog.w(TAG, "isBiometricDisabledByDevicePolicy(" + modality + "," + effectiveUserId
+ + ")=" + isBiometricDisabled);
+ return isBiometricDisabled;
+ }
+
+ /**
* Checks if there are any available biometrics, and returns the modality. This method also
* returns errors through the callback (no biometric feature, hardware not detected, no
* templates enrolled, etc). This service must not start authentication if errors are sent.
@@ -996,7 +1040,7 @@ public class BiometricService extends SystemService {
* TODO(kchyn): Update this to handle DEVICE_CREDENTIAL better, reduce duplicate code in callers
*/
private Pair<Integer, Integer> checkAndGetAuthenticators(int userId, Bundle bundle,
- String opPackageName) throws RemoteException {
+ String opPackageName, boolean checkDevicePolicyManager) throws RemoteException {
if (!Utils.isBiometricAllowed(bundle)
&& Utils.isDeviceCredentialAllowed(bundle)
&& !mTrustManager.isDeviceSecure(userId)) {
@@ -1033,6 +1077,11 @@ public class BiometricService extends SystemService {
}
if (authenticator.impl.hasEnrolledTemplates(userId, opPackageName)) {
hasTemplatesEnrolled = true;
+ // If the device policy manager disables a specific biometric, skip it.
+ if (checkDevicePolicyManager &&
+ isBiometricDisabledByDevicePolicy(modality, userId)) {
+ continue;
+ }
if (isEnabledForApp(modality, userId)) {
enabledForApps = true;
break;
@@ -1043,6 +1092,7 @@ public class BiometricService extends SystemService {
}
Slog.d(TAG, "checkAndGetAuthenticators: user=" + userId
+ + " checkDevicePolicyManager=" + checkDevicePolicyManager
+ " isHardwareDetected=" + isHardwareDetected
+ " hasTemplatesEnrolled=" + hasTemplatesEnrolled
+ " enabledForApps=" + enabledForApps);
@@ -1502,8 +1552,10 @@ public class BiometricService extends SystemService {
int result;
try {
+ final boolean checkDevicePolicyManager = bundle.getBoolean(
+ BiometricPrompt.EXTRA_DISALLOW_BIOMETRICS_IF_POLICY_EXISTS, false);
final Pair<Integer, Integer> pair = checkAndGetAuthenticators(userId, bundle,
- opPackageName);
+ opPackageName, checkDevicePolicyManager);
modality = pair.first;
result = pair.second;
} catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/connectivity/DnsManager.java b/services/core/java/com/android/server/connectivity/DnsManager.java
index 2321afb7df43..5250a771d73c 100644
--- a/services/core/java/com/android/server/connectivity/DnsManager.java
+++ b/services/core/java/com/android/server/connectivity/DnsManager.java
@@ -337,7 +337,6 @@ public class DnsManager {
.collect(Collectors.toList()))
: useTls ? paramsParcel.servers // Opportunistic
: new String[0]; // Off
- paramsParcel.tlsFingerprints = new String[0];
// Prepare to track the validation status of the DNS servers in the
// resolver config when private DNS is in opportunistic or strict mode.
if (useTls) {
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index 177e2d8b5fa2..c99774a41f10 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -52,9 +52,6 @@ class AutomaticBrightnessController {
private static final boolean DEBUG_PRETEND_LIGHT_SENSOR_ABSENT = false;
- // If true, enables the use of the screen auto-brightness adjustment setting.
- private static final boolean USE_SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT = true;
-
// How long the current sensor reading is assumed to be valid beyond the current time.
// This provides a bit of prediction, as well as ensures that the weight for the last sample is
// non-zero, which in turn ensures that the total weight is non-zero.
@@ -131,13 +128,6 @@ class AutomaticBrightnessController {
private boolean mLoggingEnabled;
- // Timeout after which we remove the effects any user interactions might've had on the
- // brightness mapping. This timeout doesn't start until we transition to a non-interactive
- // display policy so that we don't reset while users are using their devices, but also so that
- // we don't erroneously keep the short-term model if the device is dozing but the display is
- // fully on.
- private long mShortTermModelTimeout;
-
// Amount of time to delay auto-brightness after screen on while waiting for
// the light sensor to warm-up in milliseconds.
// May be 0 if no warm-up is required.
@@ -202,7 +192,6 @@ class AutomaticBrightnessController {
// we use a relative threshold to determine when to revert to the OEM curve.
private boolean mShortTermModelValid;
private float mShortTermModelAnchor;
- private float SHORT_TERM_MODEL_THRESHOLD_RATIO = 0.6f;
// Context-sensitive brightness configurations require keeping track of the foreground app's
// package name and category, which is done by registering a TaskStackListener to call back to
@@ -224,14 +213,13 @@ class AutomaticBrightnessController {
int lightSensorRate, int initialLightSensorRate, long brighteningLightDebounceConfig,
long darkeningLightDebounceConfig, boolean resetAmbientLuxAfterWarmUpConfig,
HysteresisLevels ambientBrightnessThresholds,
- HysteresisLevels screenBrightnessThresholds, long shortTermModelTimeout,
+ HysteresisLevels screenBrightnessThresholds,
PackageManager packageManager) {
this(new Injector(), callbacks, looper, sensorManager, lightSensor, mapper,
lightSensorWarmUpTime, brightnessMin, brightnessMax, dozeScaleFactor,
lightSensorRate, initialLightSensorRate, brighteningLightDebounceConfig,
darkeningLightDebounceConfig, resetAmbientLuxAfterWarmUpConfig,
- ambientBrightnessThresholds, screenBrightnessThresholds, shortTermModelTimeout,
- packageManager);
+ ambientBrightnessThresholds, screenBrightnessThresholds, packageManager);
}
@VisibleForTesting
@@ -241,7 +229,7 @@ class AutomaticBrightnessController {
int lightSensorRate, int initialLightSensorRate, long brighteningLightDebounceConfig,
long darkeningLightDebounceConfig, boolean resetAmbientLuxAfterWarmUpConfig,
HysteresisLevels ambientBrightnessThresholds,
- HysteresisLevels screenBrightnessThresholds, long shortTermModelTimeout,
+ HysteresisLevels screenBrightnessThresholds,
PackageManager packageManager) {
mInjector = injector;
mCallbacks = callbacks;
@@ -261,7 +249,6 @@ class AutomaticBrightnessController {
mWeightingIntercept = AMBIENT_LIGHT_LONG_HORIZON_MILLIS;
mAmbientBrightnessThresholds = ambientBrightnessThresholds;
mScreenBrightnessThresholds = screenBrightnessThresholds;
- mShortTermModelTimeout = shortTermModelTimeout;
mShortTermModelValid = true;
mShortTermModelAnchor = -1;
@@ -370,7 +357,7 @@ class AutomaticBrightnessController {
}
if (!isInteractivePolicy(policy) && isInteractivePolicy(oldPolicy)) {
mHandler.sendEmptyMessageDelayed(MSG_INVALIDATE_SHORT_TERM_MODEL,
- mShortTermModelTimeout);
+ mBrightnessMapper.getShortTermModelTimeout());
} else if (isInteractivePolicy(policy) && !isInteractivePolicy(oldPolicy)) {
mHandler.removeMessages(MSG_INVALIDATE_SHORT_TERM_MODEL);
}
@@ -452,7 +439,7 @@ class AutomaticBrightnessController {
pw.println(" mAmbientLightRingBuffer=" + mAmbientLightRingBuffer);
pw.println(" mScreenAutoBrightness=" + mScreenAutoBrightness);
pw.println(" mDisplayPolicy=" + DisplayPowerRequest.policyToString(mDisplayPolicy));
- pw.println(" mShortTermModelTimeout=" + mShortTermModelTimeout);
+ pw.println(" mShortTermModelTimeout=" + mBrightnessMapper.getShortTermModelTimeout());
pw.println(" mShortTermModelAnchor=" + mShortTermModelAnchor);
pw.println(" mShortTermModelValid=" + mShortTermModelValid);
pw.println(" mBrightnessAdjustmentSamplePending=" + mBrightnessAdjustmentSamplePending);
@@ -552,20 +539,10 @@ class AutomaticBrightnessController {
// If the short term model was invalidated and the change is drastic enough, reset it.
if (!mShortTermModelValid && mShortTermModelAnchor != -1) {
- final float minAmbientLux =
- mShortTermModelAnchor - mShortTermModelAnchor * SHORT_TERM_MODEL_THRESHOLD_RATIO;
- final float maxAmbientLux =
- mShortTermModelAnchor + mShortTermModelAnchor * SHORT_TERM_MODEL_THRESHOLD_RATIO;
- if (minAmbientLux < mAmbientLux && mAmbientLux < maxAmbientLux) {
- if (mLoggingEnabled) {
- Slog.d(TAG, "ShortTermModel: re-validate user data, ambient lux is " +
- minAmbientLux + " < " + mAmbientLux + " < " + maxAmbientLux);
- }
- mShortTermModelValid = true;
- } else {
- Slog.d(TAG, "ShortTermModel: reset data, ambient lux is " + mAmbientLux +
- "(" + minAmbientLux + ", " + maxAmbientLux + ")");
+ if (mBrightnessMapper.shouldResetShortTermModel(mAmbientLux, mShortTermModelAnchor)) {
resetShortTermModel();
+ } else {
+ mShortTermModelValid = true;
}
}
}
diff --git a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
index 171cc5abdb97..ff0b01594bcf 100644
--- a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
+++ b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
@@ -47,6 +47,7 @@ public abstract class BrightnessMappingStrategy {
private static final float LUX_GRAD_SMOOTHING = 0.25f;
private static final float MAX_GRAD = 1.0f;
+ private static final float SHORT_TERM_MODEL_THRESHOLD_RATIO = 0.6f;
protected boolean mLoggingEnabled;
@@ -69,6 +70,9 @@ public abstract class BrightnessMappingStrategy {
int[] backlightRange = resources.getIntArray(
com.android.internal.R.array.config_screenBrightnessBacklight);
+ long shortTermModelTimeout = resources.getInteger(
+ com.android.internal.R.integer.config_autoBrightnessShortTermModelTimeout);
+
if (isValidMapping(nitsRange, backlightRange)
&& isValidMapping(luxLevels, brightnessLevelsNits)) {
int minimumBacklight = resources.getInteger(
@@ -82,11 +86,14 @@ public abstract class BrightnessMappingStrategy {
}
BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder(
luxLevels, brightnessLevelsNits);
+ builder.setShortTermModelTimeout(shortTermModelTimeout);
+ builder.setShortTermModelLowerLuxMultiplier(SHORT_TERM_MODEL_THRESHOLD_RATIO);
+ builder.setShortTermModelUpperLuxMultiplier(SHORT_TERM_MODEL_THRESHOLD_RATIO);
return new PhysicalMappingStrategy(builder.build(), nitsRange, backlightRange,
autoBrightnessAdjustmentMaxGamma);
} else if (isValidMapping(luxLevels, brightnessLevelsBacklight)) {
return new SimpleMappingStrategy(luxLevels, brightnessLevelsBacklight,
- autoBrightnessAdjustmentMaxGamma);
+ autoBrightnessAdjustmentMaxGamma, shortTermModelTimeout);
} else {
return null;
}
@@ -189,6 +196,12 @@ public abstract class BrightnessMappingStrategy {
public abstract boolean setBrightnessConfiguration(@Nullable BrightnessConfiguration config);
/**
+ * Gets the current {@link BrightnessConfiguration}.
+ */
+ @Nullable
+ public abstract BrightnessConfiguration getBrightnessConfiguration();
+
+ /**
* Returns the desired brightness of the display based on the current ambient lux, including
* any context-related corrections.
*
@@ -274,8 +287,53 @@ public abstract class BrightnessMappingStrategy {
/** @return The default brightness configuration. */
public abstract BrightnessConfiguration getDefaultConfig();
+
+ /**
+ * Returns the timeout for the short term model
+ *
+ * Timeout after which we remove the effects any user interactions might've had on the
+ * brightness mapping. This timeout doesn't start until we transition to a non-interactive
+ * display policy so that we don't reset while users are using their devices, but also so that
+ * we don't erroneously keep the short-term model if the device is dozing but the
+ * display is fully on.
+ */
+ public abstract long getShortTermModelTimeout();
+
public abstract void dump(PrintWriter pw);
+ /**
+ * Check if the short term model should be reset given the anchor lux the last
+ * brightness change was made at and the current ambient lux.
+ */
+ public boolean shouldResetShortTermModel(float ambientLux, float shortTermModelAnchor) {
+ BrightnessConfiguration config = getBrightnessConfiguration();
+ float minThresholdRatio = SHORT_TERM_MODEL_THRESHOLD_RATIO;
+ float maxThresholdRatio = SHORT_TERM_MODEL_THRESHOLD_RATIO;
+ if (config != null) {
+ if (!Float.isNaN(config.getShortTermModelLowerLuxMultiplier())) {
+ minThresholdRatio = config.getShortTermModelLowerLuxMultiplier();
+ }
+ if (!Float.isNaN(config.getShortTermModelUpperLuxMultiplier())) {
+ maxThresholdRatio = config.getShortTermModelUpperLuxMultiplier();
+ }
+ }
+ final float minAmbientLux =
+ shortTermModelAnchor - shortTermModelAnchor * minThresholdRatio;
+ final float maxAmbientLux =
+ shortTermModelAnchor + shortTermModelAnchor * maxThresholdRatio;
+ if (minAmbientLux < ambientLux && ambientLux <= maxAmbientLux) {
+ if (mLoggingEnabled) {
+ Slog.d(TAG, "ShortTermModel: re-validate user data, ambient lux is "
+ + minAmbientLux + " < " + ambientLux + " < " + maxAmbientLux);
+ }
+ return false;
+ } else {
+ Slog.d(TAG, "ShortTermModel: reset data, ambient lux is " + ambientLux
+ + "(" + minAmbientLux + ", " + maxAmbientLux + ")");
+ return true;
+ }
+ }
+
protected float normalizeAbsoluteBrightness(int brightness) {
brightness = MathUtils.constrain(brightness,
PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON);
@@ -455,8 +513,10 @@ public abstract class BrightnessMappingStrategy {
private float mAutoBrightnessAdjustment;
private float mUserLux;
private float mUserBrightness;
+ private long mShortTermModelTimeout;
- public SimpleMappingStrategy(float[] lux, int[] brightness, float maxGamma) {
+ private SimpleMappingStrategy(float[] lux, int[] brightness, float maxGamma,
+ long timeout) {
Preconditions.checkArgument(lux.length != 0 && brightness.length != 0,
"Lux and brightness arrays must not be empty!");
Preconditions.checkArgument(lux.length == brightness.length,
@@ -481,6 +541,12 @@ public abstract class BrightnessMappingStrategy {
PLOG.start("simple mapping strategy");
}
computeSpline();
+ mShortTermModelTimeout = timeout;
+ }
+
+ @Override
+ public long getShortTermModelTimeout() {
+ return mShortTermModelTimeout;
}
@Override
@@ -489,6 +555,11 @@ public abstract class BrightnessMappingStrategy {
}
@Override
+ public BrightnessConfiguration getBrightnessConfiguration() {
+ return null;
+ }
+
+ @Override
public float getBrightness(float lux, String packageName,
@ApplicationInfo.Category int category) {
return mSpline.interpolate(lux);
@@ -660,6 +731,15 @@ public abstract class BrightnessMappingStrategy {
}
@Override
+ public long getShortTermModelTimeout() {
+ if (mConfig.getShortTermModelTimeout() >= 0) {
+ return mConfig.getShortTermModelTimeout();
+ } else {
+ return mDefaultConfig.getShortTermModelTimeout();
+ }
+ }
+
+ @Override
public boolean setBrightnessConfiguration(@Nullable BrightnessConfiguration config) {
if (config == null) {
config = mDefaultConfig;
@@ -676,6 +756,11 @@ public abstract class BrightnessMappingStrategy {
}
@Override
+ public BrightnessConfiguration getBrightnessConfiguration() {
+ return mConfig;
+ }
+
+ @Override
public float getBrightness(float lux, String packageName,
@ApplicationInfo.Category int category) {
float nits = mBrightnessSpline.interpolate(lux);
diff --git a/services/core/java/com/android/server/display/DisplayDevice.java b/services/core/java/com/android/server/display/DisplayDevice.java
index 7ce63c5f89b2..e69a3b8ba4c1 100644
--- a/services/core/java/com/android/server/display/DisplayDevice.java
+++ b/services/core/java/com/android/server/display/DisplayDevice.java
@@ -138,18 +138,13 @@ abstract class DisplayDevice {
}
/**
- * Sets the refresh ranges, and display modes that the system is allowed to switch between.
- * Display modes are roughly ordered by preference.
+ * Sets the display mode specs.
*
* Not all display devices will automatically switch between modes, so it's important that the
- * most-desired modes are at the beginning of the allowed array.
- *
- * @param defaultModeId is used, if the device does not support multiple refresh
- * rates, and to navigate other parameters.
+ * default modeId is set correctly.
*/
- public void setDesiredDisplayConfigSpecs(int defaultModeId, float minRefreshRate,
- float maxRefreshRate, int[] modes) {
- }
+ public void setDesiredDisplayModeSpecsLocked(
+ DisplayModeDirector.DesiredDisplayModeSpecs displayModeSpecs) {}
/**
* Sets the requested color mode.
@@ -157,6 +152,24 @@ abstract class DisplayDevice {
public void setRequestedColorModeLocked(int colorMode) {
}
+ /**
+ * Sends the Auto Low Latency Mode (ALLM) signal over HDMI, or requests an internal display to
+ * switch to a low-latency mode.
+ *
+ * @param on Whether to set ALLM on or off.
+ */
+ public void setAutoLowLatencyModeLocked(boolean on) {
+ }
+
+ /**
+ * Sends a ContentType=Game signal over HDMI, or requests an internal display to switch to a
+ * game mode (generally lower latency).
+ *
+ * @param on Whether to send a ContentType=Game signal or not
+ */
+ public void setGameContentTypeLocked(boolean on) {
+ }
+
public void onOverlayChangedLocked() {
}
diff --git a/services/core/java/com/android/server/display/DisplayDeviceInfo.java b/services/core/java/com/android/server/display/DisplayDeviceInfo.java
index 729ea1772066..ac41434a1b5c 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceInfo.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceInfo.java
@@ -207,6 +207,16 @@ final class DisplayDeviceInfo {
public Display.HdrCapabilities hdrCapabilities;
/**
+ * Indicates whether this display supports Auto Low Latency Mode.
+ */
+ public boolean allmSupported;
+
+ /**
+ * Indicates whether this display suppors Game content type.
+ */
+ public boolean gameContentTypeSupported;
+
+ /**
* The nominal apparent density of the display in DPI used for layout calculations.
* This density is sensitive to the viewing distance. A big TV and a tablet may have
* the same apparent density even though the pixels on the TV are much bigger than
@@ -337,6 +347,8 @@ final class DisplayDeviceInfo {
|| !Arrays.equals(supportedModes, other.supportedModes)
|| !Arrays.equals(supportedColorModes, other.supportedColorModes)
|| !Objects.equals(hdrCapabilities, other.hdrCapabilities)
+ || allmSupported != other.allmSupported
+ || gameContentTypeSupported != other.gameContentTypeSupported
|| densityDpi != other.densityDpi
|| xDpi != other.xDpi
|| yDpi != other.yDpi
@@ -371,6 +383,8 @@ final class DisplayDeviceInfo {
colorMode = other.colorMode;
supportedColorModes = other.supportedColorModes;
hdrCapabilities = other.hdrCapabilities;
+ allmSupported = other.allmSupported;
+ gameContentTypeSupported = other.gameContentTypeSupported;
densityDpi = other.densityDpi;
xDpi = other.xDpi;
yDpi = other.yDpi;
@@ -400,6 +414,8 @@ final class DisplayDeviceInfo {
sb.append(", colorMode ").append(colorMode);
sb.append(", supportedColorModes ").append(Arrays.toString(supportedColorModes));
sb.append(", HdrCapabilities ").append(hdrCapabilities);
+ sb.append(", allmSupported ").append(allmSupported);
+ sb.append(", gameContentTypeSupported ").append(gameContentTypeSupported);
sb.append(", density ").append(densityDpi);
sb.append(", ").append(xDpi).append(" x ").append(yDpi).append(" dpi");
sb.append(", appVsyncOff ").append(appVsyncOffsetNanos);
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index d20191dd1f85..10386e70facb 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -431,7 +431,8 @@ public final class DisplayManagerService extends SystemService {
recordTopInsetLocked(mLogicalDisplays.get(Display.DEFAULT_DISPLAY));
}
- mDisplayModeDirector.setDisplayModeListener(new AllowedDisplayModeObserver());
+ mDisplayModeDirector.setDesiredDisplayModeSpecsListener(
+ new DesiredDisplayModeSpecsObserver());
mDisplayModeDirector.start(mSensorManager);
mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS);
@@ -1192,12 +1193,16 @@ public final class DisplayManagerService extends SystemService {
}
private void setDisplayPropertiesInternal(int displayId, boolean hasContent,
- float requestedRefreshRate, int requestedModeId, boolean inTraversal) {
+ float requestedRefreshRate, int requestedModeId, boolean requestedMinimalPostProcessing,
+ boolean inTraversal) {
synchronized (mSyncRoot) {
LogicalDisplay display = mLogicalDisplays.get(displayId);
if (display == null) {
return;
}
+
+ boolean shouldScheduleTraversal = false;
+
if (display.hasContentLocked() != hasContent) {
if (DEBUG) {
Slog.d(TAG, "Display " + displayId + " hasContent flag changed: "
@@ -1205,7 +1210,7 @@ public final class DisplayManagerService extends SystemService {
}
display.setHasContentLocked(hasContent);
- scheduleTraversalLocked(inTraversal);
+ shouldScheduleTraversal = true;
}
if (requestedModeId == 0 && requestedRefreshRate != 0) {
// Scan supported modes returned by display.getInfo() to find a mode with the same
@@ -1215,6 +1220,20 @@ public final class DisplayManagerService extends SystemService {
}
mDisplayModeDirector.getAppRequestObserver().setAppRequestedMode(
displayId, requestedModeId);
+
+
+ if (display.getDisplayInfoLocked().minimalPostProcessingSupported
+ && (display.getRequestedMinimalPostProcessingLocked()
+ != requestedMinimalPostProcessing)) {
+
+ display.setRequestedMinimalPostProcessingLocked(requestedMinimalPostProcessing);
+
+ shouldScheduleTraversal = true;
+ }
+
+ if (shouldScheduleTraversal) {
+ scheduleTraversalLocked(inTraversal);
+ }
}
}
@@ -1327,19 +1346,24 @@ public final class DisplayManagerService extends SystemService {
return SurfaceControl.getDisplayedContentSample(token, maxFrames, timestamp);
}
- private void onAllowedDisplayModesChangedInternal() {
+ private void onDesiredDisplayModeSpecsChangedInternal() {
boolean changed = false;
synchronized (mSyncRoot) {
final int count = mLogicalDisplays.size();
for (int i = 0; i < count; i++) {
LogicalDisplay display = mLogicalDisplays.valueAt(i);
int displayId = mLogicalDisplays.keyAt(i);
- int[] allowedModes = mDisplayModeDirector.getAllowedModes(displayId);
- // Note that order is important here since not all display devices are capable of
- // automatically switching, so we do actually want to check for equality and not
- // just equivalent contents (regardless of order).
- if (!Arrays.equals(allowedModes, display.getAllowedDisplayModesLocked())) {
- display.setAllowedDisplayModesLocked(allowedModes);
+ DisplayModeDirector.DesiredDisplayModeSpecs desiredDisplayModeSpecs =
+ mDisplayModeDirector.getDesiredDisplayModeSpecs(displayId);
+ DisplayModeDirector.DesiredDisplayModeSpecs existingDesiredDisplayModeSpecs =
+ display.getDesiredDisplayModeSpecsLocked();
+ if (DEBUG) {
+ Slog.i(TAG,
+ "Comparing display specs: " + desiredDisplayModeSpecs
+ + ", existing: " + existingDesiredDisplayModeSpecs);
+ }
+ if (!desiredDisplayModeSpecs.equals(existingDesiredDisplayModeSpecs)) {
+ display.setDesiredDisplayModeSpecsLocked(desiredDisplayModeSpecs);
changed = true;
}
}
@@ -2343,6 +2367,7 @@ public final class DisplayManagerService extends SystemService {
}
private final class LocalService extends DisplayManagerInternal {
+
@Override
public void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler,
SensorManager sensorManager) {
@@ -2431,9 +2456,10 @@ public final class DisplayManagerService extends SystemService {
@Override
public void setDisplayProperties(int displayId, boolean hasContent,
- float requestedRefreshRate, int requestedMode, boolean inTraversal) {
+ float requestedRefreshRate, int requestedMode,
+ boolean requestedMinimalPostProcessing, boolean inTraversal) {
setDisplayPropertiesInternal(displayId, hasContent, requestedRefreshRate,
- requestedMode, inTraversal);
+ requestedMode, requestedMinimalPostProcessing, inTraversal);
}
@Override
@@ -2488,9 +2514,10 @@ public final class DisplayManagerService extends SystemService {
}
- class AllowedDisplayModeObserver implements DisplayModeDirector.DisplayModeListener {
- public void onAllowedDisplayModesChanged() {
- onAllowedDisplayModesChangedInternal();
+ class DesiredDisplayModeSpecsObserver
+ implements DisplayModeDirector.DesiredDisplayModeSpecsListener {
+ public void onDesiredDisplayModeSpecsChanged() {
+ onDesiredDisplayModeSpecsChangedInternal();
}
}
}
diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java
index 2df682fa708c..ad728c18dd59 100644
--- a/services/core/java/com/android/server/display/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/DisplayModeDirector.java
@@ -63,7 +63,7 @@ public class DisplayModeDirector {
private static final String TAG = "DisplayModeDirector";
private static final boolean DEBUG = false;
- private static final int MSG_ALLOWED_MODES_CHANGED = 1;
+ private static final int MSG_REFRESH_RATE_RANGE_CHANGED = 1;
private static final int MSG_BRIGHTNESS_THRESHOLDS_CHANGED = 2;
private static final int MSG_DEFAULT_PEAK_REFRESH_RATE_CHANGED = 3;
private static final int MSG_REFRESH_RATE_IN_ZONE_CHANGED = 4;
@@ -95,7 +95,7 @@ public class DisplayModeDirector {
private final BrightnessObserver mBrightnessObserver;
private final DeviceConfigDisplaySettings mDeviceConfigDisplaySettings;
- private DisplayModeListener mDisplayModeListener;
+ private DesiredDisplayModeSpecsListener mDesiredDisplayModeSpecsListener;
public DisplayModeDirector(@NonNull Context context, @NonNull Handler handler) {
mContext = context;
@@ -125,23 +125,11 @@ public class DisplayModeDirector {
synchronized (mLock) {
// We may have a listener already registered before the call to start, so go ahead and
// notify them to pick up our newly initialized state.
- notifyAllowedModesChangedLocked();
+ notifyDesiredDisplayModeSpecsChangedLocked();
}
}
- /**
- * Calculates the modes the system is allowed to freely switch between based on global and
- * display-specific constraints.
- *
- * @param displayId The display to query for.
- * @return The IDs of the modes the system is allowed to freely switch between.
- */
- @NonNull
- public int[] getAllowedModes(int displayId) {
- return getDesiredDisplayConfigSpecs(displayId).allowedConfigs;
- }
-
@NonNull
private SparseArray<Vote> getVotesLocked(int displayId) {
SparseArray<Vote> displayVotes = mVotesByDisplay.get(displayId);
@@ -173,16 +161,16 @@ public class DisplayModeDirector {
* system is allowed to switch between.
*/
@NonNull
- public DesiredDisplayConfigSpecs getDesiredDisplayConfigSpecs(int displayId) {
+ public DesiredDisplayModeSpecs getDesiredDisplayModeSpecs(int displayId) {
synchronized (mLock) {
SparseArray<Vote> votes = getVotesLocked(displayId);
Display.Mode[] modes = mSupportedModesByDisplay.get(displayId);
Display.Mode defaultMode = mDefaultModeByDisplay.get(displayId);
if (modes == null || defaultMode == null) {
- Slog.e(TAG, "Asked about unknown display, returning empty desired configs!"
- + "(id=" + displayId + ")");
- return new DesiredDisplayConfigSpecs(displayId, new RefreshRateRange(60, 60),
- new int[0]);
+ Slog.e(TAG,
+ "Asked about unknown display, returning empty display mode specs!"
+ + "(id=" + displayId + ")");
+ return new DesiredDisplayModeSpecs();
}
int[] availableModes = new int[]{defaultMode.getModeId()};
@@ -255,9 +243,9 @@ public class DisplayModeDirector {
}
// filterModes function is going to filter the modes based on the voting system. If
// the application requests a given mode with preferredModeId function, it will be
- // stored as the first and only element in available modes array.
- return new DesiredDisplayConfigSpecs(defaultModeId,
- new RefreshRateRange(minRefreshRate, maxRefreshRate), availableModes);
+ // stored as defaultModeId.
+ return new DesiredDisplayModeSpecs(
+ defaultModeId, new RefreshRateRange(minRefreshRate, maxRefreshRate));
}
}
@@ -311,11 +299,13 @@ public class DisplayModeDirector {
}
/**
- * Sets the modeListener for changes to allowed display modes.
+ * Sets the desiredDisplayModeSpecsListener for changes to display mode and refresh rate
+ * ranges.
*/
- public void setDisplayModeListener(@Nullable DisplayModeListener displayModeListener) {
+ public void setDesiredDisplayModeSpecsListener(
+ @Nullable DesiredDisplayModeSpecsListener desiredDisplayModeSpecsListener) {
synchronized (mLock) {
- mDisplayModeListener = displayModeListener;
+ mDesiredDisplayModeSpecsListener = desiredDisplayModeSpecsListener;
}
}
@@ -389,16 +379,18 @@ public class DisplayModeDirector {
mVotesByDisplay.remove(displayId);
}
- notifyAllowedModesChangedLocked();
+ notifyDesiredDisplayModeSpecsChangedLocked();
}
- private void notifyAllowedModesChangedLocked() {
- if (mDisplayModeListener != null && !mHandler.hasMessages(MSG_ALLOWED_MODES_CHANGED)) {
+ private void notifyDesiredDisplayModeSpecsChangedLocked() {
+ if (mDesiredDisplayModeSpecsListener != null
+ && !mHandler.hasMessages(MSG_REFRESH_RATE_RANGE_CHANGED)) {
// We need to post this to a handler to avoid calling out while holding the lock
// since we know there are things that both listen for changes as well as provide
- // information. If we did call out while holding the lock, then there's no guaranteed
- // lock order and we run the real of risk deadlock.
- Message msg = mHandler.obtainMessage(MSG_ALLOWED_MODES_CHANGED, mDisplayModeListener);
+ // information. If we did call out while holding the lock, then there's no
+ // guaranteed lock order and we run the real of risk deadlock.
+ Message msg = mHandler.obtainMessage(
+ MSG_REFRESH_RATE_RANGE_CHANGED, mDesiredDisplayModeSpecsListener);
msg.sendToTarget();
}
}
@@ -430,13 +422,13 @@ public class DisplayModeDirector {
}
/**
- * Listens for changes to display mode coordination.
+ * Listens for changes refresh rate coordination.
*/
- public interface DisplayModeListener {
+ public interface DesiredDisplayModeSpecsListener {
/**
- * Called when the allowed display modes may have changed.
+ * Called when the refresh rate range may have changed.
*/
- void onAllowedDisplayModesChanged();
+ void onDesiredDisplayModeSpecsChanged();
}
private final class DisplayModeDirectorHandler extends Handler {
@@ -447,11 +439,6 @@ public class DisplayModeDirector {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
- case MSG_ALLOWED_MODES_CHANGED:
- DisplayModeListener displayModeListener = (DisplayModeListener) msg.obj;
- displayModeListener.onAllowedDisplayModesChanged();
- break;
-
case MSG_BRIGHTNESS_THRESHOLDS_CHANGED:
Pair<int[], int[]> thresholds = (Pair<int[], int[]>) msg.obj;
@@ -474,6 +461,12 @@ public class DisplayModeDirector {
mBrightnessObserver.onDeviceConfigRefreshRateInZoneChanged(
refreshRateInZone);
break;
+
+ case MSG_REFRESH_RATE_RANGE_CHANGED:
+ DesiredDisplayModeSpecsListener desiredDisplayModeSpecsListener =
+ (DesiredDisplayModeSpecsListener) msg.obj;
+ desiredDisplayModeSpecsListener.onDesiredDisplayModeSpecsChanged();
+ break;
}
}
}
@@ -485,11 +478,13 @@ public class DisplayModeDirector {
/**
* The lowest desired refresh rate.
*/
- public final float min;
+ public float min;
/**
* The highest desired refresh rate.
*/
- public final float max;
+ public float max;
+
+ public RefreshRateRange() {}
public RefreshRateRange(float min, float max) {
if (min < 0 || max < 0 || min > max) {
@@ -531,32 +526,32 @@ public class DisplayModeDirector {
}
/**
- * Information about the desired configuration to be set by the system. Includes the default
- * configuration ID, refresh rate range, and the list of policy decisions that influenced the
- * choice.
+ * Information about the desired display mode to be set by the system. Includes the default
+ * mode ID and refresh rate range.
+ *
+ * We have this class in addition to SurfaceControl.DesiredDisplayConfigSpecs to make clear the
+ * distinction between the config ID / physical index that
+ * SurfaceControl.DesiredDisplayConfigSpecs uses, and the mode ID used here.
*/
- public static final class DesiredDisplayConfigSpecs {
+ public static final class DesiredDisplayModeSpecs {
/**
- * Default configuration ID. This is what system defaults to for all other settings, or
+ * Default mode ID. This is what system defaults to for all other settings, or
* if the refresh rate range is not available.
*/
- public final int defaultModeId;
+ public int defaultModeId;
/**
* The refresh rate range.
*/
public final RefreshRateRange refreshRateRange;
- /**
- * For legacy reasons, keep a list of allowed configs.
- * TODO(b/142507213): Re-assess whether the list of allowed configs is still necessary.
- */
- public final int[] allowedConfigs;
- public DesiredDisplayConfigSpecs(int defaultModeId,
- @NonNull RefreshRateRange refreshRateRange,
- @NonNull int[] allowedConfigs) {
+ public DesiredDisplayModeSpecs() {
+ refreshRateRange = new RefreshRateRange();
+ }
+
+ public DesiredDisplayModeSpecs(
+ int defaultModeId, @NonNull RefreshRateRange refreshRateRange) {
this.defaultModeId = defaultModeId;
this.refreshRateRange = refreshRateRange;
- this.allowedConfigs = allowedConfigs;
}
/**
@@ -564,9 +559,8 @@ public class DisplayModeDirector {
*/
@Override
public String toString() {
- return "DesiredDisplayConfigSpecs(defaultModeId=" + defaultModeId
- + ", refreshRateRange=" + refreshRateRange.toString()
- + ", allowedConfigs=" + Arrays.toString(allowedConfigs) + ")";
+ return String.format("defaultModeId=%d min=%.0f max=%.0f", defaultModeId,
+ refreshRateRange.min, refreshRateRange.max);
}
/**
* Checks whether the two objects have the same values.
@@ -577,17 +571,16 @@ public class DisplayModeDirector {
return true;
}
- if (!(other instanceof DesiredDisplayConfigSpecs)) {
+ if (!(other instanceof DesiredDisplayModeSpecs)) {
return false;
}
- DesiredDisplayConfigSpecs desiredDisplayConfigSpecs =
- (DesiredDisplayConfigSpecs) other;
+ DesiredDisplayModeSpecs desiredDisplayModeSpecs = (DesiredDisplayModeSpecs) other;
- if (defaultModeId != desiredDisplayConfigSpecs.defaultModeId) {
+ if (defaultModeId != desiredDisplayModeSpecs.defaultModeId) {
return false;
}
- if (!refreshRateRange.equals(desiredDisplayConfigSpecs.refreshRateRange)) {
+ if (!refreshRateRange.equals(desiredDisplayModeSpecs.refreshRateRange)) {
return false;
}
return true;
@@ -597,6 +590,15 @@ public class DisplayModeDirector {
public int hashCode() {
return Objects.hash(defaultModeId, refreshRateRange);
}
+
+ /**
+ * Copy values from the other object.
+ */
+ public void copyFrom(DesiredDisplayModeSpecs other) {
+ defaultModeId = other.defaultModeId;
+ refreshRateRange.min = other.refreshRateRange.min;
+ refreshRateRange.max = other.refreshRateRange.max;
+ }
}
@VisibleForTesting
@@ -932,7 +934,7 @@ public class DisplayModeDirector {
mDefaultModeByDisplay.put(displayId, info.getDefaultMode());
}
if (changed) {
- notifyAllowedModesChangedLocked();
+ notifyDesiredDisplayModeSpecsChangedLocked();
}
}
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index e42545e111ed..f1655f0ed6e3 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -483,8 +483,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
+ initialLightSensorRate + ") to be less than or equal to "
+ "config_autoBrightnessLightSensorRate (" + lightSensorRate + ").");
}
- int shortTermModelTimeout = resources.getInteger(
- com.android.internal.R.integer.config_autoBrightnessShortTermModelTimeout);
String lightSensorType = resources.getString(
com.android.internal.R.string.config_displayLightSensorType);
@@ -498,8 +496,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mScreenBrightnessRangeMaximum, dozeScaleFactor, lightSensorRate,
initialLightSensorRate, brighteningLightDebounce, darkeningLightDebounce,
autoBrightnessResetAmbientLuxAfterWarmUp, ambientBrightnessThresholds,
- screenBrightnessThresholds, shortTermModelTimeout,
- context.getPackageManager());
+ screenBrightnessThresholds, context.getPackageManager());
} else {
mUseSoftwareAutoBrightnessConfig = false;
}
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 308c755a0868..eebc738ca26a 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -112,18 +112,19 @@ final class LocalDisplayAdapter extends DisplayAdapter {
activeColorMode = Display.COLOR_MODE_INVALID;
}
int[] colorModes = SurfaceControl.getDisplayColorModes(displayToken);
- int[] allowedConfigs = SurfaceControl.getAllowedDisplayConfigs(displayToken);
+ SurfaceControl.DesiredDisplayConfigSpecs desiredDisplayConfigSpecs =
+ SurfaceControl.getDesiredDisplayConfigSpecs(displayToken);
LocalDisplayDevice device = mDevices.get(physicalDisplayId);
if (device == null) {
// Display was added.
final boolean isInternal = mDevices.size() == 0;
- device = new LocalDisplayDevice(displayToken, physicalDisplayId,
- configs, activeConfig, allowedConfigs, colorModes, activeColorMode,
+ device = new LocalDisplayDevice(displayToken, physicalDisplayId, configs,
+ activeConfig, desiredDisplayConfigSpecs, colorModes, activeColorMode,
isInternal);
mDevices.put(physicalDisplayId, device);
sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED);
} else if (device.updatePhysicalDisplayInfoLocked(configs, activeConfig,
- allowedConfigs, colorModes, activeColorMode)) {
+ desiredDisplayConfigSpecs, colorModes, activeColorMode)) {
// Display properties changed.
sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_CHANGED);
}
@@ -172,15 +173,17 @@ final class LocalDisplayAdapter extends DisplayAdapter {
private int mDefaultModeId;
private int mActiveModeId;
private boolean mActiveModeInvalid;
- private int[] mAllowedModeIds;
- private float mMinRefreshRate;
- private float mMaxRefreshRate;
- private boolean mAllowedModeIdsInvalid;
+ private DisplayModeDirector.DesiredDisplayModeSpecs mDisplayModeSpecs =
+ new DisplayModeDirector.DesiredDisplayModeSpecs();
+ private boolean mDisplayModeSpecsInvalid;
private int mActivePhysIndex;
- private int[] mAllowedPhysIndexes;
private int mActiveColorMode;
private boolean mActiveColorModeInvalid;
private Display.HdrCapabilities mHdrCapabilities;
+ private boolean mAllmSupported;
+ private boolean mGameContentTypeSupported;
+ private boolean mAllmRequested;
+ private boolean mGameContentTypeRequested;
private boolean mSidekickActive;
private SidekickInternal mSidekickInternal;
@@ -188,13 +191,13 @@ final class LocalDisplayAdapter extends DisplayAdapter {
LocalDisplayDevice(IBinder displayToken, long physicalDisplayId,
SurfaceControl.PhysicalDisplayInfo[] physicalDisplayInfos, int activeDisplayInfo,
- int[] allowedDisplayInfos, int[] colorModes, int activeColorMode,
- boolean isInternal) {
+ SurfaceControl.DesiredDisplayConfigSpecs physicalDisplayConfigSpecs,
+ int[] colorModes, int activeColorMode, boolean isInternal) {
super(LocalDisplayAdapter.this, displayToken, UNIQUE_ID_PREFIX + physicalDisplayId);
mPhysicalDisplayId = physicalDisplayId;
mIsInternal = isInternal;
updatePhysicalDisplayInfoLocked(physicalDisplayInfos, activeDisplayInfo,
- allowedDisplayInfos, colorModes, activeColorMode);
+ physicalDisplayConfigSpecs, colorModes, activeColorMode);
updateColorModesLocked(colorModes, activeColorMode);
mSidekickInternal = LocalServices.getService(SidekickInternal.class);
if (mIsInternal) {
@@ -204,6 +207,8 @@ final class LocalDisplayAdapter extends DisplayAdapter {
mBacklight = null;
}
mHdrCapabilities = SurfaceControl.getHdrCapabilities(displayToken);
+ mAllmSupported = SurfaceControl.getAutoLowLatencyModeSupport(displayToken);
+ mGameContentTypeSupported = SurfaceControl.getGameContentTypeSupport(displayToken);
}
@Override
@@ -213,10 +218,10 @@ final class LocalDisplayAdapter extends DisplayAdapter {
public boolean updatePhysicalDisplayInfoLocked(
SurfaceControl.PhysicalDisplayInfo[] physicalDisplayInfos, int activeDisplayInfo,
- int[] allowedDisplayInfos, int[] colorModes, int activeColorMode) {
+ SurfaceControl.DesiredDisplayConfigSpecs physicalDisplayConfigSpecs,
+ int[] colorModes, int activeColorMode) {
mDisplayInfos = Arrays.copyOf(physicalDisplayInfos, physicalDisplayInfos.length);
mActivePhysIndex = activeDisplayInfo;
- mAllowedPhysIndexes = Arrays.copyOf(allowedDisplayInfos, allowedDisplayInfos.length);
// Build an updated list of all existing modes.
ArrayList<DisplayModeRecord> records = new ArrayList<DisplayModeRecord>();
boolean modesAdded = false;
@@ -264,6 +269,26 @@ final class LocalDisplayAdapter extends DisplayAdapter {
sendTraversalRequestLocked();
}
+ // Check whether surface flinger spontaneously changed display config specs out from
+ // under us. If so, schedule a traversal to reapply our display config specs.
+ if (mDisplayModeSpecs.defaultModeId != 0) {
+ int activeDefaultMode =
+ findMatchingModeIdLocked(physicalDisplayConfigSpecs.defaultConfig);
+ // If we can't map the defaultConfig index to a mode, then the physical display
+ // configs must have changed, and the code below for handling changes to the
+ // list of available modes will take care of updating display config specs.
+ if (activeDefaultMode != 0) {
+ if (mDisplayModeSpecs.defaultModeId != activeDefaultMode
+ || mDisplayModeSpecs.refreshRateRange.min
+ != physicalDisplayConfigSpecs.minRefreshRate
+ || mDisplayModeSpecs.refreshRateRange.max
+ != physicalDisplayConfigSpecs.maxRefreshRate) {
+ mDisplayModeSpecsInvalid = true;
+ sendTraversalRequestLocked();
+ }
+ }
+ }
+
boolean recordsChanged = records.size() != mSupportedModes.size() || modesAdded;
// If the records haven't changed then we're done here.
if (!recordsChanged) {
@@ -286,6 +311,17 @@ final class LocalDisplayAdapter extends DisplayAdapter {
mDefaultModeId = activeRecord.mMode.getModeId();
}
+ // Determine whether the display mode specs' default mode is still there.
+ if (mSupportedModes.indexOfKey(mDisplayModeSpecs.defaultModeId) < 0) {
+ if (mDisplayModeSpecs.defaultModeId != 0) {
+ Slog.w(TAG,
+ "DisplayModeSpecs default mode no longer available, using currently"
+ + " active mode as default.");
+ }
+ mDisplayModeSpecs.defaultModeId = activeRecord.mMode.getModeId();
+ mDisplayModeSpecsInvalid = true;
+ }
+
// Determine whether the active mode is still there.
if (mSupportedModes.indexOfKey(mActiveModeId) < 0) {
if (mActiveModeId != 0) {
@@ -296,21 +332,6 @@ final class LocalDisplayAdapter extends DisplayAdapter {
mActiveModeInvalid = true;
}
- // Determine what the currently allowed modes are
- mAllowedModeIds = new int[] { mActiveModeId };
- int[] allowedModeIds = new int[mAllowedPhysIndexes.length];
- int size = 0;
- for (int physIndex : mAllowedPhysIndexes) {
- int modeId = findMatchingModeIdLocked(physIndex);
- if (modeId > 0) {
- allowedModeIds[size++] = modeId;
- }
- }
-
- // If this is different from our desired allowed modes, then mark our current set as
- // invalid so we correct this on the next traversal.
- mAllowedModeIdsInvalid = !Arrays.equals(allowedModeIds, mAllowedModeIds);
-
// Schedule traversals so that we apply pending changes.
sendTraversalRequestLocked();
return true;
@@ -397,6 +418,8 @@ final class LocalDisplayAdapter extends DisplayAdapter {
mInfo.defaultModeId = mDefaultModeId;
mInfo.supportedModes = getDisplayModes(mSupportedModes);
mInfo.colorMode = mActiveColorMode;
+ mInfo.allmSupported = mAllmSupported;
+ mInfo.gameContentTypeSupported = mGameContentTypeSupported;
mInfo.supportedColorModes =
new int[mSupportedColorModes.size()];
for (int i = 0; i < mSupportedColorModes.size(); i++) {
@@ -624,10 +647,40 @@ final class LocalDisplayAdapter extends DisplayAdapter {
}
@Override
- public void setDesiredDisplayConfigSpecs(int defaultModeId, float minRefreshRate,
- float maxRefreshRate, int[] modes) {
- updateDesiredDisplayConfigSpecs(defaultModeId, minRefreshRate, maxRefreshRate);
- updateAllowedModesLocked(modes);
+ public void setDesiredDisplayModeSpecsLocked(
+ DisplayModeDirector.DesiredDisplayModeSpecs displayModeSpecs) {
+ if (displayModeSpecs.defaultModeId == 0) {
+ // Bail if the caller is requesting a null mode. We'll get called again shortly with
+ // a valid mode.
+ return;
+ }
+ int defaultPhysIndex = findDisplayInfoIndexLocked(displayModeSpecs.defaultModeId);
+ if (defaultPhysIndex < 0) {
+ // When a display is hotplugged, it's possible for a mode to be removed that was
+ // previously valid. Because of the way display changes are propagated through the
+ // framework, and the caching of the display mode specs in LogicalDisplay, it's
+ // possible we'll get called with a stale mode id that no longer represents a valid
+ // mode. This should only happen in extremely rare cases. A followup call will
+ // contain a valid mode id.
+ Slog.w(TAG,
+ "Ignoring request for invalid default mode id "
+ + displayModeSpecs.defaultModeId);
+ updateDeviceInfoLocked();
+ return;
+ }
+ if (mDisplayModeSpecsInvalid || !displayModeSpecs.equals(mDisplayModeSpecs)) {
+ mDisplayModeSpecsInvalid = false;
+ mDisplayModeSpecs.copyFrom(displayModeSpecs);
+ final IBinder token = getDisplayTokenLocked();
+ SurfaceControl.setDesiredDisplayConfigSpecs(token,
+ new SurfaceControl.DesiredDisplayConfigSpecs(defaultPhysIndex,
+ mDisplayModeSpecs.refreshRateRange.min,
+ mDisplayModeSpecs.refreshRateRange.max));
+ int activePhysIndex = SurfaceControl.getActiveConfig(token);
+ if (updateActiveModeLocked(activePhysIndex)) {
+ updateDeviceInfoLocked();
+ }
+ }
}
@Override
@@ -650,131 +703,66 @@ final class LocalDisplayAdapter extends DisplayAdapter {
mActiveModeInvalid = mActiveModeId == 0;
if (mActiveModeInvalid) {
Slog.w(TAG, "In unknown mode after setting allowed configs"
- + ": allowedPhysIndexes=" + mAllowedPhysIndexes
+ ", activePhysIndex=" + mActivePhysIndex);
}
return true;
}
- // TODO(b/142507213): Remove once refresh rates are plummed through to kernel.
- public void updateAllowedModesLocked(int[] allowedModes) {
- if (Arrays.equals(allowedModes, mAllowedModeIds) && !mAllowedModeIdsInvalid) {
- return;
+ public boolean requestColorModeLocked(int colorMode) {
+ if (mActiveColorMode == colorMode) {
+ return false;
}
- if (updateAllowedModesInternalLocked(allowedModes)) {
- updateDeviceInfoLocked();
+ if (!mSupportedColorModes.contains(colorMode)) {
+ Slog.w(TAG, "Unable to find color mode " + colorMode
+ + ", ignoring request.");
+ return false;
}
+ SurfaceControl.setActiveColorMode(getDisplayTokenLocked(), colorMode);
+ mActiveColorMode = colorMode;
+ mActiveColorModeInvalid = false;
+ return true;
}
- public void updateDesiredDisplayConfigSpecs(int defaultModeId, float minRefreshRate,
- float maxRefreshRate) {
- if (minRefreshRate == mMinRefreshRate
- && maxRefreshRate == mMaxRefreshRate
- && defaultModeId == mDefaultModeId) {
+ @Override
+ public void setAutoLowLatencyModeLocked(boolean on) {
+ if (mAllmRequested == on) {
return;
}
- if (updateDesiredDisplayConfigSpecsInternalLocked(defaultModeId, minRefreshRate,
- maxRefreshRate)) {
- updateDeviceInfoLocked();
- }
- }
- public boolean updateDesiredDisplayConfigSpecsInternalLocked(int defaultModeId,
- float minRefreshRate, float maxRefreshRate) {
- if (DEBUG) {
- Slog.w(TAG, "updateDesiredDisplayConfigSpecsInternalLocked("
- + "defaultModeId="
- + Integer.toString(defaultModeId)
- + ", minRefreshRate="
- + Float.toString(minRefreshRate)
- + ", maxRefreshRate="
- + Float.toString(minRefreshRate));
- }
+ mAllmRequested = on;
- final IBinder token = getDisplayTokenLocked();
- SurfaceControl.setDesiredDisplayConfigSpecs(token,
- new SurfaceControl.DesiredDisplayConfigSpecs(
- defaultModeId, minRefreshRate, maxRefreshRate));
- int activePhysIndex = SurfaceControl.getActiveConfig(token);
- return updateActiveModeLocked(activePhysIndex);
- }
-
- public boolean updateAllowedModesInternalLocked(int[] allowedModes) {
- if (DEBUG) {
- Slog.w(TAG, "updateAllowedModesInternalLocked(allowedModes="
- + Arrays.toString(allowedModes) + ")");
- }
- int[] allowedPhysIndexes = new int[allowedModes.length];
- int size = 0;
- for (int modeId : allowedModes) {
- int physIndex = findDisplayInfoIndexLocked(modeId);
- if (physIndex < 0) {
- Slog.w(TAG, "Requested mode ID " + modeId + " not available,"
- + " dropping from allowed set.");
- } else {
- allowedPhysIndexes[size++] = physIndex;
- }
+ if (!mAllmSupported) {
+ Slog.d(TAG, "Unable to set ALLM because the connected display "
+ + "does not support ALLM.");
+ return;
}
- // If we couldn't find one or more of the suggested allowed modes then we need to
- // shrink the array to its actual size.
- if (size != allowedModes.length) {
- allowedPhysIndexes = Arrays.copyOf(allowedPhysIndexes, size);
- }
+ SurfaceControl.setAutoLowLatencyMode(getDisplayTokenLocked(), on);
+ }
- // If we found no suitable modes, then we try again with the default mode which we
- // assume has a suitable physical config.
- if (size == 0) {
- if (DEBUG) {
- Slog.w(TAG, "No valid modes allowed, falling back to default mode (id="
- + mDefaultModeId + ")");
- }
- allowedModes = new int[] { mDefaultModeId };
- allowedPhysIndexes = new int[] { findDisplayInfoIndexLocked(mDefaultModeId) };
+ @Override
+ public void setGameContentTypeLocked(boolean on) {
+ if (mGameContentTypeRequested == on) {
+ return;
}
- mAllowedModeIds = allowedModes;
- mAllowedModeIdsInvalid = false;
-
- if (Arrays.equals(mAllowedPhysIndexes, allowedPhysIndexes)) {
- return false;
- }
- mAllowedPhysIndexes = allowedPhysIndexes;
+ mGameContentTypeRequested = on;
- if (DEBUG) {
- Slog.w(TAG, "Setting allowed physical configs: allowedPhysIndexes="
- + Arrays.toString(allowedPhysIndexes));
+ if (!mGameContentTypeSupported) {
+ Slog.d(TAG, "Unable to set game content type because the connected "
+ + "display does not support game content type.");
+ return;
}
- SurfaceControl.setAllowedDisplayConfigs(getDisplayTokenLocked(), allowedPhysIndexes);
- int activePhysIndex = SurfaceControl.getActiveConfig(getDisplayTokenLocked());
- return updateActiveModeLocked(activePhysIndex);
- }
-
- public boolean requestColorModeLocked(int colorMode) {
- if (mActiveColorMode == colorMode) {
- return false;
- }
- if (!mSupportedColorModes.contains(colorMode)) {
- Slog.w(TAG, "Unable to find color mode " + colorMode
- + ", ignoring request.");
- return false;
- }
- SurfaceControl.setActiveColorMode(getDisplayTokenLocked(), colorMode);
- mActiveColorMode = colorMode;
- mActiveColorModeInvalid = false;
- return true;
+ SurfaceControl.setGameContentType(getDisplayTokenLocked(), on);
}
@Override
public void dumpLocked(PrintWriter pw) {
super.dumpLocked(pw);
pw.println("mPhysicalDisplayId=" + mPhysicalDisplayId);
- pw.println("mAllowedPhysIndexes=" + Arrays.toString(mAllowedPhysIndexes));
- pw.println("mAllowedModeIds=" + Arrays.toString(mAllowedModeIds));
- pw.println("mMinRefreshRate=" + mMinRefreshRate);
- pw.println("mMaxRefreshRate=" + mMaxRefreshRate);
- pw.println("mAllowedModeIdsInvalid=" + mAllowedModeIdsInvalid);
+ pw.println("mDisplayModeSpecs={" + mDisplayModeSpecs + "}");
+ pw.println("mDisplayModeSpecsInvalid=" + mDisplayModeSpecsInvalid);
pw.println("mActivePhysIndex=" + mActivePhysIndex);
pw.println("mActiveModeId=" + mActiveModeId);
pw.println("mActiveColorMode=" + mActiveColorMode);
@@ -782,6 +770,10 @@ final class LocalDisplayAdapter extends DisplayAdapter {
pw.println("mState=" + Display.stateToString(mState));
pw.println("mBrightness=" + mBrightness);
pw.println("mBacklight=" + mBacklight);
+ pw.println("mAllmSupported=" + mAllmSupported);
+ pw.println("mAllmRequested=" + mAllmRequested);
+ pw.println("mGameContentTypeSupported" + mGameContentTypeSupported);
+ pw.println("mGameContentTypeRequested" + mGameContentTypeRequested);
pw.println("mDisplayInfos=");
for (int i = 0; i < mDisplayInfos.length; i++) {
pw.println(" " + mDisplayInfos[i]);
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index f4b2dc8cfc98..0c9445a05551 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -87,8 +87,11 @@ final class LogicalDisplay {
// True if the logical display has unique content.
private boolean mHasContent;
- private int[] mAllowedDisplayModes = new int[0];
private int mRequestedColorMode;
+ private boolean mRequestedMinimalPostProcessing;
+
+ private DisplayModeDirector.DesiredDisplayModeSpecs mDesiredDisplayModeSpecs =
+ new DisplayModeDirector.DesiredDisplayModeSpecs();
// The display offsets to apply to the display projection.
private int mDisplayOffsetX;
@@ -282,6 +285,8 @@ final class LogicalDisplay {
deviceInfo.supportedColorModes,
deviceInfo.supportedColorModes.length);
mBaseDisplayInfo.hdrCapabilities = deviceInfo.hdrCapabilities;
+ mBaseDisplayInfo.minimalPostProcessingSupported =
+ deviceInfo.allmSupported || deviceInfo.gameContentTypeSupported;
mBaseDisplayInfo.logicalDensityDpi = deviceInfo.densityDpi;
mBaseDisplayInfo.physicalXDpi = deviceInfo.xDpi;
mBaseDisplayInfo.physicalYDpi = deviceInfo.yDpi;
@@ -352,15 +357,18 @@ final class LogicalDisplay {
// Set the color mode and allowed display mode.
if (device == mPrimaryDisplayDevice) {
- // See ag/9588196 for correct values.
- device.setDesiredDisplayConfigSpecs(0, 60, 60, mAllowedDisplayModes);
+ device.setDesiredDisplayModeSpecsLocked(mDesiredDisplayModeSpecs);
device.setRequestedColorModeLocked(mRequestedColorMode);
} else {
// Reset to default for non primary displays
- device.setDesiredDisplayConfigSpecs(0, 60, 60, new int[] {0});
+ device.setDesiredDisplayModeSpecsLocked(
+ new DisplayModeDirector.DesiredDisplayModeSpecs());
device.setRequestedColorModeLocked(0);
}
+ device.setAutoLowLatencyModeLocked(mRequestedMinimalPostProcessing);
+ device.setGameContentTypeLocked(mRequestedMinimalPostProcessing);
+
// Only grab the display info now as it may have been changed based on the requests above.
final DisplayInfo displayInfo = getDisplayInfoLocked();
final DisplayDeviceInfo displayDeviceInfo = device.getDisplayDeviceInfoLocked();
@@ -462,17 +470,18 @@ final class LogicalDisplay {
}
/**
- * Sets the display modes the system is free to switch between.
+ * Sets the display configs the system can use.
*/
- public void setAllowedDisplayModesLocked(int[] modes) {
- mAllowedDisplayModes = modes;
+ public void setDesiredDisplayModeSpecsLocked(
+ DisplayModeDirector.DesiredDisplayModeSpecs specs) {
+ mDesiredDisplayModeSpecs = specs;
}
/**
- * Returns the display modes the system is free to switch between.
+ * Returns the display configs the system can choose.
*/
- public int[] getAllowedDisplayModesLocked() {
- return mAllowedDisplayModes;
+ public DisplayModeDirector.DesiredDisplayModeSpecs getDesiredDisplayModeSpecsLocked() {
+ return mDesiredDisplayModeSpecs;
}
/**
@@ -482,6 +491,23 @@ final class LogicalDisplay {
mRequestedColorMode = colorMode;
}
+ /**
+ * Returns the last requested minimal post processing setting.
+ */
+ public boolean getRequestedMinimalPostProcessingLocked() {
+ return mRequestedMinimalPostProcessing;
+ }
+
+ /**
+ * Instructs the connected display to do minimal post processing. This is implemented either
+ * via HDMI 2.1 ALLM or HDMI 1.4 ContentType=Game.
+ *
+ * @param on Whether to set minimal post processing on/off on the connected display.
+ */
+ public void setRequestedMinimalPostProcessingLocked(boolean on) {
+ mRequestedMinimalPostProcessing = on;
+ }
+
/** Returns the pending requested color mode. */
public int getRequestedColorModeLocked() {
return mRequestedColorMode;
@@ -531,7 +557,7 @@ final class LogicalDisplay {
pw.println("mDisplayId=" + mDisplayId);
pw.println("mLayerStack=" + mLayerStack);
pw.println("mHasContent=" + mHasContent);
- pw.println("mAllowedDisplayModes=" + Arrays.toString(mAllowedDisplayModes));
+ pw.println("mDesiredDisplayModeSpecs={" + mDesiredDisplayModeSpecs + "}");
pw.println("mRequestedColorMode=" + mRequestedColorMode);
pw.println("mDisplayOffset=(" + mDisplayOffsetX + ", " + mDisplayOffsetY + ")");
pw.println("mDisplayScalingDisabled=" + mDisplayScalingDisabled);
@@ -539,5 +565,6 @@ final class LogicalDisplay {
mPrimaryDisplayDevice.getNameLocked() : "null"));
pw.println("mBaseDisplayInfo=" + mBaseDisplayInfo);
pw.println("mOverrideDisplayInfo=" + mOverrideDisplayInfo);
+ pw.println("mRequestedMinimalPostProcessing=" + mRequestedMinimalPostProcessing);
}
}
diff --git a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
index 739dd64451e4..b6255d15795e 100644
--- a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
@@ -315,9 +315,9 @@ final class OverlayDisplayAdapter extends DisplayAdapter {
}
@Override
- public void setDesiredDisplayConfigSpecs(int defaultModeId, float minRefreshRate,
- float maxRefreshRate, int[] modes) {
- final int id = defaultModeId;
+ public void setDesiredDisplayModeSpecsLocked(
+ DisplayModeDirector.DesiredDisplayModeSpecs displayModeSpecs) {
+ final int id = displayModeSpecs.defaultModeId;
int index = -1;
if (id == 0) {
// Use the default.
diff --git a/services/core/java/com/android/server/incremental/IncrementalManagerService.java b/services/core/java/com/android/server/incremental/IncrementalManagerService.java
index 1b1a29293639..d673ec84c47e 100644
--- a/services/core/java/com/android/server/incremental/IncrementalManagerService.java
+++ b/services/core/java/com/android/server/incremental/IncrementalManagerService.java
@@ -17,8 +17,11 @@
package com.android.server.incremental;
import android.annotation.NonNull;
+import android.content.ComponentName;
import android.content.Context;
import android.content.pm.DataLoaderManager;
+import android.content.pm.DataLoaderParamsParcel;
+import android.content.pm.FileSystemControlParcel;
import android.content.pm.IDataLoader;
import android.content.pm.IDataLoaderStatusListener;
import android.os.Bundle;
@@ -27,8 +30,6 @@ import android.os.ResultReceiver;
import android.os.ServiceManager;
import android.os.ShellCallback;
import android.os.incremental.IIncrementalManager;
-import android.os.incremental.IncrementalDataLoaderParamsParcel;
-import android.os.incremental.IncrementalFileSystemControlParcel;
import android.util.Slog;
import java.io.FileDescriptor;
@@ -67,24 +68,26 @@ public class IncrementalManagerService extends IIncrementalManager.Stub {
mDataLoaderManager = mContext.getSystemService(DataLoaderManager.class);
ServiceManager.addService(BINDER_SERVICE_NAME, this);
// Starts and register IIncrementalManagerNative service
- // TODO(b/136132412): add jni implementation
+ mNativeInstance = nativeStartService();
}
+
/**
* Notifies native IIncrementalManager service that system is ready.
*/
public void systemReady() {
- // TODO(b/136132412): add jni implementation
+ nativeSystemReady(mNativeInstance);
}
/**
* Finds data loader service provider and binds to it. This requires PackageManager.
*/
@Override
- public boolean prepareDataLoader(int mountId, IncrementalFileSystemControlParcel control,
- IncrementalDataLoaderParamsParcel params,
+ public boolean prepareDataLoader(int mountId, FileSystemControlParcel control,
+ DataLoaderParamsParcel params,
IDataLoaderStatusListener listener) {
Bundle dataLoaderParams = new Bundle();
- dataLoaderParams.putCharSequence("packageName", params.packageName);
+ dataLoaderParams.putParcelable("componentName",
+ new ComponentName(params.packageName, params.className));
dataLoaderParams.putParcelable("control", control);
dataLoaderParams.putParcelable("params", params);
DataLoaderManager dataLoaderManager = mContext.getSystemService(DataLoaderManager.class);
@@ -108,8 +111,7 @@ public class IncrementalManagerService extends IIncrementalManager.Stub {
return false;
}
try {
- // TODO: fix file list
- dataLoader.start(null);
+ dataLoader.start();
return true;
} catch (RemoteException ex) {
return false;
@@ -138,10 +140,6 @@ public class IncrementalManagerService extends IIncrementalManager.Stub {
Slog.e(TAG, "Failed to retrieve data loader for ID=" + mountId);
return;
}
- try {
- dataLoader.onFileCreated(inode, metadata);
- } catch (RemoteException ex) {
- }
}
@Override
@@ -156,4 +154,8 @@ public class IncrementalManagerService extends IIncrementalManager.Stub {
(new IncrementalManagerShellCommand(mContext)).exec(
this, in, out, err, args, callback, resultReceiver);
}
+
+ private static native long nativeStartService();
+
+ private static native void nativeSystemReady(long nativeInstance);
}
diff --git a/services/core/java/com/android/server/incremental/IncrementalManagerShellCommand.java b/services/core/java/com/android/server/incremental/IncrementalManagerShellCommand.java
index d35e806b2685..5c18f5880146 100644
--- a/services/core/java/com/android/server/incremental/IncrementalManagerShellCommand.java
+++ b/services/core/java/com/android/server/incremental/IncrementalManagerShellCommand.java
@@ -19,11 +19,13 @@ package com.android.server.incremental;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.content.ComponentName;
import android.content.Context;
import android.content.IIntentReceiver;
import android.content.IIntentSender;
import android.content.Intent;
import android.content.IntentSender;
+import android.content.pm.DataLoaderParams;
import android.content.pm.InstallationFile;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
@@ -31,7 +33,6 @@ import android.os.Bundle;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.ShellCommand;
-import android.os.incremental.IncrementalDataLoaderParams;
import android.util.Slog;
import java.io.FileDescriptor;
@@ -54,6 +55,8 @@ public final class IncrementalManagerShellCommand extends ShellCommand {
private static final String TAG = "IncrementalShellCommand";
// Assuming the adb data loader is always installed on the device
private static final String LOADER_PACKAGE_NAME = "com.android.incremental.nativeadb";
+ private static final String LOADER_CLASS_NAME =
+ LOADER_PACKAGE_NAME + ".NativeAdbDataLoaderService";
private final @NonNull Context mContext;
private static final int ERROR_INVALID_ARGUMENTS = -1;
@@ -111,14 +114,15 @@ public final class IncrementalManagerShellCommand extends ShellCommand {
pw.println("File names and sizes don't match.");
return ERROR_DATA_LOADER_INIT;
}
- final IncrementalDataLoaderParams params = new IncrementalDataLoaderParams(
- "", LOADER_PACKAGE_NAME, dataLoaderDynamicArgs);
+ final DataLoaderParams params = DataLoaderParams.forIncremental(
+ new ComponentName(LOADER_PACKAGE_NAME, LOADER_CLASS_NAME), "",
+ dataLoaderDynamicArgs);
PackageInstaller.SessionParams sessionParams = new PackageInstaller.SessionParams(
PackageInstaller.SessionParams.MODE_FULL_INSTALL);
sessionParams.installFlags |= PackageManager.INSTALL_ALL_USERS;
// Replace existing if same package is already installed
sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
- sessionParams.setIncrementalParams(params);
+ sessionParams.setDataLoaderParams(params);
try {
int sessionId = packageInstaller.createSession(sessionParams);
diff --git a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
index d71ffb770cc3..58f6ba2fd67f 100644
--- a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
+++ b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
@@ -762,6 +762,7 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
if (mUpdatingPackageNames != null) {
pw.print("Packages being updated: "); pw.println(mUpdatingPackageNames);
}
+ dumpSupportedUsers(pw, prefix);
if (mServiceNameResolver != null) {
pw.print(prefix); pw.print("Name resolver: ");
mServiceNameResolver.dumpShort(pw); pw.println();
diff --git a/services/core/java/com/android/server/input/ConfigurationProcessor.java b/services/core/java/com/android/server/input/ConfigurationProcessor.java
index 970e86acf8b8..3888b1b71096 100644
--- a/services/core/java/com/android/server/input/ConfigurationProcessor.java
+++ b/services/core/java/com/android/server/input/ConfigurationProcessor.java
@@ -17,7 +17,6 @@
package com.android.server.input;
import android.text.TextUtils;
-import android.util.Pair;
import android.util.Slog;
import android.util.Xml;
@@ -29,7 +28,9 @@ import org.xmlpull.v1.XmlPullParser;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
class ConfigurationProcessor {
@@ -86,9 +87,9 @@ class ConfigurationProcessor {
* the second item in the pair is the display port.
*/
@VisibleForTesting
- static List<Pair<String, String>> processInputPortAssociations(InputStream xml)
+ static Map<String, Integer> processInputPortAssociations(InputStream xml)
throws Exception {
- List<Pair<String, String>> associations = new ArrayList<>();
+ Map<String, Integer> associations = new HashMap<String, Integer>();
try (InputStreamReader confReader = new InputStreamReader(xml)) {
XmlPullParser parser = Xml.newPullParser();
parser.setInput(confReader);
@@ -101,19 +102,18 @@ class ConfigurationProcessor {
break;
}
String inputPort = parser.getAttributeValue(null, "input");
- String displayPort = parser.getAttributeValue(null, "display");
- if (TextUtils.isEmpty(inputPort) || TextUtils.isEmpty(displayPort)) {
+ String displayPortStr = parser.getAttributeValue(null, "display");
+ if (TextUtils.isEmpty(inputPort) || TextUtils.isEmpty(displayPortStr)) {
// This is likely an error by an OEM during device configuration
Slog.wtf(TAG, "Ignoring incomplete entry");
continue;
}
try {
- Integer.parseUnsignedInt(displayPort);
+ int displayPort = Integer.parseUnsignedInt(displayPortStr);
+ associations.put(inputPort, displayPort);
} catch (NumberFormatException e) {
Slog.wtf(TAG, "Display port should be an integer");
- continue;
}
- associations.add(new Pair<>(inputPort, displayPort));
}
}
return associations;
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 16b7d9951ad4..bf73aa39c581 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -64,7 +64,6 @@ import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.text.TextUtils;
import android.util.Log;
-import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.view.Display;
@@ -113,8 +112,8 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
+import java.util.Map;
import java.util.Objects;
-
/*
* Wraps the C++ InputManager and provides its callbacks.
*/
@@ -184,6 +183,10 @@ public class InputManagerService extends IInputManager.Stub
IInputFilter mInputFilter; // guarded by mInputFilterLock
InputFilterHost mInputFilterHost; // guarded by mInputFilterLock
+ // The associations of input devices to displays by port. Maps from input device port (String)
+ // to display id (int). Currently only accessed by InputReader.
+ private final Map<String, Integer> mStaticAssociations;
+
private static native long nativeInit(InputManagerService service,
Context context, MessageQueue messageQueue);
private static native void nativeStart(long ptr);
@@ -314,6 +317,7 @@ public class InputManagerService extends IInputManager.Stub
this.mContext = context;
this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());
+ mStaticAssociations = loadStaticInputPortAssociations();
mUseDevInputEventForAudioJack =
context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
@@ -1727,6 +1731,17 @@ public class InputManagerService extends IInputManager.Stub
String dumpStr = nativeDump(mPtr);
if (dumpStr != null) {
pw.println(dumpStr);
+ dumpAssociations(pw);
+ }
+ }
+
+ private void dumpAssociations(PrintWriter pw) {
+ if (!mStaticAssociations.isEmpty()) {
+ pw.println("Static Associations:");
+ mStaticAssociations.forEach((k, v) -> {
+ pw.print(" port: " + k);
+ pw.println(" display: " + v);
+ });
}
}
@@ -1910,15 +1925,16 @@ public class InputManagerService extends IInputManager.Stub
}
/**
- * Flatten a list of pairs into a list, with value positioned directly next to the key
+ * Flatten a map into a string list, with value positioned directly next to the
+ * key.
* @return Flattened list
*/
- private static <T> List<T> flatten(@NonNull List<Pair<T, T>> pairs) {
- List<T> list = new ArrayList<>(pairs.size() * 2);
- for (Pair<T, T> pair : pairs) {
- list.add(pair.first);
- list.add(pair.second);
- }
+ private static List<String> flatten(@NonNull Map<String, Integer> map) {
+ List<String> list = new ArrayList<>(map.size() * 2);
+ map.forEach((k, v)-> {
+ list.add(k);
+ list.add(v.toString());
+ });
return list;
}
@@ -1926,23 +1942,26 @@ public class InputManagerService extends IInputManager.Stub
* Ports are highly platform-specific, so only allow these to be specified in the vendor
* directory.
*/
- // Native callback
- private static String[] getInputPortAssociations() {
+ private static Map<String, Integer> loadStaticInputPortAssociations() {
File baseDir = Environment.getVendorDirectory();
File confFile = new File(baseDir, PORT_ASSOCIATIONS_PATH);
try {
InputStream stream = new FileInputStream(confFile);
- List<Pair<String, String>> associations =
- ConfigurationProcessor.processInputPortAssociations(stream);
- List<String> associationList = flatten(associations);
- return associationList.toArray(new String[0]);
+ return ConfigurationProcessor.processInputPortAssociations(stream);
} catch (FileNotFoundException e) {
// Most of the time, file will not exist, which is expected.
} catch (Exception e) {
Slog.e(TAG, "Could not parse '" + confFile.getAbsolutePath() + "'", e);
}
- return new String[0];
+
+ return new HashMap<>();
+ }
+
+ // Native callback
+ private String[] getInputPortAssociations() {
+ List<String> associationList = flatten(mStaticAssociations);
+ return associationList.toArray(new String[0]);
}
/**
diff --git a/services/core/java/com/android/server/integrity/AppIntegrityManagerService.java b/services/core/java/com/android/server/integrity/AppIntegrityManagerService.java
index 005fb696b089..3762ebb0b902 100644
--- a/services/core/java/com/android/server/integrity/AppIntegrityManagerService.java
+++ b/services/core/java/com/android/server/integrity/AppIntegrityManagerService.java
@@ -37,7 +37,7 @@ public class AppIntegrityManagerService extends SystemService {
@Override
public void onStart() {
- mService = new AppIntegrityManagerServiceImpl(mContext);
- // TODO: define and publish a binder service.
+ mService = AppIntegrityManagerServiceImpl.create(mContext);
+ publishBinderService(Context.APP_INTEGRITY_SERVICE, mService);
}
}
diff --git a/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java b/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
index 39c1b8535565..33e12c6d4fec 100644
--- a/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
+++ b/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
@@ -17,40 +17,115 @@
package com.android.server.integrity;
import static android.content.Intent.ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION;
+import static android.content.Intent.EXTRA_ORIGINATING_UID;
+import static android.content.Intent.EXTRA_PACKAGE_NAME;
+import static android.content.Intent.EXTRA_VERSION_CODE;
+import static android.content.integrity.AppIntegrityManager.EXTRA_STATUS;
+import static android.content.integrity.AppIntegrityManager.STATUS_FAILURE;
+import static android.content.integrity.AppIntegrityManager.STATUS_SUCCESS;
import static android.content.pm.PackageManager.EXTRA_VERIFICATION_ID;
+import static com.android.server.integrity.IntegrityUtils.getHexDigest;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.IntentSender;
+import android.content.integrity.AppInstallMetadata;
+import android.content.integrity.IAppIntegrityManager;
+import android.content.integrity.Rule;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
+import android.content.pm.ParceledListSlice;
+import android.content.pm.Signature;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
+import android.os.RemoteException;
import android.util.Slog;
+import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.LocalServices;
+import com.android.server.integrity.engine.RuleEvaluationEngine;
+import com.android.server.integrity.model.IntegrityCheckResult;
+import com.android.server.integrity.model.RuleMetadata;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.HashMap;
+import java.util.Map;
/** Implementation of {@link AppIntegrityManagerService}. */
-class AppIntegrityManagerServiceImpl {
+public class AppIntegrityManagerServiceImpl extends IAppIntegrityManager.Stub {
private static final String TAG = "AppIntegrityManagerServiceImpl";
+ private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
+ private static final char[] HEX_CHARS = "0123456789ABCDEF".toCharArray();
+ private static final String PACKAGE_INSTALLER = "com.google.android.packageinstaller";
+ private static final String BASE_APK_FILE = "base.apk";
+ private static final String ALLOWED_INSTALLERS_METADATA_NAME = "allowed-installers";
+ private static final String ALLOWED_INSTALLER_DELIMITER = ",";
+ private static final String INSTALLER_PACKAGE_CERT_DELIMITER = "\\|";
+
+ private static final String ADB_INSTALLER = "adb";
+ private static final String UNKNOWN_INSTALLER = "";
+ private static final String INSTALLER_CERT_NOT_APPLICABLE = "";
+
+ // Access to files inside mRulesDir is protected by mRulesLock;
private final Context mContext;
private final Handler mHandler;
private final PackageManagerInternal mPackageManagerInternal;
+ private final RuleEvaluationEngine mEvaluationEngine;
+ private final IntegrityFileManager mIntegrityFileManager;
- AppIntegrityManagerServiceImpl(Context context) {
- mContext = context;
-
+ /** Create an instance of {@link AppIntegrityManagerServiceImpl}. */
+ public static AppIntegrityManagerServiceImpl create(Context context) {
HandlerThread handlerThread = new HandlerThread("AppIntegrityManagerServiceHandler");
handlerThread.start();
- mHandler = handlerThread.getThreadHandler();
- mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
+ return new AppIntegrityManagerServiceImpl(
+ context,
+ LocalServices.getService(PackageManagerInternal.class),
+ RuleEvaluationEngine.getRuleEvaluationEngine(),
+ IntegrityFileManager.getInstance(),
+ handlerThread.getThreadHandler());
+ }
+
+ @VisibleForTesting
+ AppIntegrityManagerServiceImpl(
+ Context context,
+ PackageManagerInternal packageManagerInternal,
+ RuleEvaluationEngine evaluationEngine,
+ IntegrityFileManager integrityFileManager,
+ Handler handler) {
+ mContext = context;
+ mPackageManagerInternal = packageManagerInternal;
+ mEvaluationEngine = evaluationEngine;
+ mIntegrityFileManager = integrityFileManager;
+ mHandler = handler;
IntentFilter integrityVerificationFilter = new IntentFilter();
integrityVerificationFilter.addAction(ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION);
+ try {
+ integrityVerificationFilter.addDataType(PACKAGE_MIME_TYPE);
+ } catch (IntentFilter.MalformedMimeTypeException e) {
+ throw new RuntimeException("Mime type malformed: should never happen.", e);
+ }
mContext.registerReceiver(
new BroadcastReceiver() {
@@ -68,13 +143,410 @@ class AppIntegrityManagerServiceImpl {
mHandler);
}
- // protected broadcasts cannot be sent in the test.
- @VisibleForTesting
- void handleIntegrityVerification(Intent intent) {
+ @Override
+ public void updateRuleSet(
+ String version, ParceledListSlice<Rule> rules, IntentSender statusReceiver)
+ throws RemoteException {
+ String ruleProvider = getCallerPackageNameOrThrow();
+
+ mHandler.post(
+ () -> {
+ boolean success = true;
+ try {
+ mIntegrityFileManager.writeRules(version, ruleProvider, rules.getList());
+ } catch (Exception e) {
+ Slog.e(TAG, "Error writing rules.", e);
+ success = false;
+ }
+
+ Intent intent = new Intent();
+ intent.putExtra(EXTRA_STATUS, success ? STATUS_SUCCESS : STATUS_FAILURE);
+ try {
+ statusReceiver.sendIntent(
+ mContext,
+ /* code= */ 0,
+ intent,
+ /* onFinished= */ null,
+ /* handler= */ null);
+ } catch (IntentSender.SendIntentException e) {
+ Slog.e(TAG, "Error sending status feedback.", e);
+ }
+ });
+ }
+
+ @Override
+ public String getCurrentRuleSetVersion() throws RemoteException {
+ getCallerPackageNameOrThrow();
+
+ RuleMetadata ruleMetadata = mIntegrityFileManager.readMetadata();
+ return (ruleMetadata != null && ruleMetadata.getVersion() != null)
+ ? ruleMetadata.getVersion()
+ : "";
+ }
+
+ @Override
+ public String getCurrentRuleSetProvider() throws RemoteException {
+ getCallerPackageNameOrThrow();
+
+ RuleMetadata ruleMetadata = mIntegrityFileManager.readMetadata();
+ return (ruleMetadata != null && ruleMetadata.getRuleProvider() != null)
+ ? ruleMetadata.getRuleProvider()
+ : "";
+ }
+
+ private void handleIntegrityVerification(Intent intent) {
int verificationId = intent.getIntExtra(EXTRA_VERIFICATION_ID, -1);
- // TODO: implement this method.
- Slog.i(TAG, "Received integrity verification intent " + intent.toString());
- mPackageManagerInternal.setIntegrityVerificationResult(
- verificationId, PackageManager.VERIFICATION_ALLOW);
+
+ // Fail early if we don't have any rules at all.
+ if (!mIntegrityFileManager.initialized()) {
+ Slog.i(TAG, "Rules not initialized. Skipping integrity check.");
+ mPackageManagerInternal.setIntegrityVerificationResult(
+ verificationId, PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
+ return;
+ }
+
+ try {
+ Slog.i(TAG, "Received integrity verification intent " + intent.toString());
+ Slog.i(TAG, "Extras " + intent.getExtras());
+
+ String packageName = intent.getStringExtra(EXTRA_PACKAGE_NAME);
+
+ PackageInfo packageInfo = getPackageArchiveInfo(intent.getData());
+ if (packageInfo == null) {
+ Slog.w(TAG, "Cannot parse package " + packageName);
+ // We can't parse the package.
+ mPackageManagerInternal.setIntegrityVerificationResult(
+ verificationId, PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
+ return;
+ }
+
+ String installerPackageName = getInstallerPackageName(intent);
+ String appCert = getCertificateFingerprint(packageInfo);
+
+ AppInstallMetadata.Builder builder = new AppInstallMetadata.Builder();
+
+ builder.setPackageName(getPackageNameNormalized(packageName));
+ builder.setAppCertificate(appCert == null ? "" : appCert);
+ builder.setVersionCode(intent.getIntExtra(EXTRA_VERSION_CODE, -1));
+ builder.setInstallerName(getPackageNameNormalized(installerPackageName));
+ builder.setInstallerCertificate(
+ getInstallerCertificateFingerprint(installerPackageName));
+ builder.setIsPreInstalled(isSystemApp(packageName));
+
+ AppInstallMetadata appInstallMetadata = builder.build();
+ Map<String, String> allowedInstallers = getAllowedInstallers(packageInfo);
+
+ Slog.i(
+ TAG,
+ "To be verified: " + appInstallMetadata + " installers " + allowedInstallers);
+ IntegrityCheckResult result =
+ mEvaluationEngine.evaluate(appInstallMetadata, allowedInstallers);
+ Slog.i(
+ TAG,
+ "Integrity check result: "
+ + result.getEffect()
+ + " due to "
+ + result.getRule());
+ mPackageManagerInternal.setIntegrityVerificationResult(
+ verificationId,
+ result.getEffect() == IntegrityCheckResult.Effect.ALLOW
+ ? PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW
+ : PackageManagerInternal.INTEGRITY_VERIFICATION_REJECT);
+ } catch (IllegalArgumentException e) {
+ // This exception indicates something is wrong with the input passed by package manager.
+ // e.g., someone trying to trick the system. We block installs in this case.
+ Slog.e(TAG, "Invalid input to integrity verification", e);
+ mPackageManagerInternal.setIntegrityVerificationResult(
+ verificationId, PackageManagerInternal.INTEGRITY_VERIFICATION_REJECT);
+ } catch (Exception e) {
+ // Other exceptions indicate an error within the integrity component implementation and
+ // we allow them.
+ Slog.e(TAG, "Error handling integrity verification", e);
+ mPackageManagerInternal.setIntegrityVerificationResult(
+ verificationId, PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
+ }
+ }
+
+ /**
+ * Verify the UID and return the installer package name.
+ *
+ * @return the package name of the installer, or null if it cannot be determined or it is
+ * installed via adb.
+ */
+ @Nullable
+ private String getInstallerPackageName(Intent intent) {
+ String installer =
+ intent.getStringExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_PACKAGE);
+ if (installer == null) {
+ return ADB_INSTALLER;
+ }
+ int installerUid = intent.getIntExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_UID, -1);
+ if (installerUid < 0) {
+ Slog.e(
+ TAG,
+ "Installer cannot be determined: installer: "
+ + installer
+ + " installer UID: "
+ + installerUid);
+ return UNKNOWN_INSTALLER;
+ }
+
+ try {
+ int actualInstallerUid =
+ mContext.getPackageManager().getPackageUid(installer, /* flags= */ 0);
+ if (actualInstallerUid != installerUid) {
+ // Installer package name can be faked but the installerUid cannot.
+ Slog.e(
+ TAG,
+ "Installer "
+ + installer
+ + " has UID "
+ + actualInstallerUid
+ + " which doesn't match alleged installer UID "
+ + installerUid);
+ return UNKNOWN_INSTALLER;
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ Slog.e(TAG, "Installer package " + installer + " not found.");
+ return UNKNOWN_INSTALLER;
+ }
+
+ // At this time we can trust "installer".
+
+ // A common way for apps to install packages is to send an intent to PackageInstaller. In
+ // that case, the installer will always show up as PackageInstaller which is not what we
+ // want.
+ if (installer.equals(PACKAGE_INSTALLER)) {
+ int originatingUid = intent.getIntExtra(EXTRA_ORIGINATING_UID, -1);
+ if (originatingUid < 0) {
+ Slog.e(TAG, "Installer is package installer but originating UID not found.");
+ return UNKNOWN_INSTALLER;
+ }
+ String[] installerPackages =
+ mContext.getPackageManager().getPackagesForUid(originatingUid);
+ if (installerPackages == null || installerPackages.length == 0) {
+ Slog.e(TAG, "No package found associated with originating UID " + originatingUid);
+ return UNKNOWN_INSTALLER;
+ }
+ // In the case of multiple package sharing a UID, we just return the first one.
+ return installerPackages[0];
+ }
+
+ return installer;
+ }
+
+ /** We will use the SHA256 digest of a package name if it is more than 32 bytes long. */
+ private String getPackageNameNormalized(String packageName) {
+ if (packageName.length() <= 32) {
+ return packageName;
+ }
+
+ try {
+ MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
+ byte[] hashBytes = messageDigest.digest(packageName.getBytes(StandardCharsets.UTF_8));
+ return getHexDigest(hashBytes);
+ } catch (NoSuchAlgorithmException e) {
+ throw new RuntimeException("SHA-256 algorithm not found", e);
+ }
+ }
+
+ private String getCertificateFingerprint(@NonNull PackageInfo packageInfo) {
+ return getFingerprint(getSignature(packageInfo));
+ }
+
+ private String getInstallerCertificateFingerprint(String installer) {
+ if (installer.equals(ADB_INSTALLER) || installer.equals(UNKNOWN_INSTALLER)) {
+ return INSTALLER_CERT_NOT_APPLICABLE;
+ }
+ try {
+ PackageInfo installerInfo =
+ mContext.getPackageManager()
+ .getPackageInfo(installer, PackageManager.GET_SIGNATURES);
+ return getCertificateFingerprint(installerInfo);
+ } catch (PackageManager.NameNotFoundException e) {
+ Slog.i(TAG, "Installer package " + installer + " not found.");
+ return "";
+ }
+ }
+
+ /** Get the allowed installers and their associated certificate hashes from <meta-data> tag. */
+ private Map<String, String> getAllowedInstallers(@NonNull PackageInfo packageInfo) {
+ Map<String, String> packageCertMap = new HashMap<>();
+ if (packageInfo.applicationInfo != null && packageInfo.applicationInfo.metaData != null) {
+ Bundle metaData = packageInfo.applicationInfo.metaData;
+ String allowedInstallers = metaData.getString(ALLOWED_INSTALLERS_METADATA_NAME);
+ if (allowedInstallers != null) {
+ // parse the metadata for certs.
+ String[] installerCertPairs = allowedInstallers.split(ALLOWED_INSTALLER_DELIMITER);
+ for (String packageCertPair : installerCertPairs) {
+ String[] packageAndCert =
+ packageCertPair.split(INSTALLER_PACKAGE_CERT_DELIMITER);
+ if (packageAndCert.length == 2) {
+ String packageName = getPackageNameNormalized(packageAndCert[0]);
+ String cert = packageAndCert[1];
+ packageCertMap.put(packageName, cert);
+ }
+ }
+ }
+ }
+
+ return packageCertMap;
+ }
+
+ private static Signature getSignature(@NonNull PackageInfo packageInfo) {
+ if (packageInfo.signatures == null || packageInfo.signatures.length < 1) {
+ throw new IllegalArgumentException("Package signature not found in " + packageInfo);
+ }
+ // Only the first element is guaranteed to be present.
+ return packageInfo.signatures[0];
+ }
+
+ private static String getFingerprint(Signature cert) {
+ InputStream input = new ByteArrayInputStream(cert.toByteArray());
+
+ CertificateFactory factory;
+ try {
+ factory = CertificateFactory.getInstance("X509");
+ } catch (CertificateException e) {
+ throw new RuntimeException("Error getting CertificateFactory", e);
+ }
+ X509Certificate certificate = null;
+ try {
+ if (factory != null) {
+ certificate = (X509Certificate) factory.generateCertificate(input);
+ }
+ } catch (CertificateException e) {
+ throw new RuntimeException("Error getting X509Certificate", e);
+ }
+
+ if (certificate == null) {
+ throw new RuntimeException("X509 Certificate not found");
+ }
+
+ try {
+ MessageDigest digest = MessageDigest.getInstance("SHA-256");
+ byte[] publicKey = digest.digest(certificate.getEncoded());
+ return getHexDigest(publicKey);
+ } catch (NoSuchAlgorithmException | CertificateEncodingException e) {
+ throw new IllegalArgumentException("Error error computing fingerprint", e);
+ }
+ }
+
+ private PackageInfo getPackageArchiveInfo(Uri dataUri) {
+ File installationPath = getInstallationPath(dataUri);
+ if (installationPath == null) {
+ throw new IllegalArgumentException("Installation path is null, package not found");
+ }
+ PackageInfo packageInfo;
+ try {
+ // The installation path will be a directory for a multi-apk install on L+
+ if (installationPath.isDirectory()) {
+ packageInfo = getMultiApkInfo(installationPath);
+ } else {
+ packageInfo =
+ mContext.getPackageManager()
+ .getPackageArchiveInfo(
+ installationPath.getPath(),
+ PackageManager.GET_SIGNATURES
+ | PackageManager.GET_META_DATA);
+ }
+ return packageInfo;
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Exception reading " + dataUri, e);
+ }
+ }
+
+ private PackageInfo getMultiApkInfo(File multiApkDirectory) {
+ // The base apk will normally be called base.apk
+ File baseFile = new File(multiApkDirectory, BASE_APK_FILE);
+ PackageInfo basePackageInfo =
+ mContext.getPackageManager()
+ .getPackageArchiveInfo(
+ baseFile.getAbsolutePath(),
+ PackageManager.GET_SIGNATURES | PackageManager.GET_META_DATA);
+
+ if (basePackageInfo == null) {
+ for (File apkFile : multiApkDirectory.listFiles()) {
+ if (apkFile.isDirectory()) {
+ continue;
+ }
+
+ // If we didn't find a base.apk, then try to parse each apk until we find the one
+ // that succeeds.
+ basePackageInfo =
+ mContext.getPackageManager()
+ .getPackageArchiveInfo(
+ apkFile.getAbsolutePath(),
+ PackageManager.GET_SIGNING_CERTIFICATES
+ | PackageManager.GET_META_DATA);
+ if (basePackageInfo != null) {
+ Slog.i(TAG, "Found package info from " + apkFile);
+ break;
+ }
+ }
+ }
+
+ if (basePackageInfo == null) {
+ throw new IllegalArgumentException(
+ "Base package info cannot be found from installation directory");
+ }
+
+ return basePackageInfo;
+ }
+
+ private File getInstallationPath(Uri dataUri) {
+ if (dataUri == null) {
+ throw new IllegalArgumentException("Null data uri");
+ }
+
+ String scheme = dataUri.getScheme();
+ if (!"file".equalsIgnoreCase(scheme)) {
+ throw new IllegalArgumentException("Unsupported scheme for " + dataUri);
+ }
+
+ File installationPath = new File(dataUri.getPath());
+ if (!installationPath.exists()) {
+ throw new IllegalArgumentException("Cannot find file for " + dataUri);
+ }
+ if (!installationPath.canRead()) {
+ throw new IllegalArgumentException("Cannot read file for " + dataUri);
+ }
+ return installationPath;
+ }
+
+ private String getCallerPackageNameOrThrow() {
+ final String[] allowedRuleProviders =
+ mContext.getResources()
+ .getStringArray(R.array.config_integrityRuleProviderPackages);
+ for (String packageName : allowedRuleProviders) {
+ try {
+ // At least in tests, getPackageUid gives "NameNotFound" but getPackagesFromUid
+ // give the correct package name.
+ int uid = mContext.getPackageManager().getPackageUid(packageName, 0);
+ if (uid == Binder.getCallingUid()) {
+ // Caller is allowed in the config.
+ if (isSystemApp(packageName)) {
+ return packageName;
+ }
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ // Ignore the exception. We don't expect the app to be necessarily installed.
+ Slog.i(TAG, "Rule provider package " + packageName + " not installed.");
+ }
+ }
+ throw new SecurityException(
+ "Only system packages specified in config_integrityRuleProviderPackages are"
+ + " allowed to call this method.");
+ }
+
+ private boolean isSystemApp(String packageName) {
+ try {
+ PackageInfo existingPackageInfo =
+ mContext.getPackageManager().getPackageInfo(packageName, /* flags= */ 0);
+ return existingPackageInfo.applicationInfo != null
+ && existingPackageInfo.applicationInfo.isSystemApp();
+ } catch (PackageManager.NameNotFoundException e) {
+ return false;
+ }
}
}
diff --git a/services/core/java/com/android/server/integrity/IntegrityFileManager.java b/services/core/java/com/android/server/integrity/IntegrityFileManager.java
new file mode 100644
index 000000000000..30cafaa2b775
--- /dev/null
+++ b/services/core/java/com/android/server/integrity/IntegrityFileManager.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.integrity;
+
+import android.annotation.Nullable;
+import android.content.integrity.AppInstallMetadata;
+import android.content.integrity.Rule;
+import android.os.Environment;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.integrity.model.RuleMetadata;
+import com.android.server.integrity.parser.RuleBinaryParser;
+import com.android.server.integrity.parser.RuleMetadataParser;
+import com.android.server.integrity.parser.RuleParseException;
+import com.android.server.integrity.parser.RuleParser;
+import com.android.server.integrity.serializer.RuleBinarySerializer;
+import com.android.server.integrity.serializer.RuleMetadataSerializer;
+import com.android.server.integrity.serializer.RuleSerializeException;
+import com.android.server.integrity.serializer.RuleSerializer;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.List;
+import java.util.Optional;
+
+/** Abstraction over the underlying storage of rules and other metadata. */
+public class IntegrityFileManager {
+ private static final String TAG = "IntegrityFileManager";
+
+ // TODO: this is a prototype implementation of this class. Thus no tests are included.
+ // Implementing rule indexing will likely overhaul this class and more tests should be included
+ // then.
+
+ private static final String METADATA_FILE = "metadata";
+ private static final String RULES_FILE = "rules";
+ private static final Object RULES_LOCK = new Object();
+
+ private static IntegrityFileManager sInstance = null;
+
+ private final RuleParser mRuleParser;
+ private final RuleSerializer mRuleSerializer;
+
+ private final File mDataDir;
+ // mRulesDir contains data of the actual rules currently stored.
+ private final File mRulesDir;
+ // mStagingDir is used to store the temporary rules / metadata during updating, since we want to
+ // update rules atomically.
+ private final File mStagingDir;
+
+ @Nullable private RuleMetadata mRuleMetadataCache;
+
+ /** Get the singleton instance of this class. */
+ public static synchronized IntegrityFileManager getInstance() {
+ if (sInstance == null) {
+ sInstance = new IntegrityFileManager();
+ }
+ return sInstance;
+ }
+
+ private IntegrityFileManager() {
+ this(
+ new RuleBinaryParser(),
+ new RuleBinarySerializer(),
+ Environment.getDataSystemDirectory());
+ }
+
+ @VisibleForTesting
+ IntegrityFileManager(RuleParser ruleParser, RuleSerializer ruleSerializer, File dataDir) {
+ mRuleParser = ruleParser;
+ mRuleSerializer = ruleSerializer;
+ mDataDir = dataDir;
+
+ mRulesDir = new File(dataDir, "integrity_rules");
+ mStagingDir = new File(dataDir, "integrity_staging");
+
+ if (!mStagingDir.mkdirs() || !mRulesDir.mkdirs()) {
+ Slog.e(TAG, "Error creating staging and rules directory");
+ // TODO: maybe throw an exception?
+ }
+
+ File metadataFile = new File(mRulesDir, METADATA_FILE);
+ if (metadataFile.exists()) {
+ try (FileInputStream inputStream = new FileInputStream(metadataFile)) {
+ mRuleMetadataCache = RuleMetadataParser.parse(inputStream);
+ } catch (Exception e) {
+ Slog.e(TAG, "Error reading metadata file.", e);
+ }
+ }
+ }
+
+ /**
+ * Returns if the rules have been initialized.
+ *
+ * <p>Used to fail early if there are no rules (so we don't need to parse the apk at all).
+ */
+ public boolean initialized() {
+ return new File(mRulesDir, RULES_FILE).exists()
+ && new File(mRulesDir, METADATA_FILE).exists();
+ }
+
+ /** Write rules to persistent storage. */
+ public void writeRules(String version, String ruleProvider, List<Rule> rules)
+ throws IOException, RuleSerializeException {
+ try {
+ writeMetadata(mStagingDir, ruleProvider, version);
+ } catch (IOException e) {
+ Slog.e(TAG, "Error writing metadata.", e);
+ // We don't consider this fatal so we continue execution.
+ }
+
+ try (FileOutputStream fileOutputStream =
+ new FileOutputStream(new File(mStagingDir, RULES_FILE))) {
+ mRuleSerializer.serialize(rules, Optional.empty(), fileOutputStream);
+ }
+
+ switchStagingRulesDir();
+ }
+
+ /**
+ * Read rules from persistent storage.
+ *
+ * @param appInstallMetadata information about the install used to select rules to read
+ */
+ public List<Rule> readRules(AppInstallMetadata appInstallMetadata)
+ throws IOException, RuleParseException {
+ // TODO: select rules by index
+ synchronized (RULES_LOCK) {
+ try (FileInputStream inputStream =
+ new FileInputStream(new File(mRulesDir, RULES_FILE))) {
+ List<Rule> rules = mRuleParser.parse(inputStream);
+ return rules;
+ }
+ }
+ }
+
+ /** Read the metadata of the current rules in storage. */
+ @Nullable
+ public RuleMetadata readMetadata() {
+ return mRuleMetadataCache;
+ }
+
+ private void switchStagingRulesDir() throws IOException {
+ synchronized (RULES_LOCK) {
+ File tmpDir = new File(mDataDir, "temp");
+
+ if (!(mRulesDir.renameTo(tmpDir)
+ && mStagingDir.renameTo(mRulesDir)
+ && tmpDir.renameTo(mStagingDir))) {
+ throw new IOException("Error switching staging/rules directory");
+ }
+ }
+ }
+
+ private void writeMetadata(File directory, String ruleProvider, String version)
+ throws IOException {
+ mRuleMetadataCache = new RuleMetadata(ruleProvider, version);
+
+ File metadataFile = new File(directory, METADATA_FILE);
+
+ try (FileOutputStream outputStream = new FileOutputStream(metadataFile)) {
+ RuleMetadataSerializer.serialize(mRuleMetadataCache, outputStream);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/integrity/IntegrityUtils.java b/services/core/java/com/android/server/integrity/IntegrityUtils.java
new file mode 100644
index 000000000000..f49c675dbd8d
--- /dev/null
+++ b/services/core/java/com/android/server/integrity/IntegrityUtils.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.integrity;
+
+import static com.android.internal.util.Preconditions.checkArgument;
+
+/** Utils class for simple operations used in integrity module. */
+public class IntegrityUtils {
+
+ private static final char[] HEX_CHARS = "0123456789ABCDEF".toCharArray();
+
+ /**
+ * Obtain the raw bytes from hex encoded string.
+ *
+ * @throws IllegalArgumentException if {@code hexDigest} is not a valid hex encoding of some
+ * bytes
+ */
+ public static byte[] getBytesFromHexDigest(String hexDigest) {
+ checkArgument(
+ hexDigest.length() % 2 == 0,
+ "Invalid hex encoding " + hexDigest + ": must have even length");
+
+ byte[] rawBytes = new byte[hexDigest.length() / 2];
+ for (int i = 0; i < rawBytes.length; i++) {
+ int upperNibble = hexDigest.charAt(2 * i);
+ int lowerNibble = hexDigest.charAt(2 * i + 1);
+ rawBytes[i] = (byte) ((hexToDec(upperNibble) << 4) | hexToDec(lowerNibble));
+ }
+ return rawBytes;
+ }
+
+ /** Obtain hex encoded string from raw bytes. */
+ public static String getHexDigest(byte[] rawBytes) {
+ char[] hexChars = new char[rawBytes.length * 2];
+
+ for (int i = 0; i < rawBytes.length; i++) {
+ int upperNibble = (rawBytes[i] >>> 4) & 0xF;
+ int lowerNibble = rawBytes[i] & 0xF;
+ hexChars[i * 2] = decToHex(upperNibble);
+ hexChars[i * 2 + 1] = decToHex(lowerNibble);
+ }
+ return new String(hexChars);
+ }
+
+ private static int hexToDec(int hexChar) {
+ if (hexChar >= '0' && hexChar <= '9') {
+ return hexChar - '0';
+ }
+ if (hexChar >= 'a' && hexChar <= 'f') {
+ return hexChar - 'a' + 10;
+ }
+ if (hexChar >= 'A' && hexChar <= 'F') {
+ return hexChar - 'A' + 10;
+ }
+ throw new IllegalArgumentException("Invalid hex char " + hexChar);
+ }
+
+ private static char decToHex(int dec) {
+ if (dec >= 0 && dec < HEX_CHARS.length) {
+ return HEX_CHARS[dec];
+ }
+
+ throw new IllegalArgumentException("Invalid dec value to be converted to hex digit " + dec);
+ }
+}
diff --git a/services/core/java/com/android/server/integrity/OWNERS b/services/core/java/com/android/server/integrity/OWNERS
index 019aa4fb0f2b..55a4e409c767 100644
--- a/services/core/java/com/android/server/integrity/OWNERS
+++ b/services/core/java/com/android/server/integrity/OWNERS
@@ -3,4 +3,3 @@ khelmy@google.com
mdchurchill@google.com
sturla@google.com
songpan@google.com
-bjy@google.com
diff --git a/services/core/java/com/android/server/integrity/engine/RuleEvaluationEngine.java b/services/core/java/com/android/server/integrity/engine/RuleEvaluationEngine.java
index b8202b6c0dc6..07eacbfd87dd 100644
--- a/services/core/java/com/android/server/integrity/engine/RuleEvaluationEngine.java
+++ b/services/core/java/com/android/server/integrity/engine/RuleEvaluationEngine.java
@@ -17,12 +17,21 @@
package com.android.server.integrity.engine;
import android.content.integrity.AppInstallMetadata;
+import android.content.integrity.AtomicFormula;
+import android.content.integrity.CompoundFormula;
+import android.content.integrity.Formula;
import android.content.integrity.Rule;
+import android.util.Slog;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.integrity.IntegrityFileManager;
import com.android.server.integrity.model.IntegrityCheckResult;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
+import java.util.Map;
+import java.util.Optional;
/**
* The engine used to evaluate rules against app installs.
@@ -30,17 +39,24 @@ import java.util.List;
* <p>Every app install is evaluated against rules (pushed by the verifier) by the evaluation engine
* to allow/block that install.
*/
-public final class RuleEvaluationEngine {
+public class RuleEvaluationEngine {
private static final String TAG = "RuleEvaluation";
// The engine for loading rules, retrieving metadata for app installs, and evaluating app
// installs against rules.
private static RuleEvaluationEngine sRuleEvaluationEngine;
+ private final IntegrityFileManager mIntegrityFileManager;
+
+ @VisibleForTesting
+ RuleEvaluationEngine(IntegrityFileManager integrityFileManager) {
+ mIntegrityFileManager = integrityFileManager;
+ }
+
/** Provide a singleton instance of the rule evaluation engine. */
public static synchronized RuleEvaluationEngine getRuleEvaluationEngine() {
if (sRuleEvaluationEngine == null) {
- return new RuleEvaluationEngine();
+ return new RuleEvaluationEngine(IntegrityFileManager.getInstance());
}
return sRuleEvaluationEngine;
}
@@ -52,13 +68,57 @@ public final class RuleEvaluationEngine {
* against.
* @return result of the integrity check
*/
- public IntegrityCheckResult evaluate(AppInstallMetadata appInstallMetadata) {
+ public IntegrityCheckResult evaluate(
+ AppInstallMetadata appInstallMetadata, Map<String, String> allowedInstallers) {
List<Rule> rules = loadRules(appInstallMetadata);
+ allowedInstallersRule(allowedInstallers).ifPresent(rules::add);
return RuleEvaluator.evaluateRules(rules, appInstallMetadata);
}
private List<Rule> loadRules(AppInstallMetadata appInstallMetadata) {
- // TODO: Load rules
- return new ArrayList<>();
+ try {
+ return mIntegrityFileManager.readRules(appInstallMetadata);
+ } catch (Exception e) {
+ Slog.e(TAG, "Error loading rules.", e);
+ return new ArrayList<>();
+ }
+ }
+
+ private static Optional<Rule> allowedInstallersRule(Map<String, String> allowedInstallers) {
+ if (allowedInstallers.isEmpty()) {
+ return Optional.empty();
+ }
+
+ List<Formula> formulas = new ArrayList<>(allowedInstallers.size());
+ allowedInstallers.forEach(
+ (installer, cert) -> {
+ formulas.add(allowedInstallerFormula(installer, cert));
+ });
+
+ // We need this special case since OR-formulas require at least two operands.
+ Formula allInstallersFormula =
+ formulas.size() == 1
+ ? formulas.get(0)
+ : new CompoundFormula(CompoundFormula.OR, formulas);
+
+ return Optional.of(
+ new Rule(
+ new CompoundFormula(
+ CompoundFormula.NOT, Arrays.asList(allInstallersFormula)),
+ Rule.DENY));
+ }
+
+ private static Formula allowedInstallerFormula(String installer, String cert) {
+ return new CompoundFormula(
+ CompoundFormula.AND,
+ Arrays.asList(
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.INSTALLER_NAME,
+ installer,
+ /* isHashedValue= */ false),
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.INSTALLER_CERTIFICATE,
+ cert,
+ /* isHashedValue= */ false)));
}
}
diff --git a/services/core/java/com/android/server/integrity/engine/RuleEvaluator.java b/services/core/java/com/android/server/integrity/engine/RuleEvaluator.java
index ee51d4f87848..b1c20d27c792 100644
--- a/services/core/java/com/android/server/integrity/engine/RuleEvaluator.java
+++ b/services/core/java/com/android/server/integrity/engine/RuleEvaluator.java
@@ -21,9 +21,6 @@ import static android.content.integrity.Rule.FORCE_ALLOW;
import android.annotation.NonNull;
import android.content.integrity.AppInstallMetadata;
-import android.content.integrity.AtomicFormula;
-import android.content.integrity.CompoundFormula;
-import android.content.integrity.Formula;
import android.content.integrity.Rule;
import android.util.Slog;
@@ -56,8 +53,7 @@ final class RuleEvaluator {
List<Rule> rules, AppInstallMetadata appInstallMetadata) {
List<Rule> matchedRules = new ArrayList<>();
for (Rule rule : rules) {
- if (isConjunctionOfFormulas(rule.getFormula())
- && rule.getFormula().isSatisfied(appInstallMetadata)) {
+ if (rule.getFormula().isSatisfied(appInstallMetadata)) {
matchedRules.add(rule);
}
}
@@ -81,25 +77,4 @@ final class RuleEvaluator {
}
return denied ? IntegrityCheckResult.deny(denyRule) : IntegrityCheckResult.allow();
}
-
- private static boolean isConjunctionOfFormulas(Formula formula) {
- if (formula == null) {
- return false;
- }
- if (isAtomicFormula(formula)) {
- return true;
- }
- CompoundFormula compoundFormula = (CompoundFormula) formula;
- return compoundFormula.getConnector() == CompoundFormula.AND
- && compoundFormula.getFormulas().stream().allMatch(RuleEvaluator::isAtomicFormula);
- }
-
- private static boolean isAtomicFormula(Formula formula) {
- if (formula instanceof AtomicFormula) {
- return true;
- }
- CompoundFormula compoundFormula = (CompoundFormula) formula;
- return compoundFormula.getConnector() == CompoundFormula.NOT
- && compoundFormula.getFormulas().get(0) instanceof AtomicFormula;
- }
}
diff --git a/services/core/java/com/android/server/integrity/model/BitOutputStream.java b/services/core/java/com/android/server/integrity/model/BitOutputStream.java
index ecb9189b2a0d..b8ea041c4196 100644
--- a/services/core/java/com/android/server/integrity/model/BitOutputStream.java
+++ b/services/core/java/com/android/server/integrity/model/BitOutputStream.java
@@ -42,7 +42,7 @@ public class BitOutputStream {
int offset = 1 << (numOfBits - 1);
while (numOfBits-- > 0) {
mBitSet.set(mIndex, (value & offset) != 0);
- offset >>= 1;
+ offset >>>= 1;
mIndex++;
}
}
diff --git a/services/core/java/com/android/server/integrity/model/ComponentBitSize.java b/services/core/java/com/android/server/integrity/model/ComponentBitSize.java
index d47ce2df45e1..6ec2d5f70372 100644
--- a/services/core/java/com/android/server/integrity/model/ComponentBitSize.java
+++ b/services/core/java/com/android/server/integrity/model/ComponentBitSize.java
@@ -29,7 +29,7 @@ public final class ComponentBitSize {
public static final int OPERATOR_BITS = 3;
public static final int CONNECTOR_BITS = 2;
public static final int SEPARATOR_BITS = 2;
- public static final int VALUE_SIZE_BITS = 5;
+ public static final int VALUE_SIZE_BITS = 6;
public static final int IS_HASHED_BITS = 1;
public static final int ATOMIC_FORMULA_START = 0;
diff --git a/services/core/java/com/android/server/integrity/model/RuleMetadata.java b/services/core/java/com/android/server/integrity/model/RuleMetadata.java
new file mode 100644
index 000000000000..6b582ae7b5f2
--- /dev/null
+++ b/services/core/java/com/android/server/integrity/model/RuleMetadata.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.integrity.model;
+
+import android.annotation.Nullable;
+
+/** Data class containing relevant metadata associated with a rule set. */
+public class RuleMetadata {
+
+ private final String mRuleProvider;
+ private final String mVersion;
+
+ public RuleMetadata(String ruleProvider, String version) {
+ mRuleProvider = ruleProvider;
+ mVersion = version;
+ }
+
+ @Nullable
+ public String getRuleProvider() {
+ return mRuleProvider;
+ }
+
+ @Nullable
+ public String getVersion() {
+ return mVersion;
+ }
+}
diff --git a/services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java b/services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java
index 3ef45a637bc1..8f84abc88752 100644
--- a/services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java
+++ b/services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java
@@ -34,16 +34,20 @@ import android.content.integrity.CompoundFormula;
import android.content.integrity.Formula;
import android.content.integrity.Rule;
+import com.android.server.integrity.IntegrityUtils;
import com.android.server.integrity.model.BitInputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
/** A helper class to parse rules into the {@link Rule} model from Binary representation. */
public class RuleBinaryParser implements RuleParser {
+ private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
+
@Override
public List<Rule> parse(byte[] ruleBytes) throws RuleParseException {
try {
@@ -122,26 +126,52 @@ public class RuleBinaryParser implements RuleParser {
int key = bitInputStream.getNext(KEY_BITS);
int operator = bitInputStream.getNext(OPERATOR_BITS);
- boolean isHashedValue = bitInputStream.getNext(IS_HASHED_BITS) == 1;
- int valueSize = bitInputStream.getNext(VALUE_SIZE_BITS);
- StringBuilder value = new StringBuilder();
- while (valueSize-- > 0) {
- value.append((char) bitInputStream.getNext(/* numOfBits= */ 8));
- }
-
switch (key) {
case AtomicFormula.PACKAGE_NAME:
case AtomicFormula.APP_CERTIFICATE:
case AtomicFormula.INSTALLER_NAME:
case AtomicFormula.INSTALLER_CERTIFICATE:
- return new AtomicFormula.StringAtomicFormula(key, value.toString(), isHashedValue);
+ boolean isHashedValue = bitInputStream.getNext(IS_HASHED_BITS) == 1;
+ int valueSize = bitInputStream.getNext(VALUE_SIZE_BITS);
+ String stringValue = getStringValue(bitInputStream, valueSize, isHashedValue);
+ return new AtomicFormula.StringAtomicFormula(key, stringValue, isHashedValue);
case AtomicFormula.VERSION_CODE:
- return new AtomicFormula.IntAtomicFormula(
- key, operator, Integer.parseInt(value.toString()));
+ int intValue = getIntValue(bitInputStream);
+ return new AtomicFormula.IntAtomicFormula(key, operator, intValue);
case AtomicFormula.PRE_INSTALLED:
- return new AtomicFormula.BooleanAtomicFormula(key, value.toString().equals("1"));
+ boolean booleanValue = getBooleanValue(bitInputStream);
+ return new AtomicFormula.BooleanAtomicFormula(key, booleanValue);
default:
throw new IllegalArgumentException(String.format("Unknown key: %d", key));
}
}
+
+ // Get value string from stream.
+ // If the value is not hashed, get its raw form directly.
+ // If the value is hashed, get the hex-encoding of the value. Serialized values are in raw form.
+ // All hashed values are hex-encoded.
+ private static String getStringValue(
+ BitInputStream bitInputStream, int valueSize, boolean isHashedValue)
+ throws IOException {
+ if (!isHashedValue) {
+ StringBuilder value = new StringBuilder();
+ while (valueSize-- > 0) {
+ value.append((char) bitInputStream.getNext(/* numOfBits= */ 8));
+ }
+ return value.toString();
+ }
+ ByteBuffer byteBuffer = ByteBuffer.allocate(valueSize);
+ while (valueSize-- > 0) {
+ byteBuffer.put((byte) (bitInputStream.getNext(/* numOfBits= */ 8) & 0xFF));
+ }
+ return IntegrityUtils.getHexDigest(byteBuffer.array());
+ }
+
+ private static int getIntValue(BitInputStream bitInputStream) throws IOException {
+ return bitInputStream.getNext(/* numOfBits= */ 32);
+ }
+
+ private static boolean getBooleanValue(BitInputStream bitInputStream) throws IOException {
+ return bitInputStream.getNext(/* numOfBits= */ 1) == 1;
+ }
}
diff --git a/services/core/java/com/android/server/integrity/parser/RuleMetadataParser.java b/services/core/java/com/android/server/integrity/parser/RuleMetadataParser.java
new file mode 100644
index 000000000000..28d2e6914103
--- /dev/null
+++ b/services/core/java/com/android/server/integrity/parser/RuleMetadataParser.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.integrity.parser;
+
+import android.annotation.Nullable;
+import android.util.Xml;
+
+import com.android.server.integrity.model.RuleMetadata;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+
+/** Helper class for parsing rule metadata. */
+public class RuleMetadataParser {
+
+ public static final String RULE_PROVIDER_TAG = "P";
+ public static final String VERSION_TAG = "V";
+
+ /** Parse the rule metadata from an input stream. */
+ @Nullable
+ public static RuleMetadata parse(InputStream inputStream)
+ throws XmlPullParserException, IOException {
+
+ String ruleProvider = "";
+ String version = "";
+
+ XmlPullParser xmlPullParser = Xml.newPullParser();
+ xmlPullParser.setInput(inputStream, StandardCharsets.UTF_8.name());
+
+ int eventType;
+ while ((eventType = xmlPullParser.next()) != XmlPullParser.END_DOCUMENT) {
+ if (eventType == XmlPullParser.START_TAG) {
+ String tag = xmlPullParser.getName();
+ switch (tag) {
+ case RULE_PROVIDER_TAG:
+ ruleProvider = xmlPullParser.nextText();
+ break;
+ case VERSION_TAG:
+ version = xmlPullParser.nextText();
+ break;
+ default:
+ throw new IllegalStateException("Unknown tag in metadata: " + tag);
+ }
+ }
+ }
+
+ return new RuleMetadata(ruleProvider, version);
+ }
+}
diff --git a/services/core/java/com/android/server/integrity/serializer/ByteTrackedOutputStream.java b/services/core/java/com/android/server/integrity/serializer/ByteTrackedOutputStream.java
new file mode 100644
index 000000000000..c8d318f5096f
--- /dev/null
+++ b/services/core/java/com/android/server/integrity/serializer/ByteTrackedOutputStream.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.integrity.serializer;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * An output stream that tracks the total number written bytes since construction and allows
+ * querying this value any time during the execution.
+ *
+ * This class is used for constructing the rule indexing.
+ */
+public class ByteTrackedOutputStream {
+
+ private static long sWrittenBytesCount;
+ private static OutputStream sOutputStream;
+
+ public ByteTrackedOutputStream(OutputStream outputStream) {
+ sWrittenBytesCount = 0;
+ sOutputStream = outputStream;
+ }
+
+ /**
+ * Writes the given bytes into the output stream provided in constructor and updates the
+ * total number of written bytes.
+ */
+ public void write(byte[] bytes) throws IOException {
+ sWrittenBytesCount += bytes.length;
+ sOutputStream.write(bytes);
+ }
+
+ /**
+ * Returns the total number of bytes written into the output stream at the requested time.
+ */
+ public long getWrittenBytesCount() {
+ return sWrittenBytesCount;
+ }
+}
diff --git a/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java b/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java
index fdbb7d9df293..22af0852f620 100644
--- a/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java
+++ b/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java
@@ -27,58 +27,117 @@ import static com.android.server.integrity.model.ComponentBitSize.KEY_BITS;
import static com.android.server.integrity.model.ComponentBitSize.OPERATOR_BITS;
import static com.android.server.integrity.model.ComponentBitSize.SEPARATOR_BITS;
import static com.android.server.integrity.model.ComponentBitSize.VALUE_SIZE_BITS;
+import static com.android.server.integrity.serializer.RuleIndexingDetails.APP_CERTIFICATE_INDEXED;
+import static com.android.server.integrity.serializer.RuleIndexingDetails.NOT_INDEXED;
+import static com.android.server.integrity.serializer.RuleIndexingDetails.PACKAGE_NAME_INDEXED;
import android.content.integrity.AtomicFormula;
import android.content.integrity.CompoundFormula;
import android.content.integrity.Formula;
import android.content.integrity.Rule;
+import com.android.internal.util.Preconditions;
+import com.android.server.integrity.IntegrityUtils;
import com.android.server.integrity.model.BitOutputStream;
import java.io.ByteArrayOutputStream;
+import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.List;
+import java.util.Map;
import java.util.Optional;
+import java.util.TreeMap;
/** A helper class to serialize rules from the {@link Rule} model to Binary representation. */
public class RuleBinarySerializer implements RuleSerializer {
- // Get the byte representation for a list of rules, and write them to an output stream.
+ // The parsing time seems acceptable for 100 rules based on the tests in go/ic-rule-file-format.
+ private static final int INDEXING_BLOCK_SIZE = 100;
+
+ private static final String START_INDEXING_KEY = "START_KEY";
+ private static final String END_INDEXING_KEY = "END_KEY";
+
+ // Get the byte representation for a list of rules.
@Override
- public void serialize(
- List<Rule> rules, Optional<Integer> formatVersion, OutputStream outputStream)
+ public byte[] serialize(List<Rule> rules, Optional<Integer> formatVersion)
throws RuleSerializeException {
try {
- BitOutputStream bitOutputStream = new BitOutputStream();
-
- int formatVersionValue = formatVersion.orElse(DEFAULT_FORMAT_VERSION);
- bitOutputStream.setNext(FORMAT_VERSION_BITS, formatVersionValue);
- outputStream.write(bitOutputStream.toByteArray());
-
- for (Rule rule : rules) {
- bitOutputStream.clear();
- serializeRule(rule, bitOutputStream);
- outputStream.write(bitOutputStream.toByteArray());
- }
+ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ serialize(rules, formatVersion, byteArrayOutputStream);
+ return byteArrayOutputStream.toByteArray();
} catch (Exception e) {
throw new RuleSerializeException(e.getMessage(), e);
}
}
- // Get the byte representation for a list of rules.
+ // Get the byte representation for a list of rules, and write them to an output stream.
@Override
- public byte[] serialize(List<Rule> rules, Optional<Integer> formatVersion)
+ public void serialize(
+ List<Rule> rules, Optional<Integer> formatVersion, OutputStream originalOutputStream)
throws RuleSerializeException {
try {
- ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
- serialize(rules, formatVersion, byteArrayOutputStream);
- return byteArrayOutputStream.toByteArray();
+ // Determine the indexing groups and the order of the rules within each indexed group.
+ Map<Integer, TreeMap<String, List<Rule>>> indexedRules =
+ RuleIndexingDetailsIdentifier.splitRulesIntoIndexBuckets(rules);
+
+ ByteTrackedOutputStream outputStream =
+ new ByteTrackedOutputStream(originalOutputStream);
+
+ serializeRuleFileMetadata(formatVersion, outputStream);
+
+ Map<String, Long> packageNameIndexes =
+ serializeRuleList(indexedRules.get(PACKAGE_NAME_INDEXED), outputStream);
+ Map<String, Long> appCertificateIndexes =
+ serializeRuleList(indexedRules.get(APP_CERTIFICATE_INDEXED), outputStream);
+ Map<String, Long> unindexedRulesIndex =
+ serializeRuleList(indexedRules.get(NOT_INDEXED), outputStream);
+
+ // TODO(b/145493956): Write these indexes into a index file provided by integrity file
+ // manager.
} catch (Exception e) {
throw new RuleSerializeException(e.getMessage(), e);
}
}
+ private void serializeRuleFileMetadata(Optional<Integer> formatVersion,
+ ByteTrackedOutputStream outputStream) throws IOException {
+ int formatVersionValue = formatVersion.orElse(DEFAULT_FORMAT_VERSION);
+
+ BitOutputStream bitOutputStream = new BitOutputStream();
+ bitOutputStream.setNext(FORMAT_VERSION_BITS, formatVersionValue);
+ outputStream.write(bitOutputStream.toByteArray());
+ }
+
+ private Map<String, Long> serializeRuleList(TreeMap<String, List<Rule>> rulesMap,
+ ByteTrackedOutputStream outputStream)
+ throws IOException {
+ Preconditions.checkArgument(rulesMap != null,
+ "serializeRuleList should never be called with null rule list.");
+
+ BitOutputStream bitOutputStream = new BitOutputStream();
+ Map<String, Long> indexMapping = new TreeMap();
+ long indexTracker = 0;
+
+ indexMapping.put(START_INDEXING_KEY, outputStream.getWrittenBytesCount());
+ for (Map.Entry<String, List<Rule>> entry : rulesMap.entrySet()) {
+ if (indexTracker >= INDEXING_BLOCK_SIZE) {
+ indexMapping.put(entry.getKey(), outputStream.getWrittenBytesCount());
+ indexTracker = 0;
+ }
+
+ for (Rule rule : entry.getValue()) {
+ bitOutputStream.clear();
+ serializeRule(rule, bitOutputStream);
+ outputStream.write(bitOutputStream.toByteArray());
+ indexTracker++;
+ }
+ }
+ indexMapping.put(END_INDEXING_KEY, outputStream.getWrittenBytesCount());
+
+ return indexMapping;
+ }
+
private void serializeRule(Rule rule, BitOutputStream bitOutputStream) {
if (rule == null) {
throw new IllegalArgumentException("Null rule can not be serialized");
@@ -131,7 +190,7 @@ public class RuleBinarySerializer implements RuleSerializer {
AtomicFormula.StringAtomicFormula stringAtomicFormula =
(AtomicFormula.StringAtomicFormula) atomicFormula;
bitOutputStream.setNext(OPERATOR_BITS, AtomicFormula.EQ);
- serializeValue(
+ serializeStringValue(
stringAtomicFormula.getValue(),
stringAtomicFormula.getIsHashedValue(),
bitOutputStream);
@@ -139,27 +198,24 @@ public class RuleBinarySerializer implements RuleSerializer {
AtomicFormula.IntAtomicFormula intAtomicFormula =
(AtomicFormula.IntAtomicFormula) atomicFormula;
bitOutputStream.setNext(OPERATOR_BITS, intAtomicFormula.getOperator());
- serializeValue(
- String.valueOf(intAtomicFormula.getValue()),
- /* isHashedValue= */ false,
- bitOutputStream);
+ serializeIntValue(intAtomicFormula.getValue(), bitOutputStream);
} else if (atomicFormula.getTag() == AtomicFormula.BOOLEAN_ATOMIC_FORMULA_TAG) {
AtomicFormula.BooleanAtomicFormula booleanAtomicFormula =
(AtomicFormula.BooleanAtomicFormula) atomicFormula;
bitOutputStream.setNext(OPERATOR_BITS, AtomicFormula.EQ);
- serializeValue(
- booleanAtomicFormula.getValue() ? "1" : "0",
- /* isHashedValue= */ false,
- bitOutputStream);
+ serializeBooleanValue(booleanAtomicFormula.getValue(), bitOutputStream);
} else {
throw new IllegalArgumentException(
String.format("Invalid atomic formula type: %s", atomicFormula.getClass()));
}
}
- private void serializeValue(
+ private void serializeStringValue(
String value, boolean isHashedValue, BitOutputStream bitOutputStream) {
- byte[] valueBytes = value.getBytes(StandardCharsets.UTF_8);
+ if (value == null) {
+ throw new IllegalArgumentException("String value can not be null.");
+ }
+ byte[] valueBytes = getBytesForString(value, isHashedValue);
bitOutputStream.setNext(isHashedValue);
bitOutputStream.setNext(VALUE_SIZE_BITS, valueBytes.length);
@@ -167,4 +223,23 @@ public class RuleBinarySerializer implements RuleSerializer {
bitOutputStream.setNext(/* numOfBits= */ 8, valueByte);
}
}
+
+ private void serializeIntValue(int value, BitOutputStream bitOutputStream) {
+ bitOutputStream.setNext(/* numOfBits= */ 32, value);
+ }
+
+ private void serializeBooleanValue(boolean value, BitOutputStream bitOutputStream) {
+ bitOutputStream.setNext(value);
+ }
+
+ // Get the byte array for a value.
+ // If the value is not hashed, use its byte array form directly.
+ // If the value is hashed, get the raw form decoding of the value. All hashed values are
+ // hex-encoded. Serialized values are in raw form.
+ private static byte[] getBytesForString(String value, boolean isHashedValue) {
+ if (!isHashedValue) {
+ return value.getBytes(StandardCharsets.UTF_8);
+ }
+ return IntegrityUtils.getBytesFromHexDigest(value);
+ }
}
diff --git a/services/core/java/com/android/server/integrity/serializer/RuleIndexTypeIdentifier.java b/services/core/java/com/android/server/integrity/serializer/RuleIndexTypeIdentifier.java
deleted file mode 100644
index 4d3961df6092..000000000000
--- a/services/core/java/com/android/server/integrity/serializer/RuleIndexTypeIdentifier.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.integrity.serializer;
-
-import android.annotation.IntDef;
-import android.content.integrity.AtomicFormula;
-import android.content.integrity.CompoundFormula;
-import android.content.integrity.Formula;
-import android.content.integrity.Rule;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.List;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-/** A helper class for identifying the indexing type of a given rule. */
-public class RuleIndexTypeIdentifier {
-
- static final int NOT_INDEXED = 0;
- static final int PACKAGE_NAME_INDEXED = 1;
- static final int APP_CERTIFICATE_INDEXED = 2;
-
- /** Represents which indexed file the rule should be located. */
- @IntDef(
- value = {
- NOT_INDEXED,
- PACKAGE_NAME_INDEXED,
- APP_CERTIFICATE_INDEXED
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface IndexType {
- }
-
- /** Determines the indexing file type that a given rule should be located at. */
- public static int getIndexType(Rule rule) {
- if (rule == null) {
- throw new IllegalArgumentException("Indexing type cannot be determined for null rule.");
- }
- return getIndexType(rule.getFormula());
- }
-
- private static int getIndexType(Formula formula) {
- if (formula == null) {
- throw new IllegalArgumentException(
- "Indexing type cannot be determined for null formula.");
- }
-
- switch (formula.getTag()) {
- case Formula.COMPOUND_FORMULA_TAG:
- return getIndexTypeForCompoundFormula((CompoundFormula) formula);
- case Formula.STRING_ATOMIC_FORMULA_TAG:
- return getIndexTypeForAtomicStringFormula((AtomicFormula) formula);
- case Formula.INT_ATOMIC_FORMULA_TAG:
- case Formula.BOOLEAN_ATOMIC_FORMULA_TAG:
- // Package name and app certificate related formulas are string atomic formulas.
- return NOT_INDEXED;
- default:
- throw new IllegalArgumentException(
- String.format("Invalid formula tag type: %s", formula.getTag()));
- }
- }
-
- private static int getIndexTypeForCompoundFormula(CompoundFormula compoundFormula) {
- int connector = compoundFormula.getConnector();
- List<Formula> formulas = compoundFormula.getFormulas();
-
- switch (connector) {
- case CompoundFormula.NOT:
- // Having a NOT operator in the indexing messes up the indexing; e.g., deny
- // installation if app certificate is NOT X (should not be indexed with app cert
- // X). We will not keep these rules indexed.
- return NOT_INDEXED;
- case CompoundFormula.AND:
- case CompoundFormula.OR:
- Set<Integer> indexingTypesForAllFormulas =
- formulas.stream()
- .map(formula -> getIndexType(formula))
- .collect(Collectors.toSet());
- if (indexingTypesForAllFormulas.contains(PACKAGE_NAME_INDEXED)) {
- return PACKAGE_NAME_INDEXED;
- } else if (indexingTypesForAllFormulas.contains(APP_CERTIFICATE_INDEXED)) {
- return APP_CERTIFICATE_INDEXED;
- } else {
- return NOT_INDEXED;
- }
- default:
- return NOT_INDEXED;
- }
- }
-
- private static int getIndexTypeForAtomicStringFormula(AtomicFormula atomicFormula) {
- switch (atomicFormula.getKey()) {
- case AtomicFormula.PACKAGE_NAME:
- return PACKAGE_NAME_INDEXED;
- case AtomicFormula.APP_CERTIFICATE:
- return APP_CERTIFICATE_INDEXED;
- default:
- return NOT_INDEXED;
- }
- }
-}
-
diff --git a/services/core/java/com/android/server/integrity/serializer/RuleIndexingDetails.java b/services/core/java/com/android/server/integrity/serializer/RuleIndexingDetails.java
new file mode 100644
index 000000000000..dd871e2bbe6c
--- /dev/null
+++ b/services/core/java/com/android/server/integrity/serializer/RuleIndexingDetails.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.integrity.serializer;
+
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/** Holds the indexing type and indexing key of a given formula. */
+class RuleIndexingDetails {
+
+ static final int NOT_INDEXED = 0;
+ static final int PACKAGE_NAME_INDEXED = 1;
+ static final int APP_CERTIFICATE_INDEXED = 2;
+
+ /** Represents which indexed file the rule should be located. */
+ @IntDef(
+ value = {
+ NOT_INDEXED,
+ PACKAGE_NAME_INDEXED,
+ APP_CERTIFICATE_INDEXED
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface IndexType {
+ }
+
+ private @IndexType int mIndexType;
+ private String mRuleKey;
+
+ /** Constructor without a ruleKey for {@code NOT_INDEXED}. */
+ RuleIndexingDetails(@IndexType int indexType) {
+ this.mIndexType = indexType;
+ this.mRuleKey = null;
+ }
+
+ /** Constructor with a ruleKey for indexed rules. */
+ RuleIndexingDetails(@IndexType int indexType, String ruleKey) {
+ this.mIndexType = indexType;
+ this.mRuleKey = ruleKey;
+ }
+
+ /** Returns the indexing type for the rule. */
+ @IndexType
+ public int getIndexType() {
+ return mIndexType;
+ }
+
+ /** Returns the identified rule key. */
+ public String getRuleKey() {
+ return mRuleKey;
+ }
+}
diff --git a/services/core/java/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifier.java b/services/core/java/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifier.java
new file mode 100644
index 000000000000..cbc365e2c250
--- /dev/null
+++ b/services/core/java/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifier.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.integrity.serializer;
+
+import static com.android.server.integrity.serializer.RuleIndexingDetails.APP_CERTIFICATE_INDEXED;
+import static com.android.server.integrity.serializer.RuleIndexingDetails.NOT_INDEXED;
+import static com.android.server.integrity.serializer.RuleIndexingDetails.PACKAGE_NAME_INDEXED;
+
+import android.content.integrity.AtomicFormula;
+import android.content.integrity.CompoundFormula;
+import android.content.integrity.Formula;
+import android.content.integrity.Rule;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.TreeMap;
+
+/** A helper class for identifying the indexing type and key of a given rule. */
+class RuleIndexingDetailsIdentifier {
+
+ private static final String DEFAULT_RULE_KEY = "N/A";
+
+ /**
+ * Splits a given rule list into three indexing categories. Each rule category is returned as a
+ * TreeMap that is sorted by their indexing keys -- where keys correspond to package name for
+ * PACKAGE_NAME_INDEXED rules, app certificate for APP_CERTIFICATE_INDEXED rules and N/A for
+ * NOT_INDEXED rules.
+ */
+ public static Map<Integer, TreeMap<String, List<Rule>>> splitRulesIntoIndexBuckets(
+ List<Rule> rules) {
+ if (rules == null) {
+ throw new IllegalArgumentException(
+ "Index buckets cannot be created for null rule list.");
+ }
+
+ Map<Integer, TreeMap<String, List<Rule>>> typeOrganizedRuleMap = new HashMap();
+ typeOrganizedRuleMap.put(NOT_INDEXED, new TreeMap());
+ typeOrganizedRuleMap.put(PACKAGE_NAME_INDEXED, new TreeMap());
+ typeOrganizedRuleMap.put(APP_CERTIFICATE_INDEXED, new TreeMap());
+
+ // Split the rules into the appropriate indexed pattern. The Tree Maps help us to keep the
+ // entries sorted by their index key.
+ for (Rule rule : rules) {
+ RuleIndexingDetails indexingDetails;
+ try {
+ indexingDetails = getIndexingDetails(rule.getFormula());
+ } catch (Exception e) {
+ throw new IllegalArgumentException(
+ String.format("Malformed rule identified. [%s]", rule.toString()));
+ }
+
+ String ruleKey =
+ indexingDetails.getIndexType() != NOT_INDEXED
+ ? indexingDetails.getRuleKey()
+ : DEFAULT_RULE_KEY;
+
+ if (!typeOrganizedRuleMap.get(indexingDetails.getIndexType()).containsKey(ruleKey)) {
+ typeOrganizedRuleMap
+ .get(indexingDetails.getIndexType())
+ .put(ruleKey, new ArrayList());
+ }
+
+ typeOrganizedRuleMap
+ .get(indexingDetails.getIndexType())
+ .get(ruleKey)
+ .add(rule);
+ }
+
+ return typeOrganizedRuleMap;
+ }
+
+ private static RuleIndexingDetails getIndexingDetails(Formula formula) {
+ switch (formula.getTag()) {
+ case Formula.COMPOUND_FORMULA_TAG:
+ return getIndexingDetailsForCompoundFormula((CompoundFormula) formula);
+ case Formula.STRING_ATOMIC_FORMULA_TAG:
+ return getIndexingDetailsForStringAtomicFormula(
+ (AtomicFormula.StringAtomicFormula) formula);
+ case Formula.INT_ATOMIC_FORMULA_TAG:
+ case Formula.BOOLEAN_ATOMIC_FORMULA_TAG:
+ // Package name and app certificate related formulas are string atomic formulas.
+ return new RuleIndexingDetails(NOT_INDEXED);
+ default:
+ throw new IllegalArgumentException(
+ String.format("Invalid formula tag type: %s", formula.getTag()));
+ }
+ }
+
+ private static RuleIndexingDetails getIndexingDetailsForCompoundFormula(
+ CompoundFormula compoundFormula) {
+ int connector = compoundFormula.getConnector();
+ List<Formula> formulas = compoundFormula.getFormulas();
+
+ switch (connector) {
+ case CompoundFormula.AND:
+ case CompoundFormula.OR:
+ // If there is a package name related atomic rule, return package name indexed.
+ Optional<RuleIndexingDetails> packageNameRule =
+ formulas.stream()
+ .map(formula -> getIndexingDetails(formula))
+ .filter(ruleIndexingDetails -> ruleIndexingDetails.getIndexType()
+ == PACKAGE_NAME_INDEXED)
+ .findAny();
+ if (packageNameRule.isPresent()) {
+ return packageNameRule.get();
+ }
+
+ // If there is an app certificate related atomic rule but no package name related
+ // atomic rule, return app certificate indexed.
+ Optional<RuleIndexingDetails> appCertificateRule =
+ formulas.stream()
+ .map(formula -> getIndexingDetails(formula))
+ .filter(ruleIndexingDetails -> ruleIndexingDetails.getIndexType()
+ == APP_CERTIFICATE_INDEXED)
+ .findAny();
+ if (appCertificateRule.isPresent()) {
+ return appCertificateRule.get();
+ }
+
+ // Do not index when there is not package name or app certificate indexing.
+ return new RuleIndexingDetails(NOT_INDEXED);
+ default:
+ // Having a NOT operator in the indexing messes up the indexing; e.g., deny
+ // installation if app certificate is NOT X (should not be indexed with app cert
+ // X). We will not keep these rules indexed.
+ // Also any other type of unknown operators will not be indexed.
+ return new RuleIndexingDetails(NOT_INDEXED);
+ }
+ }
+
+ private static RuleIndexingDetails getIndexingDetailsForStringAtomicFormula(
+ AtomicFormula.StringAtomicFormula atomicFormula) {
+ switch (atomicFormula.getKey()) {
+ case AtomicFormula.PACKAGE_NAME:
+ return new RuleIndexingDetails(PACKAGE_NAME_INDEXED, atomicFormula.getValue());
+ case AtomicFormula.APP_CERTIFICATE:
+ return new RuleIndexingDetails(APP_CERTIFICATE_INDEXED, atomicFormula.getValue());
+ default:
+ return new RuleIndexingDetails(NOT_INDEXED);
+ }
+ }
+}
+
diff --git a/services/core/java/com/android/server/integrity/serializer/RuleMetadataSerializer.java b/services/core/java/com/android/server/integrity/serializer/RuleMetadataSerializer.java
new file mode 100644
index 000000000000..5c51f31ba8cc
--- /dev/null
+++ b/services/core/java/com/android/server/integrity/serializer/RuleMetadataSerializer.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.integrity.serializer;
+
+import static com.android.server.integrity.parser.RuleMetadataParser.RULE_PROVIDER_TAG;
+import static com.android.server.integrity.parser.RuleMetadataParser.VERSION_TAG;
+
+import android.util.Xml;
+
+import com.android.server.integrity.model.RuleMetadata;
+
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+
+/** Helper class for writing rule metadata. */
+public class RuleMetadataSerializer {
+ /** Serialize the rule metadata to an output stream. */
+ public static void serialize(RuleMetadata ruleMetadata, OutputStream outputStream)
+ throws IOException {
+ XmlSerializer xmlSerializer = Xml.newSerializer();
+ xmlSerializer.setOutput(outputStream, StandardCharsets.UTF_8.name());
+
+ serializeTaggedValue(xmlSerializer, RULE_PROVIDER_TAG, ruleMetadata.getRuleProvider());
+ serializeTaggedValue(xmlSerializer, VERSION_TAG, ruleMetadata.getVersion());
+
+ xmlSerializer.endDocument();
+ }
+
+ private static void serializeTaggedValue(XmlSerializer xmlSerializer, String tag, String value)
+ throws IOException {
+ xmlSerializer.startTag(/* namespace= */ null, tag);
+ xmlSerializer.text(value);
+ xmlSerializer.endTag(/* namespace= */ null, tag);
+ }
+}
diff --git a/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java b/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
index cfe50c6c8ac9..4c04dbc623ed 100644
--- a/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
+++ b/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
@@ -16,6 +16,10 @@
package com.android.server.integrity.serializer;
+import static com.android.server.integrity.serializer.RuleIndexingDetails.APP_CERTIFICATE_INDEXED;
+import static com.android.server.integrity.serializer.RuleIndexingDetails.NOT_INDEXED;
+import static com.android.server.integrity.serializer.RuleIndexingDetails.PACKAGE_NAME_INDEXED;
+
import android.content.integrity.AtomicFormula;
import android.content.integrity.CompoundFormula;
import android.content.integrity.Formula;
@@ -29,7 +33,9 @@ import java.io.OutputStream;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.util.List;
+import java.util.Map;
import java.util.Optional;
+import java.util.TreeMap;
/** A helper class to serialize rules from the {@link Rule} model to Xml representation. */
public class RuleXmlSerializer implements RuleSerializer {
@@ -75,13 +81,35 @@ public class RuleXmlSerializer implements RuleSerializer {
}
}
- private void serializeRules(List<Rule> rules, XmlSerializer xmlSerializer) throws IOException {
- xmlSerializer.startTag(NAMESPACE, RULE_LIST_TAG);
- for (Rule rule : rules) {
- serializeRule(rule, xmlSerializer);
+ private void serializeRules(List<Rule> rules, XmlSerializer xmlSerializer)
+ throws RuleSerializeException {
+ try {
+ // Determine the indexing groups and the order of the rules within each indexed group.
+ Map<Integer, TreeMap<String, List<Rule>>> indexedRules =
+ RuleIndexingDetailsIdentifier.splitRulesIntoIndexBuckets(rules);
+
+ // Write the XML formatted rules in order.
+ xmlSerializer.startTag(NAMESPACE, RULE_LIST_TAG);
+
+ serializeRuleList(indexedRules.get(PACKAGE_NAME_INDEXED), xmlSerializer);
+ serializeRuleList(indexedRules.get(APP_CERTIFICATE_INDEXED), xmlSerializer);
+ serializeRuleList(indexedRules.get(NOT_INDEXED), xmlSerializer);
+
+ xmlSerializer.endTag(NAMESPACE, RULE_LIST_TAG);
+ xmlSerializer.endDocument();
+ } catch (Exception e) {
+ throw new RuleSerializeException(e.getMessage(), e);
+ }
+ }
+
+ private void serializeRuleList(TreeMap<String, List<Rule>> rulesMap,
+ XmlSerializer xmlSerializer)
+ throws IOException {
+ for (Map.Entry<String, List<Rule>> entry : rulesMap.entrySet()) {
+ for (Rule rule : entry.getValue()) {
+ serializeRule(rule, xmlSerializer);
+ }
}
- xmlSerializer.endTag(NAMESPACE, RULE_LIST_TAG);
- xmlSerializer.endDocument();
}
private void serializeRule(Rule rule, XmlSerializer xmlSerializer) throws IOException {
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index ec4aedd01cea..bcc4c1fd902c 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -27,8 +27,6 @@ import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSW
import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN;
import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PIN;
import static com.android.internal.widget.LockPatternUtils.EscrowTokenStateChangeCallback;
-import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_ENABLED_BY_DEFAULT;
-import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_ENABLED_KEY;
import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_HANDLE_KEY;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT;
import static com.android.internal.widget.LockPatternUtils.USER_FRP;
@@ -1325,6 +1323,8 @@ public class LockSettingsService extends ILockSettings.Stub {
private void unlockUser(int userId, byte[] token, byte[] secret,
@ChallengeType int challengeType, long challenge,
@Nullable ArrayList<PendingResetLockout> resetLockouts) {
+ Slog.i(TAG, "Unlocking user " + userId + " with secret only, length "
+ + (secret != null ? secret.length : 0));
// TODO: make this method fully async so we can update UI with progress strings
final boolean alreadyUnlocked = mUserManager.isUserUnlockingOrUnlocked(userId);
final CountDownLatch latch = new CountDownLatch(1);
@@ -2580,23 +2580,12 @@ public class LockSettingsService extends ILockSettings.Stub {
return type == PersistentData.TYPE_SP || type == PersistentData.TYPE_SP_WEAVER;
}
long handle = getSyntheticPasswordHandleLocked(userId);
- // This is a global setting
- long enabled = getLong(SYNTHETIC_PASSWORD_ENABLED_KEY,
- SYNTHETIC_PASSWORD_ENABLED_BY_DEFAULT, UserHandle.USER_SYSTEM);
- return enabled != 0 && handle != SyntheticPasswordManager.DEFAULT_HANDLE;
+ return handle != SyntheticPasswordManager.DEFAULT_HANDLE;
}
@VisibleForTesting
protected boolean shouldMigrateToSyntheticPasswordLocked(int userId) {
- long handle = getSyntheticPasswordHandleLocked(userId);
- // This is a global setting
- long enabled = getLong(SYNTHETIC_PASSWORD_ENABLED_KEY,
- SYNTHETIC_PASSWORD_ENABLED_BY_DEFAULT, UserHandle.USER_SYSTEM);
- return enabled != 0 && handle == SyntheticPasswordManager.DEFAULT_HANDLE;
- }
-
- private void enableSyntheticPasswordLocked() {
- setLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 1, UserHandle.USER_SYSTEM);
+ return true;
}
private VerifyCredentialResponse spBasedDoVerifyCredential(LockscreenCredential userCredential,
@@ -2651,11 +2640,7 @@ public class LockSettingsService extends ILockSettings.Stub {
}
}
}
-
if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
- setUserPasswordMetrics(userCredential, userId);
- unlockKeystore(authResult.authToken.deriveKeyStorePassword(), userId);
-
// Do resetLockout / revokeChallenge when all profiles are unlocked
if (hasEnrolledBiometrics) {
if (resetLockouts == null) {
@@ -2664,18 +2649,13 @@ public class LockSettingsService extends ILockSettings.Stub {
resetLockouts.add(new PendingResetLockout(userId, response.getPayload()));
}
- final byte[] secret = authResult.authToken.deriveDiskEncryptionKey();
- Slog.i(TAG, "Unlocking user " + userId + " with secret only, length " + secret.length);
- unlockUser(userId, null, secret, challengeType, challenge, resetLockouts);
-
- activateEscrowTokens(authResult.authToken, userId);
-
- if (isManagedProfileWithSeparatedLock(userId)) {
- setDeviceUnlockedForUser(userId);
- }
- mStrongAuth.reportSuccessfulStrongAuthUnlock(userId);
-
- onAuthTokenKnownForUser(userId, authResult.authToken);
+ // TODO: Move setUserPasswordMetrics() inside onCredentialVerified(): this will require
+ // LSS to store an encrypted version of the latest password metric for every user,
+ // because user credential is not known when onCredentialVerified() is called during
+ // a token-based unlock.
+ setUserPasswordMetrics(userCredential, userId);
+ onCredentialVerified(authResult.authToken, challengeType, challenge, resetLockouts,
+ userId);
} else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
if (response.getTimeout() > 0) {
requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_LOCKOUT, userId);
@@ -2685,6 +2665,27 @@ public class LockSettingsService extends ILockSettings.Stub {
return response;
}
+ private void onCredentialVerified(AuthenticationToken authToken,
+ @ChallengeType int challengeType, long challenge,
+ @Nullable ArrayList<PendingResetLockout> resetLockouts, int userId) {
+
+ unlockKeystore(authToken.deriveKeyStorePassword(), userId);
+
+ {
+ final byte[] secret = authToken.deriveDiskEncryptionKey();
+ unlockUser(userId, null, secret, challengeType, challenge, resetLockouts);
+ Arrays.fill(secret, (byte) 0);
+ }
+ activateEscrowTokens(authToken, userId);
+
+ if (isManagedProfileWithSeparatedLock(userId)) {
+ setDeviceUnlockedForUser(userId);
+ }
+ mStrongAuth.reportSuccessfulStrongAuthUnlock(userId);
+
+ onAuthTokenKnownForUser(userId, authToken);
+ }
+
private void setDeviceUnlockedForUser(int userId) {
final TrustManager trustManager = mContext.getSystemService(TrustManager.class);
trustManager.setDeviceLockedForUser(userId, false);
@@ -2923,7 +2924,6 @@ public class LockSettingsService extends ILockSettings.Stub {
private long addEscrowToken(byte[] token, int userId, EscrowTokenStateChangeCallback callback) {
if (DEBUG) Slog.d(TAG, "addEscrowToken: user=" + userId);
synchronized (mSpManager) {
- enableSyntheticPasswordLocked();
// Migrate to synthetic password based credentials if the user has no password,
// the token can then be activated immediately.
AuthenticationToken auth = null;
@@ -3057,8 +3057,10 @@ public class LockSettingsService extends ILockSettings.Stub {
return false;
}
}
- unlockUser(userId, null, authResult.authToken.deriveDiskEncryptionKey());
- onAuthTokenKnownForUser(userId, authResult.authToken);
+ // TODO: Reset biometrics lockout here. Ideally that should be self-contained inside
+ // onCredentialVerified(), which will require some refactoring on the current lockout
+ // reset logic.
+ onCredentialVerified(authResult.authToken, CHALLENGE_NONE, 0, null, userId);
return true;
}
diff --git a/services/core/java/com/android/server/media/AudioPlayerStateMonitor.java b/services/core/java/com/android/server/media/AudioPlayerStateMonitor.java
index eb706d7791d3..1d391775e550 100644
--- a/services/core/java/com/android/server/media/AudioPlayerStateMonitor.java
+++ b/services/core/java/com/android/server/media/AudioPlayerStateMonitor.java
@@ -240,8 +240,7 @@ class AudioPlayerStateMonitor {
if (!mPrevActiveAudioPlaybackConfigs.containsKey(
config.getPlayerInterfaceId())) {
if (DEBUG) {
- Log.d(TAG, "Found a new active media playback. "
- + AudioPlaybackConfiguration.toLogFriendlyString(config));
+ Log.d(TAG, "Found a new active media playback. " + config);
}
// New active audio playback.
int index = mSortedAudioPlaybackClientUids.indexOf(uid);
diff --git a/services/core/java/com/android/server/media/MediaRoute2Provider.java b/services/core/java/com/android/server/media/MediaRoute2Provider.java
index 9a49c166e2b2..f11b70ebbf71 100644
--- a/services/core/java/com/android/server/media/MediaRoute2Provider.java
+++ b/services/core/java/com/android/server/media/MediaRoute2Provider.java
@@ -22,8 +22,11 @@ import android.content.ComponentName;
import android.content.Intent;
import android.media.MediaRoute2Info;
import android.media.MediaRoute2ProviderInfo;
-import android.os.Bundle;
+import android.media.RouteSessionInfo;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
import java.util.Objects;
abstract class MediaRoute2Provider {
@@ -31,7 +34,8 @@ abstract class MediaRoute2Provider {
final String mUniqueId;
Callback mCallback;
- private MediaRoute2ProviderInfo mProviderInfo;
+ private volatile MediaRoute2ProviderInfo mProviderInfo;
+ private volatile List<RouteSessionInfo> mSessionInfos = Collections.emptyList();
MediaRoute2Provider(@NonNull ComponentName componentName) {
mComponentName = Objects.requireNonNull(componentName, "Component name must not be null.");
@@ -42,8 +46,14 @@ abstract class MediaRoute2Provider {
mCallback = callback;
}
- public abstract void requestSelectRoute(String packageName, String routeId, int seq);
- public abstract void unselectRoute(String packageName, String routeId);
+ public abstract void requestCreateSession(String packageName, String routeId,
+ String controlCategory, long requestId);
+ public abstract void releaseSession(int sessionId);
+
+ public abstract void selectRoute(int sessionId, MediaRoute2Info route);
+ public abstract void deselectRoute(int sessionId, MediaRoute2Info route);
+ public abstract void transferToRoute(int sessionId, MediaRoute2Info route);
+
public abstract void sendControlRequest(MediaRoute2Info route, Intent request);
public abstract void requestSetVolume(MediaRoute2Info route, int volume);
public abstract void requestUpdateVolume(MediaRoute2Info route, int delta);
@@ -58,15 +68,29 @@ abstract class MediaRoute2Provider {
return mProviderInfo;
}
- void setAndNotifyProviderInfo(MediaRoute2ProviderInfo info) {
- //TODO: check if info is not updated
- if (info == null) {
+ @NonNull
+ public List<RouteSessionInfo> getSessionInfos() {
+ return mSessionInfos;
+ }
+
+ void setAndNotifyProviderState(MediaRoute2ProviderInfo providerInfo,
+ List<RouteSessionInfo> sessionInfos) {
+ if (providerInfo == null) {
mProviderInfo = null;
} else {
- mProviderInfo = new MediaRoute2ProviderInfo.Builder(info)
+ mProviderInfo = new MediaRoute2ProviderInfo.Builder(providerInfo)
.setUniqueId(mUniqueId)
.build();
}
+ List<RouteSessionInfo> sessionInfoWithProviderId = new ArrayList<RouteSessionInfo>();
+ for (RouteSessionInfo sessionInfo : sessionInfos) {
+ sessionInfoWithProviderId.add(
+ new RouteSessionInfo.Builder(sessionInfo)
+ .setProviderId(mUniqueId)
+ .build());
+ }
+ mSessionInfos = sessionInfoWithProviderId;
+
if (mCallback != null) {
mCallback.onProviderStateChanged(this);
}
@@ -79,8 +103,10 @@ abstract class MediaRoute2Provider {
public interface Callback {
void onProviderStateChanged(@Nullable MediaRoute2Provider provider);
- void onRouteSelected(@NonNull MediaRoute2ProviderProxy provider,
- @NonNull String clientPackageName, @NonNull MediaRoute2Info route,
- @Nullable Bundle controlHints, int seq);
+ void onSessionCreated(@NonNull MediaRoute2Provider provider,
+ @Nullable RouteSessionInfo sessionInfo, long requestId);
+ // TODO: Remove this when MediaRouter2ServiceImpl notifies clients of session changes.
+ void onSessionInfoChanged(@NonNull MediaRoute2Provider provider,
+ @NonNull RouteSessionInfo sessionInfo);
}
}
diff --git a/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java b/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
index a5abb1835e7b..f8d8f9fd5fbd 100644
--- a/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
+++ b/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
@@ -17,6 +17,7 @@
package com.android.server.media;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -26,7 +27,7 @@ import android.media.IMediaRoute2ProviderClient;
import android.media.MediaRoute2Info;
import android.media.MediaRoute2ProviderInfo;
import android.media.MediaRoute2ProviderService;
-import android.os.Bundle;
+import android.media.RouteSessionInfo;
import android.os.Handler;
import android.os.IBinder;
import android.os.IBinder.DeathRecipient;
@@ -37,6 +38,8 @@ import android.util.Slog;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
+import java.util.Collections;
+import java.util.List;
import java.util.Objects;
/**
@@ -74,22 +77,45 @@ final class MediaRoute2ProviderProxy extends MediaRoute2Provider implements Serv
}
@Override
- public void requestSelectRoute(String packageName, String routeId, int seq) {
+ public void requestCreateSession(String packageName, String routeId, String controlCategory,
+ long requestId) {
if (mConnectionReady) {
- mActiveConnection.requestSelectRoute(packageName, routeId, seq);
+ mActiveConnection.requestCreateSession(packageName, routeId, controlCategory,
+ requestId);
updateBinding();
}
}
@Override
- public void unselectRoute(String packageName, String routeId) {
+ public void releaseSession(int sessionId) {
if (mConnectionReady) {
- mActiveConnection.unselectRoute(packageName, routeId);
+ mActiveConnection.releaseSession(sessionId);
updateBinding();
}
}
@Override
+ public void selectRoute(int sessionId, MediaRoute2Info route) {
+ if (mConnectionReady) {
+ mActiveConnection.selectRoute(sessionId, route.getId());
+ }
+ }
+
+ @Override
+ public void deselectRoute(int sessionId, MediaRoute2Info route) {
+ if (mConnectionReady) {
+ mActiveConnection.deselectRoute(sessionId, route.getId());
+ }
+ }
+
+ @Override
+ public void transferToRoute(int sessionId, MediaRoute2Info route) {
+ if (mConnectionReady) {
+ mActiveConnection.transferToRoute(sessionId, route.getId());
+ }
+ }
+
+ @Override
public void sendControlRequest(MediaRoute2Info route, Intent request) {
if (mConnectionReady) {
mActiveConnection.sendControlRequest(route.getId(), request);
@@ -244,28 +270,40 @@ final class MediaRoute2ProviderProxy extends MediaRoute2Provider implements Serv
}
}
- private void onProviderInfoUpdated(Connection connection, MediaRoute2ProviderInfo info) {
+ private void onProviderStateUpdated(Connection connection,
+ MediaRoute2ProviderInfo providerInfo, List<RouteSessionInfo> sessionInfos) {
if (mActiveConnection != connection) {
return;
}
if (DEBUG) {
Slog.d(TAG, this + ": State changed ");
}
- setAndNotifyProviderInfo(info);
+ setAndNotifyProviderState(providerInfo, sessionInfos);
}
- private void onRouteSelected(Connection connection,
- String packageName, String routeId, Bundle controlHints, int seq) {
+ private void onSessionCreated(Connection connection, @Nullable RouteSessionInfo sessionInfo,
+ long requestId) {
if (mActiveConnection != connection) {
return;
}
- MediaRoute2ProviderInfo providerInfo = getProviderInfo();
- MediaRoute2Info route = (providerInfo == null) ? null : providerInfo.getRoute(routeId);
- if (route == null) {
- Slog.w(TAG, this + ": Unknown route " + routeId + " is selected from remove provider");
+ if (sessionInfo != null) {
+ sessionInfo = new RouteSessionInfo.Builder(sessionInfo)
+ .setProviderId(getUniqueId())
+ .build();
+ }
+ mCallback.onSessionCreated(this, sessionInfo, requestId);
+ }
+
+ private void onSessionInfoChanged(Connection connection, RouteSessionInfo sessionInfo) {
+ if (mActiveConnection != connection) {
return;
}
- mCallback.onRouteSelected(this, packageName, route, controlHints, seq);
+ if (sessionInfo == null) {
+ Slog.w(TAG, "onSessionInfoChanged: Ignoring null sessionInfo sent from "
+ + mComponentName);
+ return;
+ }
+ mCallback.onSessionInfoChanged(this, sessionInfo);
}
private void disconnect() {
@@ -273,7 +311,7 @@ final class MediaRoute2ProviderProxy extends MediaRoute2Provider implements Serv
mConnectionReady = false;
mActiveConnection.dispose();
mActiveConnection = null;
- setAndNotifyProviderInfo(null);
+ setAndNotifyProviderState(null, Collections.emptyList());
}
}
@@ -308,19 +346,45 @@ final class MediaRoute2ProviderProxy extends MediaRoute2Provider implements Serv
mClient.dispose();
}
- public void requestSelectRoute(String packageName, String routeId, int seq) {
+ public void requestCreateSession(String packageName, String routeId, String controlCategory,
+ long requestId) {
try {
- mProvider.requestSelectRoute(packageName, routeId, seq);
+ mProvider.requestCreateSession(packageName, routeId,
+ controlCategory, requestId);
} catch (RemoteException ex) {
- Slog.e(TAG, "Failed to deliver request to set discovery mode.", ex);
+ Slog.e(TAG, "Failed to deliver request to create a session.", ex);
}
}
- public void unselectRoute(String packageName, String routeId) {
+ public void releaseSession(int sessionId) {
try {
- mProvider.unselectRoute(packageName, routeId);
+ mProvider.releaseSession(sessionId);
} catch (RemoteException ex) {
- Slog.e(TAG, "Failed to deliver request to set discovery mode.", ex);
+ Slog.e(TAG, "Failed to deliver request to release a session.", ex);
+ }
+ }
+
+ public void selectRoute(int sessionId, String routeId) {
+ try {
+ mProvider.selectRoute(sessionId, routeId);
+ } catch (RemoteException ex) {
+ Slog.e(TAG, "Failed to deliver request to select a route for a session.", ex);
+ }
+ }
+
+ public void deselectRoute(int sessionId, String routeId) {
+ try {
+ mProvider.deselectRoute(sessionId, routeId);
+ } catch (RemoteException ex) {
+ Slog.e(TAG, "Failed to deliver request to deselect a route from a session.", ex);
+ }
+ }
+
+ public void transferToRoute(int sessionId, String routeId) {
+ try {
+ mProvider.transferToRoute(sessionId, routeId);
+ } catch (RemoteException ex) {
+ Slog.e(TAG, "Failed to deliver request to transfer a session to a route.", ex);
}
}
@@ -353,13 +417,19 @@ final class MediaRoute2ProviderProxy extends MediaRoute2Provider implements Serv
mHandler.post(() -> onConnectionDied(Connection.this));
}
- void postProviderInfoUpdated(MediaRoute2ProviderInfo info) {
- mHandler.post(() -> onProviderInfoUpdated(Connection.this, info));
+ void postProviderStateUpdated(MediaRoute2ProviderInfo providerInfo,
+ List<RouteSessionInfo> sessionInfos) {
+ mHandler.post(() -> onProviderStateUpdated(Connection.this,
+ providerInfo, sessionInfos));
+ }
+
+ void postSessionCreated(@Nullable RouteSessionInfo sessionInfo, long requestId) {
+ mHandler.post(() -> onSessionCreated(Connection.this, sessionInfo,
+ requestId));
}
- void postRouteSelected(String packageName, String routeId, Bundle controlHints, int seq) {
- mHandler.post(() -> onRouteSelected(Connection.this,
- packageName, routeId, controlHints, seq));
+ void postSessionInfoChanged(RouteSessionInfo sessionInfo) {
+ mHandler.post(() -> onSessionInfoChanged(Connection.this, sessionInfo));
}
}
@@ -375,21 +445,28 @@ final class MediaRoute2ProviderProxy extends MediaRoute2Provider implements Serv
}
@Override
- public void updateProviderInfo(MediaRoute2ProviderInfo info) {
+ public void updateState(MediaRoute2ProviderInfo providerInfo,
+ List<RouteSessionInfo> sessionInfos) {
Connection connection = mConnectionRef.get();
if (connection != null) {
- connection.postProviderInfoUpdated(info);
+ connection.postProviderStateUpdated(providerInfo, sessionInfos);
}
}
@Override
- public void notifyRouteSelected(String packageName, String routeId,
- Bundle controlHints, int seq) {
+ public void notifySessionCreated(@Nullable RouteSessionInfo sessionInfo, long requestId) {
Connection connection = mConnectionRef.get();
if (connection != null) {
- connection.postRouteSelected(packageName, routeId, controlHints, seq);
+ connection.postSessionCreated(sessionInfo, requestId);
}
}
+ @Override
+ public void notifySessionInfoChanged(RouteSessionInfo sessionInfo) {
+ Connection connection = mConnectionRef.get();
+ if (connection != null) {
+ connection.postSessionInfoChanged(sessionInfo);
+ }
+ }
}
}
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index 9fcee50d7037..82d22505b303 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -28,13 +28,12 @@ import android.media.IMediaRouter2Client;
import android.media.IMediaRouter2Manager;
import android.media.MediaRoute2Info;
import android.media.MediaRoute2ProviderInfo;
-import android.media.MediaRouter2;
+import android.media.RouteSessionInfo;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
-import android.os.Message;
import android.os.RemoteException;
import android.os.UserHandle;
import android.text.TextUtils;
@@ -53,8 +52,11 @@ import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Objects;
import java.util.Set;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.atomic.AtomicInteger;
/**
* TODO: Merge this to MediaRouterService once it's finished.
@@ -66,6 +68,7 @@ class MediaRouter2ServiceImpl {
private final Context mContext;
private final Object mLock = new Object();
+ final AtomicInteger mNextClientId = new AtomicInteger(1);
@GuardedBy("mLock")
private final SparseArray<UserRecord> mUserRecords = new SparseArray<>();
@@ -75,8 +78,7 @@ class MediaRouter2ServiceImpl {
private final ArrayMap<IBinder, ManagerRecord> mAllManagerRecords = new ArrayMap<>();
@GuardedBy("mLock")
private int mCurrentUserId = -1;
- @GuardedBy("mLock")
- private int mSelectRouteRequestSequenceNumber = 1;
+
MediaRouter2ServiceImpl(Context context) {
mContext = context;
@@ -166,43 +168,97 @@ class MediaRouter2ServiceImpl {
}
}
- public void sendControlRequest(@NonNull IMediaRouter2Client client,
- @NonNull MediaRoute2Info route, @NonNull Intent request) {
+ public void requestCreateSession(IMediaRouter2Client client, MediaRoute2Info route,
+ String controlCategory, int requestId) {
Objects.requireNonNull(client, "client must not be null");
Objects.requireNonNull(route, "route must not be null");
- Objects.requireNonNull(request, "request must not be null");
+ if (TextUtils.isEmpty(controlCategory)) {
+ throw new IllegalArgumentException("controlCategory must not be empty");
+ }
final long token = Binder.clearCallingIdentity();
+
try {
synchronized (mLock) {
- sendControlRequestLocked(client, route, request);
+ requestCreateSessionLocked(client, route, controlCategory, requestId);
}
} finally {
Binder.restoreCallingIdentity(token);
}
}
- public void setControlCategories(@NonNull IMediaRouter2Client client,
- @Nullable List<String> categories) {
+ public void selectRoute(IMediaRouter2Client client, String uniqueSessionId,
+ MediaRoute2Info route) {
Objects.requireNonNull(client, "client must not be null");
+ Objects.requireNonNull(route, "route must not be null");
final long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- Client2Record clientRecord = mAllClientRecords.get(client.asBinder());
- setControlCategoriesLocked(clientRecord, categories);
+ selectRouteLocked(client, uniqueSessionId, route);
}
} finally {
Binder.restoreCallingIdentity(token);
}
}
- public void requestSelectRoute2(@NonNull IMediaRouter2Client client,
- @Nullable MediaRoute2Info route) {
+
+ public void deselectRoute(IMediaRouter2Client client, String uniqueSessionId,
+ MediaRoute2Info route) {
+ Objects.requireNonNull(client, "client must not be null");
+ Objects.requireNonNull(route, "route must not be null");
+
final long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- requestSelectRoute2Locked(mAllClientRecords.get(client.asBinder()), false, route);
+ deselectRouteLocked(client, uniqueSessionId, route);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ public void transferToRoute(IMediaRouter2Client client, String uniqueSessionId,
+ MediaRoute2Info route) {
+ Objects.requireNonNull(client, "client must not be null");
+ Objects.requireNonNull(route, "route must not be null");
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ transferToRouteLocked(client, uniqueSessionId, route);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ public void sendControlRequest(@NonNull IMediaRouter2Client client,
+ @NonNull MediaRoute2Info route, @NonNull Intent request) {
+ Objects.requireNonNull(client, "client must not be null");
+ Objects.requireNonNull(route, "route must not be null");
+ Objects.requireNonNull(request, "request must not be null");
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ sendControlRequestLocked(client, route, request);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ public void setControlCategories(@NonNull IMediaRouter2Client client,
+ @NonNull List<String> categories) {
+ Objects.requireNonNull(client, "client must not be null");
+ Objects.requireNonNull(categories, "categories must not be null");
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ Client2Record clientRecord = mAllClientRecords.get(client.asBinder());
+ setControlCategoriesLocked(clientRecord, categories);
}
} finally {
Binder.restoreCallingIdentity(token);
@@ -237,12 +293,12 @@ class MediaRouter2ServiceImpl {
}
}
- public void selectClientRoute2(@NonNull IMediaRouter2Manager manager,
- String packageName, @Nullable MediaRoute2Info route) {
+ public void requestCreateClientSession(IMediaRouter2Manager manager, String packageName,
+ MediaRoute2Info route, int requestId) {
final long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- selectClientRoute2Locked(manager, packageName, route);
+ requestClientCreateSessionLocked(manager, packageName, route, requestId);
}
} finally {
Binder.restoreCallingIdentity(token);
@@ -279,6 +335,18 @@ class MediaRouter2ServiceImpl {
}
}
+ @NonNull
+ public List<RouteSessionInfo> getActiveSessions(IMediaRouter2Manager manager) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ return getActiveSessionsLocked(manager);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
//TODO: Review this is handling multi-user properly.
void switchUser() {
synchronized (mLock) {
@@ -352,46 +420,70 @@ class MediaRouter2ServiceImpl {
}
}
- private void requestSelectRoute2Locked(Client2Record clientRecord, boolean selectedByManager,
- MediaRoute2Info route) {
+ private void requestCreateSessionLocked(@NonNull IMediaRouter2Client client,
+ @NonNull MediaRoute2Info route, @NonNull String controlCategory, long requestId) {
+ final IBinder binder = client.asBinder();
+ final Client2Record clientRecord = mAllClientRecords.get(binder);
+
+ // client id is not assigned yet
+ if (toClientId(requestId) == 0) {
+ requestId = toUniqueRequestId(clientRecord.mClientId, toClientRequestId(requestId));
+ }
+
if (clientRecord != null) {
- MediaRoute2Info oldRoute = clientRecord.mSelectedRoute;
- clientRecord.mSelectingRoute = route;
- clientRecord.mIsManagerSelecting = selectedByManager;
-
- UserHandler handler = clientRecord.mUserRecord.mHandler;
- //TODO: Handle transfer instead of unselect and select
- if (oldRoute != null) {
- handler.sendMessage(obtainMessage(
- UserHandler::unselectRoute, handler, clientRecord.mPackageName, oldRoute));
- }
- if (route != null) {
- final int seq = mSelectRouteRequestSequenceNumber;
- mSelectRouteRequestSequenceNumber++;
-
- handler.sendMessage(obtainMessage(
- UserHandler::requestSelectRoute, handler, clientRecord.mPackageName,
- route, seq));
- // Remove all previous timeout messages
- for (int previousSeq : clientRecord.mSelectRouteSequenceNumbers) {
- clientRecord.mUserRecord.mHandler.removeMessages(previousSeq);
- }
- clientRecord.mSelectRouteSequenceNumbers.clear();
+ clientRecord.mUserRecord.mHandler.sendMessage(
+ obtainMessage(UserHandler::requestCreateSessionOnHandler,
+ clientRecord.mUserRecord.mHandler,
+ clientRecord, route, controlCategory, requestId));
+ }
+ }
- // When the request is not handled in timeout, set the client's route to default.
- Message timeoutMsg = obtainMessage(UserHandler::handleRouteSelectionTimeout,
- handler, clientRecord.mPackageName, route);
- timeoutMsg.what = seq; // Make the message cancelable.
- handler.sendMessageDelayed(timeoutMsg, ROUTE_SELECTION_REQUEST_TIMEOUT_MS);
- clientRecord.mSelectRouteSequenceNumbers.add(seq);
- }
+ private void selectRouteLocked(@NonNull IMediaRouter2Client client, String uniqueSessionId,
+ @NonNull MediaRoute2Info route) {
+ final IBinder binder = client.asBinder();
+ final Client2Record clientRecord = mAllClientRecords.get(binder);
+
+ if (clientRecord != null) {
+ clientRecord.mUserRecord.mHandler.sendMessage(
+ obtainMessage(UserHandler::selectRouteOnHandler,
+ clientRecord.mUserRecord.mHandler,
+ clientRecord, uniqueSessionId, route));
+ }
+ }
+
+ private void deselectRouteLocked(@NonNull IMediaRouter2Client client, String uniqueSessionId,
+ @NonNull MediaRoute2Info route) {
+ final IBinder binder = client.asBinder();
+ final Client2Record clientRecord = mAllClientRecords.get(binder);
+
+ if (clientRecord != null) {
+ clientRecord.mUserRecord.mHandler.sendMessage(
+ obtainMessage(UserHandler::deselectRouteOnHandler,
+ clientRecord.mUserRecord.mHandler,
+ clientRecord, uniqueSessionId, route));
+ }
+ }
+
+ private void transferToRouteLocked(@NonNull IMediaRouter2Client client, String uniqueSessionId,
+ @NonNull MediaRoute2Info route) {
+ final IBinder binder = client.asBinder();
+ final Client2Record clientRecord = mAllClientRecords.get(binder);
+
+ if (clientRecord != null) {
+ clientRecord.mUserRecord.mHandler.sendMessage(
+ obtainMessage(UserHandler::transferToRouteOnHandler,
+ clientRecord.mUserRecord.mHandler,
+ clientRecord, uniqueSessionId, route));
}
}
private void setControlCategoriesLocked(Client2Record clientRecord, List<String> categories) {
if (clientRecord != null) {
- clientRecord.mControlCategories = categories;
+ if (clientRecord.mControlCategories.equals(categories)) {
+ return;
+ }
+ clientRecord.mControlCategories = categories;
clientRecord.mUserRecord.mHandler.sendMessage(
obtainMessage(UserHandler::updateClientUsage,
clientRecord.mUserRecord.mHandler, clientRecord));
@@ -487,17 +579,20 @@ class MediaRouter2ServiceImpl {
}
}
- private void selectClientRoute2Locked(IMediaRouter2Manager manager,
- String packageName, MediaRoute2Info route) {
+ private void requestClientCreateSessionLocked(IMediaRouter2Manager manager,
+ String packageName, MediaRoute2Info route, int requestId) {
ManagerRecord managerRecord = mAllManagerRecords.get(manager.asBinder());
if (managerRecord != null) {
Client2Record clientRecord =
managerRecord.mUserRecord.findClientRecordLocked(packageName);
if (clientRecord == null) {
- Slog.w(TAG, "Ignoring route selection for unknown client.");
+ Slog.w(TAG, "Ignoring session creation for unknown client.");
}
+ long uniqueRequestId = toUniqueRequestId(managerRecord.mClientId, requestId);
if (clientRecord != null && managerRecord.mTrusted) {
- requestSelectRoute2Locked(clientRecord, true, route);
+ //TODO: select category properly
+ requestCreateSessionLocked(clientRecord.mClient, route,
+ route.getSupportedCategories().get(0), uniqueRequestId);
}
}
}
@@ -526,6 +621,20 @@ class MediaRouter2ServiceImpl {
}
}
+ private List<RouteSessionInfo> getActiveSessionsLocked(IMediaRouter2Manager manager) {
+ final IBinder binder = manager.asBinder();
+ ManagerRecord managerRecord = mAllManagerRecords.get(binder);
+
+ if (managerRecord == null) {
+ return Collections.emptyList();
+ }
+
+ List<RouteSessionInfo> sessionInfos = new ArrayList<>();
+ for (MediaRoute2Provider provider : managerRecord.mUserRecord.mHandler.mMediaProviders) {
+ sessionInfos.addAll(provider.getSessionInfos());
+ }
+ return sessionInfos;
+ }
private void initializeUserLocked(UserRecord userRecord) {
if (DEBUG) {
@@ -553,6 +662,18 @@ class MediaRouter2ServiceImpl {
}
}
+ static long toUniqueRequestId(int clientId, int requestId) {
+ return ((long) clientId << 32) | requestId;
+ }
+
+ static int toClientId(long uniqueRequestId) {
+ return (int) (uniqueRequestId >> 32);
+ }
+
+ static int toClientRequestId(long uniqueRequestId) {
+ return (int) uniqueRequestId;
+ }
+
final class UserRecord {
public final int mUserId;
//TODO: make records private for thread-safety
@@ -565,6 +686,7 @@ class MediaRouter2ServiceImpl {
mHandler = new UserHandler(MediaRouter2ServiceImpl.this, this);
}
+ // TODO: This assumes that only one client exists in a package. Is it true?
Client2Record findClientRecordLocked(String packageName) {
for (Client2Record clientRecord : mClientRecords) {
if (TextUtils.equals(clientRecord.mPackageName, packageName)) {
@@ -583,6 +705,7 @@ class MediaRouter2ServiceImpl {
public final int mUid;
public final int mPid;
public final boolean mTrusted;
+ public final int mClientId;
public List<String> mControlCategories;
public boolean mIsManagerSelecting;
@@ -599,6 +722,7 @@ class MediaRouter2ServiceImpl {
mUid = uid;
mPid = pid;
mTrusted = trusted;
+ mClientId = mNextClientId.getAndIncrement();
}
public void dispose() {
@@ -618,6 +742,7 @@ class MediaRouter2ServiceImpl {
public final int mPid;
public final String mPackageName;
public final boolean mTrusted;
+ public final int mClientId;
ManagerRecord(UserRecord userRecord, IMediaRouter2Manager manager,
int uid, int pid, String packageName, boolean trusted) {
@@ -627,6 +752,7 @@ class MediaRouter2ServiceImpl {
mPid = pid;
mPackageName = packageName;
mTrusted = trusted;
+ mClientId = mNextClientId.getAndIncrement();
}
public void dispose() {
@@ -663,10 +789,13 @@ class MediaRouter2ServiceImpl {
private final SystemMediaRoute2Provider mSystemProvider;
private final ArrayList<MediaRoute2Provider> mMediaProviders =
new ArrayList<>();
- private final List<MediaRoute2ProviderInfo> mProviderInfos = new ArrayList<>();
+
+ private final List<MediaRoute2ProviderInfo> mLastProviderInfos = new ArrayList<>();
+ private final CopyOnWriteArrayList<SessionCreationRequest> mSessionCreationRequests =
+ new CopyOnWriteArrayList<>();
+ private final Map<String, Client2Record> mSessionToClientMap = new ArrayMap<>();
private boolean mRunning;
- private boolean mProviderInfosUpdateScheduled;
UserHandler(MediaRouter2ServiceImpl service, UserRecord userRecord) {
super(Looper.getMainLooper(), null, true);
@@ -710,30 +839,37 @@ class MediaRouter2ServiceImpl {
}
@Override
- public void onRouteSelected(@NonNull MediaRoute2ProviderProxy provider,
- String clientPackageName, MediaRoute2Info route, Bundle controlHints, int seq) {
- sendMessage(PooledLambda.obtainMessage(
- UserHandler::updateSelectedRoute, this, provider, clientPackageName, route,
- controlHints, seq));
+ public void onSessionCreated(@NonNull MediaRoute2Provider provider,
+ @Nullable RouteSessionInfo sessionInfo, long requestId) {
+ sendMessage(PooledLambda.obtainMessage(UserHandler::handleCreateSessionResultOnHandler,
+ this, provider, sessionInfo, requestId));
+ }
+
+ @Override
+ public void onSessionInfoChanged(@NonNull MediaRoute2Provider provider,
+ @NonNull RouteSessionInfo sessionInfo) {
+ sendMessage(PooledLambda.obtainMessage(UserHandler::updateSession,
+ this, provider, sessionInfo));
}
+ //TODO: notify session info updates
private void updateProvider(MediaRoute2Provider provider) {
int providerIndex = getProviderInfoIndex(provider.getUniqueId());
MediaRoute2ProviderInfo providerInfo = provider.getProviderInfo();
MediaRoute2ProviderInfo prevInfo =
- (providerIndex < 0) ? null : mProviderInfos.get(providerIndex);
+ (providerIndex < 0) ? null : mLastProviderInfos.get(providerIndex);
if (Objects.equals(prevInfo, providerInfo)) return;
if (prevInfo == null) {
- mProviderInfos.add(providerInfo);
+ mLastProviderInfos.add(providerInfo);
Collection<MediaRoute2Info> addedRoutes = providerInfo.getRoutes();
if (addedRoutes.size() > 0) {
sendMessage(PooledLambda.obtainMessage(UserHandler::notifyRoutesAddedToClients,
this, getClients(), new ArrayList<>(addedRoutes)));
}
} else if (providerInfo == null) {
- mProviderInfos.remove(prevInfo);
+ mLastProviderInfos.remove(prevInfo);
Collection<MediaRoute2Info> removedRoutes = prevInfo.getRoutes();
if (removedRoutes.size() > 0) {
sendMessage(PooledLambda.obtainMessage(
@@ -741,7 +877,7 @@ class MediaRouter2ServiceImpl {
this, getClients(), new ArrayList<>(removedRoutes)));
}
} else {
- mProviderInfos.set(providerIndex, providerInfo);
+ mLastProviderInfos.set(providerIndex, providerInfo);
List<MediaRoute2Info> addedRoutes = new ArrayList<>();
List<MediaRoute2Info> removedRoutes = new ArrayList<>();
List<MediaRoute2Info> changedRoutes = new ArrayList<>();
@@ -790,8 +926,8 @@ class MediaRouter2ServiceImpl {
}
private int getProviderInfoIndex(String providerId) {
- for (int i = 0; i < mProviderInfos.size(); i++) {
- MediaRoute2ProviderInfo providerInfo = mProviderInfos.get(i);
+ for (int i = 0; i < mLastProviderInfos.size(); i++) {
+ MediaRoute2ProviderInfo providerInfo = mLastProviderInfos.get(i);
if (TextUtils.equals(providerInfo.getUniqueId(), providerId)) {
return i;
}
@@ -799,100 +935,217 @@ class MediaRouter2ServiceImpl {
return -1;
}
- private void updateSelectedRoute(MediaRoute2ProviderProxy provider,
- String clientPackageName, MediaRoute2Info selectedRoute, Bundle controlHints,
- int seq) {
- if (selectedRoute == null
- || !TextUtils.equals(clientPackageName, selectedRoute.getClientPackageName())) {
- Log.w(TAG, "Ignoring route selection which has non-matching clientPackageName.");
+ private void requestCreateSessionOnHandler(Client2Record clientRecord,
+ MediaRoute2Info route, String controlCategory, long requestId) {
+
+ final MediaRoute2Provider provider = findProvider(route.getProviderId());
+ if (provider == null) {
+ Slog.w(TAG, "Ignoring session creation request since no provider found for"
+ + " given route=" + route);
+ notifySessionCreationFailed(clientRecord, toClientRequestId(requestId));
return;
}
- MediaRouter2ServiceImpl service = mServiceRef.get();
- if (service == null) {
+ if (!route.getSupportedCategories().contains(controlCategory)) {
+ Slog.w(TAG, "Ignoring session creation request since the given route=" + route
+ + " doesn't support the given category=" + controlCategory);
+ notifySessionCreationFailed(clientRecord, toClientRequestId(requestId));
return;
}
- Client2Record clientRecord;
- synchronized (service.mLock) {
- clientRecord = mUserRecord.findClientRecordLocked(clientPackageName);
+ // TODO: Apply timeout for each request (How many seconds should we wait?)
+ SessionCreationRequest request = new SessionCreationRequest(
+ clientRecord, route, controlCategory, requestId);
+ mSessionCreationRequests.add(request);
+
+ provider.requestCreateSession(clientRecord.mPackageName, route.getId(),
+ controlCategory, requestId);
+ }
+
+ private void selectRouteOnHandler(@NonNull Client2Record clientRecord,
+ String uniqueSessionId, MediaRoute2Info route) {
+ if (!checkArgumentsForSessionControl(clientRecord, uniqueSessionId, route,
+ "selecting")) {
+ return;
+ }
+
+ final String providerId = route.getProviderId();
+ final MediaRoute2Provider provider = findProvider(providerId);
+ // TODO: Remove this null check when the mMediaProviders are referenced only in handler.
+ if (provider == null) {
+ return;
+ }
+ provider.selectRoute(RouteSessionInfo.getSessionId(uniqueSessionId, providerId), route);
+ }
+
+ private void deselectRouteOnHandler(@NonNull Client2Record clientRecord,
+ String uniqueSessionId, MediaRoute2Info route) {
+ if (!checkArgumentsForSessionControl(clientRecord, uniqueSessionId, route,
+ "deselecting")) {
+ return;
+ }
+
+ final String providerId = route.getProviderId();
+ final MediaRoute2Provider provider = findProvider(providerId);
+ // TODO: Remove this null check when the mMediaProviders are referenced only in handler.
+ if (provider == null) {
+ return;
}
+ provider.deselectRoute(
+ RouteSessionInfo.getSessionId(uniqueSessionId, providerId), route);
+ }
- //TODO: handle a case such that controlHints is null. (How should we notify MR2?)
+ private void transferToRouteOnHandler(@NonNull Client2Record clientRecord,
+ String uniqueSessionId, MediaRoute2Info route) {
+ if (!checkArgumentsForSessionControl(clientRecord, uniqueSessionId, route,
+ "transferring to")) {
+ return;
+ }
- if (clientRecord.mSelectingRoute == null || !TextUtils.equals(
- clientRecord.mSelectingRoute.getUniqueId(), selectedRoute.getUniqueId())) {
- Log.w(TAG, "Ignoring invalid updateSelectedRoute call. selectingRoute="
- + clientRecord.mSelectingRoute + " route=" + selectedRoute);
- unselectRoute(clientPackageName, selectedRoute);
+ final String providerId = route.getProviderId();
+ final MediaRoute2Provider provider = findProvider(providerId);
+ // TODO: Remove this null check when the mMediaProviders are referenced only in handler.
+ if (provider == null) {
return;
}
- clientRecord.mSelectingRoute = null;
- clientRecord.mSelectedRoute = selectedRoute;
+ provider.transferToRoute(
+ RouteSessionInfo.getSessionId(uniqueSessionId, providerId), route);
+ }
+
+ private boolean checkArgumentsForSessionControl(@NonNull Client2Record clientRecord,
+ String uniqueSessionId, MediaRoute2Info route, @NonNull String description) {
+ if (route == null) {
+ Slog.w(TAG, "Ignoring " + description + " null route");
+ return false;
+ }
+
+ final String providerId = route.getProviderId();
+ final MediaRoute2Provider provider = findProvider(providerId);
+ if (provider == null) {
+ Slog.w(TAG, "Ignoring " + description + " route since no provider found for "
+ + "given route=" + route);
+ return false;
+ }
- notifyRouteSelectedToClient(clientRecord.mClient,
- selectedRoute,
- clientRecord.mIsManagerSelecting
- ? MediaRouter2.SELECT_REASON_SYSTEM_SELECTED :
- MediaRouter2.SELECT_REASON_USER_SELECTED,
- controlHints);
- updateClientUsage(clientRecord);
+ if (TextUtils.isEmpty(uniqueSessionId)) {
+ Slog.w(TAG, "Ignoring " + description + " route with empty unique session ID. "
+ + "route=" + route);
+ return false;
+ }
+
+ Client2Record matchingRecord = mSessionToClientMap.get(uniqueSessionId);
+ if (matchingRecord != clientRecord) {
+ Slog.w(TAG, "Ignoring " + description + " route from non-matching client. "
+ + "packageName=" + clientRecord.mPackageName + " route=" + route);
+ return false;
+ }
- // Remove the fallback route selection message.
- removeMessages(seq);
+ try {
+ RouteSessionInfo.getSessionId(uniqueSessionId, providerId);
+ } catch (Exception ex) {
+ Slog.w(TAG, "Failed to get int session id from unique session id. "
+ + "uniqueSessionId=" + uniqueSessionId + " providerId=" + providerId);
+ return false;
+ }
+
+ return true;
}
- private void handleRouteSelectionTimeout(String clientPackageName,
- MediaRoute2Info selectingRoute) {
- MediaRouter2ServiceImpl service = mServiceRef.get();
- if (service == null) {
+ private void handleCreateSessionResultOnHandler(
+ @NonNull MediaRoute2Provider provider, @Nullable RouteSessionInfo sessionInfo,
+ long requestId) {
+ SessionCreationRequest matchingRequest = null;
+
+ for (SessionCreationRequest request : mSessionCreationRequests) {
+ if (request.mRequestId == requestId
+ && TextUtils.equals(
+ request.mRoute.getProviderId(), provider.getUniqueId())) {
+ matchingRequest = request;
+ break;
+ }
+ }
+
+ if (matchingRequest == null) {
+ Slog.w(TAG, "Ignoring session creation result for unknown request. "
+ + "requestId=" + requestId + ", sessionInfo=" + sessionInfo);
return;
}
- Client2Record clientRecord;
- synchronized (service.mLock) {
- clientRecord = mUserRecord.findClientRecordLocked(clientPackageName);
+ mSessionCreationRequests.remove(matchingRequest);
+
+ if (sessionInfo == null) {
+ // Failed
+ notifySessionCreationFailed(matchingRequest.mClientRecord,
+ toClientRequestId(requestId));
+ return;
}
- if (clientRecord.mSelectingRoute == null || !TextUtils.equals(
- clientRecord.mSelectingRoute.getUniqueId(), selectingRoute.getUniqueId())) {
- Log.w(TAG, "Ignoring invalid selectFallbackRoute call. "
- + "Current selectingRoute=" + clientRecord.mSelectingRoute
- + " , original selectingRoute=" + selectingRoute);
+ String originalRouteId = matchingRequest.mRoute.getId();
+ String originalCategory = matchingRequest.mControlCategory;
+ Client2Record client2Record = matchingRequest.mClientRecord;
+
+ if (!sessionInfo.getSelectedRoutes().contains(originalRouteId)
+ || !TextUtils.equals(originalCategory,
+ sessionInfo.getControlCategory())) {
+ Slog.w(TAG, "Created session doesn't match the original request."
+ + " originalRouteId=" + originalRouteId
+ + ", originalCategory=" + originalCategory + ", requestId=" + requestId
+ + ", sessionInfo=" + sessionInfo);
+ notifySessionCreationFailed(matchingRequest.mClientRecord,
+ toClientRequestId(requestId));
return;
}
- clientRecord.mSelectingRoute = null;
- // TODO: When the default route is introduced, make mSelectedRoute always non-null.
- MediaRoute2Info fallbackRoute = null;
- clientRecord.mSelectedRoute = fallbackRoute;
+ // Succeeded
+ notifySessionCreated(matchingRequest.mClientRecord,
+ sessionInfo, toClientRequestId(requestId));
+ mSessionToClientMap.put(sessionInfo.getUniqueSessionId(), client2Record);
+ // TODO: Tell managers for the session creation
+ }
+
+ private void updateSession(@NonNull MediaRoute2Provider provider,
+ @NonNull RouteSessionInfo sessionInfo) {
+ RouteSessionInfo sessionInfoWithProviderId = new RouteSessionInfo.Builder(sessionInfo)
+ .setProviderId(provider.getUniqueId())
+ .build();
- notifyRouteSelectedToClient(clientRecord.mClient,
- fallbackRoute,
- MediaRouter2.SELECT_REASON_FALLBACK,
- Bundle.EMPTY /* controlHints */);
- updateClientUsage(clientRecord);
+ Client2Record client2Record = mSessionToClientMap.get(
+ sessionInfoWithProviderId.getUniqueSessionId());
+ if (client2Record == null) {
+ Slog.w(TAG, "No matching client found for session=" + sessionInfoWithProviderId);
+ // TODO: Tell managers for the session update
+ return;
+ }
+ notifySessionInfoChanged(client2Record, sessionInfoWithProviderId);
+ // TODO: Tell managers for the session update
}
- private void requestSelectRoute(String clientPackageName, MediaRoute2Info route, int seq) {
- if (route != null) {
- MediaRoute2Provider provider = findProvider(route.getProviderId());
- if (provider == null) {
- Slog.w(TAG, "Ignoring to select route of unknown provider " + route);
- } else {
- provider.requestSelectRoute(clientPackageName, route.getId(), seq);
- }
+ private void notifySessionCreated(Client2Record clientRecord, RouteSessionInfo sessionInfo,
+ int requestId) {
+ try {
+ clientRecord.mClient.notifySessionCreated(sessionInfo, requestId);
+ } catch (RemoteException ex) {
+ Slog.w(TAG, "Failed to notify client of the session creation."
+ + " Client probably died.", ex);
}
}
- private void unselectRoute(String clientPackageName, MediaRoute2Info route) {
- if (route != null) {
- MediaRoute2Provider provider = findProvider(route.getProviderId());
- if (provider == null) {
- Slog.w(TAG, "Ignoring to unselect route of unknown provider " + route);
- } else {
- provider.unselectRoute(clientPackageName, route.getId());
- }
+ private void notifySessionCreationFailed(Client2Record clientRecord, int requestId) {
+ try {
+ clientRecord.mClient.notifySessionCreated(/* sessionInfo= */ null, requestId);
+ } catch (RemoteException ex) {
+ Slog.w(TAG, "Failed to notify client of the session creation failure."
+ + " Client probably died.", ex);
+ }
+ }
+
+ private void notifySessionInfoChanged(Client2Record clientRecord,
+ RouteSessionInfo sessionInfo) {
+ try {
+ clientRecord.mClient.notifySessionInfoChanged(sessionInfo);
+ } catch (RemoteException ex) {
+ Slog.w(TAG, "Failed to notify client of the session info change."
+ + " Client probably died.", ex);
}
}
@@ -947,7 +1200,7 @@ class MediaRouter2ServiceImpl {
private void notifyRoutesToClient(IMediaRouter2Client client) {
List<MediaRoute2Info> routes = new ArrayList<>();
- for (MediaRoute2ProviderInfo providerInfo : mProviderInfos) {
+ for (MediaRoute2ProviderInfo providerInfo : mLastProviderInfos) {
routes.addAll(providerInfo.getRoutes());
}
if (routes.size() == 0) {
@@ -960,13 +1213,9 @@ class MediaRouter2ServiceImpl {
}
}
+ // TODO: Remove notifyRouteSelected* methods
private void notifyRouteSelectedToClient(IMediaRouter2Client client,
MediaRoute2Info route, int reason, Bundle controlHints) {
- try {
- client.notifyRouteSelected(route, reason, controlHints);
- } catch (RemoteException ex) {
- Slog.w(TAG, "Failed to notify routes selected. Client probably died.", ex);
- }
}
private void notifyRoutesAddedToClients(List<IMediaRouter2Client> clients,
@@ -1004,7 +1253,7 @@ class MediaRouter2ServiceImpl {
private void notifyRoutesToManager(IMediaRouter2Manager manager) {
List<MediaRoute2Info> routes = new ArrayList<>();
- for (MediaRoute2ProviderInfo providerInfo : mProviderInfos) {
+ for (MediaRoute2ProviderInfo providerInfo : mLastProviderInfos) {
routes.addAll(providerInfo.getRoutes());
}
if (routes.size() == 0) {
@@ -1081,5 +1330,21 @@ class MediaRouter2ServiceImpl {
}
return null;
}
+
+ final class SessionCreationRequest {
+ public final Client2Record mClientRecord;
+ public final MediaRoute2Info mRoute;
+ public final String mControlCategory;
+ public final long mRequestId;
+
+ SessionCreationRequest(@NonNull Client2Record clientRecord,
+ @NonNull MediaRoute2Info route,
+ @NonNull String controlCategory, long requestId) {
+ mClientRecord = clientRecord;
+ mRoute = route;
+ mControlCategory = controlCategory;
+ mRequestId = requestId;
+ }
+ }
}
}
diff --git a/services/core/java/com/android/server/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java
index 9c99e8f43639..3e2bf4e66aaa 100644
--- a/services/core/java/com/android/server/media/MediaRouterService.java
+++ b/services/core/java/com/android/server/media/MediaRouterService.java
@@ -39,6 +39,7 @@ import android.media.MediaRouter;
import android.media.MediaRouterClientState;
import android.media.RemoteDisplayState;
import android.media.RemoteDisplayState.RemoteDisplayInfo;
+import android.media.RouteSessionInfo;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
@@ -457,8 +458,28 @@ public final class MediaRouterService extends IMediaRouterService.Stub
// Binder call
@Override
- public void requestSelectRoute2(IMediaRouter2Client client, MediaRoute2Info route) {
- mService2.requestSelectRoute2(client, route);
+ public void requestCreateSession(IMediaRouter2Client client, MediaRoute2Info route,
+ String controlCategory, int requestId) {
+ mService2.requestCreateSession(client, route, controlCategory, requestId);
+ }
+
+ // Binder call
+ @Override
+ public void selectRoute(IMediaRouter2Client client, String sessionId, MediaRoute2Info route) {
+ mService2.selectRoute(client, sessionId, route);
+ }
+
+ // Binder call
+ @Override
+ public void deselectRoute(IMediaRouter2Client client, String sessionId, MediaRoute2Info route) {
+ mService2.deselectRoute(client, sessionId, route);
+ }
+
+ // Binder call
+ @Override
+ public void transferToRoute(IMediaRouter2Client client, String sessionId,
+ MediaRoute2Info route) {
+ mService2.transferToRoute(client, sessionId, route);
}
// Binder call
@@ -486,11 +507,10 @@ public final class MediaRouterService extends IMediaRouterService.Stub
// Binder call
@Override
- public void selectClientRoute2(IMediaRouter2Manager manager,
- String packageName, MediaRoute2Info route) {
- mService2.selectClientRoute2(manager, packageName, route);
+ public void requestCreateClientSession(IMediaRouter2Manager manager, String packageName,
+ MediaRoute2Info route, int requestId) {
+ mService2.requestCreateClientSession(manager, packageName, route, requestId);
}
-
// Binder call
@Override
public void setControlCategories(IMediaRouter2Client client, List<String> categories) {
@@ -523,6 +543,12 @@ public final class MediaRouterService extends IMediaRouterService.Stub
mService2.requestUpdateVolume2Manager(manager, route, delta);
}
+ // Binder call
+ @Override
+ public List<RouteSessionInfo> getActiveSessions(IMediaRouter2Manager manager) {
+ return mService2.getActiveSessions(manager);
+ }
+
void restoreBluetoothA2dp() {
try {
boolean a2dpOn;
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index 0aee8507d5af..aa24ed26023a 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -62,7 +62,7 @@ import java.util.List;
* This is the system implementation of a Session. Apps will interact with the
* MediaSession wrapper class instead.
*/
-public class MediaSessionRecord implements IBinder.DeathRecipient {
+public class MediaSessionRecord implements IBinder.DeathRecipient, AutoCloseable {
private static final String TAG = "MediaSessionRecord";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -125,7 +125,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
public MediaSessionRecord(int ownerPid, int ownerUid, int userId, String ownerPackageName,
ISessionCallback cb, String tag, Bundle sessionInfo,
- MediaSessionService service, Looper handlerLooper) {
+ MediaSessionService service, Looper handlerLooper) throws RemoteException {
mOwnerPid = ownerPid;
mOwnerUid = ownerUid;
mUserId = userId;
@@ -142,6 +142,9 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
mAudioManagerInternal = LocalServices.getService(AudioManagerInternal.class);
mAudioAttrs = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).build();
+
+ // May throw RemoteException if the session app is killed.
+ mSessionCb.mCb.asBinder().linkToDeath(this, 0);
}
/**
@@ -154,15 +157,6 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
}
/**
- * Get the controller binder for the {@link MediaController}.
- *
- * @return The controller binder apps talk to.
- */
- public ISessionController getControllerBinder() {
- return mController;
- }
-
- /**
* Get the session token for creating {@link MediaController}.
*
* @return The session token.
@@ -181,15 +175,6 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
}
/**
- * Get the tag for the session.
- *
- * @return The session's tag.
- */
- public String getTag() {
- return mTag;
- }
-
- /**
* Get the intent the app set for their media button receiver.
*
* @return The pending intent set by the app or null.
@@ -199,25 +184,6 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
}
/**
- * Get this session's flags.
- *
- * @return The flags for this session.
- */
- public long getFlags() {
- return mFlags;
- }
-
- /**
- * Check if this session has the specified flag.
- *
- * @param flag The flag to check.
- * @return True if this session has that flag set, false otherwise.
- */
- public boolean hasFlag(int flag) {
- return (mFlags & flag) != 0;
- }
-
- /**
* Get the UID this session was created for.
*
* @return The UID for this session.
@@ -265,10 +231,9 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
* @param useSuggested True to use adjustSuggestedStreamVolume instead of
*/
public void adjustVolume(String packageName, String opPackageName, int pid, int uid,
- ISessionControllerCallback caller, boolean asSystemService, int direction, int flags,
- boolean useSuggested) {
+ boolean asSystemService, int direction, int flags, boolean useSuggested) {
int previousFlagPlaySound = flags & AudioManager.FLAG_PLAY_SOUND;
- if (isPlaybackActive() || hasFlag(MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY)) {
+ if (checkPlaybackActiveState(true) || isSystemPriority()) {
flags &= ~AudioManager.FLAG_PLAY_SOUND;
}
if (mVolumeType == PlaybackInfo.PLAYBACK_TYPE_LOCAL) {
@@ -291,7 +256,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
Log.w(TAG, "adjusting volume, pkg=" + packageName + ", asSystemService="
+ asSystemService + ", dir=" + direction);
}
- mSessionCb.adjustVolume(packageName, pid, uid, caller, asSystemService, direction);
+ mSessionCb.adjustVolume(packageName, pid, uid, asSystemService, direction);
int volumeBefore = (mOptimisticVolume < 0 ? mCurrentVolume : mOptimisticVolume);
mOptimisticVolume = volumeBefore + direction;
@@ -310,8 +275,8 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
}
}
- private void setVolumeTo(String packageName, String opPackageName, int pid, int uid,
- ISessionControllerCallback caller, int value, int flags) {
+ private void setVolumeTo(String packageName, String opPackageName, int pid, int uid, int value,
+ int flags) {
if (mVolumeType == PlaybackInfo.PLAYBACK_TYPE_LOCAL) {
int stream = AudioAttributes.toLegacyStreamType(mAudioAttrs);
final int volumeValue = value;
@@ -333,7 +298,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
return;
}
value = Math.max(0, Math.min(value, mMaxVolume));
- mSessionCb.setVolumeTo(packageName, pid, uid, caller, value);
+ mSessionCb.setVolumeTo(packageName, pid, uid, value);
int volumeBefore = (mOptimisticVolume < 0 ? mCurrentVolume : mOptimisticVolume);
mOptimisticVolume = Math.max(0, Math.min(value, mMaxVolume));
@@ -361,84 +326,27 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
}
/**
- * Get the playback state.
- *
- * @return The current playback state.
- */
- public PlaybackState getPlaybackState() {
- return mPlaybackState;
- }
-
- /**
- * Check if the session is currently performing playback.
- *
- * @return True if the session is performing playback, false otherwise.
- */
- public boolean isPlaybackActive() {
- int state = mPlaybackState == null ? PlaybackState.STATE_NONE : mPlaybackState.getState();
- return MediaSession.isActiveState(state);
- }
-
- /**
- * Get the type of playback, either local or remote.
- *
- * @return The current type of playback.
- */
- public int getPlaybackType() {
- return mVolumeType;
- }
-
- /**
- * Get the local audio stream being used. Only valid if playback type is
- * local.
+ * Check if the session's playback active state matches with the expectation. This always return
+ * {@code false} if the playback state is {@code null}, where we cannot know the actual playback
+ * state associated with the session.
*
- * @return The audio stream the session is using.
+ * @param expected True if playback is expected to be active. false otherwise.
+ * @return True if the session's playback matches with the expectation. false otherwise.
*/
- public AudioAttributes getAudioAttributes() {
- return mAudioAttrs;
- }
-
- /**
- * Get the type of volume control. Only valid if playback type is remote.
- *
- * @return The volume control type being used.
- */
- public int getVolumeControl() {
- return mVolumeControlType;
- }
-
- /**
- * Get the max volume that can be set. Only valid if playback type is
- * remote.
- *
- * @return The max volume that can be set.
- */
- public int getMaxVolume() {
- return mMaxVolume;
- }
-
- /**
- * Get the current volume for this session. Only valid if playback type is
- * remote.
- *
- * @return The current volume of the remote playback.
- */
- public int getCurrentVolume() {
- return mCurrentVolume;
+ public boolean checkPlaybackActiveState(boolean expected) {
+ if (mPlaybackState == null) {
+ return false;
+ }
+ return MediaSession.isActiveState(mPlaybackState.getState()) == expected;
}
/**
- * Get the volume we'd like it to be set to. This is only valid for a short
- * while after a call to adjust or set volume.
+ * Get whether the playback is local.
*
- * @return The current optimistic volume or -1.
+ * @return {@code true} if the playback is local.
*/
- public int getOptimisticVolume() {
- return mOptimisticVolume;
- }
-
- public boolean isTransportControlEnabled() {
- return hasFlag(MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS);
+ public boolean isPlaybackLocal() {
+ return mVolumeType == PlaybackInfo.PLAYBACK_TYPE_LOCAL;
}
@Override
@@ -450,21 +358,19 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
* Finish cleaning up this session, including disconnecting if connected and
* removing the death observer from the callback binder.
*/
- public void onDestroy() {
+ @Override
+ public void close() {
synchronized (mLock) {
if (mDestroyed) {
return;
}
+ mSessionCb.mCb.asBinder().unlinkToDeath(this, 0);
mDestroyed = true;
mPlaybackState = null;
mHandler.post(MessageHandler.MSG_DESTROYED);
}
}
- public ISessionCallback getCallback() {
- return mSessionCb.mCb;
- }
-
/**
* Sends media button.
*
@@ -1009,14 +915,13 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
}
public boolean sendMediaButton(String packageName, int pid, int uid,
- ISessionControllerCallback caller, boolean asSystemService,
- KeyEvent keyEvent) {
+ boolean asSystemService, KeyEvent keyEvent) {
try {
if (asSystemService) {
mCb.onMediaButton(mContext.getPackageName(), Process.myPid(),
Process.SYSTEM_UID, createMediaButtonIntent(keyEvent), 0, null);
} else {
- mCb.onMediaButtonFromController(packageName, pid, uid, caller,
+ mCb.onMediaButtonFromController(packageName, pid, uid,
createMediaButtonIntent(keyEvent));
}
return true;
@@ -1026,201 +931,189 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
return false;
}
- public void sendCommand(String packageName, int pid, int uid,
- ISessionControllerCallback caller, String command, Bundle args, ResultReceiver cb) {
+ public void sendCommand(String packageName, int pid, int uid, String command, Bundle args,
+ ResultReceiver cb) {
try {
- mCb.onCommand(packageName, pid, uid, caller, command, args, cb);
+ mCb.onCommand(packageName, pid, uid, command, args, cb);
} catch (RemoteException e) {
Slog.e(TAG, "Remote failure in sendCommand.", e);
}
}
- public void sendCustomAction(String packageName, int pid, int uid,
- ISessionControllerCallback caller, String action,
+ public void sendCustomAction(String packageName, int pid, int uid, String action,
Bundle args) {
try {
- mCb.onCustomAction(packageName, pid, uid, caller, action, args);
+ mCb.onCustomAction(packageName, pid, uid, action, args);
} catch (RemoteException e) {
Slog.e(TAG, "Remote failure in sendCustomAction.", e);
}
}
- public void prepare(String packageName, int pid, int uid,
- ISessionControllerCallback caller) {
+ public void prepare(String packageName, int pid, int uid) {
try {
- mCb.onPrepare(packageName, pid, uid, caller);
+ mCb.onPrepare(packageName, pid, uid);
} catch (RemoteException e) {
Slog.e(TAG, "Remote failure in prepare.", e);
}
}
- public void prepareFromMediaId(String packageName, int pid, int uid,
- ISessionControllerCallback caller, String mediaId, Bundle extras) {
+ public void prepareFromMediaId(String packageName, int pid, int uid, String mediaId,
+ Bundle extras) {
try {
- mCb.onPrepareFromMediaId(packageName, pid, uid, caller, mediaId, extras);
+ mCb.onPrepareFromMediaId(packageName, pid, uid, mediaId, extras);
} catch (RemoteException e) {
Slog.e(TAG, "Remote failure in prepareFromMediaId.", e);
}
}
- public void prepareFromSearch(String packageName, int pid, int uid,
- ISessionControllerCallback caller, String query, Bundle extras) {
+ public void prepareFromSearch(String packageName, int pid, int uid, String query,
+ Bundle extras) {
try {
- mCb.onPrepareFromSearch(packageName, pid, uid, caller, query, extras);
+ mCb.onPrepareFromSearch(packageName, pid, uid, query, extras);
} catch (RemoteException e) {
Slog.e(TAG, "Remote failure in prepareFromSearch.", e);
}
}
- public void prepareFromUri(String packageName, int pid, int uid,
- ISessionControllerCallback caller, Uri uri, Bundle extras) {
+ public void prepareFromUri(String packageName, int pid, int uid, Uri uri, Bundle extras) {
try {
- mCb.onPrepareFromUri(packageName, pid, uid, caller, uri, extras);
+ mCb.onPrepareFromUri(packageName, pid, uid, uri, extras);
} catch (RemoteException e) {
Slog.e(TAG, "Remote failure in prepareFromUri.", e);
}
}
- public void play(String packageName, int pid, int uid, ISessionControllerCallback caller) {
+ public void play(String packageName, int pid, int uid) {
try {
- mCb.onPlay(packageName, pid, uid, caller);
+ mCb.onPlay(packageName, pid, uid);
} catch (RemoteException e) {
Slog.e(TAG, "Remote failure in play.", e);
}
}
- public void playFromMediaId(String packageName, int pid, int uid,
- ISessionControllerCallback caller, String mediaId, Bundle extras) {
+ public void playFromMediaId(String packageName, int pid, int uid, String mediaId,
+ Bundle extras) {
try {
- mCb.onPlayFromMediaId(packageName, pid, uid, caller, mediaId, extras);
+ mCb.onPlayFromMediaId(packageName, pid, uid, mediaId, extras);
} catch (RemoteException e) {
Slog.e(TAG, "Remote failure in playFromMediaId.", e);
}
}
- public void playFromSearch(String packageName, int pid, int uid,
- ISessionControllerCallback caller, String query, Bundle extras) {
+ public void playFromSearch(String packageName, int pid, int uid, String query,
+ Bundle extras) {
try {
- mCb.onPlayFromSearch(packageName, pid, uid, caller, query, extras);
+ mCb.onPlayFromSearch(packageName, pid, uid, query, extras);
} catch (RemoteException e) {
Slog.e(TAG, "Remote failure in playFromSearch.", e);
}
}
- public void playFromUri(String packageName, int pid, int uid,
- ISessionControllerCallback caller, Uri uri, Bundle extras) {
+ public void playFromUri(String packageName, int pid, int uid, Uri uri, Bundle extras) {
try {
- mCb.onPlayFromUri(packageName, pid, uid, caller, uri, extras);
+ mCb.onPlayFromUri(packageName, pid, uid, uri, extras);
} catch (RemoteException e) {
Slog.e(TAG, "Remote failure in playFromUri.", e);
}
}
- public void skipToTrack(String packageName, int pid, int uid,
- ISessionControllerCallback caller, long id) {
+ public void skipToTrack(String packageName, int pid, int uid, long id) {
try {
- mCb.onSkipToTrack(packageName, pid, uid, caller, id);
+ mCb.onSkipToTrack(packageName, pid, uid, id);
} catch (RemoteException e) {
Slog.e(TAG, "Remote failure in skipToTrack", e);
}
}
- public void pause(String packageName, int pid, int uid, ISessionControllerCallback caller) {
+ public void pause(String packageName, int pid, int uid) {
try {
- mCb.onPause(packageName, pid, uid, caller);
+ mCb.onPause(packageName, pid, uid);
} catch (RemoteException e) {
Slog.e(TAG, "Remote failure in pause.", e);
}
}
- public void stop(String packageName, int pid, int uid, ISessionControllerCallback caller) {
+ public void stop(String packageName, int pid, int uid) {
try {
- mCb.onStop(packageName, pid, uid, caller);
+ mCb.onStop(packageName, pid, uid);
} catch (RemoteException e) {
Slog.e(TAG, "Remote failure in stop.", e);
}
}
- public void next(String packageName, int pid, int uid, ISessionControllerCallback caller) {
+ public void next(String packageName, int pid, int uid) {
try {
- mCb.onNext(packageName, pid, uid, caller);
+ mCb.onNext(packageName, pid, uid);
} catch (RemoteException e) {
Slog.e(TAG, "Remote failure in next.", e);
}
}
- public void previous(String packageName, int pid, int uid,
- ISessionControllerCallback caller) {
+ public void previous(String packageName, int pid, int uid) {
try {
- mCb.onPrevious(packageName, pid, uid, caller);
+ mCb.onPrevious(packageName, pid, uid);
} catch (RemoteException e) {
Slog.e(TAG, "Remote failure in previous.", e);
}
}
- public void fastForward(String packageName, int pid, int uid,
- ISessionControllerCallback caller) {
+ public void fastForward(String packageName, int pid, int uid) {
try {
- mCb.onFastForward(packageName, pid, uid, caller);
+ mCb.onFastForward(packageName, pid, uid);
} catch (RemoteException e) {
Slog.e(TAG, "Remote failure in fastForward.", e);
}
}
- public void rewind(String packageName, int pid, int uid,
- ISessionControllerCallback caller) {
+ public void rewind(String packageName, int pid, int uid) {
try {
- mCb.onRewind(packageName, pid, uid, caller);
+ mCb.onRewind(packageName, pid, uid);
} catch (RemoteException e) {
Slog.e(TAG, "Remote failure in rewind.", e);
}
}
- public void seekTo(String packageName, int pid, int uid, ISessionControllerCallback caller,
- long pos) {
+ public void seekTo(String packageName, int pid, int uid, long pos) {
try {
- mCb.onSeekTo(packageName, pid, uid, caller, pos);
+ mCb.onSeekTo(packageName, pid, uid, pos);
} catch (RemoteException e) {
Slog.e(TAG, "Remote failure in seekTo.", e);
}
}
- public void rate(String packageName, int pid, int uid, ISessionControllerCallback caller,
- Rating rating) {
+ public void rate(String packageName, int pid, int uid, Rating rating) {
try {
- mCb.onRate(packageName, pid, uid, caller, rating);
+ mCb.onRate(packageName, pid, uid, rating);
} catch (RemoteException e) {
Slog.e(TAG, "Remote failure in rate.", e);
}
}
- public void setPlaybackSpeed(String packageName, int pid, int uid,
- ISessionControllerCallback caller, float speed) {
+ public void setPlaybackSpeed(String packageName, int pid, int uid, float speed) {
try {
- mCb.onSetPlaybackSpeed(packageName, pid, uid, caller, speed);
+ mCb.onSetPlaybackSpeed(packageName, pid, uid, speed);
} catch (RemoteException e) {
Slog.e(TAG, "Remote failure in setPlaybackSpeed.", e);
}
}
- public void adjustVolume(String packageName, int pid, int uid,
- ISessionControllerCallback caller, boolean asSystemService, int direction) {
+ public void adjustVolume(String packageName, int pid, int uid, boolean asSystemService,
+ int direction) {
try {
if (asSystemService) {
mCb.onAdjustVolume(mContext.getPackageName(), Process.myPid(),
- Process.SYSTEM_UID, null, direction);
+ Process.SYSTEM_UID, direction);
} else {
- mCb.onAdjustVolume(packageName, pid, uid, caller, direction);
+ mCb.onAdjustVolume(packageName, pid, uid, direction);
}
} catch (RemoteException e) {
Slog.e(TAG, "Remote failure in adjustVolume.", e);
}
}
- public void setVolumeTo(String packageName, int pid, int uid,
- ISessionControllerCallback caller, int value) {
+ public void setVolumeTo(String packageName, int pid, int uid, int value) {
try {
- mCb.onSetVolumeTo(packageName, pid, uid, caller, value);
+ mCb.onSetVolumeTo(packageName, pid, uid, value);
} catch (RemoteException e) {
Slog.e(TAG, "Remote failure in setVolumeTo.", e);
}
@@ -1235,17 +1128,16 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
class ControllerStub extends ISessionController.Stub {
@Override
- public void sendCommand(String packageName, ISessionControllerCallback caller,
- String command, Bundle args, ResultReceiver cb) {
+ public void sendCommand(String packageName, String command, Bundle args,
+ ResultReceiver cb) {
mSessionCb.sendCommand(packageName, Binder.getCallingPid(), Binder.getCallingUid(),
- caller, command, args, cb);
+ command, args, cb);
}
@Override
- public boolean sendMediaButton(String packageName, ISessionControllerCallback cb,
- KeyEvent keyEvent) {
+ public boolean sendMediaButton(String packageName, KeyEvent keyEvent) {
return mSessionCb.sendMediaButton(packageName, Binder.getCallingPid(),
- Binder.getCallingUid(), cb, false, keyEvent);
+ Binder.getCallingUid(), false, keyEvent);
}
@Override
@@ -1316,13 +1208,13 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
}
@Override
- public void adjustVolume(String packageName, String opPackageName,
- ISessionControllerCallback caller, int direction, int flags) {
+ public void adjustVolume(String packageName, String opPackageName, int direction,
+ int flags) {
int pid = Binder.getCallingPid();
int uid = Binder.getCallingUid();
final long token = Binder.clearCallingIdentity();
try {
- MediaSessionRecord.this.adjustVolume(packageName, opPackageName, pid, uid, caller,
+ MediaSessionRecord.this.adjustVolume(packageName, opPackageName, pid, uid,
false, direction, flags, false /* useSuggested */);
} finally {
Binder.restoreCallingIdentity(token);
@@ -1330,134 +1222,120 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
}
@Override
- public void setVolumeTo(String packageName, String opPackageName,
- ISessionControllerCallback caller, int value, int flags) {
+ public void setVolumeTo(String packageName, String opPackageName, int value, int flags) {
int pid = Binder.getCallingPid();
int uid = Binder.getCallingUid();
final long token = Binder.clearCallingIdentity();
try {
- MediaSessionRecord.this.setVolumeTo(packageName, opPackageName, pid, uid, caller,
- value, flags);
+ MediaSessionRecord.this.setVolumeTo(packageName, opPackageName, pid, uid, value,
+ flags);
} finally {
Binder.restoreCallingIdentity(token);
}
}
@Override
- public void prepare(String packageName, ISessionControllerCallback caller) {
- mSessionCb.prepare(packageName, Binder.getCallingPid(), Binder.getCallingUid(), caller);
+ public void prepare(String packageName) {
+ mSessionCb.prepare(packageName, Binder.getCallingPid(), Binder.getCallingUid());
}
@Override
- public void prepareFromMediaId(String packageName, ISessionControllerCallback caller,
- String mediaId, Bundle extras) {
+ public void prepareFromMediaId(String packageName, String mediaId, Bundle extras) {
mSessionCb.prepareFromMediaId(packageName, Binder.getCallingPid(),
- Binder.getCallingUid(), caller, mediaId, extras);
+ Binder.getCallingUid(), mediaId, extras);
}
@Override
- public void prepareFromSearch(String packageName, ISessionControllerCallback caller,
- String query, Bundle extras) {
+ public void prepareFromSearch(String packageName, String query, Bundle extras) {
mSessionCb.prepareFromSearch(packageName, Binder.getCallingPid(),
- Binder.getCallingUid(), caller, query, extras);
+ Binder.getCallingUid(), query, extras);
}
@Override
- public void prepareFromUri(String packageName, ISessionControllerCallback caller,
- Uri uri, Bundle extras) {
+ public void prepareFromUri(String packageName, Uri uri, Bundle extras) {
mSessionCb.prepareFromUri(packageName, Binder.getCallingPid(), Binder.getCallingUid(),
- caller, uri, extras);
+ uri, extras);
}
@Override
- public void play(String packageName, ISessionControllerCallback caller) {
- mSessionCb.play(packageName, Binder.getCallingPid(), Binder.getCallingUid(), caller);
+ public void play(String packageName) {
+ mSessionCb.play(packageName, Binder.getCallingPid(), Binder.getCallingUid());
}
@Override
- public void playFromMediaId(String packageName, ISessionControllerCallback caller,
- String mediaId, Bundle extras) {
+ public void playFromMediaId(String packageName, String mediaId, Bundle extras) {
mSessionCb.playFromMediaId(packageName, Binder.getCallingPid(), Binder.getCallingUid(),
- caller, mediaId, extras);
+ mediaId, extras);
}
@Override
- public void playFromSearch(String packageName, ISessionControllerCallback caller,
- String query, Bundle extras) {
+ public void playFromSearch(String packageName, String query, Bundle extras) {
mSessionCb.playFromSearch(packageName, Binder.getCallingPid(), Binder.getCallingUid(),
- caller, query, extras);
+ query, extras);
}
@Override
- public void playFromUri(String packageName, ISessionControllerCallback caller,
- Uri uri, Bundle extras) {
+ public void playFromUri(String packageName, Uri uri, Bundle extras) {
mSessionCb.playFromUri(packageName, Binder.getCallingPid(), Binder.getCallingUid(),
- caller, uri, extras);
+ uri, extras);
}
@Override
- public void skipToQueueItem(String packageName, ISessionControllerCallback caller,
- long id) {
- mSessionCb.skipToTrack(packageName, Binder.getCallingPid(), Binder.getCallingUid(),
- caller, id);
+ public void skipToQueueItem(String packageName, long id) {
+ mSessionCb.skipToTrack(packageName, Binder.getCallingPid(), Binder.getCallingUid(), id);
}
@Override
- public void pause(String packageName, ISessionControllerCallback caller) {
- mSessionCb.pause(packageName, Binder.getCallingPid(), Binder.getCallingUid(), caller);
+ public void pause(String packageName) {
+ mSessionCb.pause(packageName, Binder.getCallingPid(), Binder.getCallingUid());
}
@Override
- public void stop(String packageName, ISessionControllerCallback caller) {
- mSessionCb.stop(packageName, Binder.getCallingPid(), Binder.getCallingUid(), caller);
+ public void stop(String packageName) {
+ mSessionCb.stop(packageName, Binder.getCallingPid(), Binder.getCallingUid());
}
@Override
- public void next(String packageName, ISessionControllerCallback caller) {
- mSessionCb.next(packageName, Binder.getCallingPid(), Binder.getCallingUid(), caller);
+ public void next(String packageName) {
+ mSessionCb.next(packageName, Binder.getCallingPid(), Binder.getCallingUid());
}
@Override
- public void previous(String packageName, ISessionControllerCallback caller) {
- mSessionCb.previous(packageName, Binder.getCallingPid(), Binder.getCallingUid(),
- caller);
+ public void previous(String packageName) {
+ mSessionCb.previous(packageName, Binder.getCallingPid(), Binder.getCallingUid());
}
@Override
- public void fastForward(String packageName, ISessionControllerCallback caller) {
- mSessionCb.fastForward(packageName, Binder.getCallingPid(), Binder.getCallingUid(),
- caller);
+ public void fastForward(String packageName) {
+ mSessionCb.fastForward(packageName, Binder.getCallingPid(), Binder.getCallingUid());
}
@Override
- public void rewind(String packageName, ISessionControllerCallback caller) {
- mSessionCb.rewind(packageName, Binder.getCallingPid(), Binder.getCallingUid(), caller);
+ public void rewind(String packageName) {
+ mSessionCb.rewind(packageName, Binder.getCallingPid(), Binder.getCallingUid());
}
@Override
- public void seekTo(String packageName, ISessionControllerCallback caller, long pos) {
- mSessionCb.seekTo(packageName, Binder.getCallingPid(), Binder.getCallingUid(), caller,
- pos);
+ public void seekTo(String packageName, long pos) {
+ mSessionCb.seekTo(packageName, Binder.getCallingPid(), Binder.getCallingUid(), pos);
}
@Override
- public void rate(String packageName, ISessionControllerCallback caller, Rating rating) {
- mSessionCb.rate(packageName, Binder.getCallingPid(), Binder.getCallingUid(), caller,
- rating);
+ public void rate(String packageName, Rating rating) {
+ mSessionCb.rate(packageName, Binder.getCallingPid(), Binder.getCallingUid(), rating);
}
@Override
- public void setPlaybackSpeed(String packageName, ISessionControllerCallback caller,
+ public void setPlaybackSpeed(String packageName,
float speed) {
mSessionCb.setPlaybackSpeed(packageName, Binder.getCallingPid(), Binder.getCallingUid(),
- caller, speed);
+ speed);
}
@Override
- public void sendCustomAction(String packageName, ISessionControllerCallback caller,
- String action, Bundle args) {
+ public void sendCustomAction(String packageName, String action, Bundle args) {
mSessionCb.sendCustomAction(packageName, Binder.getCallingPid(), Binder.getCallingUid(),
- caller, action, args);
+ action, args);
}
@Override
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 069aeefd7a73..0f059dba5274 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -25,7 +25,6 @@ import android.app.KeyguardManager;
import android.app.PendingIntent;
import android.app.PendingIntent.CanceledException;
import android.content.ActivityNotFoundException;
-import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
@@ -134,9 +133,7 @@ public class MediaSessionService extends SystemService implements Monitor {
new ArrayList<>();
private KeyguardManager mKeyguardManager;
- private IAudioService mAudioService;
private AudioManagerInternal mAudioManagerInternal;
- private ActivityManager mActivityManager;
private ContentResolver mContentResolver;
private SettingsObserver mSettingsObserver;
private boolean mHasFeatureLeanback;
@@ -168,10 +165,7 @@ public class MediaSessionService extends SystemService implements Monitor {
publishBinderService(Context.MEDIA_SESSION_SERVICE, mSessionManagerImpl);
Watchdog.getInstance().addMonitor(this);
mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
- mAudioService = getAudioService();
mAudioManagerInternal = LocalServices.getService(AudioManagerInternal.class);
- mActivityManager =
- (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
mAudioPlayerStateMonitor = AudioPlayerStateMonitor.getInstance(mContext);
mAudioPlayerStateMonitor.registerListener(
(config, isRemoved) -> {
@@ -211,7 +205,7 @@ public class MediaSessionService extends SystemService implements Monitor {
Log.w(TAG, "Unknown session updated. Ignoring.");
return;
}
- if ((record.getFlags() & MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY) != 0) {
+ if (record.isSystemPriority()) {
if (DEBUG_KEY_EVENT) {
Log.d(TAG, "Global priority session is updated, active=" + record.isActive());
}
@@ -466,12 +460,7 @@ public class MediaSessionService extends SystemService implements Monitor {
}
}
- try {
- session.getCallback().asBinder().unlinkToDeath(session, 0);
- } catch (Exception e) {
- // ignore exceptions while destroying a session.
- }
- session.onDestroy();
+ session.close();
mHandler.postSessionsChanged(session.getUserId());
}
@@ -576,10 +565,10 @@ public class MediaSessionService extends SystemService implements Monitor {
throw new RuntimeException("Session request from invalid user.");
}
- final MediaSessionRecord session = new MediaSessionRecord(callerPid, callerUid, userId,
- callerPackageName, cb, tag, sessionInfo, this, mHandler.getLooper());
+ final MediaSessionRecord session;
try {
- cb.asBinder().linkToDeath(session, 0);
+ session = new MediaSessionRecord(callerPid, callerUid, userId,
+ callerPackageName, cb, tag, sessionInfo, this, mHandler.getLooper());
} catch (RemoteException e) {
throw new RuntimeException("Media Session owner died prematurely.", e);
}
@@ -1842,7 +1831,7 @@ public class MediaSessionService extends SystemService implements Monitor {
break;
}
record.adjustVolume(packageName, opPackageName, pid, uid,
- null /* caller */, true /* asSystemService */, direction,
+ true /* asSystemService */, direction,
AudioManager.FLAG_SHOW_UI, false /* useSuggested */);
break;
}
@@ -1852,8 +1841,7 @@ public class MediaSessionService extends SystemService implements Monitor {
AudioManager.FLAG_PLAY_SOUND | AudioManager.FLAG_VIBRATE
| AudioManager.FLAG_FROM_KEY;
record.adjustVolume(packageName, opPackageName, pid, uid,
- null /* caller */, true /* asSystemService */, 0,
- flags, false /* useSuggested */);
+ true /* asSystemService */, 0, flags, false /* useSuggested */);
}
}
}
@@ -2087,7 +2075,7 @@ public class MediaSessionService extends SystemService implements Monitor {
+ flags + ", suggestedStream=" + suggestedStream
+ ", preferSuggestedStream=" + preferSuggestedStream);
}
- session.adjustVolume(packageName, opPackageName, pid, uid, null, asSystemService,
+ session.adjustVolume(packageName, opPackageName, pid, uid, asSystemService,
direction, flags, true);
}
}
@@ -2398,25 +2386,6 @@ public class MediaSessionService extends SystemService implements Monitor {
onReceiveResult(resultCode, null);
}
};
-
- BroadcastReceiver mKeyEventDone = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (intent == null) {
- return;
- }
- Bundle extras = intent.getExtras();
- if (extras == null) {
- return;
- }
- synchronized (mLock) {
- if (extras.containsKey(EXTRA_WAKELOCK_ACQUIRED)
- && mMediaEventWakeLock.isHeld()) {
- mMediaEventWakeLock.release();
- }
- }
- }
- };
}
final class MessageHandler extends Handler {
diff --git a/services/core/java/com/android/server/media/MediaSessionStack.java b/services/core/java/com/android/server/media/MediaSessionStack.java
index a5e7d8e18005..732563f6e05e 100644
--- a/services/core/java/com/android/server/media/MediaSessionStack.java
+++ b/services/core/java/com/android/server/media/MediaSessionStack.java
@@ -16,7 +16,6 @@
package com.android.server.media;
-import android.media.session.MediaController.PlaybackInfo;
import android.media.session.MediaSession;
import android.media.session.PlaybackState;
import android.os.Debug;
@@ -144,7 +143,7 @@ class MediaSessionStack {
*/
public MediaSessionRecord getMediaSessionRecord(MediaSession.Token sessionToken) {
for (MediaSessionRecord record : mSessions) {
- if (Objects.equals(record.getControllerBinder(), sessionToken.getBinder())) {
+ if (Objects.equals(record.getSessionToken(), sessionToken)) {
return record;
}
}
@@ -230,8 +229,8 @@ class MediaSessionStack {
MediaSessionRecord mediaButtonSession = null;
for (MediaSessionRecord session : mSessions) {
if (uid == session.getUid()) {
- if (session.getPlaybackState() != null && session.isPlaybackActive() ==
- mAudioPlayerStateMonitor.isPlaybackActive(session.getUid())) {
+ if (session.checkPlaybackActiveState(
+ mAudioPlayerStateMonitor.isPlaybackActive(session.getUid()))) {
// If there's a media session whose PlaybackState matches
// the audio playback state, return it immediately.
return session;
@@ -287,7 +286,7 @@ class MediaSessionStack {
int size = records.size();
for (int i = 0; i < size; i++) {
MediaSessionRecord record = records.get(i);
- if (record.isPlaybackActive()) {
+ if (record.checkPlaybackActiveState(true)) {
mCachedVolumeDefault = record;
return record;
}
@@ -301,7 +300,7 @@ class MediaSessionStack {
int size = records.size();
for (int i = 0; i < size; i++) {
MediaSessionRecord record = records.get(i);
- if (record.getPlaybackType() == PlaybackInfo.PLAYBACK_TYPE_REMOTE) {
+ if (!record.isPlaybackLocal()) {
return record;
}
}
@@ -359,7 +358,7 @@ class MediaSessionStack {
continue;
}
- if (session.isPlaybackActive()) {
+ if (session.checkPlaybackActiveState(true)) {
result.add(lastPlaybackActiveIndex++, session);
lastActiveIndex++;
} else {
diff --git a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
index 4f64177ad135..8fdfcbfb2ad9 100644
--- a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
+++ b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
@@ -35,6 +35,8 @@ import android.util.Log;
import com.android.internal.R;
+import java.util.Collections;
+
/**
* Provides routes for local playbacks such as phone speaker, wired headset, or Bluetooth speakers.
*/
@@ -88,21 +90,30 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
initializeRoutes();
}
- //TODO: implement method
@Override
- public void requestSelectRoute(@NonNull String packageName, @NonNull String routeId, int seq) {
- try {
- mAudioService.setBluetoothA2dpOn(
- !TextUtils.equals(routeId, mDefaultRoute.getId()));
- } catch (RemoteException ex) {
- Log.e(TAG, "Error changing Bluetooth A2DP route");
- }
+ public void requestCreateSession(String packageName, String routeId, String controlCategory,
+ long requestId) {
+ // Do nothing
+ }
+
+ @Override
+ public void releaseSession(int sessionId) {
+ // Do nothing
+ }
+
+ @Override
+ public void selectRoute(int sessionId, MediaRoute2Info route) {
+ //TODO: implement method
+ }
+
+ @Override
+ public void deselectRoute(int sessionId, MediaRoute2Info route) {
+ //TODO: implement method
}
- //TODO: implement method
@Override
- public void unselectRoute(@NonNull String packageName, @NonNull String routeId) {
- // does nothing..?
+ public void transferToRoute(int sessionId, MediaRoute2Info route) {
+ //TODO: implement method
}
//TODO: implement method
@@ -205,6 +216,6 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
builder.addRoute(mBluetoothA2dpRoute);
}
builder.addRoute(mDefaultRoute);
- setAndNotifyProviderInfo(builder.build());
+ setAndNotifyProviderState(builder.build(), Collections.emptyList());
}
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 82d74bc197b7..99562eb28886 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -223,6 +223,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.CollectionUtils;
import com.android.internal.util.ConcurrentUtils;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastXmlSerializer;
@@ -1032,6 +1033,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
// READ_NETWORK_USAGE_HISTORY permission above.
synchronized (mNetworkPoliciesSecondLock) {
+ updateNetworkRulesNL();
updateNetworkEnabledNL();
updateNotificationsNL();
}
@@ -1802,7 +1804,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
/**
* Examine all currently active subscriptions from
- * {@link SubscriptionManager#getActiveSubscriptionIdList()} and update
+ * {@link SubscriptionManager#getActiveSubscriptionInfoList()} and update
* internal data structures.
* <p>
* Callers <em>must not</em> hold any locks when this method called.
@@ -1813,21 +1815,22 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
final SubscriptionManager sm = mContext.getSystemService(SubscriptionManager.class);
+ final List<SubscriptionInfo> subList = CollectionUtils.emptyIfNull(
+ sm.getActiveSubscriptionInfoList());
- final int[] subIds = ArrayUtils.defeatNullable(sm.getActiveSubscriptionIdList());
final List<String[]> mergedSubscriberIdsList = new ArrayList();
-
- final SparseArray<String> subIdToSubscriberId = new SparseArray<>(subIds.length);
- for (int subId : subIds) {
- final String subscriberId = tm.getSubscriberId(subId);
+ final SparseArray<String> subIdToSubscriberId = new SparseArray<>(subList.size());
+ for (SubscriptionInfo sub : subList) {
+ final TelephonyManager tmSub = tm.createForSubscriptionId(sub.getSubscriptionId());
+ final String subscriberId = tmSub.getSubscriberId();
if (!TextUtils.isEmpty(subscriberId)) {
- subIdToSubscriberId.put(subId, subscriberId);
+ subIdToSubscriberId.put(tmSub.getSubscriptionId(), subscriberId);
} else {
- Slog.wtf(TAG, "Missing subscriberId for subId " + subId);
+ Slog.wtf(TAG, "Missing subscriberId for subId " + tmSub.getSubscriptionId());
}
- String[] mergedSubscriberId = ArrayUtils.defeatNullable(
- tm.createForSubscriptionId(subId).getMergedSubscriberIdsFromGroup());
+ final String[] mergedSubscriberId = ArrayUtils.defeatNullable(
+ tmSub.getMergedImsisFromGroup());
mergedSubscriberIdsList.add(mergedSubscriberId);
}
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 673e8302a426..0288f0c5e3cf 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -873,6 +873,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
+ mPersistThreshold);
}
+ final long oldGlobalAlertBytes = mGlobalAlertBytes;
+
// update and persist if beyond new thresholds
final long currentTime = mClock.millis();
synchronized (mStatsLock) {
@@ -886,8 +888,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
mUidTagRecorder.maybePersistLocked(currentTime);
}
- // re-arm global alert
- registerGlobalAlert();
+ if (oldGlobalAlertBytes != mGlobalAlertBytes) {
+ registerGlobalAlert();
+ }
}
@Override
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 12afef2cf950..f42f4f7c5c61 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2261,8 +2261,8 @@ public class NotificationManagerService extends SystemService {
private void createNotificationChannelGroup(String pkg, int uid, NotificationChannelGroup group,
boolean fromApp, boolean fromListener) {
- Preconditions.checkNotNull(group);
- Preconditions.checkNotNull(pkg);
+ Objects.requireNonNull(group);
+ Objects.requireNonNull(pkg);
final NotificationChannelGroup preUpdate =
mPreferencesHelper.getNotificationChannelGroup(group.getId(), pkg, uid);
@@ -3005,7 +3005,7 @@ public class NotificationManagerService extends SystemService {
boolean needsPolicyFileChange = false;
for (int i = 0; i < channelsSize; i++) {
final NotificationChannel channel = channels.get(i);
- Preconditions.checkNotNull(channel, "channel in list is null");
+ Objects.requireNonNull(channel, "channel in list is null");
needsPolicyFileChange = mPreferencesHelper.createNotificationChannel(pkg, uid,
channel, true /* fromTargetApp */,
mConditionProviders.isPackageOrComponentAllowed(
@@ -3126,7 +3126,7 @@ public class NotificationManagerService extends SystemService {
public void updateNotificationChannelForPackage(String pkg, int uid,
NotificationChannel channel) {
enforceSystemOrSystemUI("Caller not system or systemui");
- Preconditions.checkNotNull(channel);
+ Objects.requireNonNull(channel);
updateNotificationChannelInt(pkg, uid, channel, false);
}
@@ -3877,21 +3877,21 @@ public class NotificationManagerService extends SystemService {
@Override
public AutomaticZenRule getAutomaticZenRule(String id) throws RemoteException {
- Preconditions.checkNotNull(id, "Id is null");
+ Objects.requireNonNull(id, "Id is null");
enforcePolicyAccess(Binder.getCallingUid(), "getAutomaticZenRule");
return mZenModeHelper.getAutomaticZenRule(id);
}
@Override
public String addAutomaticZenRule(AutomaticZenRule automaticZenRule) {
- Preconditions.checkNotNull(automaticZenRule, "automaticZenRule is null");
- Preconditions.checkNotNull(automaticZenRule.getName(), "Name is null");
+ Objects.requireNonNull(automaticZenRule, "automaticZenRule is null");
+ Objects.requireNonNull(automaticZenRule.getName(), "Name is null");
if (automaticZenRule.getOwner() == null
&& automaticZenRule.getConfigurationActivity() == null) {
throw new NullPointerException(
"Rule must have a conditionproviderservice and/or configuration activity");
}
- Preconditions.checkNotNull(automaticZenRule.getConditionId(), "ConditionId is null");
+ Objects.requireNonNull(automaticZenRule.getConditionId(), "ConditionId is null");
if (automaticZenRule.getZenPolicy() != null
&& automaticZenRule.getInterruptionFilter() != INTERRUPTION_FILTER_PRIORITY) {
throw new IllegalArgumentException("ZenPolicy is only applicable to "
@@ -3906,14 +3906,14 @@ public class NotificationManagerService extends SystemService {
@Override
public boolean updateAutomaticZenRule(String id, AutomaticZenRule automaticZenRule)
throws RemoteException {
- Preconditions.checkNotNull(automaticZenRule, "automaticZenRule is null");
- Preconditions.checkNotNull(automaticZenRule.getName(), "Name is null");
+ Objects.requireNonNull(automaticZenRule, "automaticZenRule is null");
+ Objects.requireNonNull(automaticZenRule.getName(), "Name is null");
if (automaticZenRule.getOwner() == null
&& automaticZenRule.getConfigurationActivity() == null) {
throw new NullPointerException(
"Rule must have a conditionproviderservice and/or configuration activity");
}
- Preconditions.checkNotNull(automaticZenRule.getConditionId(), "ConditionId is null");
+ Objects.requireNonNull(automaticZenRule.getConditionId(), "ConditionId is null");
enforcePolicyAccess(Binder.getCallingUid(), "updateAutomaticZenRule");
return mZenModeHelper.updateAutomaticZenRule(id, automaticZenRule,
@@ -3922,7 +3922,7 @@ public class NotificationManagerService extends SystemService {
@Override
public boolean removeAutomaticZenRule(String id) throws RemoteException {
- Preconditions.checkNotNull(id, "Id is null");
+ Objects.requireNonNull(id, "Id is null");
// Verify that they can modify zen rules.
enforcePolicyAccess(Binder.getCallingUid(), "removeAutomaticZenRule");
@@ -3931,7 +3931,7 @@ public class NotificationManagerService extends SystemService {
@Override
public boolean removeAutomaticZenRules(String packageName) throws RemoteException {
- Preconditions.checkNotNull(packageName, "Package name is null");
+ Objects.requireNonNull(packageName, "Package name is null");
enforceSystemOrSystemUI("removeAutomaticZenRules");
return mZenModeHelper.removeAutomaticZenRules(packageName, "removeAutomaticZenRules");
@@ -3939,7 +3939,7 @@ public class NotificationManagerService extends SystemService {
@Override
public int getRuleInstanceCount(ComponentName owner) throws RemoteException {
- Preconditions.checkNotNull(owner, "Owner is null");
+ Objects.requireNonNull(owner, "Owner is null");
enforceSystemOrSystemUI("getRuleInstanceCount");
return mZenModeHelper.getCurrentInstanceCount(owner);
@@ -3947,8 +3947,8 @@ public class NotificationManagerService extends SystemService {
@Override
public void setAutomaticZenRuleState(String id, Condition condition) {
- Preconditions.checkNotNull(id, "id is null");
- Preconditions.checkNotNull(condition, "Condition is null");
+ Objects.requireNonNull(id, "id is null");
+ Objects.requireNonNull(condition, "Condition is null");
enforcePolicyAccess(Binder.getCallingUid(), "setAutomaticZenRuleState");
@@ -4292,7 +4292,7 @@ public class NotificationManagerService extends SystemService {
@Override
public boolean isNotificationListenerAccessGranted(ComponentName listener) {
- Preconditions.checkNotNull(listener);
+ Objects.requireNonNull(listener);
checkCallerIsSystemOrSameApp(listener.getPackageName());
return mListeners.isPackageOrComponentAllowed(listener.flattenToString(),
getCallingUserHandle().getIdentifier());
@@ -4301,7 +4301,7 @@ public class NotificationManagerService extends SystemService {
@Override
public boolean isNotificationListenerAccessGrantedForUser(ComponentName listener,
int userId) {
- Preconditions.checkNotNull(listener);
+ Objects.requireNonNull(listener);
checkCallerIsSystem();
return mListeners.isPackageOrComponentAllowed(listener.flattenToString(),
userId);
@@ -4309,7 +4309,7 @@ public class NotificationManagerService extends SystemService {
@Override
public boolean isNotificationAssistantAccessGranted(ComponentName assistant) {
- Preconditions.checkNotNull(assistant);
+ Objects.requireNonNull(assistant);
checkCallerIsSystemOrSameApp(assistant.getPackageName());
return mAssistants.isPackageOrComponentAllowed(assistant.flattenToString(),
getCallingUserHandle().getIdentifier());
@@ -4332,7 +4332,7 @@ public class NotificationManagerService extends SystemService {
@Override
public void setNotificationListenerAccessGrantedForUser(ComponentName listener, int userId,
boolean granted) {
- Preconditions.checkNotNull(listener);
+ Objects.requireNonNull(listener);
checkCallerIsSystemOrShell();
final long identity = Binder.clearCallingIdentity();
try {
@@ -4450,7 +4450,7 @@ public class NotificationManagerService extends SystemService {
public void updateNotificationChannelGroupFromPrivilegedListener(
INotificationListener token, String pkg, UserHandle user,
NotificationChannelGroup group) throws RemoteException {
- Preconditions.checkNotNull(user);
+ Objects.requireNonNull(user);
verifyPrivilegedListener(token, user, false);
createNotificationChannelGroup(
pkg, getUidForPackageAndUser(pkg, user), group, false, true);
@@ -4460,9 +4460,9 @@ public class NotificationManagerService extends SystemService {
@Override
public void updateNotificationChannelFromPrivilegedListener(INotificationListener token,
String pkg, UserHandle user, NotificationChannel channel) throws RemoteException {
- Preconditions.checkNotNull(channel);
- Preconditions.checkNotNull(pkg);
- Preconditions.checkNotNull(user);
+ Objects.requireNonNull(channel);
+ Objects.requireNonNull(pkg);
+ Objects.requireNonNull(user);
verifyPrivilegedListener(token, user, false);
updateNotificationChannelInt(pkg, getUidForPackageAndUser(pkg, user), channel, true);
@@ -4471,8 +4471,8 @@ public class NotificationManagerService extends SystemService {
@Override
public ParceledListSlice<NotificationChannel> getNotificationChannelsFromPrivilegedListener(
INotificationListener token, String pkg, UserHandle user) throws RemoteException {
- Preconditions.checkNotNull(pkg);
- Preconditions.checkNotNull(user);
+ Objects.requireNonNull(pkg);
+ Objects.requireNonNull(user);
verifyPrivilegedListener(token, user, true);
return mPreferencesHelper.getNotificationChannels(pkg, getUidForPackageAndUser(pkg, user),
@@ -4483,8 +4483,8 @@ public class NotificationManagerService extends SystemService {
public ParceledListSlice<NotificationChannelGroup>
getNotificationChannelGroupsFromPrivilegedListener(
INotificationListener token, String pkg, UserHandle user) throws RemoteException {
- Preconditions.checkNotNull(pkg);
- Preconditions.checkNotNull(user);
+ Objects.requireNonNull(pkg);
+ Objects.requireNonNull(user);
verifyPrivilegedListener(token, user, true);
List<NotificationChannelGroup> groups = new ArrayList<>();
@@ -4520,7 +4520,7 @@ public class NotificationManagerService extends SystemService {
@Override
public boolean isPackagePaused(String pkg) {
- Preconditions.checkNotNull(pkg);
+ Objects.requireNonNull(pkg);
checkCallerIsSameApp(pkg);
return isPackagePausedOrSuspended(pkg, Binder.getCallingUid());
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index b1ffa8c7160b..cdb0a17ada0a 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -621,10 +621,10 @@ public class PreferencesHelper implements RankingConfig {
@Override
public void createNotificationChannelGroup(String pkg, int uid, NotificationChannelGroup group,
boolean fromTargetApp) {
- Preconditions.checkNotNull(pkg);
- Preconditions.checkNotNull(group);
- Preconditions.checkNotNull(group.getId());
- Preconditions.checkNotNull(!TextUtils.isEmpty(group.getName()));
+ Objects.requireNonNull(pkg);
+ Objects.requireNonNull(group);
+ Objects.requireNonNull(group.getId());
+ Objects.requireNonNull(!TextUtils.isEmpty(group.getName()));
synchronized (mPackagePreferences) {
PackagePreferences r = getOrCreatePackagePreferencesLocked(pkg, uid);
if (r == null) {
@@ -658,9 +658,9 @@ public class PreferencesHelper implements RankingConfig {
@Override
public boolean createNotificationChannel(String pkg, int uid, NotificationChannel channel,
boolean fromTargetApp, boolean hasDndAccess) {
- Preconditions.checkNotNull(pkg);
- Preconditions.checkNotNull(channel);
- Preconditions.checkNotNull(channel.getId());
+ Objects.requireNonNull(pkg);
+ Objects.requireNonNull(channel);
+ Objects.requireNonNull(channel.getId());
Preconditions.checkArgument(!TextUtils.isEmpty(channel.getName()));
boolean needsPolicyFileChange = false;
synchronized (mPackagePreferences) {
@@ -788,8 +788,8 @@ public class PreferencesHelper implements RankingConfig {
@Override
public void updateNotificationChannel(String pkg, int uid, NotificationChannel updatedChannel,
boolean fromUser) {
- Preconditions.checkNotNull(updatedChannel);
- Preconditions.checkNotNull(updatedChannel.getId());
+ Objects.requireNonNull(updatedChannel);
+ Objects.requireNonNull(updatedChannel.getId());
synchronized (mPackagePreferences) {
PackagePreferences r = getOrCreatePackagePreferencesLocked(pkg, uid);
if (r == null) {
@@ -850,7 +850,7 @@ public class PreferencesHelper implements RankingConfig {
@Override
public NotificationChannel getNotificationChannel(String pkg, int uid, String channelId,
boolean includeDeleted) {
- Preconditions.checkNotNull(pkg);
+ Objects.requireNonNull(pkg);
synchronized (mPackagePreferences) {
PackagePreferences r = getOrCreatePackagePreferencesLocked(pkg, uid);
if (r == null) {
@@ -891,8 +891,8 @@ public class PreferencesHelper implements RankingConfig {
@Override
@VisibleForTesting
public void permanentlyDeleteNotificationChannel(String pkg, int uid, String channelId) {
- Preconditions.checkNotNull(pkg);
- Preconditions.checkNotNull(channelId);
+ Objects.requireNonNull(pkg);
+ Objects.requireNonNull(channelId);
synchronized (mPackagePreferences) {
PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
if (r == null) {
@@ -904,7 +904,7 @@ public class PreferencesHelper implements RankingConfig {
@Override
public void permanentlyDeleteNotificationChannels(String pkg, int uid) {
- Preconditions.checkNotNull(pkg);
+ Objects.requireNonNull(pkg);
synchronized (mPackagePreferences) {
PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
if (r == null) {
@@ -993,7 +993,7 @@ public class PreferencesHelper implements RankingConfig {
public NotificationChannelGroup getNotificationChannelGroupWithChannels(String pkg,
int uid, String groupId, boolean includeDeleted) {
- Preconditions.checkNotNull(pkg);
+ Objects.requireNonNull(pkg);
synchronized (mPackagePreferences) {
PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
if (r == null || groupId == null || !r.groups.containsKey(groupId)) {
@@ -1016,7 +1016,7 @@ public class PreferencesHelper implements RankingConfig {
public NotificationChannelGroup getNotificationChannelGroup(String groupId, String pkg,
int uid) {
- Preconditions.checkNotNull(pkg);
+ Objects.requireNonNull(pkg);
synchronized (mPackagePreferences) {
PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
if (r == null) {
@@ -1029,7 +1029,7 @@ public class PreferencesHelper implements RankingConfig {
@Override
public ParceledListSlice<NotificationChannelGroup> getNotificationChannelGroups(String pkg,
int uid, boolean includeDeleted, boolean includeNonGrouped, boolean includeEmpty) {
- Preconditions.checkNotNull(pkg);
+ Objects.requireNonNull(pkg);
Map<String, NotificationChannelGroup> groups = new ArrayMap<>();
synchronized (mPackagePreferences) {
PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
@@ -1111,7 +1111,7 @@ public class PreferencesHelper implements RankingConfig {
@Override
public ParceledListSlice<NotificationChannel> getNotificationChannels(String pkg, int uid,
boolean includeDeleted) {
- Preconditions.checkNotNull(pkg);
+ Objects.requireNonNull(pkg);
List<NotificationChannel> channels = new ArrayList<>();
synchronized (mPackagePreferences) {
PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
@@ -1168,7 +1168,7 @@ public class PreferencesHelper implements RankingConfig {
}
public int getDeletedChannelCount(String pkg, int uid) {
- Preconditions.checkNotNull(pkg);
+ Objects.requireNonNull(pkg);
int deletedCount = 0;
synchronized (mPackagePreferences) {
PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
@@ -1187,7 +1187,7 @@ public class PreferencesHelper implements RankingConfig {
}
public int getBlockedChannelCount(String pkg, int uid) {
- Preconditions.checkNotNull(pkg);
+ Objects.requireNonNull(pkg);
int blockedCount = 0;
synchronized (mPackagePreferences) {
PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
diff --git a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
index 9a1b30dc2b0b..1e2d52d76697 100644
--- a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
+++ b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
@@ -38,6 +38,7 @@ import com.android.internal.util.Preconditions;
import com.android.server.SystemConfig;
import java.io.FileDescriptor;
+import java.util.Objects;
/**
* Implementation of the service that provides a privileged API to capture and consume bugreports.
@@ -67,9 +68,9 @@ class BugreportManagerServiceImpl extends IDumpstate.Stub {
FileDescriptor bugreportFd, FileDescriptor screenshotFd,
int bugreportMode, IDumpstateListener listener) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, "startBugreport");
- Preconditions.checkNotNull(callingPackage);
- Preconditions.checkNotNull(bugreportFd);
- Preconditions.checkNotNull(listener);
+ Objects.requireNonNull(callingPackage);
+ Objects.requireNonNull(bugreportFd);
+ Objects.requireNonNull(listener);
validateBugreportMode(bugreportMode);
final long identity = Binder.clearCallingIdentity();
try {
diff --git a/services/core/java/com/android/server/package-info.java b/services/core/java/com/android/server/package-info.java
index a783e8d61a32..dd94edd53c70 100644
--- a/services/core/java/com/android/server/package-info.java
+++ b/services/core/java/com/android/server/package-info.java
@@ -13,5 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
+/**
+ * @hide
+ * TODO(b/146466118) remove this javadoc tag
+ */
@android.annotation.Hide
package com.android.server;
diff --git a/services/core/java/com/android/server/pm/DataLoaderManagerService.java b/services/core/java/com/android/server/pm/DataLoaderManagerService.java
index 0719797ed85a..0dfea7fd5f96 100644
--- a/services/core/java/com/android/server/pm/DataLoaderManagerService.java
+++ b/services/core/java/com/android/server/pm/DataLoaderManagerService.java
@@ -76,13 +76,12 @@ public class DataLoaderManagerService extends SystemService {
return false;
}
}
- CharSequence packageNameSeq = params.getCharSequence("packageName");
- if (packageNameSeq == null) {
- Slog.e(TAG, "Must specify package name.");
+ ComponentName componentName = params.getParcelable("componentName");
+ if (componentName == null) {
+ Slog.e(TAG, "Must specify component name.");
return false;
}
- String packageName = packageNameSeq.toString();
- ComponentName dataLoaderComponent = getDataLoaderServiceName(packageName);
+ ComponentName dataLoaderComponent = resolveDataLoaderComponentName(componentName);
if (dataLoaderComponent == null) {
return false;
}
@@ -103,22 +102,23 @@ public class DataLoaderManagerService extends SystemService {
/**
* Find the ComponentName of the data loader service provider, given its package name.
*
- * @param packageName the package name of the provider.
+ * @param componentName the name of the provider.
* @return ComponentName of the data loader service provider. Null if provider not found.
*/
- private @Nullable ComponentName getDataLoaderServiceName(String packageName) {
+ private @Nullable ComponentName resolveDataLoaderComponentName(
+ ComponentName componentName) {
final PackageManager pm = mContext.getPackageManager();
if (pm == null) {
Slog.e(TAG, "PackageManager is not available.");
return null;
}
Intent intent = new Intent(Intent.ACTION_LOAD_DATA);
- intent.setPackage(packageName);
+ intent.setComponent(componentName);
List<ResolveInfo> services =
pm.queryIntentServicesAsUser(intent, 0, UserHandle.getCallingUserId());
if (services == null || services.isEmpty()) {
Slog.e(TAG,
- "Failed to find data loader service provider in package " + packageName);
+ "Failed to find data loader service provider in " + componentName);
return null;
}
@@ -128,23 +128,21 @@ public class DataLoaderManagerService extends SystemService {
int numServices = services.size();
for (int i = 0; i < numServices; i++) {
ResolveInfo ri = services.get(i);
- ComponentName componentName = new ComponentName(
+ ComponentName resolved = new ComponentName(
ri.serviceInfo.packageName, ri.serviceInfo.name);
// There should only be one matching provider inside the given package.
// If there's more than one, return the first one found.
try {
- ApplicationInfo ai = pm.getApplicationInfo(componentName.getPackageName(), 0);
+ ApplicationInfo ai = pm.getApplicationInfo(resolved.getPackageName(), 0);
if (checkLoader && !ai.isPrivilegedApp()) {
Slog.w(TAG,
- "Data loader: " + componentName.getPackageName()
- + " is not a privileged app, skipping.");
+ "Data loader: " + resolved + " is not a privileged app, skipping.");
continue;
}
- return componentName;
+ return resolved;
} catch (PackageManager.NameNotFoundException ex) {
Slog.w(TAG,
- "Privileged data loader: " + componentName.getPackageName()
- + " not found, skipping.");
+ "Privileged data loader: " + resolved + " not found, skipping.");
}
}
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 26cd42daa9f8..f962eedb5111 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -28,6 +28,7 @@ import android.os.IBinder.DeathRecipient;
import android.os.IInstalld;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.storage.CrateMetadata;
import android.text.format.DateUtils;
import android.util.Slog;
@@ -293,6 +294,43 @@ public class Installer extends SystemService {
}
}
+ /**
+ * To get all of the CrateMetadata of the crates for the specified user app by the installd.
+ *
+ * @param uuid the UUID
+ * @param packageNames the application package names
+ * @param userId the user id
+ * @return the array of CrateMetadata
+ */
+ @Nullable
+ public CrateMetadata[] getAppCrates(@NonNull String uuid, @NonNull String[] packageNames,
+ @UserIdInt int userId) throws InstallerException {
+ if (!checkBeforeRemote()) return null;
+ try {
+ return mInstalld.getAppCrates(uuid, packageNames, userId);
+ } catch (Exception e) {
+ throw InstallerException.from(e);
+ }
+ }
+
+ /**
+ * To retrieve all of the CrateMetadata of the crate for the specified user app by the installd.
+ *
+ * @param uuid the UUID
+ * @param userId the user id
+ * @return the array of CrateMetadata
+ */
+ @Nullable
+ public CrateMetadata[] getUserCrates(String uuid, @UserIdInt int userId)
+ throws InstallerException {
+ if (!checkBeforeRemote()) return null;
+ try {
+ return mInstalld.getUserCrates(uuid, userId);
+ } catch (Exception e) {
+ throw InstallerException.from(e);
+ }
+ }
+
public void setAppQuota(String uuid, int userId, int appId, long cacheQuota)
throws InstallerException {
if (!checkBeforeRemote()) return;
@@ -580,6 +618,30 @@ public class Installer extends SystemService {
}
}
+ /**
+ * Bind mount private volume CE and DE mirror storage.
+ */
+ public void onPrivateVolumeMounted(String volumeUuid) throws InstallerException {
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.onPrivateVolumeMounted(volumeUuid);
+ } catch (Exception e) {
+ throw InstallerException.from(e);
+ }
+ }
+
+ /**
+ * Unmount private volume CE and DE mirror storage.
+ */
+ public void onPrivateVolumeRemoved(String volumeUuid) throws InstallerException {
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.onPrivateVolumeRemoved(volumeUuid);
+ } catch (Exception e) {
+ throw InstallerException.from(e);
+ }
+ }
+
public boolean prepareAppProfile(String pkg, @UserIdInt int userId, @AppIdInt int appId,
String profileName, String codePath, String dexMetadataPath) throws InstallerException {
if (!checkBeforeRemote()) return false;
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index a54534b461f1..e2dfa126225f 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -217,6 +217,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
public void systemReady() {
mAppOps = mContext.getSystemService(AppOpsManager.class);
+ mStagingManager.systemReady();
synchronized (mSessions) {
readSessionsLocked();
@@ -257,8 +258,9 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
}
// Don't hold mSessions lock when calling restoreSession, since it might trigger an APK
// atomic install which needs to query sessions, which requires lock on mSessions.
+ boolean isDeviceUpgrading = mPm.isDeviceUpgrading();
for (PackageInstallerSession session : stagedSessionsToRestore) {
- if (mPm.isDeviceUpgrading() && !session.isStagedAndInTerminalState()) {
+ if (isDeviceUpgrading && !session.isStagedAndInTerminalState()) {
session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
"Build fingerprint has changed");
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 286d291836ec..ac183dcf6b7a 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -16,6 +16,8 @@
package com.android.server.pm;
+import static android.content.pm.DataLoaderType.INCREMENTAL;
+import static android.content.pm.DataLoaderType.STREAMING;
import static android.content.pm.PackageManager.INSTALL_FAILED_ABORTED;
import static android.content.pm.PackageManager.INSTALL_FAILED_BAD_SIGNATURE;
import static android.content.pm.PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
@@ -49,14 +51,21 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.admin.DevicePolicyEventLogger;
import android.app.admin.DevicePolicyManagerInternal;
+import android.content.ComponentName;
import android.content.Context;
import android.content.IIntentReceiver;
import android.content.IIntentSender;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.ApplicationInfo;
+import android.content.pm.DataLoaderManager;
+import android.content.pm.DataLoaderParams;
+import android.content.pm.FileSystemControlParcel;
+import android.content.pm.IDataLoader;
+import android.content.pm.IDataLoaderStatusListener;
import android.content.pm.IPackageInstallObserver2;
import android.content.pm.IPackageInstallerSession;
+import android.content.pm.IPackageInstallerSessionFileSystemConnector;
import android.content.pm.InstallationFile;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller;
@@ -83,6 +92,7 @@ import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.ParcelableException;
import android.os.Process;
+import android.os.RemoteException;
import android.os.RevocableFileDescriptor;
import android.os.SystemProperties;
import android.os.UserHandle;
@@ -126,12 +136,12 @@ import java.io.FileDescriptor;
import java.io.FileFilter;
import java.io.FileOutputStream;
import java.io.IOException;
-import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
public class PackageInstallerSession extends IPackageInstallerSession.Stub {
private static final String TAG = "PackageInstallerSession";
@@ -188,7 +198,11 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
private static final String ATTR_VOLUME_UUID = "volumeUuid";
private static final String ATTR_NAME = "name";
private static final String ATTR_INSTALL_REASON = "installRason";
- private static final String ATTR_DATA_LOADER_PACKAGE_NAME = "dataLoaderPackageName";
+ private static final String ATTR_IS_DATALOADER = "isDataLoader";
+ private static final String ATTR_DATALOADER_TYPE = "dataLoaderType";
+ private static final String ATTR_DATALOADER_PACKAGE_NAME = "dataLoaderPackageName";
+ private static final String ATTR_DATALOADER_CLASS_NAME = "dataLoaderClassName";
+ private static final String ATTR_DATALOADER_ARGUMENTS = "dataLoaderArguments";
private static final String ATTR_LENGTH_BYTES = "lengthBytes";
private static final String ATTR_METADATA = "metadata";
@@ -413,7 +427,15 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
};
private boolean isDataLoaderInstallation() {
- return !TextUtils.isEmpty(params.dataLoaderPackageName);
+ return params.dataLoaderParams != null;
+ }
+
+ private boolean isStreamingInstallation() {
+ return isDataLoaderInstallation() && params.dataLoaderParams.getType() == STREAMING;
+ }
+
+ private boolean isIncrementalInstallation() {
+ return isDataLoaderInstallation() && params.dataLoaderParams.getType() == INCREMENTAL;
}
/**
@@ -524,14 +546,13 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
stagedSessionErrorMessage != null ? stagedSessionErrorMessage : "";
// TODO(b/136132412): sanity check if session should not be incremental
- if (!params.isStaged && params.incrementalParams != null
- && !params.incrementalParams.getPackageName().isEmpty()) {
+ if (!params.isStaged && isIncrementalInstallation()) {
IncrementalManager incrementalManager = (IncrementalManager) mContext.getSystemService(
Context.INCREMENTAL_SERVICE);
if (incrementalManager != null) {
mIncrementalFileStorages =
new IncrementalFileStorages(mPackageName, stageDir, incrementalManager,
- params.incrementalParams);
+ params.dataLoaderParams);
}
}
}
@@ -571,6 +592,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
info.installFlags = params.installFlags;
info.isMultiPackage = params.isMultiPackage;
info.isStaged = params.isStaged;
+ info.rollbackDataPolicy = params.rollbackDataPolicy;
info.parentSessionId = mParentSessionId;
info.childSessionIds = mChildSessionIds.copyKeys();
if (info.childSessionIds == null) {
@@ -712,7 +734,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
public void removeSplit(String splitName) {
if (isDataLoaderInstallation()) {
throw new IllegalStateException(
- "Cannot remove splits in a callback installation session.");
+ "Cannot remove splits in a data loader installation session.");
}
if (TextUtils.isEmpty(params.appPackageName)) {
throw new IllegalStateException("Must specify package name to remove a split");
@@ -751,7 +773,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
private void assertCanWrite(boolean reverseMode) {
if (isDataLoaderInstallation()) {
throw new IllegalStateException(
- "Cannot write regular files in a callback installation session.");
+ "Cannot write regular files in a data loader installation session.");
}
synchronized (mLock) {
assertCallerIsOwnerOrRootLocked();
@@ -892,7 +914,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
public ParcelFileDescriptor openRead(String name) {
if (isDataLoaderInstallation()) {
throw new IllegalStateException(
- "Cannot read regular files in a callback installation session.");
+ "Cannot read regular files in a data loader installation session.");
}
synchronized (mLock) {
assertCallerIsOwnerOrRootLocked();
@@ -1003,6 +1025,21 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
mHandler.obtainMessage(MSG_COMMIT).sendToTarget();
}
+ private class FileSystemConnector extends IPackageInstallerSessionFileSystemConnector.Stub {
+ @Override
+ public void writeData(String name, long offsetBytes, long lengthBytes,
+ ParcelFileDescriptor incomingFd) {
+ if (incomingFd == null) {
+ throw new IllegalArgumentException("incomingFd can't be null");
+ }
+ try {
+ doWriteInternal(name, offsetBytes, lengthBytes, incomingFd);
+ } catch (IOException e) {
+ throw ExceptionUtils.wrap(e);
+ }
+ }
+ }
+
private class ChildStatusIntentReceiver {
private final SparseIntArray mChildSessionsRemaining;
private final IntentSender mStatusReceiver;
@@ -1646,7 +1683,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
computeProgressLocked(true);
// Unpack native libraries for non-incremental installation
- if (params.incrementalParams == null) {
+ if (isIncrementalInstallation()) {
extractNativeLibraries(stageDir, params.abiOverride, mayInheritNativeLibs());
}
}
@@ -2356,6 +2393,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
if (mIncrementalFileStorages != null) {
try {
mIncrementalFileStorages.addFile(new InstallationFile(name, lengthBytes, metadata));
+ //TODO(b/136132412): merge incremental and callback installation schemes
+ return;
} catch (IOException ex) {
throw new IllegalStateException(
"Failed to add and configure Incremental File: " + name, ex);
@@ -2363,7 +2402,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
if (!isDataLoaderInstallation()) {
throw new IllegalStateException(
- "Cannot add files to non-callback installation session.");
+ "Cannot add files to non-data loader installation session.");
}
// Use installer provided name for now; we always rename later
if (!FileUtils.isValidExtFilename(name)) {
@@ -2382,7 +2421,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
public void removeFile(String name) {
if (!isDataLoaderInstallation()) {
throw new IllegalStateException(
- "Cannot add files to non-callback installation session.");
+ "Cannot add files to non-data loader installation session.");
}
if (TextUtils.isEmpty(params.appPackageName)) {
throw new IllegalStateException("Must specify package name to remove a split");
@@ -2396,84 +2435,121 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
}
+ static class Notificator {
+ private int mValue = 0;
+
+ void setValue(int value) {
+ synchronized (this) {
+ mValue = value;
+ this.notify();
+ }
+ }
+ int waitForValue() {
+ synchronized (this) {
+ while (mValue == 0) {
+ try {
+ this.wait();
+ } catch (InterruptedException e) {
+ // Happens if someone interrupts your thread.
+ }
+ }
+ return mValue;
+ }
+ }
+ }
+
/**
* Makes sure files are present in staging location.
*/
private void prepareDataLoader()
throws PackageManagerException, StreamingException {
- if (!isDataLoaderInstallation()) {
+ if (!isStreamingInstallation()) {
return;
}
- FilesystemConnector connector = new FilesystemConnector();
+ FileSystemConnector connector = new FileSystemConnector();
- FileInfo[] addedFiles = mFiles.stream().filter(
- file -> sAddedFilter.accept(new File(file.name))).toArray(FileInfo[]::new);
- String[] removedFiles = mFiles.stream().filter(
+ List<InstallationFile> addedFiles = mFiles.stream().filter(
+ file -> sAddedFilter.accept(new File(file.name))).map(
+ file -> new InstallationFile(
+ file.name, file.lengthBytes, file.metadata)).collect(
+ Collectors.toList());
+ List<String> removedFiles = mFiles.stream().filter(
file -> sRemovedFilter.accept(new File(file.name))).map(
- file -> file.name.substring(0,
- file.name.length() - REMOVE_MARKER_EXTENSION.length())).toArray(
- String[]::new);
+ file -> file.name.substring(
+ 0, file.name.length() - REMOVE_MARKER_EXTENSION.length())).collect(
+ Collectors.toList());
- DataLoader dataLoader = new DataLoader();
- try {
- dataLoader.onCreate(connector);
+ DataLoaderManager dataLoaderManager = mContext.getSystemService(DataLoaderManager.class);
+ if (dataLoaderManager == null) {
+ throw new PackageManagerException(INSTALL_FAILED_MEDIA_UNAVAILABLE,
+ "Failed to find data loader manager service");
+ }
- if (!dataLoader.onPrepareImage(addedFiles, removedFiles)) {
- throw new PackageManagerException(INSTALL_FAILED_MEDIA_UNAVAILABLE,
- "Failed to prepare image.");
+ // TODO(b/146080380): make this code async.
+ final Notificator created = new Notificator();
+ final Notificator started = new Notificator();
+ final Notificator imageReady = new Notificator();
+
+ IDataLoaderStatusListener listener = new IDataLoaderStatusListener.Stub() {
+ @Override
+ public void onStatusChanged(int dataLoaderId, int status) {
+ switch (status) {
+ case IDataLoaderStatusListener.DATA_LOADER_CREATED: {
+ created.setValue(1);
+ break;
+ }
+ case IDataLoaderStatusListener.DATA_LOADER_STARTED: {
+ started.setValue(1);
+ break;
+ }
+ case IDataLoaderStatusListener.DATA_LOADER_IMAGE_READY: {
+ imageReady.setValue(1);
+ break;
+ }
+ case IDataLoaderStatusListener.DATA_LOADER_IMAGE_NOT_READY: {
+ imageReady.setValue(2);
+ break;
+ }
+ }
}
- } catch (IOException e) {
- throw new StreamingException(e);
- } finally {
- dataLoader.onDestroy();
- }
- }
+ };
- // TODO(b/146080380): implement DataLoader using Incremental infrastructure.
- class FilesystemConnector {
- void writeData(FileInfo fileInfo, long offset, long lengthBytes,
- ParcelFileDescriptor incomingFd) throws IOException {
- doWriteInternal(fileInfo.name, offset, lengthBytes, incomingFd);
- }
- }
+ final DataLoaderParams params = this.params.dataLoaderParams;
+
+ final FileSystemControlParcel control = new FileSystemControlParcel();
+ control.callback = connector;
- static class DataLoader {
- private ParcelFileDescriptor mInFd = null;
- private FilesystemConnector mConnector = null;
+ Bundle dataLoaderParams = new Bundle();
+ dataLoaderParams.putParcelable("componentName", params.getComponentName());
+ dataLoaderParams.putParcelable("control", control);
+ dataLoaderParams.putParcelable("params", params.getData());
- void onCreate(FilesystemConnector connector) throws IOException {
- mConnector = connector;
+ if (!dataLoaderManager.initializeDataLoader(sessionId, dataLoaderParams, listener)) {
+ throw new PackageManagerException(INSTALL_FAILED_MEDIA_UNAVAILABLE,
+ "Failed to initialize data loader");
}
+ created.waitForValue();
- void onDestroy() {
- IoUtils.closeQuietly(mInFd);
+ IDataLoader dataLoader = dataLoaderManager.getDataLoader(sessionId);
+ if (dataLoader == null) {
+ throw new PackageManagerException(INSTALL_FAILED_MEDIA_UNAVAILABLE,
+ "Failure to obtain data loader");
}
- private static final String STDIN_PATH = "-";
- boolean onPrepareImage(FileInfo[] addedFiles, String[] removedFiles) throws IOException {
- for (FileInfo fileInfo : addedFiles) {
- String filePath = new String(fileInfo.metadata, StandardCharsets.UTF_8);
- if (STDIN_PATH.equals(filePath) || TextUtils.isEmpty(filePath)) {
- if (mInFd == null) {
- Slog.e(TAG, "Invalid stdin file descriptor.");
- return false;
- }
- ParcelFileDescriptor inFd = ParcelFileDescriptor.dup(mInFd.getFileDescriptor());
- mConnector.writeData(fileInfo, 0, fileInfo.lengthBytes, inFd);
- } else {
- File localFile = new File(filePath);
- ParcelFileDescriptor incomingFd = null;
- try {
- incomingFd = ParcelFileDescriptor.open(localFile,
- ParcelFileDescriptor.MODE_READ_ONLY);
- mConnector.writeData(fileInfo, 0, localFile.length(), incomingFd);
- } finally {
- IoUtils.closeQuietly(incomingFd);
- }
- }
+ try {
+ dataLoader.start();
+ started.waitForValue();
+
+ dataLoader.prepareImage(addedFiles, removedFiles);
+ if (imageReady.waitForValue() == 2) {
+ throw new PackageManagerException(INSTALL_FAILED_MEDIA_UNAVAILABLE,
+ "Failed to prepare image.");
}
- return true;
+
+ dataLoader.destroy();
+ } catch (RemoteException e) {
+ throw new StreamingException(e);
}
}
@@ -2835,7 +2911,17 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
writeStringAttribute(out, ATTR_VOLUME_UUID, params.volumeUuid);
writeIntAttribute(out, ATTR_INSTALL_REASON, params.installReason);
- writeStringAttribute(out, ATTR_DATA_LOADER_PACKAGE_NAME, params.dataLoaderPackageName);
+ final boolean isDataLoader = params.dataLoaderParams != null;
+ writeBooleanAttribute(out, ATTR_IS_DATALOADER, isDataLoader);
+ if (isDataLoader) {
+ writeIntAttribute(out, ATTR_DATALOADER_TYPE, params.dataLoaderParams.getType());
+ writeStringAttribute(out, ATTR_DATALOADER_PACKAGE_NAME,
+ params.dataLoaderParams.getComponentName().getPackageName());
+ writeStringAttribute(out, ATTR_DATALOADER_CLASS_NAME,
+ params.dataLoaderParams.getComponentName().getClassName());
+ writeStringAttribute(out, ATTR_DATALOADER_ARGUMENTS,
+ params.dataLoaderParams.getArguments());
+ }
writeGrantedRuntimePermissionsLocked(out, params.grantedRuntimePermissions);
writeWhitelistedRestrictedPermissionsLocked(out,
@@ -2946,7 +3032,15 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
params.volumeUuid = readStringAttribute(in, ATTR_VOLUME_UUID);
params.installReason = readIntAttribute(in, ATTR_INSTALL_REASON);
- params.dataLoaderPackageName = readStringAttribute(in, ATTR_DATA_LOADER_PACKAGE_NAME);
+ if (readBooleanAttribute(in, ATTR_IS_DATALOADER)) {
+ params.dataLoaderParams = new DataLoaderParams(
+ readIntAttribute(in, ATTR_DATALOADER_TYPE),
+ new ComponentName(
+ readStringAttribute(in, ATTR_DATALOADER_PACKAGE_NAME),
+ readStringAttribute(in, ATTR_DATALOADER_CLASS_NAME)),
+ readStringAttribute(in, ATTR_DATALOADER_ARGUMENTS),
+ null);
+ }
final File appIconFile = buildAppIconFile(sessionId, sessionsDir);
if (appIconFile.exists()) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 99d5e4a21df4..b793d6de2e40 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -27,6 +27,8 @@ import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
import static android.content.Intent.ACTION_MAIN;
import static android.content.Intent.CATEGORY_DEFAULT;
import static android.content.Intent.CATEGORY_HOME;
+import static android.content.Intent.EXTRA_PACKAGE_NAME;
+import static android.content.Intent.EXTRA_VERSION_CODE;
import static android.content.pm.PackageManager.CERT_INPUT_RAW_X509;
import static android.content.pm.PackageManager.CERT_INPUT_SHA256;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
@@ -34,6 +36,7 @@ import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+import static android.content.pm.PackageManager.EXTRA_VERIFICATION_ID;
import static android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
import static android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKED_COMPAT;
@@ -96,6 +99,8 @@ import static com.android.internal.annotations.VisibleForTesting.Visibility;
import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE;
import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_PARENT;
import static com.android.internal.content.NativeLibraryHelper.LIB_DIR_NAME;
+import static com.android.internal.util.ArrayUtils.emptyIfNull;
+import static com.android.internal.util.ArrayUtils.filter;
import static com.android.server.pm.ComponentResolver.RESOLVE_PRIORITY_SORTER;
import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
import static com.android.server.pm.InstructionSets.getDexCodeInstructionSet;
@@ -249,7 +254,6 @@ import android.os.storage.VolumeInfo;
import android.os.storage.VolumeRecord;
import android.permission.IPermissionManager;
import android.provider.DeviceConfig;
-import android.provider.MediaStore;
import android.provider.Settings.Global;
import android.provider.Settings.Secure;
import android.security.KeyStore;
@@ -385,6 +389,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
+import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
@@ -556,6 +561,11 @@ public class PackageManagerService extends IPackageManager.Stub
private static final boolean DEFAULT_VERIFY_ENABLE = true;
/**
+ * Whether integrity verification is enabled by default.
+ */
+ private static final boolean DEFAULT_INTEGRITY_VERIFY_ENABLE = true;
+
+ /**
* The default maximum time to wait for the verification agent to return in
* milliseconds.
*/
@@ -1442,6 +1452,7 @@ public class PackageManagerService extends IPackageManager.Stub
static final int DEFERRED_NO_KILL_POST_DELETE = 23;
static final int DEFERRED_NO_KILL_INSTALL_OBSERVER = 24;
static final int INTEGRITY_VERIFICATION_COMPLETE = 25;
+ static final int CHECK_PENDING_INTEGRITY_VERIFICATION = 26;
static final int DEFERRED_NO_KILL_POST_DELETE_DELAY_MS = 3 * 1000;
static final int DEFERRED_NO_KILL_INSTALL_OBSERVER_DELAY_MS = 500;
@@ -1705,13 +1716,13 @@ public class PackageManagerService extends IPackageManager.Stub
final int verificationId = msg.arg1;
final PackageVerificationState state = mPendingVerification.get(verificationId);
- if ((state != null) && !state.timeoutExtended()) {
+ if ((state != null) && !state.isVerificationComplete()
+ && !state.timeoutExtended()) {
final InstallParams params = state.getInstallParams();
final InstallArgs args = params.mArgs;
final Uri originUri = Uri.fromFile(args.origin.resolvedFile);
Slog.i(TAG, "Verification timed out for " + originUri);
- mPendingVerification.remove(verificationId);
final UserHandle user = args.getUser();
if (getDefaultVerificationResponse(user)
@@ -1726,11 +1737,54 @@ public class PackageManagerService extends IPackageManager.Stub
PackageManager.VERIFICATION_REJECT, user);
params.setReturnCode(
PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE);
+ state.setVerifierResponse(Binder.getCallingUid(),
+ PackageManager.VERIFICATION_REJECT);
+ }
+
+ if (state.areAllVerificationsComplete()) {
+ mPendingVerification.remove(verificationId);
}
Trace.asyncTraceEnd(
TRACE_TAG_PACKAGE_MANAGER, "verification", verificationId);
+
params.handleVerificationFinished();
+
+ }
+ break;
+ }
+ case CHECK_PENDING_INTEGRITY_VERIFICATION: {
+ final int verificationId = msg.arg1;
+ final PackageVerificationState state = mPendingVerification.get(verificationId);
+
+ if (state != null && !state.isIntegrityVerificationComplete()) {
+ final InstallParams params = state.getInstallParams();
+ final InstallArgs args = params.mArgs;
+ final Uri originUri = Uri.fromFile(args.origin.resolvedFile);
+
+ Slog.i(TAG, "Integrity verification timed out for " + originUri);
+
+ state.setIntegrityVerificationResult(
+ getDefaultIntegrityVerificationResponse());
+
+ if (getDefaultIntegrityVerificationResponse()
+ == PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW) {
+ Slog.i(TAG, "Integrity check times out, continuing with " + originUri);
+ } else {
+ params.setReturnCode(
+ PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE);
+ }
+
+ if (state.areAllVerificationsComplete()) {
+ mPendingVerification.remove(verificationId);
+ }
+
+ Trace.asyncTraceEnd(
+ TRACE_TAG_PACKAGE_MANAGER,
+ "integrity_verification",
+ verificationId);
+
+ params.handleIntegrityVerificationFinished();
}
break;
}
@@ -1739,7 +1793,9 @@ public class PackageManagerService extends IPackageManager.Stub
final PackageVerificationState state = mPendingVerification.get(verificationId);
if (state == null) {
- Slog.w(TAG, "Invalid verification token " + verificationId + " received");
+ Slog.w(TAG, "Verification with id " + verificationId
+ + " not found."
+ + " It may be invalid or overridden by integrity verification");
break;
}
@@ -1748,8 +1804,6 @@ public class PackageManagerService extends IPackageManager.Stub
state.setVerifierResponse(response.callerUid, response.code);
if (state.isVerificationComplete()) {
- mPendingVerification.remove(verificationId);
-
final InstallParams params = state.getInstallParams();
final InstallArgs args = params.mArgs;
final Uri originUri = Uri.fromFile(args.origin.resolvedFile);
@@ -1762,6 +1816,10 @@ public class PackageManagerService extends IPackageManager.Stub
PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE);
}
+ if (state.areAllVerificationsComplete()) {
+ mPendingVerification.remove(verificationId);
+ }
+
Trace.asyncTraceEnd(
TRACE_TAG_PACKAGE_MANAGER, "verification", verificationId);
@@ -1771,7 +1829,40 @@ public class PackageManagerService extends IPackageManager.Stub
break;
}
case INTEGRITY_VERIFICATION_COMPLETE: {
- // TODO: implement this case.
+ final int verificationId = msg.arg1;
+
+ final PackageVerificationState state = mPendingVerification.get(verificationId);
+ if (state == null) {
+ Slog.w(TAG, "Integrity verification with id " + verificationId
+ + " not found. It may be invalid or overridden by verifier");
+ break;
+ }
+
+ final int response = (Integer) msg.obj;
+
+ final InstallParams params = state.getInstallParams();
+ final InstallArgs args = params.mArgs;
+ final Uri originUri = Uri.fromFile(args.origin.resolvedFile);
+
+ state.setIntegrityVerificationResult(response);
+
+ if (response == PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW) {
+ Slog.i(TAG, "Integrity check passed for " + originUri);
+ } else {
+ params.setReturnCode(
+ PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE);
+ }
+
+ if (state.areAllVerificationsComplete()) {
+ mPendingVerification.remove(verificationId);
+ }
+
+ Trace.asyncTraceEnd(
+ TRACE_TAG_PACKAGE_MANAGER,
+ "integrity_verification",
+ verificationId);
+
+ params.handleIntegrityVerificationFinished();
break;
}
case START_INTENT_FILTER_VERIFICATIONS: {
@@ -12781,7 +12872,7 @@ public class PackageManagerService extends IPackageManager.Stub
@Override
public String[] getUnsuspendablePackagesForUser(String[] packageNames, int userId) {
- Preconditions.checkNotNull("packageNames cannot be null", packageNames);
+ Preconditions.checkNotNull(packageNames, "packageNames cannot be null");
mContext.enforceCallingOrSelfPermission(Manifest.permission.SUSPEND_APPS,
"getUnsuspendablePackagesForUser");
final int callingUid = Binder.getCallingUid();
@@ -13097,6 +13188,15 @@ public class PackageManagerService extends IPackageManager.Stub
}
/**
+ * Get the default integrity verification response code.
+ */
+ private int getDefaultIntegrityVerificationResponse() {
+ // We are not exposing this as a user-configurable setting because we don't want to provide
+ // an easy way to get around the integrity check.
+ return PackageManager.VERIFICATION_REJECT;
+ }
+
+ /**
* Check whether or not package verification has been enabled.
*
* @return true if verification should be performed
@@ -13139,6 +13239,15 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
+ /**
+ * Check whether or not integrity verification has been enabled.
+ */
+ private boolean isIntegrityVerificationEnabled() {
+ // We are not exposing this as a user-configurable setting because we don't want to provide
+ // an easy way to get around the integrity check.
+ return DEFAULT_INTEGRITY_VERIFY_ENABLE;
+ }
+
@Override
public void verifyIntentFilter(int id, int verificationCode, List<String> failedDomains)
throws RemoteException {
@@ -13849,6 +13958,7 @@ public class PackageManagerService extends IPackageManager.Stub
@NonNull final InstallSource installSource;
final String volumeUuid;
private boolean mVerificationCompleted;
+ private boolean mIntegrityVerificationCompleted;
private boolean mEnableRollbackCompleted;
private InstallArgs mArgs;
int mRet;
@@ -14110,155 +14220,30 @@ public class PackageManagerService extends IPackageManager.Stub
final InstallArgs args = createInstallArgs(this);
mVerificationCompleted = true;
+ mIntegrityVerificationCompleted = true;
mEnableRollbackCompleted = true;
mArgs = args;
if (ret == PackageManager.INSTALL_SUCCEEDED) {
- // TODO: http://b/22976637
- // Apps installed for "all" users use the device owner to verify the app
- UserHandle verifierUser = getUser();
- if (verifierUser == UserHandle.ALL) {
- verifierUser = UserHandle.SYSTEM;
- }
-
- /*
- * Determine if we have any installed package verifiers. If we
- * do, then we'll defer to them to verify the packages.
- */
- final int requiredUid = mRequiredVerifierPackage == null ? -1
- : getPackageUid(mRequiredVerifierPackage, MATCH_DEBUG_TRIAGED_MISSING,
- verifierUser.getIdentifier());
- final int installerUid =
- verificationInfo == null ? -1 : verificationInfo.installerUid;
- if (!origin.existing && requiredUid != -1
- && isVerificationEnabled(
- verifierUser.getIdentifier(), installFlags, installerUid)) {
- final Intent verification = new Intent(
- Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
- verification.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
- verification.setDataAndType(Uri.fromFile(new File(origin.resolvedPath)),
- PACKAGE_MIME_TYPE);
- verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-
- // Query all live verifiers based on current user state
- final List<ResolveInfo> receivers = queryIntentReceiversInternal(verification,
- PACKAGE_MIME_TYPE, 0, verifierUser.getIdentifier(),
- false /*allowDynamicSplits*/);
-
- if (DEBUG_VERIFY) {
- Slog.d(TAG, "Found " + receivers.size() + " verifiers for intent "
- + verification.toString() + " with " + pkgLite.verifiers.length
- + " optional verifiers");
- }
-
- final int verificationId = mPendingVerificationToken++;
-
- verification.putExtra(PackageManager.EXTRA_VERIFICATION_ID, verificationId);
-
- verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_PACKAGE,
- installSource.initiatingPackageName);
-
- verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALL_FLAGS,
- installFlags);
-
- verification.putExtra(PackageManager.EXTRA_VERIFICATION_PACKAGE_NAME,
- pkgLite.packageName);
-
- verification.putExtra(PackageManager.EXTRA_VERIFICATION_VERSION_CODE,
- pkgLite.versionCode);
-
- verification.putExtra(PackageManager.EXTRA_VERIFICATION_LONG_VERSION_CODE,
- pkgLite.getLongVersionCode());
-
- if (verificationInfo != null) {
- if (verificationInfo.originatingUri != null) {
- verification.putExtra(Intent.EXTRA_ORIGINATING_URI,
- verificationInfo.originatingUri);
- }
- if (verificationInfo.referrer != null) {
- verification.putExtra(Intent.EXTRA_REFERRER,
- verificationInfo.referrer);
- }
- if (verificationInfo.originatingUid >= 0) {
- verification.putExtra(Intent.EXTRA_ORIGINATING_UID,
- verificationInfo.originatingUid);
- }
- if (verificationInfo.installerUid >= 0) {
- verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_UID,
- verificationInfo.installerUid);
- }
- }
-
- final PackageVerificationState verificationState = new PackageVerificationState(
- requiredUid, this);
+ final int verificationId = mPendingVerificationToken++;
+ // Perform package verification (unless we are simply moving the package).
+ if (!origin.existing) {
+ PackageVerificationState verificationState =
+ new PackageVerificationState(this);
mPendingVerification.append(verificationId, verificationState);
- final List<ComponentName> sufficientVerifiers = matchVerifiers(pkgLite,
- receivers, verificationState);
+ sendIntegrityVerificationRequest(verificationId, pkgLite, verificationState);
+ ret = sendPackageVerificationRequest(
+ verificationId, pkgLite, verificationState);
- DeviceIdleInternal idleController =
- mInjector.getLocalDeviceIdleController();
- final long idleDuration = getVerificationTimeout();
-
- /*
- * If any sufficient verifiers were listed in the package
- * manifest, attempt to ask them.
- */
- if (sufficientVerifiers != null) {
- final int N = sufficientVerifiers.size();
- if (N == 0) {
- Slog.i(TAG, "Additional verifiers required, but none installed.");
- ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
- } else {
- for (int i = 0; i < N; i++) {
- final ComponentName verifierComponent = sufficientVerifiers.get(i);
- idleController.addPowerSaveTempWhitelistApp(Process.myUid(),
- verifierComponent.getPackageName(), idleDuration,
- verifierUser.getIdentifier(), false, "package verifier");
-
- final Intent sufficientIntent = new Intent(verification);
- sufficientIntent.setComponent(verifierComponent);
- mContext.sendBroadcastAsUser(sufficientIntent, verifierUser);
- }
- }
- }
-
- final ComponentName requiredVerifierComponent = matchComponentForVerifier(
- mRequiredVerifierPackage, receivers);
- if (ret == PackageManager.INSTALL_SUCCEEDED
- && mRequiredVerifierPackage != null) {
- Trace.asyncTraceBegin(
- TRACE_TAG_PACKAGE_MANAGER, "verification", verificationId);
- /*
- * Send the intent to the required verification agent,
- * but only start the verification timeout after the
- * target BroadcastReceivers have run.
- */
- verification.setComponent(requiredVerifierComponent);
- idleController.addPowerSaveTempWhitelistApp(Process.myUid(),
- mRequiredVerifierPackage, idleDuration,
- verifierUser.getIdentifier(), false, "package verifier");
- mContext.sendOrderedBroadcastAsUser(verification, verifierUser,
- android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
- new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- final Message msg = mHandler
- .obtainMessage(CHECK_PENDING_VERIFICATION);
- msg.arg1 = verificationId;
- mHandler.sendMessageDelayed(msg, getVerificationTimeout());
- }
- }, null, 0, null, null);
-
- /*
- * We don't want the copy to proceed until verification
- * succeeds.
- */
- mVerificationCompleted = false;
+ // If both verifications are skipped, we should remove the state.
+ if (verificationState.areAllVerificationsComplete()) {
+ mPendingVerification.remove(verificationId);
}
}
+
if ((installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0) {
// TODO(ruhler) b/112431924: Don't do this in case of 'move'?
final int enableRollbackToken = mPendingEnableRollbackToken++;
@@ -14314,6 +14299,228 @@ public class PackageManagerService extends IPackageManager.Stub
mRet = ret;
}
+ /**
+ * Send a request to check the integrity of the package.
+ */
+ void sendIntegrityVerificationRequest(
+ int verificationId,
+ PackageInfoLite pkgLite,
+ PackageVerificationState verificationState) {
+ if (!isIntegrityVerificationEnabled()) {
+ // Consider the integrity check as passed.
+ verificationState.setIntegrityVerificationResult(
+ PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
+ return;
+ }
+
+ final Intent integrityVerification =
+ new Intent(Intent.ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION);
+
+ integrityVerification.setDataAndType(Uri.fromFile(new File(origin.resolvedPath)),
+ PACKAGE_MIME_TYPE);
+
+ final int flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
+ | Intent.FLAG_RECEIVER_REGISTERED_ONLY
+ | Intent.FLAG_RECEIVER_FOREGROUND;
+ integrityVerification.addFlags(flags);
+
+ integrityVerification.putExtra(EXTRA_VERIFICATION_ID, verificationId);
+ integrityVerification.putExtra(EXTRA_PACKAGE_NAME, pkgLite.packageName);
+ integrityVerification.putExtra(EXTRA_VERSION_CODE, pkgLite.versionCode);
+ populateInstallerExtras(integrityVerification);
+
+ // send to integrity component only.
+ integrityVerification.setPackage("android");
+
+ DeviceIdleInternal idleController =
+ mInjector.getLocalDeviceIdleController();
+ final long idleDuration = getVerificationTimeout();
+
+ idleController.addPowerSaveTempWhitelistAppDirect(Process.myUid(),
+ idleDuration,
+ false, "integrity component");
+ mContext.sendOrderedBroadcastAsUser(integrityVerification, UserHandle.SYSTEM,
+ /* receiverPermission= */ null,
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final Message msg =
+ mHandler.obtainMessage(CHECK_PENDING_INTEGRITY_VERIFICATION);
+ msg.arg1 = verificationId;
+ // TODO: do we want to use the same timeout?
+ mHandler.sendMessageDelayed(msg, getVerificationTimeout());
+ }
+ }, /* scheduler= */ null,
+ /* initialCode= */ 0,
+ /* initialData= */ null,
+ /* initialExtras= */ null);
+
+ Trace.asyncTraceBegin(
+ TRACE_TAG_PACKAGE_MANAGER, "integrity_verification", verificationId);
+
+ // stop the copy until verification succeeds.
+ mIntegrityVerificationCompleted = false;
+ }
+
+ /**
+ * Send a request to verifier(s) to verify the package if necessary, and return
+ * {@link PackageManager#INSTALL_SUCCEEDED} if succeeded.
+ */
+ int sendPackageVerificationRequest(
+ int verificationId,
+ PackageInfoLite pkgLite,
+ PackageVerificationState verificationState) {
+ int ret = INSTALL_SUCCEEDED;
+
+ // TODO: http://b/22976637
+ // Apps installed for "all" users use the device owner to verify the app
+ UserHandle verifierUser = getUser();
+ if (verifierUser == UserHandle.ALL) {
+ verifierUser = UserHandle.SYSTEM;
+ }
+
+ /*
+ * Determine if we have any installed package verifiers. If we
+ * do, then we'll defer to them to verify the packages.
+ */
+ final int requiredUid = mRequiredVerifierPackage == null ? -1
+ : getPackageUid(mRequiredVerifierPackage, MATCH_DEBUG_TRIAGED_MISSING,
+ verifierUser.getIdentifier());
+ verificationState.setRequiredVerifierUid(requiredUid);
+ final int installerUid =
+ verificationInfo == null ? -1 : verificationInfo.installerUid;
+ if (!origin.existing && requiredUid != -1
+ && isVerificationEnabled(
+ verifierUser.getIdentifier(), installFlags, installerUid)) {
+ final Intent verification = new Intent(
+ Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
+ verification.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ verification.setDataAndType(Uri.fromFile(new File(origin.resolvedPath)),
+ PACKAGE_MIME_TYPE);
+ verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+
+ // Query all live verifiers based on current user state
+ final List<ResolveInfo> receivers = queryIntentReceiversInternal(verification,
+ PACKAGE_MIME_TYPE, 0, verifierUser.getIdentifier(),
+ false /*allowDynamicSplits*/);
+
+ if (DEBUG_VERIFY) {
+ Slog.d(TAG, "Found " + receivers.size() + " verifiers for intent "
+ + verification.toString() + " with " + pkgLite.verifiers.length
+ + " optional verifiers");
+ }
+
+ verification.putExtra(PackageManager.EXTRA_VERIFICATION_ID, verificationId);
+
+ verification.putExtra(
+ PackageManager.EXTRA_VERIFICATION_INSTALL_FLAGS, installFlags);
+
+ verification.putExtra(
+ PackageManager.EXTRA_VERIFICATION_PACKAGE_NAME, pkgLite.packageName);
+
+ verification.putExtra(
+ PackageManager.EXTRA_VERIFICATION_VERSION_CODE, pkgLite.versionCode);
+
+ verification.putExtra(
+ PackageManager.EXTRA_VERIFICATION_LONG_VERSION_CODE,
+ pkgLite.getLongVersionCode());
+
+ populateInstallerExtras(verification);
+
+ final List<ComponentName> sufficientVerifiers = matchVerifiers(pkgLite,
+ receivers, verificationState);
+
+ DeviceIdleInternal idleController =
+ mInjector.getLocalDeviceIdleController();
+ final long idleDuration = getVerificationTimeout();
+
+ /*
+ * If any sufficient verifiers were listed in the package
+ * manifest, attempt to ask them.
+ */
+ if (sufficientVerifiers != null) {
+ final int n = sufficientVerifiers.size();
+ if (n == 0) {
+ Slog.i(TAG, "Additional verifiers required, but none installed.");
+ ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
+ } else {
+ for (int i = 0; i < n; i++) {
+ final ComponentName verifierComponent = sufficientVerifiers.get(i);
+ idleController.addPowerSaveTempWhitelistApp(Process.myUid(),
+ verifierComponent.getPackageName(), idleDuration,
+ verifierUser.getIdentifier(), false, "package verifier");
+
+ final Intent sufficientIntent = new Intent(verification);
+ sufficientIntent.setComponent(verifierComponent);
+ mContext.sendBroadcastAsUser(sufficientIntent, verifierUser);
+ }
+ }
+ }
+
+ final ComponentName requiredVerifierComponent = matchComponentForVerifier(
+ mRequiredVerifierPackage, receivers);
+ if (mRequiredVerifierPackage != null) {
+ /*
+ * Send the intent to the required verification agent,
+ * but only start the verification timeout after the
+ * target BroadcastReceivers have run.
+ */
+ verification.setComponent(requiredVerifierComponent);
+ idleController.addPowerSaveTempWhitelistApp(Process.myUid(),
+ mRequiredVerifierPackage, idleDuration,
+ verifierUser.getIdentifier(), false, "package verifier");
+ mContext.sendOrderedBroadcastAsUser(verification, verifierUser,
+ android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final Message msg = mHandler
+ .obtainMessage(CHECK_PENDING_VERIFICATION);
+ msg.arg1 = verificationId;
+ mHandler.sendMessageDelayed(msg, getVerificationTimeout());
+ }
+ }, null, 0, null, null);
+
+ Trace.asyncTraceBegin(
+ TRACE_TAG_PACKAGE_MANAGER, "verification", verificationId);
+
+ /*
+ * We don't want the copy to proceed until verification
+ * succeeds.
+ */
+ mVerificationCompleted = false;
+ }
+ } else {
+ verificationState.setVerifierResponse(
+ requiredUid, PackageManager.VERIFICATION_ALLOW);
+ }
+ return ret;
+ }
+
+ void populateInstallerExtras(Intent intent) {
+ intent.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_PACKAGE,
+ installSource.initiatingPackageName);
+
+ if (verificationInfo != null) {
+ if (verificationInfo.originatingUri != null) {
+ intent.putExtra(Intent.EXTRA_ORIGINATING_URI,
+ verificationInfo.originatingUri);
+ }
+ if (verificationInfo.referrer != null) {
+ intent.putExtra(Intent.EXTRA_REFERRER,
+ verificationInfo.referrer);
+ }
+ if (verificationInfo.originatingUid >= 0) {
+ intent.putExtra(Intent.EXTRA_ORIGINATING_UID,
+ verificationInfo.originatingUid);
+ }
+ if (verificationInfo.installerUid >= 0) {
+ intent.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_UID,
+ verificationInfo.installerUid);
+ }
+ }
+ }
+
void setReturnCode(int ret) {
if (mRet == PackageManager.INSTALL_SUCCEEDED) {
// Only update mRet if it was previously INSTALL_SUCCEEDED to
@@ -14323,10 +14530,28 @@ public class PackageManagerService extends IPackageManager.Stub
}
void handleVerificationFinished() {
- mVerificationCompleted = true;
- handleReturnCode();
+ if (!mVerificationCompleted) {
+ mVerificationCompleted = true;
+ if (mIntegrityVerificationCompleted || mRet != INSTALL_SUCCEEDED) {
+ mIntegrityVerificationCompleted = true;
+ handleReturnCode();
+ }
+ // integrity verification still pending.
+ }
+ }
+
+ void handleIntegrityVerificationFinished() {
+ if (!mIntegrityVerificationCompleted) {
+ mIntegrityVerificationCompleted = true;
+ if (mVerificationCompleted || mRet != INSTALL_SUCCEEDED) {
+ mVerificationCompleted = true;
+ handleReturnCode();
+ }
+ // verifier still pending
+ }
}
+
void handleRollbackEnabled() {
// TODO(ruhler) b/112431924: Consider halting the install if we
// couldn't enable rollback.
@@ -14336,7 +14561,8 @@ public class PackageManagerService extends IPackageManager.Stub
@Override
void handleReturnCode() {
- if (mVerificationCompleted && mEnableRollbackCompleted) {
+ if (mVerificationCompleted
+ && mIntegrityVerificationCompleted && mEnableRollbackCompleted) {
if ((installFlags & PackageManager.INSTALL_DRY_RUN) != 0) {
String packageName = "";
try {
@@ -16629,37 +16855,48 @@ public class PackageManagerService extends IPackageManager.Stub
+ " Activities needs verification ...");
int count = 0;
-
+ boolean handlesWebUris = false;
+ final boolean alreadyVerified;
synchronized (mLock) {
// If this is a new install and we see that we've already run verification for this
// package, we have nothing to do: it means the state was restored from backup.
- if (!replacing) {
- IntentFilterVerificationInfo ivi =
- mSettings.getIntentFilterVerificationLPr(packageName);
- if (ivi != null) {
- if (DEBUG_DOMAIN_VERIFICATION) {
- Slog.i(TAG, "Package " + packageName+ " already verified: status="
- + ivi.getStatusString());
- }
- return;
+ final IntentFilterVerificationInfo ivi =
+ mSettings.getIntentFilterVerificationLPr(packageName);
+ alreadyVerified = (ivi != null);
+ if (!replacing && alreadyVerified) {
+ if (DEBUG_DOMAIN_VERIFICATION) {
+ Slog.i(TAG, "Package " + packageName + " already verified: status="
+ + ivi.getStatusString());
}
+ return;
}
- // If any filters need to be verified, then all need to be.
+ // If any filters need to be verified, then all need to be. In addition, we need to
+ // know whether an updating app has any web navigation intent filters, to re-
+ // examine handling policy even if not re-verifying.
boolean needToVerify = false;
for (ParsedActivity a : activities) {
for (ParsedActivityIntentInfo filter : a.intents) {
+ if (filter.handlesWebUris(true)) {
+ handlesWebUris = true;
+ }
if (filter.needsVerification() && needsNetworkVerificationLPr(filter)) {
if (DEBUG_DOMAIN_VERIFICATION) {
Slog.d(TAG,
"Intent filter needs verification, so processing all filters");
}
needToVerify = true;
+ // It's safe to break out here because filter.needsVerification()
+ // can only be true if filter.handlesWebUris(true) returns true, so
+ // we've already noted that.
break;
}
}
}
+ // Note whether this app publishes any web navigation handling support at all,
+ // and whether there are any web-nav filters that fit the profile for running
+ // a verification pass now.
if (needToVerify) {
final int verificationId = mIntentFilterVerificationToken++;
for (ParsedActivity a : activities) {
@@ -16677,13 +16914,23 @@ public class PackageManagerService extends IPackageManager.Stub
}
if (count > 0) {
+ // count > 0 means that we're running a full verification pass
if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG, "Starting " + count
+ " IntentFilter verification" + (count > 1 ? "s" : "")
+ " for userId:" + userId);
mIntentFilterVerifier.startVerifications(userId);
+ } else if (alreadyVerified && handlesWebUris) {
+ // App used autoVerify in the past, no longer does, but still handles web
+ // navigation starts.
+ if (DEBUG_DOMAIN_VERIFICATION) {
+ Slog.d(TAG, "App changed web filters but no longer verifying - resetting policy");
+ }
+ synchronized (mLock) {
+ clearIntentFilterVerificationsLPw(packageName, userId);
+ }
} else {
if (DEBUG_DOMAIN_VERIFICATION) {
- Slog.d(TAG, "No filters or not all autoVerify for " + packageName);
+ Slog.d(TAG, "No web filters or no prior verify policy for " + packageName);
}
}
}
@@ -19261,6 +19508,18 @@ public class PackageManagerService extends IPackageManager.Stub
return ensureSystemPackageName(appPredictionServiceComponentName.getPackageName());
}
+ private @NonNull String[] dropNonSystemPackages(@NonNull String[] pkgNames) {
+ return emptyIfNull(filter(pkgNames, String[]::new, mIsSystemPackage), String.class);
+ }
+
+ private Predicate<String> mIsSystemPackage = (pkgName) -> {
+ if ("android".equals(pkgName)) {
+ return true;
+ }
+ AndroidPackage pkg = mPackages.get(pkgName);
+ return pkg != null && pkg.isSystem();
+ };
+
@Override
public String getSystemCaptionsServicePackageName() {
String flattenedSystemCaptionsServiceComponentName =
@@ -22539,7 +22798,11 @@ public class PackageManagerService extends IPackageManager.Stub
@Override
public @NonNull String[] getKnownPackageNames(int knownPackage, int userId) {
- switch (knownPackage) {
+ return dropNonSystemPackages(getKnownPackageNamesInternal(knownPackage, userId));
+ }
+
+ private String[] getKnownPackageNamesInternal(int knownPackage, int userId) {
+ switch(knownPackage) {
case PackageManagerInternal.PACKAGE_BROWSER:
return new String[]{mPermissionManager.getDefaultBrowser(userId)};
case PackageManagerInternal.PACKAGE_INSTALLER:
@@ -22566,6 +22829,8 @@ public class PackageManagerService extends IPackageManager.Stub
return filterOnlySystemPackages(mAppPredictionServicePackage);
case PackageManagerInternal.PACKAGE_TELEPHONY:
return filterOnlySystemPackages(mTelephonyPackages);
+ case PackageManagerInternal.PACKAGE_COMPANION:
+ return filterOnlySystemPackages("com.android.companiondevicemanager");
default:
return ArrayUtils.emptyArray(String.class);
}
@@ -22626,6 +22891,17 @@ public class PackageManagerService extends IPackageManager.Stub
}
@Override
+ public long getCeDataInode(String packageName, int userId) {
+ synchronized (mLock) {
+ final PackageSetting ps = mSettings.mPackages.get(packageName);
+ if (ps != null) {
+ return ps.getCeDataInode(userId);
+ }
+ return 0;
+ }
+ }
+
+ @Override
public Bundle getSuspendedPackageLauncherExtras(String packageName, int userId) {
synchronized (mLock) {
final PackageSetting ps = mSettings.mPackages.get(packageName);
@@ -23051,16 +23327,10 @@ public class PackageManagerService extends IPackageManager.Stub
}
@Override
- public String getSharedUserIdForPackage(String packageName) {
- synchronized (mLock) {
- return getSharedUserIdForPackageLocked(packageName);
- }
- }
-
- @Override
- public String[] getPackagesForSharedUserId(String sharedUserId, int userId) {
+ @NonNull
+ public String[] getSharedUserPackagesForPackage(String packageName, int userId) {
synchronized (mLock) {
- return getPackagesForSharedUserIdLocked(sharedUserId, userId);
+ return getSharedUserPackagesForPackageLocked(packageName, userId);
}
}
@@ -23293,36 +23563,25 @@ public class PackageManagerService extends IPackageManager.Stub
}
@GuardedBy("mLock")
- private String getSharedUserIdForPackageLocked(String packageName) {
- final PackageSetting ps = mSettings.mPackages.get(packageName);
- return (ps != null && ps.isSharedUser()) ? ps.sharedUser.name : null;
- }
-
- @GuardedBy("mLock")
- private String[] getPackagesForSharedUserIdLocked(String sharedUserId, int userId) {
- try {
- final SharedUserSetting sus = mSettings.getSharedUserLPw(
- sharedUserId, 0, 0, false);
- if (sus == null) {
- return EmptyArray.STRING;
- }
- String[] res = new String[sus.packages.size()];
- final Iterator<PackageSetting> it = sus.packages.iterator();
- int i = 0;
- while (it.hasNext()) {
- PackageSetting ps = it.next();
- if (ps.getInstalled(userId)) {
- res[i++] = ps.name;
- }
- }
- res = ArrayUtils.trimToSize(res, i);
- if (res != null) {
- return res;
+ @NonNull
+ private String[] getSharedUserPackagesForPackageLocked(String packageName, int userId) {
+ final PackageSetting packageSetting = mSettings.mPackages.get(packageName);
+ if (packageSetting == null || !packageSetting.isSharedUser()) {
+ return EmptyArray.STRING;
+ }
+
+ ArraySet<PackageSetting> packages = packageSetting.sharedUser.packages;
+ String[] res = new String[packages.size()];
+ final Iterator<PackageSetting> it = packages.iterator();
+ int i = 0;
+ while (it.hasNext()) {
+ PackageSetting ps = it.next();
+ if (ps.getInstalled(userId)) {
+ res[i++] = ps.name;
}
- } catch (PackageManagerException e) {
- // Should not happen
}
- return EmptyArray.STRING;
+ res = ArrayUtils.trimToSize(res, i);
+ return res != null ? res : EmptyArray.STRING;
}
@Override
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index dfffbd6cabef..10e2780863d8 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -34,6 +34,7 @@ import android.content.IIntentSender;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.ApplicationInfo;
+import android.content.pm.DataLoaderParams;
import android.content.pm.FeatureInfo;
import android.content.pm.IPackageDataObserver;
import android.content.pm.IPackageInstaller;
@@ -136,7 +137,9 @@ class PackageManagerShellCommand extends ShellCommand {
private final static String ART_PROFILE_SNAPSHOT_DEBUG_LOCATION = "/data/misc/profman/";
private static final int DEFAULT_WAIT_MS = 60 * 1000;
- private static final String PM_SHELL_DATALOADER = "com.android.pm.dataloader";
+ private static final String DATA_LOADER_PACKAGE = "android";
+ private static final String DATA_LOADER_CLASS =
+ "com.android.server.pm.PackageManagerShellCommandDataLoader";
final IPackageManager mInterface;
final IPermissionManager mPermissionManager;
@@ -1159,8 +1162,10 @@ class PackageManagerShellCommand extends ShellCommand {
private int runStreamingInstall() throws RemoteException {
final InstallParams params = makeInstallParams();
- if (TextUtils.isEmpty(params.sessionParams.dataLoaderPackageName)) {
- params.sessionParams.setDataLoaderPackageName(PM_SHELL_DATALOADER);
+ if (params.sessionParams.dataLoaderParams == null) {
+ final DataLoaderParams dataLoaderParams = DataLoaderParams.forStreaming(
+ new ComponentName(DATA_LOADER_PACKAGE, DATA_LOADER_CLASS), "");
+ params.sessionParams.setDataLoaderParams(dataLoaderParams);
}
return doRunInstall(params);
}
@@ -1171,7 +1176,7 @@ class PackageManagerShellCommand extends ShellCommand {
private int doRunInstall(final InstallParams params) throws RemoteException {
final PrintWriter pw = getOutPrintWriter();
- final boolean streaming = !TextUtils.isEmpty(params.sessionParams.dataLoaderPackageName);
+ final boolean streaming = params.sessionParams.dataLoaderParams != null;
ArrayList<String> inPaths = getRemainingArgs();
if (inPaths.isEmpty()) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java b/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java
new file mode 100644
index 000000000000..1ee9ab8927bb
--- /dev/null
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm;
+
+import android.annotation.NonNull;
+import android.content.pm.DataLoaderParams;
+import android.content.pm.InstallationFile;
+import android.os.ParcelFileDescriptor;
+import android.service.dataloader.DataLoaderService;
+import android.text.TextUtils;
+import android.util.Slog;
+
+import libcore.io.IoUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.Collection;
+
+/**
+ * Callback data loader for PackageManagerShellCommand installations.
+ */
+public class PackageManagerShellCommandDataLoader extends DataLoaderService {
+ public static final String TAG = "PackageManagerShellCommandDataLoader";
+
+ static class DataLoader implements DataLoaderService.DataLoader {
+ private ParcelFileDescriptor mInFd = null;
+ private FileSystemConnector mConnector = null;
+
+ private static final String STDIN_PATH = "-";
+
+ @Override
+ public boolean onCreate(@NonNull DataLoaderParams dataLoaderParams,
+ @NonNull FileSystemConnector connector) {
+ mConnector = connector;
+ return true;
+ }
+ @Override
+ public boolean onPrepareImage(Collection<InstallationFile> addedFiles,
+ Collection<String> removedFiles) {
+ try {
+ for (InstallationFile fileInfo : addedFiles) {
+ String filePath = new String(fileInfo.getMetadata(), StandardCharsets.UTF_8);
+ if (STDIN_PATH.equals(filePath) || TextUtils.isEmpty(filePath)) {
+ // TODO(b/146080380): add support for STDIN installations.
+ if (mInFd == null) {
+ Slog.e(TAG, "Invalid stdin file descriptor.");
+ return false;
+ }
+ ParcelFileDescriptor inFd = ParcelFileDescriptor.dup(
+ mInFd.getFileDescriptor());
+ mConnector.writeData(fileInfo.getName(), 0, fileInfo.getSize(), inFd);
+ } else {
+ File localFile = new File(filePath);
+ ParcelFileDescriptor incomingFd = null;
+ try {
+ // TODO(b/146080380): open files via callback into shell command.
+ incomingFd = ParcelFileDescriptor.open(localFile,
+ ParcelFileDescriptor.MODE_READ_ONLY);
+ mConnector.writeData(fileInfo.getName(), 0, localFile.length(),
+ incomingFd);
+ } finally {
+ IoUtils.closeQuietly(incomingFd);
+ }
+ }
+ }
+ return true;
+ } catch (IOException e) {
+ return false;
+ }
+ }
+ }
+
+ @Override
+ public DataLoaderService.DataLoader onCreateDataLoader() {
+ return new DataLoader();
+ }
+}
diff --git a/services/core/java/com/android/server/pm/PackageVerificationState.java b/services/core/java/com/android/server/pm/PackageVerificationState.java
index c50bf59f0206..ea7af9031bd0 100644
--- a/services/core/java/com/android/server/pm/PackageVerificationState.java
+++ b/services/core/java/com/android/server/pm/PackageVerificationState.java
@@ -22,18 +22,17 @@ import android.util.SparseBooleanArray;
import com.android.server.pm.PackageManagerService.InstallParams;
/**
- * Tracks the package verification state for a particular package. Each package
- * verification has a required verifier and zero or more sufficient verifiers.
- * Only one of the sufficient verifier list must return affirmative to allow the
- * package to be considered verified. If there are zero sufficient verifiers,
- * then package verification is considered complete.
+ * Tracks the package verification state for a particular package. Each package verification has a
+ * required verifier and zero or more sufficient verifiers. Only one of the sufficient verifier list
+ * must return affirmative to allow the package to be considered verified. If there are zero
+ * sufficient verifiers, then package verification is considered complete.
*/
class PackageVerificationState {
private final InstallParams mParams;
private final SparseBooleanArray mSufficientVerifierUids;
- private final int mRequiredVerifierUid;
+ private int mRequiredVerifierUid;
private boolean mSufficientVerificationComplete;
@@ -45,16 +44,13 @@ class PackageVerificationState {
private boolean mExtendedTimeout;
+ private boolean mIntegrityVerificationComplete;
+
/**
- * Create a new package verification state where {@code requiredVerifierUid}
- * is the user ID for the package that must reply affirmative before things
- * can continue.
- *
- * @param requiredVerifierUid user ID of required package verifier
- * @param args
+ * Create a new package verification state where {@code requiredVerifierUid} is the user ID for
+ * the package that must reply affirmative before things can continue.
*/
- PackageVerificationState(int requiredVerifierUid, InstallParams params) {
- mRequiredVerifierUid = requiredVerifierUid;
+ PackageVerificationState(InstallParams params) {
mParams = params;
mSufficientVerifierUids = new SparseBooleanArray();
mExtendedTimeout = false;
@@ -64,6 +60,11 @@ class PackageVerificationState {
return mParams;
}
+ /** Sets the user ID of the required package verifier. */
+ void setRequiredVerifierUid(int uid) {
+ mRequiredVerifierUid = uid;
+ }
+
/**
* Add a verifier which is added to our sufficient list.
*
@@ -74,8 +75,8 @@ class PackageVerificationState {
}
/**
- * Should be called when a verification is received from an agent so the
- * state of the package verification can be tracked.
+ * Should be called when a verification is received from an agent so the state of the package
+ * verification can be tracked.
*
* @param uid user ID of the verifying agent
* @return {@code true} if the verifying agent actually exists in our list
@@ -114,9 +115,8 @@ class PackageVerificationState {
}
/**
- * Returns whether verification is considered complete. This means that the
- * required verifier and at least one of the sufficient verifiers has
- * returned a positive verification.
+ * Returns whether verification is considered complete. This means that the required verifier
+ * and at least one of the sufficient verifiers has returned a positive verification.
*
* @return {@code true} when verification is considered complete
*/
@@ -133,8 +133,8 @@ class PackageVerificationState {
}
/**
- * Returns whether installation should be allowed. This should only be
- * called after {@link #isVerificationComplete()} returns {@code true}.
+ * Returns whether installation should be allowed. This should only be called after {@link
+ * #isVerificationComplete()} returns {@code true}.
*
* @return {@code true} if installation should be allowed
*/
@@ -150,9 +150,7 @@ class PackageVerificationState {
return true;
}
- /**
- * Extend the timeout for this Package to be verified.
- */
+ /** Extend the timeout for this Package to be verified. */
void extendTimeout() {
if (!mExtendedTimeout) {
mExtendedTimeout = true;
@@ -167,4 +165,16 @@ class PackageVerificationState {
boolean timeoutExtended() {
return mExtendedTimeout;
}
+
+ void setIntegrityVerificationResult(int code) {
+ mIntegrityVerificationComplete = true;
+ }
+
+ boolean isIntegrityVerificationComplete() {
+ return mIntegrityVerificationComplete;
+ }
+
+ boolean areAllVerificationsComplete() {
+ return mIntegrityVerificationComplete && isVerificationComplete();
+ }
}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 6653011b8b22..9642a1a21cf3 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -1249,6 +1249,7 @@ public final class Settings {
return false;
}
ps.clearDomainVerificationStatusForUser(userId);
+ ps.setIntentFilterVerificationInfo(null);
return true;
}
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 688c34fed44f..6c3eb31d22af 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -22,10 +22,12 @@ import android.apex.ApexInfo;
import android.apex.ApexInfoList;
import android.apex.ApexSessionInfo;
import android.apex.ApexSessionParams;
+import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.IIntentReceiver;
import android.content.IIntentSender;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.IntentSender;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller;
@@ -774,6 +776,17 @@ public class StagingManager {
}
}
+ void systemReady() {
+ // Register the receiver of boot completed intent for staging manager.
+ mContext.registerReceiver(new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context ctx, Intent intent) {
+ mPreRebootVerificationHandler.readyToStart();
+ ctx.unregisterReceiver(this);
+ }
+ }, new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
+ }
+
private static class LocalIntentReceiverAsync {
final Consumer<Intent> mConsumer;
@@ -824,6 +837,9 @@ public class StagingManager {
}
private final class PreRebootVerificationHandler extends Handler {
+ // Hold session ids before handler gets ready to do the verification.
+ private IntArray mPendingSessionIds;
+ private boolean mIsReady;
PreRebootVerificationHandler(Looper looper) {
super(looper);
@@ -876,8 +892,26 @@ public class StagingManager {
}
}
+ // Notify the handler that system is ready, and reschedule the pre-reboot verifications.
+ private synchronized void readyToStart() {
+ mIsReady = true;
+ if (mPendingSessionIds != null) {
+ for (int i = 0; i < mPendingSessionIds.size(); i++) {
+ startPreRebootVerification(mPendingSessionIds.get(i));
+ }
+ mPendingSessionIds = null;
+ }
+ }
+
// Method for starting the pre-reboot verification
- private void startPreRebootVerification(int sessionId) {
+ private synchronized void startPreRebootVerification(int sessionId) {
+ if (!mIsReady) {
+ if (mPendingSessionIds == null) {
+ mPendingSessionIds = new IntArray();
+ }
+ mPendingSessionIds.add(sessionId);
+ return;
+ }
obtainMessage(MSG_PRE_REBOOT_VERIFICATION_START, sessionId, 0).sendToTarget();
}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 5fabdb618f44..5854e321665b 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -84,7 +84,6 @@ import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.IntArray;
-import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
@@ -1510,7 +1509,7 @@ public class UserManagerService extends IUserManager.Stub {
public void setUserIcon(@UserIdInt int userId, Bitmap bitmap) {
checkManageUsersPermission("update users");
if (hasUserRestriction(UserManager.DISALLOW_SET_USER_ICON, userId)) {
- Log.w(LOG_TAG, "Cannot set user icon. DISALLOW_SET_USER_ICON is enabled.");
+ Slog.w(LOG_TAG, "Cannot set user icon. DISALLOW_SET_USER_ICON is enabled.");
return;
}
mLocalService.setUserIcon(userId, bitmap);
@@ -1558,7 +1557,7 @@ public class UserManagerService extends IUserManager.Stub {
return ParcelFileDescriptor.open(
new File(iconPath), ParcelFileDescriptor.MODE_READ_ONLY);
} catch (FileNotFoundException e) {
- Log.e(LOG_TAG, "Couldn't find icon file", e);
+ Slog.e(LOG_TAG, "Couldn't find icon file", e);
}
return null;
}
@@ -1656,7 +1655,7 @@ public class UserManagerService extends IUserManager.Stub {
}
}
if (DBG) {
- Log.d(LOG_TAG, "setDevicePolicyUserRestrictions: "
+ Slog.d(LOG_TAG, "setDevicePolicyUserRestrictions: "
+ " originatingUserId=" + originatingUserId
+ " global=" + global + (globalChanged ? " (changed)" : "")
+ " local=" + local + (localChanged ? " (changed)" : "")
@@ -1718,7 +1717,7 @@ public class UserManagerService extends IUserManager.Stub {
@GuardedBy("mRestrictionsLock")
private void invalidateEffectiveUserRestrictionsLR(@UserIdInt int userId) {
if (DBG) {
- Log.d(LOG_TAG, "invalidateEffectiveUserRestrictions userId=" + userId);
+ Slog.d(LOG_TAG, "invalidateEffectiveUserRestrictions userId=" + userId);
}
mCachedEffectiveUserRestrictions.remove(userId);
}
@@ -1940,7 +1939,7 @@ public class UserManagerService extends IUserManager.Stub {
try {
mAppOpsService.setUserRestrictions(effective, mUserRestriconToken, userId);
} catch (RemoteException e) {
- Log.w(LOG_TAG, "Unable to notify AppOpsService of UserRestrictions");
+ Slog.w(LOG_TAG, "Unable to notify AppOpsService of UserRestrictions");
}
}
});
@@ -2012,7 +2011,7 @@ public class UserManagerService extends IUserManager.Stub {
try {
runningUsers = ActivityManager.getService().getRunningUserIds();
} catch (RemoteException e) {
- Log.w(LOG_TAG, "Unable to access ActivityManagerService");
+ Slog.w(LOG_TAG, "Unable to access ActivityManagerService");
return;
}
// Then re-calculate the effective restrictions and apply, only for running users.
@@ -2596,7 +2595,7 @@ public class UserManagerService extends IUserManager.Stub {
}
}
} catch (Resources.NotFoundException e) {
- Log.e(LOG_TAG, "Couldn't find resource: config_defaultFirstUserRestrictions", e);
+ Slog.e(LOG_TAG, "Couldn't find resource: config_defaultFirstUserRestrictions", e);
}
if (!restrictions.isEmpty()) {
@@ -3056,7 +3055,7 @@ public class UserManagerService extends IUserManager.Stub {
? UserManager.DISALLOW_ADD_MANAGED_PROFILE
: UserManager.DISALLOW_ADD_USER;
if (hasUserRestriction(restriction, UserHandle.getCallingUserId())) {
- Log.w(LOG_TAG, "Cannot add user. " + restriction + " is enabled.");
+ Slog.w(LOG_TAG, "Cannot add user. " + restriction + " is enabled.");
return null;
}
return createUserInternalUnchecked(name, userType, flags, parentId,
@@ -3115,7 +3114,7 @@ public class UserManagerService extends IUserManager.Stub {
DeviceStorageMonitorInternal dsm = LocalServices
.getService(DeviceStorageMonitorInternal.class);
if (dsm.isMemoryLow()) {
- Log.w(LOG_TAG, "Cannot add user. Not enough space on disk.");
+ Slog.w(LOG_TAG, "Cannot add user. Not enough space on disk.");
return null;
}
@@ -3138,36 +3137,36 @@ public class UserManagerService extends IUserManager.Stub {
if (parent == null) return null;
}
if (!preCreate && !canAddMoreUsersOfType(userTypeDetails)) {
- Log.e(LOG_TAG, "Cannot add more users of type " + userType
+ Slog.e(LOG_TAG, "Cannot add more users of type " + userType
+ ". Maximum number of that type already exists.");
return null;
}
// TODO(b/142482943): Perhaps let the following code apply to restricted users too.
if (isProfile && !canAddMoreProfilesToUser(userType, parentId, false)) {
- Log.e(LOG_TAG, "Cannot add more profiles of type " + userType
+ Slog.e(LOG_TAG, "Cannot add more profiles of type " + userType
+ " for user " + parentId);
return null;
}
if (!isGuest && !isProfile && !isDemo && isUserLimitReached()) {
// If we're not adding a guest/demo user or a profile and the 'user limit' has
// been reached, cannot add a user.
- Log.e(LOG_TAG, "Cannot add user. Maximum user limit is reached.");
+ Slog.e(LOG_TAG, "Cannot add user. Maximum user limit is reached.");
return null;
}
// In legacy mode, restricted profile's parent can only be the owner user
if (isRestricted && !UserManager.isSplitSystemUser()
&& (parentId != UserHandle.USER_SYSTEM)) {
- Log.w(LOG_TAG, "Cannot add restricted profile - parent user must be owner");
+ Slog.w(LOG_TAG, "Cannot add restricted profile - parent user must be owner");
return null;
}
if (isRestricted && UserManager.isSplitSystemUser()) {
if (parent == null) {
- Log.w(LOG_TAG, "Cannot add restricted profile - parent user must be "
+ Slog.w(LOG_TAG, "Cannot add restricted profile - parent user must be "
+ "specified");
return null;
}
if (!parent.info.canHaveProfile()) {
- Log.w(LOG_TAG, "Cannot add restricted profile - profiles cannot be "
+ Slog.w(LOG_TAG, "Cannot add restricted profile - profiles cannot be "
+ "created for the specified parent user id " + parentId);
return null;
}
@@ -3318,7 +3317,7 @@ public class UserManagerService extends IUserManager.Stub {
+ Integer.toHexString(preCreatedUser.flags) + ").");
return null;
}
- Log.i(LOG_TAG, "Reusing pre-created user " + preCreatedUser.id + " of type "
+ Slog.i(LOG_TAG, "Reusing pre-created user " + preCreatedUser.id + " of type "
+ userType + " and bestowing on it flags " + UserInfo.flagsToString(flags));
preCreatedUser.name = name;
preCreatedUser.flags = newFlags;
@@ -3483,7 +3482,7 @@ public class UserManagerService extends IUserManager.Stub {
checkManageUsersPermission("Only the system can remove users");
if (getUserRestrictions(UserHandle.getCallingUserId()).getBoolean(
UserManager.DISALLOW_REMOVE_USER, false)) {
- Log.w(LOG_TAG, "Cannot remove user. DISALLOW_REMOVE_USER is enabled.");
+ Slog.w(LOG_TAG, "Cannot remove user. DISALLOW_REMOVE_USER is enabled.");
return false;
}
@@ -3535,7 +3534,7 @@ public class UserManagerService extends IUserManager.Stub {
String restriction = isManagedProfile
? UserManager.DISALLOW_REMOVE_MANAGED_PROFILE : UserManager.DISALLOW_REMOVE_USER;
if (getUserRestrictions(UserHandle.getCallingUserId()).getBoolean(restriction, false)) {
- Log.w(LOG_TAG, "Cannot remove user. " + restriction + " is enabled.");
+ Slog.w(LOG_TAG, "Cannot remove user. " + restriction + " is enabled.");
return false;
}
return removeUserUnchecked(userId);
@@ -3553,25 +3552,25 @@ public class UserManagerService extends IUserManager.Stub {
final UserData userData;
int currentUser = ActivityManager.getCurrentUser();
if (currentUser == userId) {
- Log.w(LOG_TAG, "Current user cannot be removed.");
+ Slog.w(LOG_TAG, "Current user cannot be removed.");
return false;
}
synchronized (mPackagesLock) {
synchronized (mUsersLock) {
userData = mUsers.get(userId);
if (userId == UserHandle.USER_SYSTEM) {
- Log.e(LOG_TAG, "System user cannot be removed.");
+ Slog.e(LOG_TAG, "System user cannot be removed.");
return false;
}
if (userData == null) {
- Log.e(LOG_TAG, String.format(
+ Slog.e(LOG_TAG, String.format(
"Cannot remove user %d, invalid user id provided.", userId));
return false;
}
if (mRemovingUserIds.get(userId)) {
- Log.e(LOG_TAG, String.format(
+ Slog.e(LOG_TAG, String.format(
"User %d is already scheduled for removal.", userId));
return false;
}
@@ -3591,7 +3590,7 @@ public class UserManagerService extends IUserManager.Stub {
try {
mAppOpsService.removeUser(userId);
} catch (RemoteException e) {
- Log.w(LOG_TAG, "Unable to notify AppOpsService of removing user.", e);
+ Slog.w(LOG_TAG, "Unable to notify AppOpsService of removing user.", e);
}
// TODO(b/142482943): Send some sort of broadcast for profiles even if non-managed?
@@ -3616,7 +3615,7 @@ public class UserManagerService extends IUserManager.Stub {
}
});
} catch (RemoteException e) {
- Log.w(LOG_TAG, "Failed to stop user during removal.", e);
+ Slog.w(LOG_TAG, "Failed to stop user during removal.", e);
return false;
}
return res == ActivityManager.USER_OP_SUCCESS;
@@ -3828,7 +3827,7 @@ public class UserManagerService extends IUserManager.Stub {
readEntry(restrictions, values, parser);
}
} catch (IOException|XmlPullParserException e) {
- Log.w(LOG_TAG, "Error parsing " + restrictionsFile.getBaseFile(), e);
+ Slog.w(LOG_TAG, "Error parsing " + restrictionsFile.getBaseFile(), e);
} finally {
IoUtils.closeQuietly(fis);
}
@@ -3978,6 +3977,10 @@ public class UserManagerService extends IUserManager.Stub {
@Override
public boolean isUserNameSet(@UserIdInt int userId) {
+ if (!hasManageUsersOrPermission(android.Manifest.permission.GET_ACCOUNTS_PRIVILEGED)) {
+ throw new SecurityException("You need MANAGE_USERS or GET_ACCOUNTS_PRIVILEGED "
+ + "permissions to: get whether user name is set");
+ }
synchronized (mUsersLock) {
final UserInfo userInfo = getUserInfoLU(userId);
return userInfo != null && userInfo.name != null;
@@ -4862,8 +4865,8 @@ public class UserManagerService extends IUserManager.Stub {
}
private static void debug(String message) {
- Log.d(LOG_TAG, message +
- (DBG_WITH_STACKTRACE ? " called at\n" + Debug.getCallers(10, " ") : ""));
+ Slog.d(LOG_TAG, message
+ + (DBG_WITH_STACKTRACE ? " called at\n" + Debug.getCallers(10, " ") : ""));
}
/** @see #getMaxUsersOfTypePerParent(UserTypeDetails) */
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index e0bd0b400940..90bd94781a1e 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -208,13 +208,6 @@ public class UserRestrictionsUtils {
);
/**
- * User restrictions that default to {@code true} for device owners.
- */
- private static final Set<String> DEFAULT_ENABLED_FOR_DEVICE_OWNERS = Sets.newArraySet(
- UserManager.DISALLOW_ADD_MANAGED_PROFILE
- );
-
- /**
* User restrictions that default to {@code true} for managed profile owners.
*
* NB: {@link UserManager#DISALLOW_INSTALL_UNKNOWN_SOURCES} is also set by default but it is
@@ -418,14 +411,6 @@ public class UserRestrictionsUtils {
}
/**
- * Returns the user restrictions that default to {@code true} for device owners.
- * These user restrictions are local, though. ie only for the device owner's user id.
- */
- public static @NonNull Set<String> getDefaultEnabledForDeviceOwner() {
- return DEFAULT_ENABLED_FOR_DEVICE_OWNERS;
- }
-
- /**
* Returns the user restrictions that default to {@code true} for managed profile owners.
*/
public static @NonNull Set<String> getDefaultEnabledForManagedProfiles() {
diff --git a/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java b/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java
index c36b9938a8cd..77bb48eadc41 100644
--- a/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java
+++ b/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java
@@ -67,10 +67,11 @@ import java.util.Set;
* then:
* <ul>
* <li>If {@link #isImplicitWhitelistMode()}, the package is implicitly treated as whitelisted
- * for all users</li>
- * <li>Otherwise, the package is implicitly treated as blacklisted for all non-SYSTEM users</li>
- * <li>Either way, for {@link UserHandle#USER_SYSTEM}, the package will be implicitly
- * whitelisted so that it can be used for local development purposes.</li>
+ * for <b>all</b> users</li>
+ * <li>Otherwise, if {@link #isImplicitWhitelistSystemMode()}, the package is implicitly treated
+ * as whitelisted for the <b>{@link UserHandle#USER_SYSTEM}</b> user (not other users),
+ * which is useful for local development purposes</li>
+ * <li>Otherwise, the package is implicitly treated as blacklisted for all users</li>
* </ul>
*
* <p><b>NOTE:</b> the {@code SystemConfig} state is only updated on first boot or after a system
@@ -86,22 +87,24 @@ class UserSystemPackageInstaller {
* System Property whether to only install system packages on a user if they're whitelisted for
* that user type. These are flags and can be freely combined.
* <ul>
- * <li> 0 (0b0000) - disable whitelist (install all system packages; no logging)</li>
- * <li> 1 (0b0001) - enforce (only install system packages if they are whitelisted)</li>
- * <li> 2 (0b0010) - log (log when a non-whitelisted package is run)</li>
- * <li> 4 (0b0100) - implicitly whitelist any package not mentioned in the whitelist</li>
- * <li> 8 (0b1000) - ignore OTAs (don't install system packages during OTAs)</li>
- * <li>-1 - use device default (as defined in res/res/values/config.xml)</li>
+ * <li> 0 - disable whitelist (install all system packages; no logging)</li>
+ * <li> 1 - enforce (only install system packages if they are whitelisted)</li>
+ * <li> 2 - log (log when a non-whitelisted package is run)</li>
+ * <li> 4 - for all users: implicitly whitelist any package not mentioned in the whitelist</li>
+ * <li> 8 - for SYSTEM: implicitly whitelist any package not mentioned in the whitelist</li>
+ * <li> 16 - ignore OTAs (don't install system packages during OTAs)</li>
+ * <li>-1 - use device default (as defined in res/res/values/config.xml)</li>
* </ul>
* Note: This list must be kept current with config_userTypePackageWhitelistMode in
* frameworks/base/core/res/res/values/config.xml
*/
static final String PACKAGE_WHITELIST_MODE_PROP = "persist.debug.user.package_whitelist_mode";
- static final int USER_TYPE_PACKAGE_WHITELIST_MODE_DISABLE = 0;
- static final int USER_TYPE_PACKAGE_WHITELIST_MODE_ENFORCE = 0b0001;
- static final int USER_TYPE_PACKAGE_WHITELIST_MODE_LOG = 0b0010;
- static final int USER_TYPE_PACKAGE_WHITELIST_MODE_IMPLICIT_WHITELIST = 0b0100;
- static final int USER_TYPE_PACKAGE_WHITELIST_MODE_IGNORE_OTA = 0b1000;
+ static final int USER_TYPE_PACKAGE_WHITELIST_MODE_DISABLE = 0x00;
+ static final int USER_TYPE_PACKAGE_WHITELIST_MODE_ENFORCE = 0x01;
+ static final int USER_TYPE_PACKAGE_WHITELIST_MODE_LOG = 0x02;
+ static final int USER_TYPE_PACKAGE_WHITELIST_MODE_IMPLICIT_WHITELIST = 0x04;
+ static final int USER_TYPE_PACKAGE_WHITELIST_MODE_IMPLICIT_WHITELIST_SYSTEM = 0x08;
+ static final int USER_TYPE_PACKAGE_WHITELIST_MODE_IGNORE_OTA = 0x10;
static final int USER_TYPE_PACKAGE_WHITELIST_MODE_DEVICE_DEFAULT = -1;
@IntDef(flag = true, prefix = "USER_TYPE_PACKAGE_WHITELIST_MODE_", value = {
@@ -281,6 +284,14 @@ class UserSystemPackageInstaller {
return isImplicitWhitelistMode(getWhitelistMode());
}
+ /**
+ * Whether to treat all packages that are not mentioned at all in the whitelist to be implicitly
+ * whitelisted for the SYSTEM user.
+ */
+ boolean isImplicitWhitelistSystemMode() {
+ return isImplicitWhitelistSystemMode(getWhitelistMode());
+ }
+
/** See {@link #isEnforceMode()}. */
private static boolean isEnforceMode(int whitelistMode) {
return (whitelistMode & USER_TYPE_PACKAGE_WHITELIST_MODE_ENFORCE) != 0;
@@ -301,6 +312,11 @@ class UserSystemPackageInstaller {
return (whitelistMode & USER_TYPE_PACKAGE_WHITELIST_MODE_IMPLICIT_WHITELIST) != 0;
}
+ /** See {@link #isImplicitWhitelistSystemMode()}. */
+ private static boolean isImplicitWhitelistSystemMode(int whitelistMode) {
+ return (whitelistMode & USER_TYPE_PACKAGE_WHITELIST_MODE_IMPLICIT_WHITELIST_SYSTEM) != 0;
+ }
+
/** Gets the PackageWhitelistMode for use of {@link #mWhitelistedPackagesForUserTypes}. */
private @PackageWhitelistMode int getWhitelistMode() {
final int runtimeMode = SystemProperties.getInt(
@@ -332,8 +348,8 @@ class UserSystemPackageInstaller {
if (!isEnforceMode(mode)) {
return null;
}
- final boolean isSystemUser = mUm.isUserTypeSubtypeOfSystem(userType);
- final boolean isImplicitWhitelistMode = isImplicitWhitelistMode(mode);
+ final boolean implicitlyWhitelist = isImplicitWhitelistMode(mode)
+ || (isImplicitWhitelistSystemMode(mode) && mUm.isUserTypeSubtypeOfSystem(userType));
final Set<String> whitelistedPackages = getWhitelistedPackagesForUserType(userType);
final Set<String> installPackages = new ArraySet<>();
@@ -343,7 +359,7 @@ class UserSystemPackageInstaller {
return;
}
if (shouldInstallPackage(pkg, mWhitelistedPackagesForUserTypes,
- whitelistedPackages, isImplicitWhitelistMode, isSystemUser)) {
+ whitelistedPackages, implicitlyWhitelist)) {
// Although the whitelist uses manifest names, this function returns packageNames.
installPackages.add(pkg.getPackageName());
}
@@ -360,31 +376,18 @@ class UserSystemPackageInstaller {
* installed. This is only used for overriding the userWhitelist in
* certain situations (based on its keyset).
* @param userWhitelist set of package manifest names that should be installed on this
- * particular user. This must be consistent with userTypeWhitelist, but is
- * passed in separately to avoid repeatedly calculating it from
+ * <b>particular</b> user. This must be consistent with userTypeWhitelist,
+ * but is passed in separately to avoid repeatedly calculating it from
* userTypeWhitelist.
- * @param isImplicitWhitelistMode whether non-mentioned packages are implicitly whitelisted.
- * @param isSystemUser whether the user is USER_SYSTEM (which gets special treatment).
+ * @param implicitlyWhitelist whether non-mentioned packages are implicitly whitelisted.
*/
@VisibleForTesting
static boolean shouldInstallPackage(AndroidPackage sysPkg,
@NonNull ArrayMap<String, Long> userTypeWhitelist,
- @NonNull Set<String> userWhitelist, boolean isImplicitWhitelistMode,
- boolean isSystemUser) {
-
+ @NonNull Set<String> userWhitelist, boolean implicitlyWhitelist) {
final String pkgName = sysPkg.getManifestPackageName();
- boolean install = (isImplicitWhitelistMode && !userTypeWhitelist.containsKey(pkgName))
+ return (implicitlyWhitelist && !userTypeWhitelist.containsKey(pkgName))
|| userWhitelist.contains(pkgName);
-
- // For the purposes of local development, any package that isn't even mentioned in the
- // whitelist at all is implicitly treated as whitelisted for the SYSTEM user.
- if (!install && isSystemUser && !userTypeWhitelist.containsKey(pkgName)) {
- install = true;
- Slog.e(TAG, "System package " + pkgName + " is not mentioned "
- + "in SystemConfig's 'install-in-user-type' but we are "
- + "implicitly treating it as whitelisted for the SYSTEM user.");
- }
- return install;
}
/**
diff --git a/services/core/java/com/android/server/pm/permission/BasePermission.java b/services/core/java/com/android/server/pm/permission/BasePermission.java
index 05545cdbe50a..565a85fd1ac1 100644
--- a/services/core/java/com/android/server/pm/permission/BasePermission.java
+++ b/services/core/java/com/android/server/pm/permission/BasePermission.java
@@ -280,6 +280,9 @@ public final class BasePermission {
public boolean isTelephony() {
return (protectionLevel & PermissionInfo.PROTECTION_FLAG_TELEPHONY) != 0;
}
+ public boolean isCompanion() {
+ return (protectionLevel & PermissionInfo.PROTECTION_FLAG_COMPANION) != 0;
+ }
public void transfer(@NonNull String origPackageName, @NonNull String newPackageName) {
if (!origPackageName.equals(sourcePackageName)) {
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 603b01a17e14..6d6ec250e4cc 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -726,10 +726,12 @@ public final class DefaultPermissionGrantPolicy {
userId, STORAGE_PERMISSIONS);
// TextClassifier Service
- String textClassifierPackageName =
- mContext.getPackageManager().getSystemTextClassifierPackageName();
- if (!TextUtils.isEmpty(textClassifierPackageName)) {
- grantPermissionsToSystemPackage(textClassifierPackageName, userId,
+ final String[] packages = mContext.getPackageManager().getSystemTextClassifierPackages();
+ if (packages.length > 0) {
+ // We have a list of supported system TextClassifier package names, the first one
+ // package is the default system TextClassifier service. Grant permissions to default
+ // TextClassifier Service.
+ grantPermissionsToSystemPackage(packages[0], userId,
COARSE_BACKGROUND_LOCATION_PERMISSIONS, CONTACTS_PERMISSIONS);
}
@@ -998,7 +1000,7 @@ public final class DefaultPermissionGrantPolicy {
private void revokeRuntimePermissions(String packageName, Set<String> permissions,
boolean systemFixed, int userId) {
PackageInfo pkg = getSystemPackageInfo(packageName);
- if (ArrayUtils.isEmpty(pkg.requestedPermissions)) {
+ if (pkg == null || ArrayUtils.isEmpty(pkg.requestedPermissions)) {
return;
}
Set<String> revokablePermissions = new ArraySet<>(Arrays.asList(pkg.requestedPermissions));
diff --git a/services/core/java/com/android/server/pm/permission/OneTimePermissionUserManager.java b/services/core/java/com/android/server/pm/permission/OneTimePermissionUserManager.java
new file mode 100644
index 000000000000..b809951947d9
--- /dev/null
+++ b/services/core/java/com/android/server/pm/permission/OneTimePermissionUserManager.java
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.permission;
+
+import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED;
+
+import android.annotation.NonNull;
+import android.app.ActivityManager;
+import android.app.AlarmManager;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.permission.PermissionControllerManager;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.GuardedBy;
+
+/**
+ * Class that handles one-time permissions for a user
+ */
+public class OneTimePermissionUserManager {
+
+ private static final String LOG_TAG = OneTimePermissionUserManager.class.getSimpleName();
+
+ private final @NonNull Context mContext;
+ private final @NonNull ActivityManager mActivityManager;
+ private final @NonNull AlarmManager mAlarmManager;
+ private final @NonNull PermissionControllerManager mPermissionControllerManager;
+
+ private final Object mLock = new Object();
+
+ /** Maps the uid to the PackageInactivityListener */
+ @GuardedBy("mLock")
+ private final SparseArray<PackageInactivityListener> mListeners = new SparseArray<>();
+
+ OneTimePermissionUserManager(@NonNull Context context) {
+ mContext = context;
+ mActivityManager = context.getSystemService(ActivityManager.class);
+ mAlarmManager = context.getSystemService(AlarmManager.class);
+ mPermissionControllerManager = context.getSystemService(PermissionControllerManager.class);
+ }
+
+ /**
+ * Starts a one-time permission session for a given package. A one-time permission session is
+ * ended if app becomes inactive. Inactivity is defined as the package's uid importance level
+ * staying > importanceToResetTimer for timeoutMillis milliseconds. If the package's uid
+ * importance level goes <= importanceToResetTimer then the timer is reset and doesn't start
+ * until going > importanceToResetTimer.
+ * <p>
+ * When this timeoutMillis is reached if the importance level is <= importanceToKeepSessionAlive
+ * then the session is extended until either the importance goes above
+ * importanceToKeepSessionAlive which will end the session or <= importanceToResetTimer which
+ * will continue the session and reset the timer.
+ * </p>
+ * <p>
+ * Importance levels are defined in {@link android.app.ActivityManager.RunningAppProcessInfo}.
+ * </p>
+ * <p>
+ * Once the session ends PermissionControllerService#onNotifyOneTimePermissionSessionTimeout
+ * is invoked.
+ * </p>
+ * <p>
+ * Note that if there is currently an active session for a package a new one isn't created and
+ * the existing one isn't changed.
+ * </p>
+ * @param packageName The package to start a one-time permission session for
+ * @param timeoutMillis Number of milliseconds for an app to be in an inactive state
+ * @param importanceToResetTimer The least important level to uid must be to reset the timer
+ * @param importanceToKeepSessionAlive The least important level the uid must be to keep the
+ * session alive
+ *
+ * @hide
+ */
+ void startPackageOneTimeSession(@NonNull String packageName, long timeoutMillis,
+ int importanceToResetTimer, int importanceToKeepSessionAlive) {
+ int uid;
+ try {
+ uid = mContext.getPackageManager().getPackageUid(packageName, 0);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(LOG_TAG, "Unknown package name " + packageName, e);
+ return;
+ }
+
+ synchronized (mLock) {
+ PackageInactivityListener listener = mListeners.get(uid);
+ if (listener == null) {
+ listener = new PackageInactivityListener(uid, packageName, timeoutMillis,
+ importanceToResetTimer, importanceToKeepSessionAlive);
+ mListeners.put(uid, listener);
+ }
+ }
+ }
+
+ /**
+ * Stops the one-time permission session for the package. The callback to the end of session is
+ * not invoked. If there is no one-time session for the package then nothing happens.
+ *
+ * @param packageName Package to stop the one-time permission session for
+ */
+ void stopPackageOneTimeSession(@NonNull String packageName) {
+ int uid;
+ try {
+ uid = mContext.getPackageManager().getPackageUid(packageName, 0);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(LOG_TAG, "Unknown package name " + packageName, e);
+ return;
+ }
+
+ synchronized (mLock) {
+ PackageInactivityListener listener = mListeners.get(uid);
+ if (listener != null) {
+ mListeners.remove(uid);
+ listener.cancel();
+ }
+ }
+ }
+
+ /**
+ * A class which watches a package for inactivity and notifies the permission controller when
+ * the package becomes inactive
+ */
+ private class PackageInactivityListener implements AlarmManager.OnAlarmListener {
+
+ private static final long TIMER_INACTIVE = -1;
+
+ private final int mUid;
+ private final @NonNull String mPackageName;
+ private final long mTimeout;
+ private final int mImportanceToResetTimer;
+ private final int mImportanceToKeepSessionAlive;
+
+ private boolean mIsAlarmSet;
+ private boolean mIsFinished;
+
+ private long mTimerStart = TIMER_INACTIVE;
+
+ private final ActivityManager.OnUidImportanceListener mStartTimerListener;
+ private final ActivityManager.OnUidImportanceListener mSessionKillableListener;
+ private final ActivityManager.OnUidImportanceListener mGoneListener;
+
+ private final Object mInnerLock = new Object();
+
+ private PackageInactivityListener(int uid, @NonNull String packageName, long timeout,
+ int importanceToResetTimer, int importanceToKeepSessionAlive) {
+ mUid = uid;
+ mPackageName = packageName;
+ mTimeout = timeout;
+ mImportanceToResetTimer = importanceToResetTimer;
+ mImportanceToKeepSessionAlive = importanceToKeepSessionAlive;
+
+ mStartTimerListener =
+ (changingUid, importance) -> onImportanceChanged(changingUid, importance);
+ mSessionKillableListener =
+ (changingUid, importance) -> onImportanceChanged(changingUid, importance);
+ mGoneListener =
+ (changingUid, importance) -> onImportanceChanged(changingUid, importance);
+
+ mActivityManager.addOnUidImportanceListener(mStartTimerListener,
+ importanceToResetTimer);
+ mActivityManager.addOnUidImportanceListener(mSessionKillableListener,
+ importanceToKeepSessionAlive);
+ mActivityManager.addOnUidImportanceListener(mGoneListener, IMPORTANCE_CACHED);
+
+ onImportanceChanged(mUid, mActivityManager.getPackageImportance(packageName));
+ }
+
+ private void onImportanceChanged(int uid, int importance) {
+ if (uid != mUid) {
+ return;
+ }
+ synchronized (mInnerLock) {
+ if (importance > IMPORTANCE_CACHED) {
+ onPackageInactiveLocked();
+ return;
+ }
+ if (importance > mImportanceToResetTimer) {
+ if (mTimerStart == TIMER_INACTIVE) {
+ mTimerStart = System.currentTimeMillis();
+ }
+ } else {
+ mTimerStart = TIMER_INACTIVE;
+ }
+ if (importance > mImportanceToKeepSessionAlive) {
+ setAlarmLocked();
+ } else {
+ cancelAlarmLocked();
+ }
+ }
+ }
+
+ /**
+ * Stop watching the package for inactivity
+ */
+ private void cancel() {
+ synchronized (mInnerLock) {
+ mIsFinished = true;
+ cancelAlarmLocked();
+ mActivityManager.removeOnUidImportanceListener(mStartTimerListener);
+ mActivityManager.removeOnUidImportanceListener(mSessionKillableListener);
+ mActivityManager.removeOnUidImportanceListener(mGoneListener);
+ }
+ }
+
+ /**
+ * Set the alarm which will callback when the package is inactive
+ */
+ @GuardedBy("mInnerLock")
+ private void setAlarmLocked() {
+ if (mIsAlarmSet) {
+ return;
+ }
+
+ long revokeTime = mTimerStart + mTimeout;
+ if (revokeTime > System.currentTimeMillis()) {
+ mAlarmManager.setExact(AlarmManager.RTC_WAKEUP, revokeTime, LOG_TAG, this,
+ mContext.getMainThreadHandler());
+ mIsAlarmSet = true;
+ } else {
+ mIsAlarmSet = true;
+ onAlarm();
+ }
+ }
+
+ /**
+ * Cancel the alarm
+ */
+ @GuardedBy("mInnerLock")
+ private void cancelAlarmLocked() {
+ if (mIsAlarmSet) {
+ mAlarmManager.cancel(this);
+ mIsAlarmSet = false;
+ }
+ }
+
+ /**
+ * Called when the package is considered inactive. This is the end of the session
+ */
+ @GuardedBy("mInnerLock")
+ private void onPackageInactiveLocked() {
+ if (mIsFinished) {
+ return;
+ }
+ mIsFinished = true;
+ cancelAlarmLocked();
+ mContext.getMainThreadHandler().post(
+ () -> mPermissionControllerManager.notifyOneTimePermissionSessionTimeout(
+ mPackageName));
+ mActivityManager.removeOnUidImportanceListener(mStartTimerListener);
+ mActivityManager.removeOnUidImportanceListener(mSessionKillableListener);
+ mActivityManager.removeOnUidImportanceListener(mGoneListener);
+ synchronized (mLock) {
+ mListeners.remove(mUid);
+ }
+ }
+
+ @Override
+ public void onAlarm() {
+ synchronized (mInnerLock) {
+ if (!mIsAlarmSet) {
+ return;
+ }
+ mIsAlarmSet = false;
+ onPackageInactiveLocked();
+ }
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 8ce1a52afd0c..605f8695f2cf 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -204,6 +204,10 @@ public class PermissionManagerService extends IPermissionManager.Stub {
/** Permission controller: User space permission management */
private PermissionControllerManager mPermissionControllerManager;
+ /** Map of OneTimePermissionUserManagers keyed by userId */
+ private final SparseArray<OneTimePermissionUserManager> mOneTimePermissionUserManagers =
+ new SparseArray<>();
+
/** Default permission policy to provide proper behaviour out-of-the-box */
private final DefaultPermissionGrantPolicy mDefaultPermissionGrantPolicy;
@@ -1579,15 +1583,11 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
// If shared user we just reset the state to which only this app contributed.
- final String sharedUserId =
- mPackageManagerInt.getSharedUserIdForPackage(pkg.getPackageName());
- final String[] pkgNames =
- mPackageManagerInt.getPackagesForSharedUserId(sharedUserId, userId);
- if (pkgNames != null && pkgNames.length > 0) {
+ final String[] pkgNames = mPackageManagerInt.getSharedUserPackagesForPackage(
+ pkg.getPackageName(), userId);
+ if (pkgNames.length > 0) {
boolean used = false;
- final int packageCount = pkgNames.length;
- for (int j = 0; j < packageCount; j++) {
- final String sharedPkgName = pkgNames[j];
+ for (String sharedPkgName : pkgNames) {
final AndroidPackage sharedPkg =
mPackageManagerInt.getPackage(sharedPkgName);
if (sharedPkg != null && !sharedPkg.getPackageName().equals(packageName)
@@ -3009,6 +3009,53 @@ public class PermissionManagerService extends IPermissionManager.Stub {
SystemConfig.getInstance().getSplitPermissions());
}
+ private OneTimePermissionUserManager getOneTimePermissionUserManager(@UserIdInt int userId) {
+ synchronized (mLock) {
+ OneTimePermissionUserManager oneTimePermissionUserManager =
+ mOneTimePermissionUserManagers.get(userId);
+ if (oneTimePermissionUserManager == null) {
+ oneTimePermissionUserManager = new OneTimePermissionUserManager(
+ mContext.createContextAsUser(UserHandle.of(userId), /*flags*/ 0));
+ mOneTimePermissionUserManagers.put(userId, oneTimePermissionUserManager);
+ }
+ return oneTimePermissionUserManager;
+ }
+ }
+
+ @Override
+ public void startOneTimePermissionSession(String packageName, @UserIdInt int userId,
+ long timeoutMillis, int importanceToResetTimer, int importanceToKeepSessionAlive) {
+ mContext.enforceCallingPermission(Manifest.permission.REVOKE_RUNTIME_PERMISSIONS,
+ "Must be able to revoke runtime permissions to register permissions as one time.");
+ mContext.enforceCallingPermission(Manifest.permission.PACKAGE_USAGE_STATS,
+ "Must be able to access usage stats to register permissions as one time.");
+ packageName = Preconditions.checkNotNull(packageName);
+
+ long token = Binder.clearCallingIdentity();
+ try {
+ getOneTimePermissionUserManager(userId).startPackageOneTimeSession(packageName,
+ timeoutMillis, importanceToResetTimer, importanceToKeepSessionAlive);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public void stopOneTimePermissionSession(String packageName, @UserIdInt int userId) {
+ mContext.enforceCallingPermission(Manifest.permission.REVOKE_RUNTIME_PERMISSIONS,
+ "Must be able to revoke runtime permissions to remove permissions as one time.");
+ mContext.enforceCallingPermission(Manifest.permission.PACKAGE_USAGE_STATS,
+ "Must be able to access usage stats to remove permissions as one time.");
+ Preconditions.checkNotNull(packageName);
+
+ long token = Binder.clearCallingIdentity();
+ try {
+ getOneTimePermissionUserManager(userId).stopPackageOneTimeSession(packageName);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
private boolean isNewPlatformPermissionForPackage(String perm, AndroidPackage pkg) {
boolean allowed = false;
final int NP = PackageParser.NEW_PERMISSIONS.length;
@@ -3279,6 +3326,13 @@ public class PermissionManagerService extends IPermissionManager.Stub {
// Special permissions for the system telephony apps.
allowed = true;
}
+ if (!allowed && bp.isCompanion()
+ && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
+ PackageManagerInternal.PACKAGE_COMPANION, UserHandle.USER_SYSTEM),
+ pkg.getPackageName())) {
+ // Special permissions for the system companion device manager.
+ allowed = true;
+ }
}
return allowed;
}
diff --git a/services/core/java/com/android/server/policy/LegacyGlobalActions.java b/services/core/java/com/android/server/policy/LegacyGlobalActions.java
index c779ebf4a995..52714933c8e2 100644
--- a/services/core/java/com/android/server/policy/LegacyGlobalActions.java
+++ b/services/core/java/com/android/server/policy/LegacyGlobalActions.java
@@ -62,7 +62,6 @@ import com.android.internal.globalactions.SinglePressAction;
import com.android.internal.globalactions.ToggleAction;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.util.EmergencyAffordanceManager;
import com.android.internal.widget.LockPatternUtils;
import com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs;
@@ -133,7 +132,7 @@ class LegacyGlobalActions implements DialogInterface.OnDismissListener, DialogIn
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
filter.addAction(Intent.ACTION_SCREEN_OFF);
- filter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
+ filter.addAction(TelephonyManager.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
context.registerReceiver(mBroadcastReceiver, filter);
ConnectivityManager cm = (ConnectivityManager)
@@ -231,7 +230,7 @@ class LegacyGlobalActions implements DialogInterface.OnDismissListener, DialogIn
mIsWaitingForEcmExit = true;
// Launch ECM exit dialog
Intent ecmDialogIntent =
- new Intent(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS, null);
+ new Intent(TelephonyManager.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS, null);
ecmDialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(ecmDialogIntent);
} else {
@@ -741,7 +740,7 @@ class LegacyGlobalActions implements DialogInterface.OnDismissListener, DialogIn
if (!PhoneWindowManager.SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS.equals(reason)) {
mHandler.sendEmptyMessage(MESSAGE_DISMISS);
}
- } else if (TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED.equals(action)) {
+ } else if (TelephonyManager.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED.equals(action)) {
// Airplane mode can be changed after ECM exits if airplane toggle button
// is pressed during ECM mode
if (!(intent.getBooleanExtra("PHONE_IN_ECM_STATE", false)) &&
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java
index b1feb148e5b3..e7269a6d9498 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyService.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java
@@ -353,15 +353,14 @@ public final class PermissionPolicyService extends SystemService {
final PermissionToOpSynchroniser synchroniser = new PermissionToOpSynchroniser(
getUserContext(getContext(), UserHandle.of(userId)));
synchroniser.addPackage(pkg.packageName);
- final String[] sharedPkgNames = packageManagerInternal.getPackagesForSharedUserId(
- pkg.sharedUserId, userId);
- if (sharedPkgNames != null) {
- for (String sharedPkgName : sharedPkgNames) {
- final AndroidPackage sharedPkg = packageManagerInternal
- .getPackage(sharedPkgName);
- if (sharedPkg != null) {
- synchroniser.addPackage(sharedPkg.getPackageName());
- }
+ final String[] sharedPkgNames = packageManagerInternal.getSharedUserPackagesForPackage(
+ pkg.packageName, userId);
+
+ for (String sharedPkgName : sharedPkgNames) {
+ final AndroidPackage sharedPkg = packageManagerInternal
+ .getPackage(sharedPkgName);
+ if (sharedPkg != null) {
+ synchroniser.addPackage(sharedPkg.getPackageName());
}
}
synchroniser.syncPackages();
diff --git a/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java b/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java
index b0f22e4248ba..f3a60185bfb6 100644
--- a/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java
+++ b/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java
@@ -145,7 +145,8 @@ public abstract class SoftRestrictedPermissionPolicy {
}
@Override
public boolean mayAllowExtraAppOp() {
- return !shouldApplyRestriction && hasRequestedLegacyExternalStorage;
+ return !shouldApplyRestriction && hasRequestedLegacyExternalStorage
+ && targetSDK <= Build.VERSION_CODES.Q;
}
@Override
public boolean mayDenyExtraAppOpIfGranted() {
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index f608642f3b81..a2425a349b7c 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -336,13 +336,6 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants {
boolean isAnimatingLw();
/**
- * @return Whether the window can affect SystemUI flags, meaning that SystemUI (system bars,
- * for example) will be affected by the flags specified in this window. This is the
- * case when the surface is on screen but not exiting.
- */
- boolean canAffectSystemUiFlags();
-
- /**
* Is this window considered to be gone for purposes of layout?
*/
boolean isGoneForLayoutLw();
diff --git a/services/core/java/com/android/server/power/TEST_MAPPING b/services/core/java/com/android/server/power/TEST_MAPPING
new file mode 100644
index 000000000000..acf3f79e3626
--- /dev/null
+++ b/services/core/java/com/android/server/power/TEST_MAPPING
@@ -0,0 +1,45 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsBatterySavingTestCases",
+ "options": [
+ {"exclude-annotation": "androidx.test.filters.LargeTest"},
+ {"exclude-annotation": "androidx.test.filters.FlakyTest"}
+ ]
+ },
+ {
+ "name": "FrameworksMockingServicesTests",
+ "options": [
+ {"include-filter": "com.android.server.power"},
+ {"exclude-annotation": "androidx.test.filters.FlakyTest"}
+ ]
+ },
+ {
+ "name": "FrameworksServicesTests",
+ "options": [
+ {"include-filter": "com.android.server.power"},
+ {"exclude-annotation": "androidx.test.filters.FlakyTest"},
+ {
+ "exclude-filter": "com.android.server.power.PowerManagerServiceTest#testWakefulnessAwake_ShouldWakeUpWhenPluggedIn"
+ }
+ ]
+ }
+ ],
+ "postsubmit": [
+ {
+ "name": "CtsBatterySavingTestCases"
+ },
+ {
+ "name": "FrameworksMockingServicesTests",
+ "options": [
+ {"include-filter": "com.android.server.power"}
+ ]
+ },
+ {
+ "name": "FrameworksServicesTests",
+ "options": [
+ {"include-filter": "com.android.server.power"}
+ ]
+ }
+ ]
+}
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index c4522e03b700..392792dbae69 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -511,7 +511,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
- Preconditions.checkNotNull(callback, "callback cannot be null");
+ Objects.requireNonNull(callback, "callback cannot be null");
getOrCreateController(userId).onAddRoleHolder(roleName, packageName, flags,
callback);
@@ -531,7 +531,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
- Preconditions.checkNotNull(callback, "callback cannot be null");
+ Objects.requireNonNull(callback, "callback cannot be null");
getOrCreateController(userId).onRemoveRoleHolder(roleName, packageName, flags,
callback);
@@ -550,7 +550,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
"clearRoleHoldersAsUser");
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
- Preconditions.checkNotNull(callback, "callback cannot be null");
+ Objects.requireNonNull(callback, "callback cannot be null");
getOrCreateController(userId).onClearRoleHolders(roleName, flags, callback);
}
@@ -566,7 +566,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
getContext().enforceCallingOrSelfPermission(Manifest.permission.OBSERVE_ROLE_HOLDERS,
"addOnRoleHoldersChangedListenerAsUser");
- Preconditions.checkNotNull(listener, "listener cannot be null");
+ Objects.requireNonNull(listener, "listener cannot be null");
RemoteCallbackList<IOnRoleHoldersChangedListener> listeners = getOrCreateListeners(
userId);
@@ -584,7 +584,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
getContext().enforceCallingOrSelfPermission(Manifest.permission.OBSERVE_ROLE_HOLDERS,
"removeOnRoleHoldersChangedListenerAsUser");
- Preconditions.checkNotNull(listener, "listener cannot be null");
+ Objects.requireNonNull(listener, "listener cannot be null");
RemoteCallbackList<IOnRoleHoldersChangedListener> listeners = getListeners(userId);
if (listener == null) {
@@ -599,7 +599,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
RoleManager.PERMISSION_MANAGE_ROLES_FROM_CONTROLLER,
"setRoleNamesFromController");
- Preconditions.checkNotNull(roleNames, "roleNames cannot be null");
+ Objects.requireNonNull(roleNames, "roleNames cannot be null");
int userId = UserHandle.getCallingUserId();
getOrCreateUserState(userId).setRoleNames(roleNames);
diff --git a/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java b/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java
index 1123f70b4334..e6e6e23bf714 100644
--- a/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java
+++ b/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java
@@ -16,6 +16,7 @@
package com.android.server.rollback;
+import android.content.pm.PackageManager;
import android.content.rollback.PackageRollbackInfo;
import android.content.rollback.PackageRollbackInfo.RestoreInfo;
import android.os.storage.StorageManager;
@@ -119,11 +120,22 @@ public class AppDataRollbackHelper {
}
try {
- mInstaller.restoreAppDataSnapshot(packageRollbackInfo.getPackageName(), appId, seInfo,
- userId, rollbackId, storageFlags);
+ switch (packageRollbackInfo.getRollbackDataPolicy()) {
+ case PackageManager.RollbackDataPolicy.WIPE:
+ mInstaller.clearAppData(null, packageRollbackInfo.getPackageName(),
+ userId, storageFlags, 0);
+ break;
+ case PackageManager.RollbackDataPolicy.RESTORE:
+ mInstaller.restoreAppDataSnapshot(packageRollbackInfo.getPackageName(), appId,
+ seInfo, userId, rollbackId, storageFlags);
+ break;
+ default:
+ break;
+ }
} catch (InstallerException ie) {
- Slog.e(TAG, "Unable to restore app data snapshot: "
- + packageRollbackInfo.getPackageName(), ie);
+ Slog.e(TAG, "Unable to restore/wipe app data: "
+ + packageRollbackInfo.getPackageName() + " policy="
+ + packageRollbackInfo.getRollbackDataPolicy(), ie);
}
return changedRollback;
@@ -207,13 +219,24 @@ public class AppDataRollbackHelper {
if (hasPendingRestore) {
try {
- mInstaller.restoreAppDataSnapshot(info.getPackageName(), ri.appId,
- ri.seInfo, userId, rollback.info.getRollbackId(),
- Installer.FLAG_STORAGE_CE);
+ switch (info.getRollbackDataPolicy()) {
+ case PackageManager.RollbackDataPolicy.WIPE:
+ mInstaller.clearAppData(null, info.getPackageName(), userId,
+ Installer.FLAG_STORAGE_CE, 0);
+ break;
+ case PackageManager.RollbackDataPolicy.RESTORE:
+ mInstaller.restoreAppDataSnapshot(info.getPackageName(), ri.appId,
+ ri.seInfo, userId, rollback.info.getRollbackId(),
+ Installer.FLAG_STORAGE_CE);
+ break;
+ default:
+ break;
+ }
info.removeRestoreInfo(ri);
} catch (InstallerException ie) {
- Slog.e(TAG, "Unable to restore app data snapshot for: "
- + info.getPackageName(), ie);
+ Slog.e(TAG, "Unable to restore/wipe app data for: "
+ + info.getPackageName() + " policy="
+ + info.getRollbackDataPolicy(), ie);
}
}
}
diff --git a/services/core/java/com/android/server/rollback/Rollback.java b/services/core/java/com/android/server/rollback/Rollback.java
index 6898e1cd1f83..88c1564fdb60 100644
--- a/services/core/java/com/android/server/rollback/Rollback.java
+++ b/services/core/java/com/android/server/rollback/Rollback.java
@@ -306,7 +306,7 @@ class Rollback {
* @return boolean True if the rollback was enabled successfully for the specified package.
*/
boolean enableForPackage(String packageName, long newVersion, long installedVersion,
- boolean isApex, String sourceDir, String[] splitSourceDirs) {
+ boolean isApex, String sourceDir, String[] splitSourceDirs, int rollbackDataPolicy) {
try {
RollbackStore.backupPackageCodePath(this, packageName, sourceDir);
if (!ArrayUtils.isEmpty(splitSourceDirs)) {
@@ -323,7 +323,8 @@ class Rollback {
new VersionedPackage(packageName, newVersion),
new VersionedPackage(packageName, installedVersion),
new IntArray() /* pendingBackups */, new ArrayList<>() /* pendingRestores */,
- isApex, new IntArray(), new SparseLongArray() /* ceSnapshotInodes */);
+ isApex, new IntArray(), new SparseLongArray() /* ceSnapshotInodes */,
+ rollbackDataPolicy);
synchronized (mLock) {
info.getPackages().add(packageRollbackInfo);
@@ -344,10 +345,12 @@ class Rollback {
for (PackageRollbackInfo pkgRollbackInfo : info.getPackages()) {
if (pkgRollbackInfo.getPackageName().equals(packageName)) {
- dataHelper.snapshotAppData(info.getRollbackId(), pkgRollbackInfo, userIds);
-
- RollbackStore.saveRollback(this);
- pkgRollbackInfo.getSnapshottedUsers().addAll(IntArray.wrap(userIds));
+ if (pkgRollbackInfo.getRollbackDataPolicy()
+ == PackageManager.RollbackDataPolicy.RESTORE) {
+ dataHelper.snapshotAppData(info.getRollbackId(), pkgRollbackInfo, userIds);
+ pkgRollbackInfo.getSnapshottedUsers().addAll(IntArray.wrap(userIds));
+ RollbackStore.saveRollback(this);
+ }
break;
}
}
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index 6cdfcff61415..9a65ae6dba4d 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -841,7 +841,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
ApplicationInfo appInfo = pkgInfo.applicationInfo;
return rollback.enableForPackage(packageName, newPackage.versionCode,
pkgInfo.getLongVersionCode(), isApex, appInfo.sourceDir,
- appInfo.splitSourceDirs);
+ appInfo.splitSourceDirs, session.rollbackDataPolicy);
}
@Override
diff --git a/services/core/java/com/android/server/rollback/RollbackStore.java b/services/core/java/com/android/server/rollback/RollbackStore.java
index 550c75442892..df75a29edd79 100644
--- a/services/core/java/com/android/server/rollback/RollbackStore.java
+++ b/services/core/java/com/android/server/rollback/RollbackStore.java
@@ -21,6 +21,7 @@ import static android.os.UserHandle.USER_SYSTEM;
import static com.android.server.rollback.Rollback.rollbackStateFromString;
import android.annotation.NonNull;
+import android.content.pm.PackageManager;
import android.content.pm.VersionedPackage;
import android.content.rollback.PackageRollbackInfo;
import android.content.rollback.PackageRollbackInfo.RestoreInfo;
@@ -345,6 +346,8 @@ class RollbackStore {
json.put("installedUsers", convertToJsonArray(snapshottedUsers));
json.put("ceSnapshotInodes", ceSnapshotInodesToJson(info.getCeSnapshotInodes()));
+ json.put("rollbackDataPolicy", info.getRollbackDataPolicy());
+
return json;
}
@@ -367,8 +370,13 @@ class RollbackStore {
final SparseLongArray ceSnapshotInodes = ceSnapshotInodesFromJson(
json.getJSONArray("ceSnapshotInodes"));
+ // Backward compatibility: no such field for old versions.
+ final int rollbackDataPolicy = json.optInt("rollbackDataPolicy",
+ PackageManager.RollbackDataPolicy.RESTORE);
+
return new PackageRollbackInfo(versionRolledBackFrom, versionRolledBackTo,
- pendingBackups, pendingRestores, isApex, snapshottedUsers, ceSnapshotInodes);
+ pendingBackups, pendingRestores, isApex, snapshottedUsers, ceSnapshotInodes,
+ rollbackDataPolicy);
}
private static JSONArray versionedPackagesToJson(List<VersionedPackage> packages)
diff --git a/services/core/java/com/android/server/security/FileIntegrityService.java b/services/core/java/com/android/server/security/FileIntegrityService.java
new file mode 100644
index 000000000000..0bbb17950856
--- /dev/null
+++ b/services/core/java/com/android/server/security/FileIntegrityService.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.security;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.IBinder;
+import android.os.Process;
+import android.os.SystemProperties;
+import android.security.Credentials;
+import android.security.IFileIntegrityService;
+import android.security.KeyStore;
+import android.util.Slog;
+
+import com.android.server.SystemService;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * A {@link SystemService} that provides file integrity related operations.
+ * @hide
+ */
+public class FileIntegrityService extends SystemService {
+ private static final String TAG = "FileIntegrityService";
+
+ private static CertificateFactory sCertFactory;
+
+ private Collection<X509Certificate> mTrustedCertificates = new ArrayList<X509Certificate>();
+
+ private final IBinder mService = new IFileIntegrityService.Stub() {
+ @Override
+ public boolean isApkVeritySupported() {
+ return SystemProperties.getInt("ro.apk_verity.mode", 0) == 2;
+ }
+
+ @Override
+ public boolean isAppSourceCertificateTrusted(byte[] certificateBytes) {
+ enforceAnyCallingPermissions(
+ android.Manifest.permission.REQUEST_INSTALL_PACKAGES,
+ android.Manifest.permission.INSTALL_PACKAGES);
+ try {
+ if (!isApkVeritySupported()) {
+ return false;
+ }
+
+ return mTrustedCertificates.contains(toCertificate(certificateBytes));
+ } catch (CertificateException e) {
+ Slog.e(TAG, "Failed to convert the certificate: " + e);
+ return false;
+ }
+ }
+
+ private void enforceAnyCallingPermissions(String ...permissions) {
+ for (String permission : permissions) {
+ if (getContext().checkCallingPermission(permission)
+ == PackageManager.PERMISSION_GRANTED) {
+ return;
+ }
+ }
+ throw new SecurityException("Insufficient permission");
+ }
+ };
+
+ public FileIntegrityService(final Context context) {
+ super(context);
+ try {
+ sCertFactory = CertificateFactory.getInstance("X.509");
+ } catch (CertificateException e) {
+ Slog.wtf(TAG, "Cannot get an instance of X.509 certificate factory");
+ }
+ }
+
+ @Override
+ public void onStart() {
+ loadAllCertificates();
+ publishBinderService(Context.FILE_INTEGRITY_SERVICE, mService);
+ }
+
+ private void loadAllCertificates() {
+ // A better alternative to load certificates would be to read from .fs-verity kernel
+ // keyring, which fsverity_init loads to during earlier boot time from the same sources
+ // below. But since the read operation from keyring is not provided in kernel, we need to
+ // duplicate the same loading logic here.
+
+ // Load certificates trusted by the device manufacturer.
+ loadCertificatesFromDirectory("/product/etc/security/fsverity");
+
+ // Load certificates trusted by the device owner.
+ loadCertificatesFromKeystore(KeyStore.getInstance());
+ }
+
+ private void loadCertificatesFromDirectory(String path) {
+ try {
+ File[] files = new File(path).listFiles();
+ if (files == null) {
+ return;
+ }
+
+ for (File cert : files) {
+ collectCertificate(Files.readAllBytes(cert.toPath()));
+ }
+ } catch (IOException e) {
+ Slog.wtf(TAG, "Failed to load fs-verity certificate from " + path, e);
+ }
+ }
+
+ private void loadCertificatesFromKeystore(KeyStore keystore) {
+ for (final String alias : keystore.list(Credentials.APP_SOURCE_CERTIFICATE,
+ Process.FSVERITY_CERT_UID)) {
+ byte[] certificateBytes = keystore.get(Credentials.APP_SOURCE_CERTIFICATE + alias,
+ Process.FSVERITY_CERT_UID, false /* suppressKeyNotFoundWarning */);
+ if (certificateBytes == null) {
+ Slog.w(TAG, "The retrieved fs-verity certificate is null, ignored " + alias);
+ continue;
+ }
+ collectCertificate(certificateBytes);
+ }
+ }
+
+ /**
+ * Tries to convert {@code bytes} into an X.509 certificate and store in memory.
+ * Errors need to be surpressed in order fo the next certificates to still be collected.
+ */
+ private void collectCertificate(@Nullable byte[] bytes) {
+ try {
+ mTrustedCertificates.add(toCertificate(bytes));
+ } catch (CertificateException | AssertionError e) {
+ Slog.e(TAG, "Invalid certificate, ignored: " + e);
+ }
+ }
+
+ /**
+ * Converts byte array into one X.509 certificate. If multiple certificate is defined, ignore
+ * the rest. The rational is to make it harder to smuggle.
+ */
+ @NonNull
+ private static X509Certificate toCertificate(@Nullable byte[] bytes)
+ throws CertificateException {
+ Certificate certificate = sCertFactory.generateCertificate(new ByteArrayInputStream(bytes));
+ if (!(certificate instanceof X509Certificate)) {
+ throw new CertificateException("Expected to contain an X.509 certificate");
+ }
+ return (X509Certificate) certificate;
+ }
+}
diff --git a/services/core/java/com/android/server/slice/SliceManagerService.java b/services/core/java/com/android/server/slice/SliceManagerService.java
index 3b2f32479ed2..7c8c49461e64 100644
--- a/services/core/java/com/android/server/slice/SliceManagerService.java
+++ b/services/core/java/com/android/server/slice/SliceManagerService.java
@@ -106,7 +106,7 @@ public class SliceManagerService extends ISliceManager.Stub {
@VisibleForTesting
SliceManagerService(Context context, Looper looper) {
mContext = context;
- mPackageManagerInternal = Preconditions.checkNotNull(
+ mPackageManagerInternal = Objects.requireNonNull(
LocalServices.getService(PackageManagerInternal.class));
mAppOps = context.getSystemService(AppOpsManager.class);
mAssistUtils = new AssistUtils(context);
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareService.java b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareService.java
index a7cfe1037f11..987c05fd8c9d 100644
--- a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareService.java
+++ b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareService.java
@@ -42,6 +42,7 @@ import com.android.server.SystemService;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
/**
@@ -179,8 +180,8 @@ public class SoundTriggerMiddlewareService extends ISoundTriggerMiddlewareServic
// Permission check.
checkPermissions();
// Input validation.
- Preconditions.checkNotNull(callback);
- Preconditions.checkNotNull(callback.asBinder());
+ Objects.requireNonNull(callback);
+ Objects.requireNonNull(callback.asBinder());
synchronized (this) {
// State validation.
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/ValidationUtil.java b/services/core/java/com/android/server/soundtrigger_middleware/ValidationUtil.java
index 4898e6b59ab2..43047d1ebaaa 100644
--- a/services/core/java/com/android/server/soundtrigger_middleware/ValidationUtil.java
+++ b/services/core/java/com/android/server/soundtrigger_middleware/ValidationUtil.java
@@ -29,6 +29,7 @@ import android.media.soundtrigger_middleware.SoundModelType;
import com.android.internal.util.Preconditions;
+import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -42,7 +43,7 @@ import java.util.regex.Pattern;
*/
public class ValidationUtil {
static void validateUuid(@Nullable String uuid) {
- Preconditions.checkNotNull(uuid);
+ Objects.requireNonNull(uuid);
Matcher matcher = UuidUtil.PATTERN.matcher(uuid);
if (!matcher.matches()) {
throw new IllegalArgumentException(
@@ -55,37 +56,37 @@ public class ValidationUtil {
}
static void validateModel(@Nullable SoundModel model, int expectedType) {
- Preconditions.checkNotNull(model);
+ Objects.requireNonNull(model);
if (model.type != expectedType) {
throw new IllegalArgumentException("Invalid type");
}
validateUuid(model.uuid);
validateUuid(model.vendorUuid);
- Preconditions.checkNotNull(model.data);
+ Objects.requireNonNull(model.data);
}
static void validatePhraseModel(@Nullable PhraseSoundModel model) {
- Preconditions.checkNotNull(model);
+ Objects.requireNonNull(model);
validateModel(model.common, SoundModelType.KEYPHRASE);
- Preconditions.checkNotNull(model.phrases);
+ Objects.requireNonNull(model.phrases);
for (Phrase phrase : model.phrases) {
- Preconditions.checkNotNull(phrase);
+ Objects.requireNonNull(phrase);
if ((phrase.recognitionModes & ~(RecognitionMode.VOICE_TRIGGER
| RecognitionMode.USER_IDENTIFICATION | RecognitionMode.USER_AUTHENTICATION
| RecognitionMode.GENERIC_TRIGGER)) != 0) {
throw new IllegalArgumentException("Invalid recognitionModes");
}
- Preconditions.checkNotNull(phrase.users);
- Preconditions.checkNotNull(phrase.locale);
- Preconditions.checkNotNull(phrase.text);
+ Objects.requireNonNull(phrase.users);
+ Objects.requireNonNull(phrase.locale);
+ Objects.requireNonNull(phrase.text);
}
}
static void validateRecognitionConfig(@Nullable RecognitionConfig config) {
- Preconditions.checkNotNull(config);
- Preconditions.checkNotNull(config.phraseRecognitionExtras);
+ Objects.requireNonNull(config);
+ Objects.requireNonNull(config.phraseRecognitionExtras);
for (PhraseRecognitionExtra extra : config.phraseRecognitionExtras) {
- Preconditions.checkNotNull(extra);
+ Objects.requireNonNull(extra);
if ((extra.recognitionModes & ~(RecognitionMode.VOICE_TRIGGER
| RecognitionMode.USER_IDENTIFICATION | RecognitionMode.USER_AUTHENTICATION
| RecognitionMode.GENERIC_TRIGGER)) != 0) {
@@ -94,15 +95,15 @@ public class ValidationUtil {
if (extra.confidenceLevel < 0 || extra.confidenceLevel > 100) {
throw new IllegalArgumentException("Invalid confidenceLevel");
}
- Preconditions.checkNotNull(extra.levels);
+ Objects.requireNonNull(extra.levels);
for (ConfidenceLevel level : extra.levels) {
- Preconditions.checkNotNull(level);
+ Objects.requireNonNull(level);
if (level.levelPercent < 0 || level.levelPercent > 100) {
throw new IllegalArgumentException("Invalid confidenceLevel");
}
}
}
- Preconditions.checkNotNull(config.data);
+ Objects.requireNonNull(config.data);
}
static void validateModelParameter(int modelParam) {
diff --git a/services/core/java/com/android/server/storage/AppCollector.java b/services/core/java/com/android/server/storage/AppCollector.java
index 0b51f9cc7b7c..ecbc88f36b33 100644
--- a/services/core/java/com/android/server/storage/AppCollector.java
+++ b/services/core/java/com/android/server/storage/AppCollector.java
@@ -59,7 +59,7 @@ public class AppCollector {
* @param volume Volume to check for apps.
*/
public AppCollector(Context context, @NonNull VolumeInfo volume) {
- Preconditions.checkNotNull(volume);
+ Objects.requireNonNull(volume);
mBackgroundHandler = new BackgroundHandler(BackgroundThread.get().getLooper(),
volume,
diff --git a/services/core/java/com/android/server/storage/CacheQuotaStrategy.java b/services/core/java/com/android/server/storage/CacheQuotaStrategy.java
index 60de10c4f32a..aafadf912f7c 100644
--- a/services/core/java/com/android/server/storage/CacheQuotaStrategy.java
+++ b/services/core/java/com/android/server/storage/CacheQuotaStrategy.java
@@ -66,6 +66,7 @@ import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
/**
* CacheQuotaStrategy is a strategy for determining cache quotas using usage stats and foreground
@@ -95,10 +96,10 @@ public class CacheQuotaStrategy implements RemoteCallback.OnResultListener {
public CacheQuotaStrategy(
Context context, UsageStatsManagerInternal usageStatsManager, Installer installer,
ArrayMap<String, SparseLongArray> quotaMap) {
- mContext = Preconditions.checkNotNull(context);
- mUsageStats = Preconditions.checkNotNull(usageStatsManager);
- mInstaller = Preconditions.checkNotNull(installer);
- mQuotaMap = Preconditions.checkNotNull(quotaMap);
+ mContext = Objects.requireNonNull(context);
+ mUsageStats = Objects.requireNonNull(usageStatsManager);
+ mInstaller = Objects.requireNonNull(installer);
+ mQuotaMap = Objects.requireNonNull(quotaMap);
mPreviousValuesFile = new AtomicFile(new File(
new File(Environment.getDataDirectory(), "system"), "cachequota.xml"));
}
diff --git a/services/core/java/com/android/server/storage/StorageSessionController.java b/services/core/java/com/android/server/storage/StorageSessionController.java
index aa3ab63a32bb..f4fb93a0ce23 100644
--- a/services/core/java/com/android/server/storage/StorageSessionController.java
+++ b/services/core/java/com/android/server/storage/StorageSessionController.java
@@ -43,6 +43,7 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Preconditions;
import java.io.FileDescriptor;
+import java.util.Objects;
/**
* Controls storage sessions for users initiated by the {@link StorageManagerService}.
@@ -63,7 +64,7 @@ public final class StorageSessionController {
private volatile boolean mIsResetting;
public StorageSessionController(Context context, boolean isFuseEnabled) {
- mContext = Preconditions.checkNotNull(context);
+ mContext = Objects.requireNonNull(context);
mIsFuseEnabled = isFuseEnabled;
}
diff --git a/services/core/java/com/android/server/storage/StorageUserConnection.java b/services/core/java/com/android/server/storage/StorageUserConnection.java
index 10514ad7edcb..c02ded83586a 100644
--- a/services/core/java/com/android/server/storage/StorageUserConnection.java
+++ b/services/core/java/com/android/server/storage/StorageUserConnection.java
@@ -48,6 +48,7 @@ import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -69,7 +70,7 @@ public final class StorageUserConnection {
@GuardedBy("mLock") private final Map<String, Session> mSessions = new HashMap<>();
public StorageUserConnection(Context context, int userId, StorageSessionController controller) {
- mContext = Preconditions.checkNotNull(context);
+ mContext = Objects.requireNonNull(context);
mUserId = Preconditions.checkArgumentNonnegative(userId);
mSessionController = controller;
}
@@ -83,10 +84,10 @@ public final class StorageUserConnection {
*/
public void startSession(String sessionId, ParcelFileDescriptor pfd, String upperPath,
String lowerPath) throws ExternalStorageServiceException {
- Preconditions.checkNotNull(sessionId);
- Preconditions.checkNotNull(pfd);
- Preconditions.checkNotNull(upperPath);
- Preconditions.checkNotNull(lowerPath);
+ Objects.requireNonNull(sessionId);
+ Objects.requireNonNull(pfd);
+ Objects.requireNonNull(upperPath);
+ Objects.requireNonNull(lowerPath);
prepareRemote();
synchronized (mLock) {
diff --git a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
index 6a986b9da515..5283cc409d38 100644
--- a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
+++ b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
@@ -62,6 +62,7 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayDeque;
import java.util.Map;
+import java.util.Objects;
import java.util.Queue;
/**
@@ -137,7 +138,7 @@ public final class TextClassificationManagerService extends ITextClassifierServi
private TextClassificationConstants mSettings;
private TextClassificationManagerService(Context context) {
- mContext = Preconditions.checkNotNull(context);
+ mContext = Objects.requireNonNull(context);
mLock = new Object();
mSettingsListener = new TextClassifierSettingsListener(mContext);
}
@@ -156,8 +157,8 @@ public final class TextClassificationManagerService extends ITextClassifierServi
@Nullable TextClassificationSessionId sessionId,
TextSelection.Request request, ITextClassifierCallback callback)
throws RemoteException {
- Preconditions.checkNotNull(request);
- Preconditions.checkNotNull(callback);
+ Objects.requireNonNull(request);
+ Objects.requireNonNull(callback);
final int userId = request.getUserId();
validateInput(mContext, request.getCallingPackageName(), userId);
@@ -186,8 +187,8 @@ public final class TextClassificationManagerService extends ITextClassifierServi
@Nullable TextClassificationSessionId sessionId,
TextClassification.Request request, ITextClassifierCallback callback)
throws RemoteException {
- Preconditions.checkNotNull(request);
- Preconditions.checkNotNull(callback);
+ Objects.requireNonNull(request);
+ Objects.requireNonNull(callback);
final int userId = request.getUserId();
validateInput(mContext, request.getCallingPackageName(), userId);
@@ -215,8 +216,8 @@ public final class TextClassificationManagerService extends ITextClassifierServi
@Nullable TextClassificationSessionId sessionId,
TextLinks.Request request, ITextClassifierCallback callback)
throws RemoteException {
- Preconditions.checkNotNull(request);
- Preconditions.checkNotNull(callback);
+ Objects.requireNonNull(request);
+ Objects.requireNonNull(callback);
final int userId = request.getUserId();
validateInput(mContext, request.getCallingPackageName(), userId);
@@ -244,7 +245,7 @@ public final class TextClassificationManagerService extends ITextClassifierServi
public void onSelectionEvent(
@Nullable TextClassificationSessionId sessionId, SelectionEvent event)
throws RemoteException {
- Preconditions.checkNotNull(event);
+ Objects.requireNonNull(event);
final int userId = event.getUserId();
validateInput(mContext, event.getPackageName(), userId);
@@ -268,7 +269,7 @@ public final class TextClassificationManagerService extends ITextClassifierServi
public void onTextClassifierEvent(
@Nullable TextClassificationSessionId sessionId,
TextClassifierEvent event) throws RemoteException {
- Preconditions.checkNotNull(event);
+ Objects.requireNonNull(event);
final String packageName = event.getEventContext() == null
? null
: event.getEventContext().getPackageName();
@@ -299,8 +300,8 @@ public final class TextClassificationManagerService extends ITextClassifierServi
@Nullable TextClassificationSessionId sessionId,
TextLanguage.Request request,
ITextClassifierCallback callback) throws RemoteException {
- Preconditions.checkNotNull(request);
- Preconditions.checkNotNull(callback);
+ Objects.requireNonNull(request);
+ Objects.requireNonNull(callback);
final int userId = request.getUserId();
validateInput(mContext, request.getCallingPackageName(), userId);
@@ -329,8 +330,8 @@ public final class TextClassificationManagerService extends ITextClassifierServi
@Nullable TextClassificationSessionId sessionId,
ConversationActions.Request request,
ITextClassifierCallback callback) throws RemoteException {
- Preconditions.checkNotNull(request);
- Preconditions.checkNotNull(callback);
+ Objects.requireNonNull(request);
+ Objects.requireNonNull(callback);
final int userId = request.getUserId();
validateInput(mContext, request.getCallingPackageName(), userId);
@@ -360,8 +361,8 @@ public final class TextClassificationManagerService extends ITextClassifierServi
public void onCreateTextClassificationSession(
TextClassificationContext classificationContext, TextClassificationSessionId sessionId)
throws RemoteException {
- Preconditions.checkNotNull(sessionId);
- Preconditions.checkNotNull(classificationContext);
+ Objects.requireNonNull(sessionId);
+ Objects.requireNonNull(classificationContext);
final int userId = classificationContext.getUserId();
validateInput(mContext, classificationContext.getPackageName(), userId);
@@ -391,7 +392,7 @@ public final class TextClassificationManagerService extends ITextClassifierServi
@Override
public void onDestroyTextClassificationSession(TextClassificationSessionId sessionId)
throws RemoteException {
- Preconditions.checkNotNull(sessionId);
+ Objects.requireNonNull(sessionId);
synchronized (mLock) {
final int userId = mSessionUserIds.containsKey(sessionId)
@@ -514,7 +515,7 @@ public final class TextClassificationManagerService extends ITextClassifierServi
UserState owningUser, int uid) {
mName = name;
mRequest =
- logOnFailure(Preconditions.checkNotNull(request), "handling pending request");
+ logOnFailure(Objects.requireNonNull(request), "handling pending request");
mOnServiceFailure =
logOnFailure(onServiceFailure, "notifying callback of service failure");
mBinder = binder;
@@ -604,8 +605,8 @@ public final class TextClassificationManagerService extends ITextClassifierServi
private UserState(int userId, Context context, Object lock) {
mUserId = userId;
- mContext = Preconditions.checkNotNull(context);
- mLock = Preconditions.checkNotNull(lock);
+ mContext = Objects.requireNonNull(context);
+ mLock = Objects.requireNonNull(lock);
}
@GuardedBy("mLock")
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
index 1b1ac6d3ed07..c50248d4b402 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
@@ -23,21 +23,19 @@ import android.app.AlarmManager;
import android.app.timedetector.ManualTimeSuggestion;
import android.app.timedetector.PhoneTimeSuggestion;
import android.content.Intent;
-import android.util.ArrayMap;
+import android.telephony.TelephonyManager;
import android.util.LocalLog;
import android.util.Slog;
import android.util.TimestampedValue;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.timezonedetector.ArrayMapWithHistory;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.util.LinkedList;
-import java.util.Map;
/**
* An implementation of TimeDetectorStrategy that passes phone and manual suggestions to
@@ -99,14 +97,12 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
private TimestampedValue<Long> mLastAutoSystemClockTimeSet;
/**
- * A mapping from phoneId to a linked list of time suggestions (the "first" being the latest).
- * We typically expect one or two entries in this Map: devices will have a small number
- * of telephony devices and phoneIds are assumed to be stable. The LinkedList associated with
- * the ID will not exceed {@link #KEEP_SUGGESTION_HISTORY_SIZE} in size.
+ * A mapping from phoneId to a time suggestion. We typically expect one or two mappings: devices
+ * will have a small number of telephony devices and phoneIds are assumed to be stable.
*/
@GuardedBy("this")
- private ArrayMap<Integer, LinkedList<PhoneTimeSuggestion>> mSuggestionByPhoneId =
- new ArrayMap<>();
+ private ArrayMapWithHistory<Integer, PhoneTimeSuggestion> mSuggestionByPhoneId =
+ new ArrayMapWithHistory<>(KEEP_SUGGESTION_HISTORY_SIZE);
@Override
public void initialize(@NonNull Callback callback) {
@@ -179,16 +175,7 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
ipw.println("Phone suggestion history:");
ipw.increaseIndent(); // level 2
- for (Map.Entry<Integer, LinkedList<PhoneTimeSuggestion>> entry
- : mSuggestionByPhoneId.entrySet()) {
- ipw.println("Phone " + entry.getKey());
-
- ipw.increaseIndent(); // level 3
- for (PhoneTimeSuggestion suggestion : entry.getValue()) {
- ipw.println(suggestion);
- }
- ipw.decreaseIndent(); // level 3
- }
+ mSuggestionByPhoneId.dump(ipw);
ipw.decreaseIndent(); // level 2
ipw.decreaseIndent(); // level 1
@@ -205,20 +192,10 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
}
int phoneId = suggestion.getPhoneId();
- LinkedList<PhoneTimeSuggestion> phoneSuggestions = mSuggestionByPhoneId.get(phoneId);
- if (phoneSuggestions == null) {
- // The first time we've seen this phoneId.
- phoneSuggestions = new LinkedList<>();
- mSuggestionByPhoneId.put(phoneId, phoneSuggestions);
- } else if (phoneSuggestions.isEmpty()) {
- Slog.w(LOG_TAG, "Suggestions unexpectedly empty when adding suggestion=" + suggestion);
- }
-
- if (!phoneSuggestions.isEmpty()) {
+ PhoneTimeSuggestion previousSuggestion = mSuggestionByPhoneId.get(phoneId);
+ if (previousSuggestion != null) {
// We can log / discard suggestions with obvious issues with the reference time clock.
- PhoneTimeSuggestion previousSuggestion = phoneSuggestions.getFirst();
- if (previousSuggestion == null
- || previousSuggestion.getUtcTime() == null
+ if (previousSuggestion.getUtcTime() == null
|| previousSuggestion.getUtcTime().getValue() == null) {
// This should be impossible given we only store validated suggestions.
Slog.w(LOG_TAG, "Previous suggestion is null or has a null time."
@@ -240,10 +217,7 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
}
// Store the latest suggestion.
- phoneSuggestions.addFirst(suggestion);
- if (phoneSuggestions.size() > KEEP_SUGGESTION_HISTORY_SIZE) {
- phoneSuggestions.removeLast();
- }
+ mSuggestionByPhoneId.put(phoneId, suggestion);
return true;
}
@@ -331,15 +305,7 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
int bestScore = PHONE_INVALID_SCORE;
for (int i = 0; i < mSuggestionByPhoneId.size(); i++) {
Integer phoneId = mSuggestionByPhoneId.keyAt(i);
- LinkedList<PhoneTimeSuggestion> phoneSuggestions = mSuggestionByPhoneId.valueAt(i);
- if (phoneSuggestions == null) {
- // Unexpected - map is missing a value.
- Slog.w(LOG_TAG, "Suggestions unexpectedly missing for phoneId."
- + " phoneId=" + phoneId);
- continue;
- }
-
- PhoneTimeSuggestion candidateSuggestion = phoneSuggestions.getFirst();
+ PhoneTimeSuggestion candidateSuggestion = mSuggestionByPhoneId.valueAt(i);
if (candidateSuggestion == null) {
// Unexpected - null suggestions should never be stored.
Slog.w(LOG_TAG, "Latest suggestion unexpectedly null for phoneId."
@@ -512,12 +478,12 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
mLastAutoSystemClockTimeSet = null;
}
- // Historically, Android has sent a TelephonyIntents.ACTION_NETWORK_SET_TIME broadcast only
+ // Historically, Android has sent a TelephonyManager.ACTION_NETWORK_SET_TIME broadcast only
// when setting the time using NITZ.
if (origin == ORIGIN_PHONE) {
// Send a broadcast that telephony code used to send after setting the clock.
// TODO Remove this broadcast as soon as there are no remaining listeners.
- Intent intent = new Intent(TelephonyIntents.ACTION_NETWORK_SET_TIME);
+ Intent intent = new Intent(TelephonyManager.ACTION_NETWORK_SET_TIME);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
intent.putExtra("time", newSystemClockMillis);
mCallback.sendStickyBroadcast(intent);
@@ -540,10 +506,6 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
@VisibleForTesting
@Nullable
public synchronized PhoneTimeSuggestion getLatestPhoneSuggestion(int phoneId) {
- LinkedList<PhoneTimeSuggestion> suggestions = mSuggestionByPhoneId.get(phoneId);
- if (suggestions == null) {
- return null;
- }
- return suggestions.getFirst();
+ return mSuggestionByPhoneId.get(phoneId);
}
}
diff --git a/services/core/java/com/android/server/timezonedetector/ArrayMapWithHistory.java b/services/core/java/com/android/server/timezonedetector/ArrayMapWithHistory.java
new file mode 100644
index 000000000000..3274f0e1112f
--- /dev/null
+++ b/services/core/java/com/android/server/timezonedetector/ArrayMapWithHistory.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.timezonedetector;
+
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.IndentingPrintWriter;
+
+/**
+ * A partial decorator for {@link ArrayMap} that records historic values for each mapping for
+ * debugging later with {@link #dump(IndentingPrintWriter)}.
+ *
+ * <p>This class is only intended for use in {@link TimeZoneDetectorStrategy} and
+ * {@link com.android.server.timedetector.TimeDetectorStrategy} so only provides the parts of the
+ * {@link ArrayMap} API needed. If it is ever extended to include deletion methods like
+ * {@link ArrayMap#remove(Object)} some thought would need to be given to the correct
+ * {@link ArrayMap#containsKey(Object)} behavior for the history. Like {@link ArrayMap}, it is not
+ * thread-safe.
+ *
+ * @param <K> the type of the key
+ * @param <V> the type of the value
+ */
+public final class ArrayMapWithHistory<K, V> {
+ private static final String TAG = "ArrayMapWithHistory";
+
+ /** The size the linked list against each value is allowed to grow to. */
+ private final int mMaxHistorySize;
+
+ @Nullable
+ private ArrayMap<K, ReferenceWithHistory<V>> mMap;
+
+ /**
+ * Creates an instance that records, at most, the specified number of values against each key.
+ */
+ public ArrayMapWithHistory(@IntRange(from = 1) int maxHistorySize) {
+ if (maxHistorySize < 1) {
+ throw new IllegalArgumentException("maxHistorySize < 1: " + maxHistorySize);
+ }
+ mMaxHistorySize = maxHistorySize;
+ }
+
+ /**
+ * See {@link ArrayMap#put(K, V)}.
+ */
+ @Nullable
+ public V put(@Nullable K key, @Nullable V value) {
+ if (mMap == null) {
+ mMap = new ArrayMap<>();
+ }
+
+ ReferenceWithHistory<V> valueHolder = mMap.get(key);
+ if (valueHolder == null) {
+ valueHolder = new ReferenceWithHistory<>(mMaxHistorySize);
+ mMap.put(key, valueHolder);
+ } else if (valueHolder.getHistoryCount() == 0) {
+ Log.w(TAG, "History for \"" + key + "\" was unexpectedly empty");
+ }
+
+ return valueHolder.set(value);
+ }
+
+ /**
+ * See {@link ArrayMap#get(Object)}.
+ */
+ @Nullable
+ public V get(@Nullable Object key) {
+ if (mMap == null) {
+ return null;
+ }
+
+ ReferenceWithHistory<V> valueHolder = mMap.get(key);
+ if (valueHolder == null) {
+ return null;
+ } else if (valueHolder.getHistoryCount() == 0) {
+ Log.w(TAG, "History for \"" + key + "\" was unexpectedly empty");
+ }
+ return valueHolder.get();
+ }
+
+ /**
+ * See {@link ArrayMap#size()}.
+ */
+ public int size() {
+ return mMap == null ? 0 : mMap.size();
+ }
+
+ /**
+ * See {@link ArrayMap#keyAt(int)}.
+ */
+ @Nullable
+ public K keyAt(int index) {
+ if (mMap == null) {
+ throw new ArrayIndexOutOfBoundsException(index);
+ }
+ return mMap.keyAt(index);
+ }
+
+ /**
+ * See {@link ArrayMap#valueAt(int)}.
+ */
+ @Nullable
+ public V valueAt(int index) {
+ if (mMap == null) {
+ throw new ArrayIndexOutOfBoundsException(index);
+ }
+
+ ReferenceWithHistory<V> valueHolder = mMap.valueAt(index);
+ if (valueHolder == null || valueHolder.getHistoryCount() == 0) {
+ Log.w(TAG, "valueAt(" + index + ") was unexpectedly null or empty");
+ return null;
+ }
+ return valueHolder.get();
+ }
+
+ /**
+ * Dumps the content of the map, including historic values, using the supplied writer.
+ */
+ public void dump(@NonNull IndentingPrintWriter ipw) {
+ if (mMap == null) {
+ ipw.println("{Empty}");
+ } else {
+ for (int i = 0; i < mMap.size(); i++) {
+ ipw.println("key idx: " + i + "=" + mMap.keyAt(i));
+ ReferenceWithHistory<V> value = mMap.valueAt(i);
+ ipw.println("val idx: " + i + "=" + value);
+ ipw.increaseIndent();
+
+ ipw.println("Historic values=[");
+ ipw.increaseIndent();
+ value.dump(ipw);
+ ipw.decreaseIndent();
+ ipw.println("]");
+
+ ipw.decreaseIndent();
+ }
+ }
+ ipw.flush();
+ }
+
+ /**
+ * Internal method intended for tests that returns the number of historic values associated with
+ * the supplied key currently. If there is no mapping for the key then {@code 0} is returned.
+ */
+ @VisibleForTesting
+ public int getHistoryCountForKeyForTests(@Nullable K key) {
+ if (mMap == null) {
+ return 0;
+ }
+
+ ReferenceWithHistory<V> valueHolder = mMap.get(key);
+ if (valueHolder == null) {
+ return 0;
+ } else if (valueHolder.getHistoryCount() == 0) {
+ Log.w(TAG, "getValuesSizeForKeyForTests(\"" + key + "\") was unexpectedly empty");
+ return 0;
+ } else {
+ return valueHolder.getHistoryCount();
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "ArrayMapWithHistory{"
+ + "mHistorySize=" + mMaxHistorySize
+ + ", mMap=" + mMap
+ + '}';
+ }
+}
diff --git a/services/core/java/com/android/server/timezonedetector/ReferenceWithHistory.java b/services/core/java/com/android/server/timezonedetector/ReferenceWithHistory.java
new file mode 100644
index 000000000000..8bd10359bc6c
--- /dev/null
+++ b/services/core/java/com/android/server/timezonedetector/ReferenceWithHistory.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.timezonedetector;
+
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import com.android.internal.util.IndentingPrintWriter;
+
+import java.util.LinkedList;
+
+/**
+ * A class that behaves like the following definition, except it stores the history of values set
+ * that can be dumped for debugging with {@link #dump(IndentingPrintWriter)}.
+ *
+ * <pre>{@code
+ * private static class Ref<V> {
+ * private V mValue;
+ *
+ * public V get() {
+ * return mValue;
+ * }
+ *
+ * public V set(V value) {
+ * V previous = mValue;
+ * mValue = value;
+ * return previous;
+ * }
+ * }
+ * }</pre>
+ *
+ * <p>This class is not thread-safe.
+ *
+ * @param <V> the type of the value
+ */
+public final class ReferenceWithHistory<V> {
+
+ /** The size the history linked list is allowed to grow to. */
+ private final int mMaxHistorySize;
+
+ @Nullable
+ private LinkedList<V> mValues;
+
+ /**
+ * Creates an instance that records, at most, the specified number of values.
+ */
+ public ReferenceWithHistory(@IntRange(from = 1) int maxHistorySize) {
+ if (maxHistorySize < 1) {
+ throw new IllegalArgumentException("maxHistorySize < 1: " + maxHistorySize);
+ }
+ this.mMaxHistorySize = maxHistorySize;
+ }
+
+ /** Returns the current value, or {@code null} if it has never been set. */
+ @Nullable
+ public V get() {
+ return (mValues == null || mValues.isEmpty()) ? null : mValues.getFirst();
+ }
+
+ /** Sets the current value. Returns the previous value, or {@code null}. */
+ @Nullable
+ public V set(@Nullable V newValue) {
+ if (mValues == null) {
+ mValues = new LinkedList<>();
+ }
+
+ V previous = get();
+
+ mValues.addFirst(newValue);
+ if (mValues.size() > mMaxHistorySize) {
+ mValues.removeLast();
+ }
+ return previous;
+ }
+
+ /**
+ * Dumps the content of the reference, including historic values, using the supplied writer.
+ */
+ public void dump(@NonNull IndentingPrintWriter ipw) {
+ if (mValues == null) {
+ ipw.println("{Empty}");
+ } else {
+ int i = 0;
+ for (V value : mValues) {
+ ipw.println(i + ": " + value);
+ i++;
+ }
+ }
+ ipw.flush();
+ }
+
+ /**
+ * Returns the number of historic entries stored currently.
+ */
+ public int getHistoryCount() {
+ return mValues == null ? 0 : mValues.size();
+ }
+
+ @Override
+ public String toString() {
+ return String.valueOf(get());
+ }
+}
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java
index b4d80531be54..b4a439991dd9 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java
@@ -27,7 +27,6 @@ import android.annotation.Nullable;
import android.app.timezonedetector.ManualTimeZoneSuggestion;
import android.app.timezonedetector.PhoneTimeZoneSuggestion;
import android.content.Context;
-import android.util.ArrayMap;
import android.util.LocalLog;
import android.util.Slog;
@@ -38,8 +37,6 @@ import com.android.internal.util.IndentingPrintWriter;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.util.LinkedList;
-import java.util.Map;
import java.util.Objects;
/**
@@ -175,14 +172,13 @@ public class TimeZoneDetectorStrategy {
private final LocalLog mTimeZoneChangesLog = new LocalLog(30, false /* useLocalTimestamps */);
/**
- * A mapping from phoneId to a linked list of phone time zone suggestions (the head being the
- * latest). We typically expect one or two entries in this Map: devices will have a small number
- * of telephony devices and phoneIds are assumed to be stable. The LinkedList associated with
- * the ID will not exceed {@link #KEEP_PHONE_SUGGESTION_HISTORY_SIZE} in size.
+ * A mapping from phoneId to a phone time zone suggestion. We typically expect one or two
+ * mappings: devices will have a small number of telephony devices and phoneIds are assumed to
+ * be stable.
*/
@GuardedBy("this")
- private ArrayMap<Integer, LinkedList<QualifiedPhoneTimeZoneSuggestion>> mSuggestionByPhoneId =
- new ArrayMap<>();
+ private ArrayMapWithHistory<Integer, QualifiedPhoneTimeZoneSuggestion> mSuggestionByPhoneId =
+ new ArrayMapWithHistory<>(KEEP_PHONE_SUGGESTION_HISTORY_SIZE);
/**
* Creates a new instance of {@link TimeZoneDetectorStrategy}.
@@ -226,16 +222,7 @@ public class TimeZoneDetectorStrategy {
new QualifiedPhoneTimeZoneSuggestion(suggestion, score);
// Store the suggestion against the correct phoneId.
- LinkedList<QualifiedPhoneTimeZoneSuggestion> suggestions =
- mSuggestionByPhoneId.get(suggestion.getPhoneId());
- if (suggestions == null) {
- suggestions = new LinkedList<>();
- mSuggestionByPhoneId.put(suggestion.getPhoneId(), suggestions);
- }
- suggestions.addFirst(scoredSuggestion);
- if (suggestions.size() > KEEP_PHONE_SUGGESTION_HISTORY_SIZE) {
- suggestions.removeLast();
- }
+ mSuggestionByPhoneId.put(suggestion.getPhoneId(), scoredSuggestion);
// Now perform auto time zone detection. The new suggestion may be used to modify the time
// zone setting.
@@ -385,7 +372,7 @@ public class TimeZoneDetectorStrategy {
}
private static boolean isOriginAutomatic(@Origin int origin) {
- return origin == ORIGIN_PHONE;
+ return origin != ORIGIN_MANUAL;
}
@GuardedBy("this")
@@ -398,13 +385,7 @@ public class TimeZoneDetectorStrategy {
// rate-limit so age is not a strong indicator of confidence. Instead, the callers are
// expected to withdraw suggestions they no longer have confidence in.
for (int i = 0; i < mSuggestionByPhoneId.size(); i++) {
- LinkedList<QualifiedPhoneTimeZoneSuggestion> phoneSuggestions =
- mSuggestionByPhoneId.valueAt(i);
- if (phoneSuggestions == null) {
- // Unexpected
- continue;
- }
- QualifiedPhoneTimeZoneSuggestion candidateSuggestion = phoneSuggestions.getFirst();
+ QualifiedPhoneTimeZoneSuggestion candidateSuggestion = mSuggestionByPhoneId.valueAt(i);
if (candidateSuggestion == null) {
// Unexpected
continue;
@@ -456,15 +437,17 @@ public class TimeZoneDetectorStrategy {
* Dumps internal state such as field values.
*/
public synchronized void dumpState(PrintWriter pw, String[] args) {
- pw.println("TimeZoneDetectorStrategy:");
- pw.println("mCallback.isTimeZoneDetectionEnabled()="
+ IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
+ ipw.println("TimeZoneDetectorStrategy:");
+
+ ipw.increaseIndent(); // level 1
+ ipw.println("mCallback.isTimeZoneDetectionEnabled()="
+ mCallback.isAutoTimeZoneDetectionEnabled());
- pw.println("mCallback.isDeviceTimeZoneInitialized()="
+ ipw.println("mCallback.isDeviceTimeZoneInitialized()="
+ mCallback.isDeviceTimeZoneInitialized());
- pw.println("mCallback.getDeviceTimeZone()="
+ ipw.println("mCallback.getDeviceTimeZone()="
+ mCallback.getDeviceTimeZone());
- IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
ipw.println("Time zone change log:");
ipw.increaseIndent(); // level 2
mTimeZoneChangesLog.dump(ipw);
@@ -472,21 +455,10 @@ public class TimeZoneDetectorStrategy {
ipw.println("Phone suggestion history:");
ipw.increaseIndent(); // level 2
- for (Map.Entry<Integer, LinkedList<QualifiedPhoneTimeZoneSuggestion>> entry
- : mSuggestionByPhoneId.entrySet()) {
- ipw.println("Phone " + entry.getKey());
-
- ipw.increaseIndent(); // level 3
- for (QualifiedPhoneTimeZoneSuggestion suggestion : entry.getValue()) {
- ipw.println(suggestion);
- }
- ipw.decreaseIndent(); // level 3
- }
+ mSuggestionByPhoneId.dump(ipw);
ipw.decreaseIndent(); // level 2
ipw.decreaseIndent(); // level 1
ipw.flush();
-
- pw.flush();
}
/**
@@ -494,12 +466,7 @@ public class TimeZoneDetectorStrategy {
*/
@VisibleForTesting
public synchronized QualifiedPhoneTimeZoneSuggestion getLatestPhoneSuggestion(int phoneId) {
- LinkedList<QualifiedPhoneTimeZoneSuggestion> suggestions =
- mSuggestionByPhoneId.get(phoneId);
- if (suggestions == null) {
- return null;
- }
- return suggestions.getFirst();
+ return mSuggestionByPhoneId.get(phoneId);
}
/**
diff --git a/services/core/java/com/android/server/uri/UriGrantsManagerService.java b/services/core/java/com/android/server/uri/UriGrantsManagerService.java
index 04839e1bd6db..e3b7c0aae507 100644
--- a/services/core/java/com/android/server/uri/UriGrantsManagerService.java
+++ b/services/core/java/com/android/server/uri/UriGrantsManagerService.java
@@ -103,6 +103,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
+import java.util.Objects;
/** Manages uri grants. */
public class UriGrantsManagerService extends IUriGrantsManager.Stub {
@@ -215,7 +216,7 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub {
public ParceledListSlice<android.content.UriPermission> getUriPermissions(
String packageName, boolean incoming, boolean persistedOnly) {
enforceNotIsolatedCaller("getUriPermissions");
- Preconditions.checkNotNull(packageName, "packageName");
+ Objects.requireNonNull(packageName, "packageName");
final int callingUid = Binder.getCallingUid();
final int callingUserId = UserHandle.getUserId(callingUid);
diff --git a/services/core/java/com/android/server/utils/quota/Categorizer.java b/services/core/java/com/android/server/utils/quota/Categorizer.java
new file mode 100644
index 000000000000..0a45dab87579
--- /dev/null
+++ b/services/core/java/com/android/server/utils/quota/Categorizer.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.utils.quota;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+/**
+ * Identifies the {@link Category} that each UPTC belongs in.
+ *
+ * @see Uptc
+ */
+public interface Categorizer {
+ /** A {@link Categorizer} that always returns {@link Category.SINGLE_CATEGORY}. */
+ Categorizer SINGLE_CATEGORIZER = (userId, packageName, tag) -> Category.SINGLE_CATEGORY;
+
+ /**
+ * Return the {@link Category} that this UPTC belongs to.
+ *
+ * @see Uptc
+ */
+ @NonNull
+ Category getCategory(int userId, @NonNull String packageName, @Nullable String tag);
+}
diff --git a/services/core/java/com/android/server/utils/quota/Category.java b/services/core/java/com/android/server/utils/quota/Category.java
new file mode 100644
index 000000000000..933c1498be99
--- /dev/null
+++ b/services/core/java/com/android/server/utils/quota/Category.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.utils.quota;
+
+import android.annotation.NonNull;
+import android.util.proto.ProtoOutputStream;
+import android.util.quota.CategoryProto;
+
+/**
+ * A category as defined by the (system) client. Categories are used to put UPTCs in different
+ * groups. A sample group of Categories could be the various App Standby buckets or foreground vs
+ * background.
+ *
+ * @see Uptc
+ */
+public final class Category {
+ /**
+ * A {@link Category} that can be used if every app should be treated the same (given the same
+ * category).
+ */
+ public static final Category SINGLE_CATEGORY = new Category("SINGLE");
+
+ @NonNull
+ private final String mName;
+
+ private final int mHash;
+
+ /** Construct a new Category with the specified name. */
+ public Category(@NonNull String name) {
+ mName = name;
+ mHash = name.hashCode();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+ if (other instanceof Category) {
+ return this.mName.equals(((Category) other).mName);
+ }
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public int hashCode() {
+ return mHash;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String toString() {
+ return "Category{" + mName + "}";
+ }
+
+ void dumpDebug(ProtoOutputStream proto, long fieldId) {
+ final long token = proto.start(fieldId);
+ proto.write(CategoryProto.NAME, mName);
+ proto.end(token);
+ }
+}
diff --git a/services/core/java/com/android/server/utils/quota/QuotaChangeListener.java b/services/core/java/com/android/server/utils/quota/QuotaChangeListener.java
new file mode 100644
index 000000000000..b6730505f6f7
--- /dev/null
+++ b/services/core/java/com/android/server/utils/quota/QuotaChangeListener.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.utils.quota;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+/**
+ * Listener that is notified when a UPTC goes in and out of quota.
+ *
+ * @see Uptc
+ */
+public interface QuotaChangeListener {
+ /**
+ * Called when the UPTC reaches its quota or comes back into quota.
+ *
+ * @see Uptc
+ */
+ void onQuotaStateChanged(int userId, @NonNull String packageName, @Nullable String tag);
+}
diff --git a/services/core/java/com/android/server/utils/quota/QuotaTracker.java b/services/core/java/com/android/server/utils/quota/QuotaTracker.java
new file mode 100644
index 000000000000..ef1f42647e30
--- /dev/null
+++ b/services/core/java/com/android/server/utils/quota/QuotaTracker.java
@@ -0,0 +1,661 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.utils.quota;
+
+import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
+
+import static com.android.server.utils.quota.Uptc.string;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.AlarmManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.util.ArraySet;
+import android.util.Pair;
+import android.util.Slog;
+import android.util.SparseArrayMap;
+import android.util.proto.ProtoOutputStream;
+import android.util.quota.QuotaTrackerProto;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.FgThread;
+import com.android.server.LocalServices;
+import com.android.server.SystemServiceManager;
+
+import java.util.PriorityQueue;
+
+/**
+ * Base class for trackers that track whether an app has exceeded a count quota.
+ *
+ * Quotas are applied per userId-package-tag combination (UPTC). Tags can be null.
+ *
+ * Count and duration limits can be applied at the same time. Each limit is evaluated and
+ * controlled independently. If a UPTC reaches one of the limits, it will be considered out
+ * of quota until it is below that limit again. Limits are applied according to the category
+ * the UPTC is placed in. Categories are basic constructs to apply different limits to
+ * different groups of UPTCs. For example, standby buckets can be a set of categories, or
+ * foreground & background could be two categories. If every UPTC should have the limits
+ * applied, then only one category is needed.
+ *
+ * Note: all limits are enforced per category unless explicitly stated otherwise.
+ *
+ * @hide
+ */
+abstract class QuotaTracker {
+ private static final String TAG = QuotaTracker.class.getSimpleName();
+ private static final boolean DEBUG = false;
+
+ private static final String ALARM_TAG_QUOTA_CHECK = "*" + TAG + ".quota_check*";
+
+ @VisibleForTesting
+ static class Injector {
+ long getElapsedRealtime() {
+ return SystemClock.elapsedRealtime();
+ }
+
+ boolean isAlarmManagerReady() {
+ return LocalServices.getService(SystemServiceManager.class).isBootCompleted();
+ }
+ }
+
+ final Object mLock = new Object();
+ final Categorizer mCategorizer;
+ @GuardedBy("mLock")
+ private final ArraySet<QuotaChangeListener> mQuotaChangeListeners = new ArraySet<>();
+
+ /**
+ * Listener to track and manage when each package comes back within quota.
+ */
+ @GuardedBy("mLock")
+ private final InQuotaAlarmListener mInQuotaAlarmListener = new InQuotaAlarmListener();
+
+ /** "Free quota status" for apps. */
+ @GuardedBy("mLock")
+ private final SparseArrayMap<Boolean> mFreeQuota = new SparseArrayMap<>();
+
+ private final AlarmManager mAlarmManager;
+ protected final Context mContext;
+ protected final Injector mInjector;
+
+ @GuardedBy("mLock")
+ private boolean mIsQuotaFree;
+
+ /**
+ * If QuotaTracker should actively track events and check quota. If false, quota will be free
+ * and events will not be tracked.
+ */
+ @GuardedBy("mLock")
+ private boolean mIsEnabled = true;
+
+ private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+ private String getPackageName(Intent intent) {
+ final Uri uri = intent.getData();
+ return uri != null ? uri.getSchemeSpecificPart() : null;
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent == null
+ || intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
+ return;
+ }
+ final String action = intent.getAction();
+ if (action == null) {
+ Slog.e(TAG, "Received intent with null action");
+ return;
+ }
+ switch (action) {
+ case Intent.ACTION_PACKAGE_FULLY_REMOVED:
+ final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
+ synchronized (mLock) {
+ onAppRemovedLocked(getPackageName(intent), uid);
+ }
+ break;
+ case Intent.ACTION_USER_REMOVED:
+ final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
+ synchronized (mLock) {
+ onUserRemovedLocked(userId);
+ }
+ break;
+ }
+ }
+ };
+
+ /** The maximum period any Category can have. */
+ @VisibleForTesting
+ static final long MAX_WINDOW_SIZE_MS = 30 * 24 * 60 * MINUTE_IN_MILLIS; // 1 month
+
+ /** The minimum time any window size can be. */
+ @VisibleForTesting
+ static final long MIN_WINDOW_SIZE_MS = 30_000; // 30 seconds
+
+ QuotaTracker(@NonNull Context context, @NonNull Categorizer categorizer,
+ @NonNull Injector injector) {
+ mCategorizer = categorizer;
+ mContext = context;
+ mInjector = injector;
+ mAlarmManager = mContext.getSystemService(AlarmManager.class);
+
+ final IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED);
+ filter.addDataScheme("package");
+ context.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null,
+ BackgroundThread.getHandler());
+ final IntentFilter userFilter = new IntentFilter(Intent.ACTION_USER_REMOVED);
+ context.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, userFilter, null,
+ BackgroundThread.getHandler());
+ }
+
+ // Exposed API to users.
+
+ /**
+ * @return true if the UPTC is within quota, false otherwise.
+ * @throws IllegalStateException if given categorizer returns a Category that's not recognized.
+ */
+ public boolean isWithinQuota(int userId, @NonNull String packageName, @Nullable String tag) {
+ synchronized (mLock) {
+ return isWithinQuotaLocked(userId, packageName, tag);
+ }
+ }
+
+ /**
+ * Indicates whether quota is currently free or not for a specific app. If quota is free, any
+ * currently ongoing events or instantaneous events won't be counted until quota is no longer
+ * free.
+ */
+ public void setQuotaFree(int userId, @NonNull String packageName, boolean isFree) {
+ synchronized (mLock) {
+ final boolean wasFree = mFreeQuota.getOrDefault(userId, packageName, Boolean.FALSE);
+ if (wasFree != isFree) {
+ mFreeQuota.add(userId, packageName, isFree);
+ onQuotaFreeChangedLocked(userId, packageName, isFree);
+ }
+ }
+ }
+
+ /** Indicates whether quota is currently free or not for all apps. */
+ public void setQuotaFree(boolean isFree) {
+ synchronized (mLock) {
+ if (mIsQuotaFree == isFree) {
+ return;
+ }
+ mIsQuotaFree = isFree;
+
+ if (!mIsEnabled) {
+ return;
+ }
+ onQuotaFreeChangedLocked(mIsQuotaFree);
+ }
+ scheduleQuotaCheck();
+ }
+
+ /**
+ * Register a {@link QuotaChangeListener} to be notified of when apps go in and out of quota.
+ */
+ public void registerQuotaChangeListener(QuotaChangeListener listener) {
+ synchronized (mLock) {
+ if (mQuotaChangeListeners.add(listener) && mQuotaChangeListeners.size() == 1) {
+ scheduleQuotaCheck();
+ }
+ }
+ }
+
+ /** Unregister the listener from future quota change notifications. */
+ public void unregisterQuotaChangeListener(QuotaChangeListener listener) {
+ synchronized (mLock) {
+ mQuotaChangeListeners.remove(listener);
+ }
+ }
+
+ // Configuration APIs
+
+ /**
+ * Completely enables or disables the quota tracker. If the tracker is disabled, all events and
+ * internal tracking data will be dropped.
+ */
+ public void setEnabled(boolean enable) {
+ synchronized (mLock) {
+ if (mIsEnabled == enable) {
+ return;
+ }
+ mIsEnabled = enable;
+
+ if (!mIsEnabled) {
+ mInQuotaAlarmListener.clearLocked();
+ mFreeQuota.clear();
+
+ dropEverythingLocked();
+ }
+ }
+ }
+
+ // Internal implementation.
+
+ @GuardedBy("mLock")
+ boolean isEnabledLocked() {
+ return mIsEnabled;
+ }
+
+ /** Returns true if global quota is free. */
+ @GuardedBy("mLock")
+ boolean isQuotaFreeLocked() {
+ return mIsQuotaFree;
+ }
+
+ /** Returns true if global quota is free or if quota is free for the given userId-package. */
+ @GuardedBy("mLock")
+ boolean isQuotaFreeLocked(int userId, @NonNull String packageName) {
+ return mIsQuotaFree || mFreeQuota.getOrDefault(userId, packageName, Boolean.FALSE);
+ }
+
+ /**
+ * Returns true only if quota is free for the given userId-package. Global quota is not taken
+ * into account.
+ */
+ @GuardedBy("mLock")
+ boolean isIndividualQuotaFreeLocked(int userId, @NonNull String packageName) {
+ return mFreeQuota.getOrDefault(userId, packageName, Boolean.FALSE);
+ }
+
+ /** The tracker has been disabled. Drop all events and internal tracking data. */
+ @GuardedBy("mLock")
+ abstract void dropEverythingLocked();
+
+ /** The global free quota status changed. */
+ @GuardedBy("mLock")
+ abstract void onQuotaFreeChangedLocked(boolean isFree);
+
+ /** The individual free quota status for the userId-package changed. */
+ @GuardedBy("mLock")
+ abstract void onQuotaFreeChangedLocked(int userId, @NonNull String packageName, boolean isFree);
+
+ /** Get the Handler used by the tracker. This Handler's thread will receive alarm callbacks. */
+ @NonNull
+ abstract Handler getHandler();
+
+ /** Makes sure to call out to AlarmManager on a separate thread. */
+ void scheduleAlarm(@AlarmManager.AlarmType int type, long triggerAtMillis, String tag,
+ AlarmManager.OnAlarmListener listener) {
+ // We don't know at what level in the lock hierarchy this tracker will be, so make sure to
+ // call out to AlarmManager without the lock held. The operation should be fast enough so
+ // put it on the FgThread.
+ FgThread.getHandler().post(() -> {
+ if (mInjector.isAlarmManagerReady()) {
+ mAlarmManager.set(type, triggerAtMillis, tag, listener, getHandler());
+ } else {
+ Slog.w(TAG, "Alarm not scheduled because boot isn't completed");
+ }
+ });
+ }
+
+ /** Makes sure to call out to AlarmManager on a separate thread. */
+ void cancelAlarm(AlarmManager.OnAlarmListener listener) {
+ // We don't know at what level in the lock hierarchy this tracker will be, so make sure to
+ // call out to AlarmManager without the lock held. The operation should be fast enough so
+ // put it on the FgThread.
+ FgThread.getHandler().post(() -> {
+ if (mInjector.isAlarmManagerReady()) {
+ mAlarmManager.cancel(listener);
+ } else {
+ Slog.w(TAG, "Alarm not cancelled because boot isn't completed");
+ }
+ });
+ }
+
+ /** Check the quota status of the specific UPTC. */
+ abstract void maybeUpdateQuotaStatus(int userId, @NonNull String packageName,
+ @Nullable String tag);
+
+ /** Check the quota status of all UPTCs in case a listener needs to be notified. */
+ @GuardedBy("mLock")
+ abstract void maybeUpdateAllQuotaStatusLocked();
+
+ /** Schedule a quota check for all apps. */
+ void scheduleQuotaCheck() {
+ // Using BackgroundThread because of the risk of lock contention.
+ BackgroundThread.getHandler().post(() -> {
+ synchronized (mLock) {
+ if (mQuotaChangeListeners.size() > 0) {
+ maybeUpdateAllQuotaStatusLocked();
+ }
+ }
+ });
+ }
+
+ @GuardedBy("mLock")
+ abstract void handleRemovedAppLocked(String packageName, int uid);
+
+ @GuardedBy("mLock")
+ private void onAppRemovedLocked(String packageName, int uid) {
+ if (packageName == null) {
+ Slog.wtf(TAG, "Told app removed but given null package name.");
+ return;
+ }
+ final int userId = UserHandle.getUserId(uid);
+
+ mInQuotaAlarmListener.removeAlarmsLocked(userId, packageName);
+
+ mFreeQuota.delete(userId, packageName);
+
+ handleRemovedAppLocked(packageName, uid);
+ }
+
+ @GuardedBy("mLock")
+ abstract void handleRemovedUserLocked(int userId);
+
+ @GuardedBy("mLock")
+ private void onUserRemovedLocked(int userId) {
+ mInQuotaAlarmListener.removeAlarmsLocked(userId);
+ mFreeQuota.delete(userId);
+
+ handleRemovedUserLocked(userId);
+ }
+
+ @GuardedBy("mLock")
+ abstract boolean isWithinQuotaLocked(int userId, @NonNull String packageName,
+ @Nullable String tag);
+
+ void postQuotaStatusChanged(final int userId, @NonNull final String packageName,
+ @Nullable final String tag) {
+ BackgroundThread.getHandler().post(() -> {
+ final QuotaChangeListener[] listeners;
+ synchronized (mLock) {
+ // Only notify all listeners if we aren't directing to one listener.
+ listeners = mQuotaChangeListeners.toArray(
+ new QuotaChangeListener[mQuotaChangeListeners.size()]);
+ }
+ for (QuotaChangeListener listener : listeners) {
+ listener.onQuotaStateChanged(userId, packageName, tag);
+ }
+ });
+ }
+
+ /**
+ * Return the time (in the elapsed realtime timebase) when the UPTC will have quota again. This
+ * value is only valid if the UPTC is currently out of quota.
+ */
+ @GuardedBy("mLock")
+ abstract long getInQuotaTimeElapsedLocked(int userId, @NonNull String packageName,
+ @Nullable String tag);
+
+ /**
+ * Maybe schedule a non-wakeup alarm for the next time this package will have quota to run
+ * again. This should only be called if the package is already out of quota.
+ */
+ @GuardedBy("mLock")
+ @VisibleForTesting
+ void maybeScheduleStartAlarmLocked(final int userId, @NonNull final String packageName,
+ @Nullable final String tag) {
+ if (mQuotaChangeListeners.size() == 0) {
+ // No need to schedule the alarm since we won't do anything when the app gets quota
+ // again.
+ return;
+ }
+
+ final String pkgString = string(userId, packageName, tag);
+
+ if (isWithinQuota(userId, packageName, tag)) {
+ // Already in quota. Why was this method called?
+ if (DEBUG) {
+ Slog.e(TAG, "maybeScheduleStartAlarmLocked called for " + pkgString
+ + " even though it's within quota");
+ }
+ mInQuotaAlarmListener.removeAlarmLocked(new Uptc(userId, packageName, tag));
+ maybeUpdateQuotaStatus(userId, packageName, tag);
+ return;
+ }
+
+ mInQuotaAlarmListener.addAlarmLocked(new Uptc(userId, packageName, tag),
+ getInQuotaTimeElapsedLocked(userId, packageName, tag));
+ }
+
+ @GuardedBy("mLock")
+ void cancelScheduledStartAlarmLocked(final int userId,
+ @NonNull final String packageName, @Nullable final String tag) {
+ mInQuotaAlarmListener.removeAlarmLocked(new Uptc(userId, packageName, tag));
+ }
+
+ static class AlarmQueue extends PriorityQueue<Pair<Uptc, Long>> {
+ AlarmQueue() {
+ super(1, (o1, o2) -> (int) (o1.second - o2.second));
+ }
+
+ /**
+ * Remove any instances of the Uptc from the queue.
+ *
+ * @return true if an instance was removed, false otherwise.
+ */
+ boolean remove(@NonNull Uptc uptc) {
+ boolean removed = false;
+ Pair[] alarms = toArray(new Pair[size()]);
+ for (int i = alarms.length - 1; i >= 0; --i) {
+ if (uptc.equals(alarms[i].first)) {
+ remove(alarms[i]);
+ removed = true;
+ }
+ }
+ return removed;
+ }
+ }
+
+ /** Track when UPTCs are expected to come back into quota. */
+ private class InQuotaAlarmListener implements AlarmManager.OnAlarmListener {
+ @GuardedBy("mLock")
+ private final AlarmQueue mAlarmQueue = new AlarmQueue();
+ /** The next time the alarm is set to go off, in the elapsed realtime timebase. */
+ @GuardedBy("mLock")
+ private long mTriggerTimeElapsed = 0;
+
+ @GuardedBy("mLock")
+ void addAlarmLocked(@NonNull Uptc uptc, long inQuotaTimeElapsed) {
+ mAlarmQueue.remove(uptc);
+ mAlarmQueue.offer(new Pair<>(uptc, inQuotaTimeElapsed));
+ setNextAlarmLocked();
+ }
+
+ @GuardedBy("mLock")
+ void clearLocked() {
+ cancelAlarm(this);
+ mAlarmQueue.clear();
+ mTriggerTimeElapsed = 0;
+ }
+
+ @GuardedBy("mLock")
+ void removeAlarmLocked(@NonNull Uptc uptc) {
+ if (mAlarmQueue.remove(uptc)) {
+ if (mAlarmQueue.size() == 0) {
+ cancelAlarm(this);
+ } else {
+ setNextAlarmLocked();
+ }
+ }
+ }
+
+ @GuardedBy("mLock")
+ void removeAlarmsLocked(int userId) {
+ boolean removed = false;
+ Pair[] alarms = mAlarmQueue.toArray(new Pair[mAlarmQueue.size()]);
+ for (int i = alarms.length - 1; i >= 0; --i) {
+ final Uptc uptc = (Uptc) alarms[i].first;
+ if (userId == uptc.userId) {
+ mAlarmQueue.remove(alarms[i]);
+ removed = true;
+ }
+ }
+ if (removed) {
+ setNextAlarmLocked();
+ }
+ }
+
+ @GuardedBy("mLock")
+ void removeAlarmsLocked(int userId, @NonNull String packageName) {
+ boolean removed = false;
+ Pair[] alarms = mAlarmQueue.toArray(new Pair[mAlarmQueue.size()]);
+ for (int i = alarms.length - 1; i >= 0; --i) {
+ final Uptc uptc = (Uptc) alarms[i].first;
+ if (userId == uptc.userId && packageName.equals(uptc.packageName)) {
+ mAlarmQueue.remove(alarms[i]);
+ removed = true;
+ }
+ }
+ if (removed) {
+ setNextAlarmLocked();
+ }
+ }
+
+ @GuardedBy("mLock")
+ private void setNextAlarmLocked() {
+ if (mAlarmQueue.size() > 0) {
+ final long nextTriggerTimeElapsed = mAlarmQueue.peek().second;
+ // Only schedule the alarm if one of the following is true:
+ // 1. There isn't one currently scheduled
+ // 2. The new alarm is significantly earlier than the previous alarm. If it's
+ // earlier but not significantly so, then we essentially delay the notification a
+ // few extra minutes.
+ if (mTriggerTimeElapsed == 0
+ || nextTriggerTimeElapsed < mTriggerTimeElapsed - 3 * MINUTE_IN_MILLIS
+ || mTriggerTimeElapsed < nextTriggerTimeElapsed) {
+ // Use a non-wakeup alarm for this
+ scheduleAlarm(AlarmManager.ELAPSED_REALTIME, nextTriggerTimeElapsed,
+ ALARM_TAG_QUOTA_CHECK, this);
+ mTriggerTimeElapsed = nextTriggerTimeElapsed;
+ }
+ } else {
+ mTriggerTimeElapsed = 0;
+ }
+ }
+
+ @Override
+ public void onAlarm() {
+ synchronized (mLock) {
+ while (mAlarmQueue.size() > 0) {
+ final Pair<Uptc, Long> alarm = mAlarmQueue.peek();
+ if (alarm.second <= mInjector.getElapsedRealtime()) {
+ getHandler().post(() -> maybeUpdateQuotaStatus(
+ alarm.first.userId, alarm.first.packageName, alarm.first.tag));
+ mAlarmQueue.remove(alarm);
+ } else {
+ break;
+ }
+ }
+ setNextAlarmLocked();
+ }
+ }
+
+ @GuardedBy("mLock")
+ void dumpLocked(IndentingPrintWriter pw) {
+ pw.println("In quota alarms:");
+ pw.increaseIndent();
+
+ if (mAlarmQueue.size() == 0) {
+ pw.println("NOT WAITING");
+ } else {
+ Pair[] alarms = mAlarmQueue.toArray(new Pair[mAlarmQueue.size()]);
+ for (int i = 0; i < alarms.length; ++i) {
+ final Uptc uptc = (Uptc) alarms[i].first;
+ pw.print(uptc);
+ pw.print(": ");
+ pw.print(alarms[i].second);
+ pw.println();
+ }
+ }
+
+ pw.decreaseIndent();
+ }
+
+ @GuardedBy("mLock")
+ void dumpLocked(ProtoOutputStream proto, long fieldId) {
+ final long token = proto.start(fieldId);
+
+ proto.write(QuotaTrackerProto.InQuotaAlarmListener.TRIGGER_TIME_ELAPSED,
+ mTriggerTimeElapsed);
+
+ Pair[] alarms = mAlarmQueue.toArray(new Pair[mAlarmQueue.size()]);
+ for (int i = 0; i < alarms.length; ++i) {
+ final long aToken = proto.start(QuotaTrackerProto.InQuotaAlarmListener.ALARMS);
+
+ final Uptc uptc = (Uptc) alarms[i].first;
+ uptc.dumpDebug(proto, QuotaTrackerProto.InQuotaAlarmListener.Alarm.UPTC);
+ proto.write(QuotaTrackerProto.InQuotaAlarmListener.Alarm.IN_QUOTA_TIME_ELAPSED,
+ (Long) alarms[i].second);
+
+ proto.end(aToken);
+ }
+
+ proto.end(token);
+ }
+ }
+
+ //////////////////////////// DATA DUMP //////////////////////////////
+
+ /** Dump state in text format. */
+ public void dump(final IndentingPrintWriter pw) {
+ synchronized (mLock) {
+ pw.println("Is enabled: " + mIsEnabled);
+ pw.println("Is global quota free: " + mIsQuotaFree);
+ pw.println("Current elapsed time: " + mInjector.getElapsedRealtime());
+ pw.println();
+
+ pw.println();
+ mInQuotaAlarmListener.dumpLocked(pw);
+
+ pw.println();
+ pw.println("Per-app free quota:");
+ pw.increaseIndent();
+ for (int u = 0; u < mFreeQuota.numMaps(); ++u) {
+ final int userId = mFreeQuota.keyAt(u);
+ for (int p = 0; p < mFreeQuota.numElementsForKey(userId); ++p) {
+ final String pkgName = mFreeQuota.keyAt(u, p);
+
+ pw.print(string(userId, pkgName, null));
+ pw.print(": ");
+ pw.println(mFreeQuota.get(userId, pkgName));
+ }
+ }
+ pw.decreaseIndent();
+ }
+ }
+
+ /**
+ * Dump state to proto.
+ *
+ * @param proto The ProtoOutputStream to write to.
+ * @param fieldId The field ID of the {@link QuotaTrackerProto}.
+ */
+ public void dump(ProtoOutputStream proto, long fieldId) {
+ final long token = proto.start(fieldId);
+
+ synchronized (mLock) {
+ proto.write(QuotaTrackerProto.IS_ENABLED, mIsEnabled);
+ proto.write(QuotaTrackerProto.IS_GLOBAL_QUOTA_FREE, mIsQuotaFree);
+ proto.write(QuotaTrackerProto.ELAPSED_REALTIME, mInjector.getElapsedRealtime());
+ mInQuotaAlarmListener.dumpLocked(proto, QuotaTrackerProto.IN_QUOTA_ALARM_LISTENER);
+ }
+
+ proto.end(token);
+ }
+}
diff --git a/services/core/java/com/android/server/utils/quota/Uptc.java b/services/core/java/com/android/server/utils/quota/Uptc.java
new file mode 100644
index 000000000000..40775441ef67
--- /dev/null
+++ b/services/core/java/com/android/server/utils/quota/Uptc.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.utils.quota;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.util.proto.ProtoOutputStream;
+import android.util.quota.UptcProto;
+
+import java.util.Objects;
+
+/**
+ * A data object that represents a userId-packageName-tag combination (UPTC). The tag can be any
+ * desired String.
+ */
+final class Uptc {
+ public final int userId;
+ @NonNull
+ public final String packageName;
+ @Nullable
+ public final String tag;
+
+ private final int mHash;
+
+ /** Construct a new Uptc with the specified values. */
+ Uptc(int userId, @NonNull String packageName, @Nullable String tag) {
+ this.userId = userId;
+ this.packageName = packageName;
+ this.tag = tag;
+
+ mHash = 31 * userId
+ + 31 * packageName.hashCode()
+ + tag == null ? 0 : (31 * tag.hashCode());
+ }
+
+ @Override
+ public String toString() {
+ return string(userId, packageName, tag);
+ }
+
+ void dumpDebug(ProtoOutputStream proto, long fieldId) {
+ final long token = proto.start(fieldId);
+
+ proto.write(UptcProto.USER_ID, userId);
+ proto.write(UptcProto.NAME, packageName);
+ proto.write(UptcProto.TAG, tag);
+
+ proto.end(token);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof Uptc) {
+ final Uptc other = (Uptc) obj;
+ return userId == other.userId
+ && Objects.equals(packageName, other.packageName)
+ && Objects.equals(tag, other.tag);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return mHash;
+ }
+
+ /** Standardize the output of a UPTC. */
+ static String string(int userId, @NonNull String packageName, @Nullable String tag) {
+ return "<" + userId + ">" + packageName + (tag == null ? "" : ("::" + tag));
+ }
+}
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index c57ac11723b4..d746691b4773 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -228,11 +228,10 @@ final class AccessibilityController {
}
}
- public void onAppWindowTransitionLocked(WindowState windowState, int transition) {
- final int displayId = windowState.getDisplayId();
+ public void onAppWindowTransitionLocked(int displayId, int transition) {
final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
if (displayMagnifier != null) {
- displayMagnifier.onAppWindowTransitionLocked(windowState, transition);
+ displayMagnifier.onAppWindowTransitionLocked(displayId, transition);
}
// Not relevant for the window observer.
}
@@ -446,11 +445,11 @@ final class AccessibilityController {
mHandler.sendEmptyMessage(MyHandler.MESSAGE_NOTIFY_ROTATION_CHANGED);
}
- public void onAppWindowTransitionLocked(WindowState windowState, int transition) {
+ public void onAppWindowTransitionLocked(int displayId, int transition) {
if (DEBUG_WINDOW_TRANSITIONS) {
Slog.i(LOG_TAG, "Window transition: "
+ AppTransition.appTransitionToString(transition)
- + " displayId: " + windowState.getDisplayId());
+ + " displayId: " + displayId);
}
final boolean magnifying = mMagnifedViewport.isMagnifyingLocked();
if (magnifying) {
@@ -1310,7 +1309,7 @@ final class AccessibilityController {
// If a window has tap exclude region, we need to account it.
final Region displayRegion = new Region(windowState.getDisplayFrameLw());
final Region tapExcludeRegion = new Region();
- windowState.amendTapExcludeRegion(tapExcludeRegion);
+ windowState.getTapExcludeRegion(tapExcludeRegion);
displayRegion.op(tapExcludeRegion, displayRegion,
Region.Op.REVERSE_DIFFERENCE);
unaccountedSpace.op(displayRegion, unaccountedSpace,
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index c8357e29d9c1..94c2192b620f 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -8,6 +8,7 @@ import static android.app.WaitResult.LAUNCH_STATE_HOT;
import static android.app.WaitResult.LAUNCH_STATE_WARM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
@@ -119,6 +120,7 @@ class ActivityMetricsLogger {
private static final int WINDOW_STATE_SIDE_BY_SIDE = 1;
private static final int WINDOW_STATE_FREEFORM = 2;
private static final int WINDOW_STATE_ASSISTANT = 3;
+ private static final int WINDOW_STATE_MULTI_WINDOW = 4;
private static final int WINDOW_STATE_INVALID = -1;
/**
@@ -394,7 +396,7 @@ class ActivityMetricsLogger {
mWindowState = WINDOW_STATE_INVALID;
ActivityStack stack =
- mSupervisor.mRootActivityContainer.getTopDisplayFocusedStack();
+ mSupervisor.mRootWindowContainer.getTopDisplayFocusedStack();
if (stack == null) {
return;
}
@@ -406,7 +408,7 @@ class ActivityMetricsLogger {
@WindowingMode int windowingMode = stack.getWindowingMode();
if (windowingMode == WINDOWING_MODE_PINNED) {
- stack = mSupervisor.mRootActivityContainer.findStackBehind(stack);
+ stack = mSupervisor.mRootWindowContainer.findStackBehind(stack);
windowingMode = stack.getWindowingMode();
}
switch (windowingMode) {
@@ -420,6 +422,9 @@ class ActivityMetricsLogger {
case WINDOWING_MODE_FREEFORM:
mWindowState = WINDOW_STATE_FREEFORM;
break;
+ case WINDOWING_MODE_MULTI_WINDOW:
+ mWindowState = WINDOW_STATE_MULTI_WINDOW;
+ break;
default:
if (windowingMode != WINDOWING_MODE_UNDEFINED) {
throw new IllegalStateException("Unknown windowing mode for stack=" + stack
@@ -543,9 +548,10 @@ class ActivityMetricsLogger {
return;
}
- if (info != null) {
- // If we are already in an existing transition, only update the activity name, but not
- // the other attributes.
+ if (info != null
+ && info.mLastLaunchedActivity.mDisplayContent == launchedActivity.mDisplayContent) {
+ // If we are already in an existing transition on the same display, only update the
+ // activity name, but not the other attributes.
if (DEBUG_METRICS) Slog.i(TAG, "notifyActivityLaunched update launched activity");
// Coalesce multiple (trampoline) activities from a single sequence together.
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 6bfa1aea4931..76d18fa50680 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -379,6 +379,27 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
@VisibleForTesting static final int Z_BOOST_BASE = 800570000;
static final int INVALID_PID = -1;
+ // How long we wait until giving up on the last activity to pause. This
+ // is short because it directly impacts the responsiveness of starting the
+ // next activity.
+ private static final int PAUSE_TIMEOUT = 500;
+
+ // Ticks during which we check progress while waiting for an app to launch.
+ private static final int LAUNCH_TICK = 500;
+
+ // How long we wait for the activity to tell us it has stopped before
+ // giving up. This is a good amount of time because we really need this
+ // from the application in order to get its saved state. Once the stop
+ // is complete we may start destroying client resources triggering
+ // crashes if the UI thread was hung. We put this timeout one second behind
+ // the ANR timeout so these situations will generate ANR instead of
+ // Surface lost or other errors.
+ private static final int STOP_TIMEOUT = 11 * 1000;
+
+ // How long we wait until giving up on an activity telling us it has
+ // finished destroying itself.
+ private static final int DESTROY_TIMEOUT = 10 * 1000;
+
final ActivityTaskManagerService mAtmService;
final ActivityInfo info; // activity info provided by developer in AndroidManifest
// Non-null only for application tokens.
@@ -494,7 +515,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
boolean inHistory; // are we in the history stack?
final ActivityStackSupervisor mStackSupervisor;
- final RootActivityContainer mRootActivityContainer;
+ final RootWindowContainer mRootWindowContainer;
static final int STARTING_WINDOW_NOT_SHOWN = 0;
static final int STARTING_WINDOW_SHOWN = 1;
@@ -681,6 +702,55 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// Token for targeting this activity for assist purposes.
final Binder assistToken = new Binder();
+ private final Runnable mPauseTimeoutRunnable = new Runnable() {
+ @Override
+ public void run() {
+ // We don't at this point know if the activity is fullscreen,
+ // so we need to be conservative and assume it isn't.
+ Slog.w(TAG, "Activity pause timeout for " + ActivityRecord.this);
+ synchronized (mAtmService.mGlobalLock) {
+ if (hasProcess()) {
+ mAtmService.logAppTooSlow(app, pauseTime, "pausing " + ActivityRecord.this);
+ }
+ activityPaused(true);
+ }
+ }
+ };
+
+ private final Runnable mLaunchTickRunnable = new Runnable() {
+ @Override
+ public void run() {
+ synchronized (mAtmService.mGlobalLock) {
+ if (continueLaunchTicking()) {
+ mAtmService.logAppTooSlow(
+ app, launchTickTime, "launching " + ActivityRecord.this);
+ }
+ }
+ }
+ };
+
+ private final Runnable mDestroyTimeoutRunnable = new Runnable() {
+ @Override
+ public void run() {
+ synchronized (mAtmService.mGlobalLock) {
+ Slog.w(TAG, "Activity destroy timeout for " + ActivityRecord.this);
+ destroyed("destroyTimeout");
+ }
+ }
+ };
+
+ private final Runnable mStopTimeoutRunnable = new Runnable() {
+ @Override
+ public void run() {
+ synchronized (mAtmService.mGlobalLock) {
+ Slog.w(TAG, "Activity stop timeout for " + ActivityRecord.this);
+ if (isInHistory()) {
+ activityStopped(null /*icicle*/, null /*persistentState*/, null /*description*/);
+ }
+ }
+ }
+ };
+
private static String startingWindowStateToString(int state) {
switch (state) {
case STARTING_WINDOW_NOT_SHOWN:
@@ -1176,7 +1246,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// First time we are adding the activity to the system.
mVoiceInteraction = newTask.voiceSession != null;
mInputDispatchingTimeoutNanos = getInputDispatchingTimeoutLocked(this) * 1000000L;
- onDisplayChanged(task.getDisplayContent());
+
// TODO(b/36505427): Maybe this call should be moved inside
// updateOverrideConfiguration()
newTask.updateOverrideConfigurationFromLaunchBounds();
@@ -1494,7 +1564,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
appToken.attach(this);
- mRootActivityContainer = _service.mRootActivityContainer;
+ mRootWindowContainer = _service.mRootWindowContainer;
launchedFromPid = _launchedFromPid;
launchedFromUid = _launchedFromUid;
launchedFromPackage = _launchedFromPackage;
@@ -1811,7 +1881,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
} else if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
} else if (taskSwitch && allowTaskSnapshot) {
- return snapshot == null ? STARTING_WINDOW_TYPE_SPLASH_SCREEN
+ return snapshot == null ? STARTING_WINDOW_TYPE_NONE
: snapshotOrientationSameAsTask(snapshot) || fromRecents
? STARTING_WINDOW_TYPE_SNAPSHOT : STARTING_WINDOW_TYPE_SPLASH_SCREEN;
} else {
@@ -2030,7 +2100,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// {@link #returningOptions} of the activity under this one can be applied in
// {@link #handleAlreadyVisible()}.
if (changed || !occludesParent) {
- mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
+ mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
}
return changed;
}
@@ -2070,7 +2140,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
boolean isFocusable() {
- return mRootActivityContainer.isFocusable(this, isAlwaysFocusable());
+ return mRootWindowContainer.isFocusable(this, isAlwaysFocusable());
}
boolean isResizeable() {
@@ -2266,7 +2336,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
return false;
}
- if (mRootActivityContainer.getTopResumedActivity() == this
+ if (mRootWindowContainer.getTopResumedActivity() == this
&& getDisplayContent().mFocusedApp == this) {
if (DEBUG_FOCUS) {
Slog.d(TAG_FOCUS, "moveActivityStackToFront: already on top, activity=" + this);
@@ -2280,7 +2350,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
stack.moveToFront(reason, task);
// Report top activity change to tracking services and WM
- if (mRootActivityContainer.getTopResumedActivity() == this) {
+ if (mRootWindowContainer.getTopResumedActivity() == this) {
mAtmService.setResumedActivityUncheckLocked(this, reason);
}
return true;
@@ -2396,7 +2466,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
final boolean shouldAdjustGlobalFocus = mayAdjustTop
// It must be checked before {@link #makeFinishingLocked} is called, because a stack
// is not visible if it only contains finishing activities.
- && mRootActivityContainer.isTopDisplayFocusedStack(stack);
+ && mRootWindowContainer.isTopDisplayFocusedStack(stack);
mAtmService.deferWindowLayout();
try {
@@ -2624,11 +2694,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// If the display does not have running activity, the configuration may need to be
// updated for restoring original orientation of the display.
if (next == null) {
- mRootActivityContainer.ensureVisibilityAndConfig(next, getDisplayId(),
+ mRootWindowContainer.ensureVisibilityAndConfig(next, getDisplayId(),
false /* markFrozenIfConfigChanged */, true /* deferResume */);
}
if (activityRemoved) {
- mRootActivityContainer.resumeFocusedStacksTopActivities();
+ mRootWindowContainer.resumeFocusedStacksTopActivities();
}
if (DEBUG_CONTAINERS) {
@@ -2652,7 +2722,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
mStackSupervisor.mFinishingActivities.add(this);
}
resumeKeyDispatchingLocked();
- return mRootActivityContainer.resumeFocusedStacksTopActivities();
+ return mRootWindowContainer.resumeFocusedStacksTopActivities();
}
/**
@@ -2684,11 +2754,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
EventLogTags.writeWmDestroyActivity(mUserId, System.identityHashCode(this),
task.mTaskId, shortComponentName, reason);
- final ActivityStack stack = getActivityStack();
- if (hasProcess() && !stack.inLruList(this)) {
- Slog.w(TAG, "Activity " + this + " being finished, but not in LRU list");
- }
-
boolean removedFromHistory = false;
cleanUp(false /* cleanServices */, false /* setState */);
@@ -2735,7 +2800,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
setState(DESTROYING,
"destroyActivityLocked. finishing and not skipping destroy");
- stack.scheduleDestroyTimeoutForActivity(this);
+ mAtmService.mH.postDelayed(mDestroyTimeoutRunnable, DESTROY_TIMEOUT);
} else {
if (DEBUG_STATES) {
Slog.v(TAG_STATES, "Moving to DESTROYED: " + this + " (destroy skipped)");
@@ -2785,8 +2850,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
takeFromHistory();
- final ActivityStack stack = getActivityStack();
- stack.removeTimeoutsForActivity(this);
+ removeTimeouts();
if (DEBUG_STATES) {
Slog.v(TAG_STATES, "Moving to DESTROYED: " + this + " (removed from history)");
}
@@ -2814,7 +2878,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
* AND finished.
*/
void destroyed(String reason) {
- getActivityStack().removeDestroyTimeoutForActivity(this);
+ removeDestroyTimeout();
if (DEBUG_CONTAINERS) Slog.d(TAG_CONTAINERS, "activityDestroyedLocked: r=" + this);
@@ -2828,7 +2892,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
removeFromHistory(reason);
}
- mRootActivityContainer.resumeFocusedStacksTopActivities();
+ mRootWindowContainer.resumeFocusedStacksTopActivities();
}
/**
@@ -2872,7 +2936,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
// Get rid of any pending idle timeouts.
- stack.removeTimeoutsForActivity(this);
+ removeTimeouts();
// Clean-up activities are no longer relaunching (e.g. app process died). Notify window
// manager so it can update its bookkeeping.
clearRelaunching();
@@ -3345,13 +3409,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
void setShowWhenLocked(boolean showWhenLocked) {
mShowWhenLocked = showWhenLocked;
- mAtmService.mRootActivityContainer.ensureActivitiesVisible(null /* starting */,
+ mAtmService.mRootWindowContainer.ensureActivitiesVisible(null /* starting */,
0 /* configChanges */, false /* preserveWindows */);
}
void setInheritShowWhenLocked(boolean inheritShowWhenLocked) {
mInheritShownWhenLocked = inheritShowWhenLocked;
- mAtmService.mRootActivityContainer.ensureActivitiesVisible(null /* starting */,
+ mAtmService.mRootWindowContainer.ensureActivitiesVisible(null /* starting */,
0 /* configChanges */, false /* preserveWindows */);
}
@@ -3990,7 +4054,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// If we are preparing an app transition, then delay changing
// the visibility of this token until we execute that transition.
- if (okToAnimate() && appTransition.isTransitionSet()) {
+ // Note that we ignore display frozen since we want the opening / closing transition type
+ // can be updated correctly even display frozen, and it's safe since in applyAnimation will
+ // still check DC#okToAnimate again if the transition animation is fine to apply.
+ if (okToAnimate(true /* ignoreFrozen */) && appTransition.isTransitionSet()) {
if (visible) {
displayContent.mOpeningApps.add(this);
mEnteringAnimation = true;
@@ -4159,7 +4226,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
* transition.
*
* <p class="note><strong>Note:</strong> If the visibility of this {@link ActivityRecord} is
- * already set to {@link #visible}, we don't need to update the visibility. So {@code false} is
+ * already set to {@link #mVisible}, we don't need to update the visibility. So {@code false} is
* returned.</p>
*
* @param visible {@code true} if this {@link ActivityRecord} should become visible,
@@ -4169,16 +4236,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
*/
boolean shouldApplyAnimation(boolean visible) {
// Allow for state update and animation to be applied if:
- // * token is transitioning visibility state
- // * or the token was marked as hidden and is exiting before we had a chance to play the
+ // * activity is transitioning visibility state
+ // * or the activity was marked as hidden and is exiting before we had a chance to play the
// transition animation
- // * or this is an opening app and windows are being replaced
- // * or the token is the opening app and visible while opening task behind existing one.
- final DisplayContent displayContent = getDisplayContent();
+ // * or this is an opening app and windows are being replaced (e.g. freeform window to
+ // normal window).
return isVisible() != visible || (!isVisible() && mIsExiting)
- || (visible && forAllWindows(WindowState::waitingForReplacement, true))
- || (visible && displayContent.mOpeningApps.contains(this)
- && displayContent.mAppTransition.getAppTransition() == TRANSIT_TASK_OPEN_BEHIND);
+ || (visible && forAllWindows(WindowState::waitingForReplacement, true));
}
/**
@@ -4737,6 +4801,73 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
}
+ void activityPaused(boolean timeout) {
+ if (DEBUG_PAUSE) Slog.v(TAG_PAUSE,
+ "Activity paused: token=" + appToken + ", timeout=" + timeout);
+
+ final ActivityStack stack = getStack();
+
+ if (stack != null) {
+ removePauseTimeout();
+
+ if (stack.mPausingActivity == this) {
+ if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSED: " + this
+ + (timeout ? " (due to timeout)" : " (pause complete)"));
+ mAtmService.deferWindowLayout();
+ try {
+ stack.completePauseLocked(true /* resumeNext */, null /* resumingActivity */);
+ } finally {
+ mAtmService.continueWindowLayout();
+ }
+ return;
+ } else {
+ EventLogTags.writeWmFailedToPause(mUserId, System.identityHashCode(this),
+ shortComponentName, stack.mPausingActivity != null
+ ? stack.mPausingActivity.shortComponentName : "(none)");
+ if (isState(PAUSING)) {
+ setState(PAUSED, "activityPausedLocked");
+ if (finishing) {
+ if (DEBUG_PAUSE) Slog.v(TAG,
+ "Executing finish of failed to pause activity: " + this);
+ completeFinishing("activityPausedLocked");
+ }
+ }
+ }
+ }
+
+ mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
+ }
+
+ /**
+ * Schedule a pause timeout in case the app doesn't respond. We don't give it much time because
+ * this directly impacts the responsiveness seen by the user.
+ */
+ void schedulePauseTimeout() {
+ pauseTime = SystemClock.uptimeMillis();
+ mAtmService.mH.postDelayed(mPauseTimeoutRunnable, PAUSE_TIMEOUT);
+ if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Waiting for pause to complete...");
+ }
+
+ private void removePauseTimeout() {
+ mAtmService.mH.removeCallbacks(mPauseTimeoutRunnable);
+ }
+
+ private void removeDestroyTimeout() {
+ mAtmService.mH.removeCallbacks(mDestroyTimeoutRunnable);
+ }
+
+ private void removeStopTimeout() {
+ mAtmService.mH.removeCallbacks(mStopTimeoutRunnable);
+ }
+
+ void removeTimeouts() {
+ mStackSupervisor.removeIdleTimeoutForActivity(this);
+ removePauseTimeout();
+ removeStopTimeout();
+ removeDestroyTimeout();
+ finishLaunchTickingLocked();
+ }
+
void stopIfPossible() {
if (DEBUG_SWITCH) Slog.d(TAG_SWITCH, "Stopping: " + this);
final ActivityStack stack = getActivityStack();
@@ -4783,7 +4914,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
if (stack.shouldSleepOrShutDownActivities()) {
setSleeping(true);
}
- stack.scheduleStopTimeoutForActivity(this);
+ mAtmService.mH.postDelayed(mStopTimeoutRunnable, STOP_TIMEOUT);
} catch (Exception e) {
// Maybe just ignore exceptions here... if the process has crashed, our death
// notification will clean things up.
@@ -4798,13 +4929,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
}
- final void activityStoppedLocked(Bundle newIcicle, PersistableBundle newPersistentState,
+ void activityStopped(Bundle newIcicle, PersistableBundle newPersistentState,
CharSequence description) {
final ActivityStack stack = getActivityStack();
final boolean isStopping = mState == STOPPING;
if (!isStopping && mState != RESTARTING_PROCESS) {
Slog.i(TAG, "Activity reported stop, but no longer stopping: " + this);
- stack.removeStopTimeoutForActivity(this);
+ removeStopTimeout();
return;
}
if (newPersistentState != null) {
@@ -4822,7 +4953,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
if (DEBUG_SAVED_STATE) Slog.i(TAG_SAVED_STATE, "Saving icicle of " + this + ": " + mIcicle);
if (!stopped) {
if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to STOPPED: " + this + " (stop complete)");
- stack.removeStopTimeoutForActivity(this);
+ removeStopTimeout();
stopped = true;
if (isStopping) {
setState(STOPPED, "activityStoppedLocked");
@@ -4835,9 +4966,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
} else {
if (deferRelaunchUntilPaused) {
destroyImmediately(true /* removeFromApp */, "stop-config");
- mRootActivityContainer.resumeFocusedStacksTopActivities();
+ mRootWindowContainer.resumeFocusedStacksTopActivities();
} else {
- mRootActivityContainer.updatePreviousProcess(this);
+ mRootWindowContainer.updatePreviousProcess(this);
}
}
}
@@ -4877,11 +5008,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
if (launchTickTime == 0) {
launchTickTime = SystemClock.uptimeMillis();
- continueLaunchTickingLocked();
+ continueLaunchTicking();
}
}
- boolean continueLaunchTickingLocked() {
+ private boolean continueLaunchTicking() {
if (launchTickTime == 0) {
return false;
}
@@ -4892,10 +5023,14 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
stack.removeLaunchTickMessages();
- stack.scheduleLaunchTickForActivity(this);
+ mAtmService.mH.postDelayed(mLaunchTickRunnable, LAUNCH_TICK);
return true;
}
+ void removeLaunchTickRunnable() {
+ mAtmService.mH.removeCallbacks(mLaunchTickRunnable);
+ }
+
void finishLaunchTickingLocked() {
launchTickTime = 0;
final ActivityStack stack = getActivityStack();
@@ -5293,7 +5428,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// First find the real culprit... if this activity has stopped, then the key dispatching
// timeout should not be caused by this.
if (stopped) {
- final ActivityStack stack = mRootActivityContainer.getTopDisplayFocusedStack();
+ final ActivityStack stack = mRootWindowContainer.getTopDisplayFocusedStack();
// Try to use the one which is closest to top.
ActivityRecord r = stack.getResumedActivity();
if (r == null) {
@@ -5576,12 +5711,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
/**
* @return The to top most child window for which {@link LayoutParams#isFullscreen()} returns
- * true.
+ * true and isn't fully transparent.
*/
- WindowState getTopFullscreenWindow() {
+ WindowState getTopFullscreenOpaqueWindow() {
for (int i = mChildren.size() - 1; i >= 0; i--) {
final WindowState win = mChildren.get(i);
- if (win != null && win.mAttrs.isFullscreen()) {
+ if (win != null && win.mAttrs.isFullscreen() && !win.isFullyTransparent()) {
return win;
}
}
@@ -5969,7 +6104,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
getDisplayContent().mAppTransition.notifyAppTransitionFinishedLocked(token);
scheduleAnimation();
- if (mAtmService.mRootActivityContainer.allResumedActivitiesIdle()
+ if (mAtmService.mRootWindowContainer.allResumedActivitiesIdle()
|| mAtmService.mStackSupervisor.isStoppingNoHistoryActivity()) {
// If all activities are already idle or there is an activity that must be
// stopped immediately after visible, then we now need to make sure we perform
@@ -6063,6 +6198,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
void registerRemoteAnimations(RemoteAnimationDefinition definition) {
mRemoteAnimationDefinition = definition;
+ if (definition != null) {
+ definition.linkToDeath(this::unregisterRemoteAnimations);
+ }
+ }
+
+ void unregisterRemoteAnimations() {
+ mRemoteAnimationDefinition = null;
}
RemoteAnimationDefinition getRemoteAnimationDefinition() {
@@ -6304,6 +6446,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
resolveSizeCompatModeConfiguration(newParentConfiguration);
} else {
super.resolveOverrideConfiguration(newParentConfiguration);
+ // We ignore activities' requested orientation in multi-window modes. Task level may
+ // take them into consideration when calculating bounds.
+ if (getParent() != null && getParent().inMultiWindowMode()) {
+ resolvedConfig.orientation = Configuration.ORIENTATION_UNDEFINED;
+ }
applyAspectRatio(resolvedConfig.windowConfiguration.getBounds(),
newParentConfiguration.windowConfiguration.getAppBounds(),
newParentConfiguration.windowConfiguration.getBounds());
@@ -7005,10 +7152,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
newIntents = null;
mAtmService.getAppWarningsLocked().onResumeActivity(this);
} else {
- final ActivityStack stack = getActivityStack();
- if (stack != null) {
- stack.removePauseTimeoutForActivity(this);
- }
+ removePauseTimeout();
setState(PAUSED, "relaunchActivityLocked");
}
@@ -7279,7 +7423,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
boolean isTopRunningActivity() {
- return mRootActivityContainer.topRunningActivity() == this;
+ return mRootWindowContainer.topRunningActivity() == this;
}
/**
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 6f124ac5a54e..16245f088f0c 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -28,6 +28,7 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.PINNED_WINDOWING_MODE_ELEVATION_IN_DIP;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
@@ -191,7 +192,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStack" : TAG_ATM;
static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
private static final String TAG_APP = TAG + POSTFIX_APP;
- private static final String TAG_CLEANUP = TAG + POSTFIX_CLEANUP;
+ static final String TAG_CLEANUP = TAG + POSTFIX_CLEANUP;
private static final String TAG_PAUSE = TAG + POSTFIX_PAUSE;
private static final String TAG_RELEASE = TAG + POSTFIX_RELEASE;
private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
@@ -203,27 +204,6 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY;
- // Ticks during which we check progress while waiting for an app to launch.
- private static final int LAUNCH_TICK = 500;
-
- // How long we wait until giving up on the last activity to pause. This
- // is short because it directly impacts the responsiveness of starting the
- // next activity.
- private static final int PAUSE_TIMEOUT = 500;
-
- // How long we wait for the activity to tell us it has stopped before
- // giving up. This is a good amount of time because we really need this
- // from the application in order to get its saved state. Once the stop
- // is complete we may start destroying client resources triggering
- // crashes if the UI thread was hung. We put this timeout one second behind
- // the ANR timeout so these situations will generate ANR instead of
- // Surface lost or other errors.
- private static final int STOP_TIMEOUT = 11 * 1000;
-
- // How long we wait until giving up on an activity telling us it has
- // finished destroying itself.
- private static final int DESTROY_TIMEOUT = 10 * 1000;
-
// Set to false to disable the preview that is shown while a new activity
// is being started.
private static final boolean SHOW_APP_STARTING_PREVIEW = true;
@@ -269,15 +249,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
RESTARTING_PROCESS
}
- final ActivityTaskManagerService mService;
- final WindowManagerService mWindowManager;
-
- /**
- * List of running activities, sorted by recent usage.
- * The first entry in the list is the least recently used.
- * It contains HistoryRecord objects.
- */
- private final ArrayList<ActivityRecord> mLruActivities = new ArrayList<>();
+ final ActivityTaskManagerService mAtmService;
/**
* When we are in the process of pausing an activity, before starting the
@@ -412,26 +384,12 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
/** Run all ActivityStacks through this */
protected final ActivityStackSupervisor mStackSupervisor;
- protected final RootActivityContainer mRootActivityContainer;
+ protected final RootWindowContainer mRootWindowContainer;
private boolean mTopActivityOccludesKeyguard;
private ActivityRecord mTopDismissingKeyguardActivity;
- private static final int PAUSE_TIMEOUT_MSG = FIRST_ACTIVITY_STACK_MSG + 1;
- private static final int DESTROY_TIMEOUT_MSG = FIRST_ACTIVITY_STACK_MSG + 2;
- private static final int LAUNCH_TICK_MSG = FIRST_ACTIVITY_STACK_MSG + 3;
- private static final int STOP_TIMEOUT_MSG = FIRST_ACTIVITY_STACK_MSG + 4;
- private static final int DESTROY_ACTIVITIES_MSG = FIRST_ACTIVITY_STACK_MSG + 5;
- private static final int TRANSLUCENT_TIMEOUT_MSG = FIRST_ACTIVITY_STACK_MSG + 6;
-
- private static class ScheduleDestroyArgs {
- final WindowProcessController mOwner;
- final String mReason;
- ScheduleDestroyArgs(WindowProcessController owner, String reason) {
- mOwner = owner;
- mReason = reason;
- }
- }
+ private static final int TRANSLUCENT_TIMEOUT_MSG = FIRST_ACTIVITY_STACK_MSG + 1;
private final Handler mHandler;
@@ -444,57 +402,8 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
- case PAUSE_TIMEOUT_MSG: {
- ActivityRecord r = (ActivityRecord)msg.obj;
- // We don't at this point know if the activity is fullscreen,
- // so we need to be conservative and assume it isn't.
- Slog.w(TAG, "Activity pause timeout for " + r);
- synchronized (mService.mGlobalLock) {
- if (r.hasProcess()) {
- mService.logAppTooSlow(r.app, r.pauseTime, "pausing " + r);
- }
- activityPausedLocked(r.appToken, true);
- }
- } break;
- case LAUNCH_TICK_MSG: {
- ActivityRecord r = (ActivityRecord)msg.obj;
- synchronized (mService.mGlobalLock) {
- if (r.continueLaunchTickingLocked()) {
- mService.logAppTooSlow(r.app, r.launchTickTime, "launching " + r);
- }
- }
- } break;
- case DESTROY_TIMEOUT_MSG: {
- ActivityRecord r = (ActivityRecord)msg.obj;
- // We don't at this point know if the activity is fullscreen,
- // so we need to be conservative and assume it isn't.
- Slog.w(TAG, "Activity destroy timeout for " + r);
- synchronized (mService.mGlobalLock) {
- if (r != null) {
- r.destroyed("destroyTimeout");
- }
- }
- } break;
- case STOP_TIMEOUT_MSG: {
- ActivityRecord r = (ActivityRecord)msg.obj;
- // We don't at this point know if the activity is fullscreen,
- // so we need to be conservative and assume it isn't.
- Slog.w(TAG, "Activity stop timeout for " + r);
- synchronized (mService.mGlobalLock) {
- if (r.isInHistory()) {
- r.activityStoppedLocked(null /* icicle */,
- null /* persistentState */, null /* description */);
- }
- }
- } break;
- case DESTROY_ACTIVITIES_MSG: {
- ScheduleDestroyArgs args = (ScheduleDestroyArgs)msg.obj;
- synchronized (mService.mGlobalLock) {
- destroyActivities(args.mOwner, args.mReason);
- }
- } break;
case TRANSLUCENT_TIMEOUT_MSG: {
- synchronized (mService.mGlobalLock) {
+ synchronized (mAtmService.mGlobalLock) {
notifyActivityDrawnLocked(null);
}
} break;
@@ -534,7 +443,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
if (mUpdateConfig) {
// Ensure the resumed state of the focus activity if we updated the configuration of
// any activity.
- mRootActivityContainer.resumeFocusedStacksTopActivities();
+ mRootWindowContainer.resumeFocusedStacksTopActivities();
}
}
@@ -728,7 +637,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
}
ActivityStack(DisplayContent display, int stackId, ActivityStackSupervisor supervisor,
- int windowingMode, int activityType, boolean onTop) {
+ int activityType) {
super(supervisor.mService.mWindowManager);
mStackId = stackId;
mDockedStackMinimizeThickness =
@@ -736,20 +645,15 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
com.android.internal.R.dimen.docked_stack_minimize_thickness);
EventLogTags.writeWmStackCreated(stackId);
mStackSupervisor = supervisor;
- mService = supervisor.mService;
- mRootActivityContainer = mService.mRootActivityContainer;
+ mAtmService = supervisor.mService;
+ mRootWindowContainer = mAtmService.mRootWindowContainer;
mHandler = new ActivityStackHandler(supervisor.mLooper);
- mWindowManager = mService.mWindowManager;
mRemoteToken = new RemoteToken(this);
- mCurrentUser = mService.mAmInternal.getCurrentUserId();
+ mCurrentUser = mAtmService.mAmInternal.getCurrentUserId();
// Set display id before setting activity and window type to make sure it won't affect
// stacks on a wrong display.
mDisplayId = display.mDisplayId;
setActivityType(activityType);
- display.addStack(this, onTop ? POSITION_TOP : POSITION_BOTTOM);
- setWindowingMode(windowingMode, false /* animate */, false /* showRecents */,
- false /* enteringSplitScreenMode */, false /* deferEnsuringVisibility */,
- true /* creating */);
}
/**
@@ -769,8 +673,8 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
if (DEBUG_STACK) Slog.v(TAG_STACK, "set resumed activity to:" + record + " reason:"
+ reason);
setResumedActivity(record, reason + " - onActivityStateChanged");
- if (record == mRootActivityContainer.getTopResumedActivity()) {
- mService.setResumedActivityUncheckLocked(record, reason);
+ if (record == mRootWindowContainer.getTopResumedActivity()) {
+ mAtmService.setResumedActivityUncheckLocked(record, reason);
}
mStackSupervisor.mRecentTasks.add(record.getTask());
}
@@ -821,10 +725,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
// Update bounds if applicable
boolean hasNewOverrideBounds = false;
// Use override windowing mode to prevent extra bounds changes if inheriting the mode.
- if (overrideWindowingMode == WINDOWING_MODE_PINNED) {
- // Pinned calculation already includes rotation
- hasNewOverrideBounds = calculatePinnedBoundsForConfigChange(newBounds);
- } else if (!matchParentBounds()) {
+ if ((overrideWindowingMode != WINDOWING_MODE_PINNED) && !matchParentBounds()) {
// If the parent (display) has rotated, rotate our bounds to best-fit where their
// bounds were on the pre-rotated display.
final int newRotation = getWindowConfiguration().getRotation();
@@ -882,9 +783,6 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
null /* tempTaskBounds */, null /* tempTaskInsetBounds */,
null /* tempOtherTaskBounds */, null /* tempOtherTaskInsetBounds */,
PRESERVE_WINDOWS, true /* deferResume */);
- } else {
- resize(new Rect(newBounds), null /* tempTaskBounds */,
- null /* tempTaskInsetBounds */, PRESERVE_WINDOWS, true /* deferResume */);
}
}
if (prevIsAlwaysOnTop != isAlwaysOnTop()) {
@@ -931,7 +829,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
*/
void setWindowingMode(int preferredWindowingMode, boolean animate, boolean showRecents,
boolean enteringSplitScreenMode, boolean deferEnsuringVisibility, boolean creating) {
- mWindowManager.inSurfaceTransaction(() -> setWindowingModeInSurfaceTransaction(
+ mWmService.inSurfaceTransaction(() -> setWindowingModeInSurfaceTransaction(
preferredWindowingMode, animate, showRecents, enteringSplitScreenMode,
deferEnsuringVisibility, creating));
}
@@ -979,7 +877,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
// Looks like we can't launch in split screen mode or the stack we are launching
// doesn't support split-screen mode, go ahead an dismiss split-screen and display a
// warning toast about it.
- mService.getTaskChangeNotificationController().notifyActivityDismissingDockedStack();
+ mAtmService.getTaskChangeNotificationController().notifyActivityDismissingDockedStack();
final ActivityStack primarySplitStack = display.getSplitScreenPrimaryStack();
primarySplitStack.setWindowingModeInSurfaceTransaction(WINDOWING_MODE_UNDEFINED,
false /* animate */, false /* showRecents */,
@@ -1013,11 +911,11 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
// Inform the user that they are starting an app that may not work correctly in
// multi-window mode.
final String packageName = topActivity.info.applicationInfo.packageName;
- mService.getTaskChangeNotificationController().notifyActivityForcedResizable(
+ mAtmService.getTaskChangeNotificationController().notifyActivityForcedResizable(
topTask.mTaskId, FORCED_RESIZEABLE_REASON_SPLIT_SCREEN, packageName);
}
- mService.deferWindowLayout();
+ mAtmService.deferWindowLayout();
try {
if (!animate && topActivity != null) {
mStackSupervisor.mNoAnimActivities.add(topActivity);
@@ -1072,21 +970,21 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
// task, and from the tests
// TODO (b/78247419): Fix the rotation animation from fullscreen to minimized mode
final boolean isRecentsComponentHome =
- mService.getRecentTasks().isRecentsComponentHomeActivity(mCurrentUser);
+ mAtmService.getRecentTasks().isRecentsComponentHomeActivity(mCurrentUser);
final ActivityStack recentStack = display.getOrCreateStack(
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY,
isRecentsComponentHome ? ACTIVITY_TYPE_HOME : ACTIVITY_TYPE_RECENTS,
true /* onTop */);
recentStack.moveToFront("setWindowingMode");
// If task moved to docked stack - show recents if needed.
- mService.mWindowManager.showRecentApps();
+ mWmService.showRecentApps();
}
- mService.continueWindowLayout();
+ mAtmService.continueWindowLayout();
}
if (!deferEnsuringVisibility) {
- mRootActivityContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
- mRootActivityContainer.resumeFocusedStacksTopActivities();
+ mRootWindowContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
+ mRootWindowContainer.resumeFocusedStacksTopActivities();
}
}
@@ -1104,10 +1002,10 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
/** Resume next focusable stack after reparenting to another display. */
void postReparent() {
adjustFocusToNextFocusableStack("reparent", true /* allowFocusSelf */);
- mRootActivityContainer.resumeFocusedStacksTopActivities();
+ mRootWindowContainer.resumeFocusedStacksTopActivities();
// Update visibility of activities before notifying WM. This way it won't try to resize
// windows that are no longer visible.
- mRootActivityContainer.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
+ mRootWindowContainer.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
!PRESERVE_WINDOWS);
}
@@ -1249,18 +1147,6 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
return display != null && display.isSingleTaskInstance();
}
- /** @return {@code true} if LRU list contained the specified activity. */
- final boolean inLruList(ActivityRecord activity) {
- return mLruActivities.contains(activity);
- }
-
- /** @return {@code true} if the given activity was contained in LRU list. */
- final boolean updateLruList(ActivityRecord r) {
- final boolean contained = mLruActivities.remove(r);
- mLruActivities.add(r);
- return contained;
- }
-
final boolean isHomeOrRecentsStack() {
return isActivityTypeHome() || isActivityTypeRecents();
}
@@ -1344,7 +1230,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
boolean isFocusable() {
final ActivityRecord r = topRunningActivity();
- return mRootActivityContainer.isFocusable(this, r != null && r.isFocusable());
+ return mRootWindowContainer.isFocusable(this, r != null && r.isFocusable());
}
boolean isFocusableAndVisible() {
@@ -1384,7 +1270,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
private void clearLaunchTime(ActivityRecord r) {
// Make sure that there is no activity waiting for this to launch.
if (!mStackSupervisor.mWaitingActivityLaunched.isEmpty()) {
- mStackSupervisor.removeTimeoutsForActivityLocked(r);
+ mStackSupervisor.removeIdleTimeoutForActivity(r);
mStackSupervisor.scheduleIdleTimeoutLocked(r);
}
}
@@ -1394,7 +1280,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
forAllActivities((Consumer<ActivityRecord>) (r) -> r.setSleeping(false));
if (mPausingActivity != null) {
Slog.d(TAG, "awakeFromSleepingLocked: previously pausing activity didn't pause");
- activityPausedLocked(mPausingActivity.appToken, true);
+ mPausingActivity.activityPaused(true);
}
}
@@ -1509,7 +1395,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
if (prev == null) {
if (resuming == null) {
Slog.wtf(TAG, "Trying to pause when nothing is resumed");
- mRootActivityContainer.resumeFocusedStacksTopActivities();
+ mRootWindowContainer.resumeFocusedStacksTopActivities();
}
return false;
}
@@ -1529,7 +1415,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
prev.getTask().touchActiveTime();
clearLaunchTime(prev);
- mService.updateCpuStats();
+ mAtmService.updateCpuStats();
boolean pauseImmediately = false;
if (resuming != null && (resuming.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0) {
@@ -1550,7 +1436,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
EventLogTags.writeWmPauseActivity(prev.mUserId, System.identityHashCode(prev),
prev.shortComponentName, "userLeaving=" + userLeaving);
- mService.getLifecycleManager().scheduleTransaction(prev.app.getThread(),
+ mAtmService.getLifecycleManager().scheduleTransaction(prev.app.getThread(),
prev.appToken, PauseActivityItem.obtain(prev.finishing, userLeaving,
prev.configChangeFlags, pauseImmediately));
} catch (Exception e) {
@@ -1568,7 +1454,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
// If we are not going to sleep, we want to ensure the device is
// awake until the next activity is started.
- if (!uiSleeping && !mService.isSleepingOrShuttingDownLocked()) {
+ if (!uiSleeping && !mAtmService.isSleepingOrShuttingDownLocked()) {
mStackSupervisor.acquireLaunchWakelock();
}
@@ -1590,7 +1476,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
return false;
} else {
- schedulePauseTimeoutForActivity(prev);
+ prev.schedulePauseTimeout();
return true;
}
@@ -1599,47 +1485,12 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
// pause, so just treat it as being paused now.
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Activity not running, resuming next.");
if (resuming == null) {
- mRootActivityContainer.resumeFocusedStacksTopActivities();
+ mRootWindowContainer.resumeFocusedStacksTopActivities();
}
return false;
}
}
- final void activityPausedLocked(IBinder token, boolean timeout) {
- if (DEBUG_PAUSE) Slog.v(TAG_PAUSE,
- "Activity paused: token=" + token + ", timeout=" + timeout);
-
- final ActivityRecord r = isInStackLocked(token);
-
- if (r != null) {
- mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
- if (mPausingActivity == r) {
- if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSED: " + r
- + (timeout ? " (due to timeout)" : " (pause complete)"));
- mService.deferWindowLayout();
- try {
- completePauseLocked(true /* resumeNext */, null /* resumingActivity */);
- } finally {
- mService.continueWindowLayout();
- }
- return;
- } else {
- EventLogTags.writeWmFailedToPause(r.mUserId, System.identityHashCode(r),
- r.shortComponentName, mPausingActivity != null
- ? mPausingActivity.shortComponentName : "(none)");
- if (r.isState(PAUSING)) {
- r.setState(PAUSED, "activityPausedLocked");
- if (r.finishing) {
- if (DEBUG_PAUSE) Slog.v(TAG,
- "Executing finish of failed to pause activity: " + r);
- r.completeFinishing("activityPausedLocked");
- }
- }
- }
- }
- mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
- }
-
@VisibleForTesting
void completePauseLocked(boolean resumeNext, ActivityRecord resuming) {
ActivityRecord prev = mPausingActivity;
@@ -1687,9 +1538,9 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
}
if (resumeNext) {
- final ActivityStack topStack = mRootActivityContainer.getTopDisplayFocusedStack();
+ final ActivityStack topStack = mRootWindowContainer.getTopDisplayFocusedStack();
if (!topStack.shouldSleepOrShutDownActivities()) {
- mRootActivityContainer.resumeFocusedStacksTopActivities(topStack, prev, null);
+ mRootWindowContainer.resumeFocusedStacksTopActivities(topStack, prev, null);
} else {
checkReadyForSleep();
ActivityRecord top = topStack.topRunningActivity();
@@ -1698,7 +1549,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
// something. Also if the top activity on the stack is not the just paused
// activity, we need to go ahead and resume it to ensure we complete an
// in-flight app switch.
- mRootActivityContainer.resumeFocusedStacksTopActivities();
+ mRootWindowContainer.resumeFocusedStacksTopActivities();
}
}
}
@@ -1711,10 +1562,10 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
if (diff > 0) {
final Runnable r = PooledLambda.obtainRunnable(
ActivityManagerInternal::updateForegroundTimeIfOnBattery,
- mService.mAmInternal, prev.info.packageName,
+ mAtmService.mAmInternal, prev.info.packageName,
prev.info.applicationInfo.uid,
diff);
- mService.mH.post(r);
+ mAtmService.mH.post(r);
}
}
prev.cpuTimeAtResume = 0; // reset it
@@ -1725,11 +1576,11 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
// task stack changes, because its positioning may depend on it.
if (mStackSupervisor.mAppVisibilitiesChangedSinceLastPause
|| (getDisplay() != null && getDisplay().hasPinnedStack())) {
- mService.getTaskChangeNotificationController().notifyTaskStackChanged();
+ mAtmService.getTaskChangeNotificationController().notifyTaskStackChanged();
mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = false;
}
- mRootActivityContainer.ensureActivitiesVisible(resuming, 0, !PRESERVE_WINDOWS);
+ mRootWindowContainer.ensureActivitiesVisible(resuming, 0, !PRESERVE_WINDOWS);
}
/**
@@ -1848,7 +1699,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
if (activityType == ACTIVITY_TYPE_HOME
|| (activityType == ACTIVITY_TYPE_ASSISTANT
- && mWindowManager.getRecentsAnimationController() != null)) {
+ && mWmService.getRecentsAnimationController() != null)) {
break;
}
}
@@ -1935,7 +1786,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
/**
* Ensure visibility with an option to also update the configuration of visible activities.
* @see #ensureActivitiesVisible(ActivityRecord, int, boolean)
- * @see RootActivityContainer#ensureActivitiesVisible(ActivityRecord, int, boolean)
+ * @see RootWindowContainer#ensureActivitiesVisible(ActivityRecord, int, boolean)
*/
// TODO: Should be re-worked based on the fact that each task as a stack in most cases.
void ensureActivitiesVisible(ActivityRecord starting, int configChanges,
@@ -1985,7 +1836,9 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
return false;
}
final int windowingMode = getWindowingMode();
- return windowingMode != WINDOWING_MODE_FREEFORM && windowingMode != WINDOWING_MODE_PINNED;
+ return windowingMode != WINDOWING_MODE_FREEFORM
+ && windowingMode != WINDOWING_MODE_PINNED
+ && windowingMode != WINDOWING_MODE_MULTI_WINDOW;
}
/**
@@ -2092,7 +1945,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
mHandler.removeMessages(TRANSLUCENT_TIMEOUT_MSG);
if (waitingActivity != null) {
- mWindowManager.setWindowOpaqueLocked(waitingActivity.appToken, false);
+ mWmService.setWindowOpaqueLocked(waitingActivity.appToken, false);
if (waitingActivity.attachedToProcess()) {
try {
waitingActivity.app.getThread().scheduleTranslucentConversionComplete(
@@ -2135,7 +1988,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
*
* NOTE: It is not safe to call this method directly as it can cause an activity in a
* non-focused stack to be resumed.
- * Use {@link RootActivityContainer#resumeFocusedStacksTopActivities} to resume the
+ * Use {@link RootWindowContainer#resumeFocusedStacksTopActivities} to resume the
* right activity for the current system state.
*/
@GuardedBy("mService")
@@ -2189,7 +2042,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
@GuardedBy("mService")
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
- if (!mService.isBooting() && !mService.isBooted()) {
+ if (!mAtmService.isBooting() && !mAtmService.isBooted()) {
// Not ready yet!
return false;
}
@@ -2206,7 +2059,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
return false;
}
- mRootActivityContainer.cancelInitializingActivities();
+ mRootWindowContainer.cancelInitializingActivities();
// Remember how we'll process this pause/resume situation, and ensure
// that the state is reset however we wind up proceeding.
@@ -2240,11 +2093,11 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
// activity is paused, well that is the state we want.
if (shouldSleepOrShutDownActivities()
&& mLastPausedActivity == next
- && mRootActivityContainer.allPausedActivitiesComplete()) {
+ && mRootWindowContainer.allPausedActivitiesComplete()) {
// If the current top activity may be able to occlude keyguard but the occluded state
// has not been set, update visibility and check again if we should continue to resume.
boolean nothingToResume = true;
- if (!mService.mShuttingDown) {
+ if (!mAtmService.mShuttingDown) {
final boolean canShowWhenLocked = !mTopActivityOccludesKeyguard
&& next.canShowWhenLocked();
final boolean mayDismissKeyguard = mTopDismissingKeyguardActivity != next
@@ -2269,7 +2122,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
// Make sure that the user who owns this activity is started. If not,
// we will just leave it as is because someone should be bringing
// another user's activities to the top of the stack.
- if (!mService.mAmInternal.hasStartedUserState(next.mUserId)) {
+ if (!mAtmService.mAmInternal.hasStartedUserState(next.mUserId)) {
Slog.w(TAG, "Skipping resume of top activity " + next
+ ": user " + next.mUserId + " is stopped");
return false;
@@ -2284,7 +2137,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next);
// If we are currently pausing an activity, then don't do anything until that is done.
- if (!mRootActivityContainer.allPausedActivitiesComplete()) {
+ if (!mRootWindowContainer.allPausedActivitiesComplete()) {
if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,
"resumeTopActivityLocked: Skip resume: some activity pausing.");
@@ -2329,7 +2182,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
// activity isn't running, we can start the process earlier to save the time to wait
// for the current activity to be paused.
final boolean isTop = this == display.getFocusedStack();
- mService.startProcessAsync(next, false /* knownToBeDead */, isTop,
+ mAtmService.startProcessAsync(next, false /* knownToBeDead */, isTop,
isTop ? "pre-top-activity" : "pre-activity");
}
if (lastResumed != null) {
@@ -2386,7 +2239,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
// Launching this app's activity, make sure the app is no longer
// considered stopped.
try {
- mService.getPackageManager().setPackageStoppedState(
+ mAtmService.getPackageManager().setPackageStoppedState(
next.packageName, false, next.mUserId); /* TODO: Verify if correct userid */
} catch (RemoteException e1) {
} catch (IllegalArgumentException e) {
@@ -2472,7 +2325,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
lastFocusedStack == null ? null : lastFocusedStack.mResumedActivity;
final ActivityState lastState = next.getState();
- mService.updateCpuStats();
+ mAtmService.updateCpuStats();
if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + next
+ " (in existing)");
@@ -2481,7 +2334,6 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
next.app.updateProcessInfo(false /* updateServiceConnectionActivities */,
true /* activityChange */, true /* updateOomAdj */);
- updateLruList(next);
// Have the window manager re-evaluate the orientation of
// the screen based on the new activity order.
@@ -2498,7 +2350,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
// result of invisible window resize.
// TODO: Remove this once visibilities are set correctly immediately when
// starting an activity.
- notUpdated = !mRootActivityContainer.ensureVisibilityAndConfig(next, mDisplayId,
+ notUpdated = !mRootWindowContainer.ensureVisibilityAndConfig(next, mDisplayId,
true /* markFrozenIfConfigChanged */, false /* deferResume */);
}
@@ -2550,13 +2402,13 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
next.getTask().mTaskId, next.shortComponentName);
next.sleeping = false;
- mService.getAppWarningsLocked().onResumeActivity(next);
- next.app.setPendingUiCleanAndForceProcessStateUpTo(mService.mTopProcessState);
+ mAtmService.getAppWarningsLocked().onResumeActivity(next);
+ next.app.setPendingUiCleanAndForceProcessStateUpTo(mAtmService.mTopProcessState);
next.clearOptionsLocked();
transaction.setLifecycleStateRequest(
ResumeActivityItem.obtain(next.app.getReportedProcState(),
dc.isNextTransitionForward()));
- mService.getLifecycleManager().scheduleTransaction(transaction);
+ mAtmService.getLifecycleManager().scheduleTransaction(transaction);
if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Resumed "
+ next);
@@ -2629,7 +2481,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
// Try to move focus to the next visible stack with a running activity if this
// stack is not covering the entire screen or is on a secondary display with no home
// stack.
- return mRootActivityContainer.resumeFocusedStacksTopActivities(nextFocusedStack,
+ return mRootWindowContainer.resumeFocusedStacksTopActivities(nextFocusedStack,
prev, null /* targetOptions */);
}
}
@@ -2639,7 +2491,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
ActivityOptions.abort(options);
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeNextFocusableActivityWhenStackIsEmpty: " + reason + ", go home");
- return mRootActivityContainer.resumeHomeActivity(prev, reason, mDisplayId);
+ return mRootWindowContainer.resumeHomeActivity(prev, reason, mDisplayId);
}
void startActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity,
@@ -2846,7 +2698,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
*/
private ActivityStack adjustFocusToNextFocusableStack(String reason, boolean allowFocusSelf) {
final ActivityStack stack =
- mRootActivityContainer.getNextFocusableStack(this, !allowFocusSelf);
+ mRootWindowContainer.getNextFocusableStack(this, !allowFocusSelf);
final String myReason = reason + " adjustFocusToNextFocusableStack";
if (stack == null) {
return null;
@@ -2868,7 +2720,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
// Set focused app directly because if the next focused activity is already resumed
// (e.g. the next top activity is on a different display), there won't have activity
// state change to update it.
- mService.setResumedActivityUncheckLocked(stack.mResumedActivity, reason);
+ mAtmService.setResumedActivityUncheckLocked(stack.mResumedActivity, reason);
}
return stack;
}
@@ -2899,7 +2751,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
if (activityBelow != null) {
if (activityBelow.isState(STARTED, RESUMED, PAUSING, PAUSED)) {
if (!activityBelow.isActivityTypeHome()
- || mService.mHomeProcess != activityBelow.app) {
+ || mAtmService.mHomeProcess != activityBelow.app) {
Slog.w(TAG, " Force finishing activity "
+ activityBelow.intent.getComponent().flattenToShortString());
activityBelow.finishIfPossible(reason, false /* oomAdj */);
@@ -3030,7 +2882,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
// TODO: There is a dup. of this block of code in ActivityTaskManagerService.finishActivity
// We should consolidate.
- IActivityController controller = mService.mController;
+ IActivityController controller = mAtmService.mController;
if (controller != null) {
ActivityRecord next = topRunningActivity(srec.appToken, INVALID_TASK_ID);
if (next != null) {
@@ -3039,7 +2891,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
try {
resumeOK = controller.activityResuming(next.packageName);
} catch (RemoteException e) {
- mService.mController = null;
+ mAtmService.mController = null;
Watchdog.getInstance().setActivityController(null);
}
@@ -3083,7 +2935,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
destIntent.getComponent(), ActivityManagerService.STOCK_PM_FLAGS,
srec.mUserId);
// TODO(b/64750076): Check if calling pid should really be -1.
- final int res = mService.getActivityStartController()
+ final int res = mAtmService.getActivityStartController()
.obtainStarter(destIntent, "navigateUpTo")
.setCaller(srec.app.getThread())
.setActivityInfo(aInfo)
@@ -3111,10 +2963,9 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
* an activity moves away from the stack.
*/
void onActivityRemovedFromStack(ActivityRecord r) {
- removeTimeoutsForActivity(r);
+ r.removeTimeouts();
mExitingActivities.remove(r);
- mLruActivities.remove(r);
if (mResumedActivity != null && mResumedActivity == r) {
setResumedActivity(null, "onActivityRemovedFromStack");
@@ -3128,120 +2979,10 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
if (r.isState(RESUMED)) {
setResumedActivity(r, "onActivityAddedToStack");
}
- if (r.hasProcess()) {
- updateLruList(r);
- }
- }
-
- void removeTimeoutsForActivity(ActivityRecord r) {
- mStackSupervisor.removeTimeoutsForActivityLocked(r);
- removePauseTimeoutForActivity(r);
- removeStopTimeoutForActivity(r);
- removeDestroyTimeoutForActivity(r);
- r.finishLaunchTickingLocked();
- }
-
- void scheduleDestroyActivities(WindowProcessController owner, String reason) {
- final Message msg = mHandler.obtainMessage(DESTROY_ACTIVITIES_MSG);
- msg.obj = new ScheduleDestroyArgs(owner, reason);
- mHandler.sendMessage(msg);
- }
-
- void scheduleDestroyTimeoutForActivity(ActivityRecord r) {
- final Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG, r);
- mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
- }
-
- void removeDestroyTimeoutForActivity(ActivityRecord r) {
- mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r);
- }
-
- void scheduleStopTimeoutForActivity(ActivityRecord r) {
- final Message msg = mHandler.obtainMessage(STOP_TIMEOUT_MSG, r);
- mHandler.sendMessageDelayed(msg, STOP_TIMEOUT);
- }
-
- void removeStopTimeoutForActivity(ActivityRecord r) {
- mHandler.removeMessages(STOP_TIMEOUT_MSG, r);
- }
-
- /**
- * Schedule a pause timeout in case the app doesn't respond. We don't give it much time because
- * this directly impacts the responsiveness seen by the user.
- */
- private void schedulePauseTimeoutForActivity(ActivityRecord r) {
- final Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG, r);
- r.pauseTime = SystemClock.uptimeMillis();
- mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
- if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Waiting for pause to complete...");
- }
-
- void removePauseTimeoutForActivity(ActivityRecord r) {
- mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
- }
-
- void scheduleLaunchTickForActivity(ActivityRecord r) {
- final Message msg = mHandler.obtainMessage(LAUNCH_TICK_MSG, r);
- mHandler.sendMessageDelayed(msg, LAUNCH_TICK);
}
void removeLaunchTickMessages() {
- mHandler.removeMessages(LAUNCH_TICK_MSG);
- }
- /// HANDLER INTERFACE END
-
- private void destroyActivities(WindowProcessController owner, String reason) {
- try {
- mStackSupervisor.beginDeferResume();
-
- final PooledConsumer c = PooledLambda.obtainConsumer(ActivityStack::destroyActivity,
- PooledLambda.__(ActivityRecord.class), owner, reason);
- forAllActivities(c);
- c.recycle();
- } finally {
- mStackSupervisor.endDeferResume();
- mRootActivityContainer.resumeFocusedStacksTopActivities();
- }
- }
-
- private static void destroyActivity(
- ActivityRecord r, WindowProcessController owner, String reason) {
- if (r.finishing || (owner != null && r.app != owner) || !r.isDestroyable()) return;
-
- if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Destroying " + r
- + " in state " + r.getState()
- + " resumed=" + r.getStack().mResumedActivity
- + " pausing=" + r.getStack().mPausingActivity + " for reason " + reason);
-
- r.destroyImmediately(true /* removeFromTask */, reason);
- }
-
- private void removeHistoryRecordsForApp(ArrayList<ActivityRecord> list,
- WindowProcessController app, String listName) {
- int i = list.size();
- if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
- "Removing app " + app + " from list " + listName + " with " + i + " entries");
- while (i > 0) {
- i--;
- ActivityRecord r = list.get(i);
- if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP, "Record #" + i + " " + r);
- if (r.app == app) {
- if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP, "---> REMOVING this entry!");
- list.remove(i);
- removeTimeoutsForActivity(r);
- }
- }
- }
-
- private boolean removeHistoryRecordsForApp(WindowProcessController app) {
- removeHistoryRecordsForApp(mLruActivities, app, "mLruActivities");
- removeHistoryRecordsForApp(mStackSupervisor.mStoppingActivities, app,
- "mStoppingActivities");
- removeHistoryRecordsForApp(mStackSupervisor.mGoingToSleepActivities, app,
- "mGoingToSleepActivities");
- removeHistoryRecordsForApp(mStackSupervisor.mFinishingActivities, app,
- "mFinishingActivities");
- return mRemoveHistoryRecordsForApp.process(app);
+ forAllActivities(ActivityRecord::removeLaunchTickRunnable);
}
private void updateTransitLocked(int transit, ActivityOptions options) {
@@ -3329,9 +3070,9 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
topActivity.supportsEnterPipOnTaskSwitch = true;
}
- mRootActivityContainer.resumeFocusedStacksTopActivities();
+ mRootWindowContainer.resumeFocusedStacksTopActivities();
EventLogTags.writeWmTaskToFront(tr.mUserId, tr.mTaskId);
- mService.getTaskChangeNotificationController().notifyTaskMovedToFront(tr.getTaskInfo());
+ mAtmService.getTaskChangeNotificationController().notifyTaskMovedToFront(tr.getTaskInfo());
} finally {
getDisplay().continueUpdateImeTarget();
}
@@ -3353,14 +3094,14 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
// In LockTask mode, moving a locked task to the back of the stack may expose unlocked
// ones. Therefore we need to check if this operation is allowed.
- if (!mService.getLockTaskController().canMoveTaskToBack(tr)) {
+ if (!mAtmService.getLockTaskController().canMoveTaskToBack(tr)) {
return false;
}
// If we have a watcher, preflight the move before committing to it. First check
// for *other* available tasks, but if none are available, then try again allowing the
// current task to be selected.
- if (isTopStackOnDisplay() && mService.mController != null) {
+ if (isTopStackOnDisplay() && mAtmService.mController != null) {
ActivityRecord next = topRunningActivity(null, tr.mTaskId);
if (next == null) {
next = topRunningActivity(null, INVALID_TASK_ID);
@@ -3369,9 +3110,9 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
// ask watcher if this is allowed
boolean moveOK = true;
try {
- moveOK = mService.mController.activityResuming(next.packageName);
+ moveOK = mAtmService.mController.activityResuming(next.packageName);
} catch (RemoteException e) {
- mService.mController = null;
+ mAtmService.mController = null;
Watchdog.getInstance().setActivityController(null);
}
if (!moveOK) {
@@ -3397,12 +3138,12 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
// The new top activity is already resumed, so there's a good chance that nothing will
// get resumed below. So, update visibility now in case the transition is closed
// prematurely.
- mRootActivityContainer.ensureVisibilityAndConfig(null /* starting */,
+ mRootWindowContainer.ensureVisibilityAndConfig(null /* starting */,
getDisplay().mDisplayId, false /* markFrozenIfConfigChanged */,
false /* deferResume */);
}
- mRootActivityContainer.resumeFocusedStacksTopActivities();
+ mRootWindowContainer.resumeFocusedStacksTopActivities();
return true;
}
@@ -3422,7 +3163,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
}
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "stack.resize_" + mStackId);
- mService.deferWindowLayout();
+ mAtmService.deferWindowLayout();
try {
// Update override configurations of all tasks in the stack.
final Rect taskBounds = tempTaskBounds != null ? tempTaskBounds : bounds;
@@ -3438,7 +3179,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
ensureVisibleActivitiesConfiguration(topRunningActivity(), preserveWindows);
}
} finally {
- mService.continueWindowLayout();
+ mAtmService.continueWindowLayout();
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
}
@@ -3521,7 +3262,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
* @param app The app of the activity that died.
* @return result from removeHistoryRecordsForAppLocked.
*/
- boolean handleAppDiedLocked(WindowProcessController app) {
+ boolean handleAppDied(WindowProcessController app) {
if (mPausingActivity != null && mPausingActivity.app == app) {
if (DEBUG_PAUSE || DEBUG_CLEANUP) Slog.v(TAG_PAUSE,
"App died while pausing: " + mPausingActivity);
@@ -3532,7 +3273,8 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
mLastNoHistoryActivity = null;
}
- return removeHistoryRecordsForApp(app);
+ mStackSupervisor.removeHistoryRecords(app);
+ return mRemoveHistoryRecordsForApp.process(app);
}
boolean dump(FileDescriptor fd, PrintWriter pw, boolean dumpAll, boolean dumpClient,
@@ -3545,10 +3287,6 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
boolean printed = dumpActivities(fd, pw, dumpAll, dumpClient, dumpPackage, needSep);
- printed |= dumpHistoryList(fd, pw, mLruActivities, " ", "Run", false,
- !dumpAll, false, dumpPackage, true,
- " Running activities (most recent first):", null);
-
needSep = printed;
boolean pr = printThisActivity(pw, mPausingActivity, dumpPackage, needSep,
" mPausingActivity: ");
@@ -3664,15 +3402,16 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
}
final DisplayContent display = getDisplay();
- final boolean topFocused = mRootActivityContainer.isTopDisplayFocusedStack(this);
- if (DEBUG_TASK_MOVEMENT) Slog.d(TAG_WM, "removeChild: task=" + child);
+ if (DEBUG_TASK_MOVEMENT) {
+ Slog.d(TAG_WM, "removeChild: task=" + child + " reason=" + reason);
+ }
super.removeChild(child);
EventLogTags.writeWmRemoveTask(((Task) child).mTaskId, mStackId);
if (display.isSingleTaskInstance()) {
- mService.notifySingleTaskDisplayEmpty(display.mDisplayId);
+ mAtmService.notifySingleTaskDisplayEmpty(display.mDisplayId);
}
display.mDisplayContent.setLayoutNeeded();
@@ -3681,8 +3420,6 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
// Stack is now empty...
removeIfPossible();
}
-
- moveHomeStackToFrontIfNeeded(topFocused, display, reason);
}
@Override
@@ -3690,18 +3427,6 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
removeChild(child, "removeChild");
}
- void moveHomeStackToFrontIfNeeded(
- boolean wasTopFocusedStack, DisplayContent display, String reason) {
- if (!hasChild() && wasTopFocusedStack) {
- // We only need to adjust focused stack if this stack is in focus and we are not in the
- // process of moving the task to the top of the stack that will be focused.
- String myReason = reason + " leftTaskHistoryEmpty";
- if (!inMultiWindowMode() || adjustFocusToNextFocusableStack(myReason) == null) {
- display.moveHomeStackToFront(myReason);
- }
- }
- }
-
Task createTask(int taskId, ActivityInfo info, Intent intent,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
boolean toTop) {
@@ -3714,11 +3439,11 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
boolean toTop, ActivityRecord activity, ActivityRecord source,
ActivityOptions options) {
final Task task = Task.create(
- mService, taskId, info, intent, voiceSession, voiceInteractor, this);
+ mAtmService, taskId, info, intent, voiceSession, voiceInteractor, this);
// add the task to stack first, mTaskPositioner might need the stack association
addChild(task, toTop, (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0);
final int displayId = mDisplayId != INVALID_DISPLAY ? mDisplayId : DEFAULT_DISPLAY;
- final boolean isLockscreenShown = mService.mStackSupervisor.getKeyguardController()
+ final boolean isLockscreenShown = mAtmService.mStackSupervisor.getKeyguardController()
.isKeyguardOrAodShowing(displayId);
if (!mStackSupervisor.getLaunchParamsController()
.layoutTask(task, info.windowLayout, activity, source, options)
@@ -3780,7 +3505,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
// The task might have already been running and its visibility needs to be synchronized with
// the visibility of the stack / windows.
ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
- mRootActivityContainer.resumeFocusedStacksTopActivities();
+ mRootWindowContainer.resumeFocusedStacksTopActivities();
}
public void setAlwaysOnTop(boolean alwaysOnTop) {
@@ -3810,19 +3535,18 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
// Apps may depend on onResume()/onPause() being called in pairs.
if (setResume) {
r.setState(RESUMED, "moveToFrontAndResumeStateIfNeeded");
- updateLruList(r);
}
// If the activity was previously pausing, then ensure we transfer that as well
if (setPause) {
mPausingActivity = r;
- schedulePauseTimeoutForActivity(r);
+ r.schedulePauseTimeout();
}
// Move the stack in which we are placing the activity to the front.
moveToFront(reason);
// If the original state is resumed, there is no state change to update focused app.
// So here makes sure the activity focus is set if it is the top.
- if (origState == RESUMED && r == mRootActivityContainer.getTopResumedActivity()) {
- mService.setResumedActivityUncheckLocked(r, reason);
+ if (origState == RESUMED && r == mRootWindowContainer.getTopResumedActivity()) {
+ mAtmService.setResumedActivityUncheckLocked(r, reason);
}
}
@@ -3922,14 +3646,14 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
top.savePinnedStackBounds();
}
- mWindowManager.inSurfaceTransaction(() -> {
+ mWmService.inSurfaceTransaction(() -> {
final Task task = getBottomMostTask();
setWindowingMode(WINDOWING_MODE_UNDEFINED);
getDisplay().positionStackAtTop(this, false /* includingParents */);
mStackSupervisor.scheduleUpdatePictureInPictureModeIfNeeded(task, this);
- MetricsLoggerWrapper.logPictureInPictureFullScreen(mService.mContext,
+ MetricsLoggerWrapper.logPictureInPictureFullScreen(mAtmService.mContext,
task.effectiveUid, task.realActivity.flattenToString());
});
}
@@ -3986,6 +3710,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
final PooledConsumer c = PooledLambda.obtainConsumer(Task::alignToAdjustedBounds,
PooledLambda.__(Task.class), adjusted ? mAdjustedBounds : getRawBounds(),
insetBounds, alignBottom);
+ forAllTasks(c);
c.recycle();
}
@@ -4101,45 +3826,27 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
}
/**
- * Updates the passed-in {@code inOutBounds} based on the current state of the
- * pinned controller. This gets run *after* the override configuration is updated, so it's
- * safe to rely on the controller's state in here (though eventually this dependence should
- * be removed).
- *
- * This does NOT modify this TaskStack's configuration. However, it does, for the time-being,
- * update pinned controller state.
+ * Reset the current animation running on {@link #mBoundsAnimationTarget}.
*
- * @param inOutBounds the bounds to update (both input and output).
- * @return true if bounds were updated to some non-empty value.
+ * @param destinationBounds the final destination bounds
*/
- boolean calculatePinnedBoundsForConfigChange(Rect inOutBounds) {
- boolean animating = false;
- if ((mBoundsAnimatingRequested || mBoundsAnimating) && !mBoundsAnimationTarget.isEmpty()) {
- animating = true;
- getFinalAnimationBounds(mTmpRect2);
- } else {
- mTmpRect2.set(inOutBounds);
- }
- boolean updated = mDisplayContent.mPinnedStackControllerLocked.onTaskStackBoundsChanged(
- mTmpRect2, mTmpRect3);
- if (updated) {
- inOutBounds.set(mTmpRect3);
-
- // The final boundary is updated while there is an existing boundary animation. Let's
- // cancel this animation to prevent the obsolete animation overwritten updated bounds.
- if (animating && !inOutBounds.equals(mBoundsAnimationTarget)) {
- final DisplayContent displayContent = getDisplayContent();
- displayContent.mBoundsAnimationController.getHandler().post(() ->
- displayContent.mBoundsAnimationController.cancel(this));
- }
- // Once we've set the bounds based on the rotation of the old bounds in the new
- // orientation, clear the animation target bounds since they are obsolete, and
- // cancel any currently running animations
- mBoundsAnimationTarget.setEmpty();
- mBoundsAnimationSourceHintBounds.setEmpty();
- mCancelCurrentBoundsAnimation = true;
+ void resetCurrentBoundsAnimation(Rect destinationBounds) {
+ boolean animating = (mBoundsAnimatingRequested || mBoundsAnimating)
+ && !mBoundsAnimationTarget.isEmpty();
+
+ // The final boundary is updated while there is an existing boundary animation. Let's
+ // cancel this animation to prevent the obsolete animation overwritten updated bounds.
+ if (animating && !destinationBounds.equals(mBoundsAnimationTarget)) {
+ final BoundsAnimationController controller =
+ getDisplayContent().mBoundsAnimationController;
+ controller.getHandler().post(() -> controller.cancel(this));
}
- return updated;
+ // Once we've set the bounds based on the rotation of the old bounds in the new
+ // orientation, clear the animation target bounds since they are obsolete, and
+ // cancel any currently running animations
+ mBoundsAnimationTarget.setEmpty();
+ mBoundsAnimationSourceHintBounds.setEmpty();
+ mCancelCurrentBoundsAnimation = true;
}
/**
@@ -4383,7 +4090,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
mStackSupervisor.resizeDockedStackLocked(getRequestedOverrideBounds(), mTmpRect,
mTmpRect2, null, null, PRESERVE_WINDOWS);
}
- mRootActivityContainer.updateUIDsPresentOnDisplay();
+ mRootWindowContainer.updateUIDsPresentOnDisplay();
// Resume next focusable stack after reparenting to another display if we aren't removing
// the prevous display.
@@ -5414,11 +5121,11 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn
return false;
}
- return display != null ? display.isSleeping() : mService.isSleepingLocked();
+ return display != null ? display.isSleeping() : mAtmService.isSleepingLocked();
}
boolean shouldSleepOrShutDownActivities() {
- return shouldSleepActivities() || mService.mShuttingDown;
+ return shouldSleepActivities() || mAtmService.mShuttingDown;
}
public void dumpDebug(ProtoOutputStream proto, long fieldId,
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index 26d9dbce4a69..a380efc43a82 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -52,7 +52,9 @@ import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
import static com.android.server.wm.ActivityStack.ActivityState.PAUSED;
import static com.android.server.wm.ActivityStack.ActivityState.PAUSING;
+import static com.android.server.wm.ActivityStack.TAG_CLEANUP;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ALL;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CLEANUP;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_IDLE;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_PAUSE;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RECENTS;
@@ -71,10 +73,10 @@ import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLAS
import static com.android.server.wm.ActivityTaskManagerService.ANIMATE;
import static com.android.server.wm.ActivityTaskManagerService.H.FIRST_SUPERVISOR_STACK_MSG;
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
-import static com.android.server.wm.RootActivityContainer.MATCH_TASK_IN_STACKS_ONLY;
-import static com.android.server.wm.RootActivityContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS;
-import static com.android.server.wm.RootActivityContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE;
-import static com.android.server.wm.RootActivityContainer.TAG_STATES;
+import static com.android.server.wm.RootWindowContainer.MATCH_TASK_IN_STACKS_ONLY;
+import static com.android.server.wm.RootWindowContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS;
+import static com.android.server.wm.RootWindowContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE;
+import static com.android.server.wm.RootWindowContainer.TAG_STATES;
import static com.android.server.wm.Task.LOCK_TASK_AUTH_LAUNCHABLE;
import static com.android.server.wm.Task.LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
import static com.android.server.wm.Task.LOCK_TASK_AUTH_WHITELISTED;
@@ -242,7 +244,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
private static final int MAX_TASK_IDS_PER_USER = UserHandle.PER_USER_RANGE;
final ActivityTaskManagerService mService;
- RootActivityContainer mRootActivityContainer;
+ RootWindowContainer mRootWindowContainer;
/** The historial list of recent tasks including inactive tasks */
RecentTasks mRecentTasks;
@@ -562,7 +564,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
}
void moveRecentsStackToFront(String reason) {
- final ActivityStack recentsStack = mRootActivityContainer.getDefaultDisplay().getStack(
+ final ActivityStack recentsStack = mRootWindowContainer.getDefaultDisplay().getStack(
WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_RECENTS);
if (recentsStack != null) {
recentsStack.moveToFront(reason);
@@ -592,7 +594,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
// was 10, user 0 could only have taskIds 0 to 9, user 1: 10 to 19, user 2: 20 to 29, so on.
int candidateTaskId = nextTaskIdForUser(currentTaskId, userId);
while (mRecentTasks.containsTaskId(candidateTaskId, userId)
- || mRootActivityContainer.anyTaskForId(
+ || mRootWindowContainer.anyTaskForId(
candidateTaskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS) != null) {
candidateTaskId = nextTaskIdForUser(candidateTaskId, userId);
if (candidateTaskId == currentTaskId) {
@@ -774,7 +776,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
boolean andResume, boolean checkConfig) throws RemoteException {
- if (!mRootActivityContainer.allPausedActivitiesComplete()) {
+ if (!mRootWindowContainer.allPausedActivitiesComplete()) {
// While there are activities pausing we skipping starting any new activities until
// pauses are complete. NOTE: that we also do this for activities that are starting in
// the paused state because they will first be resumed then paused on the client side.
@@ -812,7 +814,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
// Deferring resume here because we're going to launch new activity shortly.
// We don't want to perform a redundant launch of the same record while ensuring
// configurations and trying to resume top activity of focused stack.
- mRootActivityContainer.ensureVisibilityAndConfig(r, r.getDisplayId(),
+ mRootWindowContainer.ensureVisibilityAndConfig(r, r.getDisplayId(),
false /* markFrozenIfConfigChanged */, true /* deferResume */);
}
@@ -956,9 +958,6 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
}
r.launchFailed = false;
- if (stack.updateLruList(r)) {
- Slog.w(TAG, "Activity " + r + " being launched, but already in LRU list");
- }
// TODO(lifecycler): Resume or pause requests are done as part of launch transaction,
// so updating the state should be done accordingly.
@@ -982,7 +981,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
// launching the initial activity (that is, home), so that it can have
// a chance to initialize itself while in the background, making the
// switch back to it faster and look better.
- if (mRootActivityContainer.isTopDisplayFocusedStack(stack)) {
+ if (mRootWindowContainer.isTopDisplayFocusedStack(stack)) {
mService.getActivityStartController().startSetupActivity();
}
@@ -1123,7 +1122,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
}
final DisplayContent displayContent =
- mRootActivityContainer.getDisplayContentOrCreate(launchDisplayId);
+ mRootWindowContainer.getDisplayContentOrCreate(launchDisplayId);
if (displayContent == null || displayContent.isRemoved()) {
Slog.w(TAG, "Launch on display check: display not found");
return false;
@@ -1339,7 +1338,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
// Check if able to finish booting when device is booting and all resumed activities
// are idle.
- if ((mService.isBooting() && mRootActivityContainer.allResumedActivitiesIdle())
+ if ((mService.isBooting() && mRootWindowContainer.allResumedActivitiesIdle())
|| fromTimeout) {
booting = checkFinishBootingLocked();
}
@@ -1349,7 +1348,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
r.mRelaunchReason = RELAUNCH_REASON_NONE;
}
- if (mRootActivityContainer.allResumedActivitiesIdle()) {
+ if (mRootWindowContainer.allResumedActivitiesIdle()) {
if (r != null) {
mService.scheduleAppGcsLocked();
}
@@ -1362,7 +1361,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
}
mLaunchingActivityWakeLock.release();
}
- mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
+ mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
}
// Atomically retrieve all of the other things to do.
@@ -1418,7 +1417,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
//mWindowManager.dump();
if (activityRemoved) {
- mRootActivityContainer.resumeFocusedStacksTopActivities();
+ mRootWindowContainer.resumeFocusedStacksTopActivities();
}
return r;
@@ -1445,7 +1444,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
task.setBounds(bounds);
ActivityStack stack =
- mRootActivityContainer.getLaunchStack(null, options, task, ON_TOP);
+ mRootWindowContainer.getLaunchStack(null, options, task, ON_TOP);
if (stack != currentStack) {
moveHomeStackToFrontIfNeeded(flags, stack.getDisplay(), reason);
@@ -1510,13 +1509,13 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
}
private void deferUpdateRecentsHomeStackBounds() {
- mRootActivityContainer.deferUpdateBounds(ACTIVITY_TYPE_RECENTS);
- mRootActivityContainer.deferUpdateBounds(ACTIVITY_TYPE_HOME);
+ mRootWindowContainer.deferUpdateBounds(ACTIVITY_TYPE_RECENTS);
+ mRootWindowContainer.deferUpdateBounds(ACTIVITY_TYPE_HOME);
}
private void continueUpdateRecentsHomeStackBounds() {
- mRootActivityContainer.continueUpdateBounds(ACTIVITY_TYPE_RECENTS);
- mRootActivityContainer.continueUpdateBounds(ACTIVITY_TYPE_HOME);
+ mRootWindowContainer.continueUpdateBounds(ACTIVITY_TYPE_RECENTS);
+ mRootWindowContainer.continueUpdateBounds(ACTIVITY_TYPE_HOME);
}
void notifyAppTransitionDone() {
@@ -1524,7 +1523,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
for (int i = mResizingTasksDuringAnimation.size() - 1; i >= 0; i--) {
final int taskId = mResizingTasksDuringAnimation.valueAt(i);
final Task task =
- mRootActivityContainer.anyTaskForId(taskId, MATCH_TASK_IN_STACKS_ONLY);
+ mRootWindowContainer.anyTaskForId(taskId, MATCH_TASK_IN_STACKS_ONLY);
if (task != null) {
task.setTaskDockedResizing(false);
}
@@ -1543,7 +1542,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
try {
final int windowingMode = fromStack.getWindowingMode();
final DisplayContent toDisplay =
- mRootActivityContainer.getDisplayContent(toDisplayId);
+ mRootWindowContainer.getDisplayContent(toDisplayId);
if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
// We are moving all tasks from the docked stack to the fullscreen stack,
@@ -1575,8 +1574,8 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
fromStack, toDisplay, onTop, schedulePictureInPictureModeChange);
}
- mRootActivityContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
- mRootActivityContainer.resumeFocusedStacksTopActivities();
+ mRootWindowContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
+ mRootWindowContainer.resumeFocusedStacksTopActivities();
} finally {
mAllowDockedStackResize = true;
mService.continueWindowLayout();
@@ -1628,7 +1627,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
}
final ActivityStack stack =
- mRootActivityContainer.getDefaultDisplay().getSplitScreenPrimaryStack();
+ mRootWindowContainer.getDefaultDisplay().getSplitScreenPrimaryStack();
if (stack == null) {
Slog.w(TAG, "resizeDockedStackLocked: docked stack not found");
return;
@@ -1668,7 +1667,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
// static stacks need to be adjusted so they don't overlap with the docked stack.
// We get the bounds to use from window manager which has been adjusted for any
// screen controls and is also the same for all stacks.
- final DisplayContent display = mRootActivityContainer.getDefaultDisplay();
+ final DisplayContent display = mRootWindowContainer.getDefaultDisplay();
final Rect otherTaskRect = new Rect();
for (int i = display.getStackCount() - 1; i >= 0; --i) {
final ActivityStack current = display.getStackAt(i);
@@ -1716,7 +1715,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
void resizePinnedStackLocked(Rect pinnedBounds, Rect tempPinnedTaskBounds) {
// TODO(multi-display): The display containing the stack should be passed in.
final ActivityStack stack =
- mRootActivityContainer.getDefaultDisplay().getPinnedStack();
+ mRootWindowContainer.getDefaultDisplay().getPinnedStack();
if (stack == null) {
Slog.w(TAG, "resizePinnedStackLocked: pinned stack not found");
return;
@@ -1799,7 +1798,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
boolean removeTaskById(int taskId, boolean killProcess, boolean removeFromRecents,
String reason) {
final Task task =
- mRootActivityContainer.anyTaskForId(taskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
+ mRootWindowContainer.anyTaskForId(taskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
if (task != null) {
removeTask(task, killProcess, removeFromRecents, reason);
return true;
@@ -1894,7 +1893,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
*/
boolean restoreRecentTaskLocked(Task task, ActivityOptions aOptions, boolean onTop) {
final ActivityStack stack =
- mRootActivityContainer.getLaunchStack(null, aOptions, task, onTop);
+ mRootWindowContainer.getLaunchStack(null, aOptions, task, onTop);
final ActivityStack currentStack = task.getStack();
if (currentStack == stack) {
@@ -1995,7 +1994,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
}
}
- mRootActivityContainer.applySleepTokens(false /* applyToStacks */);
+ mRootWindowContainer.applySleepTokens(false /* applyToStacks */);
checkReadyForSleepLocked(true /* allowDelay */);
}
@@ -2006,7 +2005,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
boolean timedout = false;
final long endTime = System.currentTimeMillis() + timeout;
while (true) {
- if (!mRootActivityContainer.putStacksToSleep(
+ if (!mRootWindowContainer.putStacksToSleep(
true /* allowDelay */, true /* shuttingDown */)) {
long timeRemaining = endTime - System.currentTimeMillis();
if (timeRemaining > 0) {
@@ -2053,13 +2052,13 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
return;
}
- if (!mRootActivityContainer.putStacksToSleep(
+ if (!mRootWindowContainer.putStacksToSleep(
allowDelay, false /* shuttingDown */)) {
return;
}
// Send launch end powerhint before going sleep
- mRootActivityContainer.sendPowerHintForLaunchEndIfNeeded();
+ mRootWindowContainer.sendPowerHintForLaunchEndIfNeeded();
removeSleepTimeouts();
@@ -2077,10 +2076,10 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
final ActivityStack stack = r.getActivityStack();
if (stack.getDisplay().allResumedActivitiesComplete()) {
- mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
+ mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
// Make sure activity & window visibility should be identical
// for all displays in this stage.
- mRootActivityContainer.executeAppTransitionForAllDisplay();
+ mRootWindowContainer.executeAppTransitionForAllDisplay();
return true;
}
return false;
@@ -2109,7 +2108,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
/** Checks whether the userid is a profile of the current user. */
boolean isCurrentProfileLocked(int userId) {
- if (userId == mRootActivityContainer.mCurrentUser) return true;
+ if (userId == mRootWindowContainer.mCurrentUser) return true;
return mService.mAmInternal.isCurrentProfile(userId);
}
@@ -2135,7 +2134,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
boolean remove, boolean processPausingActivities) {
ArrayList<ActivityRecord> stops = null;
- final boolean nowVisible = mRootActivityContainer.allResumedActivitiesVisible();
+ final boolean nowVisible = mRootWindowContainer.allResumedActivitiesVisible();
for (int activityNdx = mStoppingActivities.size() - 1; activityNdx >= 0; --activityNdx) {
ActivityRecord s = mStoppingActivities.get(activityNdx);
@@ -2162,7 +2161,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
if (!processPausingActivities && s.isState(PAUSING)) {
// Defer processing pausing activities in this iteration and reschedule
// a delayed idle to reprocess it again
- removeTimeoutsForActivityLocked(idleActivity);
+ removeIdleTimeoutForActivity(idleActivity);
scheduleIdleTimeoutLocked(idleActivity);
continue;
}
@@ -2181,13 +2180,36 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
return stops;
}
+ void removeHistoryRecords(WindowProcessController app) {
+ removeHistoryRecords(mStoppingActivities, app, "mStoppingActivities");
+ removeHistoryRecords(mGoingToSleepActivities, app, "mGoingToSleepActivities");
+ removeHistoryRecords(mFinishingActivities, app, "mFinishingActivities");
+ }
+
+ private void removeHistoryRecords(ArrayList<ActivityRecord> list, WindowProcessController app,
+ String listName) {
+ int i = list.size();
+ if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
+ "Removing app " + this + " from list " + listName + " with " + i + " entries");
+ while (i > 0) {
+ i--;
+ ActivityRecord r = list.get(i);
+ if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP, "Record #" + i + " " + r);
+ if (r.app == app) {
+ if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP, "---> REMOVING this entry!");
+ list.remove(i);
+ r.removeTimeouts();
+ }
+ }
+ }
+
public void dump(PrintWriter pw, String prefix) {
pw.println();
pw.println("ActivityStackSupervisor state:");
- mRootActivityContainer.dump(pw, prefix);
+ mRootWindowContainer.dump(pw, prefix);
pw.print(prefix);
pw.println("mCurTaskIdForUser=" + mCurTaskIdForUser);
- pw.println(prefix + "mUserStackInFront=" + mRootActivityContainer.mUserStackInFront);
+ pw.println(prefix + "mUserStackInFront=" + mRootWindowContainer.mUserStackInFront);
if (!mWaitingForActivityVisible.isEmpty()) {
pw.println(prefix + "mWaitingForActivityVisible=");
for (int i = 0; i < mWaitingForActivityVisible.size(); ++i) {
@@ -2195,7 +2217,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
}
}
pw.print(prefix); pw.print("isHomeRecentsComponent=");
- pw.print(mRecentTasks.isRecentsComponentHomeActivity(mRootActivityContainer.mCurrentUser));
+ pw.print(mRecentTasks.isRecentsComponentHomeActivity(mRootWindowContainer.mCurrentUser));
getKeyguardController().dump(pw, prefix);
mService.getLockTaskController().dump(pw, prefix);
@@ -2313,7 +2335,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
*/
void updateTopResumedActivityIfNeeded() {
final ActivityRecord prevTopActivity = mTopResumedActivity;
- final ActivityStack topStack = mRootActivityContainer.getTopDisplayFocusedStack();
+ final ActivityStack topStack = mRootWindowContainer.getTopDisplayFocusedStack();
if (topStack == null || topStack.mResumedActivity == prevTopActivity) {
return;
}
@@ -2371,7 +2393,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
scheduleTopResumedActivityStateIfNeeded();
}
- void removeTimeoutsForActivityLocked(ActivityRecord r) {
+ void removeIdleTimeoutForActivity(ActivityRecord r) {
if (DEBUG_IDLE) Slog.d(TAG_IDLE, "removeTimeoutsForActivity: Callers="
+ Debug.getCallers(4));
mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
@@ -2427,7 +2449,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
}
final DisplayContent preferredDisplay =
- mRootActivityContainer.getDisplayContent(preferredDisplayId);
+ mRootWindowContainer.getDisplayContent(preferredDisplayId);
final boolean singleTaskInstance = preferredDisplay != null
&& preferredDisplay.isSingleTaskInstance();
@@ -2640,7 +2662,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
} break;
case RESUME_TOP_ACTIVITY_MSG: {
synchronized (mService.mGlobalLock) {
- mRootActivityContainer.resumeFocusedStacksTopActivities();
+ mRootWindowContainer.resumeFocusedStacksTopActivities();
}
} break;
case SLEEP_TIMEOUT_MSG: {
@@ -2692,7 +2714,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
mHandler.removeMessages(REPORT_HOME_CHANGED_MSG);
// Start home activities on displays with no activities.
- mRootActivityContainer.startHomeOnEmptyDisplays("homeChanged");
+ mRootWindowContainer.startHomeOnEmptyDisplays("homeChanged");
}
} break;
case TOP_RESUMED_STATE_LOSS_TIMEOUT_MSG: {
@@ -2758,7 +2780,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
mWindowManager.prepareAppTransition(TRANSIT_DOCK_TASK_FROM_RECENTS, false);
}
- task = mRootActivityContainer.anyTaskForId(taskId,
+ task = mRootWindowContainer.anyTaskForId(taskId,
MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE, activityOptions, ON_TOP);
if (task == null) {
continueUpdateRecentsHomeStackBounds();
@@ -2772,7 +2794,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
// from whatever is started from the recents activity, so move the home stack
// forward.
// TODO (b/115289124): Multi-display supports for recents.
- mRootActivityContainer.getDefaultDisplay().moveHomeStackToFront(
+ mRootWindowContainer.getDefaultDisplay().moveHomeStackToFront(
"startActivityFromRecents");
}
@@ -2782,7 +2804,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
&& task.getRootActivity() != null) {
final ActivityRecord targetActivity = task.getTopNonFinishingActivity();
- mRootActivityContainer.sendPowerHintForLaunchStartIfNeeded(
+ mRootWindowContainer.sendPowerHintForLaunchStartIfNeeded(
true /* forceSend */, targetActivity);
final LaunchingState launchingState =
mActivityMetricsLogger.notifyActivityLaunching(task.intent);
diff --git a/services/core/java/com/android/server/wm/ActivityStartController.java b/services/core/java/com/android/server/wm/ActivityStartController.java
index 4c165df0ed4c..955e581a7db3 100644
--- a/services/core/java/com/android/server/wm/ActivityStartController.java
+++ b/services/core/java/com/android/server/wm/ActivityStartController.java
@@ -182,7 +182,7 @@ public class ActivityStartController {
options.setLaunchDisplayId(displayId);
final DisplayContent display =
- mService.mRootActivityContainer.getDisplayContent(displayId);
+ mService.mRootWindowContainer.getDisplayContent(displayId);
// The home activity will be started later, defer resuming to avoid unneccerary operations
// (e.g. start home recursively) when creating home stack.
mSupervisor.beginDeferResume();
diff --git a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
index b2fb93d1e98e..df97caa76d2d 100644
--- a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
+++ b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
@@ -69,7 +69,7 @@ class ActivityStartInterceptor {
private final ActivityTaskManagerService mService;
private final ActivityStackSupervisor mSupervisor;
- private final RootActivityContainer mRootActivityContainer;
+ private final RootWindowContainer mRootWindowContainer;
private final Context mServiceContext;
// UserManager cannot be final as it's not ready when this class is instantiated during boot
@@ -102,15 +102,15 @@ class ActivityStartInterceptor {
ActivityStartInterceptor(
ActivityTaskManagerService service, ActivityStackSupervisor supervisor) {
- this(service, supervisor, service.mRootActivityContainer, service.mContext);
+ this(service, supervisor, service.mRootWindowContainer, service.mContext);
}
@VisibleForTesting
ActivityStartInterceptor(ActivityTaskManagerService service, ActivityStackSupervisor supervisor,
- RootActivityContainer root, Context context) {
+ RootWindowContainer root, Context context) {
mService = service;
mSupervisor = supervisor;
- mRootActivityContainer = root;
+ mRootWindowContainer = root;
mServiceContext = context;
}
@@ -252,7 +252,8 @@ class ActivityStartInterceptor {
final SuspendDialogInfo dialogInfo = pmi.getSuspendedDialogInfo(suspendedPackage,
suspendingPackage, mUserId);
mIntent = SuspendedAppActivity.createSuspendedAppInterceptIntent(suspendedPackage,
- suspendingPackage, dialogInfo, mUserId);
+ suspendingPackage, dialogInfo, deferCrossProfileAppsAnimationIfNecessary(),
+ mUserId);
mCallingPid = mRealCallingPid;
mCallingUid = mRealCallingUid;
mResolvedType = null;
@@ -301,7 +302,8 @@ class ActivityStartInterceptor {
FLAG_CANCEL_CURRENT | FLAG_ONE_SHOT | FLAG_IMMUTABLE);
final KeyguardManager km = (KeyguardManager) mServiceContext
.getSystemService(KEYGUARD_SERVICE);
- final Intent newIntent = km.createConfirmDeviceCredentialIntent(null, null, userId);
+ final Intent newIntent = km.createConfirmDeviceCredentialIntent(null, null, userId,
+ true /* disallowBiometricsIfPolicyExists */);
if (newIntent == null) {
return null;
}
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 674955e20859..a2b9d956d01e 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -51,7 +51,6 @@ import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS;
import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
-import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
@@ -145,7 +144,7 @@ class ActivityStarter {
private static final int INVALID_LAUNCH_MODE = -1;
private final ActivityTaskManagerService mService;
- private final RootActivityContainer mRootActivityContainer;
+ private final RootWindowContainer mRootWindowContainer;
private final ActivityStackSupervisor mSupervisor;
private final ActivityStartInterceptor mInterceptor;
private final ActivityStartController mController;
@@ -507,7 +506,7 @@ class ActivityStarter {
ActivityStackSupervisor supervisor, ActivityStartInterceptor interceptor) {
mController = controller;
mService = service;
- mRootActivityContainer = service.mRootActivityContainer;
+ mRootWindowContainer = service.mRootWindowContainer;
mSupervisor = supervisor;
mInterceptor = interceptor;
reset(true);
@@ -615,7 +614,7 @@ class ActivityStarter {
int res;
synchronized (mService.mGlobalLock) {
- final ActivityStack stack = mRootActivityContainer.getTopDisplayFocusedStack();
+ final ActivityStack stack = mRootWindowContainer.getTopDisplayFocusedStack();
stack.mConfigWillChange = mRequest.globalConfig != null
&& mService.getGlobalConfiguration().diff(mRequest.globalConfig) != 0;
if (DEBUG_CONFIGURATION) {
@@ -846,7 +845,7 @@ class ActivityStarter {
ActivityRecord sourceRecord = null;
ActivityRecord resultRecord = null;
if (resultTo != null) {
- sourceRecord = mRootActivityContainer.isInAnyStack(resultTo);
+ sourceRecord = mRootWindowContainer.isInAnyStack(resultTo);
if (DEBUG_RESULTS) {
Slog.v(TAG_RESULTS, "Will send result to " + resultTo + " " + sourceRecord);
}
@@ -1071,7 +1070,7 @@ class ActivityStarter {
if (DEBUG_PERMISSIONS_REVIEW) {
final ActivityStack focusedStack =
- mRootActivityContainer.getTopDisplayFocusedStack();
+ mRootWindowContainer.getTopDisplayFocusedStack();
Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
true, false) + "} from uid " + callingUid + " on display "
+ (focusedStack == null ? DEFAULT_DISPLAY : focusedStack.mDisplayId));
@@ -1105,7 +1104,7 @@ class ActivityStarter {
r.appTimeTracker = sourceRecord.appTimeTracker;
}
- final ActivityStack stack = mRootActivityContainer.getTopDisplayFocusedStack();
+ final ActivityStack stack = mRootWindowContainer.getTopDisplayFocusedStack();
// If we are starting an activity that is not from the same uid as the currently resumed
// one, check whether app switches are allowed.
@@ -1439,7 +1438,7 @@ class ActivityStarter {
// update the configuration for changing to different display.
final ActivityRecord currentTop = startedActivityStack.topRunningActivity();
if (currentTop != null && currentTop.shouldUpdateConfigForDisplayChanged()) {
- mRootActivityContainer.ensureVisibilityAndConfig(
+ mRootWindowContainer.ensureVisibilityAndConfig(
currentTop, currentTop.getDisplayId(),
true /* markFrozenIfConfigChanged */, false /* deferResume */);
}
@@ -1526,7 +1525,7 @@ class ActivityStarter {
// If the activity being launched is the same as the one currently at the top, then
// we need to check if it should only be launched once.
- final ActivityStack topStack = mRootActivityContainer.getTopDisplayFocusedStack();
+ final ActivityStack topStack = mRootWindowContainer.getTopDisplayFocusedStack();
startResult = deliverToCurrentTopIfNeeded(topStack);
if (startResult != START_SUCCESS) {
return startResult;
@@ -1568,7 +1567,7 @@ class ActivityStarter {
mTargetStack.mLastPausedActivity = null;
- mRootActivityContainer.sendPowerHintForLaunchStartIfNeeded(
+ mRootWindowContainer.sendPowerHintForLaunchStartIfNeeded(
false /* forceSend */, mStartActivity);
mTargetStack.startActivityLocked(mStartActivity, topStack.getTopNonFinishingActivity(),
@@ -1596,16 +1595,16 @@ class ActivityStarter {
// task stack to be focusable, then ensure that we now update the focused stack
// accordingly.
if (mTargetStack.isFocusable()
- && !mRootActivityContainer.isTopDisplayFocusedStack(mTargetStack)) {
+ && !mRootWindowContainer.isTopDisplayFocusedStack(mTargetStack)) {
mTargetStack.moveToFront("startActivityInner");
}
- mRootActivityContainer.resumeFocusedStacksTopActivities(
+ mRootWindowContainer.resumeFocusedStacksTopActivities(
mTargetStack, mStartActivity, mOptions);
}
} else if (mStartActivity != null) {
mSupervisor.mRecentTasks.add(mStartActivity.getTask());
}
- mRootActivityContainer.updateUserStack(mStartActivity.mUserId, mTargetStack);
+ mRootWindowContainer.updateUserStack(mStartActivity.mUserId, mTargetStack);
mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(),
preferredWindowingMode, mPreferredDisplayId, mTargetStack);
@@ -1645,7 +1644,7 @@ class ActivityStarter {
// Do not start home activity if it cannot be launched on preferred display. We are not
// doing this in ActivityStackSupervisor#canPlaceEntityOnDisplay because it might
// fallback to launch on other displays.
- if (r.isActivityTypeHome() && !mRootActivityContainer.canStartHomeOnDisplay(r.info,
+ if (r.isActivityTypeHome() && !mRootWindowContainer.canStartHomeOnDisplay(r.info,
mPreferredDisplayId, true /* allowInstrumenting */)) {
Slog.w(TAG, "Cannot launch home on display " + mPreferredDisplayId);
return START_CANCELED;
@@ -1688,19 +1687,9 @@ class ActivityStarter {
return START_SUCCESS;
}
- // True if we are clearing top and resetting of a standard (default) launch mode
- // ({@code LAUNCH_MULTIPLE}) activity. The existing activity will be finished.
- final boolean clearTopAndResetStandardLaunchMode =
- (mLaunchFlags & (FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED))
- == (FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)
- && mLaunchMode == LAUNCH_MULTIPLE;
-
boolean clearTaskForReuse = false;
if (reusedTask != null) {
- // If mStartActivity does not have a task associated with it, associate it with the
- // reused activity's task. Do not do so if we're clearing top and resetting for a
- // standard launchMode activity.
- if (mStartActivity.getTask() == null && !clearTopAndResetStandardLaunchMode) {
+ if (mStartActivity.getTask() == null) {
mStartActivity.setTaskForReuse(reusedTask);
clearTaskForReuse = true;
}
@@ -1721,7 +1710,7 @@ class ActivityStarter {
}
}
- mRootActivityContainer.sendPowerHintForLaunchStartIfNeeded(false /* forceSend */,
+ mRootWindowContainer.sendPowerHintForLaunchStartIfNeeded(false /* forceSend */,
targetTaskTop);
setTargetStackIfNeeded(targetTaskTop);
@@ -1804,7 +1793,7 @@ class ActivityStarter {
// For paranoia, make sure we have correctly resumed the top activity.
topStack.mLastPausedActivity = null;
if (mDoResume) {
- mRootActivityContainer.resumeFocusedStacksTopActivities();
+ mRootWindowContainer.resumeFocusedStacksTopActivities();
}
ActivityOptions.abort(mOptions);
if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
@@ -2057,7 +2046,7 @@ class ActivityStarter {
if (mOptions.getLaunchTaskId() != -1 && mOptions.getTaskOverlay()) {
r.mTaskOverlay = true;
if (!mOptions.canTaskOverlayResume()) {
- final Task task = mRootActivityContainer.anyTaskForId(
+ final Task task = mRootWindowContainer.anyTaskForId(
mOptions.getLaunchTaskId());
final ActivityRecord top = task != null
? task.getTopNonFinishingActivity() : null;
@@ -2094,7 +2083,7 @@ class ActivityStarter {
if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
ActivityRecord checkedCaller = sourceRecord;
if (checkedCaller == null) {
- checkedCaller = mRootActivityContainer.getTopDisplayFocusedStack()
+ checkedCaller = mRootWindowContainer.getTopDisplayFocusedStack()
.topRunningNonDelayedActivityLocked(mNotTop);
}
if (!checkedCaller.mActivityComponent.equals(r.mActivityComponent)) {
@@ -2258,7 +2247,7 @@ class ActivityStarter {
putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
ActivityRecord intentActivity = null;
if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
- Task launchTask = mRootActivityContainer.anyTaskForId(mOptions.getLaunchTaskId());
+ Task launchTask = mRootWindowContainer.anyTaskForId(mOptions.getLaunchTaskId());
if (launchTask != null) {
return launchTask;
}
@@ -2266,17 +2255,17 @@ class ActivityStarter {
if (LAUNCH_SINGLE_INSTANCE == mLaunchMode) {
// There can be one and only one instance of single instance activity in the
// history, and it is always in its own unique task, so we do a special search.
- intentActivity = mRootActivityContainer.findActivity(mIntent, mStartActivity.info,
+ intentActivity = mRootWindowContainer.findActivity(mIntent, mStartActivity.info,
mStartActivity.isActivityTypeHome());
} else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
// For the launch adjacent case we only want to put the activity in an existing
// task if the activity already exists in the history.
- intentActivity = mRootActivityContainer.findActivity(mIntent, mStartActivity.info,
+ intentActivity = mRootWindowContainer.findActivity(mIntent, mStartActivity.info,
!(LAUNCH_SINGLE_TASK == mLaunchMode));
} else {
// Otherwise find the best task to put the activity in.
intentActivity =
- mRootActivityContainer.findTask(mStartActivity, mPreferredDisplayId);
+ mRootWindowContainer.findTask(mStartActivity, mPreferredDisplayId);
}
}
@@ -2393,11 +2382,11 @@ class ActivityStarter {
private void resumeTargetStackIfNeeded() {
if (mDoResume) {
- mRootActivityContainer.resumeFocusedStacksTopActivities(mTargetStack, null, mOptions);
+ mRootWindowContainer.resumeFocusedStacksTopActivities(mTargetStack, null, mOptions);
} else {
ActivityOptions.abort(mOptions);
}
- mRootActivityContainer.updateUserStack(mStartActivity.mUserId, mTargetStack);
+ mRootWindowContainer.updateUserStack(mStartActivity.mUserId, mTargetStack);
}
private void setNewTask(Task taskToAffiliate) {
@@ -2489,7 +2478,7 @@ class ActivityStarter {
}
final ActivityStack currentStack = task != null ? task.getStack() : null;
- final ActivityStack focusedStack = mRootActivityContainer.getTopDisplayFocusedStack();
+ final ActivityStack focusedStack = mRootWindowContainer.getTopDisplayFocusedStack();
if (currentStack != null) {
if (focusedStack != currentStack) {
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
@@ -2510,18 +2499,18 @@ class ActivityStarter {
if (mPreferredDisplayId != DEFAULT_DISPLAY) {
// Try to put the activity in a stack on a secondary display.
- stack = mRootActivityContainer.getValidLaunchStackOnDisplay(
+ stack = mRootWindowContainer.getValidLaunchStackOnDisplay(
mPreferredDisplayId, r, aOptions, mLaunchParams);
if (stack == null) {
// If source display is not suitable - look for topmost valid stack in the system.
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
"computeStackFocus: Can't launch on mPreferredDisplayId="
+ mPreferredDisplayId + ", looking on all displays.");
- stack = mRootActivityContainer.getNextValidLaunchStack(r, mPreferredDisplayId);
+ stack = mRootWindowContainer.getNextValidLaunchStack(r, mPreferredDisplayId);
}
}
if (stack == null) {
- stack = mRootActivityContainer.getLaunchStack(r, aOptions, task, ON_TOP);
+ stack = mRootWindowContainer.getLaunchStack(r, aOptions, task, ON_TOP);
}
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
+ r + " stackId=" + stack.mStackId);
@@ -2531,7 +2520,7 @@ class ActivityStarter {
/** Check if provided activity record can launch in currently focused stack. */
// TODO: This method can probably be consolidated into getLaunchStack() below.
private boolean canLaunchIntoFocusedStack(ActivityRecord r, boolean newTask) {
- final ActivityStack focusedStack = mRootActivityContainer.getTopDisplayFocusedStack();
+ final ActivityStack focusedStack = mRootWindowContainer.getTopDisplayFocusedStack();
final boolean canUseFocusedStack;
if (focusedStack.isActivityTypeAssistant()) {
canUseFocusedStack = r.isActivityTypeAssistant();
@@ -2576,13 +2565,13 @@ class ActivityStarter {
final boolean onTop =
(aOptions == null || !aOptions.getAvoidMoveToFront()) && !mLaunchTaskBehind;
final ActivityStack stack =
- mRootActivityContainer.getLaunchStack(r, aOptions, task, onTop, mLaunchParams,
+ mRootWindowContainer.getLaunchStack(r, aOptions, task, onTop, mLaunchParams,
mRequest.realCallingPid, mRequest.realCallingUid);
return stack;
}
// Otherwise handle adjacent launch.
- final ActivityStack focusedStack = mRootActivityContainer.getTopDisplayFocusedStack();
+ final ActivityStack focusedStack = mRootWindowContainer.getTopDisplayFocusedStack();
// The parent activity doesn't want to launch the activity on top of itself, but
// instead tries to put it onto other side in side-by-side mode.
final ActivityStack parentStack = task != null ? task.getStack(): focusedStack;
@@ -2601,7 +2590,7 @@ class ActivityStarter {
// If parent was in docked stack, the natural place to launch another activity
// will be fullscreen, so it can appear alongside the docked window.
final int activityType =
- mRootActivityContainer.resolveActivityType(r, mOptions, task);
+ mRootWindowContainer.resolveActivityType(r, mOptions, task);
return parentStack.getDisplay().getOrCreateStack(
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, activityType, ON_TOP);
} else {
@@ -2609,10 +2598,10 @@ class ActivityStarter {
// and if yes, we will launch into that stack. If not, we just put the new
// activity into parent's stack, because we can't find a better place.
final ActivityStack dockedStack =
- mRootActivityContainer.getDefaultDisplay().getSplitScreenPrimaryStack();
+ mRootWindowContainer.getDefaultDisplay().getSplitScreenPrimaryStack();
if (dockedStack != null && !dockedStack.shouldBeVisible(r)) {
// There is a docked stack, but it isn't visible, so we can't launch into that.
- return mRootActivityContainer.getLaunchStack(r, aOptions, task, ON_TOP);
+ return mRootWindowContainer.getLaunchStack(r, aOptions, task, ON_TOP);
} else {
return dockedStack;
}
@@ -2819,7 +2808,7 @@ class ActivityStarter {
prefix = prefix + " ";
pw.print(prefix);
pw.print("mCurrentUser=");
- pw.println(mRootActivityContainer.mCurrentUser);
+ pw.println(mRootWindowContainer.mCurrentUser);
pw.print(prefix);
pw.print("mLastStartReason=");
pw.println(mLastStartReason);
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index f0bc4129f4ef..ac1dbc4b755a 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -117,8 +117,8 @@ import static com.android.server.wm.ActivityTaskManagerService.H.REPORT_TIME_TRA
import static com.android.server.wm.ActivityTaskManagerService.UiHandler.DISMISS_DIALOG_UI_MSG;
import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE;
import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_ORIGINAL_POSITION;
-import static com.android.server.wm.RootActivityContainer.MATCH_TASK_IN_STACKS_ONLY;
-import static com.android.server.wm.RootActivityContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS;
+import static com.android.server.wm.RootWindowContainer.MATCH_TASK_IN_STACKS_ONLY;
+import static com.android.server.wm.RootWindowContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS;
import static com.android.server.wm.Task.LOCK_TASK_AUTH_DONT_LOCK;
import static com.android.server.wm.Task.REPARENT_KEEP_STACK_AT_FRONT;
import static com.android.server.wm.Task.REPARENT_LEAVE_STACK_IN_PLACE;
@@ -156,6 +156,8 @@ import android.app.WindowConfiguration;
import android.app.admin.DevicePolicyCache;
import android.app.assist.AssistContent;
import android.app.assist.AssistStructure;
+import android.app.servertransaction.ClientTransaction;
+import android.app.servertransaction.EnterPipRequestedItem;
import android.app.usage.UsageStatsManagerInternal;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
@@ -304,7 +306,7 @@ import java.util.Set;
public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityTaskManagerService" : TAG_ATM;
private static final String TAG_STACK = TAG + POSTFIX_STACK;
- private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH;
+ static final String TAG_SWITCH = TAG + POSTFIX_SWITCH;
private static final String TAG_IMMERSIVE = TAG + POSTFIX_IMMERSIVE;
private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
private static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY;
@@ -374,7 +376,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
*/
final Object mGlobalLockWithoutBoost = mGlobalLock;
ActivityStackSupervisor mStackSupervisor;
- RootActivityContainer mRootActivityContainer;
+ RootWindowContainer mRootWindowContainer;
WindowManagerService mWindowManager;
private UserManagerService mUserManager;
private AppOpsService mAppOpsService;
@@ -823,13 +825,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
mAppWarnings = createAppWarnings(mUiContext, mH, mUiHandler, systemDir);
mCompatModePackages = new CompatModePackages(this, systemDir, mH);
mPendingIntentController = intentController;
-
- mTempConfig.setToDefaults();
- mTempConfig.setLocales(LocaleList.getDefault());
- mConfigurationSeq = mTempConfig.seq = 1;
mStackSupervisor = createStackSupervisor();
- mRootActivityContainer = new RootActivityContainer(this);
- mRootActivityContainer.onConfigurationChanged(mTempConfig);
mTaskChangeNotificationController =
new TaskChangeNotificationController(mGlobalLock, mStackSupervisor, mH);
@@ -866,9 +862,14 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
public void setWindowManager(WindowManagerService wm) {
synchronized (mGlobalLock) {
mWindowManager = wm;
+ mRootWindowContainer = wm.mRoot;
+ mTempConfig.setToDefaults();
+ mTempConfig.setLocales(LocaleList.getDefault());
+ mConfigurationSeq = mTempConfig.seq = 1;
+ mRootWindowContainer.onConfigurationChanged(mTempConfig);
mLockTaskController.setWindowManager(wm);
mStackSupervisor.setWindowManager(wm);
- mRootActivityContainer.setWindowManager(wm);
+ mRootWindowContainer.setWindowManager(wm);
}
}
@@ -1339,7 +1340,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
sourceToken = resultTo;
}
- sourceRecord = mRootActivityContainer.isInAnyStack(sourceToken);
+ sourceRecord = mRootWindowContainer.isInAnyStack(sourceToken);
if (sourceRecord == null) {
throw new SecurityException("Called with bad activity token: " + sourceToken);
}
@@ -1728,9 +1729,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
final long origId = Binder.clearCallingIdentity();
synchronized (mGlobalLock) {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activityPaused");
- ActivityStack stack = ActivityRecord.getStackLocked(token);
- if (stack != null) {
- stack.activityPausedLocked(token, false);
+ final ActivityRecord r = ActivityRecord.forTokenLocked(token);
+ if (r != null) {
+ r.activityPaused(false);
}
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
@@ -1763,7 +1764,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
restartingName = r.app.mName;
restartingUid = r.app.mUid;
}
- r.activityStoppedLocked(icicle, persistentState, description);
+ r.activityStopped(icicle, persistentState, description);
}
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
@@ -2019,7 +2020,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
public void notifyActivityDrawn(IBinder token) {
if (DEBUG_VISIBILITY) Slog.d(TAG_VISIBILITY, "notifyActivityDrawn: token=" + token);
synchronized (mGlobalLock) {
- ActivityRecord r = mRootActivityContainer.isInAnyStack(token);
+ ActivityRecord r = mRootWindowContainer.isInAnyStack(token);
if (r != null) {
r.getActivityStack().notifyActivityDrawnLocked(r);
}
@@ -2056,7 +2057,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
synchronized (mGlobalLock) {
ActivityStack focusedStack = getTopDisplayFocusedStack();
if (focusedStack != null) {
- return mRootActivityContainer.getStackInfo(focusedStack.mStackId);
+ return mRootWindowContainer.getStackInfo(focusedStack.mStackId);
}
return null;
}
@@ -2072,14 +2073,14 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
final long callingId = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
- final ActivityStack stack = mRootActivityContainer.getStack(stackId);
+ final ActivityStack stack = mRootWindowContainer.getStack(stackId);
if (stack == null) {
Slog.w(TAG, "setFocusedStack: No stack with id=" + stackId);
return;
}
final ActivityRecord r = stack.topRunningActivity();
if (r != null && r.moveFocusableActivityToTop("setFocusedStack")) {
- mRootActivityContainer.resumeFocusedStacksTopActivities();
+ mRootWindowContainer.resumeFocusedStacksTopActivities();
}
}
} finally {
@@ -2094,14 +2095,14 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
final long callingId = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
- final Task task = mRootActivityContainer.anyTaskForId(taskId,
+ final Task task = mRootWindowContainer.anyTaskForId(taskId,
MATCH_TASK_IN_STACKS_ONLY);
if (task == null) {
return;
}
final ActivityRecord r = task.topRunningActivityLocked();
if (r != null && r.moveFocusableActivityToTop("setFocusedTask")) {
- mRootActivityContainer.resumeFocusedStacksTopActivities();
+ mRootWindowContainer.resumeFocusedStacksTopActivities();
}
}
} finally {
@@ -2204,7 +2205,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
final long origId = Binder.clearCallingIdentity();
try {
int taskId = ActivityRecord.getTaskForActivityLocked(token, !nonRoot);
- final Task task = mRootActivityContainer.anyTaskForId(taskId);
+ final Task task = mRootWindowContainer.anyTaskForId(taskId);
if (task != null) {
return ActivityRecord.getStackLocked(token).moveTaskToBack(task);
}
@@ -2222,7 +2223,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
Rect rect = new Rect();
try {
synchronized (mGlobalLock) {
- final Task task = mRootActivityContainer.anyTaskForId(taskId,
+ final Task task = mRootWindowContainer.anyTaskForId(taskId,
MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
if (task == null) {
Slog.w(TAG, "getTaskBounds: taskId=" + taskId + " not found");
@@ -2245,7 +2246,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
synchronized (mGlobalLock) {
enforceCallerIsRecentsOrHasPermission(
MANAGE_ACTIVITY_STACKS, "getTaskDescription()");
- final Task tr = mRootActivityContainer.anyTaskForId(id,
+ final Task tr = mRootWindowContainer.anyTaskForId(id,
MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
if (tr != null) {
return tr.getTaskDescription();
@@ -2265,7 +2266,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
synchronized (mGlobalLock) {
final long ident = Binder.clearCallingIdentity();
try {
- final Task task = mRootActivityContainer.anyTaskForId(taskId,
+ final Task task = mRootWindowContainer.anyTaskForId(taskId,
MATCH_TASK_IN_STACKS_ONLY);
if (task == null) {
Slog.w(TAG, "setTaskWindowingMode: No task for id=" + taskId);
@@ -2401,7 +2402,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
}
try {
- final Task task = mRootActivityContainer.anyTaskForId(taskId);
+ final Task task = mRootWindowContainer.anyTaskForId(taskId);
if (task == null) {
Slog.d(TAG, "Could not find task for id: "+ taskId);
SafeActivityOptions.abort(options);
@@ -2545,7 +2546,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
if (DEBUG_ALL) Slog.v(TAG, "getTasks: max=" + maxNum);
final boolean allowed = isGetTasksAllowed("getTasks", callingPid, callingUid);
- mRootActivityContainer.getRunningTasks(maxNum, list, ignoreActivityType,
+ mRootWindowContainer.getRunningTasks(maxNum, list, ignoreActivityType,
ignoreWindowingMode, callingUid, allowed, crossUser, callingProfileIds);
}
@@ -2592,7 +2593,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
synchronized (mGlobalLock) {
final long ident = Binder.clearCallingIdentity();
try {
- final Task task = mRootActivityContainer.anyTaskForId(taskId);
+ final Task task = mRootWindowContainer.anyTaskForId(taskId);
if (task == null) {
Slog.w(TAG, "moveTaskToStack: No task for id=" + taskId);
return;
@@ -2601,7 +2602,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
if (DEBUG_STACK) Slog.d(TAG_STACK, "moveTaskToStack: moving task=" + taskId
+ " to stackId=" + stackId + " toTop=" + toTop);
- final ActivityStack stack = mRootActivityContainer.getStack(stackId);
+ final ActivityStack stack = mRootWindowContainer.getStack(stackId);
if (stack == null) {
throw new IllegalStateException(
"moveTaskToStack: No stack for stackId=" + stackId);
@@ -2629,7 +2630,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
- final ActivityStack stack = mRootActivityContainer.getStack(stackId);
+ final ActivityStack stack = mRootWindowContainer.getStack(stackId);
if (stack == null) {
Slog.w(TAG, "resizeStack: stackId " + stackId + " not found.");
return;
@@ -2657,7 +2658,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
if (xOffset == 0 && yOffset == 0) {
return;
}
- final ActivityStack stack = mRootActivityContainer.getStack(stackId);
+ final ActivityStack stack = mRootWindowContainer.getStack(stackId);
if (stack == null) {
Slog.w(TAG, "offsetPinnedStackBounds: stackId " + stackId + " not found.");
return;
@@ -2704,7 +2705,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
synchronized (mGlobalLock) {
final long ident = Binder.clearCallingIdentity();
try {
- final Task task = mRootActivityContainer.anyTaskForId(taskId,
+ final Task task = mRootWindowContainer.anyTaskForId(taskId,
MATCH_TASK_IN_STACKS_ONLY);
if (task == null) {
Slog.w(TAG, "setTaskWindowingModeSplitScreenPrimary: No task for id=" + taskId);
@@ -2746,7 +2747,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
synchronized (mGlobalLock) {
final long ident = Binder.clearCallingIdentity();
try {
- mRootActivityContainer.removeStacksInWindowingModes(windowingModes);
+ mRootWindowContainer.removeStacksInWindowingModes(windowingModes);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -2761,7 +2762,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
synchronized (mGlobalLock) {
final long ident = Binder.clearCallingIdentity();
try {
- mRootActivityContainer.removeStacksWithActivityTypes(activityTypes);
+ mRootWindowContainer.removeStacksWithActivityTypes(activityTypes);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -2792,7 +2793,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
long ident = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
- return mRootActivityContainer.getAllStackInfos(INVALID_DISPLAY);
+ return mRootWindowContainer.getAllStackInfos(INVALID_DISPLAY);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -2805,7 +2806,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
long ident = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
- return mRootActivityContainer.getStackInfo(windowingMode, activityType);
+ return mRootWindowContainer.getStackInfo(windowingMode, activityType);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -2818,7 +2819,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
long ident = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
- return mRootActivityContainer.getAllStackInfos(displayId);
+ return mRootWindowContainer.getAllStackInfos(displayId);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -2832,7 +2833,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
long ident = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
- return mRootActivityContainer.getStackInfo(windowingMode, activityType, displayId);
+ return mRootWindowContainer.getStackInfo(windowingMode, activityType, displayId);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -2874,7 +2875,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
long ident = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
- final Task task = mRootActivityContainer.anyTaskForId(taskId,
+ final Task task = mRootWindowContainer.anyTaskForId(taskId,
MATCH_TASK_IN_STACKS_ONLY);
if (task == null) {
return;
@@ -2916,7 +2917,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
return;
}
- final ActivityStack stack = mRootActivityContainer.getTopDisplayFocusedStack();
+ final ActivityStack stack = mRootWindowContainer.getTopDisplayFocusedStack();
if (stack == null || task != stack.getTopMostTask()) {
throw new IllegalArgumentException("Invalid task, not in foreground");
}
@@ -2931,7 +2932,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
long ident = Binder.clearCallingIdentity();
try {
// When a task is locked, dismiss the pinned stack if it exists
- mRootActivityContainer.removeStacksInWindowingModes(WINDOWING_MODE_PINNED);
+ mRootWindowContainer.removeStacksInWindowingModes(WINDOWING_MODE_PINNED);
getLockTaskController().startLockTaskMode(task, isSystemCaller, callingUid);
} finally {
@@ -3033,7 +3034,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
try {
// TODO: VI Consider treating local voice interactions and voice tasks
// differently here
- mRootActivityContainer.finishVoiceTask(session);
+ mRootWindowContainer.finishVoiceTask(session);
} finally {
Binder.restoreCallingIdentity(origId);
}
@@ -3228,7 +3229,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
@Override
public void setTaskResizeable(int taskId, int resizeableMode) {
synchronized (mGlobalLock) {
- final Task task = mRootActivityContainer.anyTaskForId(
+ final Task task = mRootWindowContainer.anyTaskForId(
taskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
if (task == null) {
Slog.w(TAG, "setTaskResizeable: taskId=" + taskId + " not found");
@@ -3244,7 +3245,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
long ident = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
- final Task task = mRootActivityContainer.anyTaskForId(taskId,
+ final Task task = mRootWindowContainer.anyTaskForId(taskId,
MATCH_TASK_IN_STACKS_ONLY);
if (task == null) {
Slog.w(TAG, "resizeTask: taskId=" + taskId + " not found");
@@ -3302,6 +3303,23 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
Configuration c = new Configuration(container.getRequestedOverrideConfiguration());
c.setTo(change.getConfiguration(), configMask, windowMask);
container.onRequestedOverrideConfigurationChanged(c);
+ // TODO(b/145675353): remove the following once we could apply new bounds to the
+ // pinned stack together with its children.
+ resizePinnedStackIfNeeded(container, configMask, windowMask, c);
+ }
+
+ private void resizePinnedStackIfNeeded(ConfigurationContainer container, int configMask,
+ int windowMask, Configuration config) {
+ if ((container instanceof ActivityStack)
+ && ((configMask & ActivityInfo.CONFIG_WINDOW_CONFIGURATION) != 0)
+ && ((windowMask & WindowConfiguration.WINDOW_CONFIG_BOUNDS) != 0)) {
+ final ActivityStack stack = (ActivityStack) container;
+ if (stack.inPinnedWindowingMode()) {
+ stack.resize(config.windowConfiguration.getBounds(),
+ null /* tempTaskBounds */, null /* tempTaskInsetBounds */,
+ PRESERVE_WINDOWS, true /* deferResume */);
+ }
+ }
}
@Override
@@ -3419,7 +3437,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
synchronized (mGlobalLock) {
final long ident = Binder.clearCallingIdentity();
try {
- final ActivityStack stack = mRootActivityContainer.getStack(stackId);
+ final ActivityStack stack = mRootWindowContainer.getStack(stackId);
if (stack == null) {
Slog.w(TAG, "removeStack: No stack with id=" + stackId);
return;
@@ -3444,7 +3462,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
try {
if (DEBUG_STACK) Slog.d(TAG_STACK, "moveStackToDisplay: moving stackId=" + stackId
+ " to displayId=" + displayId);
- mRootActivityContainer.moveStackToDisplay(stackId, displayId, ON_TOP);
+ mRootWindowContainer.moveStackToDisplay(stackId, displayId, ON_TOP);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -3930,13 +3948,13 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
try {
if (DEBUG_STACK) Slog.d(TAG_STACK, "positionTaskInStack: positioning task="
+ taskId + " in stackId=" + stackId + " at position=" + position);
- final Task task = mRootActivityContainer.anyTaskForId(taskId);
+ final Task task = mRootWindowContainer.anyTaskForId(taskId);
if (task == null) {
throw new IllegalArgumentException("positionTaskInStack: no task for id="
+ taskId);
}
- final ActivityStack stack = mRootActivityContainer.getStack(stackId);
+ final ActivityStack stack = mRootWindowContainer.getStack(stackId);
if (stack == null) {
throw new IllegalArgumentException("positionTaskInStack: no stack for id="
@@ -3992,7 +4010,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
try {
synchronized (mGlobalLock) {
final ActivityStack stack =
- mRootActivityContainer.getDefaultDisplay().getSplitScreenPrimaryStack();
+ mRootWindowContainer.getDefaultDisplay().getSplitScreenPrimaryStack();
if (stack == null) {
Slog.w(TAG, "dismissSplitScreenMode: primary split-screen stack not found.");
return;
@@ -4033,7 +4051,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
try {
synchronized (mGlobalLock) {
final ActivityStack stack =
- mRootActivityContainer.getDefaultDisplay().getPinnedStack();
+ mRootWindowContainer.getDefaultDisplay().getPinnedStack();
if (stack == null) {
Slog.w(TAG, "dismissPip: pinned stack not found.");
return;
@@ -4071,7 +4089,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
synchronized (mGlobalLock) {
final long origId = Binder.clearCallingIdentity();
try {
- final ActivityStack stack = mRootActivityContainer.getStack(fromStackId);
+ final ActivityStack stack = mRootWindowContainer.getStack(fromStackId);
if (stack != null){
if (!stack.isActivityTypeStandardOrUndefined()) {
throw new IllegalArgumentException(
@@ -4106,7 +4124,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
long ident = Binder.clearCallingIdentity();
try {
- return mRootActivityContainer.moveTopStackActivityToPinnedStack(stackId);
+ return mRootWindowContainer.moveTopStackActivityToPinnedStack(stackId);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -4176,6 +4194,10 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
final Runnable enterPipRunnable = () -> {
synchronized (mGlobalLock) {
+ if (r.getParent() == null) {
+ Slog.e(TAG, "Skip enterPictureInPictureMode, destroyed " + r);
+ return;
+ }
// Only update the saved args from the args that are set
r.pictureInPictureArgs.copyOnlySet(params);
final float aspectRatio = r.pictureInPictureArgs.getAspectRatio();
@@ -4183,7 +4205,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
// Adjust the source bounds by the insets for the transition down
final Rect sourceBounds = new Rect(
r.pictureInPictureArgs.getSourceRectHint());
- mRootActivityContainer.moveActivityToPinnedStack(
+ mRootWindowContainer.moveActivityToPinnedStack(
r, sourceBounds, aspectRatio, "enterPictureInPictureMode");
final ActivityStack stack = r.getActivityStack();
stack.setPictureInPictureAspectRatio(aspectRatio);
@@ -4515,7 +4537,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
- final Task task = mRootActivityContainer.anyTaskForId(taskId,
+ final Task task = mRootWindowContainer.anyTaskForId(taskId,
MATCH_TASK_IN_STACKS_ONLY);
if (task == null) {
Slog.w(TAG, "cancelTaskWindowTransition: taskId=" + taskId + " not found");
@@ -4543,7 +4565,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
boolean restoreFromDisk) {
final Task task;
synchronized (mGlobalLock) {
- task = mRootActivityContainer.anyTaskForId(taskId,
+ task = mRootWindowContainer.anyTaskForId(taskId,
MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
if (task == null) {
Slog.w(TAG, "getTaskSnapshot: taskId=" + taskId + " not found");
@@ -4679,6 +4701,24 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
@Override
+ public void unregisterRemoteAnimations(IBinder token) {
+ mAmInternal.enforceCallingPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS,
+ "unregisterRemoteAnimations");
+ synchronized (mGlobalLock) {
+ final ActivityRecord r = ActivityRecord.isInStackLocked(token);
+ if (r == null) {
+ return;
+ }
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ r.unregisterRemoteAnimations();
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+ }
+
+ @Override
public void registerRemoteAnimationForNextActivityStart(String packageName,
RemoteAnimationAdapter adapter) {
mAmInternal.enforceCallingPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS,
@@ -4702,7 +4742,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
"registerRemoteAnimations");
definition.setCallingPidUid(Binder.getCallingPid(), Binder.getCallingUid());
synchronized (mGlobalLock) {
- final DisplayContent display = mRootActivityContainer.getDisplayContent(displayId);
+ final DisplayContent display = mRootWindowContainer.getDisplayContent(displayId);
if (display == null) {
Slog.e(TAG, "Couldn't find display with id: " + displayId);
return;
@@ -4808,7 +4848,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
if (r.requestedVrComponent != null && r.getDisplayId() != DEFAULT_DISPLAY) {
Slog.i(TAG, "Moving " + r.shortComponentName + " from display " + r.getDisplayId()
+ " to main display for VR");
- mRootActivityContainer.moveStackToDisplay(
+ mRootWindowContainer.moveStackToDisplay(
r.getStackId(), DEFAULT_DISPLAY, true /* toTop */);
}
mH.post(() -> {
@@ -4821,7 +4861,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
if (disableNonVrUi) {
// If we are in a VR mode where Picture-in-Picture mode is unsupported,
// then remove the pinned stack.
- mRootActivityContainer.removeStacksInWindowingModes(WINDOWING_MODE_PINNED);
+ mRootWindowContainer.removeStacksInWindowingModes(WINDOWING_MODE_PINNED);
}
}
});
@@ -4873,7 +4913,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
ActivityStack getTopDisplayFocusedStack() {
- return mRootActivityContainer.getTopDisplayFocusedStack();
+ return mRootWindowContainer.getTopDisplayFocusedStack();
}
/** Pokes the task persister. */
@@ -4911,7 +4951,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
final long origId = Binder.clearCallingIdentity();
try {
final DisplayContent display =
- mRootActivityContainer.getDisplayContentOrCreate(displayId);
+ mRootWindowContainer.getDisplayContentOrCreate(displayId);
if (display != null) {
display.setDisplayToSingleTaskInstance();
}
@@ -4920,6 +4960,44 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
}
+ /**
+ * Requests that an activity should enter picture-in-picture mode if possible.
+ */
+ @Override
+ public void requestPictureInPictureMode(IBinder token) throws RemoteException {
+ mAmInternal.enforceCallingPermission(Manifest.permission.MANAGE_ACTIVITY_STACKS,
+ "requestPictureInPictureMode");
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ synchronized (mGlobalLock) {
+ final ActivityRecord activity = ActivityRecord.forTokenLocked(token);
+ if (activity == null) {
+ return;
+ }
+
+ final boolean canEnterPictureInPicture = activity.checkEnterPictureInPictureState(
+ "requestPictureInPictureMode", /* beforeStopping */ false);
+ if (!canEnterPictureInPicture) {
+ throw new IllegalStateException(
+ "Requested PIP on an activity that doesn't support it");
+ }
+
+ try {
+ final ClientTransaction transaction = ClientTransaction.obtain(
+ activity.app.getThread(),
+ activity.token);
+ transaction.addCallback(EnterPipRequestedItem.obtain());
+ getLifecycleManager().scheduleTransaction(transaction);
+ } catch (Exception e) {
+ Slog.w(TAG, "Failed to send enter pip requested item: "
+ + activity.intent.getComponent(), e);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+
void dumpLastANRLocked(PrintWriter pw) {
pw.println("ACTIVITY MANAGER LAST ANR (dumpsys activity lastanr)");
if (mLastANRState == null) {
@@ -4969,12 +5047,12 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
int opti, boolean dumpAll, boolean dumpClient, String dumpPackage, String header) {
pw.println(header);
- boolean printedAnything = mRootActivityContainer.dumpActivities(fd, pw, dumpAll, dumpClient,
+ boolean printedAnything = mRootWindowContainer.dumpActivities(fd, pw, dumpAll, dumpClient,
dumpPackage);
boolean needSep = printedAnything;
boolean printed = ActivityStackSupervisor.printThisActivity(pw,
- mRootActivityContainer.getTopResumedActivity(), dumpPackage, needSep,
+ mRootWindowContainer.getTopResumedActivity(), dumpPackage, needSep,
" ResumedActivity: ");
if (printed) {
printedAnything = true;
@@ -4996,7 +5074,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
void dumpActivityContainersLocked(PrintWriter pw) {
pw.println("ACTIVITY MANAGER CONTAINERS (dumpsys activity containers)");
- mRootActivityContainer.dumpChildrenNames(pw, " ");
+ mRootWindowContainer.dumpChildrenNames(pw, " ");
pw.println(" ");
}
@@ -5023,7 +5101,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
ArrayList<ActivityRecord> activities;
synchronized (mGlobalLock) {
- activities = mRootActivityContainer.getDumpActivities(name, dumpVisibleStacksOnly,
+ activities = mRootWindowContainer.getDumpActivities(name, dumpVisibleStacksOnly,
dumpFocusedStackOnly);
}
@@ -5101,7 +5179,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
final long sleepToken = proto.start(ActivityManagerServiceDumpProcessesProto.SLEEP_STATUS);
proto.write(ActivityManagerServiceDumpProcessesProto.SleepStatus.WAKEFULNESS,
PowerManagerInternal.wakefulnessToProtoEnum(wakeFullness));
- for (ActivityTaskManagerInternal.SleepToken st : mRootActivityContainer.mSleepTokens) {
+ for (ActivityTaskManagerInternal.SleepToken st : mRootWindowContainer.mSleepTokens) {
proto.write(ActivityManagerServiceDumpProcessesProto.SleepStatus.SLEEP_TOKENS,
st.toString());
}
@@ -5137,7 +5215,11 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
* also corresponds to the merged configuration of the default display.
*/
Configuration getGlobalConfiguration() {
- return mRootActivityContainer.getConfiguration();
+ // Return default configuration before mRootWindowContainer initialized, which happens
+ // while initializing process record for system, see {@link
+ // ActivityManagerService#setSystemProcess}.
+ return mRootWindowContainer != null ? mRootWindowContainer.getConfiguration()
+ : new Configuration();
}
boolean updateConfigurationLocked(Configuration values, ActivityRecord starting,
@@ -5210,7 +5292,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
boolean persistent, int userId, boolean deferResume) {
final DisplayContent defaultDisplay =
- mRootActivityContainer.getDisplayContent(DEFAULT_DISPLAY);
+ mRootWindowContainer.getDisplayContent(DEFAULT_DISPLAY);
mTempConfig.setTo(getGlobalConfiguration());
final int changes = mTempConfig.updateFrom(values);
@@ -5268,7 +5350,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
mTempConfig.seq = increaseConfigurationSeqLocked();
// Update stored global config and notify everyone about the change.
- mRootActivityContainer.onConfigurationChanged(mTempConfig);
+ mRootWindowContainer.onConfigurationChanged(mTempConfig);
Slog.i(TAG, "Config changes=" + Integer.toHexString(changes) + " " + mTempConfig);
// TODO(multi-display): Update UsageEvents#Event to include displayId.
@@ -5316,7 +5398,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
// Override configuration of the default display duplicates global config, so we need to
// update it also. This will also notify WindowManager about changes.
- defaultDisplay.performDisplayOverrideConfigUpdate(mRootActivityContainer.getConfiguration(),
+ defaultDisplay.performDisplayOverrideConfigUpdate(mRootWindowContainer.getConfiguration(),
deferResume);
return changes;
@@ -5466,7 +5548,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
mCurAppTimeTracker.stop();
mH.obtainMessage(
REPORT_TIME_TRACKER_MSG, mCurAppTimeTracker).sendToTarget();
- mRootActivityContainer.clearOtherAppTimeTrackers(r.appTimeTracker);
+ mRootWindowContainer.clearOtherAppTimeTrackers(r.appTimeTracker);
mCurAppTimeTracker = null;
}
if (r.appTimeTracker != null) {
@@ -5528,14 +5610,14 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
ActivityTaskManagerInternal.SleepToken acquireSleepToken(String tag, int displayId) {
synchronized (mGlobalLock) {
final ActivityTaskManagerInternal.SleepToken token =
- mRootActivityContainer.createSleepToken(tag, displayId);
+ mRootWindowContainer.createSleepToken(tag, displayId);
updateSleepIfNeededLocked();
return token;
}
}
void updateSleepIfNeededLocked() {
- final boolean shouldSleep = !mRootActivityContainer.hasAwakeDisplay();
+ final boolean shouldSleep = !mRootWindowContainer.hasAwakeDisplay();
final boolean wasSleeping = mSleeping;
boolean updateOomAdj = false;
@@ -5552,7 +5634,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
Slog.d(TAG, "Top Process State changed to PROCESS_STATE_TOP");
mStackSupervisor.comeOutOfSleepIfNeededLocked();
}
- mRootActivityContainer.applySleepTokens(true /* applyToStacks */);
+ mRootWindowContainer.applySleepTokens(true /* applyToStacks */);
if (wasSleeping) {
updateOomAdj = true;
}
@@ -5765,7 +5847,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
// TODO(b/111541062): Update app time tracking to make it aware of multiple resumed activities
private void startTimeTrackingFocusedActivityLocked() {
- final ActivityRecord resumedActivity = mRootActivityContainer.getTopResumedActivity();
+ final ActivityRecord resumedActivity = mRootWindowContainer.getTopResumedActivity();
if (!mSleeping && mCurAppTimeTracker != null && resumedActivity != null) {
mCurAppTimeTracker.start(resumedActivity.packageName);
}
@@ -5790,7 +5872,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
/** Applies latest configuration and/or visibility updates if needed. */
boolean ensureConfigAndVisibilityAfterUpdate(ActivityRecord starting, int changes) {
boolean kept = true;
- final ActivityStack mainStack = mRootActivityContainer.getTopDisplayFocusedStack();
+ final ActivityStack mainStack = mRootWindowContainer.getTopDisplayFocusedStack();
// mainStack is null during startup.
if (mainStack != null) {
if (changes != 0 && starting == null) {
@@ -5805,7 +5887,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
false /* preserveWindow */);
// And we need to make sure at this point that all other activities
// are made visible with the correct configuration.
- mRootActivityContainer.ensureActivitiesVisible(starting, changes,
+ mRootWindowContainer.ensureActivitiesVisible(starting, changes,
!PRESERVE_WINDOWS);
}
}
@@ -6090,7 +6172,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
public ComponentName getHomeActivityForUser(int userId) {
synchronized (mGlobalLock) {
final ActivityRecord homeActivity =
- mRootActivityContainer.getDefaultDisplayHomeActivityForUser(userId);
+ mRootWindowContainer.getDefaultDisplayHomeActivityForUser(userId);
return homeActivity == null ? null : homeActivity.mActivityComponent;
}
}
@@ -6125,14 +6207,14 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
@Override
public List<IBinder> getTopVisibleActivities() {
synchronized (mGlobalLock) {
- return mRootActivityContainer.getTopVisibleActivities();
+ return mRootWindowContainer.getTopVisibleActivities();
}
}
@Override
public void notifyDockedStackMinimizedChanged(boolean minimized) {
synchronized (mGlobalLock) {
- mRootActivityContainer.setDockedStackMinimized(minimized);
+ mRootWindowContainer.setDockedStackMinimized(minimized);
}
}
@@ -6217,7 +6299,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
// We might change the visibilities here, so prepare an empty app transition which
// might be overridden later if we actually change visibilities.
final DisplayContent displayContent =
- mRootActivityContainer.getDisplayContent(displayId);
+ mRootWindowContainer.getDisplayContent(displayId);
if (displayContent == null) {
return;
}
@@ -6227,7 +6309,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
if (!wasTransitionSet) {
dc.prepareAppTransition(TRANSIT_NONE, false /* alwaysKeepCurrent */);
}
- mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
+ mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
// If there was a transition set already we don't want to interfere with it as we
// might be starting it too early.
@@ -6244,7 +6326,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
public void notifyKeyguardTrustedChanged() {
synchronized (mGlobalLock) {
if (mKeyguardController.isKeyguardShowing(DEFAULT_DISPLAY)) {
- mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
+ mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
}
}
}
@@ -6271,7 +6353,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
"setFocusedActivity: No activity record matching token=" + token);
}
if (r.moveFocusableActivityToTop("setFocusedActivity")) {
- mRootActivityContainer.resumeFocusedStacksTopActivities();
+ mRootWindowContainer.resumeFocusedStacksTopActivities();
}
}
}
@@ -6429,7 +6511,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
public boolean shuttingDown(boolean booted, int timeout) {
synchronized (mGlobalLock) {
mShuttingDown = true;
- mRootActivityContainer.prepareForShutdown();
+ mRootWindowContainer.prepareForShutdown();
updateEventDispatchingLocked(booted);
notifyTaskPersisterLocked(null, true);
return mStackSupervisor.shutdownLocked(timeout);
@@ -6535,7 +6617,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
@Override
public void onPackageReplaced(ApplicationInfo aInfo) {
synchronized (mGlobalLock) {
- mRootActivityContainer.updateActivityApplicationInfo(aInfo);
+ mRootWindowContainer.updateActivityApplicationInfo(aInfo);
}
}
@@ -6569,7 +6651,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
synchronized (mGlobalLock) {
final DisplayContent displayContent =
- mRootActivityContainer.getDisplayContent(displayId);
+ mRootWindowContainer.getDisplayContent(displayId);
if (displayContent == null) {
// Call might come when display is not yet added or has been removed.
if (DEBUG_CONFIGURATION) {
@@ -6616,7 +6698,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
@Override
public ActivityTokens getTopActivityForTask(int taskId) {
synchronized (mGlobalLock) {
- final Task task = mRootActivityContainer.anyTaskForId(taskId);
+ final Task task = mRootWindowContainer.anyTaskForId(taskId);
if (task == null) {
Slog.w(TAG, "getApplicationThreadForTopActivity failed:"
+ " Requested task not found");
@@ -6675,7 +6757,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
@Override
public boolean startHomeActivity(int userId, String reason) {
synchronized (mGlobalLock) {
- return mRootActivityContainer.startHomeOnDisplay(userId, reason, DEFAULT_DISPLAY);
+ return mRootWindowContainer.startHomeOnDisplay(userId, reason, DEFAULT_DISPLAY);
}
}
@@ -6683,7 +6765,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
public boolean startHomeOnDisplay(int userId, String reason, int displayId,
boolean allowInstrumenting, boolean fromHomeKey) {
synchronized (mGlobalLock) {
- return mRootActivityContainer.startHomeOnDisplay(userId, reason, displayId,
+ return mRootWindowContainer.startHomeOnDisplay(userId, reason, displayId,
allowInstrumenting, fromHomeKey);
}
}
@@ -6691,7 +6773,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
@Override
public boolean startHomeOnAllDisplays(int userId, String reason) {
synchronized (mGlobalLock) {
- return mRootActivityContainer.startHomeOnAllDisplays(userId, reason);
+ return mRootWindowContainer.startHomeOnAllDisplays(userId, reason);
}
}
@@ -6757,7 +6839,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
Runnable finishInstrumentationCallback) {
synchronized (mGlobalLockWithoutBoost) {
// Remove this application's activities from active lists.
- boolean hasVisibleActivities = mRootActivityContainer.handleAppDied(wpc);
+ boolean hasVisibleActivities = mRootWindowContainer.handleAppDied(wpc);
wpc.clearRecentTasks();
wpc.clearActivities();
@@ -6769,12 +6851,12 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
if (!restarting && hasVisibleActivities) {
deferWindowLayout();
try {
- if (!mRootActivityContainer.resumeFocusedStacksTopActivities()) {
+ if (!mRootWindowContainer.resumeFocusedStacksTopActivities()) {
// If there was nothing to resume, and we are not already restarting
// this process, but there is a visible activity that is hosted by the
// process...then make sure all visible activities are running, taking
// care of restarting this process.
- mRootActivityContainer.ensureActivitiesVisible(null, 0,
+ mRootWindowContainer.ensureActivitiesVisible(null, 0,
!PRESERVE_WINDOWS);
}
} finally {
@@ -6805,7 +6887,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
mWindowManager.closeSystemDialogs(reason);
- mRootActivityContainer.closeSystemDialogs();
+ mRootWindowContainer.closeSystemDialogs();
}
// Call into AM outside the synchronized block.
mAmInternal.broadcastCloseSystemDialogs(reason);
@@ -6819,9 +6901,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
String packageName, Set<String> disabledClasses, int userId, boolean booted) {
synchronized (mGlobalLock) {
// Clean-up disabled activities.
- if (mRootActivityContainer.finishDisabledPackageActivities(
+ if (mRootWindowContainer.finishDisabledPackageActivities(
packageName, disabledClasses, true, false, userId) && booted) {
- mRootActivityContainer.resumeFocusedStacksTopActivities();
+ mRootWindowContainer.resumeFocusedStacksTopActivities();
mStackSupervisor.scheduleIdleLocked();
}
@@ -6838,7 +6920,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
boolean didSomething =
getActivityStartController().clearPendingActivityLaunches(packageName);
- didSomething |= mRootActivityContainer.finishDisabledPackageActivities(packageName,
+ didSomething |= mRootWindowContainer.finishDisabledPackageActivities(packageName,
null, doit, evenPersistent, userId);
return didSomething;
}
@@ -6847,7 +6929,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
@Override
public void resumeTopActivities(boolean scheduleIdle) {
synchronized (mGlobalLock) {
- mRootActivityContainer.resumeFocusedStacksTopActivities();
+ mRootWindowContainer.resumeFocusedStacksTopActivities();
if (scheduleIdle) {
mStackSupervisor.scheduleIdleLocked();
}
@@ -6870,7 +6952,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "attachApplication:" + wpc.mName);
}
try {
- return mRootActivityContainer.attachApplication(wpc);
+ return mRootWindowContainer.attachApplication(wpc);
} finally {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
@@ -6895,7 +6977,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
// Showing launcher to avoid user entering credential twice.
startHomeActivity(currentUserId, "notifyLockedProfile");
}
- mRootActivityContainer.lockAllProfileTasks(userId);
+ mRootWindowContainer.lockAllProfileTasks(userId);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -6927,7 +7009,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
synchronized (mGlobalLock) {
// The output proto of "activity --proto activities"
// is ActivityManagerServiceDumpActivitiesProto
- mRootActivityContainer.dumpDebug(proto,
+ mRootWindowContainer.dumpDebug(proto,
ActivityManagerServiceDumpActivitiesProto.ACTIVITY_STACK_SUPERVISOR,
WindowTraceLogLevel.ALL);
}
@@ -7023,7 +7105,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
if (dumpPackage == null) {
pw.println(" mGlobalConfiguration: " + getGlobalConfiguration());
- mRootActivityContainer.dumpDisplayConfigs(pw, " ");
+ mRootWindowContainer.dumpDisplayConfigs(pw, " ");
}
if (dumpAll) {
if (dumpPackage == null) {
@@ -7051,7 +7133,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
if (dumpPackage == null) {
pw.println(" mWakefulness="
+ PowerManagerInternal.wakefulnessToString(wakefulness));
- pw.println(" mSleepTokens=" + mRootActivityContainer.mSleepTokens);
+ pw.println(" mSleepTokens=" + mRootWindowContainer.mSleepTokens);
if (mRunningVoice != null) {
pw.println(" mRunningVoice=" + mRunningVoice);
pw.println(" mVoiceWakeLock" + mVoiceWakeLock);
@@ -7190,7 +7272,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
@Override
public boolean canGcNow() {
synchronized (mGlobalLock) {
- return isSleeping() || mRootActivityContainer.allResumedActivitiesIdle();
+ return isSleeping() || mRootWindowContainer.allResumedActivitiesIdle();
}
}
@@ -7198,7 +7280,12 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
@Override
public WindowProcessController getTopApp() {
synchronized (mGlobalLockWithoutBoost) {
- final ActivityRecord top = mRootActivityContainer.getTopResumedActivity();
+ if (mRootWindowContainer == null) {
+ // Return null if mRootWindowContainer not yet initialize, while update
+ // oomadj after AMS created.
+ return null;
+ }
+ final ActivityRecord top = mRootWindowContainer.getTopResumedActivity();
return top != null ? top.app : null;
}
}
@@ -7207,8 +7294,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
@Override
public void rankTaskLayersIfNeeded() {
synchronized (mGlobalLockWithoutBoost) {
- if (mRootActivityContainer != null) {
- mRootActivityContainer.rankTaskLayersIfNeeded();
+ if (mRootWindowContainer != null) {
+ mRootWindowContainer.rankTaskLayersIfNeeded();
}
}
}
@@ -7216,35 +7303,35 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
@Override
public void scheduleDestroyAllActivities(String reason) {
synchronized (mGlobalLock) {
- mRootActivityContainer.scheduleDestroyAllActivities(null, reason);
+ mRootWindowContainer.scheduleDestroyAllActivities(reason);
}
}
@Override
public void removeUser(int userId) {
synchronized (mGlobalLock) {
- mRootActivityContainer.removeUser(userId);
+ mRootWindowContainer.removeUser(userId);
}
}
@Override
public boolean switchUser(int userId, UserState userState) {
synchronized (mGlobalLock) {
- return mRootActivityContainer.switchUser(userId, userState);
+ return mRootWindowContainer.switchUser(userId, userState);
}
}
@Override
public void onHandleAppCrash(WindowProcessController wpc) {
synchronized (mGlobalLock) {
- mRootActivityContainer.handleAppCrash(wpc);
+ mRootWindowContainer.handleAppCrash(wpc);
}
}
@Override
public int finishTopCrashedActivities(WindowProcessController crashedApp, String reason) {
synchronized (mGlobalLock) {
- return mRootActivityContainer.finishTopCrashedActivities(crashedApp, reason);
+ return mRootWindowContainer.finishTopCrashedActivities(crashedApp, reason);
}
}
diff --git a/services/core/java/com/android/server/wm/AppTaskImpl.java b/services/core/java/com/android/server/wm/AppTaskImpl.java
index 6d9584c50b9c..357f9e5bec6c 100644
--- a/services/core/java/com/android/server/wm/AppTaskImpl.java
+++ b/services/core/java/com/android/server/wm/AppTaskImpl.java
@@ -17,7 +17,7 @@
package com.android.server.wm;
import static com.android.server.wm.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
-import static com.android.server.wm.RootActivityContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS;
+import static com.android.server.wm.RootWindowContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS;
import android.app.ActivityManager;
import android.app.IAppTask;
@@ -79,7 +79,7 @@ class AppTaskImpl extends IAppTask.Stub {
synchronized (mService.mGlobalLock) {
long origId = Binder.clearCallingIdentity();
try {
- Task task = mService.mRootActivityContainer.anyTaskForId(mTaskId,
+ Task task = mService.mRootWindowContainer.anyTaskForId(mTaskId,
MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
if (task == null) {
throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
@@ -139,7 +139,7 @@ class AppTaskImpl extends IAppTask.Stub {
Task task;
IApplicationThread appThread;
synchronized (mService.mGlobalLock) {
- task = mService.mRootActivityContainer.anyTaskForId(mTaskId,
+ task = mService.mRootWindowContainer.anyTaskForId(mTaskId,
MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
if (task == null) {
throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
@@ -167,7 +167,7 @@ class AppTaskImpl extends IAppTask.Stub {
synchronized (mService.mGlobalLock) {
long origId = Binder.clearCallingIdentity();
try {
- Task task = mService.mRootActivityContainer.anyTaskForId(mTaskId,
+ Task task = mService.mRootWindowContainer.anyTaskForId(mTaskId,
MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
if (task == null) {
throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java
index 6ea0650df37a..369dde665068 100644
--- a/services/core/java/com/android/server/wm/AppTransitionController.java
+++ b/services/core/java/com/android/server/wm/AppTransitionController.java
@@ -48,6 +48,7 @@ import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_S
import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_WINDOWS_DRAWN;
import static com.android.server.wm.AppTransition.isKeyguardGoingAwayTransit;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
+import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM;
import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
@@ -69,6 +70,8 @@ import android.view.animation.Animation;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.protolog.common.ProtoLog;
+import java.util.ArrayList;
+import java.util.LinkedList;
import java.util.function.Predicate;
@@ -180,11 +183,7 @@ public class AppTransitionController {
final int layoutRedo;
mService.mSurfaceAnimationRunner.deferStartingAnimations();
try {
- // TODO: Apply an app transition animation on TaskStack instead of ActivityRecord when
- // appropriate.
- applyAnimations(mDisplayContent.mClosingApps, transit, false /* visible */,
- animLp, voiceInteraction);
- applyAnimations(mDisplayContent.mOpeningApps, transit, true /* visible */,
+ applyAnimations(mDisplayContent.mOpeningApps, mDisplayContent.mClosingApps, transit,
animLp, voiceInteraction);
handleClosingApps();
handleOpeningApps();
@@ -350,9 +349,9 @@ public class AppTransitionController {
}
/**
- * Apply an app transition animation on a set of {@link ActivityRecord}
+ * Apply animation to the set of window containers.
*
- * @param apps The list of apps to which an app transition animation applies.
+ * @param wcs The list of {@link WindowContainer}s to which an app transition animation applies.
* @param transit The current transition type.
* @param visible {@code true} if the apps becomes visible, {@code false} if the apps becomes
* invisible.
@@ -360,24 +359,150 @@ public class AppTransitionController {
* @param voiceInteraction {@code true} if one of the apps in this transition belongs to a voice
* interaction session driving task.
*/
- private void applyAnimations(ArraySet<ActivityRecord> apps, @TransitionType int transit,
+ private void applyAnimations(ArraySet<WindowContainer> wcs, @TransitionType int transit,
boolean visible, LayoutParams animLp, boolean voiceInteraction) {
- final int appsCount = apps.size();
+ final int appsCount = wcs.size();
for (int i = 0; i < appsCount; i++) {
+ final WindowContainer wc = wcs.valueAt(i);
+ wc.applyAnimation(animLp, transit, visible, voiceInteraction);
+ }
+ }
+
+ /**
+ * Find WindowContainers to be animated from a set of opening and closing apps. We will promote
+ * animation targets to higher level in the window hierarchy if possible.
+ *
+ * @param visible {@code true} to get animation targets for opening apps, {@code false} to get
+ * animation targets for closing apps.
+ * @return {@link WindowContainer}s to be animated.
+ */
+ @VisibleForTesting
+ static ArraySet<WindowContainer> getAnimationTargets(
+ ArraySet<ActivityRecord> openingApps, ArraySet<ActivityRecord> closingApps,
+ boolean visible) {
+
+ // The candidates of animation targets, which might be able to promote to higher level.
+ final LinkedList<WindowContainer> candidates = new LinkedList<>();
+ final ArraySet<ActivityRecord> apps = visible ? openingApps : closingApps;
+ for (int i = 0; i < apps.size(); ++i) {
final ActivityRecord app = apps.valueAt(i);
- if (transit != WindowManager.TRANSIT_UNSET && app.shouldApplyAnimation(visible)) {
- ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Changing app %s visible=%b performLayout=%b",
+ if (app.shouldApplyAnimation(visible)) {
+ candidates.add(app);
+ ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
+ "Changing app %s visible=%b performLayout=%b",
app, app.isVisible(), false);
- if (!app.mUseTransferredAnimation) {
- app.applyAnimation(animLp, transit, visible, voiceInteraction);
+ }
+ }
+
+ if (!WindowManagerService.sHierarchicalAnimations) {
+ return new ArraySet<>(candidates);
+ }
+
+ final ArraySet<ActivityRecord> otherApps = visible ? closingApps : openingApps;
+ // Ancestors of closing apps while finding animation targets for opening apps, or ancestors
+ // of opening apps while finding animation targets for closing apps.
+ final ArraySet<WindowContainer> otherAncestors = new ArraySet<>();
+ for (int i = 0; i < otherApps.size(); ++i) {
+ for (WindowContainer wc = otherApps.valueAt(i); wc != null; wc = wc.getParent()) {
+ otherAncestors.add(wc);
+ }
+ }
+
+ // The final animation targets which cannot promote to higher level anymore.
+ final ArraySet<WindowContainer> targets = new ArraySet<>();
+ final ArrayList<WindowContainer> siblings = new ArrayList<>();
+ while (!candidates.isEmpty()) {
+ final WindowContainer current = candidates.removeFirst();
+ final WindowContainer parent = current.getParent();
+ boolean canPromote = true;
+
+ if (parent == null) {
+ canPromote = false;
+ } else {
+ // In case a descendant of the parent belongs to the other group, we cannot promote
+ // the animation target from "current" to the parent.
+ //
+ // Example: Imagine we're checking if we can animate a Task instead of a set of
+ // ActivityRecords. In case an activity starts a new activity within a same Task,
+ // an ActivityRecord of an existing activity belongs to the opening apps, at the
+ // same time, the other ActivityRecord of a new activity belongs to the closing
+ // apps. In this case, we cannot promote the animation target to Task level, but
+ // need to animate each individual activity.
+ //
+ // [Task] +- [ActivityRecord1] (in opening apps)
+ // +- [ActivityRecord2] (in closing apps)
+ if (otherAncestors.contains(parent)) {
+ canPromote = false;
}
- final WindowState window = app.findMainWindow();
- final AccessibilityController accessibilityController =
- app.mWmService.mAccessibilityController;
- if (window != null && accessibilityController != null) {
- accessibilityController.onAppWindowTransitionLocked(window, transit);
+
+ // Find all siblings of the current WindowContainer in "candidates", move them into
+ // a separate list "siblings", and checks if an animation target can be promoted
+ // to its parent.
+ //
+ // We can promote an animation target to its parent if and only if all visible
+ // siblings will be animating.
+ //
+ // Example: Imagine that a Task contains two visible activity record, but only one
+ // of them is included in the opening apps and the other belongs to neither opening
+ // or closing apps. This happens when an activity launches another translucent
+ // activity in the same Task. In this case, we cannot animate Task, but have to
+ // animate each activity, otherwise an activity behind the translucent activity also
+ // animates.
+ //
+ // [Task] +- [ActivityRecord1] (visible, in opening apps)
+ // +- [ActivityRecord2] (visible, not in opening apps)
+ siblings.clear();
+ for (int j = 0; j < parent.getChildCount(); ++j) {
+ final WindowContainer sibling = parent.getChildAt(j);
+ if (sibling == current || candidates.remove(sibling)) {
+ siblings.add(sibling);
+ } else if (sibling.isVisible()) {
+ canPromote = false;
+ }
}
}
+
+ if (canPromote) {
+ candidates.add(parent);
+ } else {
+ targets.addAll(siblings);
+ }
+ }
+ ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM, "getAnimationTarget in=%s, out=%s",
+ apps, targets);
+ return targets;
+ }
+
+ /**
+ * Apply an app transition animation based on a set of {@link ActivityRecord}
+ *
+ * @param openingApps The list of opening apps to which an app transition animation applies.
+ * @param closingApps The list of closing apps to which an app transition animation applies.
+ * @param transit The current transition type.
+ * @param animLp Layout parameters in which an app transition animation runs.
+ * @param voiceInteraction {@code true} if one of the apps in this transition belongs to a voice
+ * interaction session driving task.
+ */
+ private void applyAnimations(ArraySet<ActivityRecord> openingApps,
+ ArraySet<ActivityRecord> closingApps, @TransitionType int transit,
+ LayoutParams animLp, boolean voiceInteraction) {
+ if (transit == WindowManager.TRANSIT_UNSET
+ || (openingApps.isEmpty() && closingApps.isEmpty())) {
+ return;
+ }
+
+ final ArraySet<WindowContainer> openingWcs = getAnimationTargets(
+ openingApps, closingApps, true /* visible */);
+ final ArraySet<WindowContainer> closingWcs = getAnimationTargets(
+ openingApps, closingApps, false /* visible */);
+ applyAnimations(openingWcs, transit, true /* visible */, animLp, voiceInteraction);
+ applyAnimations(closingWcs, transit, false /* visible */, animLp, voiceInteraction);
+
+ final AccessibilityController accessibilityController =
+ mDisplayContent.mWmService.mAccessibilityController;
+ if (accessibilityController != null) {
+ accessibilityController.onAppWindowTransitionLocked(
+ mDisplayContent.getDisplayId(), transit);
}
}
@@ -499,8 +624,8 @@ public class AppTransitionController {
// If we start the app transition at this point, we will interrupt it halfway with a
// new rotation animation after the old one finally finishes. It's better to defer the
// app transition.
- if (screenRotationAnimation != null && screenRotationAnimation.isAnimating() &&
- mDisplayContent.getDisplayRotation().needsUpdate()) {
+ if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()
+ && mDisplayContent.getDisplayRotation().needsUpdate()) {
ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
"Delaying app transition for screen rotation animation to finish");
return false;
diff --git a/services/core/java/com/android/server/wm/BoundsAnimationController.java b/services/core/java/com/android/server/wm/BoundsAnimationController.java
index 5dc88b37e445..9b464c2d1b96 100644
--- a/services/core/java/com/android/server/wm/BoundsAnimationController.java
+++ b/services/core/java/com/android/server/wm/BoundsAnimationController.java
@@ -185,6 +185,10 @@ public class BoundsAnimationController {
resume();
};
+ // If this animator is explicitly cancelled when it's in paused state, we should not
+ // attempt to resume the animation. Use this flag to avoid such behavior.
+ private boolean mIsCancelled;
+
BoundsAnimator(BoundsAnimationTarget target, @AnimationType int animationType, Rect from,
Rect to, @SchedulePipModeChangedState int schedulePipModeChangedState,
@SchedulePipModeChangedState int prevShedulePipModeChangedState,
@@ -221,6 +225,7 @@ public class BoundsAnimationController {
if (DEBUG) Slog.d(TAG, "onAnimationStart: mTarget=" + mTarget
+ " mPrevSchedulePipModeChangedState=" + mPrevSchedulePipModeChangedState
+ " mSchedulePipModeChangedState=" + mSchedulePipModeChangedState);
+ mIsCancelled = false;
mFinishAnimationAfterTransition = false;
mTmpRect.set(mFrom.left, mFrom.top, mFrom.left + mFrozenTaskWidth,
mFrom.top + mFrozenTaskHeight);
@@ -293,7 +298,7 @@ public class BoundsAnimationController {
public void resume() {
if (DEBUG) Slog.d(TAG, "resume:");
mHandler.removeCallbacks(mResumeRunnable);
- super.resume();
+ if (!mIsCancelled) super.resume();
}
@Override
@@ -376,6 +381,7 @@ public class BoundsAnimationController {
@Override
public void onAnimationCancel(Animator animation) {
+ mIsCancelled = true;
// Always skip the final resize when the animation is canceled
mSkipFinalResize = true;
mMoveToFullscreen = false;
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 4667eab1f55b..51742b97c314 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -25,6 +25,7 @@ import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
@@ -124,7 +125,7 @@ import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_SCREEN_ON;
import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
-import static com.android.server.wm.RootActivityContainer.TAG_STATES;
+import static com.android.server.wm.RootWindowContainer.TAG_STATES;
import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
@@ -166,6 +167,7 @@ import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.ActivityOptions;
import android.app.WindowConfiguration;
+import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.ActivityInfo.ScreenOrientation;
import android.content.res.CompatibilityInfo;
@@ -603,7 +605,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
*/
private static int sNextFreeStackId = 0;
- private RootActivityContainer mRootActivityContainer;
+ private RootWindowContainer mRootWindowContainer;
/**
* All of the stacks on this display. Order matters, topmost stack is in front of all other
@@ -661,8 +663,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
// Used in updating override configurations
private final Configuration mTempConfig = new Configuration();
- private final RootActivityContainer.FindTaskResult
- mTmpFindTaskResult = new RootActivityContainer.FindTaskResult();
+ private final RootWindowContainer.FindTaskResult
+ mTmpFindTaskResult = new RootWindowContainer.FindTaskResult();
private final Consumer<WindowState> mUpdateWindowsForAnimator = w -> {
WindowStateAnimator winAnimator = w.mWinAnimator;
@@ -841,6 +843,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
// Update effect.
w.mObscured = mTmpApplySurfaceChangesTransactionState.obscured;
+
if (!mTmpApplySurfaceChangesTransactionState.obscured) {
final boolean isDisplayed = w.isDisplayedLw();
@@ -871,6 +874,10 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
mTmpApplySurfaceChangesTransactionState.preferredRefreshRate
= w.mAttrs.preferredRefreshRate;
}
+
+ mTmpApplySurfaceChangesTransactionState.preferMinimalPostProcessing
+ |= w.mAttrs.preferMinimalPostProcessing;
+
final int preferredModeId = getDisplayPolicy().getRefreshRatePolicy()
.getPreferredModeId(w);
if (mTmpApplySurfaceChangesTransactionState.preferredModeId == 0
@@ -943,9 +950,9 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
* Create new {@link DisplayContent} instance, add itself to the root window container and
* initialize direct children.
* @param display May not be null.
- * @param root {@link RootActivityContainer}
+ * @param root {@link RootWindowContainer}
*/
- DisplayContent(Display display, RootActivityContainer root) {
+ DisplayContent(Display display, RootWindowContainer root) {
super(root.mWindowManager);
if (mWmService.mRoot.getDisplayContent(display.getDisplayId()) != null) {
throw new IllegalArgumentException("Display with ID=" + display.getDisplayId()
@@ -954,7 +961,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
+ " new=" + display);
}
- mRootActivityContainer = root;
+ mRootWindowContainer = root;
mAtmService = mWmService.mAtmService;
mDisplay = display;
mDisplayId = display.getDisplayId();
@@ -1032,7 +1039,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
onDisplayChanged(this);
// Add itself as a child to the root container.
- mWmService.mRoot.addChild(this, null);
+ mWmService.mRoot.addChild(this, POSITION_BOTTOM);
// TODO(b/62541591): evaluate whether this is the best spot to declare the
// {@link DisplayContent} ready for use.
@@ -1083,7 +1090,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
return token.asActivityRecord();
}
- private void addWindowToken(IBinder binder, WindowToken token) {
+ void addWindowToken(IBinder binder, WindowToken token) {
final DisplayContent dc = mWmService.mRoot.getWindowTokenDisplay(token);
if (dc != null) {
// We currently don't support adding a window token to the display if the display
@@ -1105,6 +1112,11 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
mTokenMap.put(binder, token);
if (token.asActivityRecord() == null) {
+ // Set displayContent for non-app token to prevent same token will add twice after
+ // onDisplayChanged.
+ // TODO: Check if it's fine that super.onDisplayChanged of WindowToken
+ // (WindowsContainer#onDisplayChanged) may skipped when token.mDisplayContent assigned.
+ token.mDisplayContent = this;
// Add non-app token to container hierarchy on the display. App tokens are added through
// the parent container managing them (e.g. Tasks).
switch (token.windowType) {
@@ -1336,7 +1348,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
false /* deferResume */, null /* result */);
activityRecord.frozenBeforeDestroy = true;
if (!kept) {
- mWmService.mAtmService.mRootActivityContainer.resumeFocusedStacksTopActivities();
+ mRootWindowContainer.resumeFocusedStacksTopActivities();
}
} else {
// We have a new configuration to push so we need to update ATMS for now.
@@ -2488,10 +2500,13 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
* @param inOutRegion The region to be amended.
*/
private void amendWindowTapExcludeRegion(Region inOutRegion) {
+ final Region region = Region.obtain();
for (int i = mTapExcludeProvidingWindows.size() - 1; i >= 0; i--) {
final WindowState win = mTapExcludeProvidingWindows.valueAt(i);
- win.amendTapExcludeRegion(inOutRegion);
+ win.getTapExcludeRegion(region);
+ inOutRegion.op(region, Op.UNION);
}
+ region.recycle();
}
@Override
@@ -3754,6 +3769,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
mLastHasContent,
mTmpApplySurfaceChangesTransactionState.preferredRefreshRate,
mTmpApplySurfaceChangesTransactionState.preferredModeId,
+ mTmpApplySurfaceChangesTransactionState.preferMinimalPostProcessing,
true /* inTraversal, must call performTraversalInTrans... below */);
final boolean wallpaperVisible = mWallpaperController.isWallpaperVisible();
@@ -3987,15 +4003,23 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
boolean okToDisplay() {
+ return okToDisplay(false);
+ }
+
+ boolean okToDisplay(boolean ignoreFrozen) {
if (mDisplayId == DEFAULT_DISPLAY) {
- return !mWmService.mDisplayFrozen
+ return (!mWmService.mDisplayFrozen || ignoreFrozen)
&& mWmService.mDisplayEnabled && mWmService.mPolicy.isScreenOn();
}
return mDisplayInfo.state == Display.STATE_ON;
}
boolean okToAnimate() {
- return okToDisplay() &&
+ return okToAnimate(false);
+ }
+
+ boolean okToAnimate(boolean ignoreFrozen) {
+ return okToDisplay(ignoreFrozen) &&
(mDisplayId != DEFAULT_DISPLAY || mWmService.mPolicy.okToAnimate());
}
@@ -4057,6 +4081,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
boolean displayHasContent;
boolean obscured;
boolean syswin;
+ boolean preferMinimalPostProcessing;
float preferredRefreshRate;
int preferredModeId;
@@ -4064,6 +4089,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
displayHasContent = false;
obscured = false;
syswin = false;
+ preferMinimalPostProcessing = false;
preferredRefreshRate = 0;
preferredModeId = 0;
}
@@ -4269,7 +4295,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
// The reparenting case is handled in WindowContainer.
if (!stack.mReparenting) {
setLayoutNeeded();
- stack.onDisplayChanged(DisplayContent.this);
}
}
@@ -5603,7 +5628,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
final ActivityStack currentFocusedStack = getFocusedStack();
if (currentFocusedStack != prevFocusedStack) {
mLastFocusedStack = prevFocusedStack;
- EventLogTags.writeWmFocusedStack(mRootActivityContainer.mCurrentUser, mDisplayId,
+ EventLogTags.writeWmFocusedStack(mRootWindowContainer.mCurrentUser, mDisplayId,
currentFocusedStack == null ? -1 : currentFocusedStack.getStackId(),
mLastFocusedStack == null ? -1 : mLastFocusedStack.getStackId(),
updateLastFocusedStackReason);
@@ -5688,7 +5713,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
// Create stack on default display instead since this display can only contain 1 stack.
// TODO: Kinda a hack, but better that having the decision at each call point. Hoping
// this goes away once ActivityView is no longer using virtual displays.
- return mRootActivityContainer.getDefaultDisplay().createStack(
+ return mRootWindowContainer.getDefaultDisplay().createStack(
windowingMode, activityType, onTop);
}
@@ -5727,8 +5752,14 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
throw new IllegalArgumentException("Stack with windowing mode cannot with non standard "
+ "activity type.");
}
- return new ActivityStack(this, stackId, mRootActivityContainer.mStackSupervisor,
- windowingMode, activityType, onTop);
+ final ActivityStack stack = new ActivityStack(this, stackId,
+ mRootWindowContainer.mStackSupervisor, activityType);
+ addStack(stack, onTop ? POSITION_TOP : POSITION_BOTTOM);
+ stack.setWindowingMode(windowingMode, false /* animate */, false /* showRecents */,
+ false /* enteringSplitScreenMode */, false /* deferEnsuringVisibility */,
+ true /* creating */);
+
+ return stack;
}
/**
@@ -5857,7 +5888,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
* Find task for putting the Activity in.
*/
void findTaskLocked(final ActivityRecord r, final boolean isPreferredDisplay,
- RootActivityContainer.FindTaskResult result) {
+ RootWindowContainer.FindTaskResult result) {
mTmpFindTaskResult.clear();
for (int stackNdx = getStackCount() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = getStackAt(stackNdx);
@@ -5916,7 +5947,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
for (int i = stacks.size() - 1; i >= 0; --i) {
- mRootActivityContainer.mStackSupervisor.removeStack(stacks.get(i));
+ mRootWindowContainer.mStackSupervisor.removeStack(stacks.get(i));
}
}
@@ -5940,7 +5971,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
for (int i = stacks.size() - 1; i >= 0; --i) {
- mRootActivityContainer.mStackSupervisor.removeStack(stacks.get(i));
+ mRootWindowContainer.mStackSupervisor.removeStack(stacks.get(i));
}
}
@@ -6017,6 +6048,10 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
return false;
}
+ if (windowingMode == WINDOWING_MODE_MULTI_WINDOW) {
+ return true;
+ }
+
final int displayWindowingMode = getWindowingMode();
if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
|| windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
@@ -6175,7 +6210,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
// This activity can be considered the top running activity if we are not considering
// the locked state, the keyguard isn't locked, or we can show when locked.
if (topRunning != null && considerKeyguardState
- && mRootActivityContainer.mStackSupervisor.getKeyguardController()
+ && mRootWindowContainer.mStackSupervisor.getKeyguardController()
.isKeyguardLocked()
&& !topRunning.canShowWhenLocked()) {
return null;
@@ -6335,8 +6370,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
// released (no more ActivityStack). But, we cannot release it at that moment or the
// related WindowContainer will also be removed. So, we set display as removed after
// reparenting stack finished.
- final DisplayContent toDisplay = mRootActivityContainer.getDefaultDisplay();
- mRootActivityContainer.mStackSupervisor.beginDeferResume();
+ final DisplayContent toDisplay = mRootWindowContainer.getDefaultDisplay();
+ mRootWindowContainer.mStackSupervisor.beginDeferResume();
try {
int numStacks = getStackCount();
// Keep the order from bottom to top.
@@ -6362,7 +6397,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
numStacks = getStackCount();
}
} finally {
- mRootActivityContainer.mStackSupervisor.endDeferResume();
+ mRootWindowContainer.mStackSupervisor.endDeferResume();
}
mRemoved = true;
@@ -6374,7 +6409,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
releaseSelfIfNeeded();
if (!mAllSleepTokens.isEmpty()) {
- mRootActivityContainer.mSleepTokens.removeAll(mAllSleepTokens);
+ mRootWindowContainer.mSleepTokens.removeAll(mAllSleepTokens);
mAllSleepTokens.clear();
mAtmService.updateSleepIfNeededLocked();
}
@@ -6393,8 +6428,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
stack.removeIfPossible();
} else if (getTopStack() == null) {
removeIfPossible();
- mRootActivityContainer.removeChild(this);
- mRootActivityContainer.mStackSupervisor
+ mRootWindowContainer.mStackSupervisor
.getKeyguardController().onDisplayRemoved(mDisplayId);
}
}
@@ -6540,7 +6574,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
@Nullable
ActivityRecord getHomeActivity() {
- return getHomeActivityForUser(mRootActivityContainer.mCurrentUser);
+ return getHomeActivityForUser(mRootWindowContainer.mCurrentUser);
}
@Nullable
@@ -6640,4 +6674,22 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
}
}
+
+ /**
+ * Similar to {@link RootWindowContainer#isAnyNonToastWindowVisibleForUid(int)}, but
+ * used for pid.
+ */
+ boolean isAnyNonToastWindowVisibleForPid(int pid) {
+ final PooledPredicate p = PooledLambda.obtainPredicate(
+ WindowState::isNonToastWindowVisibleForPid,
+ PooledLambda.__(WindowState.class), pid);
+
+ final WindowState w = getWindow(p);
+ p.recycle();
+ return w != null;
+ }
+
+ Context getDisplayUiContext() {
+ return mDisplayPolicy.getSystemUiContext();
+ }
}
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 667e713d0b39..694a73d626f8 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -232,6 +232,7 @@ public class DisplayPolicy {
private final WindowManagerService mService;
private final Context mContext;
+ private final Context mUiContext;
private final DisplayContent mDisplayContent;
private final Object mLock;
private final Handler mHandler;
@@ -449,6 +450,9 @@ public class DisplayPolicy {
mService = service;
mContext = displayContent.isDefaultDisplay ? service.mContext
: service.mContext.createDisplayContext(displayContent.getDisplay());
+ mUiContext = displayContent.isDefaultDisplay ? service.mAtmService.mUiContext
+ : service.mAtmService.mSystemThread
+ .createSystemUiContext(displayContent.getDisplayId());
mDisplayContent = displayContent;
mLock = service.getWindowManagerLock();
@@ -1874,7 +1878,7 @@ public class DisplayPolicy {
final Rect dfu = displayFrames.mUnrestricted;
Insets insets = Insets.of(0, 0, 0, 0);
for (int i = types.size() - 1; i >= 0; i--) {
- insets = Insets.max(insets, mDisplayContent.getInsetsStateController()
+ insets = Insets.max(insets, mDisplayContent.getInsetsPolicy()
.getInsetsForDispatch(win).getSource(types.valueAt(i))
.calculateInsets(dfu, attrs.getFitIgnoreVisibility()));
}
@@ -2765,10 +2769,8 @@ public class DisplayPolicy {
return mContext;
}
- private Context getSystemUiContext() {
- final Context uiContext = ActivityThread.currentActivityThread().getSystemUiContext();
- return mDisplayContent.isDefaultDisplay
- ? uiContext : uiContext.createDisplayContext(mDisplayContent.getDisplay());
+ Context getSystemUiContext() {
+ return mUiContext;
}
private int getNavigationBarWidth(int rotation, int uiMode) {
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index c7c3f8ad54a2..b59c4e38214b 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -442,13 +442,17 @@ public class DisplayRotation {
final int lastOrientation = mLastOrientation;
final int rotation = rotationForOrientation(lastOrientation, oldRotation);
ProtoLog.v(WM_DEBUG_ORIENTATION,
- "Computed rotation=%d for display id=%d based on lastOrientation=%d and "
- + "oldRotation=%d",
- rotation, displayId, lastOrientation, oldRotation);
+ "Computed rotation=%s (%d) for display id=%d based on lastOrientation=%s (%d) and "
+ + "oldRotation=%s (%d)",
+ Surface.rotationToString(rotation), rotation,
+ displayId,
+ ActivityInfo.screenOrientationToString(lastOrientation), lastOrientation,
+ Surface.rotationToString(oldRotation), oldRotation);
ProtoLog.v(WM_DEBUG_ORIENTATION,
- "Display id=%d selected orientation %d, got rotation %d", displayId,
- lastOrientation, rotation);
+ "Display id=%d selected orientation %s (%d), got rotation %s (%d)", displayId,
+ ActivityInfo.screenOrientationToString(lastOrientation), lastOrientation,
+ Surface.rotationToString(rotation), rotation);
if (oldRotation == rotation) {
// No change.
diff --git a/services/core/java/com/android/server/wm/DisplayWindowListenerController.java b/services/core/java/com/android/server/wm/DisplayWindowListenerController.java
index bb31d4522890..af13e3a76cf1 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowListenerController.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowListenerController.java
@@ -39,9 +39,9 @@ class DisplayWindowListenerController {
synchronized (mService.mGlobalLock) {
mDisplayListeners.register(listener);
try {
- for (int i = 0; i < mService.mAtmService.mRootActivityContainer.getChildCount();
+ for (int i = 0; i < mService.mAtmService.mRootWindowContainer.getChildCount();
++i) {
- DisplayContent d = mService.mAtmService.mRootActivityContainer.getChildAt(i);
+ DisplayContent d = mService.mAtmService.mRootWindowContainer.getChildAt(i);
listener.onDisplayAdded(d.mDisplayId);
}
} catch (RemoteException e) { }
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index 255ef6ec3e55..a26dfdb1bcd4 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -276,7 +276,6 @@ class DragState {
display.getDisplayId());
mDragWindowHandle.name = "drag";
mDragWindowHandle.token = mServerChannel.getToken();
- mDragWindowHandle.layer = getDragLayerLocked();
mDragWindowHandle.layoutParamsFlags = 0;
mDragWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG;
mDragWindowHandle.dispatchingTimeoutNanos =
@@ -345,12 +344,6 @@ class DragState {
}
}
- int getDragLayerLocked() {
- return mService.mPolicy.getWindowLayerFromTypeLw(WindowManager.LayoutParams.TYPE_DRAG)
- * WindowManagerService.TYPE_LAYER_MULTIPLIER
- + WindowManagerService.TYPE_LAYER_OFFSET;
- }
-
/* call out to each visible window/session informing it about the drag
*/
void broadcastDragStartedLocked(final float touchX, final float touchY) {
diff --git a/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java b/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java
index 949ff195d731..e74f61d53fea 100644
--- a/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java
+++ b/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java
@@ -59,7 +59,7 @@ class EnsureActivitiesVisibleHelper {
/**
* Ensure visibility with an option to also update the configuration of visible activities.
* @see ActivityStack#ensureActivitiesVisible(ActivityRecord, int, boolean)
- * @see RootActivityContainer#ensureActivitiesVisible(ActivityRecord, int, boolean)
+ * @see RootWindowContainer#ensureActivitiesVisible(ActivityRecord, int, boolean)
*/
void process(ActivityRecord starting, int configChanges, boolean preserveWindows,
boolean notifyClients) {
diff --git a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
index a0b878ca44dc..05ede21472f2 100644
--- a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
@@ -96,8 +96,11 @@ class ImeInsetsSourceProvider extends InsetsSourceProvider {
// TODO(b/139861270): Remove the child & sublayer check once IMMS is aware of
// actual IME target.
final WindowState dcTarget = mDisplayContent.mInputMethodTarget;
+ if (dcTarget == null) {
+ return false;
+ }
return (!dcTarget.isClosing() && mImeTargetFromIme == dcTarget)
- || (dcTarget.getParentWindow() == mImeTargetFromIme
+ || (mImeTargetFromIme != null && dcTarget.getParentWindow() == mImeTargetFromIme
&& dcTarget.mSubLayer > mImeTargetFromIme.mSubLayer);
}
diff --git a/services/core/java/com/android/server/wm/InputConsumerImpl.java b/services/core/java/com/android/server/wm/InputConsumerImpl.java
index ebe9f08f83b7..c6183de38c29 100644
--- a/services/core/java/com/android/server/wm/InputConsumerImpl.java
+++ b/services/core/java/com/android/server/wm/InputConsumerImpl.java
@@ -76,7 +76,6 @@ class InputConsumerImpl implements IBinder.DeathRecipient {
mWindowHandle.name = name;
mWindowHandle.token = mServerChannel.getToken();
mWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_INPUT_CONSUMER;
- mWindowHandle.layer = getLayerLw(mWindowHandle.layoutParamsType);
mWindowHandle.layoutParamsFlags = 0;
mWindowHandle.dispatchingTimeoutNanos =
WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
@@ -150,12 +149,6 @@ class InputConsumerImpl implements IBinder.DeathRecipient {
t.setLayer(mInputSurface, layer);
}
- private int getLayerLw(int windowType) {
- return mService.mPolicy.getWindowLayerFromTypeLw(windowType)
- * WindowManagerService.TYPE_LAYER_MULTIPLIER
- + WindowManagerService.TYPE_LAYER_OFFSET;
- }
-
void disposeChannelsLw() {
mService.mInputManager.unregisterInputChannel(mServerChannel);
mClientChannel.dispose();
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index f9ff2e395793..b9a9c125c168 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -264,7 +264,6 @@ final class InputMonitor {
inputWindowHandle.hasFocus = hasFocus;
inputWindowHandle.hasWallpaper = hasWallpaper;
inputWindowHandle.paused = child.mActivityRecord != null ? child.mActivityRecord.paused : false;
- inputWindowHandle.layer = child.mLayer;
inputWindowHandle.ownerPid = child.mSession.mPid;
inputWindowHandle.ownerUid = child.mSession.mUid;
inputWindowHandle.inputFeatures = child.mAttrs.inputFeatures;
@@ -499,8 +498,7 @@ final class InputMonitor {
}
}
- if (mAddInputConsumerHandle
- && inputWindowHandle.layer <= navInputConsumer.mWindowHandle.layer) {
+ if (mAddInputConsumerHandle) {
navInputConsumer.show(mInputTransaction, w);
mAddInputConsumerHandle = false;
}
diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
index 082187384646..184e7d61c355 100644
--- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
@@ -24,6 +24,8 @@ import static android.view.ViewRootImpl.NEW_INSETS_MODE_IME;
import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE;
import static android.view.ViewRootImpl.sNewInsetsMode;
+import static com.android.server.wm.WindowManagerService.H.LAYOUT_AND_ASSIGN_WINDOW_LAYERS_IF_NEEDED;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.graphics.Point;
@@ -36,7 +38,6 @@ import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
import com.android.internal.util.function.TriConsumer;
-import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
import java.io.PrintWriter;
@@ -222,8 +223,8 @@ class InsetsSourceProvider {
return;
}
mClientVisible = clientVisible;
- mDisplayContent.mWmService.mH.sendMessage(PooledLambda.obtainMessage(
- DisplayContent::layoutAndAssignWindowLayersIfNeeded, mDisplayContent));
+ mDisplayContent.mWmService.mH.obtainMessage(
+ LAYOUT_AND_ASSIGN_WINDOW_LAYERS_IF_NEEDED, mDisplayContent).sendToTarget();
updateVisibility();
}
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index 6f8195712337..7db30f6009b4 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -73,7 +73,7 @@ class KeyguardController {
private int mVisibilityTransactionDepth;
private final SparseArray<KeyguardDisplayState> mDisplayStates = new SparseArray<>();
private final ActivityTaskManagerService mService;
- private RootActivityContainer mRootActivityContainer;
+ private RootWindowContainer mRootWindowContainer;
KeyguardController(ActivityTaskManagerService service,
ActivityStackSupervisor stackSupervisor) {
@@ -83,7 +83,7 @@ class KeyguardController {
void setWindowManager(WindowManagerService windowManager) {
mWindowManager = windowManager;
- mRootActivityContainer = mService.mRootActivityContainer;
+ mRootWindowContainer = mService.mRootWindowContainer;
}
/**
@@ -165,7 +165,7 @@ class KeyguardController {
// Update the sleep token first such that ensureActivitiesVisible has correct sleep token
// state when evaluating visibilities.
updateKeyguardSleepToken();
- mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
+ mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
}
/**
@@ -187,16 +187,16 @@ class KeyguardController {
mAodShowing ? 1 : 0,
1 /* keyguardGoingAway */,
"keyguardGoingAway");
- mRootActivityContainer.getDefaultDisplay().mDisplayContent
+ mRootWindowContainer.getDefaultDisplay().mDisplayContent
.prepareAppTransition(TRANSIT_KEYGUARD_GOING_AWAY,
false /* alwaysKeepCurrent */, convertTransitFlags(flags),
false /* forceOverride */);
updateKeyguardSleepToken();
// Some stack visibility might change (e.g. docked stack)
- mRootActivityContainer.resumeFocusedStacksTopActivities();
- mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
- mRootActivityContainer.addStartingWindowsForVisibleActivities();
+ mRootWindowContainer.resumeFocusedStacksTopActivities();
+ mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
+ mRootWindowContainer.addStartingWindowsForVisibleActivities();
mWindowManager.executeAppTransition();
} finally {
mService.continueWindowLayout();
@@ -294,9 +294,9 @@ class KeyguardController {
private void visibilitiesUpdated() {
boolean requestDismissKeyguard = false;
- for (int displayNdx = mRootActivityContainer.getChildCount() - 1;
+ for (int displayNdx = mRootWindowContainer.getChildCount() - 1;
displayNdx >= 0; displayNdx--) {
- final DisplayContent display = mRootActivityContainer.getChildAt(displayNdx);
+ final DisplayContent display = mRootWindowContainer.getChildAt(displayNdx);
final KeyguardDisplayState state = getDisplay(display.mDisplayId);
state.visibilitiesUpdated(this, display);
requestDismissKeyguard |= state.mRequestDismissKeyguard;
@@ -325,12 +325,12 @@ class KeyguardController {
if (isKeyguardLocked()) {
mService.deferWindowLayout();
try {
- mRootActivityContainer.getDefaultDisplay().mDisplayContent
+ mRootWindowContainer.getDefaultDisplay().mDisplayContent
.prepareAppTransition(resolveOccludeTransit(),
false /* alwaysKeepCurrent */, 0 /* flags */,
true /* forceOverride */);
updateKeyguardSleepToken(DEFAULT_DISPLAY);
- mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
+ mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
mWindowManager.executeAppTransition();
} finally {
mService.continueWindowLayout();
@@ -356,12 +356,12 @@ class KeyguardController {
// If we are about to unocclude the Keyguard, but we can dismiss it without security,
// we immediately dismiss the Keyguard so the activity gets shown without a flicker.
final DisplayContent dc =
- mRootActivityContainer.getDefaultDisplay().mDisplayContent;
+ mRootWindowContainer.getDefaultDisplay().mDisplayContent;
if (mKeyguardShowing && canDismissKeyguard()
&& dc.mAppTransition.getAppTransition() == TRANSIT_KEYGUARD_UNOCCLUDE) {
dc.prepareAppTransition(mBeforeUnoccludeTransit, false /* alwaysKeepCurrent */,
0 /* flags */, true /* forceOverride */);
- mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
+ mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
mWindowManager.executeAppTransition();
}
}
@@ -379,8 +379,7 @@ class KeyguardController {
}
private int resolveOccludeTransit() {
- final DisplayContent dc =
- mService.mRootActivityContainer.getDefaultDisplay().mDisplayContent;
+ final DisplayContent dc = mRootWindowContainer.getDefaultDisplay().mDisplayContent;
if (mBeforeUnoccludeTransit != TRANSIT_UNSET
&& dc.mAppTransition.getAppTransition() == TRANSIT_KEYGUARD_UNOCCLUDE
// TODO(b/113840485): Handle app transition for individual display.
@@ -408,7 +407,7 @@ class KeyguardController {
// stack since it will be complicated/risky to try to put the activity on top
// of the lock screen in the right fullscreen configuration.
final ActivityStack stack =
- mRootActivityContainer.getDefaultDisplay().getSplitScreenPrimaryStack();
+ mRootWindowContainer.getDefaultDisplay().getSplitScreenPrimaryStack();
if (stack == null) {
return;
}
@@ -418,9 +417,9 @@ class KeyguardController {
}
private void updateKeyguardSleepToken() {
- for (int displayNdx = mRootActivityContainer.getChildCount() - 1;
+ for (int displayNdx = mRootWindowContainer.getChildCount() - 1;
displayNdx >= 0; displayNdx--) {
- final DisplayContent display = mRootActivityContainer.getChildAt(displayNdx);
+ final DisplayContent display = mRootWindowContainer.getChildAt(displayNdx);
updateKeyguardSleepToken(display.mDisplayId);
}
}
@@ -509,7 +508,7 @@ class KeyguardController {
}
// TODO(b/123372519): isShowingDream can only works on default display.
if (mDisplayId == DEFAULT_DISPLAY) {
- mOccluded |= mService.mRootActivityContainer.getDefaultDisplay().mDisplayContent
+ mOccluded |= mService.mRootWindowContainer.getDefaultDisplay().mDisplayContent
.getDisplayPolicy().isShowingDreamLw();
}
diff --git a/services/core/java/com/android/server/wm/LaunchParamsPersister.java b/services/core/java/com/android/server/wm/LaunchParamsPersister.java
index 8cf3dc8ff970..0beae7ed9da3 100644
--- a/services/core/java/com/android/server/wm/LaunchParamsPersister.java
+++ b/services/core/java/com/android/server/wm/LaunchParamsPersister.java
@@ -224,7 +224,7 @@ class LaunchParamsPersister {
final ActivityStack stack = task.getStack();
final int displayId = stack.mDisplayId;
final DisplayContent display =
- mSupervisor.mRootActivityContainer.getDisplayContent(displayId);
+ mSupervisor.mRootWindowContainer.getDisplayContent(displayId);
final DisplayInfo info = new DisplayInfo();
display.mDisplay.getDisplayInfo(info);
@@ -260,7 +260,7 @@ class LaunchParamsPersister {
return;
}
- final DisplayContent display = mSupervisor.mRootActivityContainer.getDisplayContent(
+ final DisplayContent display = mSupervisor.mRootWindowContainer.getDisplayContent(
persistableParams.mDisplayUniqueId);
if (display != null) {
outParams.mPreferredDisplayId = display.mDisplayId;
diff --git a/services/core/java/com/android/server/wm/LockTaskController.java b/services/core/java/com/android/server/wm/LockTaskController.java
index 7a72b435ac8a..02413bb48518 100644
--- a/services/core/java/com/android/server/wm/LockTaskController.java
+++ b/services/core/java/com/android/server/wm/LockTaskController.java
@@ -459,7 +459,7 @@ public class LockTaskController {
return;
}
task.performClearTaskLocked();
- mSupervisor.mRootActivityContainer.resumeFocusedStacksTopActivities();
+ mSupervisor.mRootWindowContainer.resumeFocusedStacksTopActivities();
}
/**
@@ -591,7 +591,7 @@ public class LockTaskController {
if (andResume) {
mSupervisor.findTaskToMoveToFront(task, 0, null, reason,
lockTaskModeState != LOCK_TASK_MODE_NONE);
- mSupervisor.mRootActivityContainer.resumeFocusedStacksTopActivities();
+ mSupervisor.mRootWindowContainer.resumeFocusedStacksTopActivities();
final ActivityStack stack = task.getStack();
if (stack != null) {
stack.getDisplay().mDisplayContent.executeAppTransition();
@@ -653,9 +653,9 @@ public class LockTaskController {
taskChanged = true;
}
- mSupervisor.mRootActivityContainer.mRootWindowContainer.forAllTasks(Task::setLockTaskAuth);
+ mSupervisor.mRootWindowContainer.forAllTasks(Task::setLockTaskAuth);
- final ActivityRecord r = mSupervisor.mRootActivityContainer.topRunningActivity();
+ final ActivityRecord r = mSupervisor.mRootWindowContainer.topRunningActivity();
final Task task = (r != null) ? r.getTask() : null;
if (mLockTaskModeTasks.isEmpty() && task!= null
&& task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE) {
@@ -667,7 +667,7 @@ public class LockTaskController {
}
if (taskChanged) {
- mSupervisor.mRootActivityContainer.resumeFocusedStacksTopActivities();
+ mSupervisor.mRootWindowContainer.resumeFocusedStacksTopActivities();
}
}
diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java
index a8e7aea64883..b4f75e545729 100644
--- a/services/core/java/com/android/server/wm/PinnedStackController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackController.java
@@ -16,38 +16,29 @@
package com.android.server.wm;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
-import static android.util.TypedValue.COMPLEX_UNIT_DIP;
import static com.android.server.wm.PinnedStackControllerProto.DEFAULT_BOUNDS;
import static com.android.server.wm.PinnedStackControllerProto.MOVEMENT_BOUNDS;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-import android.annotation.NonNull;
import android.app.RemoteAction;
import android.content.ComponentName;
import android.content.pm.ParceledListSlice;
import android.content.res.Resources;
-import android.graphics.Point;
import android.graphics.Rect;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.DisplayMetrics;
import android.util.Log;
-import android.util.Size;
import android.util.Slog;
-import android.util.TypedValue;
import android.util.proto.ProtoOutputStream;
import android.view.DisplayInfo;
-import android.view.Gravity;
import android.view.IPinnedStackController;
import android.view.IPinnedStackListener;
-import com.android.internal.policy.PipSnapAlgorithm;
-import com.android.internal.util.Preconditions;
import com.android.server.UiThread;
import java.io.PrintWriter;
@@ -74,7 +65,6 @@ class PinnedStackController {
private static final String TAG = TAG_WITH_CLASS_NAME ? "PinnedStackController" : TAG_WM;
- private static final float INVALID_SNAP_FRACTION = -1f;
private final WindowManagerService mService;
private final DisplayContent mDisplayContent;
private final Handler mHandler = UiThread.getHandler();
@@ -84,7 +74,6 @@ class PinnedStackController {
new PinnedStackListenerDeathHandler();
private final PinnedStackControllerCallback mCallbacks = new PinnedStackControllerCallback();
- private final PipSnapAlgorithm mSnapAlgorithm;
// States that affect how the PIP can be manipulated
private boolean mIsMinimized;
@@ -97,13 +86,9 @@ class PinnedStackController {
// Used to calculate stack bounds across rotations
private final DisplayInfo mDisplayInfo = new DisplayInfo();
- private final Rect mStableInsets = new Rect();
// The size and position information that describes where the pinned stack will go by default.
- private int mDefaultMinSize;
- private int mDefaultStackGravity;
private float mDefaultAspectRatio;
- private Point mScreenEdgeInsets;
// The aspect ratio bounds of the PIP.
private float mMinAspectRatio;
@@ -111,10 +96,11 @@ class PinnedStackController {
// Temp vars for calculation
private final DisplayMetrics mTmpMetrics = new DisplayMetrics();
- private final Rect mTmpInsets = new Rect();
- private final Rect mTmpRect = new Rect();
- private final Point mTmpDisplaySize = new Point();
+ // TODO(b/141200935): remove this when we have default/movement bounds tests in SysUI.
+ // Keep record of the default and movement bounds
+ private final Rect mLastReportedDefaultBounds = new Rect();
+ private final Rect mLastReportedMovementBounds = new Rect();
/**
* The callback object passed to listeners for them to notify the controller of state changes.
@@ -125,7 +111,6 @@ class PinnedStackController {
public void setIsMinimized(final boolean isMinimized) {
mHandler.post(() -> {
mIsMinimized = isMinimized;
- mSnapAlgorithm.setMinimized(isMinimized);
});
}
@@ -145,6 +130,27 @@ class PinnedStackController {
sourceRectHint, animationDuration, true /* fromFullscreen */);
}
}
+
+ @Override
+ public void resetBoundsAnimation(Rect bounds) {
+ synchronized (mService.mGlobalLock) {
+ if (mDisplayContent.hasPinnedStack()) {
+ final ActivityStack pinnedStack = mDisplayContent.getTopStackInWindowingMode(
+ WINDOWING_MODE_PINNED);
+ if (pinnedStack != null) {
+ pinnedStack.resetCurrentBoundsAnimation(bounds);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void reportBounds(Rect defaultBounds, Rect movementBounds) {
+ synchronized (mService.mGlobalLock) {
+ mLastReportedDefaultBounds.set(defaultBounds);
+ mLastReportedMovementBounds.set(movementBounds);
+ }
+ }
}
/**
@@ -165,7 +171,6 @@ class PinnedStackController {
PinnedStackController(WindowManagerService service, DisplayContent displayContent) {
mService = service;
mDisplayContent = displayContent;
- mSnapAlgorithm = new PipSnapAlgorithm(service.mContext);
mDisplayInfo.copyFrom(mDisplayContent.getDisplayInfo());
reloadResources();
// Initialize the aspect ratio to the default aspect ratio. Don't do this in reload
@@ -183,21 +188,9 @@ class PinnedStackController {
*/
private void reloadResources() {
final Resources res = mService.mContext.getResources();
- mDefaultMinSize = res.getDimensionPixelSize(
- com.android.internal.R.dimen.default_minimal_size_pip_resizable_task);
mDefaultAspectRatio = res.getFloat(
com.android.internal.R.dimen.config_pictureInPictureDefaultAspectRatio);
- final String screenEdgeInsetsDpString = res.getString(
- com.android.internal.R.string.config_defaultPictureInPictureScreenEdgeInsets);
- final Size screenEdgeInsetsDp = !screenEdgeInsetsDpString.isEmpty()
- ? Size.parseSize(screenEdgeInsetsDpString)
- : null;
- mDefaultStackGravity = res.getInteger(
- com.android.internal.R.integer.config_defaultPictureInPictureGravity);
mDisplayContent.getDisplay().getRealMetrics(mTmpMetrics);
- mScreenEdgeInsets = screenEdgeInsetsDp == null ? new Point()
- : new Point(dpToPx(screenEdgeInsetsDp.getWidth(), mTmpMetrics),
- dpToPx(screenEdgeInsetsDp.getHeight(), mTmpMetrics));
mMinAspectRatio = res.getFloat(
com.android.internal.R.dimen.config_pictureInPictureMinAspectRatio);
mMaxAspectRatio = res.getFloat(
@@ -215,7 +208,7 @@ class PinnedStackController {
notifyDisplayInfoChanged(mDisplayInfo);
notifyImeVisibilityChanged(mIsImeShowing, mImeHeight);
// The movement bounds notification needs to be sent before the minimized state, since
- // SystemUI may use the bounds to retore the minimized position
+ // SystemUI may use the bounds to restore the minimized position
notifyMovementBoundsChanged(false /* fromImeAdjustment */,
false /* fromShelfAdjustment */);
notifyActionsChanged(mActions);
@@ -257,30 +250,6 @@ class PinnedStackController {
}
}
- /**
- * @return the default bounds to show the PIP, if a {@param snapFraction} is provided, then it
- * will apply the default bounds to the provided snap fraction.
- */
- private Rect getDefaultBounds(float snapFraction) {
- synchronized (mService.mGlobalLock) {
- final Rect insetBounds = new Rect();
- getInsetBounds(insetBounds);
-
- final Rect defaultBounds = new Rect();
- final Size size = mSnapAlgorithm.getSizeForAspectRatio(mDefaultAspectRatio,
- mDefaultMinSize, mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
- if (snapFraction != INVALID_SNAP_FRACTION) {
- defaultBounds.set(0, 0, size.getWidth(), size.getHeight());
- final Rect movementBounds = getMovementBounds(defaultBounds);
- mSnapAlgorithm.applySnapFraction(defaultBounds, movementBounds, snapFraction);
- } else {
- Gravity.apply(mDefaultStackGravity, size.getWidth(), size.getHeight(), insetBounds,
- 0, mIsImeShowing ? mImeHeight : 0, defaultBounds);
- }
- return defaultBounds;
- }
- }
-
private void setDisplayInfo(DisplayInfo displayInfo) {
mDisplayInfo.copyFrom(displayInfo);
notifyDisplayInfoChanged(mDisplayInfo);
@@ -300,51 +269,6 @@ class PinnedStackController {
}
/**
- * Updates the display info, calculating and returning the new stack and movement bounds in the
- * new orientation of the device if necessary.
- */
- boolean onTaskStackBoundsChanged(Rect targetBounds, Rect outBounds) {
- synchronized (mService.mGlobalLock) {
- final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
- if (isSameDimensionAndRotation(mDisplayInfo, displayInfo)) {
- // No dimension/rotation change, ignore
- outBounds.setEmpty();
- return false;
- } else if (targetBounds.isEmpty()) {
- // The stack is null, we are just initializing the stack, so just store the display
- // info and ignore
- setDisplayInfo(displayInfo);
- outBounds.setEmpty();
- return false;
- }
-
- mTmpRect.set(targetBounds);
- final Rect postChangeStackBounds = mTmpRect;
-
- // Calculate the snap fraction of the current stack along the old movement bounds
- final float snapFraction = getSnapFraction(postChangeStackBounds);
-
- setDisplayInfo(displayInfo);
-
- // Calculate the stack bounds in the new orientation to the same same fraction along the
- // rotated movement bounds.
- final Rect postChangeMovementBounds = getMovementBounds(postChangeStackBounds,
- false /* adjustForIme */);
- mSnapAlgorithm.applySnapFraction(postChangeStackBounds, postChangeMovementBounds,
- snapFraction);
- if (mIsMinimized) {
- applyMinimizedOffset(postChangeStackBounds, postChangeMovementBounds);
- }
-
- notifyMovementBoundsChanged(false /* fromImeAdjustment */,
- false /* fromShelfAdjustment */);
-
- outBounds.set(postChangeStackBounds);
- return true;
- }
- }
-
- /**
* Sets the Ime state and height.
*/
void setAdjustedForIme(boolean adjustedForIme, int imeHeight) {
@@ -400,15 +324,6 @@ class PinnedStackController {
notifyPrepareAnimation(sourceRectHint, aspectRatio, stackBounds);
}
- private boolean isSameDimensionAndRotation(@NonNull DisplayInfo display1,
- @NonNull DisplayInfo display2) {
- Preconditions.checkNotNull(display1);
- Preconditions.checkNotNull(display2);
- return ((display1.rotation == display2.rotation)
- && (display1.logicalWidth == display2.logicalWidth)
- && (display1.logicalHeight == display2.logicalHeight));
- }
-
/**
* Notifies listeners that the PIP needs to be adjusted for the IME.
*/
@@ -504,86 +419,11 @@ class PinnedStackController {
}
}
- /**
- * @return the bounds on the screen that the PIP can be visible in.
- */
- private void getInsetBounds(Rect outRect) {
- synchronized (mService.mGlobalLock) {
- mDisplayContent.getDisplayPolicy().getStableInsetsLw(mDisplayInfo.rotation,
- mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight,
- mDisplayInfo.displayCutout, mTmpInsets);
- outRect.set(mTmpInsets.left + mScreenEdgeInsets.x, mTmpInsets.top + mScreenEdgeInsets.y,
- mDisplayInfo.logicalWidth - mTmpInsets.right - mScreenEdgeInsets.x,
- mDisplayInfo.logicalHeight - mTmpInsets.bottom - mScreenEdgeInsets.y);
- }
- }
-
- /**
- * @return the movement bounds for the given {@param stackBounds} and the current state of the
- * controller.
- */
- private Rect getMovementBounds(Rect stackBounds) {
- synchronized (mService.mGlobalLock) {
- return getMovementBounds(stackBounds, true /* adjustForIme */);
- }
- }
-
- /**
- * @return the movement bounds for the given {@param stackBounds} and the current state of the
- * controller.
- */
- private Rect getMovementBounds(Rect stackBounds, boolean adjustForIme) {
- synchronized (mService.mGlobalLock) {
- final Rect movementBounds = new Rect();
- getInsetBounds(movementBounds);
-
- // Apply the movement bounds adjustments based on the current state.
- // Note that shelf offset does not affect the movement bounds here
- // since it's been taken care of in system UI.
- mSnapAlgorithm.getMovementBounds(stackBounds, movementBounds, movementBounds,
- (adjustForIme && mIsImeShowing) ? mImeHeight : 0);
- return movementBounds;
- }
- }
-
- /**
- * Applies the minimized offsets to the given stack bounds.
- */
- private void applyMinimizedOffset(Rect stackBounds, Rect movementBounds) {
- synchronized (mService.mGlobalLock) {
- mTmpDisplaySize.set(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
- mService.getStableInsetsLocked(mDisplayContent.getDisplayId(), mStableInsets);
- mSnapAlgorithm.applyMinimizedOffset(stackBounds, movementBounds, mTmpDisplaySize,
- mStableInsets);
- }
- }
-
- /**
- * @return the default snap fraction to apply instead of the default gravity when calculating
- * the default stack bounds when first entering PiP.
- */
- private float getSnapFraction(Rect stackBounds) {
- return mSnapAlgorithm.getSnapFraction(stackBounds, getMovementBounds(stackBounds));
- }
-
- /**
- * @return the pixels for a given dp value.
- */
- private int dpToPx(float dpValue, DisplayMetrics dm) {
- return (int) TypedValue.applyDimension(COMPLEX_UNIT_DIP, dpValue, dm);
- }
-
void dump(String prefix, PrintWriter pw) {
pw.println(prefix + "PinnedStackController");
- pw.print(prefix + " defaultBounds=");
- getDefaultBounds(INVALID_SNAP_FRACTION).printShortString(pw);
- pw.println();
- pw.println(prefix + " mDefaultMinSize=" + mDefaultMinSize);
- pw.println(prefix + " mDefaultStackGravity=" + mDefaultStackGravity);
+ pw.println(prefix + " mLastReportedDefaultBounds=" + mLastReportedDefaultBounds);
+ pw.println(prefix + " mLastReportedMovementBounds=" + mLastReportedMovementBounds);
pw.println(prefix + " mDefaultAspectRatio=" + mDefaultAspectRatio);
- mService.getStackBounds(WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, mTmpRect);
- pw.print(prefix + " movementBounds="); getMovementBounds(mTmpRect).printShortString(pw);
- pw.println();
pw.println(prefix + " mIsImeShowing=" + mIsImeShowing);
pw.println(prefix + " mImeHeight=" + mImeHeight);
pw.println(prefix + " mIsMinimized=" + mIsMinimized);
@@ -606,9 +446,8 @@ class PinnedStackController {
void dumpDebug(ProtoOutputStream proto, long fieldId) {
final long token = proto.start(fieldId);
- getDefaultBounds(INVALID_SNAP_FRACTION).dumpDebug(proto, DEFAULT_BOUNDS);
- mService.getStackBounds(WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, mTmpRect);
- getMovementBounds(mTmpRect).dumpDebug(proto, MOVEMENT_BOUNDS);
+ mLastReportedDefaultBounds.dumpDebug(proto, DEFAULT_BOUNDS);
+ mLastReportedMovementBounds.dumpDebug(proto, MOVEMENT_BOUNDS);
proto.end(token);
}
}
diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java
index 71bbb70956f5..a18d54198cf1 100644
--- a/services/core/java/com/android/server/wm/RecentTasks.java
+++ b/services/core/java/com/android/server/wm/RecentTasks.java
@@ -207,7 +207,7 @@ class RecentTasks {
mService.mH.post(PooledLambda.obtainRunnable((nonArg) -> {
synchronized (mService.mGlobalLock) {
// Unfreeze the task list once we touch down in a task
- final RootActivityContainer rac = mService.mRootActivityContainer;
+ final RootWindowContainer rac = mService.mRootWindowContainer;
final DisplayContent dc = rac.getDisplayContent(displayId).mDisplayContent;
if (dc.pointWithinAppWindow(x, y)) {
final ActivityStack stack = mService.getTopDisplayFocusedStack();
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index 0a8e7471af81..647be0f7038c 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -84,7 +84,7 @@ class RecentsAnimation implements RecentsAnimationCallbacks,
@Nullable WindowProcessController caller) {
mService = atm;
mStackSupervisor = stackSupervisor;
- mDefaultDisplay = mService.mRootActivityContainer.getDefaultDisplay();
+ mDefaultDisplay = mService.mRootWindowContainer.getDefaultDisplay();
mActivityStartController = activityStartController;
mWindowManager = wm;
mTargetIntent = targetIntent;
@@ -165,7 +165,7 @@ class RecentsAnimation implements RecentsAnimationCallbacks,
// TODO(multi-display) currently only support recents animation in default display.
final DisplayContent dc =
- mService.mRootActivityContainer.getDefaultDisplay().mDisplayContent;
+ mService.mRootWindowContainer.getDefaultDisplay().mDisplayContent;
if (!mWindowManager.canStartRecentsAnimation()) {
notifyAnimationCancelBeforeStart(recentsAnimationRunner);
ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS,
@@ -193,7 +193,7 @@ class RecentsAnimation implements RecentsAnimationCallbacks,
// Send launch hint if we are actually launching the target. If it's already visible
// (shouldn't happen in general) we don't need to send it.
if (targetActivity == null || !targetActivity.mVisibleRequested) {
- mService.mRootActivityContainer.sendPowerHintForLaunchStartIfNeeded(
+ mService.mRootWindowContainer.sendPowerHintForLaunchStartIfNeeded(
true /* forceSend */, targetActivity);
}
@@ -255,7 +255,7 @@ class RecentsAnimation implements RecentsAnimationCallbacks,
// If we updated the launch-behind state, update the visibility of the activities after
// we fetch the visible tasks to be controlled by the animation
- mService.mRootActivityContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
+ mService.mRootWindowContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
mStackSupervisor.getActivityMetricsLogger().notifyActivityLaunched(launchingState,
START_TASK_TO_FRONT, targetActivity);
@@ -288,7 +288,7 @@ class RecentsAnimation implements RecentsAnimationCallbacks,
// Just to be sure end the launch hint in case the target activity was never launched.
// However, if we're keeping the activity and making it visible, we can leave it on.
if (reorderMode != REORDER_KEEP_IN_PLACE) {
- mService.mRootActivityContainer.sendPowerHintForLaunchEndIfNeeded();
+ mService.mRootWindowContainer.sendPowerHintForLaunchEndIfNeeded();
}
// Once the target is shown, prevent spurious background app switches
@@ -381,8 +381,8 @@ class RecentsAnimation implements RecentsAnimationCallbacks,
}
mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
- mService.mRootActivityContainer.ensureActivitiesVisible(null, 0, false);
- mService.mRootActivityContainer.resumeFocusedStacksTopActivities();
+ mService.mRootWindowContainer.ensureActivitiesVisible(null, 0, false);
+ mService.mRootWindowContainer.resumeFocusedStacksTopActivities();
// No reason to wait for the pausing activity in this case, as the hiding of
// surfaces needs to be done immediately.
@@ -424,7 +424,7 @@ class RecentsAnimation implements RecentsAnimationCallbacks,
}
final DisplayContent dc =
- mService.mRootActivityContainer.getDefaultDisplay().mDisplayContent;
+ mService.mRootWindowContainer.getDefaultDisplay().mDisplayContent;
dc.mBoundsAnimationController.setAnimationType(
controller.shouldDeferCancelUntilNextTransition() ? FADE_IN : BOUNDS);
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 39091a6ac6e9..b255b5eb7c0e 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -754,8 +754,7 @@ public class RecentsAnimationController implements DeathRecipient {
// Only apply the input consumer if it is enabled, it is not the target (home/recents)
// being revealed with the transition, and we are actively animating the app as a part of
// the animation
- return mInputConsumerEnabled && mTargetActivityRecord != activity
- && isAnimatingApp(activity);
+ return mInputConsumerEnabled && !isTargetApp(activity) && isAnimatingApp(activity);
}
boolean updateInputConsumerForApp(InputWindowHandle inputWindowHandle,
@@ -810,7 +809,9 @@ public class RecentsAnimationController implements DeathRecipient {
PooledLambda.__(ActivityRecord.class));
boolean isAnimatingApp = task.forAllActivities(f);
f.recycle();
- return isAnimatingApp;
+ if (isAnimatingApp) {
+ return true;
+ }
}
return false;
}
diff --git a/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java b/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java
index d787cbc7cb6b..f78c82bc05c6 100644
--- a/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java
+++ b/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java
@@ -261,7 +261,7 @@ class ResetTargetTaskHelper {
DisplayContent display = mParent.getDisplay();
final boolean singleTaskInstanceDisplay = display.isSingleTaskInstance();
if (singleTaskInstanceDisplay) {
- display = mParent.mRootActivityContainer.getDefaultDisplay();
+ display = mParent.mRootWindowContainer.getDefaultDisplay();
}
final int windowingMode = mParent.getWindowingMode();
diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java
deleted file mode 100644
index 7dd9790403fc..000000000000
--- a/services/core/java/com/android/server/wm/RootActivityContainer.java
+++ /dev/null
@@ -1,2676 +0,0 @@
-/*
- * 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
- */
-
-package com.android.server.wm;
-
-import static android.app.ActivityTaskManager.INVALID_STACK_ID;
-import static android.app.ActivityTaskManager.INVALID_TASK_ID;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
-import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
-import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
-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.view.Display.DEFAULT_DISPLAY;
-import static android.view.Display.INVALID_DISPLAY;
-import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE;
-import static android.view.WindowManager.TRANSIT_SHOW_SINGLE_TASK_DISPLAY;
-
-import static com.android.server.am.ActivityStackSupervisorProto.CONFIGURATION_CONTAINER;
-import static com.android.server.am.ActivityStackSupervisorProto.DISPLAYS;
-import static com.android.server.am.ActivityStackSupervisorProto.FOCUSED_STACK_ID;
-import static com.android.server.am.ActivityStackSupervisorProto.IS_HOME_RECENTS_COMPONENT;
-import static com.android.server.am.ActivityStackSupervisorProto.KEYGUARD_CONTROLLER;
-import static com.android.server.am.ActivityStackSupervisorProto.PENDING_ACTIVITIES;
-import static com.android.server.am.ActivityStackSupervisorProto.RESUMED_ACTIVITY;
-import static com.android.server.wm.ActivityStack.ActivityState.PAUSED;
-import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
-import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;
-import static com.android.server.wm.ActivityStack.ActivityState.STOPPING;
-import static com.android.server.wm.ActivityStackSupervisor.DEFER_RESUME;
-import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
-import static com.android.server.wm.ActivityStackSupervisor.dumpHistoryList;
-import static com.android.server.wm.ActivityStackSupervisor.printThisActivity;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RECENTS;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STACK;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RECENTS;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RELEASE;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_STATES;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TASKS;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.wm.ActivityTaskManagerService.ANIMATE;
-import static com.android.server.wm.Task.REPARENT_LEAVE_STACK_IN_PLACE;
-import static com.android.server.wm.Task.REPARENT_MOVE_STACK_TO_FRONT;
-
-import static java.lang.Integer.MAX_VALUE;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.UserIdInt;
-import android.app.ActivityManager;
-import android.app.ActivityOptions;
-import android.app.AppGlobals;
-import android.app.WindowConfiguration;
-import android.content.ComponentName;
-import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.ResolveInfo;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.Rect;
-import android.hardware.display.DisplayManager;
-import android.hardware.display.DisplayManagerInternal;
-import android.hardware.power.V1_0.PowerHint;
-import android.net.Uri;
-import android.os.FactoryTest;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.os.UserHandle;
-import android.os.storage.StorageManager;
-import android.provider.Settings;
-import android.service.voice.IVoiceInteractionSession;
-import android.util.ArraySet;
-import android.util.DisplayMetrics;
-import android.util.IntArray;
-import android.util.Pair;
-import android.util.Slog;
-import android.util.SparseArray;
-import android.util.SparseIntArray;
-import android.util.TimeUtils;
-import android.util.proto.ProtoOutputStream;
-import android.view.Display;
-import android.view.DisplayInfo;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.app.ResolverActivity;
-import com.android.internal.util.function.pooled.PooledConsumer;
-import com.android.internal.util.function.pooled.PooledFunction;
-import com.android.internal.util.function.pooled.PooledLambda;
-import com.android.internal.util.function.pooled.PooledPredicate;
-import com.android.server.LocalServices;
-import com.android.server.am.ActivityManagerService;
-import com.android.server.am.AppTimeTracker;
-import com.android.server.am.UserState;
-import com.android.server.policy.WindowManagerPolicy;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
-import java.util.function.Function;
-
-/**
- * Root node for activity containers.
- * TODO: This class is mostly temporary to separate things out of ActivityStackSupervisor.java. The
- * intention is to have this merged with RootWindowContainer.java as part of unifying the hierarchy.
- */
-class RootActivityContainer extends ConfigurationContainer
- implements DisplayManager.DisplayListener {
-
- private static final String TAG = TAG_WITH_CLASS_NAME ? "RootActivityContainer" : TAG_ATM;
- static final String TAG_TASKS = TAG + POSTFIX_TASKS;
- private static final String TAG_RELEASE = TAG + POSTFIX_RELEASE;
- static final String TAG_STATES = TAG + POSTFIX_STATES;
- private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
-
- /**
- * The modes which affect which tasks are returned when calling
- * {@link RootActivityContainer#anyTaskForId(int)}.
- */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef({
- MATCH_TASK_IN_STACKS_ONLY,
- MATCH_TASK_IN_STACKS_OR_RECENT_TASKS,
- MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE
- })
- public @interface AnyTaskForIdMatchTaskMode {}
- // Match only tasks in the current stacks
- static final int MATCH_TASK_IN_STACKS_ONLY = 0;
- // Match either tasks in the current stacks, or in the recent tasks if not found in the stacks
- static final int MATCH_TASK_IN_STACKS_OR_RECENT_TASKS = 1;
- // Match either tasks in the current stacks, or in the recent tasks, restoring it to the
- // provided stack id
- static final int MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE = 2;
-
- ActivityTaskManagerService mService;
- ActivityStackSupervisor mStackSupervisor;
- WindowManagerService mWindowManager;
- DisplayManager mDisplayManager;
- private DisplayManagerInternal mDisplayManagerInternal;
- // TODO(root-unify): Remove after object merge with RootWindowContainer.
- RootWindowContainer mRootWindowContainer;
-
- /**
- * List of displays which contain activities, sorted by z-order.
- * The last entry in the list is the topmost.
- */
- private final ArrayList<DisplayContent> mDisplayContents = new ArrayList<>();
-
- /** Reference to default display so we can quickly look it up. */
- private DisplayContent mDefaultDisplay;
- private final SparseArray<IntArray> mDisplayAccessUIDs = new SparseArray<>();
-
- /** The current user */
- int mCurrentUser;
- /** Stack id of the front stack when user switched, indexed by userId. */
- SparseIntArray mUserStackInFront = new SparseIntArray(2);
-
- /**
- * A list of tokens that cause the top activity to be put to sleep.
- * They are used by components that may hide and block interaction with underlying
- * activities.
- */
- final ArrayList<ActivityTaskManagerInternal.SleepToken> mSleepTokens = new ArrayList<>();
-
- /** Is dock currently minimized. */
- boolean mIsDockMinimized;
-
- /** Set when a power hint has started, but not ended. */
- private boolean mPowerHintSent;
-
- /** Used to keep ensureActivitiesVisible() from being entered recursively. */
- private boolean mInEnsureActivitiesVisible = false;
-
- // The default minimal size that will be used if the activity doesn't specify its minimal size.
- // It will be calculated when the default display gets added.
- int mDefaultMinSizeOfResizeableTaskDp = -1;
-
- // Whether tasks have moved and we need to rank the tasks before next OOM scoring
- private boolean mTaskLayersChanged = true;
- private int mTmpTaskLayerRank;
-
- private boolean mTmpBoolean;
- private RemoteException mTmpRemoteException;
-
- private final FindTaskResult mTmpFindTaskResult = new FindTaskResult();
- static class FindTaskResult implements Function<Task, Boolean> {
- ActivityRecord mRecord;
- boolean mIdealMatch;
-
- private ActivityRecord mTarget;
- private Intent intent;
- private ActivityInfo info;
- private ComponentName cls;
- private int userId;
- private boolean isDocument;
- private Uri documentData;
-
- /**
- * Returns the top activity in any existing task matching the given Intent in the input
- * result. Returns null if no such task is found.
- */
- void process(ActivityRecord target, ActivityStack parent) {
- mTarget = target;
-
- intent = target.intent;
- info = target.info;
- cls = intent.getComponent();
- if (info.targetActivity != null) {
- cls = new ComponentName(info.packageName, info.targetActivity);
- }
- userId = UserHandle.getUserId(info.applicationInfo.uid);
- isDocument = intent != null & intent.isDocument();
- // If documentData is non-null then it must match the existing task data.
- documentData = isDocument ? intent.getData() : null;
-
- if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Looking for task of " + target + " in " + parent);
- parent.forAllTasks(this);
- }
-
- void clear() {
- mRecord = null;
- mIdealMatch = false;
- }
-
- void setTo(FindTaskResult result) {
- mRecord = result.mRecord;
- mIdealMatch = result.mIdealMatch;
- }
-
- @Override
- public Boolean apply(Task task) {
- if (task.voiceSession != null) {
- // We never match voice sessions; those always run independently.
- if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": voice session");
- return false;
- }
- if (task.mUserId != userId) {
- // Looking for a different task.
- if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": different user");
- return false;
- }
-
- // Overlays should not be considered as the task's logical top activity.
- final ActivityRecord r = task.getTopNonFinishingActivity(false /* includeOverlays */);
- if (r == null || r.finishing || r.mUserId != userId ||
- r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
- if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": mismatch root " + r);
- return false;
- }
- if (!r.hasCompatibleActivityType(mTarget)) {
- if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": mismatch activity type");
- return false;
- }
-
- final Intent taskIntent = task.intent;
- final Intent affinityIntent = task.affinityIntent;
- final boolean taskIsDocument;
- final Uri taskDocumentData;
- if (taskIntent != null && taskIntent.isDocument()) {
- taskIsDocument = true;
- taskDocumentData = taskIntent.getData();
- } else if (affinityIntent != null && affinityIntent.isDocument()) {
- taskIsDocument = true;
- taskDocumentData = affinityIntent.getData();
- } else {
- taskIsDocument = false;
- taskDocumentData = null;
- }
-
- if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Comparing existing cls="
- + (task.realActivity != null ? task.realActivity.flattenToShortString() : "")
- + "/aff=" + r.getTask().rootAffinity + " to new cls="
- + intent.getComponent().flattenToShortString() + "/aff=" + info.taskAffinity);
- // TODO Refactor to remove duplications. Check if logic can be simplified.
- if (task.realActivity != null && task.realActivity.compareTo(cls) == 0
- && Objects.equals(documentData, taskDocumentData)) {
- if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching class!");
- //dump();
- if (DEBUG_TASKS) Slog.d(TAG_TASKS,
- "For Intent " + intent + " bringing to top: " + r.intent);
- mRecord = r;
- mIdealMatch = true;
- return true;
- } else if (affinityIntent != null && affinityIntent.getComponent() != null &&
- affinityIntent.getComponent().compareTo(cls) == 0 &&
- Objects.equals(documentData, taskDocumentData)) {
- if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching class!");
- if (DEBUG_TASKS) Slog.d(TAG_TASKS,
- "For Intent " + intent + " bringing to top: " + r.intent);
- mRecord = r;
- mIdealMatch = true;
- return true;
- } else if (!isDocument && !taskIsDocument
- && mRecord == null && task.rootAffinity != null) {
- if (task.rootAffinity.equals(mTarget.taskAffinity)) {
- if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching affinity candidate!");
- // It is possible for multiple tasks to have the same root affinity especially
- // if they are in separate stacks. We save off this candidate, but keep looking
- // to see if there is a better candidate.
- mRecord = r;
- mIdealMatch = false;
- }
- } else if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Not a match: " + task);
-
- return false;
- }
- }
-
- RootActivityContainer(ActivityTaskManagerService service) {
- mService = service;
- mStackSupervisor = service.mStackSupervisor;
- mStackSupervisor.mRootActivityContainer = this;
- }
-
- void setWindowManager(WindowManagerService wm) {
- mWindowManager = wm;
- mRootWindowContainer = mWindowManager.mRoot;
- mRootWindowContainer.setRootActivityContainer(this);
- mDisplayManager = mService.mContext.getSystemService(DisplayManager.class);
- mDisplayManager.registerDisplayListener(this, mService.mUiHandler);
- mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
-
- final Display[] displays = mDisplayManager.getDisplays();
- for (int displayNdx = 0; displayNdx < displays.length; ++displayNdx) {
- final Display display = displays[displayNdx];
- final DisplayContent displayContent = new DisplayContent(display, this);
- if (displayContent.mDisplayId == DEFAULT_DISPLAY) {
- mDefaultDisplay = displayContent;
- }
- addChild(displayContent, DisplayContent.POSITION_TOP);
- }
- calculateDefaultMinimalSizeOfResizeableTasks();
-
- final DisplayContent defaultDisplay = getDefaultDisplay();
-
- defaultDisplay.getOrCreateStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
- positionChildAt(defaultDisplay, DisplayContent.POSITION_TOP);
- }
-
- // TODO(multi-display): Look at all callpoints to make sure they make sense in multi-display.
- DisplayContent getDefaultDisplay() {
- return mDefaultDisplay;
- }
-
- /**
- * Get an existing instance of {@link DisplayContent} that has the given uniqueId. Unique ID is
- * defined in {@link DisplayInfo#uniqueId}.
- *
- * @param uniqueId the unique ID of the display
- * @return the {@link DisplayContent} or {@code null} if nothing is found.
- */
- DisplayContent getDisplayContent(String uniqueId) {
- for (int i = mDisplayContents.size() - 1; i >= 0; --i) {
- final DisplayContent display = mDisplayContents.get(i);
- final boolean isValid = display.mDisplay.isValid();
- if (isValid && display.mDisplay.getUniqueId().equals(uniqueId)) {
- return display;
- }
- }
-
- return null;
- }
-
- // TODO: Look into consolidating with getDisplayContentOrCreate()
- DisplayContent getDisplayContent(int displayId) {
- for (int i = mDisplayContents.size() - 1; i >= 0; --i) {
- final DisplayContent displayContent = mDisplayContents.get(i);
- if (displayContent.mDisplayId == displayId) {
- return displayContent;
- }
- }
- return null;
- }
-
- /**
- * Get an existing instance of {@link DisplayContent} or create new if there is a
- * corresponding record in display manager.
- */
- // TODO: Look into consolidating with getDisplayContent()
- @Nullable DisplayContent getDisplayContentOrCreate(int displayId) {
- DisplayContent displayContent = getDisplayContent(displayId);
- if (displayContent != null) {
- return displayContent;
- }
- if (mDisplayManager == null) {
- // The system isn't fully initialized yet.
- return null;
- }
- final Display display = mDisplayManager.getDisplay(displayId);
- if (display == null) {
- // The display is not registered in DisplayManager.
- return null;
- }
- // The display hasn't been added to ActivityManager yet, create a new record now.
- displayContent = new DisplayContent(display, this);
- addChild(displayContent, DisplayContent.POSITION_BOTTOM);
- return displayContent;
- }
-
- ActivityRecord getDefaultDisplayHomeActivity() {
- return getDefaultDisplayHomeActivityForUser(mCurrentUser);
- }
-
- ActivityRecord getDefaultDisplayHomeActivityForUser(int userId) {
- return getDisplayContent(DEFAULT_DISPLAY).getHomeActivityForUser(userId);
- }
-
- boolean startHomeOnAllDisplays(int userId, String reason) {
- boolean homeStarted = false;
- for (int i = mDisplayContents.size() - 1; i >= 0; i--) {
- final int displayId = mDisplayContents.get(i).mDisplayId;
- homeStarted |= startHomeOnDisplay(userId, reason, displayId);
- }
- return homeStarted;
- }
-
- void startHomeOnEmptyDisplays(String reason) {
- for (int i = mDisplayContents.size() - 1; i >= 0; i--) {
- final DisplayContent display = mDisplayContents.get(i);
- if (display.topRunningActivity() == null) {
- startHomeOnDisplay(mCurrentUser, reason, display.mDisplayId);
- }
- }
- }
-
- boolean startHomeOnDisplay(int userId, String reason, int displayId) {
- return startHomeOnDisplay(userId, reason, displayId, false /* allowInstrumenting */,
- false /* fromHomeKey */);
- }
-
- /**
- * This starts home activity on displays that can have system decorations based on displayId -
- * Default display always use primary home component.
- * For Secondary displays, the home activity must have category SECONDARY_HOME and then resolves
- * according to the priorities listed below.
- * - If default home is not set, always use the secondary home defined in the config.
- * - Use currently selected primary home activity.
- * - Use the activity in the same package as currently selected primary home activity.
- * If there are multiple activities matched, use first one.
- * - Use the secondary home defined in the config.
- */
- boolean startHomeOnDisplay(int userId, String reason, int displayId, boolean allowInstrumenting,
- boolean fromHomeKey) {
- // Fallback to top focused display if the displayId is invalid.
- if (displayId == INVALID_DISPLAY) {
- final ActivityStack stack = getTopDisplayFocusedStack();
- displayId = stack != null ? stack.mDisplayId : DEFAULT_DISPLAY;
- }
-
- Intent homeIntent = null;
- ActivityInfo aInfo = null;
- if (displayId == DEFAULT_DISPLAY) {
- homeIntent = mService.getHomeIntent();
- aInfo = resolveHomeActivity(userId, homeIntent);
- } else if (shouldPlaceSecondaryHomeOnDisplay(displayId)) {
- Pair<ActivityInfo, Intent> info = resolveSecondaryHomeActivity(userId, displayId);
- aInfo = info.first;
- homeIntent = info.second;
- }
- if (aInfo == null || homeIntent == null) {
- return false;
- }
-
- if (!canStartHomeOnDisplay(aInfo, displayId, allowInstrumenting)) {
- return false;
- }
-
- // Updates the home component of the intent.
- homeIntent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
- homeIntent.setFlags(homeIntent.getFlags() | FLAG_ACTIVITY_NEW_TASK);
- // Updates the extra information of the intent.
- if (fromHomeKey) {
- homeIntent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, true);
- }
- // Update the reason for ANR debugging to verify if the user activity is the one that
- // actually launched.
- final String myReason = reason + ":" + userId + ":" + UserHandle.getUserId(
- aInfo.applicationInfo.uid) + ":" + displayId;
- mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason,
- displayId);
- return true;
- }
-
- /**
- * This resolves the home activity info.
- * @return the home activity info if any.
- */
- @VisibleForTesting
- ActivityInfo resolveHomeActivity(int userId, Intent homeIntent) {
- final int flags = ActivityManagerService.STOCK_PM_FLAGS;
- final ComponentName comp = homeIntent.getComponent();
- ActivityInfo aInfo = null;
- try {
- if (comp != null) {
- // Factory test.
- aInfo = AppGlobals.getPackageManager().getActivityInfo(comp, flags, userId);
- } else {
- final String resolvedType =
- homeIntent.resolveTypeIfNeeded(mService.mContext.getContentResolver());
- final ResolveInfo info = AppGlobals.getPackageManager()
- .resolveIntent(homeIntent, resolvedType, flags, userId);
- if (info != null) {
- aInfo = info.activityInfo;
- }
- }
- } catch (RemoteException e) {
- // ignore
- }
-
- if (aInfo == null) {
- Slog.wtf(TAG, "No home screen found for " + homeIntent, new Throwable());
- return null;
- }
-
- aInfo = new ActivityInfo(aInfo);
- aInfo.applicationInfo = mService.getAppInfoForUser(aInfo.applicationInfo, userId);
- return aInfo;
- }
-
- @VisibleForTesting
- Pair<ActivityInfo, Intent> resolveSecondaryHomeActivity(int userId, int displayId) {
- if (displayId == DEFAULT_DISPLAY) {
- throw new IllegalArgumentException(
- "resolveSecondaryHomeActivity: Should not be DEFAULT_DISPLAY");
- }
- // Resolve activities in the same package as currently selected primary home activity.
- Intent homeIntent = mService.getHomeIntent();
- ActivityInfo aInfo = resolveHomeActivity(userId, homeIntent);
- if (aInfo != null) {
- if (ResolverActivity.class.getName().equals(aInfo.name)) {
- // Always fallback to secondary home component if default home is not set.
- aInfo = null;
- } else {
- // Look for secondary home activities in the currently selected default home
- // package.
- homeIntent = mService.getSecondaryHomeIntent(aInfo.applicationInfo.packageName);
- final List<ResolveInfo> resolutions = resolveActivities(userId, homeIntent);
- final int size = resolutions.size();
- final String targetName = aInfo.name;
- aInfo = null;
- for (int i = 0; i < size; i++) {
- ResolveInfo resolveInfo = resolutions.get(i);
- // We need to traverse all resolutions to check if the currently selected
- // default home activity is present.
- if (resolveInfo.activityInfo.name.equals(targetName)) {
- aInfo = resolveInfo.activityInfo;
- break;
- }
- }
- if (aInfo == null && size > 0) {
- // First one is the best.
- aInfo = resolutions.get(0).activityInfo;
- }
- }
- }
-
- if (aInfo != null) {
- if (!canStartHomeOnDisplay(aInfo, displayId, false /* allowInstrumenting */)) {
- aInfo = null;
- }
- }
-
- // Fallback to secondary home component.
- if (aInfo == null) {
- homeIntent = mService.getSecondaryHomeIntent(null);
- aInfo = resolveHomeActivity(userId, homeIntent);
- }
- return Pair.create(aInfo, homeIntent);
- }
-
- /**
- * Retrieve all activities that match the given intent.
- * The list should already ordered from best to worst matched.
- * {@link android.content.pm.PackageManager#queryIntentActivities}
- */
- @VisibleForTesting
- List<ResolveInfo> resolveActivities(int userId, Intent homeIntent) {
- List<ResolveInfo> resolutions;
- try {
- final String resolvedType =
- homeIntent.resolveTypeIfNeeded(mService.mContext.getContentResolver());
- resolutions = AppGlobals.getPackageManager().queryIntentActivities(homeIntent,
- resolvedType, ActivityManagerService.STOCK_PM_FLAGS, userId).getList();
-
- } catch (RemoteException e) {
- resolutions = new ArrayList<>();
- }
- return resolutions;
- }
-
- boolean resumeHomeActivity(ActivityRecord prev, String reason, int displayId) {
- if (!mService.isBooting() && !mService.isBooted()) {
- // Not ready yet!
- return false;
- }
-
- if (displayId == INVALID_DISPLAY) {
- displayId = DEFAULT_DISPLAY;
- }
-
- final ActivityRecord r = getDisplayContent(displayId).getHomeActivity();
- final String myReason = reason + " resumeHomeActivity";
-
- // Only resume home activity if isn't finishing.
- if (r != null && !r.finishing) {
- r.moveFocusableActivityToTop(myReason);
- return resumeFocusedStacksTopActivities(r.getActivityStack(), prev, null);
- }
- return startHomeOnDisplay(mCurrentUser, myReason, displayId);
- }
-
- /**
- * Check if the display is valid for secondary home activity.
- * @param displayId The id of the target display.
- * @return {@code true} if allow to launch, {@code false} otherwise.
- */
- boolean shouldPlaceSecondaryHomeOnDisplay(int displayId) {
- if (displayId == DEFAULT_DISPLAY) {
- throw new IllegalArgumentException(
- "shouldPlaceSecondaryHomeOnDisplay: Should not be DEFAULT_DISPLAY");
- } else if (displayId == INVALID_DISPLAY) {
- return false;
- }
-
- if (!mService.mSupportsMultiDisplay) {
- // Can't launch home on secondary display if device does not support multi-display.
- return false;
- }
-
- final boolean deviceProvisioned = Settings.Global.getInt(
- mService.mContext.getContentResolver(),
- Settings.Global.DEVICE_PROVISIONED, 0) != 0;
- if (!deviceProvisioned) {
- // Can't launch home on secondary display before device is provisioned.
- return false;
- }
-
- if (!StorageManager.isUserKeyUnlocked(mCurrentUser)) {
- // Can't launch home on secondary displays if device is still locked.
- return false;
- }
-
- final DisplayContent display = getDisplayContent(displayId);
- if (display == null || display.isRemoved() || !display.supportsSystemDecorations()) {
- // Can't launch home on display that doesn't support system decorations.
- return false;
- }
-
- return true;
- }
-
- /**
- * Check if home activity start should be allowed on a display.
- * @param homeInfo {@code ActivityInfo} of the home activity that is going to be launched.
- * @param displayId The id of the target display.
- * @param allowInstrumenting Whether launching home should be allowed if being instrumented.
- * @return {@code true} if allow to launch, {@code false} otherwise.
- */
- boolean canStartHomeOnDisplay(ActivityInfo homeInfo, int displayId,
- boolean allowInstrumenting) {
- if (mService.mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
- && mService.mTopAction == null) {
- // We are running in factory test mode, but unable to find the factory test app, so
- // just sit around displaying the error message and don't try to start anything.
- return false;
- }
-
- final WindowProcessController app =
- mService.getProcessController(homeInfo.processName, homeInfo.applicationInfo.uid);
- if (!allowInstrumenting && app != null && app.isInstrumenting()) {
- // Don't do this if the home app is currently being instrumented.
- return false;
- }
-
- if (displayId == DEFAULT_DISPLAY || (displayId != INVALID_DISPLAY
- && displayId == mService.mVr2dDisplayId)) {
- // No restrictions to default display or vr 2d display.
- return true;
- }
-
- if (!shouldPlaceSecondaryHomeOnDisplay(displayId)) {
- return false;
- }
-
- final boolean supportMultipleInstance = homeInfo.launchMode != LAUNCH_SINGLE_TASK
- && homeInfo.launchMode != LAUNCH_SINGLE_INSTANCE;
- if (!supportMultipleInstance) {
- // Can't launch home on secondary displays if it requested to be single instance.
- return false;
- }
-
- return true;
- }
-
- /**
- * Ensure all activities visibility, update orientation and configuration.
- *
- * @param starting The currently starting activity or {@code null} if there is none.
- * @param displayId The id of the display where operation is executed.
- * @param markFrozenIfConfigChanged Whether to set {@link ActivityRecord#frozenBeforeDestroy} to
- * {@code true} if config changed.
- * @param deferResume Whether to defer resume while updating config.
- * @return 'true' if starting activity was kept or wasn't provided, 'false' if it was relaunched
- * because of configuration update.
- */
- boolean ensureVisibilityAndConfig(ActivityRecord starting, int displayId,
- boolean markFrozenIfConfigChanged, boolean deferResume) {
- // First ensure visibility without updating the config just yet. We need this to know what
- // activities are affecting configuration now.
- // Passing null here for 'starting' param value, so that visibility of actual starting
- // activity will be properly updated.
- ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
- false /* preserveWindows */, false /* notifyClients */);
-
- if (displayId == INVALID_DISPLAY) {
- // The caller didn't provide a valid display id, skip updating config.
- return true;
- }
-
- // Force-update the orientation from the WindowManager, since we need the true configuration
- // to send to the client now.
- final DisplayContent displayContent = mRootWindowContainer.getDisplayContent(displayId);
- Configuration config = null;
- if (displayContent != null) {
- config = displayContent.updateOrientation(
- getDisplayOverrideConfiguration(displayId),
- starting != null && starting.mayFreezeScreenLocked()
- ? starting.appToken : null,
- true /* forceUpdate */);
- }
- // Visibilities may change so let the starting activity have a chance to report. Can't do it
- // when visibility is changed in each AppWindowToken because it may trigger wrong
- // configuration push because the visibility of some activities may not be updated yet.
- if (starting != null) {
- starting.reportDescendantOrientationChangeIfNeeded();
- }
- if (starting != null && markFrozenIfConfigChanged && config != null) {
- starting.frozenBeforeDestroy = true;
- }
-
- if (displayContent != null) {
- // Update the configuration of the activities on the display.
- return displayContent.updateDisplayOverrideConfigurationLocked(config, starting,
- deferResume, null /* result */);
- } else {
- return true;
- }
- }
-
- /**
- * @return a list of activities which are the top ones in each visible stack. The first
- * entry will be the focused activity.
- */
- List<IBinder> getTopVisibleActivities() {
- final ArrayList<IBinder> topActivityTokens = new ArrayList<>();
- final ActivityStack topFocusedStack = getTopDisplayFocusedStack();
- // Traverse all displays.
- for (int i = mDisplayContents.size() - 1; i >= 0; i--) {
- final DisplayContent display = mDisplayContents.get(i);
- // Traverse all stacks on a display.
- for (int j = display.getStackCount() - 1; j >= 0; --j) {
- final ActivityStack stack = display.getStackAt(j);
- // Get top activity from a visible stack and add it to the list.
- if (stack.shouldBeVisible(null /* starting */)) {
- final ActivityRecord top = stack.getTopNonFinishingActivity();
- if (top != null) {
- if (stack == topFocusedStack) {
- topActivityTokens.add(0, top.appToken);
- } else {
- topActivityTokens.add(top.appToken);
- }
- }
- }
- }
- }
- return topActivityTokens;
- }
-
- ActivityStack getTopDisplayFocusedStack() {
- for (int i = mDisplayContents.size() - 1; i >= 0; --i) {
- final ActivityStack focusedStack = mDisplayContents.get(i).getFocusedStack();
- if (focusedStack != null) {
- return focusedStack;
- }
- }
- return null;
- }
-
- ActivityRecord getTopResumedActivity() {
- final ActivityStack focusedStack = getTopDisplayFocusedStack();
- if (focusedStack == null) {
- return null;
- }
- final ActivityRecord resumedActivity = focusedStack.getResumedActivity();
- if (resumedActivity != null && resumedActivity.app != null) {
- return resumedActivity;
- }
- // The top focused stack might not have a resumed activity yet - look on all displays in
- // focus order.
- for (int i = mDisplayContents.size() - 1; i >= 0; --i) {
- final DisplayContent display = mDisplayContents.get(i);
- final ActivityRecord resumedActivityOnDisplay = display.getResumedActivity();
- if (resumedActivityOnDisplay != null) {
- return resumedActivityOnDisplay;
- }
- }
- return null;
- }
-
- boolean isFocusable(ConfigurationContainer container, boolean alwaysFocusable) {
- if (container.inSplitScreenPrimaryWindowingMode() && mIsDockMinimized) {
- return false;
- }
-
- return container.getWindowConfiguration().canReceiveKeys() || alwaysFocusable;
- }
-
- boolean isTopDisplayFocusedStack(ActivityStack stack) {
- return stack != null && stack == getTopDisplayFocusedStack();
- }
-
- void updatePreviousProcess(ActivityRecord r) {
- // Now that this process has stopped, we may want to consider it to be the previous app to
- // try to keep around in case the user wants to return to it.
-
- // First, found out what is currently the foreground app, so that we don't blow away the
- // previous app if this activity is being hosted by the process that is actually still the
- // foreground.
- WindowProcessController fgApp = null;
- for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
- final DisplayContent display = mDisplayContents.get(displayNdx);
- for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getStackAt(stackNdx);
- if (isTopDisplayFocusedStack(stack)) {
- final ActivityRecord resumedActivity = stack.getResumedActivity();
- if (resumedActivity != null) {
- fgApp = resumedActivity.app;
- } else if (stack.mPausingActivity != null) {
- fgApp = stack.mPausingActivity.app;
- }
- break;
- }
- }
- }
-
- // Now set this one as the previous process, only if that really makes sense to.
- if (r.hasProcess() && fgApp != null && r.app != fgApp
- && r.lastVisibleTime > mService.mPreviousProcessVisibleTime
- && r.app != mService.mHomeProcess) {
- mService.mPreviousProcess = r.app;
- mService.mPreviousProcessVisibleTime = r.lastVisibleTime;
- }
- }
-
- boolean attachApplication(WindowProcessController app) throws RemoteException {
- final String processName = app.mName;
- boolean didSomething = false;
- for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
- final DisplayContent display = mDisplayContents.get(displayNdx);
- final ActivityStack stack = display.getFocusedStack();
- if (stack == null) {
- continue;
- }
-
- mTmpRemoteException = null;
- mTmpBoolean = false; // Set to true if an activity was started.
- final PooledFunction c = PooledLambda.obtainFunction(
- RootActivityContainer::startActivityForAttachedApplicationIfNeeded, this,
- PooledLambda.__(ActivityRecord.class), app, stack.topRunningActivity());
- stack.forAllActivities(c);
- c.recycle();
- if (mTmpRemoteException != null) {
- throw mTmpRemoteException;
- }
- didSomething |= mTmpBoolean;
- }
- if (!didSomething) {
- ensureActivitiesVisible(null, 0, false /* preserve_windows */);
- }
- return didSomething;
- }
-
- private boolean startActivityForAttachedApplicationIfNeeded(ActivityRecord r,
- WindowProcessController app, ActivityRecord top) {
- if (r.finishing || !r.okToShowLocked() || !r.visibleIgnoringKeyguard || r.app != null
- || app.mUid != r.info.applicationInfo.uid || !app.mName.equals(r.processName)) {
- return false;
- }
-
- try {
- if (mStackSupervisor.realStartActivityLocked(r, app, top == r /*andResume*/,
- true /*checkConfig*/)) {
- mTmpBoolean = true;
- }
- } catch (RemoteException e) {
- Slog.w(TAG, "Exception in new application when starting activity "
- + top.intent.getComponent().flattenToShortString(), e);
- mTmpRemoteException = e;
- return true;
- }
- return false;
- }
-
- /**
- * Make sure that all activities that need to be visible in the system actually are and update
- * their configuration.
- */
- void ensureActivitiesVisible(ActivityRecord starting, int configChanges,
- boolean preserveWindows) {
- ensureActivitiesVisible(starting, configChanges, preserveWindows, true /* notifyClients */);
- }
-
- /**
- * @see #ensureActivitiesVisible(ActivityRecord, int, boolean)
- */
- void ensureActivitiesVisible(ActivityRecord starting, int configChanges,
- boolean preserveWindows, boolean notifyClients) {
- if (mInEnsureActivitiesVisible) {
- // Don't do recursive work.
- return;
- }
- mInEnsureActivitiesVisible = true;
-
- try {
- mStackSupervisor.getKeyguardController().beginActivityVisibilityUpdate();
- // First the front stacks. In case any are not fullscreen and are in front of home.
- for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
- final DisplayContent display = mDisplayContents.get(displayNdx);
- display.ensureActivitiesVisible(starting, configChanges, preserveWindows,
- notifyClients);
- }
- } finally {
- mStackSupervisor.getKeyguardController().endActivityVisibilityUpdate();
- mInEnsureActivitiesVisible = false;
- }
- }
-
- boolean switchUser(int userId, UserState uss) {
- final int focusStackId = getTopDisplayFocusedStack().getStackId();
- // We dismiss the docked stack whenever we switch users.
- final ActivityStack dockedStack = getDefaultDisplay().getSplitScreenPrimaryStack();
- if (dockedStack != null) {
- mStackSupervisor.moveTasksToFullscreenStackLocked(
- dockedStack, dockedStack.isFocusedStackOnDisplay());
- }
- // Also dismiss the pinned stack whenever we switch users. Removing the pinned stack will
- // also cause all tasks to be moved to the fullscreen stack at a position that is
- // appropriate.
- removeStacksInWindowingModes(WINDOWING_MODE_PINNED);
-
- mUserStackInFront.put(mCurrentUser, focusStackId);
- final int restoreStackId =
- mUserStackInFront.get(userId, getDefaultDisplay().getHomeStack().mStackId);
- mCurrentUser = userId;
-
- mStackSupervisor.mStartingUsers.add(uss);
- for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
- final DisplayContent display = mDisplayContents.get(displayNdx);
- for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getStackAt(stackNdx);
- stack.switchUser(userId);
- Task task = stack.getTopMostTask();
- if (task != null) {
- stack.positionChildAtTop(task);
- }
- }
- }
-
- ActivityStack stack = getStack(restoreStackId);
- if (stack == null) {
- stack = getDefaultDisplay().getHomeStack();
- }
- final boolean homeInFront = stack.isActivityTypeHome();
- if (stack.isOnHomeDisplay()) {
- stack.moveToFront("switchUserOnHomeDisplay");
- } else {
- // Stack was moved to another display while user was swapped out.
- resumeHomeActivity(null, "switchUserOnOtherDisplay", DEFAULT_DISPLAY);
- }
- return homeInFront;
- }
-
- void removeUser(int userId) {
- mUserStackInFront.delete(userId);
- }
-
- /**
- * Update the last used stack id for non-current user (current user's last
- * used stack is the focused stack)
- */
- void updateUserStack(int userId, ActivityStack stack) {
- if (userId != mCurrentUser) {
- mUserStackInFront.put(userId, stack != null ? stack.getStackId()
- : getDefaultDisplay().getHomeStack().mStackId);
- }
- }
-
- /**
- * Move stack with all its existing content to specified display.
- * @param stackId Id of stack to move.
- * @param displayId Id of display to move stack to.
- * @param onTop Indicates whether container should be place on top or on bottom.
- */
- void moveStackToDisplay(int stackId, int displayId, boolean onTop) {
- final DisplayContent displayContent = getDisplayContentOrCreate(displayId);
- if (displayContent == null) {
- throw new IllegalArgumentException("moveStackToDisplay: Unknown displayId="
- + displayId);
- }
- final ActivityStack stack = getStack(stackId);
- if (stack == null) {
- throw new IllegalArgumentException("moveStackToDisplay: Unknown stackId="
- + stackId);
- }
-
- final DisplayContent currentDisplay = stack.getDisplay();
- if (currentDisplay == null) {
- throw new IllegalStateException("moveStackToDisplay: Stack with stack=" + stack
- + " is not attached to any display.");
- }
-
- if (currentDisplay.mDisplayId == displayId) {
- throw new IllegalArgumentException("Trying to move stack=" + stack
- + " to its current displayId=" + displayId);
- }
-
- if (displayContent.isSingleTaskInstance() && displayContent.getStackCount() > 0) {
- // We don't allow moving stacks to single instance display that already has a child.
- Slog.e(TAG, "Can not move stack=" + stack
- + " to single task instance display=" + displayContent);
- return;
- }
-
- stack.reparent(displayContent.mDisplayContent, onTop);
- // TODO(multi-display): resize stacks properly if moved from split-screen.
- }
-
- boolean moveTopStackActivityToPinnedStack(int stackId) {
- final ActivityStack stack = getStack(stackId);
- if (stack == null) {
- throw new IllegalArgumentException(
- "moveTopStackActivityToPinnedStack: Unknown stackId=" + stackId);
- }
-
- final ActivityRecord r = stack.topRunningActivity();
- if (r == null) {
- Slog.w(TAG, "moveTopStackActivityToPinnedStack: No top running activity"
- + " in stack=" + stack);
- return false;
- }
-
- if (!mService.mForceResizableActivities && !r.supportsPictureInPicture()) {
- Slog.w(TAG, "moveTopStackActivityToPinnedStack: Picture-In-Picture not supported for "
- + " r=" + r);
- return false;
- }
-
- moveActivityToPinnedStack(r, null /* sourceBounds */, 0f /* aspectRatio */,
- "moveTopActivityToPinnedStack");
- return true;
- }
-
- void moveActivityToPinnedStack(ActivityRecord r, Rect sourceHintBounds, float aspectRatio,
- String reason) {
- mService.deferWindowLayout();
-
- final DisplayContent display = r.getActivityStack().getDisplay();
-
- try {
- final Task task = r.getTask();
-
- final ActivityStack pinnedStack = display.getPinnedStack();
- // This will change the pinned stack's windowing mode to its original mode, ensuring
- // we only have one stack that is in pinned mode.
- if (pinnedStack != null) {
- pinnedStack.dismissPip();
- }
-
- final boolean singleActivity = task.getChildCount() == 1;
-
- final ActivityStack stack;
- if (singleActivity) {
- stack = r.getActivityStack();
- } else {
- // In the case of multiple activities, we will create a new stack for it and then
- // move the PIP activity into the stack.
- // We will then perform a windowing mode change for both scenarios.
- stack = display.createStack(
- r.getActivityStack().getRequestedOverrideWindowingMode(),
- r.getActivityType(), ON_TOP);
- // There are multiple activities in the task and moving the top activity should
- // reveal/leave the other activities in their original task.
-
- // Currently, we don't support reparenting activities across tasks in two different
- // stacks, so instead, just create a new task in the same stack, reparent the
- // activity into that task, and then reparent the whole task to the new stack. This
- // ensures that all the necessary work to migrate states in the old and new stacks
- // is also done.
- final Task newTask = task.getStack().createTask(
- mStackSupervisor.getNextTaskIdForUserLocked(r.mUserId), r.info,
- r.intent, null, null, true);
- r.reparent(newTask, MAX_VALUE, "moveActivityToStack");
-
- // Defer resume until below, and do not schedule PiP changes until we animate below
- newTask.reparent(stack, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT, !ANIMATE,
- DEFER_RESUME, false /* schedulePictureInPictureModeChange */, reason);
- }
-
- stack.setWindowingMode(WINDOWING_MODE_PINNED);
-
- // Reset the state that indicates it can enter PiP while pausing after we've moved it
- // to the pinned stack
- r.supportsEnterPipOnTaskSwitch = false;
- } finally {
- mService.continueWindowLayout();
- }
-
- // Notify the pinned stack controller to prepare the PiP animation, expect callback
- // delivered from SystemUI to WM to start the animation.
- final PinnedStackController pinnedStackController =
- display.mDisplayContent.getPinnedStackController();
- pinnedStackController.prepareAnimation(sourceHintBounds, aspectRatio,
- null /* stackBounds */);
-
- // TODO: revisit the following statement after the animation is moved from WM to SysUI.
- // Update the visibility of all activities after the they have been reparented to the new
- // stack. This MUST run after the animation above is scheduled to ensure that the windows
- // drawn signal is scheduled after the bounds animation start call on the bounds animator
- // thread.
- ensureActivitiesVisible(null, 0, false /* preserveWindows */);
- resumeFocusedStacksTopActivities();
-
- mService.getTaskChangeNotificationController().notifyActivityPinned(r);
- }
-
- void executeAppTransitionForAllDisplay() {
- for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
- final DisplayContent display = mDisplayContents.get(displayNdx);
- display.mDisplayContent.executeAppTransition();
- }
- }
-
- void setDockedStackMinimized(boolean minimized) {
- // Get currently focused stack before setting mIsDockMinimized. We do this because if
- // split-screen is active, primary stack will not be focusable (see #isFocusable) while
- // still occluding other stacks. This will cause getTopDisplayFocusedStack() to return null.
- final ActivityStack current = getTopDisplayFocusedStack();
- mIsDockMinimized = minimized;
- if (mIsDockMinimized) {
- if (current.inSplitScreenPrimaryWindowingMode()) {
- // The primary split-screen stack can't be focused while it is minimize, so move
- // focus to something else.
- current.adjustFocusToNextFocusableStack("setDockedStackMinimized");
- }
- }
- }
-
- ActivityRecord findTask(ActivityRecord r, int preferredDisplayId) {
- if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Looking for task of " + r);
- mTmpFindTaskResult.clear();
-
- // Looking up task on preferred display first
- final DisplayContent preferredDisplay = getDisplayContent(preferredDisplayId);
- if (preferredDisplay != null) {
- preferredDisplay.findTaskLocked(r, true /* isPreferredDisplay */, mTmpFindTaskResult);
- if (mTmpFindTaskResult.mIdealMatch) {
- return mTmpFindTaskResult.mRecord;
- }
- }
-
- for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
- final DisplayContent display = mDisplayContents.get(displayNdx);
- if (display.mDisplayId == preferredDisplayId) {
- continue;
- }
-
- display.findTaskLocked(r, false /* isPreferredDisplay */, mTmpFindTaskResult);
- if (mTmpFindTaskResult.mIdealMatch) {
- return mTmpFindTaskResult.mRecord;
- }
- }
-
- if (DEBUG_TASKS && mTmpFindTaskResult.mRecord == null) Slog.d(TAG_TASKS, "No task found");
- return mTmpFindTaskResult.mRecord;
- }
-
- /**
- * Finish the topmost activities in all stacks that belong to the crashed app.
- * @param app The app that crashed.
- * @param reason Reason to perform this action.
- * @return The task id that was finished in this stack, or INVALID_TASK_ID if none was finished.
- */
- int finishTopCrashedActivities(WindowProcessController app, String reason) {
- Task finishedTask = null;
- ActivityStack focusedStack = getTopDisplayFocusedStack();
- for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
- final DisplayContent display = mDisplayContents.get(displayNdx);
- // It is possible that request to finish activity might also remove its task and stack,
- // so we need to be careful with indexes in the loop and check child count every time.
- for (int stackNdx = 0; stackNdx < display.getStackCount(); ++stackNdx) {
- final ActivityStack stack = display.getStackAt(stackNdx);
- final Task t = stack.finishTopCrashedActivityLocked(app, reason);
- if (stack == focusedStack || finishedTask == null) {
- finishedTask = t;
- }
- }
- }
- return finishedTask != null ? finishedTask.mTaskId : INVALID_TASK_ID;
- }
-
- boolean resumeFocusedStacksTopActivities() {
- return resumeFocusedStacksTopActivities(null, null, null);
- }
-
- boolean resumeFocusedStacksTopActivities(
- ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
-
- if (!mStackSupervisor.readyToResume()) {
- return false;
- }
-
- boolean result = false;
- if (targetStack != null && (targetStack.isTopStackOnDisplay()
- || getTopDisplayFocusedStack() == targetStack)) {
- result = targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
- }
-
- for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
- boolean resumedOnDisplay = false;
- final DisplayContent display = mDisplayContents.get(displayNdx);
- for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getStackAt(stackNdx);
- final ActivityRecord topRunningActivity = stack.topRunningActivity();
- if (!stack.isFocusableAndVisible() || topRunningActivity == null) {
- continue;
- }
- if (stack == targetStack) {
- // Simply update the result for targetStack because the targetStack had
- // already resumed in above. We don't want to resume it again, especially in
- // some cases, it would cause a second launch failure if app process was dead.
- resumedOnDisplay |= result;
- continue;
- }
- if (display.isTopStack(stack) && topRunningActivity.isState(RESUMED)) {
- // Kick off any lingering app transitions form the MoveTaskToFront operation,
- // but only consider the top task and stack on that display.
- stack.executeAppTransition(targetOptions);
- } else {
- resumedOnDisplay |= topRunningActivity.makeActiveIfNeeded(target);
- }
- }
- if (!resumedOnDisplay) {
- // In cases when there are no valid activities (e.g. device just booted or launcher
- // crashed) it's possible that nothing was resumed on a display. Requesting resume
- // of top activity in focused stack explicitly will make sure that at least home
- // activity is started and resumed, and no recursion occurs.
- final ActivityStack focusedStack = display.getFocusedStack();
- if (focusedStack != null) {
- result |= focusedStack.resumeTopActivityUncheckedLocked(target, targetOptions);
- } else if (targetStack == null && display.getStackCount() == 0) {
- result |= resumeHomeActivity(null /* prev */, "empty-display",
- display.mDisplayId);
- }
- }
- }
-
- return result;
- }
-
- void applySleepTokens(boolean applyToStacks) {
- for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
- // Set the sleeping state of the display.
- final DisplayContent display = mDisplayContents.get(displayNdx);
- final boolean displayShouldSleep = display.shouldSleep();
- if (displayShouldSleep == display.isSleeping()) {
- continue;
- }
- display.setIsSleeping(displayShouldSleep);
-
- if (!applyToStacks) {
- continue;
- }
-
- // Set the sleeping state of the stacks on the display.
- for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getStackAt(stackNdx);
- if (displayShouldSleep) {
- stack.goToSleepIfPossible(false /* shuttingDown */);
- } else {
- // When the display which can only contain one task turns on, start a special
- // transition. {@link AppTransitionController#handleAppTransitionReady} later
- // picks up the transition, and schedules
- // {@link ITaskStackListener#onSingleTaskDisplayDrawn} callback which is
- // triggered after contents are drawn on the display.
- if (display.isSingleTaskInstance()) {
- display.mDisplayContent.prepareAppTransition(
- TRANSIT_SHOW_SINGLE_TASK_DISPLAY, false);
- }
- stack.awakeFromSleepingLocked();
- if (stack.isFocusedStackOnDisplay()
- && !mStackSupervisor.getKeyguardController()
- .isKeyguardOrAodShowing(display.mDisplayId)) {
- // If the keyguard is unlocked - resume immediately.
- // It is possible that the display will not be awake at the time we
- // process the keyguard going away, which can happen before the sleep token
- // is released. As a result, it is important we resume the activity here.
- resumeFocusedStacksTopActivities();
- }
- }
- }
-
- if (displayShouldSleep || mStackSupervisor.mGoingToSleepActivities.isEmpty()) {
- continue;
- }
- // The display is awake now, so clean up the going to sleep list.
- for (Iterator<ActivityRecord> it =
- mStackSupervisor.mGoingToSleepActivities.iterator(); it.hasNext(); ) {
- final ActivityRecord r = it.next();
- if (r.getDisplayId() == display.mDisplayId) {
- it.remove();
- }
- }
- }
- }
-
- protected ActivityStack getStack(int stackId) {
- for (int i = mDisplayContents.size() - 1; i >= 0; --i) {
- final ActivityStack stack = mDisplayContents.get(i).getStack(stackId);
- if (stack != null) {
- return stack;
- }
- }
- return null;
- }
-
- /** @see DisplayContent#getStack(int, int) */
- ActivityStack getStack(int windowingMode, int activityType) {
- for (int i = mDisplayContents.size() - 1; i >= 0; --i) {
- final ActivityStack stack =
- mDisplayContents.get(i).getStack(windowingMode, activityType);
- if (stack != null) {
- return stack;
- }
- }
- return null;
- }
-
- private ActivityStack getStack(int windowingMode, int activityType,
- int displayId) {
- DisplayContent display = getDisplayContent(displayId);
- if (display == null) {
- return null;
- }
- return display.getStack(windowingMode, activityType);
- }
-
- private ActivityManager.StackInfo getStackInfo(ActivityStack stack) {
- final int displayId = stack.mDisplayId;
- final DisplayContent display = getDisplayContent(displayId);
- ActivityManager.StackInfo info = new ActivityManager.StackInfo();
- stack.getBounds(info.bounds);
- info.displayId = displayId;
- info.stackId = stack.mStackId;
- info.stackToken = stack.mRemoteToken;
- info.userId = stack.mCurrentUser;
- info.visible = stack.shouldBeVisible(null);
- // A stack might be not attached to a display.
- info.position = display != null ? display.getIndexOf(stack) : 0;
- info.configuration.setTo(stack.getConfiguration());
-
- final int numTasks = stack.getChildCount();
- info.taskIds = new int[numTasks];
- info.taskNames = new String[numTasks];
- info.taskBounds = new Rect[numTasks];
- info.taskUserIds = new int[numTasks];
- final int[] currenIndex = {0};
-
- final PooledConsumer c = PooledLambda.obtainConsumer(
- RootActivityContainer::processTaskForStackInfo, PooledLambda.__(Task.class), info,
- currenIndex);
- stack.forAllTasks(c, false);
- c.recycle();
-
- final ActivityRecord top = stack.topRunningActivity();
- info.topActivity = top != null ? top.intent.getComponent() : null;
- return info;
- }
-
- private static void processTaskForStackInfo(
- Task task, ActivityManager.StackInfo info, int[] currentIndex) {
- int i = currentIndex[0];
- info.taskIds[i] = task.mTaskId;
- info.taskNames[i] = task.origActivity != null ? task.origActivity.flattenToString()
- : task.realActivity != null ? task.realActivity.flattenToString()
- : task.getTopNonFinishingActivity() != null
- ? task.getTopNonFinishingActivity().packageName : "unknown";
- info.taskBounds[i] = task.mAtmService.getTaskBounds(task.mTaskId);
- info.taskUserIds[i] = task.mUserId;
- currentIndex[0] = ++i;
- }
-
- ActivityManager.StackInfo getStackInfo(int stackId) {
- ActivityStack stack = getStack(stackId);
- if (stack != null) {
- return getStackInfo(stack);
- }
- return null;
- }
-
- ActivityManager.StackInfo getStackInfo(int windowingMode, int activityType) {
- final ActivityStack stack = getStack(windowingMode, activityType);
- return (stack != null) ? getStackInfo(stack) : null;
- }
-
- ActivityManager.StackInfo getStackInfo(int windowingMode, int activityType, int displayId) {
- final ActivityStack stack = getStack(windowingMode, activityType, displayId);
- return (stack != null) ? getStackInfo(stack) : null;
- }
-
- /** If displayId == INVALID_DISPLAY, this will get stack infos on all displays */
- ArrayList<ActivityManager.StackInfo> getAllStackInfos(int displayId) {
- ArrayList<ActivityManager.StackInfo> list = new ArrayList<>();
- if (displayId == INVALID_DISPLAY) {
- for (int displayNdx = 0; displayNdx < mDisplayContents.size(); ++displayNdx) {
- final DisplayContent display = mDisplayContents.get(displayNdx);
- for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getStackAt(stackNdx);
- list.add(getStackInfo(stack));
- }
- }
- return list;
- }
- final DisplayContent display = getDisplayContent(displayId);
- if (display == null) {
- return list;
- }
- for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getStackAt(stackNdx);
- list.add(getStackInfo(stack));
- }
- return list;
- }
-
- void deferUpdateBounds(int activityType) {
- final ActivityStack stack = getStack(WINDOWING_MODE_UNDEFINED, activityType);
- if (stack != null) {
- stack.deferUpdateBounds();
- }
- }
-
- void continueUpdateBounds(int activityType) {
- final ActivityStack stack = getStack(WINDOWING_MODE_UNDEFINED, activityType);
- if (stack != null) {
- stack.continueUpdateBounds();
- }
- }
-
- @Override
- public void onDisplayAdded(int displayId) {
- if (DEBUG_STACK) Slog.v(TAG, "Display added displayId=" + displayId);
- synchronized (mService.mGlobalLock) {
- final DisplayContent display = getDisplayContentOrCreate(displayId);
- if (display == null) {
- return;
- }
- // Do not start home before booting, or it may accidentally finish booting before it
- // starts. Instead, we expect home activities to be launched when the system is ready
- // (ActivityManagerService#systemReady).
- if (mService.isBooted() || mService.isBooting()) {
- startSystemDecorations(display.mDisplayContent);
- }
- }
- }
-
- private void startSystemDecorations(final DisplayContent displayContent) {
- startHomeOnDisplay(mCurrentUser, "displayAdded", displayContent.getDisplayId());
- displayContent.getDisplayPolicy().notifyDisplayReady();
- }
-
- @Override
- public void onDisplayRemoved(int displayId) {
- if (DEBUG_STACK) Slog.v(TAG, "Display removed displayId=" + displayId);
- if (displayId == DEFAULT_DISPLAY) {
- throw new IllegalArgumentException("Can't remove the primary display.");
- }
-
- synchronized (mService.mGlobalLock) {
- final DisplayContent displayContent = getDisplayContent(displayId);
- if (displayContent == null) {
- return;
- }
-
- displayContent.remove();
- }
- }
-
- @Override
- public void onDisplayChanged(int displayId) {
- if (DEBUG_STACK) Slog.v(TAG, "Display changed displayId=" + displayId);
- synchronized (mService.mGlobalLock) {
- final DisplayContent displayContent = getDisplayContent(displayId);
- if (displayContent != null) {
- displayContent.onDisplayChanged();
- }
- }
- }
-
- /** Update lists of UIDs that are present on displays and have access to them. */
- void updateUIDsPresentOnDisplay() {
- mDisplayAccessUIDs.clear();
- for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
- final DisplayContent displayContent = mDisplayContents.get(displayNdx);
- // Only bother calculating the whitelist for private displays
- if (displayContent.isPrivate()) {
- mDisplayAccessUIDs.append(
- displayContent.mDisplayId, displayContent.getPresentUIDs());
- }
- }
- // Store updated lists in DisplayManager. Callers from outside of AM should get them there.
- mDisplayManagerInternal.setDisplayAccessUIDs(mDisplayAccessUIDs);
- }
-
- ActivityStack findStackBehind(ActivityStack stack) {
- final DisplayContent display = getDisplayContent(stack.mDisplayId);
- if (display != null) {
- for (int i = display.getStackCount() - 1; i >= 0; i--) {
- if (display.getStackAt(i) == stack && i > 0) {
- return display.getStackAt(i - 1);
- }
- }
- }
- throw new IllegalStateException("Failed to find a stack behind stack=" + stack
- + " in=" + display);
- }
-
- @Override
- protected int getChildCount() {
- return mDisplayContents.size();
- }
-
- @Override
- protected DisplayContent getChildAt(int index) {
- return mDisplayContents.get(index);
- }
-
- @Override
- protected ConfigurationContainer getParent() {
- return null;
- }
-
- // TODO: remove after object merge with RootWindowContainer
- void onChildPositionChanged(DisplayContent display, int position) {
- // Assume AM lock is held from positionChildAt of controller in each hierarchy.
- if (display != null) {
- positionChildAt(display, position);
- }
- }
-
- /** Change the z-order of the given display. */
- private void positionChildAt(DisplayContent display, int position) {
- if (position >= mDisplayContents.size()) {
- position = mDisplayContents.size() - 1;
- } else if (position < 0) {
- position = 0;
- }
-
- if (mDisplayContents.isEmpty()) {
- mDisplayContents.add(display);
- } else if (mDisplayContents.get(position) != display) {
- mDisplayContents.remove(display);
- mDisplayContents.add(position, display);
- }
- mStackSupervisor.updateTopResumedActivityIfNeeded();
- }
-
- @VisibleForTesting
- void addChild(DisplayContent displayContent, int position) {
- positionChildAt(displayContent, position);
- mRootWindowContainer.positionChildAt(position, displayContent);
- }
-
- void removeChild(DisplayContent displayContent) {
- // The caller must tell the controller of {@link DisplayContent} to release its container
- // {@link DisplayContent}. That is done in {@link DisplayContent#releaseSelfIfNeeded}).
- mDisplayContents.remove(displayContent);
- }
-
- Configuration getDisplayOverrideConfiguration(int displayId) {
- final DisplayContent displayContent = getDisplayContentOrCreate(displayId);
- if (displayContent == null) {
- throw new IllegalArgumentException("No display found with id: " + displayId);
- }
-
- return displayContent.getRequestedOverrideConfiguration();
- }
-
- void setDisplayOverrideConfiguration(Configuration overrideConfiguration, int displayId) {
- final DisplayContent displayContent = getDisplayContentOrCreate(displayId);
- if (displayContent == null) {
- throw new IllegalArgumentException("No display found with id: " + displayId);
- }
-
- displayContent.onRequestedOverrideConfigurationChanged(overrideConfiguration);
- }
-
- void prepareForShutdown() {
- for (int i = 0; i < mDisplayContents.size(); i++) {
- createSleepToken("shutdown", mDisplayContents.get(i).mDisplayId);
- }
- }
-
- ActivityTaskManagerInternal.SleepToken createSleepToken(String tag, int displayId) {
- final DisplayContent display = getDisplayContent(displayId);
- if (display == null) {
- throw new IllegalArgumentException("Invalid display: " + displayId);
- }
-
- final SleepTokenImpl token = new SleepTokenImpl(tag, displayId);
- mSleepTokens.add(token);
- display.mAllSleepTokens.add(token);
- return token;
- }
-
- private void removeSleepToken(SleepTokenImpl token) {
- mSleepTokens.remove(token);
-
- final DisplayContent display = getDisplayContent(token.mDisplayId);
- if (display != null) {
- display.mAllSleepTokens.remove(token);
- if (display.mAllSleepTokens.isEmpty()) {
- mService.updateSleepIfNeededLocked();
- }
- }
- }
-
- void addStartingWindowsForVisibleActivities() {
- mRootWindowContainer.forAllActivities((r) -> {
- if (r.mVisibleRequested) {
- r.showStartingWindow(null /* prev */, false /* newTask */, true /*taskSwitch*/);
- }
- });
- }
-
- void invalidateTaskLayers() {
- mTaskLayersChanged = true;
- }
-
- void rankTaskLayersIfNeeded() {
- if (!mTaskLayersChanged || mRootWindowContainer == null) {
- return;
- }
- mTaskLayersChanged = false;
- mTmpTaskLayerRank = 0;
- final PooledConsumer c = PooledLambda.obtainConsumer(
- RootActivityContainer::rankTaskLayerForActivity, this,
- PooledLambda.__(ActivityRecord.class));
- mRootWindowContainer.forAllActivities(c);
- c.recycle();
- }
-
- private void rankTaskLayerForActivity(ActivityRecord r) {
- if (r.canBeTopRunning() && r.mVisibleRequested) {
- r.getTask().mLayerRank = ++mTmpTaskLayerRank;
- } else {
- r.getTask().mLayerRank = -1;
- }
- }
-
- void clearOtherAppTimeTrackers(AppTimeTracker except) {
- final PooledConsumer c = PooledLambda.obtainConsumer(
- RootActivityContainer::clearOtherAppTimeTrackers,
- PooledLambda.__(ActivityRecord.class), except);
- mRootWindowContainer.forAllActivities(c);
- c.recycle();
- }
-
- private static void clearOtherAppTimeTrackers(ActivityRecord r, AppTimeTracker except) {
- if ( r.appTimeTracker != except) {
- r.appTimeTracker = null;
- }
- }
-
- void scheduleDestroyAllActivities(WindowProcessController app, String reason) {
- for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
- final DisplayContent display = mDisplayContents.get(displayNdx);
- for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getStackAt(stackNdx);
- stack.scheduleDestroyActivities(app, reason);
- }
- }
- }
-
- // Tries to put all activity stacks to sleep. Returns true if all stacks were
- // successfully put to sleep.
- boolean putStacksToSleep(boolean allowDelay, boolean shuttingDown) {
- boolean allSleep = true;
- for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
- final DisplayContent display = mDisplayContents.get(displayNdx);
- for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
- // Stacks and activities could be removed while putting activities to sleep if
- // the app process was gone. This prevents us getting exception by accessing an
- // invalid stack index.
- if (stackNdx >= display.getStackCount()) {
- continue;
- }
-
- final ActivityStack stack = display.getStackAt(stackNdx);
- if (allowDelay) {
- allSleep &= stack.goToSleepIfPossible(shuttingDown);
- } else {
- stack.goToSleep();
- }
- }
- }
- return allSleep;
- }
-
- void handleAppCrash(WindowProcessController app) {
- final PooledConsumer c = PooledLambda.obtainConsumer(
- RootActivityContainer::handleAppCrash, PooledLambda.__(ActivityRecord.class), app);
- mRootWindowContainer.forAllActivities(c);
- c.recycle();
- }
-
- private static void handleAppCrash(ActivityRecord r, WindowProcessController app) {
- if (r.app != app) return;
- Slog.w(TAG, " Force finishing activity "
- + r.intent.getComponent().flattenToShortString());
- // Force the destroy to skip right to removal.
- r.app = null;
- r.getDisplay().mDisplayContent.prepareAppTransition(
- TRANSIT_CRASHING_ACTIVITY_CLOSE, false /* alwaysKeepCurrent */);
- r.destroyIfPossible("handleAppCrashed");
- }
-
- ActivityRecord findActivity(Intent intent, ActivityInfo info, boolean compareIntentFilters) {
- ComponentName cls = intent.getComponent();
- if (info.targetActivity != null) {
- cls = new ComponentName(info.packageName, info.targetActivity);
- }
- final int userId = UserHandle.getUserId(info.applicationInfo.uid);
-
- final PooledPredicate p = PooledLambda.obtainPredicate(
- RootActivityContainer::matchesActivity, PooledLambda.__(ActivityRecord.class),
- userId, compareIntentFilters, intent, cls);
- final ActivityRecord r = mRootWindowContainer.getActivity(p);
- p.recycle();
- return r;
- }
-
- private static boolean matchesActivity(ActivityRecord r, int userId,
- boolean compareIntentFilters, Intent intent, ComponentName cls) {
- if (!r.canBeTopRunning() || r.mUserId != userId) return false;
-
- if (compareIntentFilters) {
- if (r.intent.filterEquals(intent)) {
- return true;
- }
- } else {
- if (r.intent.getComponent().equals(cls)) {
- return true;
- }
- }
- return false;
- }
-
- boolean hasAwakeDisplay() {
- for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
- final DisplayContent display = mDisplayContents.get(displayNdx);
- if (!display.shouldSleep()) {
- return true;
- }
- }
- return false;
- }
-
- ActivityStack getLaunchStack(@Nullable ActivityRecord r,
- @Nullable ActivityOptions options, @Nullable Task candidateTask, boolean onTop) {
- return getLaunchStack(r, options, candidateTask, onTop, null /* launchParams */,
- -1 /* no realCallingPid */, -1 /* no realCallingUid */);
- }
-
- /**
- * Returns the right stack to use for launching factoring in all the input parameters.
- *
- * @param r The activity we are trying to launch. Can be null.
- * @param options The activity options used to the launch. Can be null.
- * @param candidateTask The possible task the activity might be launched in. Can be null.
- * @param launchParams The resolved launch params to use.
- * @param realCallingPid The pid from {@link ActivityStarter#setRealCallingPid}
- * @param realCallingUid The uid from {@link ActivityStarter#setRealCallingUid}
- *
- * @return The stack to use for the launch or INVALID_STACK_ID.
- */
- ActivityStack getLaunchStack(@Nullable ActivityRecord r,
- @Nullable ActivityOptions options, @Nullable Task candidateTask, boolean onTop,
- @Nullable LaunchParamsController.LaunchParams launchParams, int realCallingPid,
- int realCallingUid) {
- int taskId = INVALID_TASK_ID;
- int displayId = INVALID_DISPLAY;
- //Rect bounds = null;
-
- // We give preference to the launch preference in activity options.
- if (options != null) {
- taskId = options.getLaunchTaskId();
- displayId = options.getLaunchDisplayId();
- }
-
- // First preference for stack goes to the task Id set in the activity options. Use the stack
- // associated with that if possible.
- if (taskId != INVALID_TASK_ID) {
- // Temporarily set the task id to invalid in case in re-entry.
- options.setLaunchTaskId(INVALID_TASK_ID);
- final Task task = anyTaskForId(taskId,
- MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE, options, onTop);
- options.setLaunchTaskId(taskId);
- if (task != null) {
- return task.getStack();
- }
- }
-
- final int activityType = resolveActivityType(r, options, candidateTask);
- ActivityStack stack;
-
- // Next preference for stack goes to the display Id set the candidate display.
- if (launchParams != null && launchParams.mPreferredDisplayId != INVALID_DISPLAY) {
- displayId = launchParams.mPreferredDisplayId;
- }
- final boolean canLaunchOnDisplayFromStartRequest =
- realCallingPid != 0 && realCallingUid > 0 && r != null
- && mStackSupervisor.canPlaceEntityOnDisplay(displayId, realCallingPid,
- realCallingUid, r.info);
- // Checking if the activity's launch caller, or the realCallerId of the activity from
- // start request (i.e. entity that invokes PendingIntent) is allowed to launch on the
- // display.
- if (displayId != INVALID_DISPLAY && (canLaunchOnDisplay(r, displayId)
- || canLaunchOnDisplayFromStartRequest)) {
- if (r != null) {
- stack = getValidLaunchStackOnDisplay(displayId, r, candidateTask, options,
- launchParams);
- if (stack != null) {
- return stack;
- }
- }
- final DisplayContent display = getDisplayContentOrCreate(displayId);
- if (display != null) {
- stack = display.getOrCreateStack(r, options, candidateTask, activityType, onTop);
- if (stack != null) {
- return stack;
- }
- }
- }
-
- // Give preference to the stack and display of the input task and activity if they match the
- // mode we want to launch into.
- stack = null;
- DisplayContent display = null;
- if (candidateTask != null) {
- stack = candidateTask.getStack();
- }
- if (stack == null && r != null) {
- stack = r.getActivityStack();
- }
- if (stack != null) {
- display = stack.getDisplay();
- if (display != null && canLaunchOnDisplay(r, display.mDisplayId)) {
- int windowingMode = launchParams != null ? launchParams.mWindowingMode
- : WindowConfiguration.WINDOWING_MODE_UNDEFINED;
- if (windowingMode == WindowConfiguration.WINDOWING_MODE_UNDEFINED) {
- windowingMode = display.resolveWindowingMode(r, options, candidateTask,
- activityType);
- }
- if (stack.isCompatible(windowingMode, activityType)) {
- return stack;
- }
- if (windowingMode == WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY
- && display.getSplitScreenPrimaryStack() == stack
- && candidateTask == stack.getTopMostTask()) {
- // This is a special case when we try to launch an activity that is currently on
- // top of split-screen primary stack, but is targeting split-screen secondary.
- // In this case we don't want to move it to another stack.
- // TODO(b/78788972): Remove after differentiating between preferred and required
- // launch options.
- return stack;
- }
- }
- }
-
- if (display == null || !canLaunchOnDisplay(r, display.mDisplayId)) {
- display = getDefaultDisplay();
- }
-
- return display.getOrCreateStack(r, options, candidateTask, activityType, onTop);
- }
-
- /** @return true if activity record is null or can be launched on provided display. */
- private boolean canLaunchOnDisplay(ActivityRecord r, int displayId) {
- if (r == null) {
- return true;
- }
- return r.canBeLaunchedOnDisplay(displayId);
- }
-
- /**
- * Get a topmost stack on the display, that is a valid launch stack for specified activity.
- * If there is no such stack, new dynamic stack can be created.
- * @param displayId Target display.
- * @param r Activity that should be launched there.
- * @param candidateTask The possible task the activity might be put in.
- * @return Existing stack if there is a valid one, new dynamic stack if it is valid or null.
- */
- private ActivityStack getValidLaunchStackOnDisplay(int displayId, @NonNull ActivityRecord r,
- @Nullable Task candidateTask, @Nullable ActivityOptions options,
- @Nullable LaunchParamsController.LaunchParams launchParams) {
- final DisplayContent displayContent = getDisplayContentOrCreate(displayId);
- if (displayContent == null) {
- throw new IllegalArgumentException(
- "Display with displayId=" + displayId + " not found.");
- }
-
- if (!r.canBeLaunchedOnDisplay(displayId)) {
- return null;
- }
-
- // If {@code r} is already in target display and its task is the same as the candidate task,
- // the intention should be getting a launch stack for the reusable activity, so we can use
- // the existing stack.
- if (candidateTask != null && (r.getTask() == null || r.getTask() == candidateTask)) {
- final int attachedDisplayId = r.getDisplayId();
- if (attachedDisplayId == INVALID_DISPLAY || attachedDisplayId == displayId) {
- return candidateTask.getStack();
- }
- }
-
- int windowingMode;
- if (launchParams != null) {
- // When launch params is not null, we always defer to its windowing mode. Sometimes
- // it could be unspecified, which indicates it should inherit windowing mode from
- // display.
- windowingMode = launchParams.mWindowingMode;
- } else {
- windowingMode = options != null ? options.getLaunchWindowingMode()
- : r.getWindowingMode();
- }
- windowingMode = displayContent.validateWindowingMode(windowingMode, r, candidateTask,
- r.getActivityType());
-
- // Return the topmost valid stack on the display.
- for (int i = displayContent.getStackCount() - 1; i >= 0; --i) {
- final ActivityStack stack = displayContent.getStackAt(i);
- if (isValidLaunchStack(stack, r, windowingMode)) {
- return stack;
- }
- }
-
- // If there is no valid stack on the external display - check if new dynamic stack will do.
- if (displayId != DEFAULT_DISPLAY) {
- final int activityType =
- options != null && options.getLaunchActivityType() != ACTIVITY_TYPE_UNDEFINED
- ? options.getLaunchActivityType() : r.getActivityType();
- return displayContent.createStack(windowingMode, activityType, true /*onTop*/);
- }
-
- return null;
- }
-
- ActivityStack getValidLaunchStackOnDisplay(int displayId, @NonNull ActivityRecord r,
- @Nullable ActivityOptions options,
- @Nullable LaunchParamsController.LaunchParams launchParams) {
- return getValidLaunchStackOnDisplay(displayId, r, null /* candidateTask */, options,
- launchParams);
- }
-
- // TODO: Can probably be consolidated into getLaunchStack()...
- private boolean isValidLaunchStack(ActivityStack stack, ActivityRecord r, int windowingMode) {
- switch (stack.getActivityType()) {
- case ACTIVITY_TYPE_HOME: return r.isActivityTypeHome();
- case ACTIVITY_TYPE_RECENTS: return r.isActivityTypeRecents();
- case ACTIVITY_TYPE_ASSISTANT: return r.isActivityTypeAssistant();
- }
- // There is a 1-to-1 relationship between stack and task when not in
- // primary split-windowing mode.
- if (stack.getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
- && r.supportsSplitScreenWindowingMode()
- && (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
- || windowingMode == WINDOWING_MODE_UNDEFINED)) {
- return true;
- }
- return false;
- }
-
- int resolveActivityType(@Nullable ActivityRecord r, @Nullable ActivityOptions options,
- @Nullable Task task) {
- // Preference is given to the activity type for the activity then the task since the type
- // once set shouldn't change.
- int activityType = r != null ? r.getActivityType() : ACTIVITY_TYPE_UNDEFINED;
- if (activityType == ACTIVITY_TYPE_UNDEFINED && task != null) {
- activityType = task.getActivityType();
- }
- if (activityType != ACTIVITY_TYPE_UNDEFINED) {
- return activityType;
- }
- if (options != null) {
- activityType = options.getLaunchActivityType();
- }
- return activityType != ACTIVITY_TYPE_UNDEFINED ? activityType : ACTIVITY_TYPE_STANDARD;
- }
-
- /**
- * Get next focusable stack in the system. This will search through the stack on the same
- * display as the current focused stack, looking for a focusable and visible stack, different
- * from the target stack. If no valid candidates will be found, it will then go through all
- * displays and stacks in last-focused order.
- *
- * @param currentFocus The stack that previously had focus.
- * @param ignoreCurrent If we should ignore {@param currentFocus} when searching for next
- * candidate.
- * @return Next focusable {@link ActivityStack}, {@code null} if not found.
- */
- ActivityStack getNextFocusableStack(@NonNull ActivityStack currentFocus,
- boolean ignoreCurrent) {
- // First look for next focusable stack on the same display
- DisplayContent preferredDisplay = currentFocus.getDisplay();
- if (preferredDisplay == null) {
- // Stack is currently detached because it is being removed. Use the previous display it
- // was on.
- preferredDisplay = getDisplayContent(currentFocus.mPrevDisplayId);
- }
- final ActivityStack preferredFocusableStack = preferredDisplay.getNextFocusableStack(
- currentFocus, ignoreCurrent);
- if (preferredFocusableStack != null) {
- return preferredFocusableStack;
- }
- if (preferredDisplay.supportsSystemDecorations()) {
- // Stop looking for focusable stack on other displays because the preferred display
- // supports system decorations. Home activity would be launched on the same display if
- // no focusable stack found.
- return null;
- }
-
- // Now look through all displays
- for (int i = mDisplayContents.size() - 1; i >= 0; --i) {
- final DisplayContent display = mDisplayContents.get(i);
- if (display == preferredDisplay) {
- // We've already checked this one
- continue;
- }
- final ActivityStack nextFocusableStack = display.getNextFocusableStack(currentFocus,
- ignoreCurrent);
- if (nextFocusableStack != null) {
- return nextFocusableStack;
- }
- }
-
- return null;
- }
-
- /**
- * Get next valid stack for launching provided activity in the system. This will search across
- * displays and stacks in last-focused order for a focusable and visible stack, except those
- * that are on a currently focused display.
- *
- * @param r The activity that is being launched.
- * @param currentFocus The display that previously had focus and thus needs to be ignored when
- * searching for the next candidate.
- * @return Next valid {@link ActivityStack}, null if not found.
- */
- ActivityStack getNextValidLaunchStack(@NonNull ActivityRecord r, int currentFocus) {
- for (int i = mDisplayContents.size() - 1; i >= 0; --i) {
- final DisplayContent display = mDisplayContents.get(i);
- if (display.mDisplayId == currentFocus) {
- continue;
- }
- final ActivityStack stack = getValidLaunchStackOnDisplay(display.mDisplayId, r,
- null /* options */, null /* launchParams */);
- if (stack != null) {
- return stack;
- }
- }
- return null;
- }
-
- boolean handleAppDied(WindowProcessController app) {
- boolean hasVisibleActivities = false;
- for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
- final DisplayContent display = mDisplayContents.get(displayNdx);
- for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getStackAt(stackNdx);
- hasVisibleActivities |= stack.handleAppDiedLocked(app);
- }
- }
- return hasVisibleActivities;
- }
-
- void closeSystemDialogs() {
- mRootWindowContainer.forAllActivities((r) -> {
- if ((r.info.flags & ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
- r.finishIfPossible("close-sys", true /* oomAdj */);
- }
- });
- }
-
- FinishDisabledPackageActivitiesHelper mFinishDisabledPackageActivitiesHelper =
- new FinishDisabledPackageActivitiesHelper();
- class FinishDisabledPackageActivitiesHelper {
- private boolean mDidSomething;
- private String mPackageName;
- private Set<String> mFilterByClasses;
- private boolean mDoit;
- private boolean mEvenPersistent;
- private int mUserId;
- private Task mLastTask;
- private ComponentName mHomeActivity;
-
- private void reset(String packageName, Set<String> filterByClasses,
- boolean doit, boolean evenPersistent, int userId) {
- mDidSomething = false;
- mPackageName = packageName;
- mFilterByClasses = filterByClasses;
- mDoit = doit;
- mEvenPersistent = evenPersistent;
- mUserId = userId;
- mLastTask = null;
- mHomeActivity = null;
- }
-
- boolean process(String packageName, Set<String> filterByClasses,
- boolean doit, boolean evenPersistent, int userId) {
- reset(packageName, filterByClasses, doit, evenPersistent, userId);
-
- final PooledFunction f = PooledLambda.obtainFunction(
- FinishDisabledPackageActivitiesHelper::processActivity, this,
- PooledLambda.__(ActivityRecord.class));
- mRootWindowContainer.forAllActivities(f);
- f.recycle();
- return mDidSomething;
- }
-
- private boolean processActivity(ActivityRecord r) {
- final boolean sameComponent =
- (r.packageName.equals(mPackageName) && (mFilterByClasses == null
- || mFilterByClasses.contains(r.mActivityComponent.getClassName())))
- || (mPackageName == null && r.mUserId == mUserId);
- if ((mUserId == UserHandle.USER_ALL || r.mUserId == mUserId)
- && (sameComponent || r.getTask() == mLastTask)
- && (r.app == null || mEvenPersistent || !r.app.isPersistent())) {
- if (!mDoit) {
- if (r.finishing) {
- // If this activity is just finishing, then it is not
- // interesting as far as something to stop.
- return false;
- }
- return true;
- }
- if (r.isActivityTypeHome()) {
- if (mHomeActivity != null && mHomeActivity.equals(r.mActivityComponent)) {
- Slog.i(TAG, "Skip force-stop again " + r);
- return false;
- } else {
- mHomeActivity = r.mActivityComponent;
- }
- }
- mDidSomething = true;
- Slog.i(TAG, " Force finishing activity " + r);
- mLastTask = r.getTask();
- r.finishIfPossible("force-stop", true);
- }
-
- return false;
- }
- }
-
- /** @return true if some activity was finished (or would have finished if doit were true). */
- boolean finishDisabledPackageActivities(String packageName, Set<String> filterByClasses,
- boolean doit, boolean evenPersistent, int userId) {
- return mFinishDisabledPackageActivitiesHelper.process(packageName, filterByClasses, doit,
- evenPersistent, userId);
- }
-
- void updateActivityApplicationInfo(ApplicationInfo aInfo) {
- final String packageName = aInfo.packageName;
- final int userId = UserHandle.getUserId(aInfo.uid);
- final PooledConsumer c = PooledLambda.obtainConsumer(
- RootActivityContainer::updateActivityApplicationInfo,
- PooledLambda.__(ActivityRecord.class), aInfo, userId, packageName);
- mRootWindowContainer.forAllActivities(c);
- c.recycle();
- }
-
- private static void updateActivityApplicationInfo(
- ActivityRecord r, ApplicationInfo aInfo, int userId, String packageName) {
- if (r.mUserId == userId && packageName.equals(r.packageName)) {
- r.updateApplicationInfo(aInfo);
- }
- }
-
- void finishVoiceTask(IVoiceInteractionSession session) {
- for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
- final DisplayContent display = mDisplayContents.get(displayNdx);
- final int numStacks = display.getStackCount();
- for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
- final ActivityStack stack = display.getStackAt(stackNdx);
- stack.finishVoiceTask(session);
- }
- }
- }
-
- /**
- * Removes stacks in the input windowing modes from the system if they are of activity type
- * ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED
- */
- void removeStacksInWindowingModes(int... windowingModes) {
- for (int i = mDisplayContents.size() - 1; i >= 0; --i) {
- mDisplayContents.get(i).removeStacksInWindowingModes(windowingModes);
- }
- }
-
- void removeStacksWithActivityTypes(int... activityTypes) {
- for (int i = mDisplayContents.size() - 1; i >= 0; --i) {
- mDisplayContents.get(i).removeStacksWithActivityTypes(activityTypes);
- }
- }
-
- ActivityRecord topRunningActivity() {
- for (int i = mDisplayContents.size() - 1; i >= 0; --i) {
- final ActivityRecord topActivity = mDisplayContents.get(i).topRunningActivity();
- if (topActivity != null) {
- return topActivity;
- }
- }
- return null;
- }
-
- boolean allResumedActivitiesIdle() {
- for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
- // TODO(b/117135575): Check resumed activities on all visible stacks.
- final DisplayContent display = mDisplayContents.get(displayNdx);
- if (display.isSleeping()) {
- // No resumed activities while display is sleeping.
- continue;
- }
-
- // If the focused stack is not null or not empty, there should have some activities
- // resuming or resumed. Make sure these activities are idle.
- final ActivityStack stack = display.getFocusedStack();
- if (stack == null || !stack.hasActivity()) {
- continue;
- }
- final ActivityRecord resumedActivity = stack.getResumedActivity();
- if (resumedActivity == null || !resumedActivity.idle) {
- if (DEBUG_STATES) {
- Slog.d(TAG_STATES, "allResumedActivitiesIdle: stack="
- + stack.mStackId + " " + resumedActivity + " not idle");
- }
- return false;
- }
- }
- // Send launch end powerhint when idle
- sendPowerHintForLaunchEndIfNeeded();
- return true;
- }
-
- boolean allResumedActivitiesVisible() {
- boolean foundResumed = false;
- for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
- final DisplayContent display = mDisplayContents.get(displayNdx);
- for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getStackAt(stackNdx);
- final ActivityRecord r = stack.getResumedActivity();
- if (r != null) {
- if (!r.nowVisible) {
- return false;
- }
- foundResumed = true;
- }
- }
- }
- return foundResumed;
- }
-
- boolean allPausedActivitiesComplete() {
- boolean pausing = true;
- for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
- final DisplayContent display = mDisplayContents.get(displayNdx);
- for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getStackAt(stackNdx);
- final ActivityRecord r = stack.mPausingActivity;
- if (r != null && !r.isState(PAUSED, STOPPED, STOPPING)) {
- if (DEBUG_STATES) {
- Slog.d(TAG_STATES,
- "allPausedActivitiesComplete: r=" + r + " state=" + r.getState());
- pausing = false;
- } else {
- return false;
- }
- }
- }
- }
- return pausing;
- }
-
- /**
- * Find all visible task stacks containing {@param userId} and intercept them with an activity
- * to block out the contents and possibly start a credential-confirming intent.
- *
- * @param userId user handle for the locked managed profile.
- */
- void lockAllProfileTasks(@UserIdInt int userId) {
- mService.deferWindowLayout();
- try {
- final PooledConsumer c = PooledLambda.obtainConsumer(
- RootActivityContainer::taskTopActivityIsUser, this, PooledLambda.__(Task.class),
- userId);
- mRootWindowContainer.forAllTasks(c);
- c.recycle();
- } finally {
- mService.continueWindowLayout();
- }
- }
-
- /**
- * Detects whether we should show a lock screen in front of this task for a locked user.
- * <p>
- * We'll do this if either of the following holds:
- * <ul>
- * <li>The top activity explicitly belongs to {@param userId}.</li>
- * <li>The top activity returns a result to an activity belonging to {@param userId}.</li>
- * </ul>
- *
- * @return {@code true} if the top activity looks like it belongs to {@param userId}.
- */
- private void taskTopActivityIsUser(Task task, @UserIdInt int userId) {
- // To handle the case that work app is in the task but just is not the top one.
- final ActivityRecord activityRecord = task.getTopNonFinishingActivity();
- final ActivityRecord resultTo = (activityRecord != null ? activityRecord.resultTo : null);
-
- // Check the task for a top activity belonging to userId, or returning a
- // result to an activity belonging to userId. Example case: a document
- // picker for personal files, opened by a work app, should still get locked.
- if ((activityRecord != null && activityRecord.mUserId == userId)
- || (resultTo != null && resultTo.mUserId == userId)) {
- mService.getTaskChangeNotificationController().notifyTaskProfileLocked(
- task.mTaskId, userId);
- }
- }
-
- void cancelInitializingActivities() {
- for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
- final DisplayContent display = mDisplayContents.get(displayNdx);
- for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getStackAt(stackNdx);
- stack.cancelInitializingActivities();
- }
- }
- }
-
- Task anyTaskForId(int id) {
- return anyTaskForId(id, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE);
- }
-
- Task anyTaskForId(int id, @AnyTaskForIdMatchTaskMode int matchMode) {
- return anyTaskForId(id, matchMode, null, !ON_TOP);
- }
-
- /**
- * Returns a {@link Task} for the input id if available. {@code null} otherwise.
- * @param id Id of the task we would like returned.
- * @param matchMode The mode to match the given task id in.
- * @param aOptions The activity options to use for restoration. Can be null.
- * @param onTop If the stack for the task should be the topmost on the display.
- */
- Task anyTaskForId(int id, @AnyTaskForIdMatchTaskMode int matchMode,
- @Nullable ActivityOptions aOptions, boolean onTop) {
- // If options are set, ensure that we are attempting to actually restore a task
- if (matchMode != MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE && aOptions != null) {
- throw new IllegalArgumentException("Should not specify activity options for non-restore"
- + " lookup");
- }
-
- final PooledPredicate p = PooledLambda.obtainPredicate(
- Task::isTaskId, PooledLambda.__(Task.class), id);
- Task task = mRootWindowContainer.getTask(p);
- p.recycle();
-
- if (task != null) {
- if (aOptions != null) {
- // Resolve the stack the task should be placed in now based on options
- // and reparent if needed.
- final ActivityStack launchStack =
- getLaunchStack(null, aOptions, task, onTop);
- if (launchStack != null && task.getStack() != launchStack) {
- final int reparentMode = onTop
- ? REPARENT_MOVE_STACK_TO_FRONT : REPARENT_LEAVE_STACK_IN_PLACE;
- task.reparent(launchStack, onTop, reparentMode, ANIMATE, DEFER_RESUME,
- "anyTaskForId");
- }
- }
- return task;
- }
-
- // If we are matching stack tasks only, return now
- if (matchMode == MATCH_TASK_IN_STACKS_ONLY) {
- return null;
- }
-
- // Otherwise, check the recent tasks and return if we find it there and we are not restoring
- // the task from recents
- if (DEBUG_RECENTS) Slog.v(TAG_RECENTS, "Looking for task id=" + id + " in recents");
- task = mStackSupervisor.mRecentTasks.getTask(id);
-
- if (task == null) {
- if (DEBUG_RECENTS) {
- Slog.d(TAG_RECENTS, "\tDidn't find task id=" + id + " in recents");
- }
-
- return null;
- }
-
- if (matchMode == MATCH_TASK_IN_STACKS_OR_RECENT_TASKS) {
- return task;
- }
-
- // Implicitly, this case is MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE
- if (!mStackSupervisor.restoreRecentTaskLocked(task, aOptions, onTop)) {
- if (DEBUG_RECENTS) Slog.w(TAG_RECENTS,
- "Couldn't restore task id=" + id + " found in recents");
- return null;
- }
- if (DEBUG_RECENTS) Slog.w(TAG_RECENTS, "Restored task id=" + id + " from in recents");
- return task;
- }
-
- ActivityRecord isInAnyStack(IBinder token) {
- int numDisplays = mDisplayContents.size();
- for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
- final DisplayContent display = mDisplayContents.get(displayNdx);
- for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getStackAt(stackNdx);
- final ActivityRecord r = stack.isInStackLocked(token);
- if (r != null) {
- return r;
- }
- }
- }
- return null;
- }
-
- @VisibleForTesting
- void getRunningTasks(int maxNum, List<ActivityManager.RunningTaskInfo> list,
- @WindowConfiguration.ActivityType int ignoreActivityType,
- @WindowConfiguration.WindowingMode int ignoreWindowingMode, int callingUid,
- boolean allowed, boolean crossUser, ArraySet<Integer> profileIds) {
- mStackSupervisor.getRunningTasks().getTasks(maxNum, list, ignoreActivityType,
- ignoreWindowingMode, this, callingUid, allowed, crossUser, profileIds);
- }
-
- void sendPowerHintForLaunchStartIfNeeded(boolean forceSend, ActivityRecord targetActivity) {
- boolean sendHint = forceSend;
-
- if (!sendHint) {
- // Send power hint if we don't know what we're launching yet
- sendHint = targetActivity == null || targetActivity.app == null;
- }
-
- if (!sendHint) { // targetActivity != null
- // Send power hint when the activity's process is different than the current resumed
- // activity on all displays, or if there are no resumed activities in the system.
- boolean noResumedActivities = true;
- boolean allFocusedProcessesDiffer = true;
- for (int displayNdx = 0; displayNdx < mDisplayContents.size(); ++displayNdx) {
- final DisplayContent displayContent = mDisplayContents.get(displayNdx);
- final ActivityRecord resumedActivity = displayContent.getResumedActivity();
- final WindowProcessController resumedActivityProcess =
- resumedActivity == null ? null : resumedActivity.app;
-
- noResumedActivities &= resumedActivityProcess == null;
- if (resumedActivityProcess != null) {
- allFocusedProcessesDiffer &= !resumedActivityProcess.equals(targetActivity.app);
- }
- }
- sendHint = noResumedActivities || allFocusedProcessesDiffer;
- }
-
- if (sendHint && mService.mPowerManagerInternal != null) {
- mService.mPowerManagerInternal.powerHint(PowerHint.LAUNCH, 1);
- mPowerHintSent = true;
- }
- }
-
- void sendPowerHintForLaunchEndIfNeeded() {
- // Trigger launch power hint if activity is launched
- if (mPowerHintSent && mService.mPowerManagerInternal != null) {
- mService.mPowerManagerInternal.powerHint(PowerHint.LAUNCH, 0);
- mPowerHintSent = false;
- }
- }
-
- private void calculateDefaultMinimalSizeOfResizeableTasks() {
- final Resources res = mService.mContext.getResources();
- final float minimalSize = res.getDimension(
- com.android.internal.R.dimen.default_minimal_size_resizable_task);
- final DisplayMetrics dm = res.getDisplayMetrics();
-
- mDefaultMinSizeOfResizeableTaskDp = (int) (minimalSize / dm.density);
- }
-
- /**
- * Dumps the activities matching the given {@param name} in the either the focused stack
- * or all visible stacks if {@param dumpVisibleStacks} is true.
- */
- ArrayList<ActivityRecord> getDumpActivities(String name, boolean dumpVisibleStacksOnly,
- boolean dumpFocusedStackOnly) {
- if (dumpFocusedStackOnly) {
- return getTopDisplayFocusedStack().getDumpActivitiesLocked(name);
- } else {
- ArrayList<ActivityRecord> activities = new ArrayList<>();
- int numDisplays = mDisplayContents.size();
- for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
- final DisplayContent display = mDisplayContents.get(displayNdx);
- for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getStackAt(stackNdx);
- if (!dumpVisibleStacksOnly || stack.shouldBeVisible(null)) {
- activities.addAll(stack.getDumpActivitiesLocked(name));
- }
- }
- }
- return activities;
- }
- }
-
- public void dump(PrintWriter pw, String prefix) {
- pw.print(prefix);
- pw.println("topDisplayFocusedStack=" + getTopDisplayFocusedStack());
- for (int i = mDisplayContents.size() - 1; i >= 0; --i) {
- final DisplayContent display = mDisplayContents.get(i);
- display.dump(pw, prefix, true /* dumpAll */);
- }
- }
-
- /**
- * Dump all connected displays' configurations.
- * @param prefix Prefix to apply to each line of the dump.
- */
- void dumpDisplayConfigs(PrintWriter pw, String prefix) {
- pw.print(prefix); pw.println("Display override configurations:");
- final int displayCount = mDisplayContents.size();
- for (int i = 0; i < displayCount; i++) {
- final DisplayContent displayContent = mDisplayContents.get(i);
- pw.print(prefix); pw.print(" "); pw.print(displayContent.mDisplayId); pw.print(": ");
- pw.println(displayContent.getRequestedOverrideConfiguration());
- }
- }
-
- public void dumpDisplays(PrintWriter pw) {
- for (int i = mDisplayContents.size() - 1; i >= 0; --i) {
- final DisplayContent display = mDisplayContents.get(i);
- pw.print("[id:" + display.mDisplayId + " stacks:");
- display.dumpStacks(pw);
- pw.print("]");
- }
- }
-
- boolean dumpActivities(FileDescriptor fd, PrintWriter pw, boolean dumpAll, boolean dumpClient,
- String dumpPackage) {
- boolean printed = false;
- boolean needSep = false;
- for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
- DisplayContent displayContent = mDisplayContents.get(displayNdx);
- pw.print("Display #"); pw.print(displayContent.mDisplayId);
- pw.println(" (activities from top to bottom):");
- final DisplayContent display = mDisplayContents.get(displayNdx);
- for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getStackAt(stackNdx);
- pw.println();
- printed = stack.dump(fd, pw, dumpAll, dumpClient, dumpPackage, needSep);
- needSep = printed;
- }
- printThisActivity(pw, displayContent.getResumedActivity(), dumpPackage, needSep,
- " ResumedActivity:");
- }
-
- printed |= dumpHistoryList(fd, pw, mStackSupervisor.mFinishingActivities, " ",
- "Fin", false, !dumpAll,
- false, dumpPackage, true, " Activities waiting to finish:", null);
- printed |= dumpHistoryList(fd, pw, mStackSupervisor.mStoppingActivities, " ",
- "Stop", false, !dumpAll,
- false, dumpPackage, true, " Activities waiting to stop:", null);
- printed |= dumpHistoryList(fd, pw, mStackSupervisor.mGoingToSleepActivities,
- " ", "Sleep", false, !dumpAll,
- false, dumpPackage, true, " Activities waiting to sleep:", null);
-
- return printed;
- }
-
- protected void dumpDebug(ProtoOutputStream proto, long fieldId,
- @WindowTraceLogLevel int logLevel) {
- final long token = proto.start(fieldId);
- super.dumpDebug(proto, CONFIGURATION_CONTAINER, logLevel);
- for (int displayNdx = 0; displayNdx < mDisplayContents.size(); ++displayNdx) {
- final DisplayContent displayContent = mDisplayContents.get(displayNdx);
- displayContent.dumpDebug(proto, DISPLAYS, logLevel);
- }
- mStackSupervisor.getKeyguardController().dumpDebug(proto, KEYGUARD_CONTROLLER);
- // TODO(b/111541062): Update tests to look for resumed activities on all displays
- final ActivityStack focusedStack = getTopDisplayFocusedStack();
- if (focusedStack != null) {
- proto.write(FOCUSED_STACK_ID, focusedStack.mStackId);
- final ActivityRecord focusedActivity = focusedStack.getDisplay().getResumedActivity();
- if (focusedActivity != null) {
- focusedActivity.writeIdentifierToProto(proto, RESUMED_ACTIVITY);
- }
- } else {
- proto.write(FOCUSED_STACK_ID, INVALID_STACK_ID);
- }
- proto.write(IS_HOME_RECENTS_COMPONENT,
- mStackSupervisor.mRecentTasks.isRecentsComponentHomeActivity(mCurrentUser));
- mService.getActivityStartController().dumpDebug(proto, PENDING_ACTIVITIES);
- proto.end(token);
- }
-
- private final class SleepTokenImpl extends ActivityTaskManagerInternal.SleepToken {
- private final String mTag;
- private final long mAcquireTime;
- private final int mDisplayId;
-
- public SleepTokenImpl(String tag, int displayId) {
- mTag = tag;
- mDisplayId = displayId;
- mAcquireTime = SystemClock.uptimeMillis();
- }
-
- @Override
- public void release() {
- synchronized (mService.mGlobalLock) {
- removeSleepToken(this);
- }
- }
-
- @Override
- public String toString() {
- return "{\"" + mTag + "\", display " + mDisplayId
- + ", acquire at " + TimeUtils.formatUptime(mAcquireTime) + "}";
- }
- }
-}
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 361bbe44019b..547032795204 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -16,19 +16,59 @@
package com.android.server.wm;
+import static android.app.ActivityTaskManager.INVALID_STACK_ID;
+import static android.app.ActivityTaskManager.INVALID_TASK_ID;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+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.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
-import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
-
+import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE;
+import static android.view.WindowManager.TRANSIT_SHOW_SINGLE_TASK_DISPLAY;
+
+import static com.android.server.am.ActivityStackSupervisorProto.FOCUSED_STACK_ID;
+import static com.android.server.am.ActivityStackSupervisorProto.IS_HOME_RECENTS_COMPONENT;
+import static com.android.server.am.ActivityStackSupervisorProto.KEYGUARD_CONTROLLER;
+import static com.android.server.am.ActivityStackSupervisorProto.PENDING_ACTIVITIES;
+import static com.android.server.am.ActivityStackSupervisorProto.RESUMED_ACTIVITY;
+import static com.android.server.am.ActivityStackSupervisorProto.ROOT_WINDOW_CONTAINER;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+import static com.android.server.wm.ActivityStack.ActivityState.PAUSED;
+import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
+import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;
+import static com.android.server.wm.ActivityStack.ActivityState.STOPPING;
+import static com.android.server.wm.ActivityStackSupervisor.DEFER_RESUME;
+import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
+import static com.android.server.wm.ActivityStackSupervisor.dumpHistoryList;
+import static com.android.server.wm.ActivityStackSupervisor.printThisActivity;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RECENTS;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STACK;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RECENTS;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RELEASE;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_STATES;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TASKS;
+import static com.android.server.wm.ActivityTaskManagerService.ANIMATE;
+import static com.android.server.wm.ActivityTaskManagerService.TAG_SWITCH;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_KEEP_SCREEN_ON;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
@@ -37,6 +77,8 @@ import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
import static com.android.server.wm.RootWindowContainerProto.DISPLAYS;
import static com.android.server.wm.RootWindowContainerProto.WINDOWS;
import static com.android.server.wm.RootWindowContainerProto.WINDOW_CONTAINER;
+import static com.android.server.wm.Task.REPARENT_LEAVE_STACK_IN_PLACE;
+import static com.android.server.wm.Task.REPARENT_MOVE_STACK_TO_FRONT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE;
@@ -52,45 +94,95 @@ import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_C
import static com.android.server.wm.WindowSurfacePlacer.SET_UPDATE_ROTATION;
import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_ACTION_PENDING;
-import android.annotation.CallSuper;
+import static java.lang.Integer.MAX_VALUE;
+
+import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.app.ActivityManager;
+import android.app.ActivityOptions;
+import android.app.AppGlobals;
+import android.app.WindowConfiguration;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.Rect;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManagerInternal;
import android.hardware.power.V1_0.PowerHint;
+import android.net.Uri;
import android.os.Binder;
import android.os.Debug;
+import android.os.FactoryTest;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.os.Trace;
import android.os.UserHandle;
+import android.os.storage.StorageManager;
+import android.provider.Settings;
+import android.service.voice.IVoiceInteractionSession;
import android.util.ArraySet;
+import android.util.DisplayMetrics;
+import android.util.IntArray;
+import android.util.Pair;
import android.util.Slog;
+import android.util.SparseArray;
import android.util.SparseIntArray;
+import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
+import android.view.Display;
import android.view.DisplayInfo;
import android.view.SurfaceControl;
import android.view.WindowManager;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.app.ResolverActivity;
+import com.android.internal.util.function.pooled.PooledConsumer;
+import com.android.internal.util.function.pooled.PooledFunction;
+import com.android.internal.util.function.pooled.PooledLambda;
+import com.android.internal.util.function.pooled.PooledPredicate;
+import com.android.server.LocalServices;
+import com.android.server.am.ActivityManagerService;
+import com.android.server.am.AppTimeTracker;
+import com.android.server.am.UserState;
+import com.android.server.policy.WindowManagerPolicy;
import com.android.server.protolog.common.ProtoLog;
+import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
import java.util.function.Consumer;
+import java.util.function.Function;
/** Root {@link WindowContainer} for the device. */
class RootWindowContainer extends WindowContainer<DisplayContent>
- implements ConfigurationContainerListener {
+ implements DisplayManager.DisplayListener {
private static final String TAG = TAG_WITH_CLASS_NAME ? "RootWindowContainer" : TAG_WM;
private static final int SET_SCREEN_BRIGHTNESS_OVERRIDE = 1;
private static final int SET_USER_ACTIVITY_TIMEOUT = 2;
-
- // TODO: Remove after object merge with RootActivityContainer.
- private RootActivityContainer mRootActivityContainer;
+ static final String TAG_TASKS = TAG + POSTFIX_TASKS;
+ private static final String TAG_RELEASE = TAG + POSTFIX_RELEASE;
+ static final String TAG_STATES = TAG + POSTFIX_STATES;
+ private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
private Object mLastWindowFreezeSource = null;
private Session mHoldScreen = null;
@@ -131,6 +223,213 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
// transaction from the global transaction.
private final SurfaceControl.Transaction mDisplayTransaction;
+ /**
+ * The modes which affect which tasks are returned when calling
+ * {@link RootWindowContainer#anyTaskForId(int)}.
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ MATCH_TASK_IN_STACKS_ONLY,
+ MATCH_TASK_IN_STACKS_OR_RECENT_TASKS,
+ MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE
+ })
+ public @interface AnyTaskForIdMatchTaskMode {}
+ // Match only tasks in the current stacks
+ static final int MATCH_TASK_IN_STACKS_ONLY = 0;
+ // Match either tasks in the current stacks, or in the recent tasks if not found in the stacks
+ static final int MATCH_TASK_IN_STACKS_OR_RECENT_TASKS = 1;
+ // Match either tasks in the current stacks, or in the recent tasks, restoring it to the
+ // provided stack id
+ static final int MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE = 2;
+
+ ActivityTaskManagerService mService;
+ ActivityStackSupervisor mStackSupervisor;
+ WindowManagerService mWindowManager;
+ DisplayManager mDisplayManager;
+ private DisplayManagerInternal mDisplayManagerInternal;
+
+ /** Reference to default display so we can quickly look it up. */
+ private DisplayContent mDefaultDisplay;
+ private final SparseArray<IntArray> mDisplayAccessUIDs = new SparseArray<>();
+
+ /** The current user */
+ int mCurrentUser;
+ /** Stack id of the front stack when user switched, indexed by userId. */
+ SparseIntArray mUserStackInFront = new SparseIntArray(2);
+
+ /**
+ * A list of tokens that cause the top activity to be put to sleep.
+ * They are used by components that may hide and block interaction with underlying
+ * activities.
+ */
+ final ArrayList<ActivityTaskManagerInternal.SleepToken> mSleepTokens = new ArrayList<>();
+
+ /** Is dock currently minimized. */
+ boolean mIsDockMinimized;
+
+ /** Set when a power hint has started, but not ended. */
+ private boolean mPowerHintSent;
+
+ /** Used to keep ensureActivitiesVisible() from being entered recursively. */
+ private boolean mInEnsureActivitiesVisible = false;
+
+ // The default minimal size that will be used if the activity doesn't specify its minimal size.
+ // It will be calculated when the default display gets added.
+ int mDefaultMinSizeOfResizeableTaskDp = -1;
+
+ // Whether tasks have moved and we need to rank the tasks before next OOM scoring
+ private boolean mTaskLayersChanged = true;
+ private int mTmpTaskLayerRank;
+
+ private boolean mTmpBoolean;
+ private RemoteException mTmpRemoteException;
+
+ private String mDestroyAllActivitiesReason;
+ private final Runnable mDestroyAllActivitiesRunnable = new Runnable() {
+ @Override
+ public void run() {
+ synchronized (mService.mGlobalLock) {
+ try {
+ mStackSupervisor.beginDeferResume();
+
+ final PooledConsumer c = PooledLambda.obtainConsumer(
+ RootWindowContainer::destroyActivity, RootWindowContainer.this,
+ PooledLambda.__(ActivityRecord.class));
+ forAllActivities(c);
+ c.recycle();
+ } finally {
+ mStackSupervisor.endDeferResume();
+ resumeFocusedStacksTopActivities();
+ }
+ }
+ }
+
+ };
+
+ private final FindTaskResult mTmpFindTaskResult = new FindTaskResult();
+ static class FindTaskResult implements Function<Task, Boolean> {
+ ActivityRecord mRecord;
+ boolean mIdealMatch;
+
+ private ActivityRecord mTarget;
+ private Intent intent;
+ private ActivityInfo info;
+ private ComponentName cls;
+ private int userId;
+ private boolean isDocument;
+ private Uri documentData;
+
+ /**
+ * Returns the top activity in any existing task matching the given Intent in the input
+ * result. Returns null if no such task is found.
+ */
+ void process(ActivityRecord target, ActivityStack parent) {
+ mTarget = target;
+
+ intent = target.intent;
+ info = target.info;
+ cls = intent.getComponent();
+ if (info.targetActivity != null) {
+ cls = new ComponentName(info.packageName, info.targetActivity);
+ }
+ userId = UserHandle.getUserId(info.applicationInfo.uid);
+ isDocument = intent != null & intent.isDocument();
+ // If documentData is non-null then it must match the existing task data.
+ documentData = isDocument ? intent.getData() : null;
+
+ if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Looking for task of " + target + " in " + parent);
+ parent.forAllTasks(this);
+ }
+
+ void clear() {
+ mRecord = null;
+ mIdealMatch = false;
+ }
+
+ void setTo(FindTaskResult result) {
+ mRecord = result.mRecord;
+ mIdealMatch = result.mIdealMatch;
+ }
+
+ @Override
+ public Boolean apply(Task task) {
+ if (task.voiceSession != null) {
+ // We never match voice sessions; those always run independently.
+ if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": voice session");
+ return false;
+ }
+ if (task.mUserId != userId) {
+ // Looking for a different task.
+ if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": different user");
+ return false;
+ }
+
+ // Overlays should not be considered as the task's logical top activity.
+ final ActivityRecord r = task.getTopNonFinishingActivity(false /* includeOverlays */);
+ if (r == null || r.finishing || r.mUserId != userId
+ || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
+ if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": mismatch root " + r);
+ return false;
+ }
+ if (!r.hasCompatibleActivityType(mTarget)) {
+ if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": mismatch activity type");
+ return false;
+ }
+
+ final Intent taskIntent = task.intent;
+ final Intent affinityIntent = task.affinityIntent;
+ final boolean taskIsDocument;
+ final Uri taskDocumentData;
+ if (taskIntent != null && taskIntent.isDocument()) {
+ taskIsDocument = true;
+ taskDocumentData = taskIntent.getData();
+ } else if (affinityIntent != null && affinityIntent.isDocument()) {
+ taskIsDocument = true;
+ taskDocumentData = affinityIntent.getData();
+ } else {
+ taskIsDocument = false;
+ taskDocumentData = null;
+ }
+
+ if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Comparing existing cls="
+ + (task.realActivity != null ? task.realActivity.flattenToShortString() : "")
+ + "/aff=" + r.getTask().rootAffinity + " to new cls="
+ + intent.getComponent().flattenToShortString() + "/aff=" + info.taskAffinity);
+ // TODO Refactor to remove duplications. Check if logic can be simplified.
+ if (task.realActivity != null && task.realActivity.compareTo(cls) == 0
+ && Objects.equals(documentData, taskDocumentData)) {
+ if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching class!");
+ //dump();
+ if (DEBUG_TASKS) Slog.d(TAG_TASKS,
+ "For Intent " + intent + " bringing to top: " + r.intent);
+ mRecord = r;
+ mIdealMatch = true;
+ return true;
+ } else if (affinityIntent != null && affinityIntent.getComponent() != null
+ && affinityIntent.getComponent().compareTo(cls) == 0 &&
+ Objects.equals(documentData, taskDocumentData)) {
+ if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching class!");
+ if (DEBUG_TASKS) Slog.d(TAG_TASKS,
+ "For Intent " + intent + " bringing to top: " + r.intent);
+ mRecord = r;
+ mIdealMatch = true;
+ return true;
+ } else if (!isDocument && !taskIsDocument
+ && mRecord == null && task.rootAffinity != null) {
+ if (task.rootAffinity.equals(mTarget.taskAffinity)) {
+ if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching affinity candidate!");
+ // It is possible for multiple tasks to have the same root affinity especially
+ // if they are in separate stacks. We save off this candidate, but keep looking
+ // to see if there is a better candidate.
+ mRecord = r;
+ mIdealMatch = false;
+ }
+ } else if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Not a match: " + task);
+
+ return false;
+ }
+ }
+
private final Consumer<WindowState> mCloseSystemDialogsConsumer = w -> {
if (w.mHasSurface) {
try {
@@ -151,13 +450,9 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
super(service);
mDisplayTransaction = service.mTransactionFactory.get();
mHandler = new MyHandler(service.mH.getLooper());
- }
-
- void setRootActivityContainer(RootActivityContainer container) {
- mRootActivityContainer = container;
- if (container != null) {
- container.registerConfigurationChangeListener(this);
- }
+ mService = service.mAtmService;
+ mStackSupervisor = mService.mStackSupervisor;
+ mStackSupervisor.mRootWindowContainer = this;
}
boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
@@ -213,16 +508,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
!mWmService.mPerDisplayFocusEnabled /* updateInputWindows */);
}
- DisplayContent getDisplayContent(int displayId) {
- for (int i = mChildren.size() - 1; i >= 0; --i) {
- final DisplayContent current = mChildren.get(i);
- if (current.getDisplayId() == displayId) {
- return current;
- }
- }
- return null;
- }
-
/**
* Called when DisplayWindowSettings values may change.
*/
@@ -286,14 +571,19 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
}
/**
- * Returns true if the callingUid has any non-toast window currently visible to the user.
- * Also ignores TYPE_APPLICATION_STARTING, since those windows don't belong to apps.
+ * Returns {@code true} if the callingUid has any non-toast window currently visible to the
+ * user. Also ignores {@link android.view.WindowManager.LayoutParams#TYPE_APPLICATION_STARTING},
+ * since those windows don't belong to apps.
+ * @see WindowState#isNonToastOrStarting()
*/
boolean isAnyNonToastWindowVisibleForUid(int callingUid) {
- return forAllWindows(w ->
- w.getOwningUid() == callingUid && w.mAttrs.type != TYPE_TOAST
- && w.mAttrs.type != TYPE_APPLICATION_STARTING && w.isVisibleNow(),
- true /* traverseTopToBottom */);
+ final PooledPredicate p = PooledLambda.obtainPredicate(
+ WindowState::isNonToastWindowVisibleForUid,
+ PooledLambda.__(WindowState.class), callingUid);
+
+ final WindowState w = getWindow(p);
+ p.recycle();
+ return w != null;
}
/**
@@ -383,17 +673,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
}
}
- ActivityStack getStack(int windowingMode, int activityType) {
- for (int i = mChildren.size() - 1; i >= 0; i--) {
- final DisplayContent dc = mChildren.get(i);
- final ActivityStack stack = dc.getStack(windowingMode, activityType);
- if (stack != null) {
- return stack;
- }
- }
- return null;
- }
-
void setSecureSurfaceState(int userId, boolean disabled) {
forAllWindows((w) -> {
if (w.mHasSurface && userId == UserHandle.getUserId(w.mOwnerUid)) {
@@ -998,9 +1277,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
}
}
- @CallSuper
- @Override
- public void dumpDebug(ProtoOutputStream proto, long fieldId,
+ public void dumpDebugInner(ProtoOutputStream proto, long fieldId,
@WindowTraceLogLevel int logLevel) {
if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
return;
@@ -1029,19 +1306,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
}
@Override
- void positionChildAt(int position, DisplayContent child, boolean includingParents) {
- super.positionChildAt(position, child, includingParents);
- if (mRootActivityContainer != null) {
- mRootActivityContainer.onChildPositionChanged(child, position);
- }
- }
-
- void positionChildAt(int position, DisplayContent child) {
- // Only called from controller so no need to notify the change to controller.
- super.positionChildAt(position, child, false /* includingParents */);
- }
-
- @Override
void scheduleAnimation() {
mWmService.scheduleAnimationLocked();
}
@@ -1085,4 +1349,2306 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
}
return null;
}
+
+ void getDisplayContextsWithNonToastVisibleWindows(int pid, List<Context> outContexts) {
+ if (outContexts == null) {
+ return;
+ }
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ DisplayContent dc = mChildren.get(i);
+ if (dc.isAnyNonToastWindowVisibleForPid(pid)) {
+ outContexts.add(dc.getDisplayUiContext());
+ }
+ }
+ }
+
+ @Nullable Context getDisplayUiContext(int displayId) {
+ return getDisplayContent(displayId) != null
+ ? getDisplayContent(displayId).getDisplayUiContext() : null;
+ }
+
+ void setWindowManager(WindowManagerService wm) {
+ mWindowManager = wm;
+ mDisplayManager = mService.mContext.getSystemService(DisplayManager.class);
+ mDisplayManager.registerDisplayListener(this, mService.mUiHandler);
+ mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
+
+ final Display[] displays = mDisplayManager.getDisplays();
+ for (int displayNdx = 0; displayNdx < displays.length; ++displayNdx) {
+ final Display display = displays[displayNdx];
+ final DisplayContent displayContent = new DisplayContent(display, this);
+ if (displayContent.mDisplayId == DEFAULT_DISPLAY) {
+ mDefaultDisplay = displayContent;
+ }
+ }
+ calculateDefaultMinimalSizeOfResizeableTasks();
+
+ final DisplayContent defaultDisplay = getDefaultDisplay();
+
+ defaultDisplay.getOrCreateStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
+ positionChildAt(POSITION_TOP, defaultDisplay, false /* includingParents */);
+ }
+
+ // TODO(multi-display): Look at all callpoints to make sure they make sense in multi-display.
+ DisplayContent getDefaultDisplay() {
+ return mDefaultDisplay;
+ }
+
+ /**
+ * Get an existing instance of {@link DisplayContent} that has the given uniqueId. Unique ID is
+ * defined in {@link DisplayInfo#uniqueId}.
+ *
+ * @param uniqueId the unique ID of the display
+ * @return the {@link DisplayContent} or {@code null} if nothing is found.
+ */
+ DisplayContent getDisplayContent(String uniqueId) {
+ for (int i = getChildCount() - 1; i >= 0; --i) {
+ final DisplayContent display = getChildAt(i);
+ final boolean isValid = display.mDisplay.isValid();
+ if (isValid && display.mDisplay.getUniqueId().equals(uniqueId)) {
+ return display;
+ }
+ }
+
+ return null;
+ }
+
+ // TODO: Look into consolidating with getDisplayContentOrCreate()
+ DisplayContent getDisplayContent(int displayId) {
+ for (int i = getChildCount() - 1; i >= 0; --i) {
+ final DisplayContent displayContent = getChildAt(i);
+ if (displayContent.mDisplayId == displayId) {
+ return displayContent;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Get an existing instance of {@link DisplayContent} or create new if there is a
+ * corresponding record in display manager.
+ */
+ // TODO: Look into consolidating with getDisplayContent()
+ @Nullable DisplayContent getDisplayContentOrCreate(int displayId) {
+ DisplayContent displayContent = getDisplayContent(displayId);
+ if (displayContent != null) {
+ return displayContent;
+ }
+ if (mDisplayManager == null) {
+ // The system isn't fully initialized yet.
+ return null;
+ }
+ final Display display = mDisplayManager.getDisplay(displayId);
+ if (display == null) {
+ // The display is not registered in DisplayManager.
+ return null;
+ }
+ // The display hasn't been added to ActivityManager yet, create a new record now.
+ displayContent = new DisplayContent(display, this);
+ return displayContent;
+ }
+
+ ActivityRecord getDefaultDisplayHomeActivity() {
+ return getDefaultDisplayHomeActivityForUser(mCurrentUser);
+ }
+
+ ActivityRecord getDefaultDisplayHomeActivityForUser(int userId) {
+ return getDisplayContent(DEFAULT_DISPLAY).getHomeActivityForUser(userId);
+ }
+
+ boolean startHomeOnAllDisplays(int userId, String reason) {
+ boolean homeStarted = false;
+ for (int i = getChildCount() - 1; i >= 0; i--) {
+ final int displayId = getChildAt(i).mDisplayId;
+ homeStarted |= startHomeOnDisplay(userId, reason, displayId);
+ }
+ return homeStarted;
+ }
+
+ void startHomeOnEmptyDisplays(String reason) {
+ for (int i = getChildCount() - 1; i >= 0; i--) {
+ final DisplayContent display = getChildAt(i);
+ if (display.topRunningActivity() == null) {
+ startHomeOnDisplay(mCurrentUser, reason, display.mDisplayId);
+ }
+ }
+ }
+
+ boolean startHomeOnDisplay(int userId, String reason, int displayId) {
+ return startHomeOnDisplay(userId, reason, displayId, false /* allowInstrumenting */,
+ false /* fromHomeKey */);
+ }
+
+ /**
+ * This starts home activity on displays that can have system decorations based on displayId -
+ * Default display always use primary home component.
+ * For Secondary displays, the home activity must have category SECONDARY_HOME and then resolves
+ * according to the priorities listed below.
+ * - If default home is not set, always use the secondary home defined in the config.
+ * - Use currently selected primary home activity.
+ * - Use the activity in the same package as currently selected primary home activity.
+ * If there are multiple activities matched, use first one.
+ * - Use the secondary home defined in the config.
+ */
+ boolean startHomeOnDisplay(int userId, String reason, int displayId, boolean allowInstrumenting,
+ boolean fromHomeKey) {
+ // Fallback to top focused display if the displayId is invalid.
+ if (displayId == INVALID_DISPLAY) {
+ final ActivityStack stack = getTopDisplayFocusedStack();
+ displayId = stack != null ? stack.mDisplayId : DEFAULT_DISPLAY;
+ }
+
+ Intent homeIntent = null;
+ ActivityInfo aInfo = null;
+ if (displayId == DEFAULT_DISPLAY) {
+ homeIntent = mService.getHomeIntent();
+ aInfo = resolveHomeActivity(userId, homeIntent);
+ } else if (shouldPlaceSecondaryHomeOnDisplay(displayId)) {
+ Pair<ActivityInfo, Intent> info = resolveSecondaryHomeActivity(userId, displayId);
+ aInfo = info.first;
+ homeIntent = info.second;
+ }
+ if (aInfo == null || homeIntent == null) {
+ return false;
+ }
+
+ if (!canStartHomeOnDisplay(aInfo, displayId, allowInstrumenting)) {
+ return false;
+ }
+
+ // Updates the home component of the intent.
+ homeIntent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
+ homeIntent.setFlags(homeIntent.getFlags() | FLAG_ACTIVITY_NEW_TASK);
+ // Updates the extra information of the intent.
+ if (fromHomeKey) {
+ homeIntent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, true);
+ }
+ // Update the reason for ANR debugging to verify if the user activity is the one that
+ // actually launched.
+ final String myReason = reason + ":" + userId + ":" + UserHandle.getUserId(
+ aInfo.applicationInfo.uid) + ":" + displayId;
+ mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason,
+ displayId);
+ return true;
+ }
+
+ /**
+ * This resolves the home activity info.
+ * @return the home activity info if any.
+ */
+ @VisibleForTesting
+ ActivityInfo resolveHomeActivity(int userId, Intent homeIntent) {
+ final int flags = ActivityManagerService.STOCK_PM_FLAGS;
+ final ComponentName comp = homeIntent.getComponent();
+ ActivityInfo aInfo = null;
+ try {
+ if (comp != null) {
+ // Factory test.
+ aInfo = AppGlobals.getPackageManager().getActivityInfo(comp, flags, userId);
+ } else {
+ final String resolvedType =
+ homeIntent.resolveTypeIfNeeded(mService.mContext.getContentResolver());
+ final ResolveInfo info = AppGlobals.getPackageManager()
+ .resolveIntent(homeIntent, resolvedType, flags, userId);
+ if (info != null) {
+ aInfo = info.activityInfo;
+ }
+ }
+ } catch (RemoteException e) {
+ // ignore
+ }
+
+ if (aInfo == null) {
+ Slog.wtf(TAG, "No home screen found for " + homeIntent, new Throwable());
+ return null;
+ }
+
+ aInfo = new ActivityInfo(aInfo);
+ aInfo.applicationInfo = mService.getAppInfoForUser(aInfo.applicationInfo, userId);
+ return aInfo;
+ }
+
+ @VisibleForTesting
+ Pair<ActivityInfo, Intent> resolveSecondaryHomeActivity(int userId, int displayId) {
+ if (displayId == DEFAULT_DISPLAY) {
+ throw new IllegalArgumentException(
+ "resolveSecondaryHomeActivity: Should not be DEFAULT_DISPLAY");
+ }
+ // Resolve activities in the same package as currently selected primary home activity.
+ Intent homeIntent = mService.getHomeIntent();
+ ActivityInfo aInfo = resolveHomeActivity(userId, homeIntent);
+ if (aInfo != null) {
+ if (ResolverActivity.class.getName().equals(aInfo.name)) {
+ // Always fallback to secondary home component if default home is not set.
+ aInfo = null;
+ } else {
+ // Look for secondary home activities in the currently selected default home
+ // package.
+ homeIntent = mService.getSecondaryHomeIntent(aInfo.applicationInfo.packageName);
+ final List<ResolveInfo> resolutions = resolveActivities(userId, homeIntent);
+ final int size = resolutions.size();
+ final String targetName = aInfo.name;
+ aInfo = null;
+ for (int i = 0; i < size; i++) {
+ ResolveInfo resolveInfo = resolutions.get(i);
+ // We need to traverse all resolutions to check if the currently selected
+ // default home activity is present.
+ if (resolveInfo.activityInfo.name.equals(targetName)) {
+ aInfo = resolveInfo.activityInfo;
+ break;
+ }
+ }
+ if (aInfo == null && size > 0) {
+ // First one is the best.
+ aInfo = resolutions.get(0).activityInfo;
+ }
+ }
+ }
+
+ if (aInfo != null) {
+ if (!canStartHomeOnDisplay(aInfo, displayId, false /* allowInstrumenting */)) {
+ aInfo = null;
+ }
+ }
+
+ // Fallback to secondary home component.
+ if (aInfo == null) {
+ homeIntent = mService.getSecondaryHomeIntent(null);
+ aInfo = resolveHomeActivity(userId, homeIntent);
+ }
+ return Pair.create(aInfo, homeIntent);
+ }
+
+ /**
+ * Retrieve all activities that match the given intent.
+ * The list should already ordered from best to worst matched.
+ * {@link android.content.pm.PackageManager#queryIntentActivities}
+ */
+ @VisibleForTesting
+ List<ResolveInfo> resolveActivities(int userId, Intent homeIntent) {
+ List<ResolveInfo> resolutions;
+ try {
+ final String resolvedType =
+ homeIntent.resolveTypeIfNeeded(mService.mContext.getContentResolver());
+ resolutions = AppGlobals.getPackageManager().queryIntentActivities(homeIntent,
+ resolvedType, ActivityManagerService.STOCK_PM_FLAGS, userId).getList();
+
+ } catch (RemoteException e) {
+ resolutions = new ArrayList<>();
+ }
+ return resolutions;
+ }
+
+ boolean resumeHomeActivity(ActivityRecord prev, String reason, int displayId) {
+ if (!mService.isBooting() && !mService.isBooted()) {
+ // Not ready yet!
+ return false;
+ }
+
+ if (displayId == INVALID_DISPLAY) {
+ displayId = DEFAULT_DISPLAY;
+ }
+
+ final ActivityRecord r = getDisplayContent(displayId).getHomeActivity();
+ final String myReason = reason + " resumeHomeActivity";
+
+ // Only resume home activity if isn't finishing.
+ if (r != null && !r.finishing) {
+ r.moveFocusableActivityToTop(myReason);
+ return resumeFocusedStacksTopActivities(r.getActivityStack(), prev, null);
+ }
+ return startHomeOnDisplay(mCurrentUser, myReason, displayId);
+ }
+
+ /**
+ * Check if the display is valid for secondary home activity.
+ * @param displayId The id of the target display.
+ * @return {@code true} if allow to launch, {@code false} otherwise.
+ */
+ boolean shouldPlaceSecondaryHomeOnDisplay(int displayId) {
+ if (displayId == DEFAULT_DISPLAY) {
+ throw new IllegalArgumentException(
+ "shouldPlaceSecondaryHomeOnDisplay: Should not be DEFAULT_DISPLAY");
+ } else if (displayId == INVALID_DISPLAY) {
+ return false;
+ }
+
+ if (!mService.mSupportsMultiDisplay) {
+ // Can't launch home on secondary display if device does not support multi-display.
+ return false;
+ }
+
+ final boolean deviceProvisioned = Settings.Global.getInt(
+ mService.mContext.getContentResolver(),
+ Settings.Global.DEVICE_PROVISIONED, 0) != 0;
+ if (!deviceProvisioned) {
+ // Can't launch home on secondary display before device is provisioned.
+ return false;
+ }
+
+ if (!StorageManager.isUserKeyUnlocked(mCurrentUser)) {
+ // Can't launch home on secondary displays if device is still locked.
+ return false;
+ }
+
+ final DisplayContent display = getDisplayContent(displayId);
+ if (display == null || display.isRemoved() || !display.supportsSystemDecorations()) {
+ // Can't launch home on display that doesn't support system decorations.
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Check if home activity start should be allowed on a display.
+ * @param homeInfo {@code ActivityInfo} of the home activity that is going to be launched.
+ * @param displayId The id of the target display.
+ * @param allowInstrumenting Whether launching home should be allowed if being instrumented.
+ * @return {@code true} if allow to launch, {@code false} otherwise.
+ */
+ boolean canStartHomeOnDisplay(ActivityInfo homeInfo, int displayId,
+ boolean allowInstrumenting) {
+ if (mService.mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
+ && mService.mTopAction == null) {
+ // We are running in factory test mode, but unable to find the factory test app, so
+ // just sit around displaying the error message and don't try to start anything.
+ return false;
+ }
+
+ final WindowProcessController app =
+ mService.getProcessController(homeInfo.processName, homeInfo.applicationInfo.uid);
+ if (!allowInstrumenting && app != null && app.isInstrumenting()) {
+ // Don't do this if the home app is currently being instrumented.
+ return false;
+ }
+
+ if (displayId == DEFAULT_DISPLAY || (displayId != INVALID_DISPLAY
+ && displayId == mService.mVr2dDisplayId)) {
+ // No restrictions to default display or vr 2d display.
+ return true;
+ }
+
+ if (!shouldPlaceSecondaryHomeOnDisplay(displayId)) {
+ return false;
+ }
+
+ final boolean supportMultipleInstance = homeInfo.launchMode != LAUNCH_SINGLE_TASK
+ && homeInfo.launchMode != LAUNCH_SINGLE_INSTANCE;
+ if (!supportMultipleInstance) {
+ // Can't launch home on secondary displays if it requested to be single instance.
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Ensure all activities visibility, update orientation and configuration.
+ *
+ * @param starting The currently starting activity or {@code null} if there is none.
+ * @param displayId The id of the display where operation is executed.
+ * @param markFrozenIfConfigChanged Whether to set {@link ActivityRecord#frozenBeforeDestroy} to
+ * {@code true} if config changed.
+ * @param deferResume Whether to defer resume while updating config.
+ * @return 'true' if starting activity was kept or wasn't provided, 'false' if it was relaunched
+ * because of configuration update.
+ */
+ boolean ensureVisibilityAndConfig(ActivityRecord starting, int displayId,
+ boolean markFrozenIfConfigChanged, boolean deferResume) {
+ // First ensure visibility without updating the config just yet. We need this to know what
+ // activities are affecting configuration now.
+ // Passing null here for 'starting' param value, so that visibility of actual starting
+ // activity will be properly updated.
+ ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
+ false /* preserveWindows */, false /* notifyClients */);
+
+ if (displayId == INVALID_DISPLAY) {
+ // The caller didn't provide a valid display id, skip updating config.
+ return true;
+ }
+
+ // Force-update the orientation from the WindowManager, since we need the true configuration
+ // to send to the client now.
+ final DisplayContent displayContent = getDisplayContent(displayId);
+ Configuration config = null;
+ if (displayContent != null) {
+ config = displayContent.updateOrientation(
+ getDisplayOverrideConfiguration(displayId),
+ starting != null && starting.mayFreezeScreenLocked()
+ ? starting.appToken : null,
+ true /* forceUpdate */);
+ }
+ // Visibilities may change so let the starting activity have a chance to report. Can't do it
+ // when visibility is changed in each AppWindowToken because it may trigger wrong
+ // configuration push because the visibility of some activities may not be updated yet.
+ if (starting != null) {
+ starting.reportDescendantOrientationChangeIfNeeded();
+ }
+ if (starting != null && markFrozenIfConfigChanged && config != null) {
+ starting.frozenBeforeDestroy = true;
+ }
+
+ if (displayContent != null) {
+ // Update the configuration of the activities on the display.
+ return displayContent.updateDisplayOverrideConfigurationLocked(config, starting,
+ deferResume, null /* result */);
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * @return a list of activities which are the top ones in each visible stack. The first
+ * entry will be the focused activity.
+ */
+ List<IBinder> getTopVisibleActivities() {
+ final ArrayList<IBinder> topActivityTokens = new ArrayList<>();
+ final ActivityStack topFocusedStack = getTopDisplayFocusedStack();
+ // Traverse all displays.
+ for (int i = getChildCount() - 1; i >= 0; i--) {
+ final DisplayContent display = getChildAt(i);
+ // Traverse all stacks on a display.
+ for (int j = display.getStackCount() - 1; j >= 0; --j) {
+ final ActivityStack stack = display.getStackAt(j);
+ // Get top activity from a visible stack and add it to the list.
+ if (stack.shouldBeVisible(null /* starting */)) {
+ final ActivityRecord top = stack.getTopNonFinishingActivity();
+ if (top != null) {
+ if (stack == topFocusedStack) {
+ topActivityTokens.add(0, top.appToken);
+ } else {
+ topActivityTokens.add(top.appToken);
+ }
+ }
+ }
+ }
+ }
+ return topActivityTokens;
+ }
+
+ ActivityStack getTopDisplayFocusedStack() {
+ for (int i = getChildCount() - 1; i >= 0; --i) {
+ final ActivityStack focusedStack = getChildAt(i).getFocusedStack();
+ if (focusedStack != null) {
+ return focusedStack;
+ }
+ }
+ return null;
+ }
+
+ ActivityRecord getTopResumedActivity() {
+ final ActivityStack focusedStack = getTopDisplayFocusedStack();
+ if (focusedStack == null) {
+ return null;
+ }
+ final ActivityRecord resumedActivity = focusedStack.getResumedActivity();
+ if (resumedActivity != null && resumedActivity.app != null) {
+ return resumedActivity;
+ }
+ // The top focused stack might not have a resumed activity yet - look on all displays in
+ // focus order.
+ for (int i = getChildCount() - 1; i >= 0; --i) {
+ final DisplayContent display = getChildAt(i);
+ final ActivityRecord resumedActivityOnDisplay = display.getResumedActivity();
+ if (resumedActivityOnDisplay != null) {
+ return resumedActivityOnDisplay;
+ }
+ }
+ return null;
+ }
+
+ boolean isFocusable(ConfigurationContainer container, boolean alwaysFocusable) {
+ if (container.inSplitScreenPrimaryWindowingMode() && mIsDockMinimized) {
+ return false;
+ }
+
+ return container.getWindowConfiguration().canReceiveKeys() || alwaysFocusable;
+ }
+
+ boolean isTopDisplayFocusedStack(ActivityStack stack) {
+ return stack != null && stack == getTopDisplayFocusedStack();
+ }
+
+ void updatePreviousProcess(ActivityRecord r) {
+ // Now that this process has stopped, we may want to consider it to be the previous app to
+ // try to keep around in case the user wants to return to it.
+
+ // First, found out what is currently the foreground app, so that we don't blow away the
+ // previous app if this activity is being hosted by the process that is actually still the
+ // foreground.
+ WindowProcessController fgApp = null;
+ for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
+ final DisplayContent display = getChildAt(displayNdx);
+ for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getStackAt(stackNdx);
+ if (isTopDisplayFocusedStack(stack)) {
+ final ActivityRecord resumedActivity = stack.getResumedActivity();
+ if (resumedActivity != null) {
+ fgApp = resumedActivity.app;
+ } else if (stack.mPausingActivity != null) {
+ fgApp = stack.mPausingActivity.app;
+ }
+ break;
+ }
+ }
+ }
+
+ // Now set this one as the previous process, only if that really makes sense to.
+ if (r.hasProcess() && fgApp != null && r.app != fgApp
+ && r.lastVisibleTime > mService.mPreviousProcessVisibleTime
+ && r.app != mService.mHomeProcess) {
+ mService.mPreviousProcess = r.app;
+ mService.mPreviousProcessVisibleTime = r.lastVisibleTime;
+ }
+ }
+
+ boolean attachApplication(WindowProcessController app) throws RemoteException {
+ final String processName = app.mName;
+ boolean didSomething = false;
+ for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
+ final DisplayContent display = getChildAt(displayNdx);
+ final ActivityStack stack = display.getFocusedStack();
+ if (stack == null) {
+ continue;
+ }
+
+ mTmpRemoteException = null;
+ mTmpBoolean = false; // Set to true if an activity was started.
+ final PooledFunction c = PooledLambda.obtainFunction(
+ RootWindowContainer::startActivityForAttachedApplicationIfNeeded, this,
+ PooledLambda.__(ActivityRecord.class), app, stack.topRunningActivity());
+ stack.forAllActivities(c);
+ c.recycle();
+ if (mTmpRemoteException != null) {
+ throw mTmpRemoteException;
+ }
+ didSomething |= mTmpBoolean;
+ }
+ if (!didSomething) {
+ ensureActivitiesVisible(null, 0, false /* preserve_windows */);
+ }
+ return didSomething;
+ }
+
+ private boolean startActivityForAttachedApplicationIfNeeded(ActivityRecord r,
+ WindowProcessController app, ActivityRecord top) {
+ if (r.finishing || !r.okToShowLocked() || !r.visibleIgnoringKeyguard || r.app != null
+ || app.mUid != r.info.applicationInfo.uid || !app.mName.equals(r.processName)) {
+ return false;
+ }
+
+ try {
+ if (mStackSupervisor.realStartActivityLocked(r, app, top == r /*andResume*/,
+ true /*checkConfig*/)) {
+ mTmpBoolean = true;
+ }
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Exception in new application when starting activity "
+ + top.intent.getComponent().flattenToShortString(), e);
+ mTmpRemoteException = e;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Make sure that all activities that need to be visible in the system actually are and update
+ * their configuration.
+ */
+ void ensureActivitiesVisible(ActivityRecord starting, int configChanges,
+ boolean preserveWindows) {
+ ensureActivitiesVisible(starting, configChanges, preserveWindows, true /* notifyClients */);
+ }
+
+ /**
+ * @see #ensureActivitiesVisible(ActivityRecord, int, boolean)
+ */
+ void ensureActivitiesVisible(ActivityRecord starting, int configChanges,
+ boolean preserveWindows, boolean notifyClients) {
+ if (mInEnsureActivitiesVisible) {
+ // Don't do recursive work.
+ return;
+ }
+ mInEnsureActivitiesVisible = true;
+
+ try {
+ mStackSupervisor.getKeyguardController().beginActivityVisibilityUpdate();
+ // First the front stacks. In case any are not fullscreen and are in front of home.
+ for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
+ final DisplayContent display = getChildAt(displayNdx);
+ display.ensureActivitiesVisible(starting, configChanges, preserveWindows,
+ notifyClients);
+ }
+ } finally {
+ mStackSupervisor.getKeyguardController().endActivityVisibilityUpdate();
+ mInEnsureActivitiesVisible = false;
+ }
+ }
+
+ boolean switchUser(int userId, UserState uss) {
+ final int focusStackId = getTopDisplayFocusedStack().getStackId();
+ // We dismiss the docked stack whenever we switch users.
+ final ActivityStack dockedStack = getDefaultDisplay().getSplitScreenPrimaryStack();
+ if (dockedStack != null) {
+ mStackSupervisor.moveTasksToFullscreenStackLocked(
+ dockedStack, dockedStack.isFocusedStackOnDisplay());
+ }
+ // Also dismiss the pinned stack whenever we switch users. Removing the pinned stack will
+ // also cause all tasks to be moved to the fullscreen stack at a position that is
+ // appropriate.
+ removeStacksInWindowingModes(WINDOWING_MODE_PINNED);
+
+ mUserStackInFront.put(mCurrentUser, focusStackId);
+ final int restoreStackId =
+ mUserStackInFront.get(userId, getDefaultDisplay().getHomeStack().mStackId);
+ mCurrentUser = userId;
+
+ mStackSupervisor.mStartingUsers.add(uss);
+ for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
+ final DisplayContent display = getChildAt(displayNdx);
+ for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getStackAt(stackNdx);
+ stack.switchUser(userId);
+ Task task = stack.getTopMostTask();
+ if (task != null) {
+ stack.positionChildAtTop(task);
+ }
+ }
+ }
+
+ ActivityStack stack = getStack(restoreStackId);
+ if (stack == null) {
+ stack = getDefaultDisplay().getHomeStack();
+ }
+ final boolean homeInFront = stack.isActivityTypeHome();
+ if (stack.isOnHomeDisplay()) {
+ stack.moveToFront("switchUserOnHomeDisplay");
+ } else {
+ // Stack was moved to another display while user was swapped out.
+ resumeHomeActivity(null, "switchUserOnOtherDisplay", DEFAULT_DISPLAY);
+ }
+ return homeInFront;
+ }
+
+ void removeUser(int userId) {
+ mUserStackInFront.delete(userId);
+ }
+
+ /**
+ * Update the last used stack id for non-current user (current user's last
+ * used stack is the focused stack)
+ */
+ void updateUserStack(int userId, ActivityStack stack) {
+ if (userId != mCurrentUser) {
+ mUserStackInFront.put(userId, stack != null ? stack.getStackId()
+ : getDefaultDisplay().getHomeStack().mStackId);
+ }
+ }
+
+ /**
+ * Move stack with all its existing content to specified display.
+ * @param stackId Id of stack to move.
+ * @param displayId Id of display to move stack to.
+ * @param onTop Indicates whether container should be place on top or on bottom.
+ */
+ void moveStackToDisplay(int stackId, int displayId, boolean onTop) {
+ final DisplayContent displayContent = getDisplayContentOrCreate(displayId);
+ if (displayContent == null) {
+ throw new IllegalArgumentException("moveStackToDisplay: Unknown displayId="
+ + displayId);
+ }
+ final ActivityStack stack = getStack(stackId);
+ if (stack == null) {
+ throw new IllegalArgumentException("moveStackToDisplay: Unknown stackId="
+ + stackId);
+ }
+
+ final DisplayContent currentDisplay = stack.getDisplay();
+ if (currentDisplay == null) {
+ throw new IllegalStateException("moveStackToDisplay: Stack with stack=" + stack
+ + " is not attached to any display.");
+ }
+
+ if (currentDisplay.mDisplayId == displayId) {
+ throw new IllegalArgumentException("Trying to move stack=" + stack
+ + " to its current displayId=" + displayId);
+ }
+
+ if (displayContent.isSingleTaskInstance() && displayContent.getStackCount() > 0) {
+ // We don't allow moving stacks to single instance display that already has a child.
+ Slog.e(TAG, "Can not move stack=" + stack
+ + " to single task instance display=" + displayContent);
+ return;
+ }
+
+ stack.reparent(displayContent.mDisplayContent, onTop);
+ // TODO(multi-display): resize stacks properly if moved from split-screen.
+ }
+
+ boolean moveTopStackActivityToPinnedStack(int stackId) {
+ final ActivityStack stack = getStack(stackId);
+ if (stack == null) {
+ throw new IllegalArgumentException(
+ "moveTopStackActivityToPinnedStack: Unknown stackId=" + stackId);
+ }
+
+ final ActivityRecord r = stack.topRunningActivity();
+ if (r == null) {
+ Slog.w(TAG, "moveTopStackActivityToPinnedStack: No top running activity"
+ + " in stack=" + stack);
+ return false;
+ }
+
+ if (!mService.mForceResizableActivities && !r.supportsPictureInPicture()) {
+ Slog.w(TAG, "moveTopStackActivityToPinnedStack: Picture-In-Picture not supported for "
+ + " r=" + r);
+ return false;
+ }
+
+ moveActivityToPinnedStack(r, null /* sourceBounds */, 0f /* aspectRatio */,
+ "moveTopActivityToPinnedStack");
+ return true;
+ }
+
+ void moveActivityToPinnedStack(ActivityRecord r, Rect sourceHintBounds, float aspectRatio,
+ String reason) {
+ mService.deferWindowLayout();
+
+ final DisplayContent display = r.getActivityStack().getDisplay();
+
+ try {
+ final Task task = r.getTask();
+
+ final ActivityStack pinnedStack = display.getPinnedStack();
+ // This will change the pinned stack's windowing mode to its original mode, ensuring
+ // we only have one stack that is in pinned mode.
+ if (pinnedStack != null) {
+ pinnedStack.dismissPip();
+ }
+
+ final boolean singleActivity = task.getChildCount() == 1;
+
+ final ActivityStack stack;
+ if (singleActivity) {
+ stack = r.getActivityStack();
+ } else {
+ // In the case of multiple activities, we will create a new stack for it and then
+ // move the PIP activity into the stack.
+ // We will then perform a windowing mode change for both scenarios.
+ stack = display.createStack(
+ r.getActivityStack().getRequestedOverrideWindowingMode(),
+ r.getActivityType(), ON_TOP);
+ // There are multiple activities in the task and moving the top activity should
+ // reveal/leave the other activities in their original task.
+
+ // Currently, we don't support reparenting activities across tasks in two different
+ // stacks, so instead, just create a new task in the same stack, reparent the
+ // activity into that task, and then reparent the whole task to the new stack. This
+ // ensures that all the necessary work to migrate states in the old and new stacks
+ // is also done.
+ final Task newTask = task.getStack().createTask(
+ mStackSupervisor.getNextTaskIdForUserLocked(r.mUserId), r.info,
+ r.intent, null, null, true);
+ r.reparent(newTask, MAX_VALUE, "moveActivityToStack");
+
+ // Defer resume until below, and do not schedule PiP changes until we animate below
+ newTask.reparent(stack, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT, !ANIMATE,
+ DEFER_RESUME, false /* schedulePictureInPictureModeChange */, reason);
+ }
+
+ stack.setWindowingMode(WINDOWING_MODE_PINNED);
+
+ // Reset the state that indicates it can enter PiP while pausing after we've moved it
+ // to the pinned stack
+ r.supportsEnterPipOnTaskSwitch = false;
+ } finally {
+ mService.continueWindowLayout();
+ }
+
+ // Notify the pinned stack controller to prepare the PiP animation, expect callback
+ // delivered from SystemUI to WM to start the animation.
+ final PinnedStackController pinnedStackController =
+ display.mDisplayContent.getPinnedStackController();
+ pinnedStackController.prepareAnimation(sourceHintBounds, aspectRatio,
+ null /* stackBounds */);
+
+ // TODO: revisit the following statement after the animation is moved from WM to SysUI.
+ // Update the visibility of all activities after the they have been reparented to the new
+ // stack. This MUST run after the animation above is scheduled to ensure that the windows
+ // drawn signal is scheduled after the bounds animation start call on the bounds animator
+ // thread.
+ ensureActivitiesVisible(null, 0, false /* preserveWindows */);
+ resumeFocusedStacksTopActivities();
+
+ mService.getTaskChangeNotificationController().notifyActivityPinned(r);
+ }
+
+ void executeAppTransitionForAllDisplay() {
+ for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
+ final DisplayContent display = getChildAt(displayNdx);
+ display.mDisplayContent.executeAppTransition();
+ }
+ }
+
+ void setDockedStackMinimized(boolean minimized) {
+ // Get currently focused stack before setting mIsDockMinimized. We do this because if
+ // split-screen is active, primary stack will not be focusable (see #isFocusable) while
+ // still occluding other stacks. This will cause getTopDisplayFocusedStack() to return null.
+ final ActivityStack current = getTopDisplayFocusedStack();
+ mIsDockMinimized = minimized;
+ if (mIsDockMinimized) {
+ if (current.inSplitScreenPrimaryWindowingMode()) {
+ // The primary split-screen stack can't be focused while it is minimize, so move
+ // focus to something else.
+ current.adjustFocusToNextFocusableStack("setDockedStackMinimized");
+ }
+ }
+ }
+
+ ActivityRecord findTask(ActivityRecord r, int preferredDisplayId) {
+ if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Looking for task of " + r);
+ mTmpFindTaskResult.clear();
+
+ // Looking up task on preferred display first
+ final DisplayContent preferredDisplay = getDisplayContent(preferredDisplayId);
+ if (preferredDisplay != null) {
+ preferredDisplay.findTaskLocked(r, true /* isPreferredDisplay */, mTmpFindTaskResult);
+ if (mTmpFindTaskResult.mIdealMatch) {
+ return mTmpFindTaskResult.mRecord;
+ }
+ }
+
+ for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
+ final DisplayContent display = getChildAt(displayNdx);
+ if (display.mDisplayId == preferredDisplayId) {
+ continue;
+ }
+
+ display.findTaskLocked(r, false /* isPreferredDisplay */, mTmpFindTaskResult);
+ if (mTmpFindTaskResult.mIdealMatch) {
+ return mTmpFindTaskResult.mRecord;
+ }
+ }
+
+ if (DEBUG_TASKS && mTmpFindTaskResult.mRecord == null) Slog.d(TAG_TASKS, "No task found");
+ return mTmpFindTaskResult.mRecord;
+ }
+
+ /**
+ * Finish the topmost activities in all stacks that belong to the crashed app.
+ * @param app The app that crashed.
+ * @param reason Reason to perform this action.
+ * @return The task id that was finished in this stack, or INVALID_TASK_ID if none was finished.
+ */
+ int finishTopCrashedActivities(WindowProcessController app, String reason) {
+ Task finishedTask = null;
+ ActivityStack focusedStack = getTopDisplayFocusedStack();
+ for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
+ final DisplayContent display = getChildAt(displayNdx);
+ // It is possible that request to finish activity might also remove its task and stack,
+ // so we need to be careful with indexes in the loop and check child count every time.
+ for (int stackNdx = 0; stackNdx < display.getStackCount(); ++stackNdx) {
+ final ActivityStack stack = display.getStackAt(stackNdx);
+ final Task t = stack.finishTopCrashedActivityLocked(app, reason);
+ if (stack == focusedStack || finishedTask == null) {
+ finishedTask = t;
+ }
+ }
+ }
+ return finishedTask != null ? finishedTask.mTaskId : INVALID_TASK_ID;
+ }
+
+ boolean resumeFocusedStacksTopActivities() {
+ return resumeFocusedStacksTopActivities(null, null, null);
+ }
+
+ boolean resumeFocusedStacksTopActivities(
+ ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
+
+ if (!mStackSupervisor.readyToResume()) {
+ return false;
+ }
+
+ boolean result = false;
+ if (targetStack != null && (targetStack.isTopStackOnDisplay()
+ || getTopDisplayFocusedStack() == targetStack)) {
+ result = targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
+ }
+
+ for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
+ boolean resumedOnDisplay = false;
+ final DisplayContent display = getChildAt(displayNdx);
+ for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getStackAt(stackNdx);
+ final ActivityRecord topRunningActivity = stack.topRunningActivity();
+ if (!stack.isFocusableAndVisible() || topRunningActivity == null) {
+ continue;
+ }
+ if (stack == targetStack) {
+ // Simply update the result for targetStack because the targetStack had
+ // already resumed in above. We don't want to resume it again, especially in
+ // some cases, it would cause a second launch failure if app process was dead.
+ resumedOnDisplay |= result;
+ continue;
+ }
+ if (display.isTopStack(stack) && topRunningActivity.isState(RESUMED)) {
+ // Kick off any lingering app transitions form the MoveTaskToFront operation,
+ // but only consider the top task and stack on that display.
+ stack.executeAppTransition(targetOptions);
+ } else {
+ resumedOnDisplay |= topRunningActivity.makeActiveIfNeeded(target);
+ }
+ }
+ if (!resumedOnDisplay) {
+ // In cases when there are no valid activities (e.g. device just booted or launcher
+ // crashed) it's possible that nothing was resumed on a display. Requesting resume
+ // of top activity in focused stack explicitly will make sure that at least home
+ // activity is started and resumed, and no recursion occurs.
+ final ActivityStack focusedStack = display.getFocusedStack();
+ if (focusedStack != null) {
+ result |= focusedStack.resumeTopActivityUncheckedLocked(target, targetOptions);
+ } else if (targetStack == null && display.getStackCount() == 0) {
+ result |= resumeHomeActivity(null /* prev */, "empty-display",
+ display.mDisplayId);
+ }
+ }
+ }
+
+ return result;
+ }
+
+ void applySleepTokens(boolean applyToStacks) {
+ for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
+ // Set the sleeping state of the display.
+ final DisplayContent display = getChildAt(displayNdx);
+ final boolean displayShouldSleep = display.shouldSleep();
+ if (displayShouldSleep == display.isSleeping()) {
+ continue;
+ }
+ display.setIsSleeping(displayShouldSleep);
+
+ if (!applyToStacks) {
+ continue;
+ }
+
+ // Set the sleeping state of the stacks on the display.
+ for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getStackAt(stackNdx);
+ if (displayShouldSleep) {
+ stack.goToSleepIfPossible(false /* shuttingDown */);
+ } else {
+ // When the display which can only contain one task turns on, start a special
+ // transition. {@link AppTransitionController#handleAppTransitionReady} later
+ // picks up the transition, and schedules
+ // {@link ITaskStackListener#onSingleTaskDisplayDrawn} callback which is
+ // triggered after contents are drawn on the display.
+ if (display.isSingleTaskInstance()) {
+ display.mDisplayContent.prepareAppTransition(
+ TRANSIT_SHOW_SINGLE_TASK_DISPLAY, false);
+ }
+ stack.awakeFromSleepingLocked();
+ if (stack.isFocusedStackOnDisplay()
+ && !mStackSupervisor.getKeyguardController()
+ .isKeyguardOrAodShowing(display.mDisplayId)) {
+ // If the keyguard is unlocked - resume immediately.
+ // It is possible that the display will not be awake at the time we
+ // process the keyguard going away, which can happen before the sleep token
+ // is released. As a result, it is important we resume the activity here.
+ resumeFocusedStacksTopActivities();
+ }
+ }
+ }
+
+ if (displayShouldSleep || mStackSupervisor.mGoingToSleepActivities.isEmpty()) {
+ continue;
+ }
+ // The display is awake now, so clean up the going to sleep list.
+ for (Iterator<ActivityRecord> it =
+ mStackSupervisor.mGoingToSleepActivities.iterator(); it.hasNext(); ) {
+ final ActivityRecord r = it.next();
+ if (r.getDisplayId() == display.mDisplayId) {
+ it.remove();
+ }
+ }
+ }
+ }
+
+ protected ActivityStack getStack(int stackId) {
+ for (int i = getChildCount() - 1; i >= 0; --i) {
+ final ActivityStack stack = getChildAt(i).getStack(stackId);
+ if (stack != null) {
+ return stack;
+ }
+ }
+ return null;
+ }
+
+ /** @see DisplayContent#getStack(int, int) */
+ ActivityStack getStack(int windowingMode, int activityType) {
+ for (int i = getChildCount() - 1; i >= 0; --i) {
+ final ActivityStack stack = getChildAt(i).getStack(windowingMode, activityType);
+ if (stack != null) {
+ return stack;
+ }
+ }
+ return null;
+ }
+
+ private ActivityStack getStack(int windowingMode, int activityType,
+ int displayId) {
+ DisplayContent display = getDisplayContent(displayId);
+ if (display == null) {
+ return null;
+ }
+ return display.getStack(windowingMode, activityType);
+ }
+
+ private ActivityManager.StackInfo getStackInfo(ActivityStack stack) {
+ final int displayId = stack.mDisplayId;
+ final DisplayContent display = getDisplayContent(displayId);
+ ActivityManager.StackInfo info = new ActivityManager.StackInfo();
+ stack.getBounds(info.bounds);
+ info.displayId = displayId;
+ info.stackId = stack.mStackId;
+ info.stackToken = stack.mRemoteToken;
+ info.userId = stack.mCurrentUser;
+ info.visible = stack.shouldBeVisible(null);
+ // A stack might be not attached to a display.
+ info.position = display != null ? display.getIndexOf(stack) : 0;
+ info.configuration.setTo(stack.getConfiguration());
+
+ final int numTasks = stack.getChildCount();
+ info.taskIds = new int[numTasks];
+ info.taskNames = new String[numTasks];
+ info.taskBounds = new Rect[numTasks];
+ info.taskUserIds = new int[numTasks];
+ final int[] currenIndex = {0};
+
+ final PooledConsumer c = PooledLambda.obtainConsumer(
+ RootWindowContainer::processTaskForStackInfo, PooledLambda.__(Task.class), info,
+ currenIndex);
+ stack.forAllTasks(c, false);
+ c.recycle();
+
+ final ActivityRecord top = stack.topRunningActivity();
+ info.topActivity = top != null ? top.intent.getComponent() : null;
+ return info;
+ }
+
+ private static void processTaskForStackInfo(
+ Task task, ActivityManager.StackInfo info, int[] currentIndex) {
+ int i = currentIndex[0];
+ info.taskIds[i] = task.mTaskId;
+ info.taskNames[i] = task.origActivity != null ? task.origActivity.flattenToString()
+ : task.realActivity != null ? task.realActivity.flattenToString()
+ : task.getTopNonFinishingActivity() != null
+ ? task.getTopNonFinishingActivity().packageName : "unknown";
+ info.taskBounds[i] = task.mAtmService.getTaskBounds(task.mTaskId);
+ info.taskUserIds[i] = task.mUserId;
+ currentIndex[0] = ++i;
+ }
+
+ ActivityManager.StackInfo getStackInfo(int stackId) {
+ ActivityStack stack = getStack(stackId);
+ if (stack != null) {
+ return getStackInfo(stack);
+ }
+ return null;
+ }
+
+ ActivityManager.StackInfo getStackInfo(int windowingMode, int activityType) {
+ final ActivityStack stack = getStack(windowingMode, activityType);
+ return (stack != null) ? getStackInfo(stack) : null;
+ }
+
+ ActivityManager.StackInfo getStackInfo(int windowingMode, int activityType, int displayId) {
+ final ActivityStack stack = getStack(windowingMode, activityType, displayId);
+ return (stack != null) ? getStackInfo(stack) : null;
+ }
+
+ /** If displayId == INVALID_DISPLAY, this will get stack infos on all displays */
+ ArrayList<ActivityManager.StackInfo> getAllStackInfos(int displayId) {
+ ArrayList<ActivityManager.StackInfo> list = new ArrayList<>();
+ if (displayId == INVALID_DISPLAY) {
+ for (int displayNdx = 0; displayNdx < getChildCount(); ++displayNdx) {
+ final DisplayContent display = getChildAt(displayNdx);
+ for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getStackAt(stackNdx);
+ list.add(getStackInfo(stack));
+ }
+ }
+ return list;
+ }
+ final DisplayContent display = getDisplayContent(displayId);
+ if (display == null) {
+ return list;
+ }
+ for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getStackAt(stackNdx);
+ list.add(getStackInfo(stack));
+ }
+ return list;
+ }
+
+ void deferUpdateBounds(int activityType) {
+ final ActivityStack stack = getStack(WINDOWING_MODE_UNDEFINED, activityType);
+ if (stack != null) {
+ stack.deferUpdateBounds();
+ }
+ }
+
+ void continueUpdateBounds(int activityType) {
+ final ActivityStack stack = getStack(WINDOWING_MODE_UNDEFINED, activityType);
+ if (stack != null) {
+ stack.continueUpdateBounds();
+ }
+ }
+
+ @Override
+ public void onDisplayAdded(int displayId) {
+ if (DEBUG_STACK) Slog.v(TAG, "Display added displayId=" + displayId);
+ synchronized (mService.mGlobalLock) {
+ final DisplayContent display = getDisplayContentOrCreate(displayId);
+ if (display == null) {
+ return;
+ }
+ // Do not start home before booting, or it may accidentally finish booting before it
+ // starts. Instead, we expect home activities to be launched when the system is ready
+ // (ActivityManagerService#systemReady).
+ if (mService.isBooted() || mService.isBooting()) {
+ startSystemDecorations(display.mDisplayContent);
+ }
+ }
+ }
+
+ private void startSystemDecorations(final DisplayContent displayContent) {
+ startHomeOnDisplay(mCurrentUser, "displayAdded", displayContent.getDisplayId());
+ displayContent.getDisplayPolicy().notifyDisplayReady();
+ }
+
+ @Override
+ public void onDisplayRemoved(int displayId) {
+ if (DEBUG_STACK) Slog.v(TAG, "Display removed displayId=" + displayId);
+ if (displayId == DEFAULT_DISPLAY) {
+ throw new IllegalArgumentException("Can't remove the primary display.");
+ }
+
+ synchronized (mService.mGlobalLock) {
+ final DisplayContent displayContent = getDisplayContent(displayId);
+ if (displayContent == null) {
+ return;
+ }
+
+ displayContent.remove();
+ }
+ }
+
+ @Override
+ public void onDisplayChanged(int displayId) {
+ if (DEBUG_STACK) Slog.v(TAG, "Display changed displayId=" + displayId);
+ synchronized (mService.mGlobalLock) {
+ final DisplayContent displayContent = getDisplayContent(displayId);
+ if (displayContent != null) {
+ displayContent.onDisplayChanged();
+ }
+ }
+ }
+
+ /** Update lists of UIDs that are present on displays and have access to them. */
+ void updateUIDsPresentOnDisplay() {
+ mDisplayAccessUIDs.clear();
+ for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
+ final DisplayContent displayContent = getChildAt(displayNdx);
+ // Only bother calculating the whitelist for private displays
+ if (displayContent.isPrivate()) {
+ mDisplayAccessUIDs.append(
+ displayContent.mDisplayId, displayContent.getPresentUIDs());
+ }
+ }
+ // Store updated lists in DisplayManager. Callers from outside of AM should get them there.
+ mDisplayManagerInternal.setDisplayAccessUIDs(mDisplayAccessUIDs);
+ }
+
+ ActivityStack findStackBehind(ActivityStack stack) {
+ final DisplayContent display = getDisplayContent(stack.mDisplayId);
+ if (display != null) {
+ for (int i = display.getStackCount() - 1; i >= 0; i--) {
+ if (display.getStackAt(i) == stack && i > 0) {
+ return display.getStackAt(i - 1);
+ }
+ }
+ }
+ throw new IllegalStateException("Failed to find a stack behind stack=" + stack
+ + " in=" + display);
+ }
+
+ @Override
+ void positionChildAt(int position, DisplayContent child, boolean includingParents) {
+ super.positionChildAt(position, child, includingParents);
+ mStackSupervisor.updateTopResumedActivityIfNeeded();
+ }
+
+ Configuration getDisplayOverrideConfiguration(int displayId) {
+ final DisplayContent displayContent = getDisplayContentOrCreate(displayId);
+ if (displayContent == null) {
+ throw new IllegalArgumentException("No display found with id: " + displayId);
+ }
+
+ return displayContent.getRequestedOverrideConfiguration();
+ }
+
+ void setDisplayOverrideConfiguration(Configuration overrideConfiguration, int displayId) {
+ final DisplayContent displayContent = getDisplayContentOrCreate(displayId);
+ if (displayContent == null) {
+ throw new IllegalArgumentException("No display found with id: " + displayId);
+ }
+
+ displayContent.onRequestedOverrideConfigurationChanged(overrideConfiguration);
+ }
+
+ void prepareForShutdown() {
+ for (int i = 0; i < getChildCount(); i++) {
+ createSleepToken("shutdown", getChildAt(i).mDisplayId);
+ }
+ }
+
+ ActivityTaskManagerInternal.SleepToken createSleepToken(String tag, int displayId) {
+ final DisplayContent display = getDisplayContent(displayId);
+ if (display == null) {
+ throw new IllegalArgumentException("Invalid display: " + displayId);
+ }
+
+ final SleepTokenImpl token = new SleepTokenImpl(tag, displayId);
+ mSleepTokens.add(token);
+ display.mAllSleepTokens.add(token);
+ return token;
+ }
+
+ private void removeSleepToken(SleepTokenImpl token) {
+ mSleepTokens.remove(token);
+
+ final DisplayContent display = getDisplayContent(token.mDisplayId);
+ if (display != null) {
+ display.mAllSleepTokens.remove(token);
+ if (display.mAllSleepTokens.isEmpty()) {
+ mService.updateSleepIfNeededLocked();
+ }
+ }
+ }
+
+ void addStartingWindowsForVisibleActivities() {
+ forAllActivities((r) -> {
+ if (r.mVisibleRequested) {
+ r.showStartingWindow(null /* prev */, false /* newTask */, true /*taskSwitch*/);
+ }
+ });
+ }
+
+ void invalidateTaskLayers() {
+ mTaskLayersChanged = true;
+ }
+
+ void rankTaskLayersIfNeeded() {
+ if (!mTaskLayersChanged) {
+ return;
+ }
+ mTaskLayersChanged = false;
+ mTmpTaskLayerRank = 0;
+ final PooledConsumer c = PooledLambda.obtainConsumer(
+ RootWindowContainer::rankTaskLayerForActivity, this,
+ PooledLambda.__(ActivityRecord.class));
+ forAllActivities(c);
+ c.recycle();
+ }
+
+ private void rankTaskLayerForActivity(ActivityRecord r) {
+ if (r.canBeTopRunning() && r.mVisibleRequested) {
+ r.getTask().mLayerRank = ++mTmpTaskLayerRank;
+ } else {
+ r.getTask().mLayerRank = -1;
+ }
+ }
+
+ void clearOtherAppTimeTrackers(AppTimeTracker except) {
+ final PooledConsumer c = PooledLambda.obtainConsumer(
+ RootWindowContainer::clearOtherAppTimeTrackers,
+ PooledLambda.__(ActivityRecord.class), except);
+ forAllActivities(c);
+ c.recycle();
+ }
+
+ private static void clearOtherAppTimeTrackers(ActivityRecord r, AppTimeTracker except) {
+ if (r.appTimeTracker != except) {
+ r.appTimeTracker = null;
+ }
+ }
+
+ void scheduleDestroyAllActivities(String reason) {
+ mDestroyAllActivitiesReason = reason;
+ mService.mH.post(mDestroyAllActivitiesRunnable);
+ }
+
+ private void destroyActivity(ActivityRecord r) {
+ if (r.finishing || !r.isDestroyable()) return;
+
+ if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Destroying " + r + " in state " + r.getState()
+ + " resumed=" + r.getStack().mResumedActivity + " pausing="
+ + r.getStack().mPausingActivity + " for reason " + mDestroyAllActivitiesReason);
+
+ r.destroyImmediately(true /* removeFromTask */, mDestroyAllActivitiesReason);
+ }
+
+ // Tries to put all activity stacks to sleep. Returns true if all stacks were
+ // successfully put to sleep.
+ boolean putStacksToSleep(boolean allowDelay, boolean shuttingDown) {
+ boolean allSleep = true;
+ for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
+ final DisplayContent display = getChildAt(displayNdx);
+ for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+ // Stacks and activities could be removed while putting activities to sleep if
+ // the app process was gone. This prevents us getting exception by accessing an
+ // invalid stack index.
+ if (stackNdx >= display.getStackCount()) {
+ continue;
+ }
+
+ final ActivityStack stack = display.getStackAt(stackNdx);
+ if (allowDelay) {
+ allSleep &= stack.goToSleepIfPossible(shuttingDown);
+ } else {
+ stack.goToSleep();
+ }
+ }
+ }
+ return allSleep;
+ }
+
+ void handleAppCrash(WindowProcessController app) {
+ final PooledConsumer c = PooledLambda.obtainConsumer(
+ RootWindowContainer::handleAppCrash, PooledLambda.__(ActivityRecord.class), app);
+ forAllActivities(c);
+ c.recycle();
+ }
+
+ private static void handleAppCrash(ActivityRecord r, WindowProcessController app) {
+ if (r.app != app) return;
+ Slog.w(TAG, " Force finishing activity "
+ + r.intent.getComponent().flattenToShortString());
+ r.app = null;
+ r.getDisplay().mDisplayContent.prepareAppTransition(
+ TRANSIT_CRASHING_ACTIVITY_CLOSE, false /* alwaysKeepCurrent */);
+ r.destroyIfPossible("handleAppCrashed");
+ }
+
+ ActivityRecord findActivity(Intent intent, ActivityInfo info, boolean compareIntentFilters) {
+ ComponentName cls = intent.getComponent();
+ if (info.targetActivity != null) {
+ cls = new ComponentName(info.packageName, info.targetActivity);
+ }
+ final int userId = UserHandle.getUserId(info.applicationInfo.uid);
+
+ final PooledPredicate p = PooledLambda.obtainPredicate(
+ RootWindowContainer::matchesActivity, PooledLambda.__(ActivityRecord.class),
+ userId, compareIntentFilters, intent, cls);
+ final ActivityRecord r = getActivity(p);
+ p.recycle();
+ return r;
+ }
+
+ private static boolean matchesActivity(ActivityRecord r, int userId,
+ boolean compareIntentFilters, Intent intent, ComponentName cls) {
+ if (!r.canBeTopRunning() || r.mUserId != userId) return false;
+
+ if (compareIntentFilters) {
+ if (r.intent.filterEquals(intent)) {
+ return true;
+ }
+ } else {
+ if (r.intent.getComponent().equals(cls)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ boolean hasAwakeDisplay() {
+ for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
+ final DisplayContent display = getChildAt(displayNdx);
+ if (!display.shouldSleep()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ ActivityStack getLaunchStack(@Nullable ActivityRecord r,
+ @Nullable ActivityOptions options, @Nullable Task candidateTask, boolean onTop) {
+ return getLaunchStack(r, options, candidateTask, onTop, null /* launchParams */,
+ -1 /* no realCallingPid */, -1 /* no realCallingUid */);
+ }
+
+ /**
+ * Returns the right stack to use for launching factoring in all the input parameters.
+ *
+ * @param r The activity we are trying to launch. Can be null.
+ * @param options The activity options used to the launch. Can be null.
+ * @param candidateTask The possible task the activity might be launched in. Can be null.
+ * @param launchParams The resolved launch params to use.
+ * @param realCallingPid The pid from {@link ActivityStarter#setRealCallingPid}
+ * @param realCallingUid The uid from {@link ActivityStarter#setRealCallingUid}
+ *
+ * @return The stack to use for the launch or INVALID_STACK_ID.
+ */
+ ActivityStack getLaunchStack(@Nullable ActivityRecord r,
+ @Nullable ActivityOptions options, @Nullable Task candidateTask, boolean onTop,
+ @Nullable LaunchParamsController.LaunchParams launchParams, int realCallingPid,
+ int realCallingUid) {
+ int taskId = INVALID_TASK_ID;
+ int displayId = INVALID_DISPLAY;
+ //Rect bounds = null;
+
+ // We give preference to the launch preference in activity options.
+ if (options != null) {
+ taskId = options.getLaunchTaskId();
+ displayId = options.getLaunchDisplayId();
+ }
+
+ // First preference for stack goes to the task Id set in the activity options. Use the stack
+ // associated with that if possible.
+ if (taskId != INVALID_TASK_ID) {
+ // Temporarily set the task id to invalid in case in re-entry.
+ options.setLaunchTaskId(INVALID_TASK_ID);
+ final Task task = anyTaskForId(taskId,
+ MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE, options, onTop);
+ options.setLaunchTaskId(taskId);
+ if (task != null) {
+ return task.getStack();
+ }
+ }
+
+ final int activityType = resolveActivityType(r, options, candidateTask);
+ ActivityStack stack;
+
+ // Next preference for stack goes to the display Id set the candidate display.
+ if (launchParams != null && launchParams.mPreferredDisplayId != INVALID_DISPLAY) {
+ displayId = launchParams.mPreferredDisplayId;
+ }
+ final boolean canLaunchOnDisplayFromStartRequest =
+ realCallingPid != 0 && realCallingUid > 0 && r != null
+ && mStackSupervisor.canPlaceEntityOnDisplay(displayId, realCallingPid,
+ realCallingUid, r.info);
+ // Checking if the activity's launch caller, or the realCallerId of the activity from
+ // start request (i.e. entity that invokes PendingIntent) is allowed to launch on the
+ // display.
+ if (displayId != INVALID_DISPLAY && (canLaunchOnDisplay(r, displayId)
+ || canLaunchOnDisplayFromStartRequest)) {
+ if (r != null) {
+ stack = getValidLaunchStackOnDisplay(displayId, r, candidateTask, options,
+ launchParams);
+ if (stack != null) {
+ return stack;
+ }
+ }
+ final DisplayContent display = getDisplayContentOrCreate(displayId);
+ if (display != null) {
+ stack = display.getOrCreateStack(r, options, candidateTask, activityType, onTop);
+ if (stack != null) {
+ return stack;
+ }
+ }
+ }
+
+ // Give preference to the stack and display of the input task and activity if they match the
+ // mode we want to launch into.
+ stack = null;
+ DisplayContent display = null;
+ if (candidateTask != null) {
+ stack = candidateTask.getStack();
+ }
+ if (stack == null && r != null) {
+ stack = r.getActivityStack();
+ }
+ if (stack != null) {
+ display = stack.getDisplay();
+ if (display != null && canLaunchOnDisplay(r, display.mDisplayId)) {
+ int windowingMode = launchParams != null ? launchParams.mWindowingMode
+ : WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+ if (windowingMode == WindowConfiguration.WINDOWING_MODE_UNDEFINED) {
+ windowingMode = display.resolveWindowingMode(r, options, candidateTask,
+ activityType);
+ }
+ if (stack.isCompatible(windowingMode, activityType)) {
+ return stack;
+ }
+ if (windowingMode == WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY
+ && display.getSplitScreenPrimaryStack() == stack
+ && candidateTask == stack.getTopMostTask()) {
+ // This is a special case when we try to launch an activity that is currently on
+ // top of split-screen primary stack, but is targeting split-screen secondary.
+ // In this case we don't want to move it to another stack.
+ // TODO(b/78788972): Remove after differentiating between preferred and required
+ // launch options.
+ return stack;
+ }
+ }
+ }
+
+ if (display == null || !canLaunchOnDisplay(r, display.mDisplayId)) {
+ display = getDefaultDisplay();
+ }
+
+ return display.getOrCreateStack(r, options, candidateTask, activityType, onTop);
+ }
+
+ /** @return true if activity record is null or can be launched on provided display. */
+ private boolean canLaunchOnDisplay(ActivityRecord r, int displayId) {
+ if (r == null) {
+ return true;
+ }
+ return r.canBeLaunchedOnDisplay(displayId);
+ }
+
+ /**
+ * Get a topmost stack on the display, that is a valid launch stack for specified activity.
+ * If there is no such stack, new dynamic stack can be created.
+ * @param displayId Target display.
+ * @param r Activity that should be launched there.
+ * @param candidateTask The possible task the activity might be put in.
+ * @return Existing stack if there is a valid one, new dynamic stack if it is valid or null.
+ */
+ private ActivityStack getValidLaunchStackOnDisplay(int displayId, @NonNull ActivityRecord r,
+ @Nullable Task candidateTask, @Nullable ActivityOptions options,
+ @Nullable LaunchParamsController.LaunchParams launchParams) {
+ final DisplayContent displayContent = getDisplayContentOrCreate(displayId);
+ if (displayContent == null) {
+ throw new IllegalArgumentException(
+ "Display with displayId=" + displayId + " not found.");
+ }
+
+ if (!r.canBeLaunchedOnDisplay(displayId)) {
+ return null;
+ }
+
+ // If {@code r} is already in target display and its task is the same as the candidate task,
+ // the intention should be getting a launch stack for the reusable activity, so we can use
+ // the existing stack.
+ if (candidateTask != null && (r.getTask() == null || r.getTask() == candidateTask)) {
+ final int attachedDisplayId = r.getDisplayId();
+ if (attachedDisplayId == INVALID_DISPLAY || attachedDisplayId == displayId) {
+ return candidateTask.getStack();
+ }
+ }
+
+ int windowingMode;
+ if (launchParams != null) {
+ // When launch params is not null, we always defer to its windowing mode. Sometimes
+ // it could be unspecified, which indicates it should inherit windowing mode from
+ // display.
+ windowingMode = launchParams.mWindowingMode;
+ } else {
+ windowingMode = options != null ? options.getLaunchWindowingMode()
+ : r.getWindowingMode();
+ }
+ windowingMode = displayContent.validateWindowingMode(windowingMode, r, candidateTask,
+ r.getActivityType());
+
+ // Return the topmost valid stack on the display.
+ for (int i = displayContent.getStackCount() - 1; i >= 0; --i) {
+ final ActivityStack stack = displayContent.getStackAt(i);
+ if (isValidLaunchStack(stack, r, windowingMode)) {
+ return stack;
+ }
+ }
+
+ // If there is no valid stack on the external display - check if new dynamic stack will do.
+ if (displayId != DEFAULT_DISPLAY) {
+ final int activityType =
+ options != null && options.getLaunchActivityType() != ACTIVITY_TYPE_UNDEFINED
+ ? options.getLaunchActivityType() : r.getActivityType();
+ return displayContent.createStack(windowingMode, activityType, true /*onTop*/);
+ }
+
+ return null;
+ }
+
+ ActivityStack getValidLaunchStackOnDisplay(int displayId, @NonNull ActivityRecord r,
+ @Nullable ActivityOptions options,
+ @Nullable LaunchParamsController.LaunchParams launchParams) {
+ return getValidLaunchStackOnDisplay(displayId, r, null /* candidateTask */, options,
+ launchParams);
+ }
+
+ // TODO: Can probably be consolidated into getLaunchStack()...
+ private boolean isValidLaunchStack(ActivityStack stack, ActivityRecord r, int windowingMode) {
+ switch (stack.getActivityType()) {
+ case ACTIVITY_TYPE_HOME: return r.isActivityTypeHome();
+ case ACTIVITY_TYPE_RECENTS: return r.isActivityTypeRecents();
+ case ACTIVITY_TYPE_ASSISTANT: return r.isActivityTypeAssistant();
+ }
+ // There is a 1-to-1 relationship between stack and task when not in
+ // primary split-windowing mode.
+ if (stack.getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
+ && r.supportsSplitScreenWindowingMode()
+ && (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
+ || windowingMode == WINDOWING_MODE_UNDEFINED)) {
+ return true;
+ }
+ return false;
+ }
+
+ int resolveActivityType(@Nullable ActivityRecord r, @Nullable ActivityOptions options,
+ @Nullable Task task) {
+ // Preference is given to the activity type for the activity then the task since the type
+ // once set shouldn't change.
+ int activityType = r != null ? r.getActivityType() : ACTIVITY_TYPE_UNDEFINED;
+ if (activityType == ACTIVITY_TYPE_UNDEFINED && task != null) {
+ activityType = task.getActivityType();
+ }
+ if (activityType != ACTIVITY_TYPE_UNDEFINED) {
+ return activityType;
+ }
+ if (options != null) {
+ activityType = options.getLaunchActivityType();
+ }
+ return activityType != ACTIVITY_TYPE_UNDEFINED ? activityType : ACTIVITY_TYPE_STANDARD;
+ }
+
+ /**
+ * Get next focusable stack in the system. This will search through the stack on the same
+ * display as the current focused stack, looking for a focusable and visible stack, different
+ * from the target stack. If no valid candidates will be found, it will then go through all
+ * displays and stacks in last-focused order.
+ *
+ * @param currentFocus The stack that previously had focus.
+ * @param ignoreCurrent If we should ignore {@param currentFocus} when searching for next
+ * candidate.
+ * @return Next focusable {@link ActivityStack}, {@code null} if not found.
+ */
+ ActivityStack getNextFocusableStack(@NonNull ActivityStack currentFocus,
+ boolean ignoreCurrent) {
+ // First look for next focusable stack on the same display
+ DisplayContent preferredDisplay = currentFocus.getDisplay();
+ if (preferredDisplay == null) {
+ // Stack is currently detached because it is being removed. Use the previous display it
+ // was on.
+ preferredDisplay = getDisplayContent(currentFocus.mPrevDisplayId);
+ }
+ final ActivityStack preferredFocusableStack = preferredDisplay.getNextFocusableStack(
+ currentFocus, ignoreCurrent);
+ if (preferredFocusableStack != null) {
+ return preferredFocusableStack;
+ }
+ if (preferredDisplay.supportsSystemDecorations()) {
+ // Stop looking for focusable stack on other displays because the preferred display
+ // supports system decorations. Home activity would be launched on the same display if
+ // no focusable stack found.
+ return null;
+ }
+
+ // Now look through all displays
+ for (int i = getChildCount() - 1; i >= 0; --i) {
+ final DisplayContent display = getChildAt(i);
+ if (display == preferredDisplay) {
+ // We've already checked this one
+ continue;
+ }
+ final ActivityStack nextFocusableStack = display.getNextFocusableStack(currentFocus,
+ ignoreCurrent);
+ if (nextFocusableStack != null) {
+ return nextFocusableStack;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Get next valid stack for launching provided activity in the system. This will search across
+ * displays and stacks in last-focused order for a focusable and visible stack, except those
+ * that are on a currently focused display.
+ *
+ * @param r The activity that is being launched.
+ * @param currentFocus The display that previously had focus and thus needs to be ignored when
+ * searching for the next candidate.
+ * @return Next valid {@link ActivityStack}, null if not found.
+ */
+ ActivityStack getNextValidLaunchStack(@NonNull ActivityRecord r, int currentFocus) {
+ for (int i = getChildCount() - 1; i >= 0; --i) {
+ final DisplayContent display = getChildAt(i);
+ if (display.mDisplayId == currentFocus) {
+ continue;
+ }
+ final ActivityStack stack = getValidLaunchStackOnDisplay(display.mDisplayId, r,
+ null /* options */, null /* launchParams */);
+ if (stack != null) {
+ return stack;
+ }
+ }
+ return null;
+ }
+
+ boolean handleAppDied(WindowProcessController app) {
+ boolean hasVisibleActivities = false;
+ for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
+ final DisplayContent display = getChildAt(displayNdx);
+ for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getStackAt(stackNdx);
+ hasVisibleActivities |= stack.handleAppDied(app);
+ }
+ }
+ return hasVisibleActivities;
+ }
+
+ void closeSystemDialogs() {
+ forAllActivities((r) -> {
+ if ((r.info.flags & ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
+ r.finishIfPossible("close-sys", true /* oomAdj */);
+ }
+ });
+ }
+
+ FinishDisabledPackageActivitiesHelper mFinishDisabledPackageActivitiesHelper =
+ new FinishDisabledPackageActivitiesHelper();
+ class FinishDisabledPackageActivitiesHelper {
+ private boolean mDidSomething;
+ private String mPackageName;
+ private Set<String> mFilterByClasses;
+ private boolean mDoit;
+ private boolean mEvenPersistent;
+ private int mUserId;
+ private Task mLastTask;
+ private ComponentName mHomeActivity;
+
+ private void reset(String packageName, Set<String> filterByClasses,
+ boolean doit, boolean evenPersistent, int userId) {
+ mDidSomething = false;
+ mPackageName = packageName;
+ mFilterByClasses = filterByClasses;
+ mDoit = doit;
+ mEvenPersistent = evenPersistent;
+ mUserId = userId;
+ mLastTask = null;
+ mHomeActivity = null;
+ }
+
+ boolean process(String packageName, Set<String> filterByClasses,
+ boolean doit, boolean evenPersistent, int userId) {
+ reset(packageName, filterByClasses, doit, evenPersistent, userId);
+
+ final PooledFunction f = PooledLambda.obtainFunction(
+ FinishDisabledPackageActivitiesHelper::processActivity, this,
+ PooledLambda.__(ActivityRecord.class));
+ forAllActivities(f);
+ f.recycle();
+ return mDidSomething;
+ }
+
+ private boolean processActivity(ActivityRecord r) {
+ final boolean sameComponent =
+ (r.packageName.equals(mPackageName) && (mFilterByClasses == null
+ || mFilterByClasses.contains(r.mActivityComponent.getClassName())))
+ || (mPackageName == null && r.mUserId == mUserId);
+ if ((mUserId == UserHandle.USER_ALL || r.mUserId == mUserId)
+ && (sameComponent || r.getTask() == mLastTask)
+ && (r.app == null || mEvenPersistent || !r.app.isPersistent())) {
+ if (!mDoit) {
+ if (r.finishing) {
+ // If this activity is just finishing, then it is not
+ // interesting as far as something to stop.
+ return false;
+ }
+ return true;
+ }
+ if (r.isActivityTypeHome()) {
+ if (mHomeActivity != null && mHomeActivity.equals(r.mActivityComponent)) {
+ Slog.i(TAG, "Skip force-stop again " + r);
+ return false;
+ } else {
+ mHomeActivity = r.mActivityComponent;
+ }
+ }
+ mDidSomething = true;
+ Slog.i(TAG, " Force finishing activity " + r);
+ mLastTask = r.getTask();
+ r.finishIfPossible("force-stop", true);
+ }
+
+ return false;
+ }
+ }
+
+ /** @return true if some activity was finished (or would have finished if doit were true). */
+ boolean finishDisabledPackageActivities(String packageName, Set<String> filterByClasses,
+ boolean doit, boolean evenPersistent, int userId) {
+ return mFinishDisabledPackageActivitiesHelper.process(packageName, filterByClasses, doit,
+ evenPersistent, userId);
+ }
+
+ void updateActivityApplicationInfo(ApplicationInfo aInfo) {
+ final String packageName = aInfo.packageName;
+ final int userId = UserHandle.getUserId(aInfo.uid);
+ final PooledConsumer c = PooledLambda.obtainConsumer(
+ RootWindowContainer::updateActivityApplicationInfo,
+ PooledLambda.__(ActivityRecord.class), aInfo, userId, packageName);
+ forAllActivities(c);
+ c.recycle();
+ }
+
+ private static void updateActivityApplicationInfo(
+ ActivityRecord r, ApplicationInfo aInfo, int userId, String packageName) {
+ if (r.mUserId == userId && packageName.equals(r.packageName)) {
+ r.updateApplicationInfo(aInfo);
+ }
+ }
+
+ void finishVoiceTask(IVoiceInteractionSession session) {
+ for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
+ final DisplayContent display = getChildAt(displayNdx);
+ final int numStacks = display.getStackCount();
+ for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
+ final ActivityStack stack = display.getStackAt(stackNdx);
+ stack.finishVoiceTask(session);
+ }
+ }
+ }
+
+ /**
+ * Removes stacks in the input windowing modes from the system if they are of activity type
+ * ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED
+ */
+ void removeStacksInWindowingModes(int... windowingModes) {
+ for (int i = getChildCount() - 1; i >= 0; --i) {
+ getChildAt(i).removeStacksInWindowingModes(windowingModes);
+ }
+ }
+
+ void removeStacksWithActivityTypes(int... activityTypes) {
+ for (int i = getChildCount() - 1; i >= 0; --i) {
+ getChildAt(i).removeStacksWithActivityTypes(activityTypes);
+ }
+ }
+
+ ActivityRecord topRunningActivity() {
+ for (int i = getChildCount() - 1; i >= 0; --i) {
+ final ActivityRecord topActivity = getChildAt(i).topRunningActivity();
+ if (topActivity != null) {
+ return topActivity;
+ }
+ }
+ return null;
+ }
+
+ boolean allResumedActivitiesIdle() {
+ for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
+ // TODO(b/117135575): Check resumed activities on all visible stacks.
+ final DisplayContent display = getChildAt(displayNdx);
+ if (display.isSleeping()) {
+ // No resumed activities while display is sleeping.
+ continue;
+ }
+
+ // If the focused stack is not null or not empty, there should have some activities
+ // resuming or resumed. Make sure these activities are idle.
+ final ActivityStack stack = display.getFocusedStack();
+ if (stack == null || !stack.hasActivity()) {
+ continue;
+ }
+ final ActivityRecord resumedActivity = stack.getResumedActivity();
+ if (resumedActivity == null || !resumedActivity.idle) {
+ if (DEBUG_STATES) {
+ Slog.d(TAG_STATES, "allResumedActivitiesIdle: stack="
+ + stack.mStackId + " " + resumedActivity + " not idle");
+ }
+ return false;
+ }
+ }
+ // Send launch end powerhint when idle
+ sendPowerHintForLaunchEndIfNeeded();
+ return true;
+ }
+
+ boolean allResumedActivitiesVisible() {
+ boolean foundResumed = false;
+ for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
+ final DisplayContent display = getChildAt(displayNdx);
+ for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getStackAt(stackNdx);
+ final ActivityRecord r = stack.getResumedActivity();
+ if (r != null) {
+ if (!r.nowVisible) {
+ return false;
+ }
+ foundResumed = true;
+ }
+ }
+ }
+ return foundResumed;
+ }
+
+ boolean allPausedActivitiesComplete() {
+ boolean pausing = true;
+ for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
+ final DisplayContent display = getChildAt(displayNdx);
+ for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getStackAt(stackNdx);
+ final ActivityRecord r = stack.mPausingActivity;
+ if (r != null && !r.isState(PAUSED, STOPPED, STOPPING)) {
+ if (DEBUG_STATES) {
+ Slog.d(TAG_STATES,
+ "allPausedActivitiesComplete: r=" + r + " state=" + r.getState());
+ pausing = false;
+ } else {
+ return false;
+ }
+ }
+ }
+ }
+ return pausing;
+ }
+
+ /**
+ * Find all visible task stacks containing {@param userId} and intercept them with an activity
+ * to block out the contents and possibly start a credential-confirming intent.
+ *
+ * @param userId user handle for the locked managed profile.
+ */
+ void lockAllProfileTasks(@UserIdInt int userId) {
+ mService.deferWindowLayout();
+ try {
+ final PooledConsumer c = PooledLambda.obtainConsumer(
+ RootWindowContainer::taskTopActivityIsUser, this, PooledLambda.__(Task.class),
+ userId);
+ forAllTasks(c);
+ c.recycle();
+ } finally {
+ mService.continueWindowLayout();
+ }
+ }
+
+ /**
+ * Detects whether we should show a lock screen in front of this task for a locked user.
+ * <p>
+ * We'll do this if either of the following holds:
+ * <ul>
+ * <li>The top activity explicitly belongs to {@param userId}.</li>
+ * <li>The top activity returns a result to an activity belonging to {@param userId}.</li>
+ * </ul>
+ *
+ * @return {@code true} if the top activity looks like it belongs to {@param userId}.
+ */
+ private void taskTopActivityIsUser(Task task, @UserIdInt int userId) {
+ // To handle the case that work app is in the task but just is not the top one.
+ final ActivityRecord activityRecord = task.getTopNonFinishingActivity();
+ final ActivityRecord resultTo = (activityRecord != null ? activityRecord.resultTo : null);
+
+ // Check the task for a top activity belonging to userId, or returning a
+ // result to an activity belonging to userId. Example case: a document
+ // picker for personal files, opened by a work app, should still get locked.
+ if ((activityRecord != null && activityRecord.mUserId == userId)
+ || (resultTo != null && resultTo.mUserId == userId)) {
+ mService.getTaskChangeNotificationController().notifyTaskProfileLocked(
+ task.mTaskId, userId);
+ }
+ }
+
+ void cancelInitializingActivities() {
+ for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
+ final DisplayContent display = getChildAt(displayNdx);
+ for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getStackAt(stackNdx);
+ stack.cancelInitializingActivities();
+ }
+ }
+ }
+
+ Task anyTaskForId(int id) {
+ return anyTaskForId(id, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE);
+ }
+
+ Task anyTaskForId(int id, @RootWindowContainer.AnyTaskForIdMatchTaskMode int matchMode) {
+ return anyTaskForId(id, matchMode, null, !ON_TOP);
+ }
+
+ /**
+ * Returns a {@link Task} for the input id if available. {@code null} otherwise.
+ * @param id Id of the task we would like returned.
+ * @param matchMode The mode to match the given task id in.
+ * @param aOptions The activity options to use for restoration. Can be null.
+ * @param onTop If the stack for the task should be the topmost on the display.
+ */
+ Task anyTaskForId(int id, @RootWindowContainer.AnyTaskForIdMatchTaskMode int matchMode,
+ @Nullable ActivityOptions aOptions, boolean onTop) {
+ // If options are set, ensure that we are attempting to actually restore a task
+ if (matchMode != MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE && aOptions != null) {
+ throw new IllegalArgumentException("Should not specify activity options for non-restore"
+ + " lookup");
+ }
+
+ final PooledPredicate p = PooledLambda.obtainPredicate(
+ Task::isTaskId, PooledLambda.__(Task.class), id);
+ Task task = getTask(p);
+ p.recycle();
+
+ if (task != null) {
+ if (aOptions != null) {
+ // Resolve the stack the task should be placed in now based on options
+ // and reparent if needed.
+ final ActivityStack launchStack =
+ getLaunchStack(null, aOptions, task, onTop);
+ if (launchStack != null && task.getStack() != launchStack) {
+ final int reparentMode = onTop
+ ? REPARENT_MOVE_STACK_TO_FRONT : REPARENT_LEAVE_STACK_IN_PLACE;
+ task.reparent(launchStack, onTop, reparentMode, ANIMATE, DEFER_RESUME,
+ "anyTaskForId");
+ }
+ }
+ return task;
+ }
+
+ // If we are matching stack tasks only, return now
+ if (matchMode == MATCH_TASK_IN_STACKS_ONLY) {
+ return null;
+ }
+
+ // Otherwise, check the recent tasks and return if we find it there and we are not restoring
+ // the task from recents
+ if (DEBUG_RECENTS) Slog.v(TAG_RECENTS, "Looking for task id=" + id + " in recents");
+ task = mStackSupervisor.mRecentTasks.getTask(id);
+
+ if (task == null) {
+ if (DEBUG_RECENTS) {
+ Slog.d(TAG_RECENTS, "\tDidn't find task id=" + id + " in recents");
+ }
+
+ return null;
+ }
+
+ if (matchMode == MATCH_TASK_IN_STACKS_OR_RECENT_TASKS) {
+ return task;
+ }
+
+ // Implicitly, this case is MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE
+ if (!mStackSupervisor.restoreRecentTaskLocked(task, aOptions, onTop)) {
+ if (DEBUG_RECENTS) Slog.w(TAG_RECENTS,
+ "Couldn't restore task id=" + id + " found in recents");
+ return null;
+ }
+ if (DEBUG_RECENTS) Slog.w(TAG_RECENTS, "Restored task id=" + id + " from in recents");
+ return task;
+ }
+
+ ActivityRecord isInAnyStack(IBinder token) {
+ int numDisplays = getChildCount();
+ for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
+ final DisplayContent display = getChildAt(displayNdx);
+ for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getStackAt(stackNdx);
+ final ActivityRecord r = stack.isInStackLocked(token);
+ if (r != null) {
+ return r;
+ }
+ }
+ }
+ return null;
+ }
+
+ @VisibleForTesting
+ void getRunningTasks(int maxNum, List<ActivityManager.RunningTaskInfo> list,
+ @WindowConfiguration.ActivityType int ignoreActivityType,
+ @WindowConfiguration.WindowingMode int ignoreWindowingMode, int callingUid,
+ boolean allowed, boolean crossUser, ArraySet<Integer> profileIds) {
+ mStackSupervisor.getRunningTasks().getTasks(maxNum, list, ignoreActivityType,
+ ignoreWindowingMode, this, callingUid, allowed, crossUser, profileIds);
+ }
+
+ void sendPowerHintForLaunchStartIfNeeded(boolean forceSend, ActivityRecord targetActivity) {
+ boolean sendHint = forceSend;
+
+ if (!sendHint) {
+ // Send power hint if we don't know what we're launching yet
+ sendHint = targetActivity == null || targetActivity.app == null;
+ }
+
+ if (!sendHint) { // targetActivity != null
+ // Send power hint when the activity's process is different than the current resumed
+ // activity on all displays, or if there are no resumed activities in the system.
+ boolean noResumedActivities = true;
+ boolean allFocusedProcessesDiffer = true;
+ for (int displayNdx = 0; displayNdx < getChildCount(); ++displayNdx) {
+ final DisplayContent displayContent = getChildAt(displayNdx);
+ final ActivityRecord resumedActivity = displayContent.getResumedActivity();
+ final WindowProcessController resumedActivityProcess =
+ resumedActivity == null ? null : resumedActivity.app;
+
+ noResumedActivities &= resumedActivityProcess == null;
+ if (resumedActivityProcess != null) {
+ allFocusedProcessesDiffer &= !resumedActivityProcess.equals(targetActivity.app);
+ }
+ }
+ sendHint = noResumedActivities || allFocusedProcessesDiffer;
+ }
+
+ if (sendHint && mService.mPowerManagerInternal != null) {
+ mService.mPowerManagerInternal.powerHint(PowerHint.LAUNCH, 1);
+ mPowerHintSent = true;
+ }
+ }
+
+ void sendPowerHintForLaunchEndIfNeeded() {
+ // Trigger launch power hint if activity is launched
+ if (mPowerHintSent && mService.mPowerManagerInternal != null) {
+ mService.mPowerManagerInternal.powerHint(PowerHint.LAUNCH, 0);
+ mPowerHintSent = false;
+ }
+ }
+
+ private void calculateDefaultMinimalSizeOfResizeableTasks() {
+ final Resources res = mService.mContext.getResources();
+ final float minimalSize = res.getDimension(
+ com.android.internal.R.dimen.default_minimal_size_resizable_task);
+ final DisplayMetrics dm = res.getDisplayMetrics();
+
+ mDefaultMinSizeOfResizeableTaskDp = (int) (minimalSize / dm.density);
+ }
+
+ /**
+ * Dumps the activities matching the given {@param name} in the either the focused stack
+ * or all visible stacks if {@param dumpVisibleStacks} is true.
+ */
+ ArrayList<ActivityRecord> getDumpActivities(String name, boolean dumpVisibleStacksOnly,
+ boolean dumpFocusedStackOnly) {
+ if (dumpFocusedStackOnly) {
+ return getTopDisplayFocusedStack().getDumpActivitiesLocked(name);
+ } else {
+ ArrayList<ActivityRecord> activities = new ArrayList<>();
+ int numDisplays = getChildCount();
+ for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
+ final DisplayContent display = getChildAt(displayNdx);
+ for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getStackAt(stackNdx);
+ if (!dumpVisibleStacksOnly || stack.shouldBeVisible(null)) {
+ activities.addAll(stack.getDumpActivitiesLocked(name));
+ }
+ }
+ }
+ return activities;
+ }
+ }
+
+ public void dump(PrintWriter pw, String prefix) {
+ pw.print(prefix);
+ pw.println("topDisplayFocusedStack=" + getTopDisplayFocusedStack());
+ for (int i = getChildCount() - 1; i >= 0; --i) {
+ final DisplayContent display = getChildAt(i);
+ display.dump(pw, prefix, true /* dumpAll */);
+ }
+ }
+
+ /**
+ * Dump all connected displays' configurations.
+ * @param prefix Prefix to apply to each line of the dump.
+ */
+ void dumpDisplayConfigs(PrintWriter pw, String prefix) {
+ pw.print(prefix); pw.println("Display override configurations:");
+ final int displayCount = getChildCount();
+ for (int i = 0; i < displayCount; i++) {
+ final DisplayContent displayContent = getChildAt(i);
+ pw.print(prefix); pw.print(" "); pw.print(displayContent.mDisplayId); pw.print(": ");
+ pw.println(displayContent.getRequestedOverrideConfiguration());
+ }
+ }
+
+ public void dumpDisplays(PrintWriter pw) {
+ for (int i = getChildCount() - 1; i >= 0; --i) {
+ final DisplayContent display = getChildAt(i);
+ pw.print("[id:" + display.mDisplayId + " stacks:");
+ display.dumpStacks(pw);
+ pw.print("]");
+ }
+ }
+
+ boolean dumpActivities(FileDescriptor fd, PrintWriter pw, boolean dumpAll, boolean dumpClient,
+ String dumpPackage) {
+ boolean printed = false;
+ boolean needSep = false;
+ for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
+ DisplayContent displayContent = getChildAt(displayNdx);
+ pw.print("Display #"); pw.print(displayContent.mDisplayId);
+ pw.println(" (activities from top to bottom):");
+ for (int stackNdx = displayContent.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = displayContent.getStackAt(stackNdx);
+ pw.println();
+ printed = stack.dump(fd, pw, dumpAll, dumpClient, dumpPackage, needSep);
+ needSep = printed;
+ }
+ printThisActivity(pw, displayContent.getResumedActivity(), dumpPackage, needSep,
+ " ResumedActivity:");
+ }
+
+ printed |= dumpHistoryList(fd, pw, mStackSupervisor.mFinishingActivities, " ",
+ "Fin", false, !dumpAll,
+ false, dumpPackage, true, " Activities waiting to finish:", null);
+ printed |= dumpHistoryList(fd, pw, mStackSupervisor.mStoppingActivities, " ",
+ "Stop", false, !dumpAll,
+ false, dumpPackage, true, " Activities waiting to stop:", null);
+ printed |= dumpHistoryList(fd, pw, mStackSupervisor.mGoingToSleepActivities,
+ " ", "Sleep", false, !dumpAll,
+ false, dumpPackage, true, " Activities waiting to sleep:", null);
+
+ return printed;
+ }
+
+ @Override
+ public void dumpDebug(ProtoOutputStream proto, long fieldId,
+ @WindowTraceLogLevel int logLevel) {
+ final long token = proto.start(fieldId);
+ dumpDebugInner(proto, ROOT_WINDOW_CONTAINER, logLevel);
+ for (int displayNdx = 0; displayNdx < getChildCount(); ++displayNdx) {
+ final DisplayContent displayContent = getChildAt(displayNdx);
+ displayContent.dumpDebug(proto,
+ com.android.server.am.ActivityStackSupervisorProto.DISPLAYS, logLevel);
+ }
+ mStackSupervisor.getKeyguardController().dumpDebug(proto, KEYGUARD_CONTROLLER);
+ // TODO(b/111541062): Update tests to look for resumed activities on all displays
+ final ActivityStack focusedStack = getTopDisplayFocusedStack();
+ if (focusedStack != null) {
+ proto.write(FOCUSED_STACK_ID, focusedStack.mStackId);
+ final ActivityRecord focusedActivity = focusedStack.getDisplay().getResumedActivity();
+ if (focusedActivity != null) {
+ focusedActivity.writeIdentifierToProto(proto, RESUMED_ACTIVITY);
+ }
+ } else {
+ proto.write(FOCUSED_STACK_ID, INVALID_STACK_ID);
+ }
+ proto.write(IS_HOME_RECENTS_COMPONENT,
+ mStackSupervisor.mRecentTasks.isRecentsComponentHomeActivity(mCurrentUser));
+ mService.getActivityStartController().dumpDebug(proto, PENDING_ACTIVITIES);
+ proto.end(token);
+ }
+
+ private final class SleepTokenImpl extends ActivityTaskManagerInternal.SleepToken {
+ private final String mTag;
+ private final long mAcquireTime;
+ private final int mDisplayId;
+
+ public SleepTokenImpl(String tag, int displayId) {
+ mTag = tag;
+ mDisplayId = displayId;
+ mAcquireTime = SystemClock.uptimeMillis();
+ }
+
+ @Override
+ public void release() {
+ synchronized (mService.mGlobalLock) {
+ removeSleepToken(this);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "{\"" + mTag + "\", display " + mDisplayId
+ + ", acquire at " + TimeUtils.formatUptime(mAcquireTime) + "}";
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/RunningTasks.java b/services/core/java/com/android/server/wm/RunningTasks.java
index 5783713b17b1..98127ab2eec8 100644
--- a/services/core/java/com/android/server/wm/RunningTasks.java
+++ b/services/core/java/com/android/server/wm/RunningTasks.java
@@ -56,7 +56,7 @@ class RunningTasks {
private ActivityStack mTopDisplayFocusStack;
void getTasks(int maxNum, List<RunningTaskInfo> list, @ActivityType int ignoreActivityType,
- @WindowingMode int ignoreWindowingMode, RootActivityContainer root,
+ @WindowingMode int ignoreWindowingMode, RootWindowContainer root,
int callingUid, boolean allowed, boolean crossUser, ArraySet<Integer> profileIds) {
// Return early if there are no tasks to fetch
if (maxNum <= 0) {
@@ -76,7 +76,7 @@ class RunningTasks {
final PooledConsumer c = PooledLambda.obtainConsumer(RunningTasks::processTask, this,
PooledLambda.__(Task.class));
- root.mRootWindowContainer.forAllTasks(c, false);
+ root.forAllTasks(c, false);
c.recycle();
// Take the first {@param maxNum} tasks and create running task infos for them
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index a175d63dce80..51986028d39c 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -448,10 +448,10 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
}
@Override
- public void updateTapExcludeRegion(IWindow window, int regionId, Region region) {
+ public void updateTapExcludeRegion(IWindow window, Region region) {
final long identity = Binder.clearCallingIdentity();
try {
- mService.updateTapExcludeRegion(window, regionId, region);
+ mService.updateTapExcludeRegion(window, region);
} finally {
Binder.restoreCallingIdentity(identity);
}
diff --git a/services/core/java/com/android/server/wm/TapExcludeRegionHolder.java b/services/core/java/com/android/server/wm/TapExcludeRegionHolder.java
deleted file mode 100644
index 8f72cdad8dce..000000000000
--- a/services/core/java/com/android/server/wm/TapExcludeRegionHolder.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 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.
- */
-
-package com.android.server.wm;
-
-import android.graphics.Rect;
-import android.graphics.Region;
-import android.util.SparseArray;
-
-/**
- * A holder that contains a collection of regions identified by int id. Each individual region can
- * be updated separately.
- */
-class TapExcludeRegionHolder {
- private SparseArray<Region> mTapExcludeRegions = new SparseArray<>();
-
- /** Update the specified region with provided position and size. */
- void updateRegion(int regionId, Region region) {
- // Remove the previous one because there is a new one incoming.
- mTapExcludeRegions.remove(regionId);
-
- if (region == null || region.isEmpty()) {
- // The incoming region is invalid. Don't use it.
- return;
- }
-
- mTapExcludeRegions.put(regionId, region);
- }
-
- /**
- * Union the provided region with current region formed by this container.
- */
- void amendRegion(Region region, Rect bounds) {
- for (int i = mTapExcludeRegions.size() - 1; i >= 0; --i) {
- final Region r = mTapExcludeRegions.valueAt(i);
- if (bounds != null) {
- r.op(bounds, Region.Op.INTERSECT);
- }
- region.op(r, Region.Op.UNION);
- }
- }
-
- /**
- * Return true if tap exclude region is empty.
- */
- boolean isEmpty() {
- return mTapExcludeRegions.size() == 0;
- }
-}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 1b2274ac5014..987ecc5c736d 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -548,8 +548,8 @@ class Task extends WindowContainer<WindowContainer> {
return;
}
mResizeMode = resizeMode;
- mAtmService.mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
- mAtmService.mRootActivityContainer.resumeFocusedStacksTopActivities();
+ mAtmService.mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
+ mAtmService.mRootWindowContainer.resumeFocusedStacksTopActivities();
updateTaskDescription();
}
@@ -602,10 +602,10 @@ class Task extends WindowContainer<WindowContainer> {
// this won't cause tons of irrelevant windows being preserved because only
// activities in this task may experience a bounds change. Configs for other
// activities stay the same.
- mAtmService.mRootActivityContainer.ensureActivitiesVisible(r, 0,
+ mAtmService.mRootWindowContainer.ensureActivitiesVisible(r, 0,
preserveWindow);
if (!kept) {
- mAtmService.mRootActivityContainer.resumeFocusedStacksTopActivities();
+ mAtmService.mRootWindowContainer.resumeFocusedStacksTopActivities();
}
}
}
@@ -670,7 +670,7 @@ class Task extends WindowContainer<WindowContainer> {
@ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
boolean schedulePictureInPictureModeChange, String reason) {
final ActivityStackSupervisor supervisor = mAtmService.mStackSupervisor;
- final RootActivityContainer root = mAtmService.mRootActivityContainer;
+ final RootWindowContainer root = mAtmService.mRootWindowContainer;
final WindowManagerService windowManager = mAtmService.mWindowManager;
final ActivityStack sourceStack = getStack();
final ActivityStack toStack = supervisor.getReparentTargetStack(this, preferredStack,
@@ -1028,7 +1028,7 @@ class Task extends WindowContainer<WindowContainer> {
forceWindowsScaleable(false /* force */);
}
- mAtmService.mRootActivityContainer.updateUIDsPresentOnDisplay();
+ mAtmService.mRootWindowContainer.updateUIDsPresentOnDisplay();
}
void updateTaskMovement(boolean toFront) {
@@ -1041,7 +1041,7 @@ class Task extends WindowContainer<WindowContainer> {
mLastTimeMoved *= -1;
}
}
- mAtmService.mRootActivityContainer.invalidateTaskLayers();
+ mAtmService.mRootWindowContainer.invalidateTaskLayers();
}
/**
@@ -1218,7 +1218,7 @@ class Task extends WindowContainer<WindowContainer> {
// Make sure the list of display UID whitelists is updated
// now that this record is in a new task.
- mAtmService.mRootActivityContainer.updateUIDsPresentOnDisplay();
+ mAtmService.mRootWindowContainer.updateUIDsPresentOnDisplay();
}
void addChild(ActivityRecord r) {
@@ -1581,9 +1581,9 @@ class Task extends WindowContainer<WindowContainer> {
// to do this for the pinned stack as the bounds are controlled by the system.
if (!inPinnedWindowingMode() && mStack != null) {
final int defaultMinSizeDp =
- mAtmService.mRootActivityContainer.mDefaultMinSizeOfResizeableTaskDp;
+ mAtmService.mRootWindowContainer.mDefaultMinSizeOfResizeableTaskDp;
final DisplayContent display =
- mAtmService.mRootActivityContainer.getDisplayContent(mStack.mDisplayId);
+ mAtmService.mRootWindowContainer.getDisplayContent(mStack.mDisplayId);
final float density =
(float) display.getConfiguration().densityDpi / DisplayMetrics.DENSITY_DEFAULT;
final int defaultMinSize = (int) (defaultMinSizeDp * density);
@@ -1881,7 +1881,10 @@ class Task extends WindowContainer<WindowContainer> {
if (inOutConfig.screenWidthDp == Configuration.SCREEN_WIDTH_DP_UNDEFINED
|| inOutConfig.screenHeightDp == Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
- if (insideParentBounds && mStack != null) {
+ if (insideParentBounds && WindowConfiguration.isFloating(windowingMode)) {
+ mTmpNonDecorBounds.set(mTmpFullBounds);
+ mTmpStableBounds.set(mTmpFullBounds);
+ } else if (insideParentBounds && mStack != null) {
final DisplayInfo di = new DisplayInfo();
mStack.getDisplay().mDisplay.getDisplayInfo(di);
@@ -2182,22 +2185,12 @@ class Task extends WindowContainer<WindowContainer> {
void reparent(ActivityStack stack, int position, boolean moveParents, String reason) {
if (DEBUG_STACK) Slog.i(TAG, "reParentTask: removing taskId=" + mTaskId
+ " from stack=" + getTaskStack());
- EventLogTags.writeWmTaskRemoved(mTaskId, "reParentTask");
-
- final ActivityStack prevStack = getTaskStack();
- final boolean wasTopFocusedStack =
- mAtmService.mRootActivityContainer.isTopDisplayFocusedStack(prevStack);
- final DisplayContent prevStackDisplay = prevStack.getDisplay();
+ EventLogTags.writeWmTaskRemoved(mTaskId, "reParentTask:" + reason);
position = stack.findPositionForTask(this, position, showForAllUsers());
reparent(stack, position);
- if (!moveParents) {
- // Only move home stack forward if we are not going to move the new parent forward.
- prevStack.moveHomeStackToFrontIfNeeded(wasTopFocusedStack, prevStackDisplay, reason);
- }
-
stack.positionChildAt(position, this, moveParents);
// If we are moving from the fullscreen stack to the pinned stack then we want to preserve
diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
index 4de61f04af5c..b8f3abe2ca2a 100644
--- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
@@ -137,7 +137,7 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
// STEP 1: Determine the display to launch the activity/task.
final int displayId = getPreferredLaunchDisplay(task, options, source, currentParams);
outParams.mPreferredDisplayId = displayId;
- DisplayContent display = mSupervisor.mRootActivityContainer.getDisplayContent(displayId);
+ DisplayContent display = mSupervisor.mRootWindowContainer.getDisplayContent(displayId);
if (DEBUG) {
appendLog("display-id=" + outParams.mPreferredDisplayId + " display-windowing-mode="
+ display.getWindowingMode());
@@ -333,13 +333,13 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
}
if (displayId != INVALID_DISPLAY
- && mSupervisor.mRootActivityContainer.getDisplayContent(displayId) == null) {
+ && mSupervisor.mRootWindowContainer.getDisplayContent(displayId) == null) {
displayId = currentParams.mPreferredDisplayId;
}
displayId = (displayId == INVALID_DISPLAY) ? currentParams.mPreferredDisplayId : displayId;
return (displayId != INVALID_DISPLAY
- && mSupervisor.mRootActivityContainer.getDisplayContent(displayId) != null)
+ && mSupervisor.mRootWindowContainer.getDisplayContent(displayId) != null)
? displayId : DEFAULT_DISPLAY;
}
@@ -656,7 +656,7 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
// There is no way for us to fit the bounds in the display without changing width
// or height. Just move the start to align with the display.
final int layoutDirection =
- mSupervisor.mRootActivityContainer.getConfiguration().getLayoutDirection();
+ mSupervisor.mRootWindowContainer.getConfiguration().getLayoutDirection();
final int left = layoutDirection == View.LAYOUT_DIRECTION_RTL
? displayStableBounds.right - inOutBounds.right + inOutBounds.left
: displayStableBounds.left;
diff --git a/services/core/java/com/android/server/wm/TaskPersister.java b/services/core/java/com/android/server/wm/TaskPersister.java
index eb130a1570cb..8cff99b8a28e 100644
--- a/services/core/java/com/android/server/wm/TaskPersister.java
+++ b/services/core/java/com/android/server/wm/TaskPersister.java
@@ -16,7 +16,7 @@
package com.android.server.wm;
-import static com.android.server.wm.RootActivityContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS;
+import static com.android.server.wm.RootWindowContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS;
import android.annotation.NonNull;
import android.graphics.Bitmap;
@@ -39,7 +39,6 @@ import com.android.internal.util.XmlUtils;
import libcore.io.IoUtils;
import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
import java.io.BufferedReader;
@@ -330,7 +329,7 @@ public class TaskPersister implements PersisterQueue.Listener {
// mWriteQueue.add(new TaskWriteQueueItem(task));
final int taskId = task.mTaskId;
- if (mService.mRootActivityContainer.anyTaskForId(taskId,
+ if (mService.mRootWindowContainer.anyTaskForId(taskId,
MATCH_TASK_IN_STACKS_OR_RECENT_TASKS) != null) {
// Should not happen.
Slog.wtf(TAG, "Existing task with taskId " + taskId + "found");
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index a867a5d41e24..2a1d271b538f 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -274,7 +274,6 @@ class TaskPositioner implements IBinder.DeathRecipient {
mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, display.getDisplayId());
mDragWindowHandle.name = TAG;
mDragWindowHandle.token = mServerChannel.getToken();
- mDragWindowHandle.layer = mService.getDragLayerLocked();
mDragWindowHandle.layoutParamsFlags = 0;
mDragWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG;
mDragWindowHandle.dispatchingTimeoutNanos =
diff --git a/services/core/java/com/android/server/wm/TaskPositioningController.java b/services/core/java/com/android/server/wm/TaskPositioningController.java
index c38e63e54239..2d303faa7921 100644
--- a/services/core/java/com/android/server/wm/TaskPositioningController.java
+++ b/services/core/java/com/android/server/wm/TaskPositioningController.java
@@ -198,7 +198,9 @@ class TaskPositioningController {
}
void finishTaskPositioning() {
- mHandler.post(() -> {
+ // TaskPositioner attaches the InputEventReceiver to the animation thread. We need to
+ // dispose the receiver on the same thread to avoid race conditions.
+ mService.mAnimationHandler.post(() -> {
if (DEBUG_TASK_POSITIONING) Slog.d(TAG_WM, "finishPositioning");
synchronized (mService.mGlobalLock) {
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index dee9e9f266a8..e4744dba85d3 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -89,6 +89,14 @@ class TaskSnapshotController {
@VisibleForTesting
static final int SNAPSHOT_MODE_NONE = 2;
+ /**
+ * Constant for <code>scaleFactor</code> when calling {@link #snapshotTask} which is
+ * interpreted as using the most appropriate scale ratio for the system.
+ * This may yield a smaller ratio on low memory devices.
+ */
+ @VisibleForTesting
+ static final float SNAPSHOT_SCALE_AUTO = -1f;
+
private final WindowManagerService mService;
private final TaskSnapshotCache mCache;
@@ -171,7 +179,7 @@ class TaskSnapshotController {
}
void snapshotTasks(ArraySet<Task> tasks) {
- snapshotTasks(mTmpTasks, false /* allowSnapshotHome */);
+ snapshotTasks(tasks, false /* allowSnapshotHome */);
}
private void snapshotTasks(ArraySet<Task> tasks, boolean allowSnapshotHome) {
@@ -260,6 +268,86 @@ class TaskSnapshotController {
});
}
+ /**
+ * Validates the state of the Task is appropriate to capture a snapshot, collects
+ * information from the task and populates the builder.
+ *
+ * @param task the task to capture
+ * @param scaleFraction the scale fraction between 0-1.0, or {@link #SNAPSHOT_SCALE_AUTO}
+ * to automatically select
+ * @param pixelFormat the desired pixel format, or {@link PixelFormat#UNKNOWN} to
+ * automatically select
+ * @param builder the snapshot builder to populate
+ *
+ * @return true if the state of the task is ok to proceed
+ */
+ @VisibleForTesting
+ boolean prepareTaskSnapshot(Task task, float scaleFraction, int pixelFormat,
+ TaskSnapshot.Builder builder) {
+ if (!mService.mPolicy.isScreenOn()) {
+ if (DEBUG_SCREENSHOT) {
+ Slog.i(TAG_WM, "Attempted to take screenshot while display was off.");
+ }
+ return false;
+ }
+ final ActivityRecord activity = findAppTokenForSnapshot(task);
+ if (activity == null) {
+ if (DEBUG_SCREENSHOT) {
+ Slog.w(TAG_WM, "Failed to take screenshot. No visible windows for " + task);
+ }
+ return false;
+ }
+ if (activity.hasCommittedReparentToAnimationLeash()) {
+ if (DEBUG_SCREENSHOT) {
+ Slog.w(TAG_WM, "Failed to take screenshot. App is animating " + activity);
+ }
+ return false;
+ }
+
+ final WindowState mainWindow = activity.findMainWindow();
+ if (mainWindow == null) {
+ Slog.w(TAG_WM, "Failed to take screenshot. No main window for " + task);
+ return false;
+ }
+
+ builder.setIsRealSnapshot(true);
+ builder.setId(System.currentTimeMillis());
+ builder.setContentInsets(getInsets(mainWindow));
+
+ final boolean isLowRamDevice = ActivityManager.isLowRamDeviceStatic();
+
+ if (scaleFraction == SNAPSHOT_SCALE_AUTO) {
+ builder.setScaleFraction(isLowRamDevice
+ ? mPersister.getReducedScale()
+ : mFullSnapshotScale);
+ builder.setReducedResolution(isLowRamDevice);
+ } else {
+ builder.setScaleFraction(scaleFraction);
+ builder.setReducedResolution(scaleFraction < 1.0f);
+ }
+
+ final boolean isWindowTranslucent = mainWindow.getAttrs().format != PixelFormat.OPAQUE;
+ final boolean isShowWallpaper = (mainWindow.getAttrs().flags & FLAG_SHOW_WALLPAPER) != 0;
+
+ if (pixelFormat == PixelFormat.UNKNOWN) {
+ pixelFormat = mPersister.use16BitFormat() && activity.fillsParent()
+ && !(isWindowTranslucent && isShowWallpaper)
+ ? PixelFormat.RGB_565
+ : PixelFormat.RGBA_8888;
+ }
+
+ final boolean isTranslucent = PixelFormat.formatHasAlpha(pixelFormat)
+ && (!activity.fillsParent() || isWindowTranslucent);
+
+ builder.setTopActivityComponent(activity.mActivityComponent);
+ builder.setPixelFormat(pixelFormat);
+ builder.setIsTranslucent(isTranslucent);
+ builder.setOrientation(activity.getTask().getConfiguration().orientation);
+ builder.setWindowingMode(task.getWindowingMode());
+ builder.setSystemUiVisibility(getSystemUiVisibility(task));
+ return true;
+ }
+
@Nullable
SurfaceControl.ScreenshotGraphicBuffer createTaskSnapshot(@NonNull Task task,
float scaleFraction) {
@@ -288,63 +376,31 @@ class TaskSnapshotController {
return screenshotBuffer;
}
- @Nullable private TaskSnapshot snapshotTask(Task task) {
- if (!mService.mPolicy.isScreenOn()) {
- if (DEBUG_SCREENSHOT) {
- Slog.i(TAG_WM, "Attempted to take screenshot while display was off.");
- }
- return null;
- }
-
- final ActivityRecord activity = findAppTokenForSnapshot(task);
- if (activity == null) {
- if (DEBUG_SCREENSHOT) {
- Slog.w(TAG_WM, "Failed to take screenshot. No visible windows for " + task);
- }
- return null;
- }
- if (activity.hasCommittedReparentToAnimationLeash()) {
- if (DEBUG_SCREENSHOT) {
- Slog.w(TAG_WM, "Failed to take screenshot. App is animating " + activity);
- }
- return null;
- }
+ @Nullable
+ TaskSnapshot snapshotTask(Task task) {
+ return snapshotTask(task, SNAPSHOT_SCALE_AUTO, PixelFormat.UNKNOWN);
+ }
- final boolean isLowRamDevice = ActivityManager.isLowRamDeviceStatic();
- final float scaleFraction = isLowRamDevice
- ? mPersister.getReducedScale()
- : mFullSnapshotScale;
+ @Nullable
+ TaskSnapshot snapshotTask(Task task, float scaleFraction, int pixelFormat) {
+ TaskSnapshot.Builder builder = new TaskSnapshot.Builder();
- final WindowState mainWindow = activity.findMainWindow();
- if (mainWindow == null) {
- Slog.w(TAG_WM, "Failed to take screenshot. No main window for " + task);
+ if (!prepareTaskSnapshot(task, scaleFraction, pixelFormat, builder)) {
+ // Failed some pre-req. Has been logged.
return null;
}
- final boolean isWindowTranslucent = mainWindow.getAttrs().format != PixelFormat.OPAQUE;
- final boolean isShowWallpaper = (mainWindow.getAttrs().flags & FLAG_SHOW_WALLPAPER) != 0;
- final int pixelFormat = mPersister.use16BitFormat() && activity.fillsParent()
- && !(isWindowTranslucent && isShowWallpaper)
- ? PixelFormat.RGB_565
- : PixelFormat.RGBA_8888;
+
final SurfaceControl.ScreenshotGraphicBuffer screenshotBuffer =
- createTaskSnapshot(task, scaleFraction, pixelFormat);
+ createTaskSnapshot(task, builder.getScaleFraction(),
+ builder.getPixelFormat());
if (screenshotBuffer == null) {
- if (DEBUG_SCREENSHOT) {
- Slog.w(TAG_WM, "Failed to take screenshot for " + task);
- }
+ // Failed to acquire image. Has been logged.
return null;
}
- final boolean isTranslucent = PixelFormat.formatHasAlpha(pixelFormat)
- && (!activity.fillsParent() || isWindowTranslucent);
- return new TaskSnapshot(
- System.currentTimeMillis() /* id */,
- activity.mActivityComponent, screenshotBuffer.getGraphicBuffer(),
- screenshotBuffer.getColorSpace(),
- activity.getTask().getConfiguration().orientation,
- getInsets(mainWindow), isLowRamDevice /* reduced */, scaleFraction /* scale */,
- true /* isRealSnapshot */, task.getWindowingMode(), getSystemUiVisibility(task),
- isTranslucent);
+ builder.setSnapshot(screenshotBuffer.getGraphicBuffer());
+ builder.setColorSpace(screenshotBuffer.getColorSpace());
+ return builder.build();
}
private boolean shouldDisableSnapshots() {
@@ -511,16 +567,16 @@ class TaskSnapshotController {
}
/**
- * @return The SystemUI visibility flags for the top fullscreen window in the given
+ * @return The SystemUI visibility flags for the top fullscreen opaque window in the given
* {@param task}.
*/
private int getSystemUiVisibility(Task task) {
final ActivityRecord topFullscreenActivity = task.getTopFullscreenActivity();
- final WindowState topFullscreenWindow = topFullscreenActivity != null
- ? topFullscreenActivity.getTopFullscreenWindow()
+ final WindowState topFullscreenOpaqueWindow = topFullscreenActivity != null
+ ? topFullscreenActivity.getTopFullscreenOpaqueWindow()
: null;
- if (topFullscreenWindow != null) {
- return topFullscreenWindow.getSystemUiVisibility();
+ if (topFullscreenOpaqueWindow != null) {
+ return topFullscreenOpaqueWindow.getSystemUiVisibility();
}
return 0;
}
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
index 10f29960081e..d36a5d4eb362 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
@@ -366,8 +366,6 @@ class TaskSnapshotPersister {
}
boolean writeBuffer() {
- // TODO(b/116112787) TaskSnapshot needs bookkeep the ColorSpace of the
- // hardware bitmap when created.
final Bitmap bitmap = Bitmap.wrapHardwareBuffer(
mSnapshot.getSnapshot(), mSnapshot.getColorSpace());
if (bitmap == null) {
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index 1484d6aeabef..5b458d894430 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -155,7 +155,7 @@ class TaskSnapshotSurface implements StartingSurface {
final MergedConfiguration tmpMergedConfiguration = new MergedConfiguration();
final TaskDescription taskDescription = new TaskDescription();
taskDescription.setBackgroundColor(WHITE);
- final WindowState topFullscreenWindow;
+ final WindowState topFullscreenOpaqueWindow;
final int sysUiVis;
final int windowFlags;
final int windowPrivateFlags;
@@ -175,15 +175,15 @@ class TaskSnapshotSurface implements StartingSurface {
+ task);
return null;
}
- topFullscreenWindow = topFullscreenActivity.getTopFullscreenWindow();
- if (mainWindow == null || topFullscreenWindow == null) {
+ topFullscreenOpaqueWindow = topFullscreenActivity.getTopFullscreenOpaqueWindow();
+ if (mainWindow == null || topFullscreenOpaqueWindow == null) {
Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find main window for activity="
+ activity);
return null;
}
- sysUiVis = topFullscreenWindow.getSystemUiVisibility();
- windowFlags = topFullscreenWindow.getAttrs().flags;
- windowPrivateFlags = topFullscreenWindow.getAttrs().privateFlags;
+ sysUiVis = topFullscreenOpaqueWindow.getSystemUiVisibility();
+ windowFlags = topFullscreenOpaqueWindow.getAttrs().flags;
+ windowPrivateFlags = topFullscreenOpaqueWindow.getAttrs().privateFlags;
layoutParams.packageName = mainWindow.getAttrs().packageName;
layoutParams.windowAnimations = mainWindow.getAttrs().windowAnimations;
@@ -202,11 +202,11 @@ class TaskSnapshotSurface implements StartingSurface {
final TaskDescription td = task.getTaskDescription();
if (td != null) {
- taskDescription.copyFrom(td);
+ taskDescription.copyFromPreserveHiddenFields(td);
}
taskBounds = new Rect();
task.getBounds(taskBounds);
- currentOrientation = topFullscreenWindow.getConfiguration().orientation;
+ currentOrientation = topFullscreenOpaqueWindow.getConfiguration().orientation;
}
try {
final int res = session.addToDisplay(window, window.mSeq, layoutParams,
@@ -222,7 +222,7 @@ class TaskSnapshotSurface implements StartingSurface {
final TaskSnapshotSurface snapshotSurface = new TaskSnapshotSurface(service, window,
surfaceControl, snapshot, layoutParams.getTitle(), taskDescription, sysUiVis,
windowFlags, windowPrivateFlags, taskBounds,
- currentOrientation, topFullscreenWindow.getClientInsetsState());
+ currentOrientation, topFullscreenOpaqueWindow.getClientInsetsState());
window.setOuter(snapshotSurface);
try {
session.relayout(window, window.mSeq, layoutParams, -1, -1, View.VISIBLE, 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 06cea3741aa1..5c02f469db41 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -30,6 +30,7 @@ import static android.view.SurfaceControl.Transaction;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM;
+import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
@@ -41,7 +42,6 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.logWithStack;
-import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING;
import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
import android.annotation.CallSuper;
@@ -70,7 +70,6 @@ import android.view.animation.Animation;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ToBooleanFunction;
-import com.android.server.policy.WindowManagerPolicy;
import com.android.server.protolog.common.ProtoLog;
import com.android.server.wm.SurfaceAnimator.Animatable;
@@ -132,6 +131,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
protected final WindowList<E> mChildren = new WindowList<E>();
// The specified orientation for this window container.
+ @ActivityInfo.ScreenOrientation
protected int mOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
private final Pools.SynchronizedPool<ForAllWindowsConsumerWrapper> mConsumerWrapperPool =
@@ -315,6 +315,10 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
mParent.onChildAdded(this);
}
if (!mReparenting) {
+ if (mParent != null && mParent.mDisplayContent != null
+ && mDisplayContent != mParent.mDisplayContent) {
+ onDisplayChanged(mParent.mDisplayContent);
+ }
onParentChanged(mParent, oldParent);
}
}
@@ -986,6 +990,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
}
}
+ @ActivityInfo.ScreenOrientation
int getOrientation() {
return getOrientation(mOrientation);
}
@@ -1038,6 +1043,8 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
if (wc.fillsParent() || orientation != SCREEN_ORIENTATION_UNSPECIFIED) {
// Use the orientation if the container fills its parent or requested an explicit
// orientation that isn't SCREEN_ORIENTATION_UNSPECIFIED.
+ ProtoLog.v(WM_DEBUG_ORIENTATION, "%s is requesting orientation %d (%s)", toString(),
+ orientation, ActivityInfo.screenOrientationToString(orientation));
return orientation;
}
}
@@ -1730,6 +1737,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
.setPosition(mSurfaceControl, spec.offsetX, spec.offsetY);
mLastMagnificationSpec = spec;
} else {
+ clearMagnificationSpec(t);
for (int i = 0; i < mChildren.size(); i++) {
mChildren.get(i).applyMagnificationSpec(t, spec);
}
@@ -2032,7 +2040,11 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
}
boolean okToAnimate() {
- return mDisplayContent != null && mDisplayContent.okToAnimate();
+ return okToAnimate(false /* ignoreFrozen */);
+ }
+
+ boolean okToAnimate(boolean ignoreFrozen) {
+ return mDisplayContent != null && mDisplayContent.okToAnimate(ignoreFrozen);
}
@Override
@@ -2165,15 +2177,8 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
}
void waitForAllWindowsDrawn() {
- final WindowManagerPolicy policy = mWmService.mPolicy;
forAllWindows(w -> {
- final boolean keyguard = policy.isKeyguardHostWindow(w.mAttrs);
- if (w.isVisibleLw() && (w.mActivityRecord != null || keyguard)) {
- w.mWinAnimator.mDrawState = DRAW_PENDING;
- // Force add to mResizingWindows.
- w.resetLastContentInsets();
- mWaitingForDrawn.add(w);
- }
+ w.requestDrawIfNeeded(mWaitingForDrawn);
}, true /* traverseTopToBottom */);
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java
index ea90e49d879e..6e243f0b937a 100644
--- a/services/core/java/com/android/server/wm/WindowManagerInternal.java
+++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java
@@ -19,6 +19,7 @@ package com.android.server.wm;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ClipData;
+import android.content.Context;
import android.graphics.Rect;
import android.graphics.Region;
import android.hardware.display.DisplayManagerInternal;
@@ -494,6 +495,11 @@ public abstract class WindowManagerInternal {
public abstract int getTopFocusedDisplayId();
/**
+ * @return The UI context of top focused display.
+ */
+ public abstract Context getTopFocusedDisplayUiContext();
+
+ /**
* Checks if this display is configured and allowed to show system decorations.
*/
public abstract boolean shouldShowSystemDecorOnDisplay(int displayId);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index acaaed9b615c..53c5ebde05bf 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -59,7 +59,6 @@ import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTE
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
-import static android.view.WindowManager.LayoutParams.TYPE_DRAG;
import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
@@ -630,10 +629,6 @@ public class WindowManagerService extends IWindowManager.Stub
boolean mDisableTransitionAnimation;
- int getDragLayerLocked() {
- return mPolicy.getWindowLayerFromTypeLw(TYPE_DRAG) * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
- }
-
class RotationWatcher {
final IRotationWatcher mWatcher;
final IBinder.DeathRecipient mDeathRecipient;
@@ -1651,7 +1646,8 @@ public class WindowManagerService extends IWindowManager.Stub
outFrame, outContentInsets, outStableInsets, outDisplayCutout)) {
res |= WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_SYSTEM_BARS;
}
- outInsetsState.set(displayContent.getInsetsPolicy().getInsetsForDispatch(win));
+ outInsetsState.set(displayContent.getInsetsPolicy().getInsetsForDispatch(win),
+ win.mClient instanceof IWindow.Stub /* copySource */);
if (mInTouchMode) {
res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE;
@@ -1721,7 +1717,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
- return mAtmService.mRootActivityContainer.getDisplayContentOrCreate(displayId);
+ return mRoot.getDisplayContentOrCreate(displayId);
}
private boolean doesAddToastWindowRequireToken(String packageName, int callingUid,
@@ -2335,7 +2331,8 @@ public class WindowManagerService extends IWindowManager.Stub
outStableInsets);
outCutout.set(win.getWmDisplayCutout().getDisplayCutout());
outBackdropFrame.set(win.getBackdropFrame(win.getFrameLw()));
- outInsetsState.set(displayContent.getInsetsPolicy().getInsetsForDispatch(win));
+ outInsetsState.set(displayContent.getInsetsPolicy().getInsetsForDispatch(win),
+ win.mClient instanceof IWindow.Stub /* copySource */);
if (DEBUG) {
Slog.v(TAG_WM, "Relayout given client " + client.asBinder()
+ ", requestedWidth=" + requestedWidth
@@ -4511,6 +4508,7 @@ public class WindowManagerService extends IWindowManager.Stub
public static final int ANIMATION_FAILSAFE = 60;
public static final int RECOMPUTE_FOCUS = 61;
public static final int ON_POINTER_DOWN_OUTSIDE_FOCUS = 62;
+ public static final int LAYOUT_AND_ASSIGN_WINDOW_LAYERS_IF_NEEDED = 63;
/**
* Used to denote that an integer field in a message will not be used.
@@ -4885,6 +4883,13 @@ public class WindowManagerService extends IWindowManager.Stub
}
break;
}
+ case LAYOUT_AND_ASSIGN_WINDOW_LAYERS_IF_NEEDED: {
+ synchronized (mGlobalLock) {
+ final DisplayContent displayContent = (DisplayContent) msg.obj;
+ displayContent.layoutAndAssignWindowLayersIfNeeded();
+ }
+ break;
+ }
}
if (DEBUG_WINDOW_TRACE) {
Slog.v(TAG_WM, "handleMessage: exit");
@@ -5777,7 +5782,7 @@ public class WindowManagerService extends IWindowManager.Stub
*/
void dumpDebugLocked(ProtoOutputStream proto, @WindowTraceLogLevel int logLevel) {
mPolicy.dumpDebug(proto, POLICY);
- mRoot.dumpDebug(proto, ROOT_WINDOW_CONTAINER, logLevel);
+ mRoot.dumpDebugInner(proto, ROOT_WINDOW_CONTAINER, logLevel);
final DisplayContent topFocusedDisplayContent = mRoot.getTopFocusedDisplayContent();
if (topFocusedDisplayContent.mCurrentFocus != null) {
topFocusedDisplayContent.mCurrentFocus.writeIdentifierToProto(proto, FOCUSED_WINDOW);
@@ -6640,14 +6645,14 @@ public class WindowManagerService extends IWindowManager.Stub
* </ol>
* Passing an invalid region will remove the area from the exclude region of this window.
*/
- void updateTapExcludeRegion(IWindow client, int regionId, Region region) {
+ void updateTapExcludeRegion(IWindow client, Region region) {
synchronized (mGlobalLock) {
final WindowState callingWin = windowForClientLocked(null, client, false);
if (callingWin == null) {
ProtoLog.w(WM_ERROR, "Bad requesting window %s", client);
return;
}
- callingWin.updateTapExcludeRegion(regionId, region);
+ callingWin.updateTapExcludeRegion(region);
}
}
@@ -6864,21 +6869,12 @@ public class WindowManagerService extends IWindowManager.Stub
if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "shouldShowIme()")) {
throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
}
-
+ boolean show;
synchronized (mGlobalLock) {
- final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
- if (displayContent == null) {
- ProtoLog.w(WM_ERROR,
- "Attempted to get IME flag of a display that does not exist: %d",
- displayId);
- return false;
- }
- if (displayContent.isUntrustedVirtualDisplay()) {
- return false;
- }
- return mDisplayWindowSettings.shouldShowImeLocked(displayContent)
- || mForceDesktopModeOnExternalDisplays;
+ show = shouldShowImeSystemWindowUncheckedLocked(displayId);
}
+
+ return show;
}
@Override
@@ -7301,18 +7297,12 @@ public class WindowManagerService extends IWindowManager.Stub
if (imeTarget == null) {
return;
}
- final DisplayContent displayContent = imeTarget.getDisplayContent();
- if (displayContent == null) {
- Slog.w(TAG_WM, "Attempted to show IME on an IME target that does not exist: "
- + imeTarget.getName());
+ final int displayId = imeTarget.getDisplayId();
+ if (!shouldShowImeSystemWindowUncheckedLocked(displayId)) {
return;
}
- if (displayContent.isUntrustedVirtualDisplay()) {
- throw new SecurityException("Attempted to show IME on an untrusted "
- + "virtual display: " + displayContent.getDisplayId());
- }
- displayContent.getInsetsStateController().getImeSourceProvider()
+ mRoot.getDisplayContent(displayId).getInsetsStateController().getImeSourceProvider()
.scheduleShowImePostLayout(imeTarget);
}
}
@@ -7363,6 +7353,13 @@ public class WindowManagerService extends IWindowManager.Stub
}
@Override
+ public Context getTopFocusedDisplayUiContext() {
+ synchronized (mGlobalLock) {
+ return mRoot.getTopFocusedDisplayContent().getDisplayUiContext();
+ }
+ }
+
+ @Override
public boolean shouldShowSystemDecorOnDisplay(int displayId) {
synchronized (mGlobalLock) {
return WindowManagerService.this.shouldShowSystemDecors(displayId);
@@ -7825,4 +7822,19 @@ public class WindowManagerService extends IWindowManager.Stub
return true;
}
+
+ private boolean shouldShowImeSystemWindowUncheckedLocked(final int displayId) {
+ final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
+ if (displayContent == null) {
+ ProtoLog.w(WM_ERROR,
+ "Attempted to get IME flag of a display that does not exist: %d",
+ displayId);
+ return false;
+ }
+ if (displayContent.isUntrustedVirtualDisplay()) {
+ return false;
+ }
+ return mDisplayWindowSettings.shouldShowImeLocked(displayContent)
+ || mForceDesktopModeOnExternalDisplays;
+ }
}
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 1a41006b7954..9a40b1b1a74a 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -44,6 +44,7 @@ import android.app.ActivityThread;
import android.app.IApplicationThread;
import android.app.ProfilerInfo;
import android.app.servertransaction.ConfigurationChangeItem;
+import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
@@ -67,6 +68,7 @@ import com.android.server.wm.ActivityTaskManagerService.HotPath;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.List;
/**
* The Activity Manager (AM) package manages the lifecycle of processes in the system through
@@ -767,6 +769,30 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
}
}
+ /**
+ * Returns display UI context list which there is any app window shows or starting activities
+ * int this process.
+ */
+ public void getDisplayContextsWithErrorDialogs(List<Context> displayContexts) {
+ if (displayContexts == null) {
+ return;
+ }
+ synchronized (mAtm.mGlobalLock) {
+ final RootWindowContainer root = mAtm.mWindowManager.mRoot;
+ root.getDisplayContextsWithNonToastVisibleWindows(mPid, displayContexts);
+
+ for (int i = mActivities.size() - 1; i >= 0; --i) {
+ final ActivityRecord r = mActivities.get(i);
+ final int displayId = r.getDisplayId();
+ final Context c = root.getDisplayUiContext(displayId);
+
+ if (r.mVisibleRequested && !displayContexts.contains(c)) {
+ displayContexts.add(c);
+ }
+ }
+ }
+ }
+
public interface ComputeOomAdjCallback {
void onVisibleActivity();
void onPausedActivity();
@@ -955,7 +981,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
return;
}
final DisplayContent displayContent =
- mAtm.mRootActivityContainer.getDisplayContent(mDisplayId);
+ mAtm.mRootWindowContainer.getDisplayContent(mDisplayId);
if (displayContent != null) {
displayContent.unregisterConfigurationChangeListener(this);
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 6918c966a3ec..bb7c26c25670 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -595,7 +595,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
/**
* A region inside of this window to be excluded from touch.
*/
- private TapExcludeRegionHolder mTapExcludeRegionHolder;
+ private final Region mTapExcludeRegion = new Region();
/**
* Used for testing because the real PowerManager is final.
@@ -767,7 +767,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
mPowerManagerWrapper = powerManagerWrapper;
mForceSeamlesslyRotate = token.mRoundedCornerOverlay;
mClientInsetsState =
- getDisplayContent().getInsetsStateController().getInsetsForDispatch(this);
+ getDisplayContent().getInsetsPolicy().getInsetsForDispatch(this);
if (DEBUG) {
Slog.v(TAG, "Window " + this + " client=" + c.asBinder()
+ " token=" + token + " (" + mAttrs.token + ")" + " params=" + a);
@@ -797,9 +797,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
mSubLayer = mPolicy.getSubWindowLayerFromTypeLw(a.type);
mIsChildWindow = true;
- ProtoLog.v(WM_DEBUG_ADD_REMOVE, "Adding %s to %s", this, parentWindow);
- parentWindow.addChild(this, sWindowSubLayerComparator);
-
mLayoutAttached = mAttrs.type !=
WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
mIsImWindow = parentWindow.mAttrs.type == TYPE_INPUT_METHOD
@@ -836,6 +833,13 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
mInputWindowHandle = new InputWindowHandle(
mActivityRecord != null ? mActivityRecord.mInputApplicationHandle : null,
getDisplayId());
+
+ // Make sure we initial all fields before adding to parentWindow, to prevent exception
+ // during onDisplayChanged.
+ if (mIsChildWindow) {
+ ProtoLog.v(WM_DEBUG_ADD_REMOVE, "Adding %s to %s", this, parentWindow);
+ parentWindow.addChild(this, sWindowSubLayerComparator);
+ }
}
void attach() {
@@ -1642,11 +1646,17 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
&& (parentAndClientVisible || isAnimating(TRANSITION | PARENTS));
}
- // TODO: Another visibility method that was added late in the release to minimize risk.
- @Override
- public boolean canAffectSystemUiFlags() {
- final boolean translucent = mAttrs.alpha == 0.0f;
- if (translucent) {
+ boolean isFullyTransparent() {
+ return mAttrs.alpha == 0f;
+ }
+
+ /**
+ * @return Whether the window can affect SystemUI flags, meaning that SystemUI (system bars,
+ * for example) will be affected by the flags specified in this window. This is the
+ * case when the surface is on screen but not exiting.
+ */
+ boolean canAffectSystemUiFlags() {
+ if (isFullyTransparent()) {
return false;
}
if (mActivityRecord == null) {
@@ -1726,6 +1736,39 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
&& isDrawnLw() && !isAnimating(TRANSITION | PARENTS);
}
+ /** @see WindowManagerInternal#waitForAllWindowsDrawn */
+ void requestDrawIfNeeded(List<WindowState> outWaitingForDrawn) {
+ if (!isVisible()) {
+ return;
+ }
+ if (mActivityRecord != null) {
+ if (mActivityRecord.allDrawn) {
+ // The allDrawn of activity is reset when the visibility is changed to visible, so
+ // the content should be ready if allDrawn is set.
+ return;
+ }
+ if (mAttrs.type == TYPE_APPLICATION_STARTING) {
+ if (isDrawnLw()) {
+ // Unnecessary to redraw a drawn starting window.
+ return;
+ }
+ } else if (mActivityRecord.startingWindow != null) {
+ // If the activity has an active starting window, there is no need to wait for the
+ // main window.
+ return;
+ }
+ } else if (!mPolicy.isKeyguardHostWindow(mAttrs)) {
+ return;
+ // Always invalidate keyguard host window to make sure it shows the latest content
+ // because its visibility may not be changed.
+ }
+
+ mWinAnimator.mDrawState = DRAW_PENDING;
+ // Force add to {@link WindowManagerService#mResizingWindows}.
+ resetLastContentInsets();
+ outWaitingForDrawn.add(this);
+ }
+
@Override
void onMovedByResize() {
ProtoLog.d(WM_DEBUG_RESIZE, "onMovedByResize: Moving %s", this);
@@ -1957,11 +2000,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
if (WindowManagerService.excludeWindowTypeFromTapOutTask(type)) {
dc.mTapExcludedWindows.remove(this);
}
- if (mTapExcludeRegionHolder != null) {
- // If a tap exclude region container was initialized for this window, then it should've
- // also been registered in display.
- dc.mTapExcludeProvidingWindows.remove(this);
- }
+
+ // Remove this window from mTapExcludeProvidingWindows. If it was not registered, this will
+ // not do anything.
+ dc.mTapExcludeProvidingWindows.remove(this);
dc.getDisplayPolicy().removeWindowLw(this);
disposeInputChannel();
@@ -2329,43 +2371,12 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
final Region region = inputWindowHandle.touchableRegion;
setTouchableRegionCropIfNeeded(inputWindowHandle);
- if (modal && mActivityRecord != null) {
- // Limit the outer touch to the activity stack region.
+ if (modal) {
flags |= FLAG_NOT_TOUCH_MODAL;
- // If the inner bounds of letterbox is available, then it will be used as the touchable
- // region so it won't cover the touchable letterbox and the touch events can slip to
- // activity from letterbox.
- mActivityRecord.getLetterboxInnerBounds(mTmpRect);
- if (mTmpRect.isEmpty()) {
- // If this is a modal window we need to dismiss it if it's not full screen and the
- // touch happens outside of the frame that displays the content. This means we need
- // to intercept touches outside of that window. The dim layer user associated with
- // the window (task or stack) will give us the good bounds, as they would be used to
- // display the dim layer.
- final Task task = getTask();
- if (task != null) {
- task.getDimBounds(mTmpRect);
- } else {
- getStack().getDimBounds(mTmpRect);
- }
- }
- if (inFreeformWindowingMode()) {
- // For freeform windows we the touch region to include the whole surface for the
- // shadows.
- final DisplayMetrics displayMetrics = getDisplayContent().getDisplayMetrics();
- final int delta = WindowManagerService.dipToPixel(
- RESIZE_HANDLE_WIDTH_IN_DP, displayMetrics);
- mTmpRect.inset(-delta, -delta);
- }
- region.set(mTmpRect);
- cropRegionToStackBoundsIfNeeded(region);
- subtractTouchExcludeRegionIfNeeded(region);
- } else if (modal && mTapExcludeRegionHolder != null) {
- final Region touchExcludeRegion = Region.obtain();
- amendTapExcludeRegion(touchExcludeRegion);
- if (!touchExcludeRegion.isEmpty()) {
- // Remove touch modal because there are some areas that cannot be touched.
- flags |= FLAG_NOT_TOUCH_MODAL;
+ if (mActivityRecord != null) {
+ // Limit the outer touch to the activity stack region.
+ updateRegionForModalActivityWindow(region);
+ } else {
// Give it a large touchable region at first because it was touch modal. The window
// might be moved on the display, so the touchable region should be large enough to
// ensure it covers the whole display, no matter where it is moved.
@@ -2373,15 +2384,13 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
final int dw = mTmpRect.width();
final int dh = mTmpRect.height();
region.set(-dw, -dh, dw + dw, dh + dh);
- // Subtract the area that cannot be touched.
- region.op(touchExcludeRegion, Region.Op.DIFFERENCE);
- inputWindowHandle.setTouchableRegionCrop(null);
}
- touchExcludeRegion.recycle();
+ subtractTouchExcludeRegionIfNeeded(region);
} else {
- // Not modal or full screen modal
+ // Not modal
getTouchableRegion(region);
}
+
// Translate to surface based coordinates.
region.translate(-mWindowFrames.mFrame.left, -mWindowFrames.mFrame.top);
@@ -2397,6 +2406,41 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
return flags;
}
+ /**
+ * Updates the region for a window in an Activity that was a touch modal. This will limit
+ * the outer touch to the activity stack region.
+ * @param outRegion The region to update.
+ */
+ private void updateRegionForModalActivityWindow(Region outRegion) {
+ // If the inner bounds of letterbox is available, then it will be used as the
+ // touchable region so it won't cover the touchable letterbox and the touch
+ // events can slip to activity from letterbox.
+ mActivityRecord.getLetterboxInnerBounds(mTmpRect);
+ if (mTmpRect.isEmpty()) {
+ // If this is a modal window we need to dismiss it if it's not full screen
+ // and the touch happens outside of the frame that displays the content. This
+ // means we need to intercept touches outside of that window. The dim layer
+ // user associated with the window (task or stack) will give us the good
+ // bounds, as they would be used to display the dim layer.
+ final Task task = getTask();
+ if (task != null) {
+ task.getDimBounds(mTmpRect);
+ } else {
+ getStack().getDimBounds(mTmpRect);
+ }
+ }
+ if (inFreeformWindowingMode()) {
+ // For freeform windows, we need the touch region to include the whole
+ // surface for the shadows.
+ final DisplayMetrics displayMetrics = getDisplayContent().getDisplayMetrics();
+ final int delta = WindowManagerService.dipToPixel(
+ RESIZE_HANDLE_WIDTH_IN_DP, displayMetrics);
+ mTmpRect.inset(-delta, -delta);
+ }
+ outRegion.set(mTmpRect);
+ cropRegionToStackBoundsIfNeeded(outRegion);
+ }
+
void checkPolicyVisibilityChange() {
if (isLegacyPolicyVisibility() != mLegacyPolicyVisibilityAfterAnim) {
if (DEBUG_VISIBILITY) {
@@ -2652,18 +2696,18 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
return mActivityRecord.getTask().getTaskStack().shouldIgnoreInput()
|| !mActivityRecord.mVisibleRequested
- || isAnimatingToRecents();
+ || isRecentsAnimationConsumingAppInput();
}
/**
- * Returns {@code true} if the window is animating to home as part of the recents animation.
+ * Returns {@code true} if the window is animating to home as part of the recents animation and
+ * it is consuming input from the app.
*/
- private boolean isAnimatingToRecents() {
+ private boolean isRecentsAnimationConsumingAppInput() {
final RecentsAnimationController recentsAnimationController =
mWmService.getRecentsAnimationController();
return recentsAnimationController != null
- && recentsAnimationController.isAnimatingTask(getTask())
- && !recentsAnimationController.isTargetApp(mActivityRecord);
+ && recentsAnimationController.shouldApplyInputConsumer(mActivityRecord);
}
@Override
@@ -3198,11 +3242,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
* region.
*/
private void subtractTouchExcludeRegionIfNeeded(Region touchableRegion) {
- if (mTapExcludeRegionHolder == null) {
+ if (mTapExcludeRegion.isEmpty()) {
return;
}
final Region touchExcludeRegion = Region.obtain();
- amendTapExcludeRegion(touchExcludeRegion);
+ getTapExcludeRegion(touchExcludeRegion);
if (!touchExcludeRegion.isEmpty()) {
touchableRegion.op(touchExcludeRegion, Region.Op.DIFFERENCE);
}
@@ -5227,21 +5271,25 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
* Update a tap exclude region identified by provided id. The requested area will be clipped to
* the window bounds.
*/
- void updateTapExcludeRegion(int regionId, Region region) {
+ void updateTapExcludeRegion(Region region) {
final DisplayContent currentDisplay = getDisplayContent();
if (currentDisplay == null) {
throw new IllegalStateException("Trying to update window not attached to any display.");
}
- if (mTapExcludeRegionHolder == null) {
- mTapExcludeRegionHolder = new TapExcludeRegionHolder();
-
+ // Clear the tap excluded region if the region passed in is null or empty.
+ if (region == null || region.isEmpty()) {
+ mTapExcludeRegion.setEmpty();
+ // Remove this window from mTapExcludeProvidingWindows since it won't be providing
+ // tap exclude regions.
+ currentDisplay.mTapExcludeProvidingWindows.remove(this);
+ } else {
+ mTapExcludeRegion.set(region);
// Make sure that this window is registered as one that provides a tap exclude region
// for its containing display.
currentDisplay.mTapExcludeProvidingWindows.add(this);
}
- mTapExcludeRegionHolder.updateRegion(regionId, region);
// Trigger touch exclude region update on current display.
currentDisplay.updateTouchExcludeRegion();
// Trigger touchable region update for this window.
@@ -5249,24 +5297,24 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
/**
- * Union the region with current tap exclude region that this window provides.
+ * Get the tap excluded region for this window in screen coordinates.
*
- * @param region The region to be amended. It is on the screen coordinates.
+ * @param outRegion The returned tap excluded region. It is on the screen coordinates.
*/
- void amendTapExcludeRegion(Region region) {
- final Region tempRegion = Region.obtain();
+ void getTapExcludeRegion(Region outRegion) {
mTmpRect.set(mWindowFrames.mFrame);
mTmpRect.offsetTo(0, 0);
- mTapExcludeRegionHolder.amendRegion(tempRegion, mTmpRect);
- // The region held by the holder is on the window coordinates. We need to translate it to
- // the screen coordinates.
- tempRegion.translate(mWindowFrames.mFrame.left, mWindowFrames.mFrame.top);
- region.op(tempRegion, Region.Op.UNION);
- tempRegion.recycle();
+
+ outRegion.set(mTapExcludeRegion);
+ outRegion.op(mTmpRect, Region.Op.INTERSECT);
+
+ // The region is on the window coordinates, so it needs to be translated into screen
+ // coordinates. There's no need to scale since that will be done by native code.
+ outRegion.translate(mWindowFrames.mFrame.left, mWindowFrames.mFrame.top);
}
boolean hasTapExcludeRegion() {
- return mTapExcludeRegionHolder != null && !mTapExcludeRegionHolder.isEmpty();
+ return !mTapExcludeRegion.isEmpty();
}
@Override
@@ -5447,4 +5495,21 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
getContentInsets(outInsets);
getStableInsets(outStableInsets);
}
+
+ /**
+ * Returns {@code true} if this window is not {@link WindowManager.LayoutParams#TYPE_TOAST}
+ * or {@link WindowManager.LayoutParams#TYPE_APPLICATION_STARTING},
+ * since this window doesn't belong to apps.
+ */
+ boolean isNonToastOrStarting() {
+ return mAttrs.type != TYPE_TOAST && mAttrs.type != TYPE_APPLICATION_STARTING;
+ }
+
+ boolean isNonToastWindowVisibleForUid(int callingUid) {
+ return getOwningUid() == callingUid && isNonToastOrStarting() && isVisibleNow();
+ }
+
+ boolean isNonToastWindowVisibleForPid(int pid) {
+ return mSession.mPid == pid && isNonToastOrStarting() && isVisibleNow();
+ }
}
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index 53edf9d3086a..2a1e980dfb3d 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -116,7 +116,7 @@ class WindowToken extends WindowContainer<WindowState> {
mOwnerCanManageAppTokens = ownerCanManageAppTokens;
mRoundedCornerOverlay = roundedCornerOverlay;
if (dc != null) {
- onDisplayChanged(dc);
+ dc.addWindowToken(token, this);
}
}
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index a34b7fdb911c..fee29db8edf2 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -52,6 +52,7 @@ cc_library_static {
"com_android_server_GraphicsStatsService.cpp",
"com_android_server_am_AppCompactor.cpp",
"com_android_server_am_LowMemDetector.cpp",
+ "com_android_server_incremental_IncrementalManagerService.cpp",
"onload.cpp",
":lib_networkStatsFactory_native",
],
@@ -145,6 +146,7 @@ cc_defaults {
"android.frameworks.schedulerservice@1.0",
"android.frameworks.sensorservice@1.0",
"android.system.suspend@1.0",
+ "service.incremental",
"suspend_control_aidl_interface-cpp",
"vintf-vibrator-cpp",
],
diff --git a/services/core/jni/com_android_server_VibratorService.cpp b/services/core/jni/com_android_server_VibratorService.cpp
index dcff5a11aca0..6811e6d0e6f2 100644
--- a/services/core/jni/com_android_server_VibratorService.cpp
+++ b/services/core/jni/com_android_server_VibratorService.cpp
@@ -410,6 +410,21 @@ static jlong vibratorGetCapabilities(JNIEnv*, jclass) {
return 0;
}
+static void vibratorAlwaysOnEnable(JNIEnv* env, jclass, jlong id, jlong effect, jlong strength) {
+ auto status = halCall(&aidl::IVibrator::alwaysOnEnable, id,
+ static_cast<aidl::Effect>(effect), static_cast<aidl::EffectStrength>(strength));
+ if (!status.isOk()) {
+ ALOGE("vibratortAlwaysOnEnable command failed (%s).", status.toString8().string());
+ }
+}
+
+static void vibratorAlwaysOnDisable(JNIEnv* env, jclass, jlong id) {
+ auto status = halCall(&aidl::IVibrator::alwaysOnDisable, id);
+ if (!status.isOk()) {
+ ALOGE("vibratorAlwaysOnDisable command failed (%s).", status.toString8().string());
+ }
+}
+
static const JNINativeMethod method_table[] = {
{ "vibratorExists", "()Z", (void*)vibratorExists },
{ "vibratorInit", "()V", (void*)vibratorInit },
@@ -422,6 +437,8 @@ static const JNINativeMethod method_table[] = {
{ "vibratorSupportsExternalControl", "()Z", (void*)vibratorSupportsExternalControl},
{ "vibratorSetExternalControl", "(Z)V", (void*)vibratorSetExternalControl},
{ "vibratorGetCapabilities", "()J", (void*)vibratorGetCapabilities},
+ { "vibratorAlwaysOnEnable", "(JJJ)V", (void*)vibratorAlwaysOnEnable},
+ { "vibratorAlwaysOnDisable", "(J)V", (void*)vibratorAlwaysOnDisable},
};
int register_android_server_VibratorService(JNIEnv *env)
diff --git a/services/core/jni/com_android_server_incremental_IncrementalManagerService.cpp b/services/core/jni/com_android_server_incremental_IncrementalManagerService.cpp
new file mode 100644
index 000000000000..5e255f46fa05
--- /dev/null
+++ b/services/core/jni/com_android_server_incremental_IncrementalManagerService.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "incremental_manager_service-jni"
+
+#include "incremental_service.h"
+#include "jni.h"
+
+#include <memory>
+#include <nativehelper/JNIHelp.h>
+
+
+namespace android {
+
+static jlong nativeStartService(JNIEnv* env, jclass klass, jobject self) {
+ return Incremental_IncrementalService_Start();
+}
+
+static void nativeSystemReady(JNIEnv* env, jclass klass, jlong self) {
+ Incremental_IncrementalService_OnSystemReady(self);
+}
+
+static const JNINativeMethod method_table[] = {
+ {"nativeStartService", "()J", (void*)nativeStartService},
+ {"nativeSystemReady", "(J)V", (void*)nativeSystemReady},
+};
+
+int register_android_server_incremental_IncrementalManagerService(JNIEnv* env) {
+ return jniRegisterNativeMethods(env,
+ "com/android/server/incremental/IncrementalManagerService",
+ method_table, std::size(method_table));
+}
+
+} // namespace android
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 9344a9b7c849..2e8e5e7b706a 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -485,8 +485,8 @@ void NativeInputManager::getReaderConfiguration(InputReaderConfiguration* outCon
// Received data: ['inputPort1', '1', 'inputPort2', '2']
// So we unpack accordingly here.
outConfig->portAssociations.clear();
- jobjectArray portAssociations = jobjectArray(env->CallStaticObjectMethod(
- gServiceClassInfo.clazz, gServiceClassInfo.getInputPortAssociations));
+ jobjectArray portAssociations = jobjectArray(env->CallObjectMethod(mServiceObj,
+ gServiceClassInfo.getInputPortAssociations));
if (!checkAndClearExceptionFromCallback(env, "getInputPortAssociations") && portAssociations) {
jsize length = env->GetArrayLength(portAssociations);
for (jsize i = 0; i < length / 2; i++) {
@@ -1920,7 +1920,7 @@ int register_android_server_InputManager(JNIEnv* env) {
GET_STATIC_METHOD_ID(gServiceClassInfo.getExcludedDeviceNames, clazz,
"getExcludedDeviceNames", "()[Ljava/lang/String;");
- GET_STATIC_METHOD_ID(gServiceClassInfo.getInputPortAssociations, clazz,
+ GET_METHOD_ID(gServiceClassInfo.getInputPortAssociations, clazz,
"getInputPortAssociations", "()[Ljava/lang/String;");
GET_METHOD_ID(gServiceClassInfo.getKeyRepeatTimeout, clazz,
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index 165edf15ca23..c0a6e4e30f3a 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -58,6 +58,7 @@ int register_android_server_am_AppCompactor(JNIEnv* env);
int register_android_server_am_LowMemDetector(JNIEnv* env);
int register_com_android_server_soundtrigger_middleware_AudioSessionProviderImpl(
JNIEnv* env);
+int register_android_server_incremental_IncrementalManagerService(JNIEnv* env);
};
using namespace android;
@@ -109,5 +110,6 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
register_android_server_am_LowMemDetector(env);
register_com_android_server_soundtrigger_middleware_AudioSessionProviderImpl(
env);
+ register_android_server_incremental_IncrementalManagerService(env);
return JNI_VERSION_1_4;
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index d91ec42e89a3..153681677d78 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -84,6 +84,7 @@ import static android.provider.Settings.Global.PRIVATE_DNS_SPECIFIER;
import static android.provider.Telephony.Carriers.DPC_URI;
import static android.provider.Telephony.Carriers.ENFORCE_KEY;
import static android.provider.Telephony.Carriers.ENFORCE_MANAGED_URI;
+import static android.security.keystore.AttestationUtils.USE_INDIVIDUAL_ATTESTATION;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_ENTRY_POINT_ADB;
import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE;
@@ -254,6 +255,7 @@ import com.android.internal.telephony.SmsApplication;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.FunctionalUtils.ThrowingRunnable;
+import com.android.internal.util.FunctionalUtils.ThrowingSupplier;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.JournaledFile;
import com.android.internal.util.Preconditions;
@@ -430,6 +432,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
private static final Set<String> GLOBAL_SETTINGS_DEPRECATED;
private static final Set<String> SYSTEM_SETTINGS_WHITELIST;
private static final Set<Integer> DA_DISALLOWED_POLICIES;
+ // A collection of user restrictions that are deprecated and should simply be ignored.
+ private static final Set<String> DEPRECATED_USER_RESTRICTIONS;
private static final String AB_DEVICE_KEY = "ro.build.ab_update";
static {
@@ -471,6 +475,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
DA_DISALLOWED_POLICIES.add(DeviceAdminInfo.USES_POLICY_DISABLE_KEYGUARD_FEATURES);
DA_DISALLOWED_POLICIES.add(DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD);
DA_DISALLOWED_POLICIES.add(DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
+
+ DEPRECATED_USER_RESTRICTIONS = Sets.newHashSet(
+ UserManager.DISALLOW_ADD_MANAGED_PROFILE,
+ UserManager.DISALLOW_REMOVE_MANAGED_PROFILE);
}
/**
@@ -2099,6 +2107,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Binder.withCleanCallingIdentity(action);
}
+ final <T> T binderWithCleanCallingIdentity(@NonNull ThrowingSupplier<T> action) {
+ return Binder.withCleanCallingIdentity(action);
+ }
+
final int userHandleGetCallingUserId() {
return UserHandle.getUserId(binderGetCallingUid());
}
@@ -2363,12 +2375,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
* @return
*/
DevicePolicyData getUserDataUnchecked(int userHandle) {
- long ident = mInjector.binderClearCallingIdentity();
- try {
- return getUserData(userHandle);
- } finally {
- mInjector.binderRestoreCallingIdentity(ident);
- }
+ return mInjector.binderWithCleanCallingIdentity(() -> getUserData(userHandle));
}
void removeUserData(int userHandle) {
@@ -2400,7 +2407,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
setDeviceOwnerSystemPropertyLocked();
findOwnerComponentIfNecessaryLocked();
migrateUserRestrictionsIfNecessaryLocked();
- maybeSetDefaultDeviceOwnerUserRestrictionsLocked();
// TODO PO may not have a class name either due to b/17652534. Address that too.
@@ -2408,15 +2414,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
}
- /** Apply default restrictions that haven't been applied to device owners yet. */
- private void maybeSetDefaultDeviceOwnerUserRestrictionsLocked() {
- final ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked();
- if (deviceOwner != null) {
- maybeSetDefaultRestrictionsForAdminLocked(mOwners.getDeviceOwnerUserId(),
- deviceOwner, UserRestrictionsUtils.getDefaultEnabledForDeviceOwner());
- }
- }
-
/** Apply default restrictions that haven't been applied to profile owners yet. */
private void maybeSetDefaultProfileOwnerUserRestrictions() {
synchronized (getLockObject()) {
@@ -2695,8 +2692,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
alarmTime = now + alarmInterval;
}
- long token = mInjector.binderClearCallingIdentity();
- try {
+ mInjector.binderWithCleanCallingIdentity(() -> {
int affectedUserHandle = parent ? getProfileParentId(userHandle) : userHandle;
AlarmManager am = mInjector.getAlarmManager();
PendingIntent pi = PendingIntent.getBroadcastAsUser(context, REQUEST_EXPIRE_PASSWORD,
@@ -2707,9 +2703,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (alarmTime != 0) {
am.set(AlarmManager.RTC, alarmTime, pi);
}
- } finally {
- mInjector.binderRestoreCallingIdentity(token);
- }
+ });
}
ActiveAdmin getActiveAdminUncheckedLocked(ComponentName who, int userHandle) {
@@ -3273,12 +3267,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
private void sendChangedNotification(int userHandle) {
Intent intent = new Intent(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- long ident = mInjector.binderClearCallingIdentity();
- try {
- mContext.sendBroadcastAsUser(intent, new UserHandle(userHandle));
- } finally {
- mInjector.binderRestoreCallingIdentity(ident);
- }
+ mInjector.binderWithCleanCallingIdentity(() ->
+ mContext.sendBroadcastAsUser(intent, new UserHandle(userHandle)));
}
private void loadSettingsLocked(DevicePolicyData policy, int userHandle) {
@@ -3846,8 +3836,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
/* throwForMissingPermission= */ true);
synchronized (getLockObject()) {
checkActiveAdminPrecondition(adminReceiver, info, policy);
- long ident = mInjector.binderClearCallingIdentity();
- try {
+ mInjector.binderWithCleanCallingIdentity(() -> {
final ActiveAdmin existingAdmin
= getActiveAdminUncheckedLocked(adminReceiver, userHandle);
if (!refreshing && existingAdmin != null) {
@@ -3878,9 +3867,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
saveSettingsLocked(userHandle);
sendAdminCommandLocked(newAdmin, DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED,
onEnableData, null);
- } finally {
- mInjector.binderRestoreCallingIdentity(ident);
- }
+ });
}
}
@@ -4062,8 +4049,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
Preconditions.checkNotNull(adminReceiver, "ComponentName is null");
enforceShell("forceRemoveActiveAdmin");
- long ident = mInjector.binderClearCallingIdentity();
- try {
+ mInjector.binderWithCleanCallingIdentity(() -> {
synchronized (getLockObject()) {
if (!isAdminTestOnlyLocked(adminReceiver, userHandle)) {
throw new SecurityException("Attempt to remove non-test admin "
@@ -4083,9 +4069,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
// Remove the admin skipping sending the broadcast.
removeAdminArtifacts(adminReceiver, userHandle);
Slog.i(LOG_TAG, "Admin " + adminReceiver + " removed from user " + userHandle);
- } finally {
- mInjector.binderRestoreCallingIdentity(ident);
- }
+ });
}
private void clearDeviceOwnerUserRestrictionLocked(UserHandle userHandle) {
@@ -4160,12 +4144,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.MANAGE_DEVICE_ADMINS, null);
}
- long ident = mInjector.binderClearCallingIdentity();
- try {
- removeActiveAdminLocked(adminReceiver, userHandle);
- } finally {
- mInjector.binderRestoreCallingIdentity(ident);
- }
+ mInjector.binderWithCleanCallingIdentity(() ->
+ removeActiveAdminLocked(adminReceiver, userHandle));
}
}
@@ -4191,8 +4171,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
synchronized (getLockObject()) {
ActiveAdmin ap = getActiveAdminForCallerLocked(
who, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, parent);
- final long ident = mInjector.binderClearCallingIdentity();
- try {
+ mInjector.binderWithCleanCallingIdentity(() -> {
final PasswordPolicy passwordPolicy = ap.mPasswordPolicy;
if (passwordPolicy.quality != quality) {
passwordPolicy.quality = quality;
@@ -4202,9 +4181,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
saveSettingsLocked(userId);
}
maybeLogPasswordComplexitySet(who, userId, parent, passwordPolicy);
- } finally {
- mInjector.binderRestoreCallingIdentity(ident);
- }
+ });
}
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SET_PASSWORD_QUALITY)
@@ -4391,12 +4368,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
private boolean isSeparateProfileChallengeEnabled(int userHandle) {
- long ident = mInjector.binderClearCallingIdentity();
- try {
- return mLockPatternUtils.isSeparateProfileChallengeEnabled(userHandle);
- } finally {
- mInjector.binderRestoreCallingIdentity(ident);
- }
+ return mInjector.binderWithCleanCallingIdentity(() ->
+ mLockPatternUtils.isSeparateProfileChallengeEnabled(userHandle));
}
@Override
@@ -5133,12 +5106,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
private UserInfo getUserInfo(@UserIdInt int userId) {
- final long token = mInjector.binderClearCallingIdentity();
- try {
- return mUserManager.getUserInfo(userId);
- } finally {
- mInjector.binderRestoreCallingIdentity(token);
- }
+ return mInjector.binderWithCleanCallingIdentity(() -> mUserManager.getUserInfo(userId));
}
private boolean setPasswordPrivileged(@NonNull String password, int flags, int callingUid) {
@@ -5263,12 +5231,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
private boolean isLockScreenSecureUnchecked(int userId) {
- long ident = mInjector.binderClearCallingIdentity();
- try {
- return mLockPatternUtils.isSecure(userId);
- } finally {
- mInjector.binderRestoreCallingIdentity(ident);
- }
+ return mInjector.binderWithCleanCallingIdentity(() -> mLockPatternUtils.isSecure(userId));
}
private void setDoNotAskCredentialsOnBoot() {
@@ -5320,12 +5283,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
updateProfileLockTimeoutLocked(userId);
}
- final long timeMs;
- final long ident = mInjector.binderClearCallingIdentity();
- try {
+ mInjector.binderWithCleanCallingIdentity(() -> {
// Update the device timeout
final int parentId = getProfileParentId(userId);
- timeMs = getMaximumTimeToLockPolicyFromAdmins(
+ final long timeMs = getMaximumTimeToLockPolicyFromAdmins(
getActiveAdminsForLockscreenPoliciesLocked(parentId, false));
final DevicePolicyData policy = getUserDataUnchecked(parentId);
@@ -5341,9 +5302,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
getPowerManagerInternal().setMaximumScreenOffTimeoutFromDeviceAdmin(
UserHandle.USER_SYSTEM, timeMs);
- } finally {
- mInjector.binderRestoreCallingIdentity(ident);
- }
+ });
}
private void updateProfileLockTimeoutLocked(@UserIdInt int userId) {
@@ -5361,13 +5320,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
policy.mLastMaximumTimeToLock = timeMs;
- final long ident = mInjector.binderClearCallingIdentity();
- try {
- getPowerManagerInternal().setMaximumScreenOffTimeoutFromDeviceAdmin(
- userId, policy.mLastMaximumTimeToLock);
- } finally {
- mInjector.binderRestoreCallingIdentity(ident);
- }
+ mInjector.binderWithCleanCallingIdentity(() ->
+ getPowerManagerInternal().setMaximumScreenOffTimeoutFromDeviceAdmin(
+ userId, policy.mLastMaximumTimeToLock));
}
@Override
@@ -5635,24 +5590,21 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
enforceCanManageCaCerts(admin, callerPackage);
- final String alias;
-
final UserHandle userHandle = mInjector.binderGetCallingUserHandle();
- final long id = mInjector.binderClearCallingIdentity();
- try {
- alias = mCertificateMonitor.installCaCert(userHandle, certBuffer);
+ final String alias = mInjector.binderWithCleanCallingIdentity(() -> {
+ String installedAlias = mCertificateMonitor.installCaCert(userHandle, certBuffer);
final boolean isDelegate = (admin == null);
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.INSTALL_CA_CERT)
.setAdmin(callerPackage)
.setBoolean(isDelegate)
.write();
- if (alias == null) {
- Log.w(LOG_TAG, "Problem installing cert");
- return false;
- }
- } finally {
- mInjector.binderRestoreCallingIdentity(id);
+ return installedAlias;
+ });
+
+ if (alias == null) {
+ Log.w(LOG_TAG, "Problem installing cert");
+ return false;
}
synchronized (getLockObject()) {
@@ -5670,8 +5622,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
enforceCanManageCaCerts(admin, callerPackage);
final int userId = mInjector.userHandleGetCallingUserId();
- final long id = mInjector.binderClearCallingIdentity();
- try {
+ mInjector.binderWithCleanCallingIdentity(() -> {
mCertificateMonitor.uninstallCaCerts(UserHandle.of(userId), aliases);
final boolean isDelegate = (admin == null);
DevicePolicyEventLogger
@@ -5679,9 +5630,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
.setAdmin(callerPackage)
.setBoolean(isDelegate)
.write();
- } finally {
- mInjector.binderRestoreCallingIdentity(id);
- }
+ });
synchronized (getLockObject()) {
if (getUserData(userId).mOwnerInstalledCaCerts.removeAll(Arrays.asList(aliases))) {
@@ -5877,7 +5826,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
idTypeToAttestationFlag.put(ID_TYPE_IMEI, AttestationUtils.ID_TYPE_IMEI);
idTypeToAttestationFlag.put(ID_TYPE_MEID, AttestationUtils.ID_TYPE_MEID);
idTypeToAttestationFlag.put(
- ID_TYPE_INDIVIDUAL_ATTESTATION, AttestationUtils.USE_INDIVIDUAL_ATTESTATION);
+ ID_TYPE_INDIVIDUAL_ATTESTATION, USE_INDIVIDUAL_ATTESTATION);
int numFlagsSet = Integer.bitCount(idAttestationFlags);
// No flags are set - return null to indicate no device ID attestation information should
@@ -5917,6 +5866,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (deviceIdAttestationRequired && attestationUtilsFlags.length > 0) {
enforceCallerCanRequestDeviceIdAttestation(who, callerPackage, callingUid);
+ enforceIndividualAttestationSupportedIfRequested(attestationUtilsFlags);
} else {
enforceCanManageScope(who, callerPackage, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER,
DELEGATION_CERT_INSTALL);
@@ -6011,6 +5961,17 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return false;
}
+ private void enforceIndividualAttestationSupportedIfRequested(int[] attestationUtilsFlags) {
+ for (int attestationFlag : attestationUtilsFlags) {
+ if (attestationFlag == USE_INDIVIDUAL_ATTESTATION
+ && !mInjector.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_DEVICE_UNIQUE_ATTESTATION)) {
+ throw new UnsupportedOperationException("Device Individual attestation is not "
+ + "supported on this device.");
+ }
+ }
+ }
+
@Override
public boolean setKeyPairCertificate(ComponentName who, String callerPackage, String alias,
byte[] cert, byte[] chain, boolean isUserSelectable) {
@@ -6085,8 +6046,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
isDelegate = false;
}
- final long id = mInjector.binderClearCallingIdentity();
- try {
+ mInjector.binderWithCleanCallingIdentity(() -> {
mContext.sendOrderedBroadcastAsUser(intent, caller, null, new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -6099,9 +6059,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
.setAdmin(intent.getComponent())
.setBoolean(isDelegate)
.write();
- } finally {
- mInjector.binderRestoreCallingIdentity(id);
- }
+ });
}
private void sendPrivateKeyAliasResponse(final String alias, final IBinder responseBinder) {
@@ -6517,8 +6475,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
enforceProfileOrDeviceOwner(admin);
final int userId = mInjector.userHandleGetCallingUserId();
- final long token = mInjector.binderClearCallingIdentity();
- try {
+ mInjector.binderWithCleanCallingIdentity(() -> {
if (vpnPackage != null && !isPackageInstalledForUser(vpnPackage, userId)) {
Slog.w(LOG_TAG, "Non-existent VPN package specified: " + vpnPackage);
throw new ServiceSpecificException(
@@ -6546,9 +6503,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
.setBoolean(lockdown)
.setInt(lockdownWhitelist != null ? lockdownWhitelist.size() : 0)
.write();
- } finally {
- mInjector.binderRestoreCallingIdentity(token);
- }
+ });
return true;
}
@@ -6557,12 +6512,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
enforceProfileOrDeviceOwner(admin);
final int userId = mInjector.userHandleGetCallingUserId();
- final long token = mInjector.binderClearCallingIdentity();
- try {
- return mInjector.getConnectivityManager().getAlwaysOnVpnPackageForUser(userId);
- } finally {
- mInjector.binderRestoreCallingIdentity(token);
- }
+ return mInjector.binderWithCleanCallingIdentity(
+ () -> mInjector.getConnectivityManager().getAlwaysOnVpnPackageForUser(userId));
}
@Override
@@ -6570,12 +6521,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
enforceProfileOrDeviceOwner(admin);
final int userId = mInjector.userHandleGetCallingUserId();
- final long token = mInjector.binderClearCallingIdentity();
- try {
- return mInjector.getConnectivityManager().isVpnLockdownEnabled(userId);
- } finally {
- mInjector.binderRestoreCallingIdentity(token);
- }
+ return mInjector.binderWithCleanCallingIdentity(
+ () -> mInjector.getConnectivityManager().isVpnLockdownEnabled(userId));
}
@Override
@@ -6584,12 +6531,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
enforceProfileOrDeviceOwner(admin);
final int userId = mInjector.userHandleGetCallingUserId();
- final long token = mInjector.binderClearCallingIdentity();
- try {
- return mInjector.getConnectivityManager().getVpnLockdownWhitelist(userId);
- } finally {
- mInjector.binderRestoreCallingIdentity(token);
- }
+ return mInjector.binderWithCleanCallingIdentity(
+ () -> mInjector.getConnectivityManager().getVpnLockdownWhitelist(userId));
}
private void forceWipeDeviceNoLock(boolean wipeExtRequested, String reason, boolean wipeEuicc) {
@@ -6686,8 +6629,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
// control over the device, wiping only the work profile. So the user restriction
// on profile removal needs to be removed first.
- final long ident = mInjector.binderClearCallingIdentity();
- try {
+ mInjector.binderWithCleanCallingIdentity(() -> {
// Clear restriction as user.
mUserManager.setUserRestriction(
UserManager.DISALLOW_REMOVE_MANAGED_PROFILE, false,
@@ -6695,9 +6637,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
// Device-wide policies set by the profile owner need to be cleaned up here.
mLockPatternUtils.setDeviceOwnerInfo(null);
- } finally {
- mInjector.binderRestoreCallingIdentity(ident);
- }
+ });
}
}
@@ -6719,8 +6659,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
String wipeReasonForUser, int userId) {
wtfIfInLock();
- long ident = mInjector.binderClearCallingIdentity();
- try {
+ mInjector.binderWithCleanCallingIdentity(() -> {
// First check whether the admin is allowed to wipe the device/user/profile.
final String restriction;
if (userId == UserHandle.USER_SYSTEM) {
@@ -6754,9 +6693,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
} else {
forceWipeUser(userId, wipeReasonForUser, (flags & WIPE_SILENTLY) != 0);
}
- } finally {
- mInjector.binderRestoreCallingIdentity(ident);
- }
+ });
}
private void sendWipeProfileNotification(String wipeReasonForUser) {
@@ -6931,8 +6868,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
synchronized (getLockObject()) {
DevicePolicyData policy = getUserData(userHandle);
if (policy.mFailedPasswordAttempts != 0 || policy.mPasswordOwner >= 0) {
- long ident = mInjector.binderClearCallingIdentity();
- try {
+ mInjector.binderWithCleanCallingIdentity(() -> {
policy.mFailedPasswordAttempts = 0;
policy.mPasswordOwner = -1;
saveSettingsLocked(userHandle);
@@ -6941,9 +6877,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
DeviceAdminReceiver.ACTION_PASSWORD_SUCCEEDED,
DeviceAdminInfo.USES_POLICY_WATCH_LOGIN, userHandle);
}
- } finally {
- mInjector.binderRestoreCallingIdentity(ident);
- }
+ });
}
}
@@ -7042,12 +6976,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
// Reset the global proxy accordingly
// Do this using system permissions, as apps cannot write to secure settings
- long origId = mInjector.binderClearCallingIdentity();
- try {
- resetGlobalProxyLocked(policy);
- } finally {
- mInjector.binderRestoreCallingIdentity(origId);
- }
+ mInjector.binderWithCleanCallingIdentity(() -> resetGlobalProxyLocked(policy));
return null;
}
}
@@ -7079,12 +7008,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Override
public void setRecommendedGlobalProxy(ComponentName who, ProxyInfo proxyInfo) {
enforceDeviceOwner(who);
- long token = mInjector.binderClearCallingIdentity();
- try {
- mInjector.getConnectivityManager().setGlobalProxy(proxyInfo);
- } finally {
- mInjector.binderRestoreCallingIdentity(token);
- }
+ mInjector.binderWithCleanCallingIdentity(
+ () -> mInjector.getConnectivityManager().setGlobalProxy(proxyInfo));
}
private void resetGlobalProxyLocked(DevicePolicyData policy) {
@@ -7376,12 +7301,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
// TODO: (b/145604635) Add upgrade case
// Turn AUTO_TIME on in settings if it is required
if (required) {
- long ident = mInjector.binderClearCallingIdentity();
- try {
- mInjector.settingsGlobalPutInt(Settings.Global.AUTO_TIME, 1 /* AUTO_TIME on */);
- } finally {
- mInjector.binderRestoreCallingIdentity(ident);
- }
+ mInjector.binderWithCleanCallingIdentity(
+ () -> mInjector.settingsGlobalPutInt(Settings.Global.AUTO_TIME,
+ 1 /* AUTO_TIME on */));
}
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SET_AUTO_TIME_REQUIRED)
@@ -7512,12 +7434,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
}
if (removeAllUsers) {
- long identitity = mInjector.binderClearCallingIdentity();
- try {
- mUserManagerInternal.removeAllUsers();
- } finally {
- mInjector.binderRestoreCallingIdentity(identitity);
- }
+ mInjector.binderWithCleanCallingIdentity(() -> mUserManagerInternal.removeAllUsers());
}
}
@@ -8030,25 +7947,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
updateDeviceOwnerLocked();
setDeviceOwnerSystemPropertyLocked();
- final Set<String> restrictions =
- UserRestrictionsUtils.getDefaultEnabledForDeviceOwner();
- if (!restrictions.isEmpty()) {
- for (String restriction : restrictions) {
- activeAdmin.ensureUserRestrictions().putBoolean(restriction, true);
- }
- activeAdmin.defaultEnabledRestrictionsAlreadySet.addAll(restrictions);
- Slog.i(LOG_TAG, "Enabled the following restrictions by default: " + restrictions);
-
- saveUserRestrictionsLocked(userId, /* parent = */ false);
- }
-
- long ident = mInjector.binderClearCallingIdentity();
- try {
- // TODO Send to system too?
- sendOwnerChangedBroadcast(DevicePolicyManager.ACTION_DEVICE_OWNER_CHANGED, userId);
- } finally {
- mInjector.binderRestoreCallingIdentity(ident);
- }
+ // TODO Send to system too?
+ mInjector.binderWithCleanCallingIdentity(
+ () -> sendOwnerChangedBroadcast(DevicePolicyManager.ACTION_DEVICE_OWNER_CHANGED,
+ userId));
mDeviceAdminServiceController.startServiceForOwner(
admin.getPackageName(), userId, "set-device-owner");
@@ -8229,15 +8131,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
final ActiveAdmin admin = getDeviceOwnerAdminLocked();
- long ident = mInjector.binderClearCallingIdentity();
- try {
+ mInjector.binderWithCleanCallingIdentity(() -> {
clearDeviceOwnerLocked(admin, deviceOwnerUserId);
removeActiveAdminLocked(deviceOwnerComponent, deviceOwnerUserId);
sendOwnerChangedBroadcast(DevicePolicyManager.ACTION_DEVICE_OWNER_CHANGED,
deviceOwnerUserId);
- } finally {
- mInjector.binderRestoreCallingIdentity(ident);
- }
+ });
Slog.i(LOG_TAG, "Device owner removed: " + deviceOwnerComponent);
}
}
@@ -8323,8 +8222,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
mOwners.writeProfileOwner(userHandle);
Slog.i(LOG_TAG, "Profile owner set: " + who + " on user " + userHandle);
- final long id = mInjector.binderClearCallingIdentity();
- try {
+ mInjector.binderWithCleanCallingIdentity(() -> {
if (mUserManager.isManagedProfile(userHandle)) {
maybeSetDefaultRestrictionsForAdminLocked(userHandle, admin,
UserRestrictionsUtils.getDefaultEnabledForManagedProfiles());
@@ -8333,9 +8231,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
sendOwnerChangedBroadcast(DevicePolicyManager.ACTION_PROFILE_OWNER_CHANGED,
userHandle);
- } finally {
- mInjector.binderRestoreCallingIdentity(id);
- }
+ });
mDeviceAdminServiceController.startServiceForOwner(
who.getPackageName(), userHandle, "set-profile-owner");
return true;
@@ -8373,15 +8269,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final ActiveAdmin admin =
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
- final long ident = mInjector.binderClearCallingIdentity();
- try {
+ mInjector.binderWithCleanCallingIdentity(() -> {
clearProfileOwnerLocked(admin, userId);
removeActiveAdminLocked(who, userId);
sendOwnerChangedBroadcast(DevicePolicyManager.ACTION_PROFILE_OWNER_CHANGED,
userId);
- } finally {
- mInjector.binderRestoreCallingIdentity(ident);
- }
+ });
Slog.i(LOG_TAG, "Profile owner " + who + " removed from user " + userId);
}
}
@@ -8590,8 +8483,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
"setProfileEnabled is called when the profile is already enabled");
return;
}
- long id = mInjector.binderClearCallingIdentity();
- try {
+ mInjector.binderWithCleanCallingIdentity(() -> {
mUserManager.setUserEnabled(userId);
UserInfo parent = mUserManager.getProfileParent(userId);
Intent intent = new Intent(Intent.ACTION_MANAGED_PROFILE_ADDED);
@@ -8599,9 +8491,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY |
Intent.FLAG_RECEIVER_FOREGROUND);
mContext.sendBroadcastAsUser(intent, new UserHandle(parent.id));
- } finally {
- mInjector.binderRestoreCallingIdentity(id);
- }
+ });
}
}
@@ -8611,16 +8501,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
enforceProfileOrDeviceOwner(who);
final int userId = UserHandle.getCallingUserId();
- final long id = mInjector.binderClearCallingIdentity();
- try {
+ mInjector.binderWithCleanCallingIdentity(() -> {
mUserManager.setUserName(userId, profileName);
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SET_PROFILE_NAME)
.setAdmin(who)
.write();
- } finally {
- mInjector.binderRestoreCallingIdentity(id);
- }
+ });
}
@Override
@@ -8662,8 +8549,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@GuardedBy("getLockObject()")
ActiveAdmin getProfileOwnerOfOrganizationOwnedDeviceLocked(int userHandle) {
- final long ident = mInjector.binderClearCallingIdentity();
- try {
+ return mInjector.binderWithCleanCallingIdentity(() -> {
for (UserInfo userInfo : mUserManager.getProfiles(userHandle)) {
if (userInfo.isManagedProfile()) {
if (getProfileOwner(userInfo.id) != null
@@ -8673,10 +8559,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
}
}
- } finally {
- mInjector.binderRestoreCallingIdentity(ident);
- }
- return null;
+ return null;
+ });
}
@Override
@@ -8717,9 +8601,15 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
// Allow access to the profile owner for the specified user, or delegate cert installer
// But only if this is an organization-owned device.
ComponentName profileOwner = getProfileOwnerAsUser(userId);
- if (profileOwner != null && canProfileOwnerAccessDeviceIds(userId)
+ final boolean isCallerProfileOwnerOrDelegate = profileOwner != null
&& (profileOwner.getPackageName().equals(packageName)
- || isCallerDelegate(packageName, uid, DELEGATION_CERT_INSTALL))) {
+ || isCallerDelegate(packageName, uid, DELEGATION_CERT_INSTALL));
+ if (isCallerProfileOwnerOrDelegate && canProfileOwnerAccessDeviceIds(userId)) {
+ return true;
+ }
+ //TODO(b/130844684): Temporarily allow profile owner on non-organization-owned devices
+ //to read device identifiers.
+ if (isCallerProfileOwnerOrDelegate) {
return true;
}
@@ -8773,8 +8663,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
* Canonical name for a given package.
*/
private String getApplicationLabel(String packageName, int userHandle) {
- long token = mInjector.binderClearCallingIdentity();
- try {
+ return mInjector.binderWithCleanCallingIdentity(() -> {
final Context userContext;
try {
UserHandle handle = new UserHandle(userHandle);
@@ -8789,9 +8678,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
result = appInfo.loadUnsafeLabel(userContext.getPackageManager());
}
return result != null ? result.toString() : null;
- } finally {
- mInjector.binderRestoreCallingIdentity(token);
- }
+ });
}
/**
@@ -9082,28 +8969,23 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
protected int getProfileParentId(int userHandle) {
- final long ident = mInjector.binderClearCallingIdentity();
- try {
+ return mInjector.binderWithCleanCallingIdentity(() -> {
UserInfo parentUser = mUserManager.getProfileParent(userHandle);
return parentUser != null ? parentUser.id : userHandle;
- } finally {
- mInjector.binderRestoreCallingIdentity(ident);
- }
+ });
}
- private int getCredentialOwner(int userHandle, boolean parent) {
- final long ident = mInjector.binderClearCallingIdentity();
- try {
+ private int getCredentialOwner(final int userHandle, final boolean parent) {
+ return mInjector.binderWithCleanCallingIdentity(() -> {
+ int effectiveUserHandle = userHandle;
if (parent) {
UserInfo parentProfile = mUserManager.getProfileParent(userHandle);
if (parentProfile != null) {
- userHandle = parentProfile.id;
+ effectiveUserHandle = parentProfile.id;
}
}
- return mUserManager.getCredentialOwnerProfile(userHandle);
- } finally {
- mInjector.binderRestoreCallingIdentity(ident);
- }
+ return mUserManager.getCredentialOwnerProfile(effectiveUserHandle);
+ });
}
private boolean isManagedProfile(int userHandle) {
@@ -9290,8 +9172,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
DELEGATION_APP_RESTRICTIONS);
final UserHandle userHandle = mInjector.binderGetCallingUserHandle();
- final long id = mInjector.binderClearCallingIdentity();
- try {
+ mInjector.binderWithCleanCallingIdentity(() -> {
mUserManager.setApplicationRestrictions(packageName, settings, userHandle);
final boolean isDelegate = (who == null);
DevicePolicyEventLogger
@@ -9300,9 +9181,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
.setBoolean(isDelegate)
.setStrings(packageName)
.write();
- } finally {
- mInjector.binderRestoreCallingIdentity(id);
- }
+ });
}
@Override
@@ -10045,8 +9924,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
enforceDeviceOwner(who);
final int callingUserId = mInjector.userHandleGetCallingUserId();
- final long id = mInjector.binderClearCallingIdentity();
- try {
+ return mInjector.binderWithCleanCallingIdentity(() -> {
String restriction = isManagedProfile(userHandle.getIdentifier())
? UserManager.DISALLOW_REMOVE_MANAGED_PROFILE
: UserManager.DISALLOW_REMOVE_USER;
@@ -10056,9 +9934,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return false;
}
return mUserManagerInternal.removeUserEvenWhenDisallowed(userHandle.getIdentifier());
- } finally {
- mInjector.binderRestoreCallingIdentity(id);
- }
+ });
}
private boolean isAdminAffectedByRestriction(
@@ -10204,8 +10080,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Preconditions.checkNotNull(who, "ComponentName is null");
enforceDeviceOwner(who);
- final long id = mInjector.binderClearCallingIdentity();
- try {
+ return mInjector.binderWithCleanCallingIdentity(() -> {
final List<UserInfo> userInfos = mInjector.getUserManager().getUsers(true
/*excludeDying*/);
final List<UserHandle> userHandles = new ArrayList<>();
@@ -10216,9 +10091,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
}
return userHandles;
- } finally {
- mInjector.binderRestoreCallingIdentity(id);
- }
+ });
}
@Override
@@ -10227,12 +10100,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
enforceProfileOrDeviceOwner(who);
final int callingUserId = mInjector.userHandleGetCallingUserId();
- final long id = mInjector.binderClearCallingIdentity();
- try {
- return mInjector.getUserManager().isUserEphemeral(callingUserId);
- } finally {
- mInjector.binderRestoreCallingIdentity(id);
- }
+ return mInjector.binderWithCleanCallingIdentity(
+ () -> mInjector.getUserManager().isUserEphemeral(callingUserId));
}
@Override
@@ -10242,15 +10111,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
DELEGATION_APP_RESTRICTIONS);
final UserHandle userHandle = mInjector.binderGetCallingUserHandle();
- final long id = mInjector.binderClearCallingIdentity();
- try {
- Bundle bundle = mUserManager.getApplicationRestrictions(packageName, userHandle);
+ return mInjector.binderWithCleanCallingIdentity(() -> {
+ Bundle bundle = mUserManager.getApplicationRestrictions(packageName, userHandle);
// if no restrictions were saved, mUserManager.getApplicationRestrictions
// returns null, but DPM method should return an empty Bundle as per JavaDoc
return bundle != null ? bundle : Bundle.EMPTY;
- } finally {
- mInjector.binderRestoreCallingIdentity(id);
- }
+ });
}
@Override
@@ -10384,8 +10250,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (deviceOwner == null) {
return; // Shouldn't happen.
}
- userRestrictions = deviceOwner.userRestrictions;
- addOrRemoveDisableCameraRestriction(userRestrictions, deviceOwner);
+ userRestrictions = addOrRemoveDisableCameraRestriction(
+ deviceOwner.userRestrictions, deviceOwner);
restrictionOwnerType = UserManagerInternal.OWNER_TYPE_DEVICE_OWNER;
originatingUserId = deviceOwner.getUserHandle().getIdentifier();
} else {
@@ -10419,6 +10285,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
userRestrictions, userId);
}
}
+ // Remove deprecated restrictions.
+ for (String deprecatedRestriction: DEPRECATED_USER_RESTRICTIONS) {
+ userRestrictions.remove(deprecatedRestriction);
+ }
mUserManagerInternal.setDevicePolicyUserRestrictions(originatingUserId,
userRestrictions, restrictionOwnerType);
}
@@ -10871,8 +10741,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
actualContactId, isContactIdIgnored, actualDirectoryId, originalIntent);
final int callingUserId = UserHandle.getCallingUserId();
- final long ident = mInjector.binderClearCallingIdentity();
- try {
+ mInjector.binderWithCleanCallingIdentity(() -> {
synchronized (getLockObject()) {
final int managedUserId = getManagedUserId(callingUserId);
if (managedUserId < 0) {
@@ -10888,9 +10757,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
ContactsInternal.startQuickContactWithErrorToastForUser(
mContext, intent, new UserHandle(managedUserId));
}
- } finally {
- mInjector.binderRestoreCallingIdentity(ident);
- }
+ });
}
/**
@@ -11050,8 +10917,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
private void maybeClearLockTaskPolicyLocked() {
- final long ident = mInjector.binderClearCallingIdentity();
- try {
+ mInjector.binderWithCleanCallingIdentity(() -> {
final List<UserInfo> userInfos = mUserManager.getUsers(/*excludeDying=*/ true);
for (int i = userInfos.size() - 1; i >= 0; i--) {
int userId = userInfos.get(i).id;
@@ -11072,9 +10938,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
setLockTaskFeaturesLocked(userId, DevicePolicyManager.LOCK_TASK_FEATURE_NONE);
}
}
- } finally {
- mInjector.binderRestoreCallingIdentity(ident);
- }
+ });
}
@Override
@@ -11147,12 +11011,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
}
- long id = mInjector.binderClearCallingIdentity();
- try {
- mInjector.settingsGlobalPutString(setting, value);
- } finally {
- mInjector.binderRestoreCallingIdentity(id);
- }
+ mInjector.binderWithCleanCallingIdentity(
+ () -> mInjector.settingsGlobalPutString(setting, value));
}
}
@@ -11272,8 +11132,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
return;
}
- long id = mInjector.binderClearCallingIdentity();
- try {
+ mInjector.binderWithCleanCallingIdentity(() -> {
if (Settings.Secure.DEFAULT_INPUT_METHOD.equals(setting)) {
final String currentValue = mInjector.settingsSecureGetStringForUser(
Settings.Secure.DEFAULT_INPUT_METHOD, callingUserId);
@@ -11289,9 +11148,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
saveSettingsLocked(callingUserId);
}
mInjector.settingsSecurePutStringForUser(setting, value, callingUserId);
- } finally {
- mInjector.binderRestoreCallingIdentity(id);
- }
+ });
}
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SET_SECURE_SETTING)
@@ -11333,12 +11190,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
int userId = UserHandle.getCallingUserId();
- long id = mInjector.binderClearCallingIdentity();
- try {
- mUserManagerInternal.setUserIcon(userId, icon);
- } finally {
- mInjector.binderRestoreCallingIdentity(id);
- }
+ mInjector.binderWithCleanCallingIdentity(
+ () -> mUserManagerInternal.setUserIcon(userId, icon));
}
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SET_USER_ICON)
@@ -11737,15 +11590,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Override
public void reportSeparateProfileChallengeChanged(@UserIdInt int userId) {
- final long ident = mInjector.binderClearCallingIdentity();
- try {
+ mInjector.binderWithCleanCallingIdentity(() -> {
synchronized (getLockObject()) {
updateMaximumTimeToLockLocked(userId);
updatePasswordQualityCacheForUserGroup(userId);
}
- } finally {
- mInjector.binderRestoreCallingIdentity(ident);
- }
+ });
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SEPARATE_PROFILE_CHALLENGE_CHANGED)
.setBoolean(isSeparateProfileChallengeEnabled(userId))
@@ -12037,8 +11887,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
.putExtra(DeviceAdminReceiver.EXTRA_SYSTEM_UPDATE_RECEIVED_TIME,
info == null ? -1 : info.getReceivedTime());
- final long ident = mInjector.binderClearCallingIdentity();
- try {
+ mInjector.binderWithCleanCallingIdentity(() -> {
synchronized (getLockObject()) {
// Broadcast to device owner first if there is one.
if (mOwners.hasDeviceOwner()) {
@@ -12068,9 +11917,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
}
}
- } finally {
- mInjector.binderRestoreCallingIdentity(ident);
- }
+ });
}
@Override
@@ -12194,8 +12041,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, DELEGATION_PERMISSION_GRANT);
}
synchronized (getLockObject()) {
- long ident = mInjector.binderClearCallingIdentity();
- try {
+ return mInjector.binderWithCleanCallingIdentity(() -> {
int granted;
if (getTargetSdk(callerPackage, user.getIdentifier())
< android.os.Build.VERSION_CODES.Q) {
@@ -12230,9 +12076,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
? DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED
: DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED;
}
- } finally {
- mInjector.binderRestoreCallingIdentity(ident);
- }
+ });
}
}
@@ -12472,8 +12316,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
// Make sure caller has DO.
enforceDeviceOwnerOrProfileOwnerOnOrganizationOwnedDevice(admin);
- final long ident = mInjector.binderClearCallingIdentity();
- try {
+ return mInjector.binderWithCleanCallingIdentity(() -> {
String[] macAddresses = mInjector.getWifiManager().getFactoryMacAddresses();
if (macAddresses == null) {
return null;
@@ -12483,9 +12326,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
.setAdmin(admin)
.write();
return macAddresses.length > 0 ? macAddresses[0] : null;
- } finally {
- mInjector.binderRestoreCallingIdentity(ident);
- }
+ });
}
/**
@@ -12521,8 +12362,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Preconditions.checkNotNull(admin);
// Make sure caller has DO.
enforceDeviceOwner(admin);
- long ident = mInjector.binderClearCallingIdentity();
- try {
+ mInjector.binderWithCleanCallingIdentity(() -> {
// Make sure there are no ongoing calls on the device.
if (mTelephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE) {
throw new IllegalStateException("Cannot be called with ongoing call on the device");
@@ -12532,9 +12372,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
.setAdmin(admin)
.write();
mInjector.powerManagerReboot(PowerManager.REBOOT_REQUESTED_BY_DEVICE_OWNER);
- } finally {
- mInjector.binderRestoreCallingIdentity(ident);
- }
+ });
}
@Override
@@ -12771,17 +12609,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final ActiveAdmin admin = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
final int callingUserId = mInjector.userHandleGetCallingUserId();
- final long identity = mInjector.binderClearCallingIdentity();
- try {
+ return mInjector.binderWithCleanCallingIdentity(() -> {
final List<String> excludedPkgs
= removeInvalidPkgsForMeteredDataRestriction(callingUserId, packageNames);
admin.meteredDisabledPackages = packageNames;
pushMeteredDisabledPackagesLocked(callingUserId);
saveSettingsLocked(callingUserId);
return excludedPkgs;
- } finally {
- mInjector.binderRestoreCallingIdentity(identity);
- }
+ });
}
}
@@ -12894,8 +12729,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
who.flattenToString(), userId));
// First, set restriction on removing the profile.
- final long ident = mInjector.binderClearCallingIdentity();
- try {
+ mInjector.binderWithCleanCallingIdentity(() -> {
// Clear restriction as user.
UserHandle parentUser = mUserManager.getProfileParent(UserHandle.of(userId));
if (!parentUser.isSystem()) {
@@ -12907,9 +12741,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
mUserManager.setUserRestriction(UserManager.DISALLOW_REMOVE_MANAGED_PROFILE, true,
parentUser);
- } finally {
- mInjector.binderRestoreCallingIdentity(ident);
- }
+ });
// markProfileOwnerOfOrganizationOwnedDevice will trigger writing of the profile owner
// data, no need to do it manually.
@@ -13027,8 +12859,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
private boolean areAllUsersAffiliatedWithDeviceLocked() {
- final long ident = mInjector.binderClearCallingIdentity();
- try {
+ return mInjector.binderWithCleanCallingIdentity(() -> {
final List<UserInfo> userInfos = mUserManager.getUsers(/*excludeDying=*/ true);
for (int i = 0; i < userInfos.size(); i++) {
int userId = userInfos.get(i).id;
@@ -13037,11 +12868,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return false;
}
}
- } finally {
- mInjector.binderRestoreCallingIdentity(ident);
- }
-
- return true;
+ return true;
+ });
}
@Override
@@ -13251,12 +13079,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
private boolean isCurrentUserDemo() {
if (UserManager.isDeviceInDemoMode(mContext)) {
final int userId = mInjector.userHandleGetCallingUserId();
- final long callingIdentity = mInjector.binderClearCallingIdentity();
- try {
- return mUserManager.getUserInfo(userId).isDemo();
- } finally {
- mInjector.binderRestoreCallingIdentity(callingIdentity);
- }
+ return mInjector.binderWithCleanCallingIdentity(
+ () -> mUserManager.getUserInfo(userId).isDemo());
}
return false;
}
@@ -13472,8 +13296,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
final int callingUserId = mInjector.userHandleGetCallingUserId();
- final long callingIdentity = mInjector.binderClearCallingIdentity();
- try {
+ return mInjector.binderWithCleanCallingIdentity(() -> {
ArrayList<UserHandle> targetUsers = new ArrayList<>();
if (!isDeviceOwner(admin, callingUserId)) {
// Profile owners can only bind to the device owner.
@@ -13492,9 +13315,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
return targetUsers;
- } finally {
- mInjector.binderRestoreCallingIdentity(callingIdentity);
- }
+ });
}
}
@@ -13535,8 +13356,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
wtfIfInLock();
- final long token = mInjector.binderClearCallingIdentity();
- try {
+ return mInjector.binderWithCleanCallingIdentity(() -> {
final AccountManager am = AccountManager.get(mContext);
final Account accounts[] = am.getAccountsAsUser(userId);
if (accounts.length == 0) {
@@ -13574,9 +13394,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Log.e(LOG_TAG, "Found incompatible accounts");
}
return !compatible;
- } finally {
- mInjector.binderRestoreCallingIdentity(token);
- }
+ });
}
private boolean hasAccountFeatures(AccountManager am, Account account, String[] features) {
@@ -13629,8 +13447,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
private void setNetworkLoggingActiveInternal(boolean active) {
synchronized (getLockObject()) {
- final long callingIdentity = mInjector.binderClearCallingIdentity();
- try {
+ mInjector.binderWithCleanCallingIdentity(() -> {
if (active) {
mNetworkLogger = new NetworkLogger(this, mInjector.getPackageManagerInternal());
if (!mNetworkLogger.startNetworkLogging()) {
@@ -13648,9 +13465,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
mNetworkLogger = null;
mInjector.getNotificationManager().cancel(SystemMessage.NOTE_NETWORK_LOGGING);
}
- } finally {
- mInjector.binderRestoreCallingIdentity(callingIdentity);
- }
+ });
}
}
@@ -13662,12 +13477,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
throw new IllegalStateException("logging is not available");
}
if (mNetworkLogger != null) {
- final long ident = mInjector.binderClearCallingIdentity();
- try {
- return mNetworkLogger.forceBatchFinalization();
- } finally {
- mInjector.binderRestoreCallingIdentity(ident);
- }
+ return mInjector.binderWithCleanCallingIdentity(
+ () -> mNetworkLogger.forceBatchFinalization());
}
return 0;
}
@@ -13690,15 +13501,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@GuardedBy("getLockObject()")
private void maybeResumeDeviceWideLoggingLocked() {
if (areAllUsersAffiliatedWithDeviceLocked()) {
- final long ident = mInjector.binderClearCallingIdentity();
- try {
+ mInjector.binderWithCleanCallingIdentity(() -> {
mSecurityLogMonitor.resume();
if (mNetworkLogger != null) {
mNetworkLogger.resume();
}
- } finally {
- mInjector.binderRestoreCallingIdentity(ident);
- }
+ });
}
}
@@ -13887,8 +13695,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
DevicePolicyData policy = getUserData(userHandle);
- long ident = mInjector.binderClearCallingIdentity();
- try {
+ return mInjector.binderWithCleanCallingIdentity(() -> {
if (policy.mPasswordTokenHandle != 0) {
mLockPatternUtils.removeEscrowToken(policy.mPasswordTokenHandle, userHandle);
}
@@ -13896,9 +13703,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
userHandle, /*EscrowTokenStateChangeCallback*/ null);
saveSettingsLocked(userHandle);
return policy.mPasswordTokenHandle != 0;
- } finally {
- mInjector.binderRestoreCallingIdentity(ident);
- }
+ });
}
}
@@ -13913,16 +13718,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
DevicePolicyData policy = getUserData(userHandle);
if (policy.mPasswordTokenHandle != 0) {
- long ident = mInjector.binderClearCallingIdentity();
- try {
+ return mInjector.binderWithCleanCallingIdentity(() -> {
boolean result = mLockPatternUtils.removeEscrowToken(
policy.mPasswordTokenHandle, userHandle);
policy.mPasswordTokenHandle = 0;
saveSettingsLocked(userHandle);
return result;
- } finally {
- mInjector.binderRestoreCallingIdentity(ident);
- }
+ });
}
}
return false;
@@ -13939,13 +13741,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
DevicePolicyData policy = getUserData(userHandle);
if (policy.mPasswordTokenHandle != 0) {
- long ident = mInjector.binderClearCallingIdentity();
- try {
- return mLockPatternUtils.isEscrowTokenActive(policy.mPasswordTokenHandle,
- userHandle);
- } finally {
- mInjector.binderRestoreCallingIdentity(ident);
- }
+ return mInjector.binderWithCleanCallingIdentity(
+ () -> mLockPatternUtils.isEscrowTokenActive(policy.mPasswordTokenHandle,
+ userHandle));
}
}
return false;
@@ -14315,13 +14113,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
enforceDeviceOwner(who);
int operatedId = -1;
- Uri resultUri;
- final long id = mInjector.binderClearCallingIdentity();
- try {
- resultUri = mContext.getContentResolver().insert(DPC_URI, apnSetting.toContentValues());
- } finally {
- mInjector.binderRestoreCallingIdentity(id);
- }
+ Uri resultUri = mInjector.binderWithCleanCallingIdentity(() ->
+ mContext.getContentResolver().insert(DPC_URI, apnSetting.toContentValues()));
if (resultUri != null) {
try {
operatedId = Integer.parseInt(resultUri.getLastPathSegment());
@@ -14346,14 +14139,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (apnId < 0) {
return false;
}
- final long id = mInjector.binderClearCallingIdentity();
- try {
- return mContext.getContentResolver().update(
- Uri.withAppendedPath(DPC_URI, Integer.toString(apnId)),
- apnSetting.toContentValues(), null, null) > 0;
- } finally {
- mInjector.binderRestoreCallingIdentity(id);
- }
+ return mInjector.binderWithCleanCallingIdentity(() ->
+ mContext.getContentResolver().update(
+ Uri.withAppendedPath(DPC_URI, Integer.toString(apnId)),
+ apnSetting.toContentValues(), null, null) > 0);
}
@Override
@@ -14371,14 +14160,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if(apnId < 0) {
return false;
}
- int numDeleted = 0;
- final long id = mInjector.binderClearCallingIdentity();
- try {
- numDeleted = mContext.getContentResolver().delete(
- Uri.withAppendedPath(DPC_URI, Integer.toString(apnId)), null, null);
- } finally {
- mInjector.binderRestoreCallingIdentity(id);
- }
+ int numDeleted = mInjector.binderWithCleanCallingIdentity(
+ () -> mContext.getContentResolver().delete(
+ Uri.withAppendedPath(DPC_URI, Integer.toString(apnId)), null, null));
return numDeleted > 0;
}
@@ -14394,13 +14178,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
private List<ApnSetting> getOverrideApnsUnchecked() {
- final Cursor cursor;
- final long id = mInjector.binderClearCallingIdentity();
- try {
- cursor = mContext.getContentResolver().query(DPC_URI, null, null, null, null);
- } finally {
- mInjector.binderRestoreCallingIdentity(id);
- }
+ final Cursor cursor = mInjector.binderWithCleanCallingIdentity(
+ () -> mContext.getContentResolver().query(DPC_URI, null, null, null, null));
if (cursor == null) {
return Collections.emptyList();
@@ -14432,13 +14211,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
private void setOverrideApnsEnabledUnchecked(boolean enabled) {
ContentValues value = new ContentValues();
value.put(ENFORCE_KEY, enabled);
- final long id = mInjector.binderClearCallingIdentity();
- try {
- mContext.getContentResolver().update(
- ENFORCE_MANAGED_URI, value, null, null);
- } finally {
- mInjector.binderRestoreCallingIdentity(id);
- }
+ mInjector.binderWithCleanCallingIdentity(() -> mContext.getContentResolver().update(
+ ENFORCE_MANAGED_URI, value, null, null));
}
@Override
@@ -14449,14 +14223,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Preconditions.checkNotNull(who, "ComponentName is null in isOverrideApnEnabled");
enforceDeviceOwner(who);
- Cursor enforceCursor;
- final long id = mInjector.binderClearCallingIdentity();
- try {
- enforceCursor = mContext.getContentResolver().query(
- ENFORCE_MANAGED_URI, null, null, null, null);
- } finally {
- mInjector.binderRestoreCallingIdentity(id);
- }
+ Cursor enforceCursor = mInjector.binderWithCleanCallingIdentity(
+ () -> mContext.getContentResolver().query(
+ ENFORCE_MANAGED_URI, null, null, null, null));
if (enforceCursor == null) {
return false;
@@ -14523,13 +14292,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
private void putPrivateDnsSettings(@Nullable String mode, @Nullable String host) {
// Set Private DNS settings using system permissions, as apps cannot write
// to global settings.
- long origId = mInjector.binderClearCallingIdentity();
- try {
+ mInjector.binderWithCleanCallingIdentity(() -> {
mInjector.settingsGlobalPutString(PRIVATE_DNS_MODE, mode);
mInjector.settingsGlobalPutString(PRIVATE_DNS_SPECIFIER, host);
- } finally {
- mInjector.binderRestoreCallingIdentity(origId);
- }
+ });
}
@Override
@@ -14615,8 +14381,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
.setBoolean(isDeviceAB())
.write();
enforceDeviceOwner(admin);
- final long id = mInjector.binderClearCallingIdentity();
- try {
+ mInjector.binderWithCleanCallingIdentity(() -> {
UpdateInstaller updateInstaller;
if (isDeviceAB()) {
updateInstaller = new AbUpdateInstaller(
@@ -14626,9 +14391,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
mContext, updateFileDescriptor, callback, mInjector, mConstants);
}
updateInstaller.startInstallUpdate();
- } finally {
- mInjector.binderRestoreCallingIdentity(id);
- }
+ });
}
private boolean isDeviceAB() {
@@ -14829,8 +14592,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
throw new SecurityException("Input package name doesn't align with actual "
+ "calling package.");
}
- final long identity = mInjector.binderClearCallingIdentity();
- try {
+ return mInjector.binderWithCleanCallingIdentity(() -> {
final int workProfileUserId = getManagedUserId(callingUserId);
if (workProfileUserId < 0) {
return false;
@@ -14854,10 +14616,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Log.e(LOG_TAG, "View event activity not found", e);
return false;
}
- } finally {
- mInjector.binderRestoreCallingIdentity(identity);
- }
- return true;
+ return true;
+ });
}
private boolean isCallingFromPackage(String packageName, int callingUid) {
diff --git a/services/incremental/Android.bp b/services/incremental/Android.bp
new file mode 100644
index 000000000000..2661925c1d06
--- /dev/null
+++ b/services/incremental/Android.bp
@@ -0,0 +1,110 @@
+// Copyright 2019, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_defaults {
+ name: "service.incremental-proto-defaults",
+
+ cpp_std: "c++2a",
+ proto: {
+ type: "lite",
+ },
+}
+
+cc_defaults {
+ name: "service.incremental-defaults",
+ defaults: ["service.incremental-proto-defaults"],
+ local_include_dirs: ["include/"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ "-Wno-unused-parameter",
+ ],
+
+ static_libs: [
+ "libbase",
+ "libext2_uuid",
+ "libdataloader_aidl-cpp",
+ "libincremental_aidl-cpp",
+ "libincremental_manager_aidl-cpp",
+ "libnativehelper",
+ "libprotobuf-cpp-lite",
+ "service.incremental.proto",
+ "libutils",
+ "libvold_binder",
+ ],
+ shared_libs: [
+ "libandroidfw",
+ "libbinder",
+ "libincfs",
+ "liblog",
+ "libz",
+ "libziparchive",
+ ],
+}
+
+filegroup {
+ name: "service.incremental_srcs",
+ srcs: [
+ "incremental_service.c",
+ "IncrementalService.cpp",
+ "BinderIncrementalService.cpp",
+ "path.cpp",
+ "ServiceWrappers.cpp",
+ ],
+}
+
+cc_library {
+ name: "service.incremental",
+ defaults: [
+ "service.incremental-defaults",
+ "linux_bionic_supported",
+ ],
+
+ export_include_dirs: ["include/",],
+ srcs: [
+ ":service.incremental_srcs",
+ ],
+}
+
+cc_library_headers {
+ name: "service.incremental_headers",
+ export_include_dirs: ["include/",],
+}
+
+cc_library_static {
+ name: "service.incremental.proto",
+ defaults: ["service.incremental-proto-defaults"],
+ proto: {
+ export_proto_headers: true,
+ },
+
+ srcs: [
+ "Metadata.proto",
+ ],
+}
+
+cc_test {
+ name: "service.incremental_test",
+ defaults: ["service.incremental-defaults"],
+ test_suites: ["device-tests"],
+ srcs: [
+ ":service.incremental_srcs",
+ "test/IncrementalServiceTest.cpp",
+ "test/path_test.cpp",
+ ],
+ static_libs: [
+ "libgmock",
+ ]
+}
diff --git a/services/incremental/BinderIncrementalService.cpp b/services/incremental/BinderIncrementalService.cpp
new file mode 100644
index 000000000000..bb26c1f93159
--- /dev/null
+++ b/services/incremental/BinderIncrementalService.cpp
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "BinderIncrementalService.h"
+
+#include <binder/IResultReceiver.h>
+#include <incfs.h>
+
+#include "ServiceWrappers.h"
+#include "jni.h"
+#include "nativehelper/JNIHelp.h"
+#include "path.h"
+
+using namespace std::literals;
+using namespace android::incremental;
+
+namespace android::os::incremental {
+
+static constexpr auto kAndroidDataEnv = "ANDROID_DATA"sv;
+static constexpr auto kDataDir = "/data"sv;
+static constexpr auto kIncrementalSubDir = "incremental"sv;
+
+static std::string getIncrementalDir() {
+ const char* dataDir = getenv(kAndroidDataEnv.data());
+ if (!dataDir || !*dataDir) {
+ dataDir = kDataDir.data();
+ }
+ return path::normalize(path::join(dataDir, kIncrementalSubDir));
+}
+
+static bool incFsEnabled() {
+ // TODO(b/136132412): use vold to check /sys/fs/incfs/version (per selinux compliance)
+ return incfs::enabled();
+}
+
+static bool incFsVersionValid(const sp<IVold>& vold) {
+ int version = -1;
+ auto status = vold->incFsVersion(&version);
+ if (!status.isOk() || version <= 0) {
+ return false;
+ }
+ return true;
+}
+
+BinderIncrementalService::BinderIncrementalService(const sp<IServiceManager>& sm)
+ : mImpl(RealServiceManager(sm), getIncrementalDir()) {}
+
+BinderIncrementalService* BinderIncrementalService::start() {
+ if (!incFsEnabled()) {
+ return nullptr;
+ }
+
+ IPCThreadState::self()->disableBackgroundScheduling(true);
+ sp<IServiceManager> sm(defaultServiceManager());
+ if (!sm) {
+ return nullptr;
+ }
+
+ sp<IBinder> voldBinder(sm->getService(String16("vold")));
+ if (voldBinder == nullptr) {
+ return nullptr;
+ }
+ sp<IVold> vold = interface_cast<IVold>(voldBinder);
+ if (!incFsVersionValid(vold)) {
+ return nullptr;
+ }
+
+ sp<BinderIncrementalService> self(new BinderIncrementalService(sm));
+ status_t ret = sm->addService(String16{getServiceName()}, self);
+ if (ret != android::OK) {
+ return nullptr;
+ }
+ sp<ProcessState> ps(ProcessState::self());
+ ps->startThreadPool();
+ ps->giveThreadPoolName();
+ return self.get();
+}
+
+status_t BinderIncrementalService::dump(int fd, const Vector<String16>& args) {
+ return OK;
+}
+
+void BinderIncrementalService::onSystemReady() {
+ mImpl.onSystemReady();
+}
+
+static binder::Status ok() {
+ return binder::Status::ok();
+}
+
+binder::Status BinderIncrementalService::openStorage(const std::string& path,
+ int32_t* _aidl_return) {
+ *_aidl_return = mImpl.openStorage(path);
+ return ok();
+}
+
+binder::Status BinderIncrementalService::createStorage(
+ const std::string& path, const DataLoaderParamsParcel& params,
+ int32_t createMode, int32_t* _aidl_return) {
+ *_aidl_return =
+ mImpl.createStorage(path, const_cast<DataLoaderParamsParcel&&>(params),
+ android::incremental::IncrementalService::CreateOptions(
+ createMode));
+ return ok();
+}
+
+binder::Status BinderIncrementalService::createLinkedStorage(const std::string& path,
+ int32_t otherStorageId,
+ int32_t createMode,
+ int32_t* _aidl_return) {
+ *_aidl_return =
+ mImpl.createLinkedStorage(path, otherStorageId,
+ android::incremental::IncrementalService::CreateOptions(
+ createMode));
+ return ok();
+}
+
+binder::Status BinderIncrementalService::makeBindMount(int32_t storageId,
+ const std::string& pathUnderStorage,
+ const std::string& targetFullPath,
+ int32_t bindType, int32_t* _aidl_return) {
+ *_aidl_return = mImpl.bind(storageId, pathUnderStorage, targetFullPath,
+ android::incremental::IncrementalService::BindKind(bindType));
+ return ok();
+}
+
+binder::Status BinderIncrementalService::deleteBindMount(int32_t storageId,
+ const std::string& targetFullPath,
+ int32_t* _aidl_return) {
+ *_aidl_return = mImpl.unbind(storageId, targetFullPath);
+ return ok();
+}
+
+binder::Status BinderIncrementalService::deleteStorage(int32_t storageId) {
+ mImpl.deleteStorage(storageId);
+ return ok();
+}
+
+binder::Status BinderIncrementalService::makeDirectory(int32_t storageId,
+ const std::string& pathUnderStorage,
+ int32_t* _aidl_return) {
+ auto inode = mImpl.makeDir(storageId, pathUnderStorage);
+ *_aidl_return = inode < 0 ? inode : 0;
+ return ok();
+}
+
+binder::Status BinderIncrementalService::makeDirectories(int32_t storageId,
+ const std::string& pathUnderStorage,
+ int32_t* _aidl_return) {
+ auto inode = mImpl.makeDirs(storageId, pathUnderStorage);
+ *_aidl_return = inode < 0 ? inode : 0;
+ return ok();
+}
+
+binder::Status BinderIncrementalService::makeFile(int32_t storageId,
+ const std::string& pathUnderStorage, int64_t size,
+ const std::vector<uint8_t>& metadata,
+ int32_t* _aidl_return) {
+ auto inode = mImpl.makeFile(storageId, pathUnderStorage, size,
+ {(const char*)metadata.data(), metadata.size()}, {});
+ *_aidl_return = inode < 0 ? inode : 0;
+ return ok();
+}
+binder::Status BinderIncrementalService::makeFileFromRange(
+ int32_t storageId, const std::string& pathUnderStorage,
+ const std::string& sourcePathUnderStorage, int64_t start, int64_t end,
+ int32_t* _aidl_return) {
+ // TODO(b/136132412): implement this
+ *_aidl_return = -1;
+ return ok();
+}
+binder::Status BinderIncrementalService::makeLink(int32_t sourceStorageId,
+ const std::string& relativeSourcePath,
+ int32_t destStorageId,
+ const std::string& relativeDestPath,
+ int32_t* _aidl_return) {
+ auto sourceInode = mImpl.nodeFor(sourceStorageId, relativeSourcePath);
+ auto [targetParentInode, name] = mImpl.parentAndNameFor(destStorageId, relativeDestPath);
+ *_aidl_return = mImpl.link(sourceStorageId, sourceInode, targetParentInode, name);
+ return ok();
+}
+binder::Status BinderIncrementalService::unlink(int32_t storageId,
+ const std::string& pathUnderStorage,
+ int32_t* _aidl_return) {
+ auto [parentNode, name] = mImpl.parentAndNameFor(storageId, pathUnderStorage);
+ *_aidl_return = mImpl.unlink(storageId, parentNode, name);
+ return ok();
+}
+binder::Status BinderIncrementalService::isFileRangeLoaded(int32_t storageId,
+ const std::string& relativePath,
+ int64_t start, int64_t end,
+ bool* _aidl_return) {
+ *_aidl_return = false;
+ return ok();
+}
+binder::Status BinderIncrementalService::getFileMetadata(int32_t storageId,
+ const std::string& relativePath,
+ std::vector<uint8_t>* _aidl_return) {
+ auto inode = mImpl.nodeFor(storageId, relativePath);
+ auto metadata = mImpl.getMetadata(storageId, inode);
+ _aidl_return->assign(metadata.begin(), metadata.end());
+ return ok();
+}
+binder::Status BinderIncrementalService::startLoading(int32_t storageId, bool* _aidl_return) {
+ *_aidl_return = mImpl.startLoading(storageId);
+ return ok();
+}
+} // namespace android::os::incremental
+
+jlong Incremental_IncrementalService_Start() {
+ return (jlong)android::os::incremental::BinderIncrementalService::start();
+}
+void Incremental_IncrementalService_OnSystemReady(jlong self) {
+ if (self) {
+ ((android::os::incremental::BinderIncrementalService*)self)->onSystemReady();
+ }
+}
diff --git a/services/incremental/BinderIncrementalService.h b/services/incremental/BinderIncrementalService.h
new file mode 100644
index 000000000000..37c9661db28d
--- /dev/null
+++ b/services/incremental/BinderIncrementalService.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <binder/BinderService.h>
+#include <binder/IServiceManager.h>
+
+#include "IncrementalService.h"
+#include "android/os/incremental/BnIncrementalManagerNative.h"
+#include "incremental_service.h"
+
+namespace android::os::incremental {
+
+class BinderIncrementalService : public BnIncrementalManagerNative,
+ public BinderService<BinderIncrementalService> {
+public:
+ BinderIncrementalService(const sp<IServiceManager> &sm);
+
+ static BinderIncrementalService *start();
+ static const char16_t *getServiceName() { return u"incremental_service"; }
+ status_t dump(int fd, const Vector<String16> &args) final;
+
+ void onSystemReady();
+ void onInvalidStorage(int mountId);
+
+ binder::Status openStorage(const std::string &path, int32_t *_aidl_return) final;
+ binder::Status createStorage(
+ const std::string &path,
+ const ::android::content::pm::DataLoaderParamsParcel &params,
+ int32_t createMode, int32_t *_aidl_return) final;
+ binder::Status createLinkedStorage(const std::string &path, int32_t otherStorageId,
+ int32_t createMode, int32_t *_aidl_return) final;
+ binder::Status makeBindMount(int32_t storageId, const std::string &pathUnderStorage,
+ const std::string &targetFullPath, int32_t bindType,
+ int32_t *_aidl_return) final;
+ binder::Status deleteBindMount(int32_t storageId, const std::string &targetFullPath,
+ int32_t *_aidl_return) final;
+ binder::Status deleteStorage(int32_t storageId) final;
+ binder::Status makeDirectory(int32_t storageId, const std::string &pathUnderStorage,
+ int32_t *_aidl_return) final;
+ binder::Status makeDirectories(int32_t storageId, const std::string &pathUnderStorage,
+ int32_t *_aidl_return) final;
+ binder::Status makeFile(int32_t storageId, const std::string &pathUnderStorage, int64_t size,
+ const std::vector<uint8_t> &metadata, int32_t *_aidl_return) final;
+ binder::Status makeFileFromRange(int32_t storageId, const std::string &pathUnderStorage,
+ const std::string &sourcePathUnderStorage, int64_t start,
+ int64_t end, int32_t *_aidl_return);
+ binder::Status makeLink(int32_t sourceStorageId, const std::string &relativeSourcePath,
+ int32_t destStorageId, const std::string &relativeDestPath,
+ int32_t *_aidl_return) final;
+ binder::Status unlink(int32_t storageId, const std::string &pathUnderStorage,
+ int32_t *_aidl_return) final;
+ binder::Status isFileRangeLoaded(int32_t storageId, const std::string &relativePath,
+ int64_t start, int64_t end, bool *_aidl_return) final;
+ binder::Status getFileMetadata(int32_t storageId, const std::string &relativePath,
+ std::vector<uint8_t> *_aidl_return) final;
+ binder::Status startLoading(int32_t storageId, bool *_aidl_return) final;
+
+private:
+ android::incremental::IncrementalService mImpl;
+};
+
+} // namespace android::os::incremental
diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp
new file mode 100644
index 000000000000..afce260ed41e
--- /dev/null
+++ b/services/incremental/IncrementalService.cpp
@@ -0,0 +1,1045 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "IncrementalService"
+
+#include "IncrementalService.h"
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
+#include <android/content/pm/IDataLoaderStatusListener.h>
+#include <android/os/IVold.h>
+#include <androidfw/ZipFileRO.h>
+#include <androidfw/ZipUtils.h>
+#include <binder/BinderService.h>
+#include <binder/ParcelFileDescriptor.h>
+#include <binder/Status.h>
+#include <sys/stat.h>
+#include <uuid/uuid.h>
+#include <zlib.h>
+
+#include <iterator>
+#include <span>
+#include <stack>
+#include <thread>
+#include <type_traits>
+
+#include "Metadata.pb.h"
+
+using namespace std::literals;
+using namespace android::content::pm;
+
+namespace android::incremental {
+
+namespace {
+
+using IncrementalFileSystemControlParcel =
+ ::android::os::incremental::IncrementalFileSystemControlParcel;
+
+struct Constants {
+ static constexpr auto backing = "backing_store"sv;
+ static constexpr auto mount = "mount"sv;
+ static constexpr auto image = "incfs.img"sv;
+ static constexpr auto storagePrefix = "st"sv;
+ static constexpr auto mountpointMdPrefix = ".mountpoint."sv;
+ static constexpr auto infoMdName = ".info"sv;
+};
+
+static const Constants& constants() {
+ static Constants c;
+ return c;
+}
+
+template <base::LogSeverity level = base::ERROR>
+bool mkdirOrLog(std::string_view name, int mode = 0770, bool allowExisting = true) {
+ auto cstr = path::c_str(name);
+ if (::mkdir(cstr, mode)) {
+ if (errno != EEXIST) {
+ PLOG(level) << "Can't create directory '" << name << '\'';
+ return false;
+ }
+ struct stat st;
+ if (::stat(cstr, &st) || !S_ISDIR(st.st_mode)) {
+ PLOG(level) << "Path exists but is not a directory: '" << name << '\'';
+ return false;
+ }
+ }
+ return true;
+}
+
+static std::string toMountKey(std::string_view path) {
+ if (path.empty()) {
+ return "@none";
+ }
+ if (path == "/"sv) {
+ return "@root";
+ }
+ if (path::isAbsolute(path)) {
+ path.remove_prefix(1);
+ }
+ std::string res(path);
+ std::replace(res.begin(), res.end(), '/', '_');
+ std::replace(res.begin(), res.end(), '@', '_');
+ return res;
+}
+
+static std::pair<std::string, std::string> makeMountDir(std::string_view incrementalDir,
+ std::string_view path) {
+ auto mountKey = toMountKey(path);
+ const auto prefixSize = mountKey.size();
+ for (int counter = 0; counter < 1000;
+ mountKey.resize(prefixSize), base::StringAppendF(&mountKey, "%d", counter++)) {
+ auto mountRoot = path::join(incrementalDir, mountKey);
+ if (mkdirOrLog(mountRoot, 0770, false)) {
+ return {mountKey, mountRoot};
+ }
+ }
+ return {};
+}
+
+template <class ProtoMessage, class Control>
+static ProtoMessage parseFromIncfs(const IncFsWrapper* incfs, Control&& control,
+ std::string_view path) {
+ struct stat st;
+ if (::stat(path::c_str(path), &st)) {
+ return {};
+ }
+ auto md = incfs->getMetadata(control, st.st_ino);
+ ProtoMessage message;
+ return message.ParseFromArray(md.data(), md.size()) ? message : ProtoMessage{};
+}
+
+static bool isValidMountTarget(std::string_view path) {
+ return path::isAbsolute(path) && path::isEmptyDir(path).value_or(true);
+}
+
+std::string makeBindMdName() {
+ static constexpr auto uuidStringSize = 36;
+
+ uuid_t guid;
+ uuid_generate(guid);
+
+ std::string name;
+ const auto prefixSize = constants().mountpointMdPrefix.size();
+ name.reserve(prefixSize + uuidStringSize);
+
+ name = constants().mountpointMdPrefix;
+ name.resize(prefixSize + uuidStringSize);
+ uuid_unparse(guid, name.data() + prefixSize);
+
+ return name;
+}
+} // namespace
+
+IncrementalService::IncFsMount::~IncFsMount() {
+ incrementalService.mIncrementalManager->destroyDataLoader(mountId);
+ control.reset();
+ LOG(INFO) << "Unmounting and cleaning up mount " << mountId << " with root '" << root << '\'';
+ for (auto&& [target, _] : bindPoints) {
+ LOG(INFO) << "\tbind: " << target;
+ incrementalService.mVold->unmountIncFs(target);
+ }
+ LOG(INFO) << "\troot: " << root;
+ incrementalService.mVold->unmountIncFs(path::join(root, constants().mount));
+ cleanupFilesystem(root);
+}
+
+auto IncrementalService::IncFsMount::makeStorage(StorageId id) -> StorageMap::iterator {
+ metadata::Storage st;
+ st.set_id(id);
+ auto metadata = st.SerializeAsString();
+
+ std::string name;
+ for (int no = nextStorageDirNo.fetch_add(1, std::memory_order_relaxed), i = 0;
+ i < 1024 && no >= 0; no = nextStorageDirNo.fetch_add(1, std::memory_order_relaxed), ++i) {
+ name.clear();
+ base::StringAppendF(&name, "%.*s%d", int(constants().storagePrefix.size()),
+ constants().storagePrefix.data(), no);
+ if (auto node =
+ incrementalService.mIncFs->makeDir(control, name, INCFS_ROOT_INODE, metadata);
+ node >= 0) {
+ std::lock_guard l(lock);
+ return storages.insert_or_assign(id, Storage{std::move(name), node}).first;
+ }
+ }
+ nextStorageDirNo = 0;
+ return storages.end();
+}
+
+void IncrementalService::IncFsMount::cleanupFilesystem(std::string_view root) {
+ ::unlink(path::join(root, constants().backing, constants().image).c_str());
+ ::rmdir(path::join(root, constants().backing).c_str());
+ ::rmdir(path::join(root, constants().mount).c_str());
+ ::rmdir(path::c_str(root));
+}
+
+IncrementalService::IncrementalService(const ServiceManagerWrapper& sm, std::string_view rootDir)
+ : mVold(sm.getVoldService()),
+ mIncrementalManager(sm.getIncrementalManager()),
+ mIncFs(sm.getIncFs()),
+ mIncrementalDir(rootDir) {
+ if (!mVold) {
+ LOG(FATAL) << "Vold service is unavailable";
+ }
+ if (!mIncrementalManager) {
+ LOG(FATAL) << "IncrementalManager service is unavailable";
+ }
+ // TODO(b/136132412): check that root dir should already exist
+ // TODO(b/136132412): enable mount existing dirs after SELinux rules are merged
+ // mountExistingImages();
+}
+
+IncrementalService::~IncrementalService() = default;
+
+std::optional<std::future<void>> IncrementalService::onSystemReady() {
+ std::promise<void> threadFinished;
+ if (mSystemReady.exchange(true)) {
+ return {};
+ }
+
+ std::vector<IfsMountPtr> mounts;
+ {
+ std::lock_guard l(mLock);
+ mounts.reserve(mMounts.size());
+ for (auto&& [id, ifs] : mMounts) {
+ if (ifs->mountId == id) {
+ mounts.push_back(ifs);
+ }
+ }
+ }
+
+ std::thread([this, mounts = std::move(mounts)]() {
+ std::vector<IfsMountPtr> failedLoaderMounts;
+ for (auto&& ifs : mounts) {
+ if (prepareDataLoader(*ifs, nullptr)) {
+ LOG(INFO) << "Successfully started data loader for mount " << ifs->mountId;
+ } else {
+ LOG(WARNING) << "Failed to start data loader for mount " << ifs->mountId;
+ failedLoaderMounts.push_back(std::move(ifs));
+ }
+ }
+
+ while (!failedLoaderMounts.empty()) {
+ LOG(WARNING) << "Deleting failed mount " << failedLoaderMounts.back()->mountId;
+ deleteStorage(*failedLoaderMounts.back());
+ failedLoaderMounts.pop_back();
+ }
+ mPrepareDataLoaders.set_value_at_thread_exit();
+ }).detach();
+ return mPrepareDataLoaders.get_future();
+}
+
+auto IncrementalService::getStorageSlotLocked() -> MountMap::iterator {
+ for (;;) {
+ if (mNextId == kMaxStorageId) {
+ mNextId = 0;
+ }
+ auto id = ++mNextId;
+ auto [it, inserted] = mMounts.try_emplace(id, nullptr);
+ if (inserted) {
+ return it;
+ }
+ }
+}
+
+StorageId IncrementalService::createStorage(std::string_view mountPoint,
+ DataLoaderParamsParcel&& dataLoaderParams,
+ CreateOptions options) {
+ LOG(INFO) << "createStorage: " << mountPoint << " | " << int(options);
+ if (!path::isAbsolute(mountPoint)) {
+ LOG(ERROR) << "path is not absolute: " << mountPoint;
+ return kInvalidStorageId;
+ }
+
+ auto mountNorm = path::normalize(mountPoint);
+ {
+ const auto id = findStorageId(mountNorm);
+ if (id != kInvalidStorageId) {
+ if (options & CreateOptions::OpenExisting) {
+ LOG(INFO) << "Opened existing storage " << id;
+ return id;
+ }
+ LOG(ERROR) << "Directory " << mountPoint << " is already mounted at storage " << id;
+ return kInvalidStorageId;
+ }
+ }
+
+ if (!(options & CreateOptions::CreateNew)) {
+ LOG(ERROR) << "not requirested create new storage, and it doesn't exist: " << mountPoint;
+ return kInvalidStorageId;
+ }
+
+ if (!path::isEmptyDir(mountNorm)) {
+ LOG(ERROR) << "Mounting over existing non-empty directory is not supported: " << mountNorm;
+ return kInvalidStorageId;
+ }
+ auto [mountKey, mountRoot] = makeMountDir(mIncrementalDir, mountNorm);
+ if (mountRoot.empty()) {
+ LOG(ERROR) << "Bad mount point";
+ return kInvalidStorageId;
+ }
+ // Make sure the code removes all crap it may create while still failing.
+ auto firstCleanup = [](const std::string* ptr) { IncFsMount::cleanupFilesystem(*ptr); };
+ auto firstCleanupOnFailure =
+ std::unique_ptr<std::string, decltype(firstCleanup)>(&mountRoot, firstCleanup);
+
+ auto mountTarget = path::join(mountRoot, constants().mount);
+ if (!mkdirOrLog(path::join(mountRoot, constants().backing)) || !mkdirOrLog(mountTarget)) {
+ return kInvalidStorageId;
+ }
+
+ const auto image = path::join(mountRoot, constants().backing, constants().image);
+ IncFsMount::Control control;
+ {
+ std::lock_guard l(mMountOperationLock);
+ IncrementalFileSystemControlParcel controlParcel;
+ auto status = mVold->mountIncFs(image, mountTarget, incfs::truncate, &controlParcel);
+ if (!status.isOk()) {
+ LOG(ERROR) << "Vold::mountIncFs() failed: " << status.toString8();
+ return kInvalidStorageId;
+ }
+ if (!controlParcel.cmd || !controlParcel.log) {
+ LOG(ERROR) << "Vold::mountIncFs() returned invalid control parcel.";
+ return kInvalidStorageId;
+ }
+ control.cmdFd = controlParcel.cmd->release();
+ control.logFd = controlParcel.log->release();
+ }
+
+ std::unique_lock l(mLock);
+ const auto mountIt = getStorageSlotLocked();
+ const auto mountId = mountIt->first;
+ l.unlock();
+
+ auto ifs =
+ std::make_shared<IncFsMount>(std::move(mountRoot), mountId, std::move(control), *this);
+ // Now it's the |ifs|'s responsibility to clean up after itself, and the only cleanup we need
+ // is the removal of the |ifs|.
+ firstCleanupOnFailure.release();
+
+ auto secondCleanup = [this, &l](auto itPtr) {
+ if (!l.owns_lock()) {
+ l.lock();
+ }
+ mMounts.erase(*itPtr);
+ };
+ auto secondCleanupOnFailure =
+ std::unique_ptr<decltype(mountIt), decltype(secondCleanup)>(&mountIt, secondCleanup);
+
+ const auto storageIt = ifs->makeStorage(ifs->mountId);
+ if (storageIt == ifs->storages.end()) {
+ LOG(ERROR) << "Can't create default storage directory";
+ return kInvalidStorageId;
+ }
+
+ {
+ metadata::Mount m;
+ m.mutable_storage()->set_id(ifs->mountId);
+ m.mutable_loader()->set_type((int)dataLoaderParams.type);
+ m.mutable_loader()->set_package_name(dataLoaderParams.packageName);
+ m.mutable_loader()->set_class_name(dataLoaderParams.className);
+ m.mutable_loader()->set_arguments(dataLoaderParams.arguments);
+ const auto metadata = m.SerializeAsString();
+ m.mutable_loader()->release_arguments();
+ m.mutable_loader()->release_class_name();
+ m.mutable_loader()->release_package_name();
+ if (auto err = mIncFs->makeFile(ifs->control, constants().infoMdName, INCFS_ROOT_INODE, 0,
+ metadata);
+ err < 0) {
+ LOG(ERROR) << "Saving mount metadata failed: " << -err;
+ return kInvalidStorageId;
+ }
+ }
+
+ const auto bk =
+ (options & CreateOptions::PermanentBind) ? BindKind::Permanent : BindKind::Temporary;
+ if (auto err = addBindMount(*ifs, storageIt->first, std::string(storageIt->second.name),
+ std::move(mountNorm), bk, l);
+ err < 0) {
+ LOG(ERROR) << "adding bind mount failed: " << -err;
+ return kInvalidStorageId;
+ }
+
+ // Done here as well, all data structures are in good state.
+ secondCleanupOnFailure.release();
+
+ if (!prepareDataLoader(*ifs, &dataLoaderParams)) {
+ LOG(ERROR) << "prepareDataLoader() failed";
+ deleteStorageLocked(*ifs, std::move(l));
+ return kInvalidStorageId;
+ }
+
+ mountIt->second = std::move(ifs);
+ l.unlock();
+ LOG(INFO) << "created storage " << mountId;
+ return mountId;
+}
+
+StorageId IncrementalService::createLinkedStorage(std::string_view mountPoint,
+ StorageId linkedStorage,
+ IncrementalService::CreateOptions options) {
+ if (!isValidMountTarget(mountPoint)) {
+ LOG(ERROR) << "Mount point is invalid or missing";
+ return kInvalidStorageId;
+ }
+
+ std::unique_lock l(mLock);
+ const auto& ifs = getIfsLocked(linkedStorage);
+ if (!ifs) {
+ LOG(ERROR) << "Ifs unavailable";
+ return kInvalidStorageId;
+ }
+
+ const auto mountIt = getStorageSlotLocked();
+ const auto storageId = mountIt->first;
+ const auto storageIt = ifs->makeStorage(storageId);
+ if (storageIt == ifs->storages.end()) {
+ LOG(ERROR) << "Can't create a new storage";
+ mMounts.erase(mountIt);
+ return kInvalidStorageId;
+ }
+
+ l.unlock();
+
+ const auto bk =
+ (options & CreateOptions::PermanentBind) ? BindKind::Permanent : BindKind::Temporary;
+ if (auto err = addBindMount(*ifs, storageIt->first, std::string(storageIt->second.name),
+ path::normalize(mountPoint), bk, l);
+ err < 0) {
+ LOG(ERROR) << "bindMount failed with error: " << err;
+ return kInvalidStorageId;
+ }
+
+ mountIt->second = ifs;
+ return storageId;
+}
+
+IncrementalService::BindPathMap::const_iterator IncrementalService::findStorageLocked(
+ std::string_view path) const {
+ auto bindPointIt = mBindsByPath.upper_bound(path);
+ if (bindPointIt == mBindsByPath.begin()) {
+ return mBindsByPath.end();
+ }
+ --bindPointIt;
+ if (!path::startsWith(path, bindPointIt->first)) {
+ return mBindsByPath.end();
+ }
+ return bindPointIt;
+}
+
+StorageId IncrementalService::findStorageId(std::string_view path) const {
+ std::lock_guard l(mLock);
+ auto it = findStorageLocked(path);
+ if (it == mBindsByPath.end()) {
+ return kInvalidStorageId;
+ }
+ return it->second->second.storage;
+}
+
+void IncrementalService::deleteStorage(StorageId storageId) {
+ const auto ifs = getIfs(storageId);
+ if (!ifs) {
+ return;
+ }
+ deleteStorage(*ifs);
+}
+
+void IncrementalService::deleteStorage(IncrementalService::IncFsMount& ifs) {
+ std::unique_lock l(ifs.lock);
+ deleteStorageLocked(ifs, std::move(l));
+}
+
+void IncrementalService::deleteStorageLocked(IncrementalService::IncFsMount& ifs,
+ std::unique_lock<std::mutex>&& ifsLock) {
+ const auto storages = std::move(ifs.storages);
+ // Don't move the bind points out: Ifs's dtor will use them to unmount everything.
+ const auto bindPoints = ifs.bindPoints;
+ ifsLock.unlock();
+
+ std::lock_guard l(mLock);
+ for (auto&& [id, _] : storages) {
+ if (id != ifs.mountId) {
+ mMounts.erase(id);
+ }
+ }
+ for (auto&& [path, _] : bindPoints) {
+ mBindsByPath.erase(path);
+ }
+ mMounts.erase(ifs.mountId);
+}
+
+StorageId IncrementalService::openStorage(std::string_view pathInMount) {
+ if (!path::isAbsolute(pathInMount)) {
+ return kInvalidStorageId;
+ }
+
+ return findStorageId(path::normalize(pathInMount));
+}
+
+Inode IncrementalService::nodeFor(StorageId storage, std::string_view subpath) const {
+ const auto ifs = getIfs(storage);
+ if (!ifs) {
+ return -1;
+ }
+ std::unique_lock l(ifs->lock);
+ auto storageIt = ifs->storages.find(storage);
+ if (storageIt == ifs->storages.end()) {
+ return -1;
+ }
+ if (subpath.empty() || subpath == "."sv) {
+ return storageIt->second.node;
+ }
+ auto path = path::join(ifs->root, constants().mount, storageIt->second.name, subpath);
+ l.unlock();
+ struct stat st;
+ if (::stat(path.c_str(), &st)) {
+ return -1;
+ }
+ return st.st_ino;
+}
+
+std::pair<Inode, std::string_view> IncrementalService::parentAndNameFor(
+ StorageId storage, std::string_view subpath) const {
+ auto name = path::basename(subpath);
+ if (name.empty()) {
+ return {-1, {}};
+ }
+ auto dir = path::dirname(subpath);
+ if (dir.empty() || dir == "/"sv) {
+ return {-1, {}};
+ }
+ auto inode = nodeFor(storage, dir);
+ return {inode, name};
+}
+
+IncrementalService::IfsMountPtr IncrementalService::getIfs(StorageId storage) const {
+ std::lock_guard l(mLock);
+ return getIfsLocked(storage);
+}
+
+const IncrementalService::IfsMountPtr& IncrementalService::getIfsLocked(StorageId storage) const {
+ auto it = mMounts.find(storage);
+ if (it == mMounts.end()) {
+ static const IfsMountPtr kEmpty = {};
+ return kEmpty;
+ }
+ return it->second;
+}
+
+int IncrementalService::bind(StorageId storage, std::string_view sourceSubdir,
+ std::string_view target, BindKind kind) {
+ if (!isValidMountTarget(target)) {
+ return -EINVAL;
+ }
+
+ const auto ifs = getIfs(storage);
+ if (!ifs) {
+ return -EINVAL;
+ }
+ std::unique_lock l(ifs->lock);
+ const auto storageInfo = ifs->storages.find(storage);
+ if (storageInfo == ifs->storages.end()) {
+ return -EINVAL;
+ }
+ auto source = path::join(storageInfo->second.name, sourceSubdir);
+ l.unlock();
+ std::unique_lock l2(mLock, std::defer_lock);
+ return addBindMount(*ifs, storage, std::move(source), path::normalize(target), kind, l2);
+}
+
+int IncrementalService::unbind(StorageId storage, std::string_view target) {
+ if (!path::isAbsolute(target)) {
+ return -EINVAL;
+ }
+
+ LOG(INFO) << "Removing bind point " << target;
+
+ // Here we should only look up by the exact target, not by a subdirectory of any existing mount,
+ // otherwise there's a chance to unmount something completely unrelated
+ const auto norm = path::normalize(target);
+ std::unique_lock l(mLock);
+ const auto storageIt = mBindsByPath.find(norm);
+ if (storageIt == mBindsByPath.end() || storageIt->second->second.storage != storage) {
+ return -EINVAL;
+ }
+ const auto bindIt = storageIt->second;
+ const auto storageId = bindIt->second.storage;
+ const auto ifs = getIfsLocked(storageId);
+ if (!ifs) {
+ LOG(ERROR) << "Internal error: storageId " << storageId << " for bound path " << target
+ << " is missing";
+ return -EFAULT;
+ }
+ mBindsByPath.erase(storageIt);
+ l.unlock();
+
+ mVold->unmountIncFs(bindIt->first);
+ std::unique_lock l2(ifs->lock);
+ if (ifs->bindPoints.size() <= 1) {
+ ifs->bindPoints.clear();
+ deleteStorageLocked(*ifs, std::move(l2));
+ } else {
+ const std::string savedFile = std::move(bindIt->second.savedFilename);
+ ifs->bindPoints.erase(bindIt);
+ l2.unlock();
+ if (!savedFile.empty()) {
+ mIncFs->unlink(ifs->control, INCFS_ROOT_INODE, savedFile);
+ }
+ }
+ return 0;
+}
+
+Inode IncrementalService::makeFile(StorageId storageId, std::string_view pathUnderStorage,
+ long size, std::string_view metadata,
+ std::string_view signature) {
+ (void)signature;
+ auto [parentInode, name] = parentAndNameFor(storageId, pathUnderStorage);
+ if (parentInode < 0) {
+ return -EINVAL;
+ }
+ if (auto ifs = getIfs(storageId)) {
+ auto inode = mIncFs->makeFile(ifs->control, name, parentInode, size, metadata);
+ if (inode < 0) {
+ return inode;
+ }
+ auto metadataBytes = std::vector<uint8_t>();
+ if (metadata.data() != nullptr && metadata.size() > 0) {
+ metadataBytes.insert(metadataBytes.end(), &metadata.data()[0],
+ &metadata.data()[metadata.size()]);
+ }
+ mIncrementalManager->newFileForDataLoader(ifs->mountId, inode, metadataBytes);
+ return inode;
+ }
+ return -EINVAL;
+}
+
+Inode IncrementalService::makeDir(StorageId storageId, std::string_view pathUnderStorage,
+ std::string_view metadata) {
+ auto [parentInode, name] = parentAndNameFor(storageId, pathUnderStorage);
+ if (parentInode < 0) {
+ return -EINVAL;
+ }
+ if (auto ifs = getIfs(storageId)) {
+ return mIncFs->makeDir(ifs->control, name, parentInode, metadata);
+ }
+ return -EINVAL;
+}
+
+Inode IncrementalService::makeDirs(StorageId storageId, std::string_view pathUnderStorage,
+ std::string_view metadata) {
+ const auto ifs = getIfs(storageId);
+ if (!ifs) {
+ return -EINVAL;
+ }
+ std::string_view parentDir(pathUnderStorage);
+ auto p = parentAndNameFor(storageId, pathUnderStorage);
+ std::stack<std::string> pathsToCreate;
+ while (p.first < 0) {
+ parentDir = path::dirname(parentDir);
+ pathsToCreate.emplace(parentDir);
+ p = parentAndNameFor(storageId, parentDir);
+ }
+ Inode inode;
+ while (!pathsToCreate.empty()) {
+ p = parentAndNameFor(storageId, pathsToCreate.top());
+ pathsToCreate.pop();
+ inode = mIncFs->makeDir(ifs->control, p.second, p.first, metadata);
+ if (inode < 0) {
+ return inode;
+ }
+ }
+ return mIncFs->makeDir(ifs->control, path::basename(pathUnderStorage), inode, metadata);
+}
+
+int IncrementalService::link(StorageId storage, Inode item, Inode newParent,
+ std::string_view newName) {
+ if (auto ifs = getIfs(storage)) {
+ return mIncFs->link(ifs->control, item, newParent, newName);
+ }
+ return -EINVAL;
+}
+
+int IncrementalService::unlink(StorageId storage, Inode parent, std::string_view name) {
+ if (auto ifs = getIfs(storage)) {
+ return mIncFs->unlink(ifs->control, parent, name);
+ }
+ return -EINVAL;
+}
+
+int IncrementalService::addBindMount(IncFsMount& ifs, StorageId storage, std::string&& sourceSubdir,
+ std::string&& target, BindKind kind,
+ std::unique_lock<std::mutex>& mainLock) {
+ if (!isValidMountTarget(target)) {
+ return -EINVAL;
+ }
+
+ std::string mdFileName;
+ if (kind != BindKind::Temporary) {
+ metadata::BindPoint bp;
+ bp.set_storage_id(storage);
+ bp.set_allocated_dest_path(&target);
+ bp.set_allocated_source_subdir(&sourceSubdir);
+ const auto metadata = bp.SerializeAsString();
+ bp.release_source_subdir();
+ bp.release_dest_path();
+ mdFileName = makeBindMdName();
+ auto node = mIncFs->makeFile(ifs.control, mdFileName, INCFS_ROOT_INODE, 0, metadata);
+ if (node < 0) {
+ return int(node);
+ }
+ }
+
+ return addBindMountWithMd(ifs, storage, std::move(mdFileName), std::move(sourceSubdir),
+ std::move(target), kind, mainLock);
+}
+
+int IncrementalService::addBindMountWithMd(IncrementalService::IncFsMount& ifs, StorageId storage,
+ std::string&& metadataName, std::string&& sourceSubdir,
+ std::string&& target, BindKind kind,
+ std::unique_lock<std::mutex>& mainLock) {
+ LOG(INFO) << "Adding bind mount: " << sourceSubdir << " -> " << target;
+ {
+ auto path = path::join(ifs.root, constants().mount, sourceSubdir);
+ std::lock_guard l(mMountOperationLock);
+ const auto status = mVold->bindMount(path, target);
+ if (!status.isOk()) {
+ LOG(ERROR) << "Calling Vold::bindMount() failed: " << status.toString8();
+ return status.exceptionCode() == binder::Status::EX_SERVICE_SPECIFIC
+ ? status.serviceSpecificErrorCode() > 0 ? -status.serviceSpecificErrorCode()
+ : status.serviceSpecificErrorCode() == 0
+ ? -EFAULT
+ : status.serviceSpecificErrorCode()
+ : -EIO;
+ }
+ }
+
+ if (!mainLock.owns_lock()) {
+ mainLock.lock();
+ }
+ std::lock_guard l(ifs.lock);
+ const auto [it, _] =
+ ifs.bindPoints.insert_or_assign(target,
+ IncFsMount::Bind{storage, std::move(metadataName),
+ std::move(sourceSubdir), kind});
+ mBindsByPath[std::move(target)] = it;
+ return 0;
+}
+
+RawMetadata IncrementalService::getMetadata(StorageId storage, Inode node) const {
+ const auto ifs = getIfs(storage);
+ if (!ifs) {
+ return {};
+ }
+ return mIncFs->getMetadata(ifs->control, node);
+}
+
+std::vector<std::string> IncrementalService::listFiles(StorageId storage) const {
+ const auto ifs = getIfs(storage);
+ if (!ifs) {
+ return {};
+ }
+
+ std::unique_lock l(ifs->lock);
+ auto subdirIt = ifs->storages.find(storage);
+ if (subdirIt == ifs->storages.end()) {
+ return {};
+ }
+ auto dir = path::join(ifs->root, constants().mount, subdirIt->second.name);
+ l.unlock();
+
+ const auto prefixSize = dir.size() + 1;
+ std::vector<std::string> todoDirs{std::move(dir)};
+ std::vector<std::string> result;
+ do {
+ auto currDir = std::move(todoDirs.back());
+ todoDirs.pop_back();
+
+ auto d =
+ std::unique_ptr<DIR, decltype(&::closedir)>(::opendir(currDir.c_str()), ::closedir);
+ while (auto e = ::readdir(d.get())) {
+ if (e->d_type == DT_REG) {
+ result.emplace_back(
+ path::join(std::string_view(currDir).substr(prefixSize), e->d_name));
+ continue;
+ }
+ if (e->d_type == DT_DIR) {
+ if (e->d_name == "."sv || e->d_name == ".."sv) {
+ continue;
+ }
+ todoDirs.emplace_back(path::join(currDir, e->d_name));
+ continue;
+ }
+ }
+ } while (!todoDirs.empty());
+ return result;
+}
+
+bool IncrementalService::startLoading(StorageId storage) const {
+ const auto ifs = getIfs(storage);
+ if (!ifs) {
+ return false;
+ }
+ bool started = false;
+ std::unique_lock l(ifs->lock);
+ if (ifs->dataLoaderStatus != IDataLoaderStatusListener::DATA_LOADER_CREATED) {
+ if (ifs->dataLoaderReady.wait_for(l, Seconds(5)) == std::cv_status::timeout) {
+ LOG(ERROR) << "Timeout waiting for data loader to be ready";
+ return false;
+ }
+ }
+ auto status = mIncrementalManager->startDataLoader(ifs->mountId, &started);
+ if (!status.isOk()) {
+ return false;
+ }
+ return started;
+}
+
+void IncrementalService::mountExistingImages() {
+ auto d = std::unique_ptr<DIR, decltype(&::closedir)>(::opendir(mIncrementalDir.c_str()),
+ ::closedir);
+ while (auto e = ::readdir(d.get())) {
+ if (e->d_type != DT_DIR) {
+ continue;
+ }
+ if (e->d_name == "."sv || e->d_name == ".."sv) {
+ continue;
+ }
+ auto root = path::join(mIncrementalDir, e->d_name);
+ if (!mountExistingImage(root, e->d_name)) {
+ IncFsMount::cleanupFilesystem(root);
+ }
+ }
+}
+
+bool IncrementalService::mountExistingImage(std::string_view root, std::string_view key) {
+ LOG(INFO) << "Trying to mount: " << key;
+
+ auto mountTarget = path::join(root, constants().mount);
+ const auto image = path::join(root, constants().backing, constants().image);
+
+ IncFsMount::Control control;
+ IncrementalFileSystemControlParcel controlParcel;
+ auto status = mVold->mountIncFs(image, mountTarget, 0, &controlParcel);
+ if (!status.isOk()) {
+ LOG(ERROR) << "Vold::mountIncFs() failed: " << status.toString8();
+ return false;
+ }
+ if (controlParcel.cmd) {
+ control.cmdFd = controlParcel.cmd->release();
+ }
+ if (controlParcel.log) {
+ control.logFd = controlParcel.log->release();
+ }
+
+ auto ifs = std::make_shared<IncFsMount>(std::string(root), -1, std::move(control), *this);
+
+ auto m = parseFromIncfs<metadata::Mount>(mIncFs.get(), ifs->control,
+ path::join(mountTarget, constants().infoMdName));
+ if (!m.has_loader() || !m.has_storage()) {
+ LOG(ERROR) << "Bad mount metadata in mount at " << root;
+ return false;
+ }
+
+ ifs->mountId = m.storage().id();
+ mNextId = std::max(mNextId, ifs->mountId + 1);
+
+ std::vector<std::pair<std::string, metadata::BindPoint>> bindPoints;
+ auto d = std::unique_ptr<DIR, decltype(&::closedir)>(::opendir(path::c_str(mountTarget)),
+ ::closedir);
+ while (auto e = ::readdir(d.get())) {
+ if (e->d_type == DT_REG) {
+ auto name = std::string_view(e->d_name);
+ if (name.starts_with(constants().mountpointMdPrefix)) {
+ bindPoints.emplace_back(name,
+ parseFromIncfs<metadata::BindPoint>(mIncFs.get(),
+ ifs->control,
+ path::join(mountTarget,
+ name)));
+ if (bindPoints.back().second.dest_path().empty() ||
+ bindPoints.back().second.source_subdir().empty()) {
+ bindPoints.pop_back();
+ mIncFs->unlink(ifs->control, INCFS_ROOT_INODE, name);
+ }
+ }
+ } else if (e->d_type == DT_DIR) {
+ if (e->d_name == "."sv || e->d_name == ".."sv) {
+ continue;
+ }
+ auto name = std::string_view(e->d_name);
+ if (name.starts_with(constants().storagePrefix)) {
+ auto md = parseFromIncfs<metadata::Storage>(mIncFs.get(), ifs->control,
+ path::join(mountTarget, name));
+ auto [_, inserted] = mMounts.try_emplace(md.id(), ifs);
+ if (!inserted) {
+ LOG(WARNING) << "Ignoring storage with duplicate id " << md.id()
+ << " for mount " << root;
+ continue;
+ }
+ ifs->storages.insert_or_assign(md.id(),
+ IncFsMount::Storage{std::string(name),
+ Inode(e->d_ino)});
+ mNextId = std::max(mNextId, md.id() + 1);
+ }
+ }
+ }
+
+ if (ifs->storages.empty()) {
+ LOG(WARNING) << "No valid storages in mount " << root;
+ return false;
+ }
+
+ int bindCount = 0;
+ for (auto&& bp : bindPoints) {
+ std::unique_lock l(mLock, std::defer_lock);
+ bindCount += !addBindMountWithMd(*ifs, bp.second.storage_id(), std::move(bp.first),
+ std::move(*bp.second.mutable_source_subdir()),
+ std::move(*bp.second.mutable_dest_path()),
+ BindKind::Permanent, l);
+ }
+
+ if (bindCount == 0) {
+ LOG(WARNING) << "No valid bind points for mount " << root;
+ deleteStorage(*ifs);
+ return false;
+ }
+
+ DataLoaderParamsParcel dlParams;
+ dlParams.type = (DataLoaderType)m.loader().type();
+ dlParams.packageName = std::move(*m.mutable_loader()->mutable_package_name());
+ dlParams.className = std::move(*m.mutable_loader()->mutable_class_name());
+ dlParams.arguments = std::move(*m.mutable_loader()->mutable_arguments());
+ if (!prepareDataLoader(*ifs, &dlParams)) {
+ deleteStorage(*ifs);
+ return false;
+ }
+
+ mMounts[ifs->mountId] = std::move(ifs);
+ return true;
+}
+
+bool IncrementalService::prepareDataLoader(IncrementalService::IncFsMount& ifs,
+ DataLoaderParamsParcel* params) {
+ if (!mSystemReady.load(std::memory_order_relaxed)) {
+ std::unique_lock l(ifs.lock);
+ if (params) {
+ if (ifs.savedDataLoaderParams) {
+ LOG(WARNING) << "Trying to pass second set of data loader parameters, ignored it";
+ } else {
+ ifs.savedDataLoaderParams = std::move(*params);
+ }
+ } else {
+ if (!ifs.savedDataLoaderParams) {
+ LOG(ERROR) << "Mount " << ifs.mountId
+ << " is broken: no data loader params (system is not ready yet)";
+ return false;
+ }
+ }
+ return true; // eventually...
+ }
+ if (base::GetBoolProperty("incremental.skip_loader", false)) {
+ LOG(INFO) << "Skipped data loader because of incremental.skip_loader property";
+ std::unique_lock l(ifs.lock);
+ ifs.savedDataLoaderParams.reset();
+ return true;
+ }
+
+ std::unique_lock l(ifs.lock);
+ if (ifs.dataLoaderStatus == IDataLoaderStatusListener::DATA_LOADER_CREATED) {
+ LOG(INFO) << "Skipped data loader preparation because it already exists";
+ return true;
+ }
+
+ auto* dlp = params ? params
+ : ifs.savedDataLoaderParams ? &ifs.savedDataLoaderParams.value() : nullptr;
+ if (!dlp) {
+ LOG(ERROR) << "Mount " << ifs.mountId << " is broken: no data loader params";
+ return false;
+ }
+ FileSystemControlParcel fsControlParcel;
+ fsControlParcel.incremental = std::make_unique<IncrementalFileSystemControlParcel>();
+ fsControlParcel.incremental->cmd =
+ std::make_unique<os::ParcelFileDescriptor>(base::unique_fd(::dup(ifs.control.cmdFd)));
+ fsControlParcel.incremental->log =
+ std::make_unique<os::ParcelFileDescriptor>(base::unique_fd(::dup(ifs.control.logFd)));
+ sp<IncrementalDataLoaderListener> listener = new IncrementalDataLoaderListener(*this);
+ bool created = false;
+ auto status = mIncrementalManager->prepareDataLoader(ifs.mountId, fsControlParcel, *dlp,
+ listener, &created);
+ if (!status.isOk() || !created) {
+ LOG(ERROR) << "Failed to create a data loader for mount " << ifs.mountId;
+ return false;
+ }
+ ifs.savedDataLoaderParams.reset();
+ return true;
+}
+
+binder::Status IncrementalService::IncrementalDataLoaderListener::onStatusChanged(MountId mountId,
+ int newStatus) {
+ std::unique_lock l(incrementalService.mLock);
+ const auto& ifs = incrementalService.getIfsLocked(mountId);
+ if (!ifs) {
+ LOG(WARNING) << "Received data loader status " << int(newStatus) << " for unknown mount "
+ << mountId;
+ return binder::Status::ok();
+ }
+ ifs->dataLoaderStatus = newStatus;
+ switch (newStatus) {
+ case IDataLoaderStatusListener::DATA_LOADER_NO_CONNECTION: {
+ auto now = Clock::now();
+ if (ifs->connectionLostTime.time_since_epoch().count() == 0) {
+ ifs->connectionLostTime = now;
+ break;
+ }
+ auto duration =
+ std::chrono::duration_cast<Seconds>(now - ifs->connectionLostTime).count();
+ if (duration >= 10) {
+ incrementalService.mIncrementalManager->showHealthBlockedUI(mountId);
+ }
+ break;
+ }
+ case IDataLoaderStatusListener::DATA_LOADER_CONNECTION_OK: {
+ ifs->dataLoaderStatus = IDataLoaderStatusListener::DATA_LOADER_STARTED;
+ break;
+ }
+ case IDataLoaderStatusListener::DATA_LOADER_CREATED: {
+ ifs->dataLoaderReady.notify_one();
+ break;
+ }
+ case IDataLoaderStatusListener::DATA_LOADER_DESTROYED: {
+ ifs->dataLoaderStatus = IDataLoaderStatusListener::DATA_LOADER_STOPPED;
+ incrementalService.deleteStorageLocked(*ifs, std::move(l));
+ break;
+ }
+ case IDataLoaderStatusListener::DATA_LOADER_STARTED: {
+ break;
+ }
+ case IDataLoaderStatusListener::DATA_LOADER_STOPPED: {
+ break;
+ }
+ default: {
+ LOG(WARNING) << "Unknown data loader status: " << newStatus
+ << " for mount: " << mountId;
+ break;
+ }
+ }
+
+ return binder::Status::ok();
+}
+
+} // namespace android::incremental
diff --git a/services/incremental/IncrementalService.h b/services/incremental/IncrementalService.h
new file mode 100644
index 000000000000..a03ffa00d035
--- /dev/null
+++ b/services/incremental/IncrementalService.h
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android-base/strings.h>
+#include <android-base/unique_fd.h>
+#include <android/os/incremental/IIncrementalManager.h>
+#include <android/content/pm/DataLoaderParamsParcel.h>
+#include <binder/IServiceManager.h>
+#include <utils/String16.h>
+#include <utils/StrongPointer.h>
+#include <utils/Vector.h>
+
+#include <atomic>
+#include <chrono>
+#include <future>
+#include <limits>
+#include <map>
+#include <mutex>
+#include <string>
+#include <string_view>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+#include "ServiceWrappers.h"
+#include "android/content/pm/BnDataLoaderStatusListener.h"
+#include "incfs.h"
+#include "path.h"
+
+using namespace android::os::incremental;
+
+namespace android::os {
+class IVold;
+}
+
+namespace android::incremental {
+
+using MountId = int;
+using StorageId = int;
+using Inode = incfs::Inode;
+using BlockIndex = incfs::BlockIndex;
+using RawMetadata = incfs::RawMetadata;
+using Clock = std::chrono::steady_clock;
+using TimePoint = std::chrono::time_point<Clock>;
+using Seconds = std::chrono::seconds;
+
+class IncrementalService {
+public:
+ explicit IncrementalService(const ServiceManagerWrapper& sm, std::string_view rootDir);
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
+ ~IncrementalService();
+#pragma GCC diagnostic pop
+
+ static constexpr StorageId kInvalidStorageId = -1;
+ static constexpr StorageId kMaxStorageId = std::numeric_limits<int>::max();
+
+ enum CreateOptions {
+ TemporaryBind = 1,
+ PermanentBind = 2,
+ CreateNew = 4,
+ OpenExisting = 8,
+
+ Default = TemporaryBind | CreateNew
+ };
+
+ enum class BindKind {
+ Temporary = 0,
+ Permanent = 1,
+ };
+
+ std::optional<std::future<void>> onSystemReady();
+
+ StorageId createStorage(std::string_view mountPoint,
+ DataLoaderParamsParcel&& dataLoaderParams,
+ CreateOptions options = CreateOptions::Default);
+ StorageId createLinkedStorage(std::string_view mountPoint, StorageId linkedStorage,
+ CreateOptions options = CreateOptions::Default);
+ StorageId openStorage(std::string_view pathInMount);
+
+ Inode nodeFor(StorageId storage, std::string_view subpath) const;
+ std::pair<Inode, std::string_view> parentAndNameFor(StorageId storage,
+ std::string_view subpath) const;
+
+ int bind(StorageId storage, std::string_view subdir, std::string_view target, BindKind kind);
+ int unbind(StorageId storage, std::string_view target);
+ void deleteStorage(StorageId storage);
+
+ Inode makeFile(StorageId storage, std::string_view name, long size, std::string_view metadata,
+ std::string_view signature);
+ Inode makeDir(StorageId storage, std::string_view name, std::string_view metadata = {});
+ Inode makeDirs(StorageId storage, std::string_view name, std::string_view metadata = {});
+
+ int link(StorageId storage, Inode item, Inode newParent, std::string_view newName);
+ int unlink(StorageId storage, Inode parent, std::string_view name);
+
+ bool isRangeLoaded(StorageId storage, Inode file, std::pair<BlockIndex, BlockIndex> range) {
+ return false;
+ }
+
+ RawMetadata getMetadata(StorageId storage, Inode node) const;
+ std::string getSigngatureData(StorageId storage, Inode node) const { return {}; }
+
+ std::vector<std::string> listFiles(StorageId storage) const;
+ bool startLoading(StorageId storage) const;
+
+ class IncrementalDataLoaderListener : public android::content::pm::BnDataLoaderStatusListener {
+ public:
+ IncrementalDataLoaderListener(IncrementalService& incrementalService)
+ : incrementalService(incrementalService) {}
+ // Callbacks interface
+ binder::Status onStatusChanged(MountId mount, int newStatus) override;
+
+ private:
+ IncrementalService& incrementalService;
+ };
+
+private:
+ struct IncFsMount {
+ struct Bind {
+ StorageId storage;
+ std::string savedFilename;
+ std::string sourceDir;
+ BindKind kind;
+ };
+
+ struct Storage {
+ std::string name;
+ Inode node;
+ };
+
+ struct Control {
+ operator IncFsControl() const { return {cmdFd, logFd}; }
+ void reset() {
+ cmdFd.reset();
+ logFd.reset();
+ }
+
+ base::unique_fd cmdFd;
+ base::unique_fd logFd;
+ };
+
+ using BindMap = std::map<std::string, Bind>;
+ using StorageMap = std::unordered_map<StorageId, Storage>;
+
+ mutable std::mutex lock;
+ const std::string root;
+ Control control;
+ /*const*/ MountId mountId;
+ StorageMap storages;
+ BindMap bindPoints;
+ std::optional<DataLoaderParamsParcel> savedDataLoaderParams;
+ std::atomic<int> nextStorageDirNo{0};
+ std::atomic<int> dataLoaderStatus = -1;
+ std::condition_variable dataLoaderReady;
+ TimePoint connectionLostTime = TimePoint();
+ const IncrementalService& incrementalService;
+
+ IncFsMount(std::string root, MountId mountId, Control control,
+ const IncrementalService& incrementalService)
+ : root(std::move(root)),
+ control(std::move(control)),
+ mountId(mountId),
+ incrementalService(incrementalService) {}
+ IncFsMount(IncFsMount&&) = delete;
+ IncFsMount& operator=(IncFsMount&&) = delete;
+ ~IncFsMount();
+
+ StorageMap::iterator makeStorage(StorageId id);
+
+ static void cleanupFilesystem(std::string_view root);
+ };
+
+ using IfsMountPtr = std::shared_ptr<IncFsMount>;
+ using MountMap = std::unordered_map<MountId, IfsMountPtr>;
+ using BindPathMap = std::map<std::string, IncFsMount::BindMap::iterator, path::PathLess>;
+
+ void mountExistingImages();
+ bool mountExistingImage(std::string_view root, std::string_view key);
+
+ IfsMountPtr getIfs(StorageId storage) const;
+ const IfsMountPtr& getIfsLocked(StorageId storage) const;
+ int addBindMount(IncFsMount& ifs, StorageId storage, std::string&& sourceSubdir,
+ std::string&& target, BindKind kind, std::unique_lock<std::mutex>& mainLock);
+
+ int addBindMountWithMd(IncFsMount& ifs, StorageId storage, std::string&& metadataName,
+ std::string&& sourceSubdir, std::string&& target, BindKind kind,
+ std::unique_lock<std::mutex>& mainLock);
+
+ bool prepareDataLoader(IncFsMount& ifs, DataLoaderParamsParcel* params);
+ BindPathMap::const_iterator findStorageLocked(std::string_view path) const;
+ StorageId findStorageId(std::string_view path) const;
+
+ void deleteStorage(IncFsMount& ifs);
+ void deleteStorageLocked(IncFsMount& ifs, std::unique_lock<std::mutex>&& ifsLock);
+ MountMap::iterator getStorageSlotLocked();
+
+ // Member variables
+ // These are shared pointers for the sake of unit testing
+ std::shared_ptr<VoldServiceWrapper> mVold;
+ std::shared_ptr<IncrementalManagerWrapper> mIncrementalManager;
+ std::shared_ptr<IncFsWrapper> mIncFs;
+ const std::string mIncrementalDir;
+
+ mutable std::mutex mLock;
+ mutable std::mutex mMountOperationLock;
+ MountMap mMounts;
+ BindPathMap mBindsByPath;
+
+ std::atomic_bool mSystemReady = false;
+ StorageId mNextId = 0;
+ std::promise<void> mPrepareDataLoaders;
+};
+
+} // namespace android::incremental
diff --git a/services/incremental/Metadata.proto b/services/incremental/Metadata.proto
new file mode 100644
index 000000000000..79f1bf8d29a9
--- /dev/null
+++ b/services/incremental/Metadata.proto
@@ -0,0 +1,25 @@
+syntax = "proto3";
+
+package android.incremental.metadata;
+
+message BindPoint {
+ int32 storage_id = 1;
+ string source_subdir = 2;
+ string dest_path = 3;
+}
+
+message DataLoader {
+ string package_name = 1;
+ string class_name = 3;
+ string arguments = 2;
+ int32 type = 4;
+}
+
+message Storage {
+ int32 id = 1;
+}
+
+message Mount {
+ Storage storage = 1;
+ DataLoader loader = 2;
+}
diff --git a/services/incremental/ServiceWrappers.cpp b/services/incremental/ServiceWrappers.cpp
new file mode 100644
index 000000000000..a79b26ae4fb3
--- /dev/null
+++ b/services/incremental/ServiceWrappers.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ServiceWrappers.h"
+
+#include <android-base/strings.h>
+#include <android-base/unique_fd.h>
+#include <binder/IServiceManager.h>
+#include <utils/String16.h>
+
+#include <string>
+#include <string_view>
+
+using namespace std::literals;
+
+namespace android::os::incremental {
+
+static constexpr auto kVoldServiceName = "vold"sv;
+static constexpr auto kIncrementalManagerName = "incremental"sv;
+
+RealServiceManager::RealServiceManager(const sp<IServiceManager>& serviceManager)
+ : mServiceManager(serviceManager) {}
+
+template <class INTERFACE>
+sp<INTERFACE> RealServiceManager::getRealService(std::string_view serviceName) const {
+ sp<IBinder> binder = mServiceManager->getService(String16(serviceName.data()));
+ if (binder == 0) {
+ return 0;
+ }
+ return interface_cast<INTERFACE>(binder);
+}
+
+std::shared_ptr<VoldServiceWrapper> RealServiceManager::getVoldService() const {
+ sp<os::IVold> vold = RealServiceManager::getRealService<os::IVold>(kVoldServiceName);
+ if (vold != 0) {
+ return std::make_shared<RealVoldService>(vold);
+ }
+ return nullptr;
+}
+
+std::shared_ptr<IncrementalManagerWrapper> RealServiceManager::getIncrementalManager() const {
+ sp<IIncrementalManager> manager =
+ RealServiceManager::getRealService<IIncrementalManager>(kIncrementalManagerName);
+ if (manager != 0) {
+ return std::make_shared<RealIncrementalManager>(manager);
+ }
+ return nullptr;
+}
+
+std::shared_ptr<IncFsWrapper> RealServiceManager::getIncFs() const {
+ return std::make_shared<RealIncFs>();
+}
+
+} // namespace android::os::incremental
diff --git a/services/incremental/ServiceWrappers.h b/services/incremental/ServiceWrappers.h
new file mode 100644
index 000000000000..570458283ac9
--- /dev/null
+++ b/services/incremental/ServiceWrappers.h
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android-base/strings.h>
+#include <android-base/unique_fd.h>
+#include <android/content/pm/DataLoaderParamsParcel.h>
+#include <android/content/pm/FileSystemControlParcel.h>
+#include <android/content/pm/IDataLoaderStatusListener.h>
+#include <android/os/IVold.h>
+#include <android/os/incremental/IIncrementalManager.h>
+#include <binder/IServiceManager.h>
+#include <incfs.h>
+
+#include <string>
+#include <string_view>
+
+using namespace android::incfs;
+using namespace android::content::pm;
+
+namespace android::os::incremental {
+
+// --- Wrapper interfaces ---
+
+class VoldServiceWrapper {
+public:
+ virtual ~VoldServiceWrapper(){};
+ virtual binder::Status mountIncFs(const std::string& imagePath, const std::string& targetDir,
+ int32_t flags,
+ IncrementalFileSystemControlParcel* _aidl_return) const = 0;
+ virtual binder::Status unmountIncFs(const std::string& dir) const = 0;
+ virtual binder::Status bindMount(const std::string& sourceDir,
+ const std::string& targetDir) const = 0;
+};
+
+class IncrementalManagerWrapper {
+public:
+ virtual ~IncrementalManagerWrapper() {}
+ virtual binder::Status prepareDataLoader(
+ int32_t mountId, const FileSystemControlParcel& control,
+ const DataLoaderParamsParcel& params,
+ const sp<IDataLoaderStatusListener>& listener,
+ bool* _aidl_return) const = 0;
+ virtual binder::Status startDataLoader(int32_t mountId, bool* _aidl_return) const = 0;
+ virtual binder::Status destroyDataLoader(int32_t mountId) const = 0;
+ virtual binder::Status newFileForDataLoader(int32_t mountId, int64_t inode,
+ const ::std::vector<uint8_t>& metadata) const = 0;
+ virtual binder::Status showHealthBlockedUI(int32_t mountId) const = 0;
+};
+
+class IncFsWrapper {
+public:
+ virtual ~IncFsWrapper() {}
+ virtual Inode makeFile(Control control, std::string_view name, Inode parent, Size size,
+ std::string_view metadata) const = 0;
+ virtual Inode makeDir(Control control, std::string_view name, Inode parent,
+ std::string_view metadata, int mode = 0555) const = 0;
+ virtual RawMetadata getMetadata(Control control, Inode inode) const = 0;
+ virtual ErrorCode link(Control control, Inode item, Inode targetParent,
+ std::string_view name) const = 0;
+ virtual ErrorCode unlink(Control control, Inode parent, std::string_view name) const = 0;
+ virtual ErrorCode writeBlocks(Control control, const incfs_new_data_block blocks[],
+ int blocksCount) const = 0;
+};
+
+class ServiceManagerWrapper {
+public:
+ virtual ~ServiceManagerWrapper() {}
+ virtual std::shared_ptr<VoldServiceWrapper> getVoldService() const = 0;
+ virtual std::shared_ptr<IncrementalManagerWrapper> getIncrementalManager() const = 0;
+ virtual std::shared_ptr<IncFsWrapper> getIncFs() const = 0;
+};
+
+// --- Real stuff ---
+
+class RealVoldService : public VoldServiceWrapper {
+public:
+ RealVoldService(const sp<os::IVold> vold) : mInterface(vold) {}
+ ~RealVoldService() = default;
+ binder::Status mountIncFs(const std::string& imagePath, const std::string& targetDir,
+ int32_t flags,
+ IncrementalFileSystemControlParcel* _aidl_return) const override {
+ return mInterface->mountIncFs(imagePath, targetDir, flags, _aidl_return);
+ }
+ binder::Status unmountIncFs(const std::string& dir) const override {
+ return mInterface->unmountIncFs(dir);
+ }
+ binder::Status bindMount(const std::string& sourceDir,
+ const std::string& targetDir) const override {
+ return mInterface->bindMount(sourceDir, targetDir);
+ }
+
+private:
+ sp<os::IVold> mInterface;
+};
+
+class RealIncrementalManager : public IncrementalManagerWrapper {
+public:
+ RealIncrementalManager(const sp<os::incremental::IIncrementalManager> manager)
+ : mInterface(manager) {}
+ ~RealIncrementalManager() = default;
+ binder::Status prepareDataLoader(
+ int32_t mountId, const FileSystemControlParcel& control,
+ const DataLoaderParamsParcel& params,
+ const sp<IDataLoaderStatusListener>& listener,
+ bool* _aidl_return) const override {
+ return mInterface->prepareDataLoader(mountId, control, params, listener, _aidl_return);
+ }
+ binder::Status startDataLoader(int32_t mountId, bool* _aidl_return) const override {
+ return mInterface->startDataLoader(mountId, _aidl_return);
+ }
+ binder::Status destroyDataLoader(int32_t mountId) const override {
+ return mInterface->destroyDataLoader(mountId);
+ }
+ binder::Status newFileForDataLoader(int32_t mountId, int64_t inode,
+ const ::std::vector<uint8_t>& metadata) const override {
+ return mInterface->newFileForDataLoader(mountId, inode, metadata);
+ }
+ binder::Status showHealthBlockedUI(int32_t mountId) const override {
+ return mInterface->showHealthBlockedUI(mountId);
+ }
+
+private:
+ sp<os::incremental::IIncrementalManager> mInterface;
+};
+
+class RealServiceManager : public ServiceManagerWrapper {
+public:
+ RealServiceManager(const sp<IServiceManager>& serviceManager);
+ ~RealServiceManager() = default;
+ std::shared_ptr<VoldServiceWrapper> getVoldService() const override;
+ std::shared_ptr<IncrementalManagerWrapper> getIncrementalManager() const override;
+ std::shared_ptr<IncFsWrapper> getIncFs() const override;
+
+private:
+ template <class INTERFACE>
+ sp<INTERFACE> getRealService(std::string_view serviceName) const;
+ sp<android::IServiceManager> mServiceManager;
+};
+
+class RealIncFs : public IncFsWrapper {
+public:
+ RealIncFs() = default;
+ ~RealIncFs() = default;
+ Inode makeFile(Control control, std::string_view name, Inode parent, Size size,
+ std::string_view metadata) const override {
+ return incfs::makeFile(control, name, parent, size, metadata);
+ }
+ Inode makeDir(Control control, std::string_view name, Inode parent, std::string_view metadata,
+ int mode) const override {
+ return incfs::makeDir(control, name, parent, metadata, mode);
+ }
+ RawMetadata getMetadata(Control control, Inode inode) const override {
+ return incfs::getMetadata(control, inode);
+ }
+ ErrorCode link(Control control, Inode item, Inode targetParent,
+ std::string_view name) const override {
+ return incfs::link(control, item, targetParent, name);
+ }
+ ErrorCode unlink(Control control, Inode parent, std::string_view name) const override {
+ return incfs::unlink(control, parent, name);
+ }
+ ErrorCode writeBlocks(Control control, const incfs_new_data_block blocks[],
+ int blocksCount) const override {
+ return incfs::writeBlocks(control, blocks, blocksCount);
+ }
+};
+
+} // namespace android::os::incremental
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/MainHandler.java b/services/incremental/include/incremental_service.h
index 79661fa4a738..7109d953ba4d 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/MainHandler.java
+++ b/services/incremental/include/incremental_service.h
@@ -14,17 +14,19 @@
* limitations under the License.
*/
-package com.android.systemui.dagger.qualifiers;
+#ifndef ANDROID_INCREMENTAL_SERVICE_H
+#define ANDROID_INCREMENTAL_SERVICE_H
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
+#include <sys/cdefs.h>
+#include <jni.h>
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
+__BEGIN_DECLS
-import javax.inject.Qualifier;
+#define INCREMENTAL_LIBRARY_NAME "service.incremental.so"
-@Qualifier
-@Documented
-@Retention(RUNTIME)
-public @interface MainHandler {
-}
+jlong Incremental_IncrementalService_Start();
+void Incremental_IncrementalService_OnSystemReady(jlong self);
+
+__END_DECLS
+
+#endif // ANDROID_INCREMENTAL_SERVICE_H
diff --git a/services/incremental/incremental_service.c b/services/incremental/incremental_service.c
new file mode 100644
index 000000000000..f6ea59ea0880
--- /dev/null
+++ b/services/incremental/incremental_service.c
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "incremental_service.h"
diff --git a/services/incremental/path.cpp b/services/incremental/path.cpp
new file mode 100644
index 000000000000..c529d61abd15
--- /dev/null
+++ b/services/incremental/path.cpp
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "path.h"
+
+#include <android-base/strings.h>
+#include <android-base/logging.h>
+
+#include <algorithm>
+#include <iterator>
+#include <limits>
+#include <memory>
+
+#include <dirent.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+using namespace std::literals;
+
+namespace android::incremental::path {
+
+bool PathCharsLess::operator()(char l, char r) const {
+ int ll = l == '/' ? std::numeric_limits<char>::min() - 1 : l;
+ int rr = r == '/' ? std::numeric_limits<char>::min() - 1 : r;
+ return ll < rr;
+}
+
+bool PathLess::operator()(std::string_view l, std::string_view r) const {
+ return std::lexicographical_compare(std::begin(l), std::end(l), std::begin(r), std::end(r),
+ PathCharsLess());
+}
+
+void details::append_next_path(std::string& target, std::string_view path) {
+ if (path.empty()) {
+ return;
+ }
+ if (!target.empty()) {
+ target.push_back('/');
+ }
+ target += path;
+}
+
+bool isAbsolute(std::string_view path) {
+ return !path.empty() && path[0] == '/';
+}
+
+std::string normalize(std::string_view path) {
+ if (path.empty()) {
+ return {};
+ }
+ if (path.starts_with("../"sv)) {
+ return {};
+ }
+
+ std::string result;
+ if (isAbsolute(path)) {
+ path.remove_prefix(1);
+ } else {
+ char buffer[PATH_MAX];
+ if (!::getcwd(buffer, sizeof(buffer))) {
+ return {};
+ }
+ result += buffer;
+ }
+
+ size_t start = 0;
+ size_t end = 0;
+ for (; end != path.npos; start = end + 1) {
+ end = path.find('/', start);
+ // Next component, excluding the separator
+ auto part = path.substr(start, end - start);
+ if (part.empty() || part == "."sv) {
+ continue;
+ }
+ if (part == ".."sv) {
+ if (result.empty()) {
+ return {};
+ }
+ auto lastPos = result.rfind('/');
+ if (lastPos == result.npos) {
+ result.clear();
+ } else {
+ result.resize(lastPos);
+ }
+ continue;
+ }
+ result += '/';
+ result += part;
+ }
+
+ return result;
+}
+
+std::string_view basename(std::string_view path) {
+ if (path.empty()) {
+ return {};
+ }
+ if (path == "/"sv) {
+ return "/"sv;
+ }
+ auto pos = path.rfind('/');
+ while (!path.empty() && pos == path.size() - 1) {
+ path.remove_suffix(1);
+ pos = path.rfind('/');
+ }
+ if (pos == path.npos) {
+ return path.empty() ? "/"sv : path;
+ }
+ return path.substr(pos + 1);
+}
+
+std::string_view dirname(std::string_view path) {
+ if (path.empty()) {
+ return {};
+ }
+ if (path == "/"sv) {
+ return "/"sv;
+ }
+ const auto pos = path.rfind('/');
+ if (pos == 0) {
+ return "/"sv;
+ }
+ if (pos == path.npos) {
+ return "."sv;
+ }
+ return path.substr(0, pos);
+}
+
+details::CStrWrapper::CStrWrapper(std::string_view sv) {
+ if (sv[sv.size()] == '\0') {
+ mCstr = sv.data();
+ } else {
+ mCopy.emplace(sv);
+ mCstr = mCopy->c_str();
+ }
+}
+
+std::optional<bool> isEmptyDir(std::string_view dir) {
+ const auto d = std::unique_ptr<DIR, decltype(&::closedir)>{::opendir(c_str(dir)), ::closedir};
+ if (!d) {
+ if (errno == EPERM || errno == EACCES) {
+ return std::nullopt;
+ }
+ return false;
+ }
+ while (auto entry = ::readdir(d.get())) {
+ if (entry->d_type != DT_DIR) {
+ return false;
+ }
+ if (entry->d_name != "."sv && entry->d_name != ".."sv) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool startsWith(std::string_view path, std::string_view prefix) {
+ if (!base::StartsWith(path, prefix)) {
+ return false;
+ }
+ return path.size() == prefix.size() || path[prefix.size()] == '/';
+}
+
+} // namespace android::incremental::path
diff --git a/services/incremental/path.h b/services/incremental/path.h
new file mode 100644
index 000000000000..a1f4b8ec3093
--- /dev/null
+++ b/services/incremental/path.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <optional>
+#include <string>
+#include <string_view>
+
+namespace android::incremental::path {
+
+namespace details {
+
+class CStrWrapper {
+public:
+ CStrWrapper(std::string_view sv);
+
+ CStrWrapper(const CStrWrapper&) = delete;
+ void operator=(const CStrWrapper&) = delete;
+ CStrWrapper(CStrWrapper&&) = delete;
+ void operator=(CStrWrapper&&) = delete;
+
+ const char* get() const { return mCstr; }
+ operator const char*() const { return get(); }
+
+private:
+ const char* mCstr;
+ std::optional<std::string> mCopy;
+};
+
+void append_next_path(std::string& res, std::string_view c);
+
+} // namespace details
+
+//
+// An std::map<> comparator that makes all nested paths to be ordered before the parents.
+//
+
+struct PathCharsLess {
+ bool operator()(char l, char r) const;
+};
+
+struct PathLess {
+ using is_transparent = void;
+ bool operator()(std::string_view l, std::string_view r) const;
+};
+
+//
+// Returns a zero-terminated version of a passed string view
+// Only makes a copy if it wasn't zero-terminated already
+// Useful for passing string view parameters to system functions.
+//
+inline details::CStrWrapper c_str(std::string_view sv) {
+ return {sv};
+}
+
+bool isAbsolute(std::string_view path);
+std::string normalize(std::string_view path);
+std::string_view dirname(std::string_view path);
+std::string_view basename(std::string_view path);
+std::optional<bool> isEmptyDir(std::string_view dir);
+bool startsWith(std::string_view path, std::string_view prefix);
+
+template <class... Paths>
+std::string join(std::string_view first, std::string_view second, Paths&&... paths) {
+ std::string result;
+ {
+ using std::size;
+ result.reserve(first.size() + second.size() + 1 + (sizeof...(paths) + ... + size(paths)));
+ }
+ result.assign(first);
+ (details::append_next_path(result, second), ..., details::append_next_path(result, paths));
+ return result;
+}
+
+} // namespace android::incremental::path
diff --git a/services/incremental/test/IncrementalServiceTest.cpp b/services/incremental/test/IncrementalServiceTest.cpp
new file mode 100644
index 000000000000..ca1e1a972047
--- /dev/null
+++ b/services/incremental/test/IncrementalServiceTest.cpp
@@ -0,0 +1,461 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/unique_fd.h>
+#include <binder/ParcelFileDescriptor.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <utils/Log.h>
+
+#include <future>
+
+#include "IncrementalService.h"
+#include "Metadata.pb.h"
+#include "ServiceWrappers.h"
+
+using namespace testing;
+using namespace android::incremental;
+using namespace std::literals;
+using testing::_;
+using testing::Invoke;
+using testing::NiceMock;
+
+#undef LOG_TAG
+#define LOG_TAG "IncrementalServiceTest"
+
+using namespace android::incfs;
+using namespace android::content::pm;
+
+namespace android::os::incremental {
+
+class MockVoldService : public VoldServiceWrapper {
+public:
+ MOCK_CONST_METHOD4(mountIncFs,
+ binder::Status(const std::string& imagePath, const std::string& targetDir,
+ int32_t flags,
+ IncrementalFileSystemControlParcel* _aidl_return));
+ MOCK_CONST_METHOD1(unmountIncFs, binder::Status(const std::string& dir));
+ MOCK_CONST_METHOD2(bindMount,
+ binder::Status(const std::string& sourceDir, const std::string& argetDir));
+
+ void mountIncFsFails() {
+ ON_CALL(*this, mountIncFs(_, _, _, _))
+ .WillByDefault(
+ Return(binder::Status::fromExceptionCode(1, String8("failed to mount"))));
+ }
+ void mountIncFsInvalidControlParcel() {
+ ON_CALL(*this, mountIncFs(_, _, _, _))
+ .WillByDefault(Invoke(this, &MockVoldService::getInvalidControlParcel));
+ }
+ void mountIncFsSuccess() {
+ ON_CALL(*this, mountIncFs(_, _, _, _))
+ .WillByDefault(Invoke(this, &MockVoldService::incFsSuccess));
+ }
+ void bindMountFails() {
+ ON_CALL(*this, bindMount(_, _))
+ .WillByDefault(Return(
+ binder::Status::fromExceptionCode(1, String8("failed to bind-mount"))));
+ }
+ void bindMountSuccess() {
+ ON_CALL(*this, bindMount(_, _)).WillByDefault(Return(binder::Status::ok()));
+ }
+ binder::Status getInvalidControlParcel(const std::string& imagePath,
+ const std::string& targetDir, int32_t flags,
+ IncrementalFileSystemControlParcel* _aidl_return) {
+ _aidl_return->cmd = nullptr;
+ _aidl_return->log = nullptr;
+ return binder::Status::ok();
+ }
+ binder::Status incFsSuccess(const std::string& imagePath, const std::string& targetDir,
+ int32_t flags, IncrementalFileSystemControlParcel* _aidl_return) {
+ _aidl_return->cmd = std::make_unique<os::ParcelFileDescriptor>(std::move(cmdFd));
+ _aidl_return->log = std::make_unique<os::ParcelFileDescriptor>(std::move(logFd));
+ return binder::Status::ok();
+ }
+
+private:
+ TemporaryFile cmdFile;
+ TemporaryFile logFile;
+ base::unique_fd cmdFd;
+ base::unique_fd logFd;
+};
+
+class MockIncrementalManager : public IncrementalManagerWrapper {
+public:
+ MOCK_CONST_METHOD5(prepareDataLoader,
+ binder::Status(int32_t mountId, const FileSystemControlParcel& control,
+ const DataLoaderParamsParcel& params,
+ const sp<IDataLoaderStatusListener>& listener,
+ bool* _aidl_return));
+ MOCK_CONST_METHOD2(startDataLoader, binder::Status(int32_t mountId, bool* _aidl_return));
+ MOCK_CONST_METHOD1(destroyDataLoader, binder::Status(int32_t mountId));
+ MOCK_CONST_METHOD3(newFileForDataLoader,
+ binder::Status(int32_t mountId, int64_t inode,
+ const ::std::vector<uint8_t>& metadata));
+ MOCK_CONST_METHOD1(showHealthBlockedUI, binder::Status(int32_t mountId));
+
+ binder::Status prepareDataLoaderOk(int32_t mountId, const FileSystemControlParcel& control,
+ const DataLoaderParamsParcel& params,
+ const sp<IDataLoaderStatusListener>& listener,
+ bool* _aidl_return) {
+ mId = mountId;
+ mListener = listener;
+ *_aidl_return = true;
+ return binder::Status::ok();
+ }
+
+ binder::Status startDataLoaderOk(int32_t mountId, bool* _aidl_return) {
+ *_aidl_return = true;
+ return binder::Status::ok();
+ }
+
+ void prepareDataLoaderFails() {
+ ON_CALL(*this, prepareDataLoader(_, _, _, _, _))
+ .WillByDefault(Return(
+ (binder::Status::fromExceptionCode(1, String8("failed to prepare")))));
+ }
+ void prepareDataLoaderSuccess() {
+ ON_CALL(*this, prepareDataLoader(_, _, _, _, _))
+ .WillByDefault(Invoke(this, &MockIncrementalManager::prepareDataLoaderOk));
+ }
+ void startDataLoaderSuccess() {
+ ON_CALL(*this, startDataLoader(_, _))
+ .WillByDefault(Invoke(this, &MockIncrementalManager::startDataLoaderOk));
+ }
+ void setDataLoaderStatusNotReady() {
+ mListener->onStatusChanged(mId, IDataLoaderStatusListener::DATA_LOADER_DESTROYED);
+ }
+ void setDataLoaderStatusReady() {
+ mListener->onStatusChanged(mId, IDataLoaderStatusListener::DATA_LOADER_CREATED);
+ }
+
+private:
+ int mId;
+ sp<IDataLoaderStatusListener> mListener;
+};
+
+class MockIncFs : public IncFsWrapper {
+public:
+ MOCK_CONST_METHOD5(makeFile,
+ Inode(Control control, std::string_view name, Inode parent, Size size,
+ std::string_view metadata));
+ MOCK_CONST_METHOD5(makeDir,
+ Inode(Control control, std::string_view name, Inode parent,
+ std::string_view metadata, int mode));
+ MOCK_CONST_METHOD2(getMetadata, RawMetadata(Control control, Inode inode));
+ MOCK_CONST_METHOD4(link,
+ ErrorCode(Control control, Inode item, Inode targetParent,
+ std::string_view name));
+ MOCK_CONST_METHOD3(unlink, ErrorCode(Control control, Inode parent, std::string_view name));
+ MOCK_CONST_METHOD3(writeBlocks,
+ ErrorCode(Control control, const incfs_new_data_block blocks[],
+ int blocksCount));
+
+ void makeFileFails() { ON_CALL(*this, makeFile(_, _, _, _, _)).WillByDefault(Return(-1)); }
+ void makeFileSuccess() { ON_CALL(*this, makeFile(_, _, _, _, _)).WillByDefault(Return(0)); }
+ RawMetadata getMountInfoMetadata(Control control, Inode inode) {
+ metadata::Mount m;
+ m.mutable_storage()->set_id(100);
+ m.mutable_loader()->set_package_name("com.test");
+ m.mutable_loader()->set_arguments("com.uri");
+ const auto metadata = m.SerializeAsString();
+ m.mutable_loader()->release_arguments();
+ m.mutable_loader()->release_package_name();
+ return std::vector<char>(metadata.begin(), metadata.end());
+ }
+ RawMetadata getStorageMetadata(Control control, Inode inode) {
+ metadata::Storage st;
+ st.set_id(100);
+ auto metadata = st.SerializeAsString();
+ return std::vector<char>(metadata.begin(), metadata.end());
+ }
+ RawMetadata getBindPointMetadata(Control control, Inode inode) {
+ metadata::BindPoint bp;
+ std::string destPath = "dest";
+ std::string srcPath = "src";
+ bp.set_storage_id(100);
+ bp.set_allocated_dest_path(&destPath);
+ bp.set_allocated_source_subdir(&srcPath);
+ const auto metadata = bp.SerializeAsString();
+ bp.release_source_subdir();
+ bp.release_dest_path();
+ return std::vector<char>(metadata.begin(), metadata.end());
+ }
+};
+
+class MockServiceManager : public ServiceManagerWrapper {
+public:
+ MockServiceManager(std::shared_ptr<MockVoldService> vold,
+ std::shared_ptr<MockIncrementalManager> manager,
+ std::shared_ptr<MockIncFs> incfs)
+ : mVold(vold), mIncrementalManager(manager), mIncFs(incfs) {}
+ std::shared_ptr<VoldServiceWrapper> getVoldService() const override { return mVold; }
+ std::shared_ptr<IncrementalManagerWrapper> getIncrementalManager() const override {
+ return mIncrementalManager;
+ }
+ std::shared_ptr<IncFsWrapper> getIncFs() const override { return mIncFs; }
+
+private:
+ std::shared_ptr<MockVoldService> mVold;
+ std::shared_ptr<MockIncrementalManager> mIncrementalManager;
+ std::shared_ptr<MockIncFs> mIncFs;
+};
+
+// --- IncrementalServiceTest ---
+
+static Inode inode(std::string_view path) {
+ struct stat st;
+ if (::stat(path::c_str(path), &st)) {
+ return -1;
+ }
+ return st.st_ino;
+}
+
+class IncrementalServiceTest : public testing::Test {
+public:
+ void SetUp() override {
+ mVold = std::make_shared<NiceMock<MockVoldService>>();
+ mIncrementalManager = std::make_shared<NiceMock<MockIncrementalManager>>();
+ mIncFs = std::make_shared<NiceMock<MockIncFs>>();
+ MockServiceManager serviceManager = MockServiceManager(mVold, mIncrementalManager, mIncFs);
+ mIncrementalService = std::make_unique<IncrementalService>(serviceManager, mRootDir.path);
+ mDataLoaderParcel.packageName = "com.test";
+ mDataLoaderParcel.arguments = "uri";
+ mIncrementalService->onSystemReady();
+ }
+
+ void setUpExistingMountDir(const std::string& rootDir) {
+ const auto dir = rootDir + "/dir1";
+ const auto mountDir = dir + "/mount";
+ const auto backingDir = dir + "/backing_store";
+ const auto storageDir = mountDir + "/st0";
+ ASSERT_EQ(0, mkdir(dir.c_str(), 0755));
+ ASSERT_EQ(0, mkdir(mountDir.c_str(), 0755));
+ ASSERT_EQ(0, mkdir(backingDir.c_str(), 0755));
+ ASSERT_EQ(0, mkdir(storageDir.c_str(), 0755));
+ const auto mountInfoFile = rootDir + "/dir1/mount/.info";
+ const auto mountPointsFile = rootDir + "/dir1/mount/.mountpoint.abcd";
+ ASSERT_TRUE(base::WriteStringToFile("info", mountInfoFile));
+ ASSERT_TRUE(base::WriteStringToFile("mounts", mountPointsFile));
+ ASSERT_GE(inode(mountInfoFile), 0);
+ ASSERT_GE(inode(mountPointsFile), 0);
+ ON_CALL(*mIncFs, getMetadata(_, inode(mountInfoFile)))
+ .WillByDefault(Invoke(mIncFs.get(), &MockIncFs::getMountInfoMetadata));
+ ON_CALL(*mIncFs, getMetadata(_, inode(mountPointsFile)))
+ .WillByDefault(Invoke(mIncFs.get(), &MockIncFs::getBindPointMetadata));
+ ON_CALL(*mIncFs, getMetadata(_, inode(rootDir + "/dir1/mount/st0")))
+ .WillByDefault(Invoke(mIncFs.get(), &MockIncFs::getStorageMetadata));
+ }
+
+protected:
+ std::shared_ptr<NiceMock<MockVoldService>> mVold;
+ std::shared_ptr<NiceMock<MockIncFs>> mIncFs;
+ std::shared_ptr<NiceMock<MockIncrementalManager>> mIncrementalManager;
+ std::unique_ptr<IncrementalService> mIncrementalService;
+ TemporaryDir mRootDir;
+ DataLoaderParamsParcel mDataLoaderParcel;
+};
+
+/*
+TEST_F(IncrementalServiceTest, testBootMountExistingImagesSuccess) {
+ TemporaryDir tempDir;
+ setUpExistingMountDir(tempDir.path);
+ mVold->mountIncFsSuccess();
+ mVold->bindMountSuccess();
+ mIncrementalManager->prepareDataLoaderSuccess();
+ ON_CALL(*mIncrementalManager, destroyDataLoader(_)).WillByDefault(Return(binder::Status::ok()));
+
+ EXPECT_CALL(*mVold, mountIncFs(_, _, _, _)).Times(1);
+ EXPECT_CALL(*mIncrementalManager, prepareDataLoader(_, _, _, _, _)).Times(1);
+
+ MockServiceManager serviceManager = MockServiceManager(mVold, mIncrementalManager, mIncFs);
+ std::unique_ptr<IncrementalService> incrementalService =
+ std::make_unique<IncrementalService>(serviceManager, tempDir.path);
+ auto finished = incrementalService->onSystemReady();
+ if (finished) {
+ finished->wait();
+ }
+}
+*/
+
+TEST_F(IncrementalServiceTest, testCreateStorageMountIncFsFails) {
+ mVold->mountIncFsFails();
+ EXPECT_CALL(*mIncrementalManager, prepareDataLoader(_, _, _, _, _)).Times(0);
+ TemporaryDir tempDir;
+ int storageId =
+ mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
+ IncrementalService::CreateOptions::CreateNew);
+ ASSERT_LT(storageId, 0);
+}
+
+TEST_F(IncrementalServiceTest, testCreateStorageMountIncFsInvalidControlParcel) {
+ mVold->mountIncFsInvalidControlParcel();
+ EXPECT_CALL(*mIncrementalManager, prepareDataLoader(_, _, _, _, _)).Times(0);
+ TemporaryDir tempDir;
+ int storageId =
+ mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
+ IncrementalService::CreateOptions::CreateNew);
+ ASSERT_LT(storageId, 0);
+}
+
+TEST_F(IncrementalServiceTest, testCreateStorageMakeFileFails) {
+ mVold->mountIncFsSuccess();
+ mIncFs->makeFileFails();
+ EXPECT_CALL(*mIncrementalManager, prepareDataLoader(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(*mIncrementalManager, destroyDataLoader(_));
+ EXPECT_CALL(*mVold, unmountIncFs(_));
+ TemporaryDir tempDir;
+ int storageId =
+ mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
+ IncrementalService::CreateOptions::CreateNew);
+ ASSERT_LT(storageId, 0);
+}
+
+TEST_F(IncrementalServiceTest, testCreateStorageBindMountFails) {
+ mVold->mountIncFsSuccess();
+ mIncFs->makeFileSuccess();
+ mVold->bindMountFails();
+ EXPECT_CALL(*mIncrementalManager, prepareDataLoader(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(*mIncrementalManager, destroyDataLoader(_));
+ EXPECT_CALL(*mVold, unmountIncFs(_));
+ TemporaryDir tempDir;
+ int storageId =
+ mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
+ IncrementalService::CreateOptions::CreateNew);
+ ASSERT_LT(storageId, 0);
+}
+
+TEST_F(IncrementalServiceTest, testCreateStoragePrepareDataLoaderFails) {
+ mVold->mountIncFsSuccess();
+ mIncFs->makeFileSuccess();
+ mVold->bindMountSuccess();
+ mIncrementalManager->prepareDataLoaderFails();
+ EXPECT_CALL(*mIncrementalManager, destroyDataLoader(_));
+ EXPECT_CALL(*mVold, unmountIncFs(_)).Times(2);
+ TemporaryDir tempDir;
+ int storageId =
+ mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
+ IncrementalService::CreateOptions::CreateNew);
+ ASSERT_LT(storageId, 0);
+}
+
+TEST_F(IncrementalServiceTest, testDeleteStorageSuccess) {
+ mVold->mountIncFsSuccess();
+ mIncFs->makeFileSuccess();
+ mVold->bindMountSuccess();
+ mIncrementalManager->prepareDataLoaderSuccess();
+ EXPECT_CALL(*mIncrementalManager, destroyDataLoader(_));
+ EXPECT_CALL(*mVold, unmountIncFs(_)).Times(2);
+ TemporaryDir tempDir;
+ int storageId =
+ mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
+ IncrementalService::CreateOptions::CreateNew);
+ ASSERT_GE(storageId, 0);
+ mIncrementalService->deleteStorage(storageId);
+}
+
+TEST_F(IncrementalServiceTest, testOnStatusNotReady) {
+ mVold->mountIncFsSuccess();
+ mIncFs->makeFileSuccess();
+ mVold->bindMountSuccess();
+ mIncrementalManager->prepareDataLoaderSuccess();
+ EXPECT_CALL(*mIncrementalManager, destroyDataLoader(_));
+ EXPECT_CALL(*mVold, unmountIncFs(_)).Times(2);
+ TemporaryDir tempDir;
+ int storageId =
+ mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
+ IncrementalService::CreateOptions::CreateNew);
+ ASSERT_GE(storageId, 0);
+ mIncrementalManager->setDataLoaderStatusNotReady();
+}
+
+TEST_F(IncrementalServiceTest, testStartDataLoaderSuccess) {
+ mVold->mountIncFsSuccess();
+ mIncFs->makeFileSuccess();
+ mVold->bindMountSuccess();
+ mIncrementalManager->prepareDataLoaderSuccess();
+ mIncrementalManager->startDataLoaderSuccess();
+ EXPECT_CALL(*mIncrementalManager, destroyDataLoader(_));
+ EXPECT_CALL(*mVold, unmountIncFs(_)).Times(2);
+ TemporaryDir tempDir;
+ int storageId =
+ mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
+ IncrementalService::CreateOptions::CreateNew);
+ ASSERT_GE(storageId, 0);
+ mIncrementalManager->setDataLoaderStatusReady();
+ ASSERT_TRUE(mIncrementalService->startLoading(storageId));
+}
+
+TEST_F(IncrementalServiceTest, testMakeDirectory) {
+ mVold->mountIncFsSuccess();
+ mIncFs->makeFileSuccess();
+ mVold->bindMountSuccess();
+ mIncrementalManager->prepareDataLoaderSuccess();
+ mIncrementalManager->startDataLoaderSuccess();
+ TemporaryDir tempDir;
+ int storageId =
+ mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
+ IncrementalService::CreateOptions::CreateNew);
+ std::string_view dir_path("test");
+ EXPECT_CALL(*mIncFs, makeDir(_, dir_path, _, _, _));
+ int fileIno = mIncrementalService->makeDir(storageId, dir_path, "");
+ ASSERT_GE(fileIno, 0);
+}
+
+TEST_F(IncrementalServiceTest, testMakeDirectoryNoParent) {
+ mVold->mountIncFsSuccess();
+ mIncFs->makeFileSuccess();
+ mVold->bindMountSuccess();
+ mIncrementalManager->prepareDataLoaderSuccess();
+ mIncrementalManager->startDataLoaderSuccess();
+ TemporaryDir tempDir;
+ int storageId =
+ mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
+ IncrementalService::CreateOptions::CreateNew);
+ std::string_view first("first");
+ std::string_view second("second");
+ std::string dir_path = std::string(first) + "/" + std::string(second);
+ EXPECT_CALL(*mIncFs, makeDir(_, first, _, _, _)).Times(0);
+ EXPECT_CALL(*mIncFs, makeDir(_, second, _, _, _)).Times(0);
+ int fileIno = mIncrementalService->makeDir(storageId, dir_path, "");
+ ASSERT_LT(fileIno, 0);
+}
+
+TEST_F(IncrementalServiceTest, testMakeDirectories) {
+ mVold->mountIncFsSuccess();
+ mIncFs->makeFileSuccess();
+ mVold->bindMountSuccess();
+ mIncrementalManager->prepareDataLoaderSuccess();
+ mIncrementalManager->startDataLoaderSuccess();
+ TemporaryDir tempDir;
+ int storageId =
+ mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
+ IncrementalService::CreateOptions::CreateNew);
+ std::string_view first("first");
+ std::string_view second("second");
+ std::string_view third("third");
+ InSequence seq;
+ EXPECT_CALL(*mIncFs, makeDir(_, first, _, _, _));
+ EXPECT_CALL(*mIncFs, makeDir(_, second, _, _, _));
+ EXPECT_CALL(*mIncFs, makeDir(_, third, _, _, _));
+ std::string dir_path =
+ std::string(first) + "/" + std::string(second) + "/" + std::string(third);
+ int fileIno = mIncrementalService->makeDirs(storageId, dir_path, "");
+ ASSERT_GE(fileIno, 0);
+}
+} // namespace android::os::incremental
diff --git a/services/incremental/test/path_test.cpp b/services/incremental/test/path_test.cpp
new file mode 100644
index 000000000000..cbe479e10087
--- /dev/null
+++ b/services/incremental/test/path_test.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "../path.h"
+
+#include <gtest/gtest.h>
+
+using namespace std::literals;
+
+namespace android::incremental::path {
+
+TEST(Path, Normalize) {
+ EXPECT_STREQ("", normalize("").c_str());
+ EXPECT_STREQ("/data/app/com.snapchat.android-evzhnJDgPOq8VcxwEkSY5g==/base.apk",
+ normalize("/data/app/com.snapchat.android-evzhnJDgPOq8VcxwEkSY5g==/base.apk")
+ .c_str());
+ EXPECT_STREQ("/a/b", normalize("/a/c/../b").c_str());
+}
+
+TEST(Path, Comparator) {
+ EXPECT_TRUE(PathLess()("/a", "/aa"));
+ EXPECT_TRUE(PathLess()("/a/b", "/aa/b"));
+ EXPECT_TRUE(PathLess()("/a", "/a/b"));
+ EXPECT_TRUE(PathLess()("/a/b"sv, "/a\0"sv));
+ EXPECT_TRUE(!PathLess()("/aa/b", "/a/b"));
+ EXPECT_TRUE(!PathLess()("/a/b", "/a/b"));
+ EXPECT_TRUE(!PathLess()("/a/b", "/a"));
+}
+
+} // namespace android::incremental::path
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index a1e02370aa51..cfe131899987 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -16,6 +16,7 @@
package com.android.server;
+import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL;
import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_HIGH;
import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL;
@@ -42,8 +43,8 @@ import android.database.sqlite.SQLiteCompatibilityWalFlags;
import android.database.sqlite.SQLiteGlobal;
import android.hardware.display.DisplayManagerInternal;
import android.net.ConnectivityModuleConnector;
+import android.net.ITetheringConnector;
import android.net.NetworkStackClient;
-import android.net.TetheringManager;
import android.os.BaseBundle;
import android.os.Binder;
import android.os.Build;
@@ -145,6 +146,7 @@ import com.android.server.recoverysystem.RecoverySystemService;
import com.android.server.restrictions.RestrictionsManagerService;
import com.android.server.role.RoleManagerService;
import com.android.server.rollback.RollbackManagerService;
+import com.android.server.security.FileIntegrityService;
import com.android.server.security.KeyAttestationApplicationIdProviderService;
import com.android.server.security.KeyChainSystemService;
import com.android.server.signedconfig.SignedConfigService;
@@ -210,8 +212,8 @@ public final class SystemServer {
"com.android.server.print.PrintManagerService";
private static final String COMPANION_DEVICE_MANAGER_SERVICE_CLASS =
"com.android.server.companion.CompanionDeviceManagerService";
- private static final String STATS_COMPANION_SERVICE_LIFECYCLE_CLASS =
- "com.android.server.stats.StatsCompanionService$Lifecycle";
+ private static final String STATS_COMPANION_LIFECYCLE_CLASS =
+ "com.android.server.stats.StatsCompanion$Lifecycle";
private static final String USB_SERVICE_CLASS =
"com.android.server.usb.UsbService$Lifecycle";
private static final String MIDI_SERVICE_CLASS =
@@ -672,6 +674,13 @@ public final class SystemServer {
AppCompatCallbacks.install(new long[0]);
t.traceEnd();
+ // FileIntegrityService responds to requests from apps and the system. It needs to run after
+ // the source (i.e. keystore) is ready, and before the apps (or the first customer in the
+ // system) run.
+ t.traceBegin("StartFileIntegrityService");
+ mSystemServiceManager.startService(FileIntegrityService.class);
+ t.traceEnd();
+
// Wait for installd to finish starting up so that it has a chance to
// create critical directories such as /data/user with the appropriate
// permissions. We need this to complete before we initialize other services.
@@ -1962,8 +1971,8 @@ public final class SystemServer {
}
// Statsd helper
- t.traceBegin("StartStatsCompanionService");
- mSystemServiceManager.startService(STATS_COMPANION_SERVICE_LIFECYCLE_CLASS);
+ t.traceBegin("StartStatsCompanion");
+ mSystemServiceManager.startService(STATS_COMPANION_LIFECYCLE_CLASS);
t.traceEnd();
// Incidentd and dumpstated helper
@@ -2267,8 +2276,14 @@ public final class SystemServer {
t.traceBegin("StartTethering");
try {
- // Tethering must start after ConnectivityService and NetworkStack.
- TetheringManager.getInstance().start();
+ // TODO: hide implementation details, b/146312721.
+ ConnectivityModuleConnector.getInstance().startModuleService(
+ ITetheringConnector.class.getName(),
+ PERMISSION_MAINLINE_NETWORK_STACK, service -> {
+ ServiceManager.addService(Context.TETHERING_SERVICE, service,
+ false /* allowIsolated */,
+ DUMP_FLAG_PRIORITY_HIGH | DUMP_FLAG_PRIORITY_NORMAL);
+ });
} catch (Throwable e) {
reportWtf("starting Tethering", e);
}
diff --git a/services/net/Android.bp b/services/net/Android.bp
index 3babb0b0a133..9c7cfc197bba 100644
--- a/services/net/Android.bp
+++ b/services/net/Android.bp
@@ -10,14 +10,12 @@ java_library_static {
srcs: [
":net-module-utils-srcs",
":services.net-sources",
- ":tethering-manager",
],
static_libs: [
"dnsresolver_aidl_interface-V2-java",
"netd_aidl_interface-unstable-java",
"netlink-client",
"networkstack-client",
- "tethering-client",
],
}
@@ -25,8 +23,6 @@ filegroup {
name: "services-tethering-shared-srcs",
srcs: [
":framework-annotations",
- "java/android/net/ConnectivityModuleConnector.java",
- "java/android/net/NetworkStackClient.java",
"java/android/net/util/NetdService.java",
"java/android/net/util/NetworkConstants.java",
],
diff --git a/services/print/java/com/android/server/print/PrintManagerService.java b/services/print/java/com/android/server/print/PrintManagerService.java
index c9b9f3e6bd48..d064f7ee62c3 100644
--- a/services/print/java/com/android/server/print/PrintManagerService.java
+++ b/services/print/java/com/android/server/print/PrintManagerService.java
@@ -78,6 +78,7 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
+import java.util.Objects;
/**
* SystemService wrapper for the PrintManager implementation. Publishes
@@ -137,7 +138,7 @@ public final class PrintManagerService extends SystemService {
@Override
public Bundle print(String printJobName, IPrintDocumentAdapter adapter,
PrintAttributes attributes, String packageName, int appId, int userId) {
- adapter = Preconditions.checkNotNull(adapter);
+ Objects.requireNonNull(adapter);
if (!isPrintingEnabled()) {
CharSequence disabledMessage = null;
DevicePolicyManagerInternal dpmi =
@@ -239,7 +240,7 @@ public final class PrintManagerService extends SystemService {
@Override
public Icon getCustomPrinterIcon(PrinterId printerId, int userId) {
- printerId = Preconditions.checkNotNull(printerId);
+ Objects.requireNonNull(printerId);
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
final UserState userState;
@@ -349,7 +350,7 @@ public final class PrintManagerService extends SystemService {
return;
}
- service = Preconditions.checkNotNull(service);
+ Objects.requireNonNull(service);
final UserState userState;
synchronized (mLock) {
@@ -391,7 +392,7 @@ public final class PrintManagerService extends SystemService {
@Override
public void createPrinterDiscoverySession(IPrinterDiscoveryObserver observer,
int userId) {
- observer = Preconditions.checkNotNull(observer);
+ Objects.requireNonNull(observer);
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
final UserState userState;
@@ -413,7 +414,7 @@ public final class PrintManagerService extends SystemService {
@Override
public void destroyPrinterDiscoverySession(IPrinterDiscoveryObserver observer,
int userId) {
- observer = Preconditions.checkNotNull(observer);
+ Objects.requireNonNull(observer);
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
final UserState userState;
@@ -435,7 +436,7 @@ public final class PrintManagerService extends SystemService {
@Override
public void startPrinterDiscovery(IPrinterDiscoveryObserver observer,
List<PrinterId> priorityList, int userId) {
- observer = Preconditions.checkNotNull(observer);
+ Objects.requireNonNull(observer);
if (priorityList != null) {
priorityList = Preconditions.checkCollectionElementsNotNull(priorityList,
"PrinterId");
@@ -460,7 +461,7 @@ public final class PrintManagerService extends SystemService {
@Override
public void stopPrinterDiscovery(IPrinterDiscoveryObserver observer, int userId) {
- observer = Preconditions.checkNotNull(observer);
+ Objects.requireNonNull(observer);
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
final UserState userState;
@@ -502,7 +503,7 @@ public final class PrintManagerService extends SystemService {
@Override
public void startPrinterStateTracking(PrinterId printerId, int userId) {
- printerId = Preconditions.checkNotNull(printerId);
+ Objects.requireNonNull(printerId);
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
final UserState userState;
@@ -523,7 +524,7 @@ public final class PrintManagerService extends SystemService {
@Override
public void stopPrinterStateTracking(PrinterId printerId, int userId) {
- printerId = Preconditions.checkNotNull(printerId);
+ Objects.requireNonNull(printerId);
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
final UserState userState;
@@ -545,7 +546,7 @@ public final class PrintManagerService extends SystemService {
@Override
public void addPrintJobStateChangeListener(IPrintJobStateChangeListener listener,
int appId, int userId) throws RemoteException {
- listener = Preconditions.checkNotNull(listener);
+ Objects.requireNonNull(listener);
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
final int resolvedAppId;
@@ -569,7 +570,7 @@ public final class PrintManagerService extends SystemService {
@Override
public void removePrintJobStateChangeListener(IPrintJobStateChangeListener listener,
int userId) {
- listener = Preconditions.checkNotNull(listener);
+ Objects.requireNonNull(listener);
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
final UserState userState;
@@ -591,7 +592,7 @@ public final class PrintManagerService extends SystemService {
@Override
public void addPrintServicesChangeListener(IPrintServicesChangeListener listener,
int userId) throws RemoteException {
- listener = Preconditions.checkNotNull(listener);
+ Objects.requireNonNull(listener);
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PRINT_SERVICES,
null);
@@ -615,7 +616,7 @@ public final class PrintManagerService extends SystemService {
@Override
public void removePrintServicesChangeListener(IPrintServicesChangeListener listener,
int userId) {
- listener = Preconditions.checkNotNull(listener);
+ Objects.requireNonNull(listener);
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PRINT_SERVICES,
null);
@@ -640,7 +641,7 @@ public final class PrintManagerService extends SystemService {
public void addPrintServiceRecommendationsChangeListener(
IRecommendationsChangeListener listener, int userId)
throws RemoteException {
- listener = Preconditions.checkNotNull(listener);
+ Objects.requireNonNull(listener);
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.READ_PRINT_SERVICE_RECOMMENDATIONS, null);
@@ -664,7 +665,7 @@ public final class PrintManagerService extends SystemService {
@Override
public void removePrintServiceRecommendationsChangeListener(
IRecommendationsChangeListener listener, int userId) {
- listener = Preconditions.checkNotNull(listener);
+ Objects.requireNonNull(listener);
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.READ_PRINT_SERVICE_RECOMMENDATIONS, null);
@@ -688,7 +689,7 @@ public final class PrintManagerService extends SystemService {
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- fd = Preconditions.checkNotNull(fd);
+ Objects.requireNonNull(fd);
if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return;
diff --git a/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java b/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java
index 1e270077780d..f0758dd3ef32 100644
--- a/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java
@@ -44,7 +44,6 @@ import android.app.AppOpsManager.PackageOps;
import android.app.IActivityManager;
import android.app.IUidObserver;
import android.app.usage.UsageStatsManager;
-import android.app.usage.UsageStatsManagerInternal;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -82,6 +81,7 @@ import org.mockito.stubbing.Answer;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
@@ -690,11 +690,11 @@ public class AppStateTrackerTest {
entries.add(new OpEntry(
AppOpsManager.OP_ACCESS_NOTIFICATIONS,
AppOpsManager.MODE_IGNORED,
- new Pair[0]));
+ Collections.emptyMap()));
entries.add(new OpEntry(
AppStateTracker.TARGET_OP,
AppOpsManager.MODE_IGNORED,
- new Pair[0]));
+ Collections.emptyMap()));
ops.add(new PackageOps(PACKAGE_1, UID_1, entries));
@@ -703,7 +703,7 @@ public class AppStateTrackerTest {
entries.add(new OpEntry(
AppStateTracker.TARGET_OP,
AppOpsManager.MODE_IGNORED,
- new Pair[0]));
+ Collections.emptyMap()));
ops.add(new PackageOps(PACKAGE_2, UID_2, entries));
@@ -712,7 +712,7 @@ public class AppStateTrackerTest {
entries.add(new OpEntry(
AppStateTracker.TARGET_OP,
AppOpsManager.MODE_ALLOWED,
- new Pair[0]));
+ Collections.emptyMap()));
ops.add(new PackageOps(PACKAGE_1, UID_10_1, entries));
@@ -721,11 +721,11 @@ public class AppStateTrackerTest {
entries.add(new OpEntry(
AppStateTracker.TARGET_OP,
AppOpsManager.MODE_IGNORED,
- new Pair[0]));
+ Collections.emptyMap()));
entries.add(new OpEntry(
AppOpsManager.OP_ACCESS_NOTIFICATIONS,
AppOpsManager.MODE_IGNORED,
- new Pair[0]));
+ Collections.emptyMap()));
ops.add(new PackageOps(PACKAGE_3, UID_10_3, entries));
diff --git a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
index 45de451e5bea..9251031eb5cd 100644
--- a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
@@ -61,6 +61,7 @@ import static org.mockito.ArgumentMatchers.longThat;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
import android.app.ActivityManagerInternal;
@@ -70,7 +71,11 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
+import android.hardware.TriggerEvent;
+import android.hardware.TriggerEventListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.net.ConnectivityManager;
@@ -131,6 +136,8 @@ public class DeviceIdleControllerTest {
@Mock
private PowerManagerInternal mPowerManagerInternal;
@Mock
+ private Sensor mMotionSensor;
+ @Mock
private SensorManager mSensorManager;
class InjectorForTest extends DeviceIdleController.Injector {
@@ -203,6 +210,11 @@ public class DeviceIdleControllerTest {
}
@Override
+ Sensor getMotionSensor() {
+ return mMotionSensor;
+ }
+
+ @Override
PowerManager getPowerManager() {
return mPowerManager;
}
@@ -1787,22 +1799,36 @@ public class DeviceIdleControllerTest {
}
@Test
- public void testStationaryDetection_QuickDozeOn() {
+ public void testStationaryDetection_QuickDozeOn_NoMotion() {
+ // Short timeout for testing.
+ mConstants.MOTION_INACTIVE_TIMEOUT = 6000L;
+ doReturn(Sensor.REPORTING_MODE_ONE_SHOT).when(mMotionSensor).getReportingMode();
+ doReturn(true).when(mSensorManager)
+ .requestTriggerSensor(eq(mDeviceIdleController.mMotionListener), eq(mMotionSensor));
setAlarmSoon(false);
enterDeepState(STATE_QUICK_DOZE_DELAY);
mDeviceIdleController.stepIdleStateLocked("testing");
verifyStateConditions(STATE_IDLE);
// Quick doze progression through states, so time should have increased appropriately.
mInjector.nowElapsed += mConstants.QUICK_DOZE_DELAY_TIMEOUT;
- final ArgumentCaptor<AlarmManager.OnAlarmListener> alarmListener = ArgumentCaptor
+ final ArgumentCaptor<AlarmManager.OnAlarmListener> motionAlarmListener = ArgumentCaptor
.forClass(AlarmManager.OnAlarmListener.class);
+ final ArgumentCaptor<AlarmManager.OnAlarmListener> motionRegistrationAlarmListener =
+ ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class);
doNothing().when(mAlarmManager).set(anyInt(), anyLong(), eq("DeviceIdleController.motion"),
- alarmListener.capture(), any());
+ motionAlarmListener.capture(), any());
+ doNothing().when(mAlarmManager).set(anyInt(), anyLong(),
+ eq("DeviceIdleController.motion_registration"),
+ motionRegistrationAlarmListener.capture(), any());
StationaryListenerForTest stationaryListener = new StationaryListenerForTest();
+ spyOn(stationaryListener);
+ InOrder inOrder = inOrder(stationaryListener);
stationaryListener.motionExpected = true;
mDeviceIdleController.registerStationaryListener(stationaryListener);
+ inOrder.verify(stationaryListener, timeout(1000L).times(1))
+ .onDeviceStationaryChanged(eq(false));
assertFalse(stationaryListener.isStationary);
// Go to IDLE_MAINTENANCE
@@ -1814,13 +1840,17 @@ public class DeviceIdleControllerTest {
mDeviceIdleController.stepIdleStateLocked("testing");
// Now enough time has passed.
- mInjector.nowElapsed += mConstants.MOTION_INACTIVE_TIMEOUT / 2;
+ mInjector.nowElapsed += mConstants.MOTION_INACTIVE_TIMEOUT;
stationaryListener.motionExpected = false;
- alarmListener.getValue().onAlarm();
+ motionAlarmListener.getValue().onAlarm();
+ inOrder.verify(stationaryListener, timeout(1000L).times(1))
+ .onDeviceStationaryChanged(eq(true));
assertTrue(stationaryListener.isStationary);
stationaryListener.motionExpected = true;
- mDeviceIdleController.mMotionListener.onSensorChanged(null);
+ mDeviceIdleController.mMotionListener.onTrigger(null);
+ inOrder.verify(stationaryListener, timeout(1000L).times(1))
+ .onDeviceStationaryChanged(eq(false));
assertFalse(stationaryListener.isStationary);
// Since we're in quick doze, the device shouldn't stop idling.
@@ -1829,18 +1859,116 @@ public class DeviceIdleControllerTest {
// Go to IDLE_MAINTENANCE
mDeviceIdleController.stepIdleStateLocked("testing");
+ motionRegistrationAlarmListener.getValue().onAlarm();
mInjector.nowElapsed += mConstants.MOTION_INACTIVE_TIMEOUT / 2;
// Back to IDLE
+ stationaryListener.motionExpected = false;
mDeviceIdleController.stepIdleStateLocked("testing");
+ verify(mSensorManager,
+ timeout(mConstants.MOTION_INACTIVE_TIMEOUT).times(2))
+ .requestTriggerSensor(eq(mDeviceIdleController.mMotionListener), eq(mMotionSensor));
// Now enough time has passed.
- mInjector.nowElapsed += mConstants.MOTION_INACTIVE_TIMEOUT / 2;
- stationaryListener.motionExpected = false;
- alarmListener.getValue().onAlarm();
+ mInjector.nowElapsed += mConstants.MOTION_INACTIVE_TIMEOUT;
+ motionAlarmListener.getValue().onAlarm();
+ inOrder.verify(stationaryListener,
+ timeout(mConstants.MOTION_INACTIVE_TIMEOUT).times(1))
+ .onDeviceStationaryChanged(eq(true));
assertTrue(stationaryListener.isStationary);
}
+ @Test
+ public void testStationaryDetection_QuickDozeOn_OneShot() {
+ // Short timeout for testing.
+ mConstants.MOTION_INACTIVE_TIMEOUT = 6000L;
+ doReturn(Sensor.REPORTING_MODE_ONE_SHOT).when(mMotionSensor).getReportingMode();
+ setAlarmSoon(false);
+ enterDeepState(STATE_QUICK_DOZE_DELAY);
+ mDeviceIdleController.stepIdleStateLocked("testing");
+ verifyStateConditions(STATE_IDLE);
+ // Quick doze progression through states, so time should have increased appropriately.
+ mInjector.nowElapsed += mConstants.QUICK_DOZE_DELAY_TIMEOUT;
+ final ArgumentCaptor<AlarmManager.OnAlarmListener> alarmListener = ArgumentCaptor
+ .forClass(AlarmManager.OnAlarmListener.class);
+ doNothing().when(mAlarmManager)
+ .set(anyInt(), anyLong(), eq("DeviceIdleController.motion"), any(), any());
+ doNothing().when(mAlarmManager).set(anyInt(), anyLong(),
+ eq("DeviceIdleController.motion_registration"),
+ alarmListener.capture(), any());
+ ArgumentCaptor<TriggerEventListener> listenerCaptor =
+ ArgumentCaptor.forClass(TriggerEventListener.class);
+
+ StationaryListenerForTest stationaryListener = new StationaryListenerForTest();
+ spyOn(stationaryListener);
+ InOrder inOrder = inOrder(stationaryListener, mSensorManager);
+
+ stationaryListener.motionExpected = true;
+ mDeviceIdleController.registerStationaryListener(stationaryListener);
+ inOrder.verify(stationaryListener, timeout(1000L).times(1))
+ .onDeviceStationaryChanged(eq(false));
+ assertFalse(stationaryListener.isStationary);
+ inOrder.verify(mSensorManager)
+ .requestTriggerSensor(listenerCaptor.capture(), eq(mMotionSensor));
+ final TriggerEventListener listener = listenerCaptor.getValue();
+
+ // Trigger motion
+ listener.onTrigger(mock(TriggerEvent.class));
+ inOrder.verify(stationaryListener, timeout(1000L).times(1))
+ .onDeviceStationaryChanged(eq(false));
+
+ // Make sure the listener is re-registered.
+ alarmListener.getValue().onAlarm();
+ inOrder.verify(mSensorManager).requestTriggerSensor(eq(listener), eq(mMotionSensor));
+ }
+
+ @Test
+ public void testStationaryDetection_QuickDozeOn_MultiShot() {
+ // Short timeout for testing.
+ mConstants.MOTION_INACTIVE_TIMEOUT = 6000L;
+ doReturn(Sensor.REPORTING_MODE_CONTINUOUS).when(mMotionSensor).getReportingMode();
+ setAlarmSoon(false);
+ enterDeepState(STATE_QUICK_DOZE_DELAY);
+ mDeviceIdleController.stepIdleStateLocked("testing");
+ verifyStateConditions(STATE_IDLE);
+ // Quick doze progression through states, so time should have increased appropriately.
+ mInjector.nowElapsed += mConstants.QUICK_DOZE_DELAY_TIMEOUT;
+ final ArgumentCaptor<AlarmManager.OnAlarmListener> alarmListener = ArgumentCaptor
+ .forClass(AlarmManager.OnAlarmListener.class);
+ doNothing().when(mAlarmManager)
+ .set(anyInt(), anyLong(), eq("DeviceIdleController.motion"), any(), any());
+ doNothing().when(mAlarmManager).set(anyInt(), anyLong(),
+ eq("DeviceIdleController.motion_registration"),
+ alarmListener.capture(), any());
+ ArgumentCaptor<SensorEventListener> listenerCaptor =
+ ArgumentCaptor.forClass(SensorEventListener.class);
+
+ StationaryListenerForTest stationaryListener = new StationaryListenerForTest();
+ spyOn(stationaryListener);
+ InOrder inOrder = inOrder(stationaryListener, mSensorManager);
+
+ stationaryListener.motionExpected = true;
+ mDeviceIdleController.registerStationaryListener(stationaryListener);
+ inOrder.verify(stationaryListener, timeout(1000L).times(1))
+ .onDeviceStationaryChanged(eq(false));
+ assertFalse(stationaryListener.isStationary);
+ inOrder.verify(mSensorManager)
+ .registerListener(listenerCaptor.capture(), eq(mMotionSensor),
+ eq(SensorManager.SENSOR_DELAY_NORMAL));
+ final SensorEventListener listener = listenerCaptor.getValue();
+
+ // Trigger motion
+ listener.onSensorChanged(mock(SensorEvent.class));
+ inOrder.verify(stationaryListener, timeout(1000L).times(1))
+ .onDeviceStationaryChanged(eq(false));
+
+ // Make sure the listener is re-registered.
+ alarmListener.getValue().onAlarm();
+ inOrder.verify(mSensorManager)
+ .registerListener(eq(listener), eq(mMotionSensor),
+ eq(SensorManager.SENSOR_DELAY_NORMAL));
+ }
+
private void enterDeepState(int state) {
switch (state) {
case STATE_ACTIVE:
diff --git a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
index fa209a7a5f8e..529339e48546 100644
--- a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
@@ -20,6 +20,7 @@ import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_ERRORED;
import static android.app.AppOpsManager.MODE_FOREGROUND;
import static android.app.AppOpsManager.OP_COARSE_LOCATION;
+import static android.app.AppOpsManager.OP_FLAGS_ALL;
import static android.app.AppOpsManager.OP_READ_SMS;
import static android.app.AppOpsManager.OP_WIFI_SCAN;
import static android.app.AppOpsManager.OP_WRITE_SMS;
@@ -465,11 +466,11 @@ public class AppOpsServiceTest {
assertWithMessage("Unexpected mode").that(mode).isEqualTo(opEntry.getMode());
if (minMillis > 0) {
assertWithMessage("Unexpected timestamp")
- .that(opEntry.getTime()).isAtLeast(minMillis);
+ .that(opEntry.getLastAccessTime(OP_FLAGS_ALL)).isAtLeast(minMillis);
}
if (minRejectMillis > 0) {
- assertWithMessage("Unexpected rejection timestamp")
- .that(opEntry.getRejectTime()).isAtLeast(minRejectMillis);
+ assertWithMessage("Unexpected rejection timestamp").that(
+ opEntry.getLastRejectTime(OP_FLAGS_ALL)).isAtLeast(minRejectMillis);
}
}
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
index 05b655af65ed..9e1ddb1f8a80 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
@@ -217,9 +217,8 @@ public class LocalDisplayAdapterTest {
doReturn(new int[]{
0
}).when(() -> SurfaceControl.getDisplayColorModes(config.displayToken));
- doReturn(new int[]{
- 0
- }).when(() -> SurfaceControl.getAllowedDisplayConfigs(config.displayToken));
+ doReturn(new SurfaceControl.DesiredDisplayConfigSpecs(0, 60.f, 60.f))
+ .when(() -> SurfaceControl.getDesiredDisplayConfigSpecs(config.displayToken));
}
private void updateAvailableDisplays() {
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index 3910993d9c27..015e574f2309 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -28,6 +28,7 @@ android_test {
"services.net",
"services.usage",
"guava",
+ "androidx.test.core",
"androidx.test.runner",
"androidx.test.rules",
"mockito-target-minus-junit4",
diff --git a/services/tests/servicestests/assets/AppIntegrityManagerServiceImplTest/test.apk b/services/tests/servicestests/assets/AppIntegrityManagerServiceImplTest/test.apk
new file mode 100644
index 000000000000..6345c986efc2
--- /dev/null
+++ b/services/tests/servicestests/assets/AppIntegrityManagerServiceImplTest/test.apk
Binary files differ
diff --git a/services/tests/servicestests/src/com/android/server/CountryDetectorServiceTest.java b/services/tests/servicestests/src/com/android/server/CountryDetectorServiceTest.java
index 192c50c7dc19..e9c5ce7127de 100644
--- a/services/tests/servicestests/src/com/android/server/CountryDetectorServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/CountryDetectorServiceTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -11,28 +11,48 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
package com.android.server;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.Mockito.doAnswer;
+
import android.content.Context;
import android.location.Country;
import android.location.CountryListener;
import android.location.ICountryListener;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
import android.os.RemoteException;
-import android.test.AndroidTestCase;
-public class CountryDetectorServiceTest extends AndroidTestCase {
- private class CountryListenerTester extends ICountryListener.Stub {
+import androidx.test.core.app.ApplicationProvider;
+
+import com.google.common.truth.Expect;
+
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Spy;
+import org.mockito.junit.MockitoJUnitRunner;
+
+@RunWith(MockitoJUnitRunner.class)
+public class CountryDetectorServiceTest {
+
+ private static class CountryListenerTester extends ICountryListener.Stub {
private Country mCountry;
@Override
- public void onCountryDetected(Country country) throws RemoteException {
+ public void onCountryDetected(Country country) {
mCountry = country;
}
- public Country getCountry() {
+ Country getCountry() {
return mCountry;
}
@@ -41,12 +61,11 @@ public class CountryDetectorServiceTest extends AndroidTestCase {
}
}
- private class CountryDetectorServiceTester extends CountryDetectorService {
-
+ private static class CountryDetectorServiceTester extends CountryDetectorService {
private CountryListener mListener;
- public CountryDetectorServiceTester(Context context) {
- super(context);
+ CountryDetectorServiceTester(Context context, Handler handler) {
+ super(context, handler);
}
@Override
@@ -59,51 +78,77 @@ public class CountryDetectorServiceTest extends AndroidTestCase {
mListener = listener;
}
- public boolean isListenerSet() {
+ boolean isListenerSet() {
return mListener != null;
}
}
- public void testAddRemoveListener() throws RemoteException {
- CountryDetectorServiceTester serviceTester = new CountryDetectorServiceTester(getContext());
- serviceTester.systemRunning();
- waitForSystemReady(serviceTester);
- CountryListenerTester listenerTester = new CountryListenerTester();
- serviceTester.addCountryListener(listenerTester);
- assertTrue(serviceTester.isListenerSet());
- serviceTester.removeCountryListener(listenerTester);
- assertFalse(serviceTester.isListenerSet());
+ @Rule
+ public final Expect expect = Expect.create();
+ @Spy
+ private Context mContext = ApplicationProvider.getApplicationContext();
+ @Spy
+ private Handler mHandler = new Handler(Looper.myLooper());
+ private CountryDetectorServiceTester mCountryDetectorService;
+
+ @BeforeClass
+ public static void oneTimeInitialization() {
+ if (Looper.myLooper() == null) {
+ Looper.prepare();
+ }
}
- public void testNotifyListeners() throws RemoteException {
- CountryDetectorServiceTester serviceTester = new CountryDetectorServiceTester(getContext());
- CountryListenerTester listenerTesterA = new CountryListenerTester();
- CountryListenerTester listenerTesterB = new CountryListenerTester();
- Country country = new Country("US", Country.COUNTRY_SOURCE_NETWORK);
- serviceTester.systemRunning();
- waitForSystemReady(serviceTester);
- serviceTester.addCountryListener(listenerTesterA);
- serviceTester.addCountryListener(listenerTesterB);
- serviceTester.notifyReceivers(country);
- assertTrue(serviceTester.isListenerSet());
- assertTrue(listenerTesterA.isNotified());
- assertTrue(listenerTesterB.isNotified());
- serviceTester.removeCountryListener(listenerTesterA);
- serviceTester.removeCountryListener(listenerTesterB);
- assertFalse(serviceTester.isListenerSet());
+ @Before
+ public void setUp() {
+ mCountryDetectorService = new CountryDetectorServiceTester(mContext, mHandler);
+
+ // Immediately invoke run on the Runnable posted to the handler
+ doAnswer(invocation -> {
+ Message message = invocation.getArgument(0);
+ message.getCallback().run();
+ return true;
+ }).when(mHandler).sendMessageAtTime(any(Message.class), anyLong());
}
- private void waitForSystemReady(CountryDetectorService service) {
- int count = 5;
- while (count-- > 0) {
- try {
- Thread.sleep(500);
- } catch (Exception e) {
- }
- if (service.isSystemReady()) {
- return;
- }
- }
- throw new RuntimeException("Wait System Ready timeout");
+ @Test
+ public void countryListener_add_successful() throws RemoteException {
+ CountryListenerTester countryListener = new CountryListenerTester();
+
+ mCountryDetectorService.systemRunning();
+ expect.that(mCountryDetectorService.isListenerSet()).isFalse();
+ mCountryDetectorService.addCountryListener(countryListener);
+
+ expect.that(mCountryDetectorService.isListenerSet()).isTrue();
+ }
+
+ @Test
+ public void countryListener_remove_successful() throws RemoteException {
+ CountryListenerTester countryListener = new CountryListenerTester();
+
+ mCountryDetectorService.systemRunning();
+ mCountryDetectorService.addCountryListener(countryListener);
+ expect.that(mCountryDetectorService.isListenerSet()).isTrue();
+ mCountryDetectorService.removeCountryListener(countryListener);
+
+ expect.that(mCountryDetectorService.isListenerSet()).isFalse();
+ }
+
+ @Test
+ public void countryListener_notify_successful() throws RemoteException {
+ CountryListenerTester countryListenerA = new CountryListenerTester();
+ CountryListenerTester countryListenerB = new CountryListenerTester();
+ Country country = new Country("US", Country.COUNTRY_SOURCE_NETWORK);
+
+ mCountryDetectorService.systemRunning();
+ mCountryDetectorService.addCountryListener(countryListenerA);
+ mCountryDetectorService.addCountryListener(countryListenerB);
+ expect.that(countryListenerA.isNotified()).isFalse();
+ expect.that(countryListenerB.isNotified()).isFalse();
+ mCountryDetectorService.notifyReceivers(country);
+
+ expect.that(countryListenerA.isNotified()).isTrue();
+ expect.that(countryListenerB.isNotified()).isTrue();
+ expect.that(countryListenerA.getCountry().equalsIgnoreSource(country)).isTrue();
+ expect.that(countryListenerB.getCountry().equalsIgnoreSource(country)).isTrue();
}
}
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
index 49412bc0c559..2ce17a1d0cea 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
@@ -349,10 +349,21 @@ public class ActivityManagerServiceTest {
verifyUidRangesNoOverlap(range, range2);
verifyIsolatedUidAllocator(range2);
- // Free both, then try to allocate the maximum number of UID ranges
+ // Free both
allocator.freeUidRangeLocked(appInfo);
allocator.freeUidRangeLocked(appInfo2);
+ // Verify for a secondary user
+ ApplicationInfo appInfo3 = new ApplicationInfo();
+ appInfo3.processName = "com.android.test.app";
+ appInfo3.uid = 1010000;
+ final IsolatedUidRange range3 = allocator.getOrCreateIsolatedUidRangeLocked(
+ appInfo3.processName, appInfo3.uid);
+ validateAppZygoteIsolatedUidRange(range3);
+ verifyIsolatedUidAllocator(range3);
+
+ allocator.freeUidRangeLocked(appInfo3);
+ // Try to allocate the maximum number of UID ranges
int maxNumUidRanges = (Process.LAST_APP_ZYGOTE_ISOLATED_UID
- Process.FIRST_APP_ZYGOTE_ISOLATED_UID + 1) / Process.NUM_UIDS_PER_APP_ZYGOTE;
for (int i = 0; i < maxNumUidRanges; i++) {
diff --git a/services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java b/services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java
index 5c2ad94720f0..73a191dc78cc 100644
--- a/services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java
+++ b/services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java
@@ -57,6 +57,7 @@ public class AudioDeviceBrokerTest {
@Mock private AudioService mMockAudioService;
@Spy private AudioDeviceInventory mSpyDevInventory;
+ @Spy private AudioSystemAdapter mSpyAudioSystem;
private BluetoothDevice mFakeBtDevice;
@@ -65,7 +66,8 @@ public class AudioDeviceBrokerTest {
mContext = InstrumentationRegistry.getTargetContext();
mMockAudioService = mock(AudioService.class);
- mSpyDevInventory = spy(new AudioDeviceInventory());
+ mSpyAudioSystem = spy(AudioSystemAdapter.getAlwaysOkAdapter());
+ mSpyDevInventory = spy(new AudioDeviceInventory(mSpyAudioSystem));
mAudioDeviceBroker = new AudioDeviceBroker(mContext, mMockAudioService, mSpyDevInventory);
mSpyDevInventory.setDeviceBroker(mAudioDeviceBroker);
@@ -81,8 +83,9 @@ public class AudioDeviceBrokerTest {
public void testSetUpAndTearDown() { }
/**
- * Verify call to postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent() for connection
- * calls into AudioDeviceInventory with the right params
+ * postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent() for connection:
+ * - verify it calls into AudioDeviceInventory with the right params
+ * - verify it calls into AudioSystem and stays connected (no 2nd call to disconnect)
* @throws Exception
*/
@Test
@@ -92,7 +95,7 @@ public class AudioDeviceBrokerTest {
mAudioDeviceBroker.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(mFakeBtDevice,
BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP, true, 1);
- Thread.sleep(MAX_MESSAGE_HANDLING_DELAY_MS);
+ Thread.sleep(2 * MAX_MESSAGE_HANDLING_DELAY_MS);
verify(mSpyDevInventory, times(1)).setBluetoothA2dpDeviceConnectionState(
any(BluetoothDevice.class),
ArgumentMatchers.eq(BluetoothProfile.STATE_CONNECTED) /*state*/,
@@ -100,6 +103,14 @@ public class AudioDeviceBrokerTest {
ArgumentMatchers.eq(true) /*suppressNoisyIntent*/, anyInt() /*musicDevice*/,
ArgumentMatchers.eq(1) /*a2dpVolume*/
);
+
+ final String expectedName = mFakeBtDevice.getName() == null ? "" : mFakeBtDevice.getName();
+ verify(mSpyAudioSystem, times(1)).setDeviceConnectionState(
+ ArgumentMatchers.eq(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP),
+ ArgumentMatchers.eq(AudioSystem.DEVICE_STATE_AVAILABLE),
+ ArgumentMatchers.eq(mFakeBtDevice.getAddress()),
+ ArgumentMatchers.eq(expectedName),
+ anyInt() /*codec*/);
}
/**
diff --git a/services/tests/servicestests/src/com/android/server/backup/BackupManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/backup/BackupManagerServiceTest.java
index 68b413ff976c..2326dfda7e12 100644
--- a/services/tests/servicestests/src/com/android/server/backup/BackupManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/BackupManagerServiceTest.java
@@ -34,9 +34,6 @@ import static org.mockito.Mockito.when;
import android.Manifest;
import android.annotation.UserIdInt;
import android.app.backup.BackupManager;
-import android.app.backup.IBackupManagerMonitor;
-import android.app.backup.IBackupObserver;
-import android.app.backup.IFullBackupRestoreObserver;
import android.app.backup.ISelectBackupTransportCallback;
import android.app.job.JobScheduler;
import android.content.ComponentName;
@@ -44,8 +41,6 @@ import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.os.ConditionVariable;
-import android.os.IBinder;
-import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -61,6 +56,7 @@ import com.android.server.backup.utils.RandomAccessFileUtils;
import org.junit.After;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -77,23 +73,8 @@ import java.util.concurrent.TimeUnit;
@Presubmit
@RunWith(AndroidJUnit4.class)
public class BackupManagerServiceTest {
- private static final String PACKAGE_NAME = "some.package.name";
- private static final String TRANSPORT_NAME = "some.transport.name";
- private static final String CURRENT_PASSWORD = "current_password";
- private static final String NEW_PASSWORD = "new_password";
- private static final String ENCRYPTION_PASSWORD = "encryption_password";
- private static final CharSequence DATA_MANAGEMENT_LABEL = "data_management_label";
- private static final String DESTINATION_STRING = "destination_string";
- private static final String[] PACKAGE_NAMES =
- new String[]{"some.package.name._1", "some.package.name._2"};
- private static final String[] TRANSPORTS =
- new String[]{"some.transport.name._1", "some.transport.name._2"};
private static final ComponentName TRANSPORT_COMPONENT_NAME = new ComponentName("package",
"class");
- private static final ComponentName[] TRANSPORT_COMPONENTS = new ComponentName[]{
- new ComponentName("package1", "class1"),
- new ComponentName("package2", "class2")
- };
private static final int NON_USER_SYSTEM = UserHandle.USER_SYSTEM + 1;
private static final int UNSTARTED_NON_USER_SYSTEM = UserHandle.USER_SYSTEM + 2;
@@ -104,16 +85,6 @@ public class BackupManagerServiceTest {
@Mock
private Context mContextMock;
@Mock
- private IBinder mAgentMock;
- @Mock
- private ParcelFileDescriptor mParcelFileDescriptorMock;
- @Mock
- private IFullBackupRestoreObserver mFullBackupRestoreObserverMock;
- @Mock
- private IBackupObserver mBackupObserverMock;
- @Mock
- private IBackupManagerMonitor mBackupManagerMonitorMock;
- @Mock
private PrintWriter mPrintWriterMock;
@Mock
private UserManager mUserManagerMock;
@@ -543,6 +514,8 @@ public class BackupManagerServiceTest {
verifyNoMoreInteractions(mUserBackupManagerService);
}
+ @Test
+ @Ignore("b/147012496")
public void testGetUserForAncestralSerialNumber() {
BackupManagerServiceTestable.sBackupDisabled = false;
BackupManagerService backupManagerService =
@@ -554,6 +527,7 @@ public class BackupManagerServiceTest {
assertThat(user).isEqualTo(UserHandle.of(1));
}
+ @Test
public void testGetUserForAncestralSerialNumber_whenDisabled() {
BackupManagerServiceTestable.sBackupDisabled = true;
BackupManagerService backupManagerService =
diff --git a/services/tests/servicestests/src/com/android/server/backup/DataChangedJournalTest.java b/services/tests/servicestests/src/com/android/server/backup/DataChangedJournalTest.java
index 4e7fe44b2b76..0e918db321e3 100644
--- a/services/tests/servicestests/src/com/android/server/backup/DataChangedJournalTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/DataChangedJournalTest.java
@@ -136,6 +136,7 @@ public class DataChangedJournalTest {
assertThat(mJournal.toString()).isEqualTo(mFile.toString());
}
+ @Test
public void listJournals_invalidJournalFile_returnsEmptyList() throws Exception {
when(invalidFile.listFiles()).thenReturn(null);
diff --git a/services/tests/servicestests/src/com/android/server/backup/utils/FileUtilsTest.java b/services/tests/servicestests/src/com/android/server/backup/utils/FileUtilsTest.java
index eaa9c4520979..d54aa3b1c2f6 100644
--- a/services/tests/servicestests/src/com/android/server/backup/utils/FileUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/utils/FileUtilsTest.java
@@ -27,7 +27,6 @@ import com.google.common.io.Files;
import org.junit.AfterClass;
import org.junit.Before;
-import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -41,11 +40,6 @@ public class FileUtilsTest {
private static File sTemporaryDir;
private File mTemporaryFile;
- @BeforeClass
- public static void setUpClass() {
- sTemporaryDir = Files.createTempDir();
- }
-
@AfterClass
public static void tearDownClass() {
if (sTemporaryDir != null) {
@@ -55,17 +49,21 @@ public class FileUtilsTest {
@Before
public void setUp() throws Exception {
+ if (sTemporaryDir != null) {
+ sTemporaryDir.delete();
+ }
+ sTemporaryDir = Files.createTempDir();
mTemporaryFile = new File(sTemporaryDir, "fileutilstest.txt");
}
/** Test that if file does not exist, {@link FileUtils#createNewFile()} creates the file. */
@Test
public void testEnsureFileExists_fileDoesNotAlreadyExist_getsCreated() {
- assertThat(!mTemporaryFile.exists());
+ assertThat(mTemporaryFile.exists()).isFalse();
FileUtils.createNewFile(mTemporaryFile);
- assertThat(mTemporaryFile.exists());
+ assertThat(mTemporaryFile.exists()).isTrue();
}
/** Test that if file does exist, {@link FileUtils#createNewFile()} does not error out. */
@@ -75,6 +73,6 @@ public class FileUtilsTest {
FileUtils.createNewFile(mTemporaryFile);
- assertThat(mTemporaryFile.exists());
+ assertThat(mTemporaryFile.exists()).isTrue();
}
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
index 211fc4db6211..f96d9961d364 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
@@ -36,6 +36,7 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.IActivityManager;
+import android.app.admin.DevicePolicyManager;
import android.app.trust.ITrustManager;
import android.content.ContentResolver;
import android.content.Context;
@@ -104,6 +105,8 @@ public class BiometricServiceTest {
IBiometricAuthenticator mFaceAuthenticator;
@Mock
ITrustManager mTrustManager;
+ @Mock
+ DevicePolicyManager mDevicePolicyManager;
@Before
public void setUp() {
@@ -111,6 +114,8 @@ public class BiometricServiceTest {
when(mContext.getContentResolver()).thenReturn(mContentResolver);
when(mContext.getResources()).thenReturn(mResources);
+ when(mContext.getSystemService(Context.DEVICE_POLICY_SERVICE))
+ .thenReturn(mDevicePolicyManager);
when(mInjector.getActivityManagerService()).thenReturn(mock(IActivityManager.class));
when(mInjector.getStatusBarService()).thenReturn(mock(IStatusBarService.class));
@@ -1198,10 +1203,71 @@ public class BiometricServiceTest {
for (String s : mInjector.getConfiguration(null)) {
SensorConfig config = new SensorConfig(s);
mBiometricService.mImpl.registerAuthenticator(config.mId, config.mModality,
- config.mStrength, mFingerprintAuthenticator);
+ config.mStrength, mFingerprintAuthenticator);
}
}
+ @Test
+ public void testWorkAuthentication_fingerprintWorksIfNotDisabledByDevicePolicyManager()
+ throws Exception {
+ setupAuthForOnly(BiometricAuthenticator.TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG);
+ when(mDevicePolicyManager
+ .getKeyguardDisabledFeatures(any() /* admin */, anyInt() /* userHandle */))
+ .thenReturn(~DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT);
+ invokeAuthenticateForWorkApp(mBiometricService.mImpl, mReceiver1);
+ waitForIdle();
+ assertEquals(mBiometricService.mPendingAuthSession.mState,
+ BiometricService.STATE_AUTH_CALLED);
+ startPendingAuthSession(mBiometricService);
+ waitForIdle();
+ assertEquals(mBiometricService.mCurrentAuthSession.mState,
+ BiometricService.STATE_AUTH_STARTED);
+ }
+
+ @Test
+ public void testWorkAuthentication_faceWorksIfNotDisabledByDevicePolicyManager()
+ throws Exception {
+ setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG);
+ when(mDevicePolicyManager
+ .getKeyguardDisabledFeatures(any() /* admin*/, anyInt() /* userHandle */))
+ .thenReturn(~DevicePolicyManager.KEYGUARD_DISABLE_FACE);
+ invokeAuthenticateForWorkApp(mBiometricService.mImpl, mReceiver1);
+ waitForIdle();
+ assertEquals(mBiometricService.mPendingAuthSession.mState,
+ BiometricService.STATE_AUTH_CALLED);
+ startPendingAuthSession(mBiometricService);
+ waitForIdle();
+ assertEquals(mBiometricService.mCurrentAuthSession.mState,
+ BiometricService.STATE_AUTH_STARTED);
+ }
+
+ @Test
+ public void testWorkAuthentication_fingerprintFailsIfDisabledByDevicePolicyManager()
+ throws Exception {
+ setupAuthForOnly(BiometricAuthenticator.TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG);
+ when(mDevicePolicyManager
+ .getKeyguardDisabledFeatures(any() /* admin */, anyInt() /* userHandle */))
+ .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT);
+ invokeAuthenticateForWorkApp(mBiometricService.mImpl, mReceiver1);
+ waitForIdle();
+ assertNotNull(mBiometricService.mCurrentAuthSession);
+ assertEquals(mBiometricService.mCurrentAuthSession.mState,
+ BiometricService.STATE_SHOWING_DEVICE_CREDENTIAL);
+ }
+
+ @Test
+ public void testWorkAuthentication_faceFailsIfDisabledByDevicePolicyManager() throws Exception {
+ setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG);
+ when(mDevicePolicyManager
+ .getKeyguardDisabledFeatures(any() /* admin */, anyInt() /* userHandle */))
+ .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FACE);
+ invokeAuthenticateForWorkApp(mBiometricService.mImpl, mReceiver1);
+ waitForIdle();
+ assertNotNull(mBiometricService.mCurrentAuthSession);
+ assertEquals(mBiometricService.mCurrentAuthSession.mState,
+ BiometricService.STATE_SHOWING_DEVICE_CREDENTIAL);
+ }
+
// Helper methods
private int invokeCanAuthenticate(BiometricService service, int authenticators)
@@ -1311,6 +1377,21 @@ public class BiometricServiceTest {
createTestBiometricPromptBundle(requireConfirmation, authenticators));
}
+ private static void invokeAuthenticateForWorkApp(IBiometricService.Stub service,
+ IBiometricServiceReceiver receiver) throws Exception {
+ final Bundle bundle = new Bundle();
+ bundle.putBoolean(BiometricPrompt.EXTRA_DISALLOW_BIOMETRICS_IF_POLICY_EXISTS, true);
+ bundle.putBoolean(BiometricPrompt.KEY_REQUIRE_CONFIRMATION, true);
+ bundle.putBoolean(BiometricPrompt.KEY_ALLOW_DEVICE_CREDENTIAL, true);
+ service.authenticate(
+ new Binder() /* token */,
+ 0 /* sessionId */,
+ 0 /* userId */,
+ receiver,
+ TEST_PACKAGE_NAME /* packageName */,
+ bundle);
+ }
+
private static Bundle createTestBiometricPromptBundle(
boolean requireConfirmation,
Integer authenticators) {
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 f97c887c2894..4fcfa32c3c3b 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -100,7 +100,6 @@ import com.android.internal.widget.LockscreenCredential;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.devicepolicy.DevicePolicyManagerService.RestrictionsListener;
-import com.android.server.pm.UserRestrictionsUtils;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
@@ -1163,7 +1162,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions(
eq(UserHandle.USER_SYSTEM),
- eq(null),
+ MockUtils.checkUserRestrictions(),
eq(UserManagerInternal.OWNER_TYPE_DEVICE_OWNER));
verify(getServices().usageStatsManagerInternal).setActiveAdminApps(
@@ -1719,28 +1718,6 @@ public class DevicePolicyManagerTest extends DpmTestBase {
assertTrue(dpm.setDeviceOwner(admin1, "owner-name",
UserHandle.USER_SYSTEM));
- // Check that the user restrictions that are enabled by default are set. Then unset them.
- final String[] defaultRestrictions = UserRestrictionsUtils
- .getDefaultEnabledForDeviceOwner().toArray(new String[0]);
- DpmTestUtils.assertRestrictions(
- DpmTestUtils.newRestrictions(defaultRestrictions),
- dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()
- );
- DpmTestUtils.assertRestrictions(
- DpmTestUtils.newRestrictions(defaultRestrictions),
- dpm.getUserRestrictions(admin1)
- );
- verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions(
- eq(UserHandle.USER_SYSTEM),
- MockUtils.checkUserRestrictions(defaultRestrictions),
- eq(UserManagerInternal.OWNER_TYPE_DEVICE_OWNER)
- );
- reset(getServices().userManagerInternal);
-
- for (String restriction : defaultRestrictions) {
- dpm.clearUserRestriction(admin1, restriction);
- }
-
assertNoDeviceOwnerRestrictions();
reset(getServices().userManagerInternal);
@@ -2004,7 +1981,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
reset(getServices().userManagerInternal);
}
- public void testDefaultEnabledUserRestrictions() throws Exception {
+ public void testNoDefaultEnabledUserRestrictions() throws Exception {
mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
mContext.callerPermissions.add(permission.MANAGE_USERS);
mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
@@ -2022,29 +1999,6 @@ public class DevicePolicyManagerTest extends DpmTestBase {
assertTrue(dpm.setDeviceOwner(admin1, "owner-name",
UserHandle.USER_SYSTEM));
- // Check that the user restrictions that are enabled by default are set. Then unset them.
- String[] defaultRestrictions = UserRestrictionsUtils
- .getDefaultEnabledForDeviceOwner().toArray(new String[0]);
- assertTrue(defaultRestrictions.length > 0);
- DpmTestUtils.assertRestrictions(
- DpmTestUtils.newRestrictions(defaultRestrictions),
- dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()
- );
- DpmTestUtils.assertRestrictions(
- DpmTestUtils.newRestrictions(defaultRestrictions),
- dpm.getUserRestrictions(admin1)
- );
- verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions(
- eq(UserHandle.USER_SYSTEM),
- MockUtils.checkUserRestrictions(defaultRestrictions),
- eq(UserManagerInternal.OWNER_TYPE_DEVICE_OWNER)
- );
- reset(getServices().userManagerInternal);
-
- for (String restriction : defaultRestrictions) {
- dpm.clearUserRestriction(admin1, restriction);
- }
-
assertNoDeviceOwnerRestrictions();
// Initialize DPMS again and check that the user restriction wasn't enabled again.
@@ -2054,47 +2008,6 @@ public class DevicePolicyManagerTest extends DpmTestBase {
assertNotNull(dpms.getDeviceOwnerAdminLocked());
assertNoDeviceOwnerRestrictions();
-
- // Add a new restriction to the default set, initialize DPMS, and check that the restriction
- // is set as it wasn't enabled during setDeviceOwner.
- final String newDefaultEnabledRestriction = UserManager.DISALLOW_REMOVE_MANAGED_PROFILE;
- assertFalse(UserRestrictionsUtils
- .getDefaultEnabledForDeviceOwner().contains(newDefaultEnabledRestriction));
- UserRestrictionsUtils
- .getDefaultEnabledForDeviceOwner().add(newDefaultEnabledRestriction);
- try {
- reset(getServices().userManagerInternal);
- initializeDpms();
- assertTrue(dpm.isDeviceOwnerApp(admin1.getPackageName()));
- assertNotNull(dpms.getDeviceOwnerAdminLocked());
-
- DpmTestUtils.assertRestrictions(
- DpmTestUtils.newRestrictions(newDefaultEnabledRestriction),
- dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()
- );
- DpmTestUtils.assertRestrictions(
- DpmTestUtils.newRestrictions(newDefaultEnabledRestriction),
- dpm.getUserRestrictions(admin1)
- );
- verify(getServices().userManagerInternal, atLeast(1)).setDevicePolicyUserRestrictions(
- eq(UserHandle.USER_SYSTEM),
- MockUtils.checkUserRestrictions(newDefaultEnabledRestriction),
- eq(UserManagerInternal.OWNER_TYPE_DEVICE_OWNER)
- );
- reset(getServices().userManagerInternal);
-
- // Remove the restriction.
- dpm.clearUserRestriction(admin1, newDefaultEnabledRestriction);
-
- // Initialize DPMS again. The restriction shouldn't be enabled for a second time.
- initializeDpms();
- assertTrue(dpm.isDeviceOwnerApp(admin1.getPackageName()));
- assertNotNull(dpms.getDeviceOwnerAdminLocked());
- assertNoDeviceOwnerRestrictions();
- } finally {
- UserRestrictionsUtils
- .getDefaultEnabledForDeviceOwner().remove(newDefaultEnabledRestriction);
- }
}
private void assertNoDeviceOwnerRestrictions() {
diff --git a/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java b/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
index f6c4d3aa5f5f..ca00116d7ead 100644
--- a/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
@@ -53,7 +53,6 @@ public class AutomaticBrightnessControllerTest {
private static final int INITIAL_LIGHT_SENSOR_RATE = 20;
private static final int BRIGHTENING_LIGHT_DEBOUNCE_CONFIG = 0;
private static final int DARKENING_LIGHT_DEBOUNCE_CONFIG = 0;
- private static final int SHORT_TERM_MODEL_TIMEOUT = 0;
private static final float DOZE_SCALE_FACTOR = 0.0f;
private static final boolean RESET_AMBIENT_LUX_AFTER_WARMUP_CONFIG = false;
@@ -86,7 +85,7 @@ public class AutomaticBrightnessControllerTest {
BRIGHTNESS_MAX, DOZE_SCALE_FACTOR, LIGHT_SENSOR_RATE, INITIAL_LIGHT_SENSOR_RATE,
BRIGHTENING_LIGHT_DEBOUNCE_CONFIG, DARKENING_LIGHT_DEBOUNCE_CONFIG,
RESET_AMBIENT_LUX_AFTER_WARMUP_CONFIG, mAmbientBrightnessThresholds,
- mScreenBrightnessThresholds, SHORT_TERM_MODEL_TIMEOUT, mPackageManager);
+ mScreenBrightnessThresholds, mPackageManager);
controller.setLoggingEnabled(true);
// Configure the brightness controller and grab an instance of the sensor listener,
@@ -189,4 +188,27 @@ public class AutomaticBrightnessControllerTest {
listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, (int) lux2));
assertEquals(255, controller.getAutomaticScreenBrightness());
}
+
+ @Test
+ public void testUserAddUserDataPoint() throws Exception {
+ Sensor lightSensor = TestUtils.createSensor(Sensor.TYPE_LIGHT, "Light Sensor");
+ AutomaticBrightnessController controller = setupController(lightSensor);
+
+ ArgumentCaptor<SensorEventListener> listenerCaptor =
+ ArgumentCaptor.forClass(SensorEventListener.class);
+ verify(mSensorManager).registerListener(listenerCaptor.capture(), eq(lightSensor),
+ eq(INITIAL_LIGHT_SENSOR_RATE * 1000), any(Handler.class));
+ SensorEventListener listener = listenerCaptor.getValue();
+
+ // Sensor reads 1000 lux,
+ listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 1000));
+
+ // User sets brightness to 100
+ controller.configure(true /* enable */, null /* configuration */,
+ 100 /* brightness */, true /* userChangedBrightness */, 0 /* adjustment */,
+ false /* userChanged */, DisplayPowerRequest.POLICY_BRIGHT);
+
+ // There should be a user data point added to the mapper.
+ verify(mBrightnessMappingStrategy).addUserDataPoint(1000f, 100);
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
index 269f9180d8a6..ebca240819e8 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
@@ -78,10 +78,9 @@ public class DisplayModeDirectorTest {
int displayId = 0;
// With no votes present, DisplayModeDirector should allow any refresh rate.
- assertEquals(new DisplayModeDirector.DesiredDisplayConfigSpecs(/*defaultModeId=*/60,
- new DisplayModeDirector.RefreshRateRange(0f, Float.POSITIVE_INFINITY),
- intRange(60, 90)),
- createDisplayModeDirectorWithDisplayFpsRange(60, 90).getDesiredDisplayConfigSpecs(
+ assertEquals(new DisplayModeDirector.DesiredDisplayModeSpecs(/*defaultModeId=*/60,
+ new DisplayModeDirector.RefreshRateRange(0f, Float.POSITIVE_INFINITY)),
+ createDisplayModeDirectorWithDisplayFpsRange(60, 90).getDesiredDisplayModeSpecs(
displayId));
int numPriorities =
@@ -105,11 +104,10 @@ public class DisplayModeDirectorTest {
priority, DisplayModeDirector.Vote.forRefreshRates(minFps + i, maxFps - i));
director.injectVotesByDisplay(votesByDisplay);
assertEquals(
- new DisplayModeDirector.DesiredDisplayConfigSpecs(
+ new DisplayModeDirector.DesiredDisplayModeSpecs(
/*defaultModeId=*/minFps + i,
- new DisplayModeDirector.RefreshRateRange(minFps + i, maxFps - i),
- intRange(minFps + i, maxFps - i)),
- director.getDesiredDisplayConfigSpecs(displayId));
+ new DisplayModeDirector.RefreshRateRange(minFps + i, maxFps - i)),
+ director.getDesiredDisplayModeSpecs(displayId));
}
}
@@ -128,10 +126,9 @@ public class DisplayModeDirectorTest {
votes.put(DisplayModeDirector.Vote.MIN_PRIORITY,
DisplayModeDirector.Vote.forRefreshRates(70, 80));
director.injectVotesByDisplay(votesByDisplay);
- assertEquals(
- new DisplayModeDirector.DesiredDisplayConfigSpecs(/*defaultModeId=*/70,
- new DisplayModeDirector.RefreshRateRange(70, 80), intRange(70, 80)),
- director.getDesiredDisplayConfigSpecs(displayId));
+ assertEquals(new DisplayModeDirector.DesiredDisplayModeSpecs(/*defaultModeId=*/70,
+ new DisplayModeDirector.RefreshRateRange(70, 80)),
+ director.getDesiredDisplayModeSpecs(displayId));
}
}
}
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java
index 0a1899be8c1f..50ed975263e0 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java
@@ -534,6 +534,7 @@ public class HdmiCecLocalDeviceAudioSystemTest {
assertThat(mNativeWrapper.getOnlyResultMessage()).isEqualTo(expectedMessage);
}
+ @Test
public void handleSystemAudioModeRequest_fromNonTV_tVNotSupport() {
HdmiCecMessage message =
HdmiCecMessageBuilder.buildSystemAudioModeRequest(
diff --git a/services/tests/servicestests/src/com/android/server/input/ConfigurationProcessorTest.java b/services/tests/servicestests/src/com/android/server/input/ConfigurationProcessorTest.java
index 636aa375a84c..2bd4a3a397b1 100644
--- a/services/tests/servicestests/src/com/android/server/input/ConfigurationProcessorTest.java
+++ b/services/tests/servicestests/src/com/android/server/input/ConfigurationProcessorTest.java
@@ -18,11 +18,9 @@ package com.android.server.input;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import android.content.Context;
-import android.util.Pair;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
@@ -32,7 +30,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.InputStream;
-import java.util.List;
+import java.util.Map;
/**
* Build/Install/Run:
@@ -52,7 +50,7 @@ public class ConfigurationProcessorTest {
public void testGetInputPortAssociations() {
final int res = com.android.frameworks.servicestests.R.raw.input_port_associations;
InputStream xml = mContext.getResources().openRawResource(res);
- List<Pair<String, String>> associations = null;
+ Map<String, Integer> associations = null;
try {
associations = ConfigurationProcessor.processInputPortAssociations(xml);
} catch (Exception e) {
@@ -60,8 +58,8 @@ public class ConfigurationProcessorTest {
}
assertNotNull(associations);
assertEquals(2, associations.size());
- assertTrue(associations.contains(Pair.create("USB1", "0")));
- assertTrue(associations.contains(Pair.create("USB2", "1")));
+ assertEquals(0, associations.get("USB1").intValue());
+ assertEquals(1, associations.get("USB2").intValue());
}
@Test
@@ -69,7 +67,7 @@ public class ConfigurationProcessorTest {
final int res =
com.android.frameworks.servicestests.R.raw.input_port_associations_bad_displayport;
InputStream xml = mContext.getResources().openRawResource(res);
- List<Pair<String, String>> associations = null;
+ Map<String, Integer> associations = null;
try {
associations = ConfigurationProcessor.processInputPortAssociations(xml);
} catch (Exception e) {
diff --git a/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java b/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java
index 37ff06a18492..a2376a6bef1c 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java
@@ -16,57 +16,380 @@
package com.android.server.integrity;
+import static android.content.integrity.AppIntegrityManager.EXTRA_STATUS;
+import static android.content.integrity.AppIntegrityManager.STATUS_FAILURE;
+import static android.content.integrity.AppIntegrityManager.STATUS_SUCCESS;
import static android.content.pm.PackageManager.EXTRA_VERIFICATION_ID;
+import static android.content.pm.PackageManager.EXTRA_VERIFICATION_INSTALLER_PACKAGE;
+import static android.content.pm.PackageManager.EXTRA_VERIFICATION_INSTALLER_UID;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.mockito.internal.verification.VerificationModeFactory.times;
+import android.content.BroadcastReceiver;
+import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.IntentSender;
+import android.content.integrity.AppInstallMetadata;
+import android.content.integrity.AtomicFormula;
+import android.content.integrity.Rule;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
+import android.content.pm.ParceledListSlice;
+import android.content.res.Resources;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Message;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
+import com.android.internal.R;
import com.android.server.LocalServices;
+import com.android.server.integrity.engine.RuleEvaluationEngine;
+import com.android.server.integrity.model.IntegrityCheckResult;
+import com.android.server.testutils.TestUtils;
+import org.junit.After;
import org.junit.Before;
-import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.StandardCopyOption;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
/** Unit test for {@link com.android.server.integrity.AppIntegrityManagerServiceImpl} */
@RunWith(AndroidJUnit4.class)
public class AppIntegrityManagerServiceImplTest {
+ private static final String TEST_DIR = "AppIntegrityManagerServiceImplTest";
+
+ private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
+ private static final String VERSION = "version";
+ private static final String TEST_FRAMEWORK_PACKAGE = "com.android.frameworks.servicestests";
- @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
+ private static final String PACKAGE_NAME = "com.test.app";
+ private static final int VERSION_CODE = 100;
+ private static final String INSTALLER = TEST_FRAMEWORK_PACKAGE;
+ // These are obtained by running the test and checking logcat.
+ private static final String APP_CERT =
+ "949ADC6CB92FF09E3784D6E9504F26F9BEAC06E60D881D55A6A81160F9CD6FD1";
+ private static final String INSTALLER_CERT =
+ "301AA3CB081134501C45F1422ABC66C24224FD5DED5FDC8F17E697176FD866AA";
+ // We use SHA256 for package names longer than 32 characters.
+ private static final String INSTALLER_SHA256 =
+ "786933C28839603EB48C50B2A688DC6BE52C833627CB2731FF8466A2AE9F94CD";
+
+ @org.junit.Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
@Mock PackageManagerInternal mPackageManagerInternal;
+ @Mock Context mMockContext;
+ @Mock Resources mMockResources;
+ @Mock RuleEvaluationEngine mRuleEvaluationEngine;
+ @Mock IntegrityFileManager mIntegrityFileManager;
+ @Mock Handler mHandler;
+
+ private PackageManager mSpyPackageManager;
+ private File mTestApk;
+ private final Context mRealContext = InstrumentationRegistry.getTargetContext();
// under test
private AppIntegrityManagerServiceImpl mService;
@Before
- public void setup() {
+ public void setup() throws Exception {
+ mTestApk = File.createTempFile("TestApk", /* suffix= */ null);
+ mTestApk.deleteOnExit();
+ try (InputStream inputStream = mRealContext.getAssets().open(TEST_DIR + "/test.apk")) {
+ Files.copy(inputStream, mTestApk.toPath(), StandardCopyOption.REPLACE_EXISTING);
+ }
+
+ mService =
+ new AppIntegrityManagerServiceImpl(
+ mMockContext,
+ mPackageManagerInternal,
+ mRuleEvaluationEngine,
+ mIntegrityFileManager,
+ mHandler);
+
+ mSpyPackageManager = spy(mRealContext.getPackageManager());
+ // setup mocks to prevent NPE
+ when(mMockContext.getPackageManager()).thenReturn(mSpyPackageManager);
+ when(mMockContext.getResources()).thenReturn(mMockResources);
+ when(mMockResources.getStringArray(anyInt())).thenReturn(new String[] {});
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ mTestApk.delete();
+ }
+
+ // This is not a test of the class, but more of a safeguard that we don't block any install in
+ // the default case. This is needed because we don't have any emergency kill switch to disable
+ // this component.
+ @Test
+ public void default_allow() throws Exception {
+ LocalServices.removeServiceForTest(PackageManagerInternal.class);
LocalServices.addService(PackageManagerInternal.class, mPackageManagerInternal);
+ mService = AppIntegrityManagerServiceImpl.create(mMockContext);
+ ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
+ ArgumentCaptor.forClass(BroadcastReceiver.class);
+ verify(mMockContext, times(2))
+ .registerReceiver(broadcastReceiverCaptor.capture(), any(), any(), any());
+ Intent intent = makeVerificationIntent();
+
+ broadcastReceiverCaptor.getValue().onReceive(mMockContext, intent);
+
+ // Since we are not mocking handler in this case, we must wait.
+ // 2 seconds should be a sensible timeout.
+ Thread.sleep(2000);
+ verify(mPackageManagerInternal)
+ .setIntegrityVerificationResult(
+ 1, PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
+ }
+
+ @Test
+ public void updateRuleSet_notAuthorized() throws Exception {
+ makeUsSystemApp();
+ Rule rule =
+ new Rule(
+ new AtomicFormula.BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true),
+ Rule.DENY);
+ TestUtils.assertExpectException(
+ SecurityException.class,
+ "Only system packages specified in config_integrityRuleProviderPackages are"
+ + " allowed to call this method.",
+ () ->
+ mService.updateRuleSet(
+ VERSION,
+ new ParceledListSlice<>(Arrays.asList(rule)),
+ /* statusReceiver= */ null));
+ }
+
+ @Test
+ public void updateRuleSet_notSystemApp() throws Exception {
+ whitelistUsAsRuleProvider();
+ Rule rule =
+ new Rule(
+ new AtomicFormula.BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true),
+ Rule.DENY);
+ TestUtils.assertExpectException(
+ SecurityException.class,
+ "Only system packages specified in config_integrityRuleProviderPackages are"
+ + " allowed to call this method.",
+ () ->
+ mService.updateRuleSet(
+ VERSION,
+ new ParceledListSlice<>(Arrays.asList(rule)),
+ /* statusReceiver= */ null));
+ }
+
+ @Test
+ public void updateRuleSet_authorized() throws Exception {
+ whitelistUsAsRuleProvider();
+ makeUsSystemApp();
+ Rule rule =
+ new Rule(
+ new AtomicFormula.BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true),
+ Rule.DENY);
+
+ // no SecurityException
+ mService.updateRuleSet(
+ VERSION, new ParceledListSlice<>(Arrays.asList(rule)), mock(IntentSender.class));
+ }
+
+ @Test
+ public void updateRuleSet_correctMethodCall() throws Exception {
+ whitelistUsAsRuleProvider();
+ makeUsSystemApp();
+ IntentSender mockReceiver = mock(IntentSender.class);
+ List<Rule> rules =
+ Arrays.asList(
+ new Rule(
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME,
+ PACKAGE_NAME,
+ /* isHashedValue= */ false),
+ Rule.DENY));
+
+ mService.updateRuleSet(VERSION, new ParceledListSlice<>(rules), mockReceiver);
+ runJobInHandler();
- mService = new AppIntegrityManagerServiceImpl(InstrumentationRegistry.getContext());
+ verify(mIntegrityFileManager).writeRules(VERSION, TEST_FRAMEWORK_PACKAGE, rules);
+ ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+ verify(mockReceiver).sendIntent(any(), anyInt(), intentCaptor.capture(), any(), any());
+ assertEquals(STATUS_SUCCESS, intentCaptor.getValue().getIntExtra(EXTRA_STATUS, -1));
}
@Test
- public void integrityVerification_allow() {
- int verificationId = 2;
- Intent integrityVerificationIntent = new Intent();
- integrityVerificationIntent.setAction(Intent.ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION);
- integrityVerificationIntent.putExtra(EXTRA_VERIFICATION_ID, verificationId);
+ public void updateRuleSet_fail() throws Exception {
+ whitelistUsAsRuleProvider();
+ makeUsSystemApp();
+ doThrow(new IOException()).when(mIntegrityFileManager).writeRules(any(), any(), any());
+ IntentSender mockReceiver = mock(IntentSender.class);
+ List<Rule> rules =
+ Arrays.asList(
+ new Rule(
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME,
+ PACKAGE_NAME,
+ /* isHashedValue= */ false),
+ Rule.DENY));
- // We cannot send the broadcast using the context since it is a protected broadcast and
- // we will get a security exception.
- mService.handleIntegrityVerification(integrityVerificationIntent);
+ mService.updateRuleSet(VERSION, new ParceledListSlice<>(rules), mockReceiver);
+ runJobInHandler();
+
+ verify(mIntegrityFileManager).writeRules(VERSION, TEST_FRAMEWORK_PACKAGE, rules);
+ ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+ verify(mockReceiver).sendIntent(any(), anyInt(), intentCaptor.capture(), any(), any());
+ assertEquals(STATUS_FAILURE, intentCaptor.getValue().getIntExtra(EXTRA_STATUS, -1));
+ }
+
+ @Test
+ public void broadcastReceiverRegistration() throws Exception {
+ ArgumentCaptor<IntentFilter> intentFilterCaptor =
+ ArgumentCaptor.forClass(IntentFilter.class);
+
+ verify(mMockContext).registerReceiver(any(), intentFilterCaptor.capture(), any(), any());
+ assertEquals(1, intentFilterCaptor.getValue().countActions());
+ assertEquals(
+ Intent.ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION,
+ intentFilterCaptor.getValue().getAction(0));
+ assertEquals(1, intentFilterCaptor.getValue().countDataTypes());
+ assertEquals(PACKAGE_MIME_TYPE, intentFilterCaptor.getValue().getDataType(0));
+ }
+
+ @Test
+ public void handleBroadcast_correctArgs() throws Exception {
+ ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
+ ArgumentCaptor.forClass(BroadcastReceiver.class);
+ verify(mMockContext)
+ .registerReceiver(broadcastReceiverCaptor.capture(), any(), any(), any());
+ Intent intent = makeVerificationIntent();
+ when(mRuleEvaluationEngine.evaluate(any(), any())).thenReturn(IntegrityCheckResult.allow());
+
+ broadcastReceiverCaptor.getValue().onReceive(mMockContext, intent);
+ runJobInHandler();
+
+ ArgumentCaptor<AppInstallMetadata> metadataCaptor =
+ ArgumentCaptor.forClass(AppInstallMetadata.class);
+ Map<String, String> allowedInstallers = new HashMap<>();
+ ArgumentCaptor<Map<String, String>> allowedInstallersCaptor =
+ ArgumentCaptor.forClass(allowedInstallers.getClass());
+ verify(mRuleEvaluationEngine)
+ .evaluate(metadataCaptor.capture(), allowedInstallersCaptor.capture());
+ AppInstallMetadata appInstallMetadata = metadataCaptor.getValue();
+ allowedInstallers = allowedInstallersCaptor.getValue();
+ assertEquals(PACKAGE_NAME, appInstallMetadata.getPackageName());
+ assertEquals(APP_CERT, appInstallMetadata.getAppCertificate());
+ assertEquals(INSTALLER_SHA256, appInstallMetadata.getInstallerName());
+ assertEquals(INSTALLER_CERT, appInstallMetadata.getInstallerCertificate());
+ assertEquals(VERSION_CODE, appInstallMetadata.getVersionCode());
+ assertFalse(appInstallMetadata.isPreInstalled());
+ // These are hardcoded in the test apk
+ assertEquals(2, allowedInstallers.size());
+ assertEquals("cert_1", allowedInstallers.get("store_1"));
+ assertEquals("cert_2", allowedInstallers.get("store_2"));
+ }
+
+ @Test
+ public void handleBroadcast_allow() throws Exception {
+ ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
+ ArgumentCaptor.forClass(BroadcastReceiver.class);
+ verify(mMockContext)
+ .registerReceiver(broadcastReceiverCaptor.capture(), any(), any(), any());
+ Intent intent = makeVerificationIntent();
+ when(mRuleEvaluationEngine.evaluate(any(), any())).thenReturn(IntegrityCheckResult.allow());
+
+ broadcastReceiverCaptor.getValue().onReceive(mMockContext, intent);
+ runJobInHandler();
verify(mPackageManagerInternal)
- .setIntegrityVerificationResult(verificationId, PackageManager.VERIFICATION_ALLOW);
+ .setIntegrityVerificationResult(
+ 1, PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
+ }
+
+ @Test
+ public void handleBroadcast_reject() throws Exception {
+ ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
+ ArgumentCaptor.forClass(BroadcastReceiver.class);
+ verify(mMockContext)
+ .registerReceiver(broadcastReceiverCaptor.capture(), any(), any(), any());
+ when(mRuleEvaluationEngine.evaluate(any(), any()))
+ .thenReturn(
+ IntegrityCheckResult.deny(
+ new Rule(
+ new AtomicFormula.BooleanAtomicFormula(
+ AtomicFormula.PRE_INSTALLED, false),
+ Rule.DENY)));
+ Intent intent = makeVerificationIntent();
+
+ broadcastReceiverCaptor.getValue().onReceive(mMockContext, intent);
+ runJobInHandler();
+
+ verify(mPackageManagerInternal)
+ .setIntegrityVerificationResult(
+ 1, PackageManagerInternal.INTEGRITY_VERIFICATION_REJECT);
+ }
+
+ private void whitelistUsAsRuleProvider() {
+ Resources mockResources = mock(Resources.class);
+ when(mockResources.getStringArray(R.array.config_integrityRuleProviderPackages))
+ .thenReturn(new String[] {TEST_FRAMEWORK_PACKAGE});
+ when(mMockContext.getResources()).thenReturn(mockResources);
+ }
+
+ private void runJobInHandler() {
+ ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
+ // sendMessageAtTime is the first non-final method in the call chain when "post" is invoked.
+ verify(mHandler).sendMessageAtTime(messageCaptor.capture(), anyLong());
+ messageCaptor.getValue().getCallback().run();
+ }
+
+ private void makeUsSystemApp() throws Exception {
+ PackageInfo packageInfo =
+ mRealContext.getPackageManager().getPackageInfo(TEST_FRAMEWORK_PACKAGE, 0);
+ packageInfo.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
+ doReturn(packageInfo)
+ .when(mSpyPackageManager)
+ .getPackageInfo(eq(TEST_FRAMEWORK_PACKAGE), anyInt());
+ }
+
+ private Intent makeVerificationIntent() throws Exception {
+ Intent intent = new Intent();
+ intent.setDataAndType(Uri.fromFile(mTestApk), PACKAGE_MIME_TYPE);
+ intent.setAction(Intent.ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION);
+ intent.putExtra(EXTRA_VERIFICATION_ID, 1);
+ intent.putExtra(Intent.EXTRA_PACKAGE_NAME, PACKAGE_NAME);
+ intent.putExtra(EXTRA_VERIFICATION_INSTALLER_PACKAGE, INSTALLER);
+ intent.putExtra(
+ EXTRA_VERIFICATION_INSTALLER_UID,
+ mRealContext.getPackageManager().getPackageUid(INSTALLER, /* flags= */ 0));
+ intent.putExtra(Intent.EXTRA_VERSION_CODE, VERSION_CODE);
+ return intent;
}
}
diff --git a/services/tests/servicestests/src/com/android/server/integrity/IntegrityFileManagerTest.java b/services/tests/servicestests/src/com/android/server/integrity/IntegrityFileManagerTest.java
new file mode 100644
index 000000000000..63189e7546e2
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/integrity/IntegrityFileManagerTest.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.integrity;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.hasItems;
+import static org.junit.Assert.assertThat;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import android.content.integrity.AppInstallMetadata;
+import android.content.integrity.AtomicFormula;
+import android.content.integrity.AtomicFormula.IntAtomicFormula;
+import android.content.integrity.AtomicFormula.StringAtomicFormula;
+import android.content.integrity.CompoundFormula;
+import android.content.integrity.Rule;
+import android.util.Slog;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.server.integrity.parser.RuleXmlParser;
+import com.android.server.integrity.serializer.RuleXmlSerializer;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+/** Unit test for {@link IntegrityFileManager} */
+@RunWith(AndroidJUnit4.class)
+public class IntegrityFileManagerTest {
+ private static final String TAG = "IntegrityFileManagerTest";
+
+ private static final String VERSION = "version";
+ private static final String RULE_PROVIDER = "rule_provider";
+
+ private File mTmpDir;
+
+ // under test
+ private IntegrityFileManager mIntegrityFileManager;
+
+ @Before
+ public void setUp() throws Exception {
+ mTmpDir = Files.createTempDirectory("IntegrityFileManagerTest").toFile();
+ Slog.i(TAG, "Using temp directory " + mTmpDir);
+
+ // Use Xml Parser/Serializer to help with debugging since we can just print the file.
+ mIntegrityFileManager =
+ new IntegrityFileManager(
+ new RuleXmlParser(), new RuleXmlSerializer(), mTmpDir);
+ Files.walk(mTmpDir.toPath())
+ .forEach(
+ path -> {
+ Slog.i(TAG, "before " + path);
+ });
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ Files.walk(mTmpDir.toPath())
+ .forEach(
+ path -> {
+ Slog.i(TAG, "after " + path);
+ });
+ // Sorting paths in reverse order guarantees that we delete inside files before deleting
+ // directory.
+ Files.walk(mTmpDir.toPath())
+ .sorted(Comparator.reverseOrder())
+ .map(Path::toFile)
+ .forEach(File::delete);
+ }
+
+ @Test
+ public void testGetMetadata() throws Exception {
+ assertNull(mIntegrityFileManager.readMetadata());
+ mIntegrityFileManager.writeRules(VERSION, RULE_PROVIDER, Collections.EMPTY_LIST);
+
+ assertNotNull(mIntegrityFileManager.readMetadata());
+ assertEquals(VERSION, mIntegrityFileManager.readMetadata().getVersion());
+ assertEquals(RULE_PROVIDER, mIntegrityFileManager.readMetadata().getRuleProvider());
+ }
+
+ @Test
+ public void testGetRules() throws Exception {
+ String packageName = "package";
+ String packageCert = "cert";
+ int version = 123;
+ Rule packageNameRule =
+ new Rule(
+ new StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME,
+ packageName,
+ /* isHashedValue= */ false),
+ Rule.DENY);
+ Rule packageCertRule =
+ new Rule(
+ new StringAtomicFormula(
+ AtomicFormula.APP_CERTIFICATE,
+ packageCert,
+ /* isHashedValue= */ false),
+ Rule.DENY);
+ Rule versionCodeRule =
+ new Rule(
+ new IntAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.LE, version),
+ Rule.DENY);
+ Rule randomRule =
+ new Rule(
+ new CompoundFormula(
+ CompoundFormula.OR,
+ Arrays.asList(
+ new StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME,
+ "abc",
+ /* isHashedValue= */ false),
+ new IntAtomicFormula(
+ AtomicFormula.VERSION_CODE,
+ AtomicFormula.LE,
+ version))),
+ Rule.DENY);
+ // We will test the specifics of indexing in other classes. Here, we just require that all
+ // rules that are related to the given AppInstallMetadata are returned and do not assert
+ // anything on other rules.
+ List<Rule> rules =
+ Arrays.asList(packageNameRule, packageCertRule, versionCodeRule, randomRule);
+ mIntegrityFileManager.writeRules(VERSION, RULE_PROVIDER, rules);
+
+ AppInstallMetadata appInstallMetadata = new AppInstallMetadata.Builder()
+ .setPackageName(packageName)
+ .setAppCertificate(packageCert)
+ .setVersionCode(version)
+ .setInstallerName("abc")
+ .setInstallerCertificate("abc")
+ .setIsPreInstalled(true)
+ .build();
+ List<Rule> rulesFetched = mIntegrityFileManager.readRules(appInstallMetadata);
+
+ assertThat(rulesFetched, hasItems(
+ equalTo(packageNameRule),
+ equalTo(packageCertRule),
+ equalTo(versionCodeRule)
+ ));
+ }
+
+ @Test
+ public void testIsInitialized() throws Exception {
+ assertFalse(mIntegrityFileManager.initialized());
+ mIntegrityFileManager.writeRules(VERSION, RULE_PROVIDER, Collections.EMPTY_LIST);
+ assertTrue(mIntegrityFileManager.initialized());
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/integrity/IntegrityUtilsTest.java b/services/tests/servicestests/src/com/android/server/integrity/IntegrityUtilsTest.java
new file mode 100644
index 000000000000..ac7f8f98ab9b
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/integrity/IntegrityUtilsTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.integrity;
+
+import static com.android.server.integrity.IntegrityUtils.getBytesFromHexDigest;
+import static com.android.server.integrity.IntegrityUtils.getHexDigest;
+import static com.android.server.testutils.TestUtils.assertExpectException;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/** Unit test for {@link com.android.server.integrity.IntegrityUtils} */
+@RunWith(AndroidJUnit4.class)
+public class IntegrityUtilsTest {
+
+ private static final String HEX_DIGEST = "1234567890ABCDEF";
+ private static final byte[] BYTES =
+ new byte[] {0x12, 0x34, 0x56, 0x78, (byte) 0x90, (byte) 0xAB, (byte) 0xCD, (byte) 0xEF};
+
+ @Test
+ public void testGetBytesFromHexDigest() {
+ assertArrayEquals(BYTES, getBytesFromHexDigest(HEX_DIGEST));
+ }
+
+ @Test
+ public void testGetHexDigest() {
+ assertEquals(HEX_DIGEST, getHexDigest(BYTES));
+ }
+
+ @Test
+ public void testInvalidHexDigest() {
+ assertExpectException(
+ IllegalArgumentException.class,
+ "must have even length",
+ () -> getBytesFromHexDigest("ABC"));
+
+ assertExpectException(
+ IllegalArgumentException.class,
+ "Invalid hex char",
+ () -> getBytesFromHexDigest("GH"));
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/integrity/engine/RuleEvaluationEngineTest.java b/services/tests/servicestests/src/com/android/server/integrity/engine/RuleEvaluationEngineTest.java
new file mode 100644
index 000000000000..d3864878d4b2
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/integrity/engine/RuleEvaluationEngineTest.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.integrity.engine;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+
+import android.content.integrity.AppInstallMetadata;
+import android.content.integrity.Rule;
+
+import com.android.server.integrity.IntegrityFileManager;
+import com.android.server.integrity.model.IntegrityCheckResult;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@RunWith(JUnit4.class)
+public class RuleEvaluationEngineTest {
+
+ private static final String INSTALLER_1 = "installer1";
+ private static final String INSTALLER_1_CERT = "installer1_cert";
+ private static final String INSTALLER_2 = "installer2";
+ private static final String INSTALLER_2_CERT = "installer2_cert";
+
+ private static final String RANDOM_INSTALLER = "random";
+ private static final String RANDOM_INSTALLER_CERT = "random_cert";
+
+ @Mock private IntegrityFileManager mIntegrityFileManager;
+
+ private RuleEvaluationEngine mEngine;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ mEngine = new RuleEvaluationEngine(mIntegrityFileManager);
+
+ when(mIntegrityFileManager.readRules(any())).thenReturn(new ArrayList<>());
+ }
+
+ @Test
+ public void testAllowedInstallers_empty() {
+ Map<String, String> allowedInstallers = Collections.emptyMap();
+
+ assertEquals(
+ IntegrityCheckResult.Effect.ALLOW,
+ mEngine.evaluate(
+ getAppInstallMetadataBuilder()
+ .setInstallerName(INSTALLER_1)
+ .setInstallerCertificate(INSTALLER_1_CERT)
+ .build(),
+ allowedInstallers)
+ .getEffect());
+ assertEquals(
+ IntegrityCheckResult.Effect.ALLOW,
+ mEngine.evaluate(
+ getAppInstallMetadataBuilder()
+ .setInstallerName(INSTALLER_2)
+ .setInstallerCertificate(INSTALLER_2_CERT)
+ .build(),
+ allowedInstallers)
+ .getEffect());
+ assertEquals(
+ IntegrityCheckResult.Effect.ALLOW,
+ mEngine.evaluate(
+ getAppInstallMetadataBuilder()
+ .setInstallerName(RANDOM_INSTALLER)
+ .setInstallerCertificate(RANDOM_INSTALLER_CERT)
+ .build(),
+ allowedInstallers)
+ .getEffect());
+ }
+
+ @Test
+ public void testAllowedInstallers_oneElement() {
+ Map<String, String> allowedInstallers =
+ Collections.singletonMap(INSTALLER_1, INSTALLER_1_CERT);
+
+ assertEquals(
+ IntegrityCheckResult.Effect.ALLOW,
+ mEngine.evaluate(
+ getAppInstallMetadataBuilder()
+ .setInstallerName(INSTALLER_1)
+ .setInstallerCertificate(INSTALLER_1_CERT)
+ .build(),
+ allowedInstallers)
+ .getEffect());
+ assertEquals(
+ IntegrityCheckResult.Effect.DENY,
+ mEngine.evaluate(
+ getAppInstallMetadataBuilder()
+ .setInstallerName(RANDOM_INSTALLER)
+ .setInstallerCertificate(INSTALLER_1_CERT)
+ .build(),
+ allowedInstallers)
+ .getEffect());
+ assertEquals(
+ IntegrityCheckResult.Effect.DENY,
+ mEngine.evaluate(
+ getAppInstallMetadataBuilder()
+ .setInstallerName(INSTALLER_1)
+ .setInstallerCertificate(RANDOM_INSTALLER_CERT)
+ .build(),
+ allowedInstallers)
+ .getEffect());
+ assertEquals(
+ IntegrityCheckResult.Effect.DENY,
+ mEngine.evaluate(
+ getAppInstallMetadataBuilder()
+ .setInstallerName(RANDOM_INSTALLER)
+ .setInstallerCertificate(RANDOM_INSTALLER_CERT)
+ .build(),
+ allowedInstallers)
+ .getEffect());
+ }
+
+ @Test
+ public void testAllowedInstallers_multipleElement() {
+ List<Rule> rules = new ArrayList<>();
+ Map<String, String> allowedInstallers = new HashMap<>(2);
+ allowedInstallers.put(INSTALLER_1, INSTALLER_1_CERT);
+ allowedInstallers.put(INSTALLER_2, INSTALLER_2_CERT);
+
+ assertEquals(
+ IntegrityCheckResult.Effect.ALLOW,
+ mEngine.evaluate(
+ getAppInstallMetadataBuilder()
+ .setInstallerName(INSTALLER_1)
+ .setInstallerCertificate(INSTALLER_1_CERT)
+ .build(),
+ allowedInstallers)
+ .getEffect());
+ assertEquals(
+ IntegrityCheckResult.Effect.ALLOW,
+ mEngine.evaluate(
+ getAppInstallMetadataBuilder()
+ .setInstallerName(INSTALLER_2)
+ .setInstallerCertificate(INSTALLER_2_CERT)
+ .build(),
+ allowedInstallers)
+ .getEffect());
+ assertEquals(
+ IntegrityCheckResult.Effect.DENY,
+ mEngine.evaluate(
+ getAppInstallMetadataBuilder()
+ .setInstallerName(INSTALLER_1)
+ .setInstallerCertificate(INSTALLER_2_CERT)
+ .build(),
+ allowedInstallers)
+ .getEffect());
+ assertEquals(
+ IntegrityCheckResult.Effect.DENY,
+ mEngine.evaluate(
+ getAppInstallMetadataBuilder()
+ .setInstallerName(INSTALLER_2)
+ .setInstallerCertificate(INSTALLER_1_CERT)
+ .build(),
+ allowedInstallers)
+ .getEffect());
+ }
+
+ /** Returns a builder with all fields filled with some dummy data. */
+ private AppInstallMetadata.Builder getAppInstallMetadataBuilder() {
+ return new AppInstallMetadata.Builder()
+ .setPackageName("abc")
+ .setAppCertificate("abc")
+ .setInstallerCertificate("abc")
+ .setInstallerName("abc")
+ .setVersionCode(-1)
+ .setIsPreInstalled(true);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/integrity/parser/RuleBinaryParserTest.java b/services/tests/servicestests/src/com/android/server/integrity/parser/RuleBinaryParserTest.java
index 88b6d70688ad..9cc0ed85a044 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/parser/RuleBinaryParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/parser/RuleBinaryParserTest.java
@@ -38,6 +38,8 @@ import android.content.integrity.AtomicFormula;
import android.content.integrity.CompoundFormula;
import android.content.integrity.Rule;
+import com.android.server.integrity.IntegrityUtils;
+
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -45,6 +47,7 @@ import org.junit.runners.JUnit4;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -81,6 +84,7 @@ public class RuleBinaryParserTest {
private static final String INVALID_OPERATOR = getBits(INVALID_OPERATOR_VALUE, OPERATOR_BITS);
private static final String IS_NOT_HASHED = "0";
+ private static final String IS_HASHED = "1";
private static final String DENY = getBits(Rule.DENY, EFFECT_BITS);
private static final int INVALID_EFFECT_VALUE = 5;
@@ -300,16 +304,47 @@ public class RuleBinaryParserTest {
}
@Test
+ public void testBinaryString_validAtomicFormula_hashedValue() throws Exception {
+ String appCertificate = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
+ String ruleBits =
+ START_BIT
+ + ATOMIC_FORMULA_START_BITS
+ + APP_CERTIFICATE
+ + EQ
+ + IS_HASHED
+ + getBits(appCertificate.length(), VALUE_SIZE_BITS)
+ + getValueBits(appCertificate)
+ + DENY
+ + END_BIT;
+ byte[] ruleBytes = getBytes(ruleBits);
+ ByteBuffer rule =
+ ByteBuffer.allocate(DEFAULT_FORMAT_VERSION_BYTES.length + ruleBytes.length);
+ rule.put(DEFAULT_FORMAT_VERSION_BYTES);
+ rule.put(ruleBytes);
+ RuleParser binaryParser = new RuleBinaryParser();
+ Rule expectedRule =
+ new Rule(
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.APP_CERTIFICATE,
+ IntegrityUtils.getHexDigest(
+ appCertificate.getBytes(StandardCharsets.UTF_8)),
+ /* isHashedValue= */ true),
+ Rule.DENY);
+
+ List<Rule> rules = binaryParser.parse(rule.array());
+
+ assertThat(rules).isEqualTo(Collections.singletonList(expectedRule));
+ }
+
+ @Test
public void testBinaryString_validAtomicFormula_integerValue() throws Exception {
- String versionCode = "1";
+ int versionCode = 1;
String ruleBits =
START_BIT
+ ATOMIC_FORMULA_START_BITS
+ VERSION_CODE
+ EQ
- + IS_NOT_HASHED
- + getBits(versionCode.length(), VALUE_SIZE_BITS)
- + getValueBits(versionCode)
+ + getBits(versionCode, /* numOfBits= */ 32)
+ DENY
+ END_BIT;
byte[] ruleBytes = getBytes(ruleBits);
@@ -337,9 +372,7 @@ public class RuleBinaryParserTest {
+ ATOMIC_FORMULA_START_BITS
+ PRE_INSTALLED
+ EQ
- + IS_NOT_HASHED
- + getBits(isPreInstalled.length(), VALUE_SIZE_BITS)
- + getValueBits(isPreInstalled)
+ + isPreInstalled
+ DENY
+ END_BIT;
byte[] ruleBytes = getBytes(ruleBits);
@@ -360,17 +393,14 @@ public class RuleBinaryParserTest {
@Test
public void testBinaryString_invalidAtomicFormula() throws Exception {
- String versionCode = "test";
+ int versionCode = 1;
String ruleBits =
START_BIT
+ ATOMIC_FORMULA_START_BITS
+ VERSION_CODE
+ EQ
- + IS_NOT_HASHED
- + getBits(versionCode.length(), VALUE_SIZE_BITS)
- + getValueBits(versionCode)
- + DENY
- + END_BIT;
+ + getBits(versionCode, /* numOfBits= */ 32)
+ + DENY;
byte[] ruleBytes = getBytes(ruleBits);
ByteBuffer rule =
ByteBuffer.allocate(DEFAULT_FORMAT_VERSION_BYTES.length + ruleBytes.length);
@@ -380,7 +410,7 @@ public class RuleBinaryParserTest {
assertExpectException(
RuleParseException.class,
- /* expectedExceptionMessageRegex */ "For input string:",
+ /* expectedExceptionMessageRegex */ "A rule must end with a '1' bit.",
() -> binaryParser.parse(rule.array()));
}
@@ -449,7 +479,7 @@ public class RuleBinaryParserTest {
@Test
public void testBinaryString_invalidRule_invalidOperator() throws Exception {
- String versionCode = "1";
+ int versionCode = 1;
String ruleBits =
START_BIT
+ COMPOUND_FORMULA_START_BITS
@@ -457,9 +487,7 @@ public class RuleBinaryParserTest {
+ ATOMIC_FORMULA_START_BITS
+ VERSION_CODE
+ INVALID_OPERATOR
- + IS_NOT_HASHED
- + getBits(versionCode.length(), VALUE_SIZE_BITS)
- + getValueBits(versionCode)
+ + getBits(versionCode, /* numOfBits= */ 32)
+ COMPOUND_FORMULA_END_BITS
+ DENY
+ END_BIT;
diff --git a/services/tests/servicestests/src/com/android/server/integrity/serializer/ByteTrackedOutputStreamTest.java b/services/tests/servicestests/src/com/android/server/integrity/serializer/ByteTrackedOutputStreamTest.java
new file mode 100644
index 000000000000..5ecb8b5c8169
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/integrity/serializer/ByteTrackedOutputStreamTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.integrity.serializer;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.android.server.integrity.model.BitOutputStream;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.io.ByteArrayOutputStream;
+
+@RunWith(JUnit4.class)
+public class ByteTrackedOutputStreamTest {
+
+ @Test
+ public void testConstructorStartsWithZeroBytesWritten() {
+ ByteTrackedOutputStream byteTrackedOutputStream =
+ new ByteTrackedOutputStream(new ByteArrayOutputStream());
+
+ assertThat(byteTrackedOutputStream.getWrittenBytesCount()).isEqualTo(0);
+ }
+
+ @Test
+ public void testSuccessfulWriteAndValidateWrittenBytesCount_directFromByteArray()
+ throws Exception {
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ ByteTrackedOutputStream byteTrackedOutputStream = new ByteTrackedOutputStream(outputStream);
+
+ byte[] outputContent = "This is going to be outputed for tests.".getBytes();
+ byteTrackedOutputStream.write(outputContent);
+
+ assertThat(byteTrackedOutputStream.getWrittenBytesCount()).isEqualTo(outputContent.length);
+ assertThat(outputStream.toByteArray().length).isEqualTo(outputContent.length);
+ }
+
+ @Test
+ public void testSuccessfulWriteAndValidateWrittenBytesCount_fromBitStream() throws Exception {
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ ByteTrackedOutputStream byteTrackedOutputStream = new ByteTrackedOutputStream(outputStream);
+
+ BitOutputStream bitOutputStream = new BitOutputStream();
+ bitOutputStream.setNext(/* numOfBits= */5, /* value= */1);
+ byteTrackedOutputStream.write(bitOutputStream.toByteArray());
+
+ // Even though we wrote 5 bits, this will complete to 1 byte.
+ assertThat(byteTrackedOutputStream.getWrittenBytesCount()).isEqualTo(1);
+
+ // Add a bit less than 2 bytes (10 bits).
+ bitOutputStream.clear();
+ bitOutputStream.setNext(/* numOfBits= */10, /* value= */1);
+ byteTrackedOutputStream.write(bitOutputStream.toByteArray());
+
+ assertThat(outputStream.toByteArray().length).isEqualTo(3);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleBinarySerializerTest.java b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleBinarySerializerTest.java
index 901277ded5dd..981db6a1a7ff 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleBinarySerializerTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleBinarySerializerTest.java
@@ -42,18 +42,26 @@ import android.content.integrity.Rule;
import androidx.annotation.NonNull;
+import com.android.server.integrity.IntegrityUtils;
+
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import java.io.ByteArrayOutputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.List;
import java.util.Optional;
@RunWith(JUnit4.class)
public class RuleBinarySerializerTest {
+ private static final String SAMPLE_INSTALLER_NAME = "com.test.installer";
+ private static final String SAMPLE_INSTALLER_CERT = "installer_cert";
+
private static final String COMPOUND_FORMULA_START_BITS =
getBits(COMPOUND_FORMULA_START, SEPARATOR_BITS);
private static final String COMPOUND_FORMULA_END_BITS =
@@ -67,12 +75,16 @@ public class RuleBinarySerializerTest {
private static final String PACKAGE_NAME = getBits(AtomicFormula.PACKAGE_NAME, KEY_BITS);
private static final String APP_CERTIFICATE = getBits(AtomicFormula.APP_CERTIFICATE, KEY_BITS);
+ private static final String INSTALLER_NAME = getBits(AtomicFormula.INSTALLER_NAME, KEY_BITS);
+ private static final String INSTALLER_CERTIFICATE =
+ getBits(AtomicFormula.INSTALLER_CERTIFICATE, KEY_BITS);
private static final String VERSION_CODE = getBits(AtomicFormula.VERSION_CODE, KEY_BITS);
private static final String PRE_INSTALLED = getBits(AtomicFormula.PRE_INSTALLED, KEY_BITS);
private static final String EQ = getBits(AtomicFormula.EQ, OPERATOR_BITS);
private static final String IS_NOT_HASHED = "0";
+ private static final String IS_HASHED = "1";
private static final String DENY = getBits(Rule.DENY, EFFECT_BITS);
@@ -83,17 +95,27 @@ public class RuleBinarySerializerTest {
getBytes(getBits(DEFAULT_FORMAT_VERSION, FORMAT_VERSION_BITS));
@Test
- public void testBinaryString_serializeEmptyRule() throws Exception {
- Rule rule = null;
+ public void testBinaryString_serializeNullRules() {
RuleSerializer binarySerializer = new RuleBinarySerializer();
assertExpectException(
RuleSerializeException.class,
- /* expectedExceptionMessageRegex= */ "Null rule can not be serialized",
- () ->
- binarySerializer.serialize(
- Collections.singletonList(rule),
- /* formatVersion= */ Optional.empty()));
+ /* expectedExceptionMessageRegex= */ "Index buckets cannot be created for null"
+ + " rule list.",
+ () -> binarySerializer.serialize(null, /* formatVersion= */ Optional.empty()));
+ }
+
+ @Test
+ public void testBinaryString_emptyRules() throws Exception {
+ ByteArrayOutputStream expectedArrayOutputStream = new ByteArrayOutputStream();
+ expectedArrayOutputStream.write(DEFAULT_FORMAT_VERSION_BYTES);
+
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ RuleSerializer binarySerializer = new RuleBinarySerializer();
+ binarySerializer.serialize(
+ Collections.emptyList(), /* formatVersion= */ Optional.empty(), outputStream);
+
+ assertThat(outputStream.toByteArray()).isEqualTo(expectedArrayOutputStream.toByteArray());
}
@Test
@@ -311,14 +333,46 @@ public class RuleBinarySerializerTest {
}
@Test
+ public void testBinaryString_serializeValidAtomicFormula_hashedValue() throws Exception {
+ String appCertificate = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
+ Rule rule =
+ new Rule(
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.APP_CERTIFICATE,
+ IntegrityUtils.getHexDigest(
+ appCertificate.getBytes(StandardCharsets.UTF_8)),
+ /* isHashedValue= */ true),
+ Rule.DENY);
+ RuleSerializer binarySerializer = new RuleBinarySerializer();
+ String expectedBits =
+ START_BIT
+ + ATOMIC_FORMULA_START_BITS
+ + APP_CERTIFICATE
+ + EQ
+ + IS_HASHED
+ + getBits(appCertificate.length(), VALUE_SIZE_BITS)
+ + getValueBits(appCertificate)
+ + DENY
+ + END_BIT;
+ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ byteArrayOutputStream.write(DEFAULT_FORMAT_VERSION_BYTES);
+ byteArrayOutputStream.write(getBytes(expectedBits));
+ byte[] expectedRules = byteArrayOutputStream.toByteArray();
+
+ byte[] actualRules =
+ binarySerializer.serialize(
+ Collections.singletonList(rule), /* formatVersion= */ Optional.empty());
+
+ assertThat(actualRules).isEqualTo(expectedRules);
+ }
+
+ @Test
public void testBinaryString_serializeValidAtomicFormula_integerValue() throws Exception {
- String versionCode = "1";
+ int versionCode = 1;
Rule rule =
new Rule(
new AtomicFormula.IntAtomicFormula(
- AtomicFormula.VERSION_CODE,
- AtomicFormula.EQ,
- Integer.parseInt(versionCode)),
+ AtomicFormula.VERSION_CODE, AtomicFormula.EQ, versionCode),
Rule.DENY);
RuleSerializer binarySerializer = new RuleBinarySerializer();
String expectedBits =
@@ -326,9 +380,7 @@ public class RuleBinarySerializerTest {
+ ATOMIC_FORMULA_START_BITS
+ VERSION_CODE
+ EQ
- + IS_NOT_HASHED
- + getBits(versionCode.length(), VALUE_SIZE_BITS)
- + getValueBits(versionCode)
+ + getBits(versionCode, /* numOfBits= */ 32)
+ DENY
+ END_BIT;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
@@ -356,9 +408,7 @@ public class RuleBinarySerializerTest {
+ ATOMIC_FORMULA_START_BITS
+ PRE_INSTALLED
+ EQ
- + IS_NOT_HASHED
- + getBits(preInstalled.length(), VALUE_SIZE_BITS)
- + getValueBits(preInstalled)
+ + preInstalled
+ DENY
+ END_BIT;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
@@ -381,7 +431,7 @@ public class RuleBinarySerializerTest {
assertExpectException(
RuleSerializeException.class,
- /* expectedExceptionMessageRegex= */ "Invalid formula type",
+ /* expectedExceptionMessageRegex= */ "Malformed rule identified.",
() ->
binarySerializer.serialize(
Collections.singletonList(rule),
@@ -402,6 +452,170 @@ public class RuleBinarySerializerTest {
assertThat(actualRules).isEqualTo(expectedRules);
}
+ @Test
+ public void testBinaryString_serializeComplexCompoundFormula_indexingOrderValid()
+ throws Exception {
+ String packageNameA = "aaa";
+ String packageNameB = "bbb";
+ String packageNameC = "ccc";
+ String appCert1 = "cert1";
+ String appCert2 = "cert2";
+ String appCert3 = "cert3";
+ Rule installerRule =
+ new Rule(
+ new CompoundFormula(
+ CompoundFormula.AND,
+ Arrays.asList(
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.INSTALLER_NAME,
+ SAMPLE_INSTALLER_NAME,
+ /* isHashedValue= */ false),
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.INSTALLER_CERTIFICATE,
+ SAMPLE_INSTALLER_CERT,
+ /* isHashedValue= */ false))),
+ Rule.DENY);
+
+ RuleSerializer binarySerializer = new RuleBinarySerializer();
+ List<Rule> ruleList = new ArrayList();
+ ruleList.add(getRuleWithAppCertificateAndSampleInstallerName(appCert3));
+ ruleList.add(getRuleWithAppCertificateAndSampleInstallerName(appCert2));
+ ruleList.add(getRuleWithAppCertificateAndSampleInstallerName(appCert1));
+ ruleList.add(getRuleWithPackageNameAndSampleInstallerName(packageNameB));
+ ruleList.add(getRuleWithPackageNameAndSampleInstallerName(packageNameC));
+ ruleList.add(getRuleWithPackageNameAndSampleInstallerName(packageNameA));
+ ruleList.add(installerRule);
+ byte[] actualRules =
+ binarySerializer.serialize(ruleList, /* formatVersion= */ Optional.empty());
+
+ // Note that ordering is important here and the test verifies that the rules are written
+ // in this sorted order.
+ ByteArrayOutputStream expectedArrayOutputStream = new ByteArrayOutputStream();
+ expectedArrayOutputStream.write(DEFAULT_FORMAT_VERSION_BYTES);
+ expectedArrayOutputStream.write(
+ getBytes(
+ getSerializedCompoundRuleWithPackageNameAndSampleInstallerName(
+ packageNameA)));
+ expectedArrayOutputStream.write(
+ getBytes(
+ getSerializedCompoundRuleWithPackageNameAndSampleInstallerName(
+ packageNameB)));
+ expectedArrayOutputStream.write(
+ getBytes(
+ getSerializedCompoundRuleWithPackageNameAndSampleInstallerName(
+ packageNameC)));
+ expectedArrayOutputStream.write(
+ getBytes(
+ getSerializedCompoundRuleWithCertificateNameAndSampleInstallerName(
+ appCert1)));
+ expectedArrayOutputStream.write(
+ getBytes(
+ getSerializedCompoundRuleWithCertificateNameAndSampleInstallerName(
+ appCert2)));
+ expectedArrayOutputStream.write(
+ getBytes(
+ getSerializedCompoundRuleWithCertificateNameAndSampleInstallerName(
+ appCert3)));
+ String expectedBitsForInstallerRule =
+ START_BIT
+ + COMPOUND_FORMULA_START_BITS
+ + AND
+ + ATOMIC_FORMULA_START_BITS
+ + INSTALLER_NAME
+ + EQ
+ + IS_NOT_HASHED
+ + getBits(SAMPLE_INSTALLER_NAME.length(), VALUE_SIZE_BITS)
+ + getValueBits(SAMPLE_INSTALLER_NAME)
+ + ATOMIC_FORMULA_START_BITS
+ + INSTALLER_CERTIFICATE
+ + EQ
+ + IS_NOT_HASHED
+ + getBits(SAMPLE_INSTALLER_CERT.length(), VALUE_SIZE_BITS)
+ + getValueBits(SAMPLE_INSTALLER_CERT)
+ + COMPOUND_FORMULA_END_BITS
+ + DENY
+ + END_BIT;
+ expectedArrayOutputStream.write(getBytes(expectedBitsForInstallerRule));
+
+ assertThat(actualRules).isEqualTo(expectedArrayOutputStream.toByteArray());
+ }
+
+ private Rule getRuleWithPackageNameAndSampleInstallerName(String packageName) {
+ return new Rule(
+ new CompoundFormula(
+ CompoundFormula.AND,
+ Arrays.asList(
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME,
+ packageName,
+ /* isHashedValue= */ false),
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.INSTALLER_NAME,
+ SAMPLE_INSTALLER_NAME,
+ /* isHashedValue= */ false))),
+ Rule.DENY);
+ }
+
+ private String getSerializedCompoundRuleWithPackageNameAndSampleInstallerName(
+ String packageName) {
+ return START_BIT
+ + COMPOUND_FORMULA_START_BITS
+ + AND
+ + ATOMIC_FORMULA_START_BITS
+ + PACKAGE_NAME
+ + EQ
+ + IS_NOT_HASHED
+ + getBits(packageName.length(), VALUE_SIZE_BITS)
+ + getValueBits(packageName)
+ + ATOMIC_FORMULA_START_BITS
+ + INSTALLER_NAME
+ + EQ
+ + IS_NOT_HASHED
+ + getBits(SAMPLE_INSTALLER_NAME.length(), VALUE_SIZE_BITS)
+ + getValueBits(SAMPLE_INSTALLER_NAME)
+ + COMPOUND_FORMULA_END_BITS
+ + DENY
+ + END_BIT;
+ }
+
+ private Rule getRuleWithAppCertificateAndSampleInstallerName(String certificate) {
+ return new Rule(
+ new CompoundFormula(
+ CompoundFormula.AND,
+ Arrays.asList(
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.APP_CERTIFICATE,
+ certificate,
+ /* isHashedValue= */ false),
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.INSTALLER_NAME,
+ SAMPLE_INSTALLER_NAME,
+ /* isHashedValue= */ false))),
+ Rule.DENY);
+ }
+
+ private String getSerializedCompoundRuleWithCertificateNameAndSampleInstallerName(
+ String appCertificate) {
+ return START_BIT
+ + COMPOUND_FORMULA_START_BITS
+ + AND
+ + ATOMIC_FORMULA_START_BITS
+ + APP_CERTIFICATE
+ + EQ
+ + IS_NOT_HASHED
+ + getBits(appCertificate.length(), VALUE_SIZE_BITS)
+ + getValueBits(appCertificate)
+ + ATOMIC_FORMULA_START_BITS
+ + INSTALLER_NAME
+ + EQ
+ + IS_NOT_HASHED
+ + getBits(SAMPLE_INSTALLER_NAME.length(), VALUE_SIZE_BITS)
+ + getValueBits(SAMPLE_INSTALLER_NAME)
+ + COMPOUND_FORMULA_END_BITS
+ + DENY
+ + END_BIT;
+ }
+
private static Formula getInvalidFormula() {
return new Formula() {
@Override
diff --git a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleIndexTypeIdentifierTest.java b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleIndexTypeIdentifierTest.java
deleted file mode 100644
index 18b91b0b1009..000000000000
--- a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleIndexTypeIdentifierTest.java
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.integrity.serializer;
-
-import static com.android.server.testutils.TestUtils.assertExpectException;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.integrity.AppInstallMetadata;
-import android.content.integrity.AtomicFormula;
-import android.content.integrity.CompoundFormula;
-import android.content.integrity.Formula;
-import android.content.integrity.Rule;
-
-import androidx.annotation.NonNull;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-import java.util.Arrays;
-
-/** Unit tests for {@link RuleIndexTypeIdentifier}. */
-@RunWith(JUnit4.class)
-public class RuleIndexTypeIdentifierTest {
-
- @Test
- public void getIndexType_nullRule() {
- Rule rule = null;
-
- assertExpectException(
- IllegalArgumentException.class,
- /* expectedExceptionMessageRegex= */
- "Indexing type cannot be determined for null rule.",
- () -> RuleIndexTypeIdentifier.getIndexType(rule));
- }
-
- @Test
- public void getIndexType_invalidFormula() {
- Rule rule = new Rule(getInvalidFormula(), Rule.DENY);
-
- assertExpectException(
- IllegalArgumentException.class,
- /* expectedExceptionMessageRegex= */ "Invalid formula tag type.",
- () -> RuleIndexTypeIdentifier.getIndexType(rule));
- }
-
- @Test
- public void getIndexType_ruleContainingPackageNameFormula() {
- String packageName = "com.test.app";
- String installerName = "com.test.installer";
- Rule rule =
- new Rule(
- new CompoundFormula(
- CompoundFormula.AND,
- Arrays.asList(
- new AtomicFormula.StringAtomicFormula(
- AtomicFormula.PACKAGE_NAME,
- packageName,
- /* isHashedValue= */ false),
- new AtomicFormula.StringAtomicFormula(
- AtomicFormula.INSTALLER_NAME,
- installerName,
- /* isHashedValue= */ false))),
- Rule.DENY);
-
- assertThat(RuleIndexTypeIdentifier.getIndexType(rule))
- .isEqualTo(RuleIndexTypeIdentifier.PACKAGE_NAME_INDEXED);
- }
-
- @Test
- public void getIndexType_ruleContainingAppCertificateFormula() {
- String appCertificate = "cert1";
- String installerName = "com.test.installer";
- Rule rule =
- new Rule(
- new CompoundFormula(
- CompoundFormula.AND,
- Arrays.asList(
- new AtomicFormula.StringAtomicFormula(
- AtomicFormula.APP_CERTIFICATE,
- appCertificate,
- /* isHashedValue= */ false),
- new AtomicFormula.StringAtomicFormula(
- AtomicFormula.INSTALLER_NAME,
- installerName,
- /* isHashedValue= */ false))),
- Rule.DENY);
-
- assertThat(RuleIndexTypeIdentifier.getIndexType(rule))
- .isEqualTo(RuleIndexTypeIdentifier.APP_CERTIFICATE_INDEXED);
- }
-
- @Test
- public void getIndexType_ruleWithUnindexedCompoundFormula() {
- String installerCertificate = "cert1";
- String installerName = "com.test.installer";
- Rule rule =
- new Rule(
- new CompoundFormula(
- CompoundFormula.AND,
- Arrays.asList(
- new AtomicFormula.StringAtomicFormula(
- AtomicFormula.INSTALLER_CERTIFICATE,
- installerCertificate,
- /* isHashedValue= */ false),
- new AtomicFormula.StringAtomicFormula(
- AtomicFormula.INSTALLER_NAME,
- installerName,
- /* isHashedValue= */ false))),
- Rule.DENY);
-
- assertThat(RuleIndexTypeIdentifier.getIndexType(rule))
- .isEqualTo(RuleIndexTypeIdentifier.NOT_INDEXED);
- }
-
- @Test
- public void getIndexType_rulContainingCompoundFormulaWithIntAndBoolean() {
- int appVersion = 12;
- Rule rule =
- new Rule(
- new CompoundFormula(
- CompoundFormula.AND,
- Arrays.asList(
- new AtomicFormula.BooleanAtomicFormula(
- AtomicFormula.PRE_INSTALLED,
- /* booleanValue= */ true),
- new AtomicFormula.IntAtomicFormula(
- AtomicFormula.VERSION_CODE,
- AtomicFormula.EQ,
- appVersion))),
- Rule.DENY);
-
- assertThat(RuleIndexTypeIdentifier.getIndexType(rule))
- .isEqualTo(RuleIndexTypeIdentifier.NOT_INDEXED);
- }
-
- @Test
- public void getIndexType_negatedRuleContainingPackageNameFormula() {
- String packageName = "com.test.app";
- String installerName = "com.test.installer";
- Rule rule =
- new Rule(
- new CompoundFormula(
- CompoundFormula.NOT,
- Arrays.asList(
- new CompoundFormula(
- CompoundFormula.AND,
- Arrays.asList(
- new AtomicFormula.StringAtomicFormula(
- AtomicFormula.PACKAGE_NAME,
- packageName,
- /* isHashedValue= */ false),
- new AtomicFormula.StringAtomicFormula(
- AtomicFormula.INSTALLER_NAME,
- installerName,
- /* isHashedValue= */ false))))),
- Rule.DENY);
-
- assertThat(RuleIndexTypeIdentifier.getIndexType(rule))
- .isEqualTo(RuleIndexTypeIdentifier.NOT_INDEXED);
- }
-
- private Formula getInvalidFormula() {
- return new Formula() {
- @Override
- public boolean isSatisfied(AppInstallMetadata appInstallMetadata) {
- return false;
- }
-
- @Override
- public int getTag() {
- return 4;
- }
-
- @Override
- public int hashCode() {
- return super.hashCode();
- }
-
- @Override
- public boolean equals(Object obj) {
- return super.equals(obj);
- }
-
- @NonNull
- @Override
- protected Object clone() throws CloneNotSupportedException {
- return super.clone();
- }
-
- @Override
- public String toString() {
- return super.toString();
- }
-
- @Override
- protected void finalize() throws Throwable {
- super.finalize();
- }
- };
- }
-}
-
diff --git a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifierTest.java b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifierTest.java
new file mode 100644
index 000000000000..55fada44b99e
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifierTest.java
@@ -0,0 +1,346 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.integrity.serializer;
+
+import static com.android.server.integrity.serializer.RuleIndexingDetails.APP_CERTIFICATE_INDEXED;
+import static com.android.server.integrity.serializer.RuleIndexingDetails.NOT_INDEXED;
+import static com.android.server.integrity.serializer.RuleIndexingDetails.PACKAGE_NAME_INDEXED;
+import static com.android.server.integrity.serializer.RuleIndexingDetailsIdentifier.splitRulesIntoIndexBuckets;
+import static com.android.server.testutils.TestUtils.assertExpectException;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.integrity.AppInstallMetadata;
+import android.content.integrity.AtomicFormula;
+import android.content.integrity.CompoundFormula;
+import android.content.integrity.Formula;
+import android.content.integrity.Rule;
+
+import androidx.annotation.NonNull;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+/** Unit tests for {@link RuleIndexingDetailsIdentifier}. */
+@RunWith(JUnit4.class)
+public class RuleIndexingDetailsIdentifierTest {
+
+ private static final String SAMPLE_APP_CERTIFICATE = "testcert";
+ private static final String SAMPLE_INSTALLER_NAME = "com.test.installer";
+ private static final String SAMPLE_INSTALLER_CERTIFICATE = "installercert";
+ private static final String SAMPLE_PACKAGE_NAME = "com.test.package";
+
+ private static final AtomicFormula ATOMIC_FORMULA_WITH_PACKAGE_NAME =
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME,
+ SAMPLE_PACKAGE_NAME,
+ /* isHashedValue= */ false);
+ private static final AtomicFormula ATOMIC_FORMULA_WITH_APP_CERTIFICATE =
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.APP_CERTIFICATE,
+ SAMPLE_APP_CERTIFICATE,
+ /* isHashedValue= */ false);
+ private static final AtomicFormula ATOMIC_FORMULA_WITH_INSTALLER_NAME =
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.INSTALLER_NAME,
+ SAMPLE_INSTALLER_NAME,
+ /* isHashedValue= */ false);
+ private static final AtomicFormula ATOMIC_FORMULA_WITH_INSTALLER_CERTIFICATE =
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.INSTALLER_CERTIFICATE,
+ SAMPLE_INSTALLER_CERTIFICATE,
+ /* isHashedValue= */ false);
+ private static final AtomicFormula ATOMIC_FORMULA_WITH_VERSION_CODE =
+ new AtomicFormula.IntAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.EQ, 12);
+ private static final AtomicFormula ATOMIC_FORMULA_WITH_ISPREINSTALLED =
+ new AtomicFormula.BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, /* booleanValue= */
+ true);
+
+
+ private static final Rule RULE_WITH_PACKAGE_NAME =
+ new Rule(
+ new CompoundFormula(
+ CompoundFormula.AND,
+ Arrays.asList(
+ ATOMIC_FORMULA_WITH_PACKAGE_NAME,
+ ATOMIC_FORMULA_WITH_INSTALLER_NAME)),
+ Rule.DENY);
+ private static final Rule RULE_WITH_APP_CERTIFICATE =
+ new Rule(
+ new CompoundFormula(
+ CompoundFormula.AND,
+ Arrays.asList(
+ ATOMIC_FORMULA_WITH_APP_CERTIFICATE,
+ ATOMIC_FORMULA_WITH_INSTALLER_NAME)),
+ Rule.DENY);
+ private static final Rule RULE_WITH_INSTALLER_RESTRICTIONS =
+ new Rule(
+ new CompoundFormula(
+ CompoundFormula.AND,
+ Arrays.asList(
+ ATOMIC_FORMULA_WITH_INSTALLER_NAME,
+ ATOMIC_FORMULA_WITH_INSTALLER_CERTIFICATE)),
+ Rule.DENY);
+
+ private static final Rule RULE_WITH_NONSTRING_RESTRICTIONS =
+ new Rule(
+ new CompoundFormula(
+ CompoundFormula.AND,
+ Arrays.asList(
+ ATOMIC_FORMULA_WITH_VERSION_CODE,
+ ATOMIC_FORMULA_WITH_ISPREINSTALLED)),
+ Rule.DENY);
+
+ @Test
+ public void getIndexType_nullRule() {
+ List<Rule> ruleList = null;
+
+ assertExpectException(
+ IllegalArgumentException.class,
+ /* expectedExceptionMessageRegex= */
+ "Index buckets cannot be created for null rule list.",
+ () -> splitRulesIntoIndexBuckets(ruleList));
+ }
+
+ @Test
+ public void getIndexType_invalidFormula() {
+ List<Rule> ruleList = new ArrayList();
+ ruleList.add(new Rule(getInvalidFormula(), Rule.DENY));
+
+ assertExpectException(
+ IllegalArgumentException.class,
+ /* expectedExceptionMessageRegex= */ "Malformed rule identified.",
+ () -> splitRulesIntoIndexBuckets(ruleList));
+ }
+
+ @Test
+ public void getIndexType_ruleContainingPackageNameFormula() {
+ List<Rule> ruleList = new ArrayList();
+ ruleList.add(RULE_WITH_PACKAGE_NAME);
+
+ Map<Integer, TreeMap<String, List<Rule>>> result = splitRulesIntoIndexBuckets(ruleList);
+
+ // Verify the resulting map content.
+ assertThat(result.keySet())
+ .containsExactly(NOT_INDEXED, PACKAGE_NAME_INDEXED, APP_CERTIFICATE_INDEXED);
+ assertThat(result.get(NOT_INDEXED)).isEmpty();
+ assertThat(result.get(APP_CERTIFICATE_INDEXED)).isEmpty();
+ assertThat(result.get(PACKAGE_NAME_INDEXED).keySet()).containsExactly(SAMPLE_PACKAGE_NAME);
+ assertThat(result.get(PACKAGE_NAME_INDEXED).get(SAMPLE_PACKAGE_NAME))
+ .containsExactly(RULE_WITH_PACKAGE_NAME);
+ }
+
+ @Test
+ public void getIndexType_ruleContainingAppCertificateFormula() {
+ List<Rule> ruleList = new ArrayList();
+ ruleList.add(RULE_WITH_APP_CERTIFICATE);
+
+ Map<Integer, TreeMap<String, List<Rule>>> result = splitRulesIntoIndexBuckets(ruleList);
+
+ assertThat(result.keySet())
+ .containsExactly(NOT_INDEXED, PACKAGE_NAME_INDEXED, APP_CERTIFICATE_INDEXED);
+ assertThat(result.get(NOT_INDEXED)).isEmpty();
+ assertThat(result.get(PACKAGE_NAME_INDEXED)).isEmpty();
+ assertThat(result.get(APP_CERTIFICATE_INDEXED).keySet())
+ .containsExactly(SAMPLE_APP_CERTIFICATE);
+ assertThat(result.get(APP_CERTIFICATE_INDEXED).get(SAMPLE_APP_CERTIFICATE))
+ .containsExactly(RULE_WITH_APP_CERTIFICATE);
+ }
+
+ @Test
+ public void getIndexType_ruleWithUnindexedCompoundFormula() {
+ List<Rule> ruleList = new ArrayList();
+ ruleList.add(RULE_WITH_INSTALLER_RESTRICTIONS);
+
+ Map<Integer, TreeMap<String, List<Rule>>> result = splitRulesIntoIndexBuckets(ruleList);
+
+ assertThat(result.keySet())
+ .containsExactly(NOT_INDEXED, PACKAGE_NAME_INDEXED, APP_CERTIFICATE_INDEXED);
+ assertThat(result.get(PACKAGE_NAME_INDEXED)).isEmpty();
+ assertThat(result.get(APP_CERTIFICATE_INDEXED)).isEmpty();
+ assertThat(result.get(NOT_INDEXED).get("N/A"))
+ .containsExactly(RULE_WITH_INSTALLER_RESTRICTIONS);
+ }
+
+ @Test
+ public void getIndexType_ruleContainingCompoundFormulaWithIntAndBoolean() {
+ List<Rule> ruleList = new ArrayList();
+ ruleList.add(RULE_WITH_NONSTRING_RESTRICTIONS);
+
+ Map<Integer, TreeMap<String, List<Rule>>> result = splitRulesIntoIndexBuckets(ruleList);
+
+ assertThat(result.keySet())
+ .containsExactly(NOT_INDEXED, PACKAGE_NAME_INDEXED, APP_CERTIFICATE_INDEXED);
+ assertThat(result.get(PACKAGE_NAME_INDEXED)).isEmpty();
+ assertThat(result.get(APP_CERTIFICATE_INDEXED)).isEmpty();
+ assertThat(result.get(NOT_INDEXED).get("N/A"))
+ .containsExactly(RULE_WITH_NONSTRING_RESTRICTIONS);
+ }
+
+ @Test
+ public void getIndexType_negatedRuleContainingPackageNameFormula() {
+ Rule negatedRule =
+ new Rule(
+ new CompoundFormula(
+ CompoundFormula.NOT,
+ Arrays.asList(
+ new CompoundFormula(
+ CompoundFormula.AND,
+ Arrays.asList(
+ ATOMIC_FORMULA_WITH_PACKAGE_NAME,
+ ATOMIC_FORMULA_WITH_APP_CERTIFICATE)))),
+ Rule.DENY);
+ List<Rule> ruleList = new ArrayList();
+ ruleList.add(negatedRule);
+
+ Map<Integer, TreeMap<String, List<Rule>>> result = splitRulesIntoIndexBuckets(ruleList);
+
+ assertThat(result.keySet())
+ .containsExactly(NOT_INDEXED, PACKAGE_NAME_INDEXED, APP_CERTIFICATE_INDEXED);
+ assertThat(result.get(PACKAGE_NAME_INDEXED)).isEmpty();
+ assertThat(result.get(APP_CERTIFICATE_INDEXED)).isEmpty();
+ assertThat(result.get(NOT_INDEXED).get("N/A")).containsExactly(negatedRule);
+ }
+
+ @Test
+ public void getIndexType_allRulesTogetherInValidOrder() {
+ Rule packageNameRuleA = getRuleWithPackageName("aaa");
+ Rule packageNameRuleB = getRuleWithPackageName("bbb");
+ Rule packageNameRuleC = getRuleWithPackageName("ccc");
+ Rule certificateRule1 = getRuleWithAppCertificate("cert1");
+ Rule certificateRule2 = getRuleWithAppCertificate("cert2");
+ Rule certificateRule3 = getRuleWithAppCertificate("cert3");
+
+ List<Rule> ruleList = new ArrayList();
+ ruleList.add(packageNameRuleB);
+ ruleList.add(packageNameRuleC);
+ ruleList.add(packageNameRuleA);
+ ruleList.add(certificateRule3);
+ ruleList.add(certificateRule2);
+ ruleList.add(certificateRule1);
+ ruleList.add(RULE_WITH_INSTALLER_RESTRICTIONS);
+ ruleList.add(RULE_WITH_NONSTRING_RESTRICTIONS);
+
+ Map<Integer, TreeMap<String, List<Rule>>> result = splitRulesIntoIndexBuckets(ruleList);
+
+ assertThat(result.keySet())
+ .containsExactly(NOT_INDEXED, PACKAGE_NAME_INDEXED, APP_CERTIFICATE_INDEXED);
+
+ // We check asserts this way to ensure ordering based on package name.
+ assertThat(result.get(PACKAGE_NAME_INDEXED).keySet()).containsExactly("aaa", "bbb", "ccc");
+ Iterator<String> keySetIterator = result.get(PACKAGE_NAME_INDEXED).keySet().iterator();
+ assertThat(keySetIterator.next()).isEqualTo("aaa");
+ assertThat(keySetIterator.next()).isEqualTo("bbb");
+ assertThat(keySetIterator.next()).isEqualTo("ccc");
+ assertThat(result.get(PACKAGE_NAME_INDEXED).get("aaa")).containsExactly(packageNameRuleA);
+ assertThat(result.get(PACKAGE_NAME_INDEXED).get("bbb")).containsExactly(packageNameRuleB);
+ assertThat(result.get(PACKAGE_NAME_INDEXED).get("ccc")).containsExactly(packageNameRuleC);
+
+ // We check asserts this way to ensure ordering based on app certificate.
+ assertThat(result.get(APP_CERTIFICATE_INDEXED).keySet()).containsExactly("cert1", "cert2",
+ "cert3");
+ keySetIterator = result.get(APP_CERTIFICATE_INDEXED).keySet().iterator();
+ assertThat(keySetIterator.next()).isEqualTo("cert1");
+ assertThat(keySetIterator.next()).isEqualTo("cert2");
+ assertThat(keySetIterator.next()).isEqualTo("cert3");
+ assertThat(result.get(APP_CERTIFICATE_INDEXED).get("cert1")).containsExactly(
+ certificateRule1);
+ assertThat(result.get(APP_CERTIFICATE_INDEXED).get("cert2")).containsExactly(
+ certificateRule2);
+ assertThat(result.get(APP_CERTIFICATE_INDEXED).get("cert3")).containsExactly(
+ certificateRule3);
+
+ assertThat(result.get(NOT_INDEXED).get("N/A"))
+ .containsExactly(
+ RULE_WITH_INSTALLER_RESTRICTIONS,
+ RULE_WITH_NONSTRING_RESTRICTIONS);
+ }
+
+ private Rule getRuleWithPackageName(String packageName) {
+ return new Rule(
+ new CompoundFormula(
+ CompoundFormula.AND,
+ Arrays.asList(
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME,
+ packageName,
+ /* isHashedValue= */ false),
+ ATOMIC_FORMULA_WITH_INSTALLER_NAME)),
+ Rule.DENY);
+ }
+
+ private Rule getRuleWithAppCertificate(String certificate) {
+ return new Rule(
+ new CompoundFormula(
+ CompoundFormula.AND,
+ Arrays.asList(
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.APP_CERTIFICATE,
+ certificate,
+ /* isHashedValue= */ false),
+ ATOMIC_FORMULA_WITH_INSTALLER_NAME)),
+ Rule.DENY);
+ }
+
+ private Formula getInvalidFormula() {
+ return new Formula() {
+ @Override
+ public boolean isSatisfied(AppInstallMetadata appInstallMetadata) {
+ return false;
+ }
+
+ @Override
+ public int getTag() {
+ return 4;
+ }
+
+ @Override
+ public int hashCode() {
+ return super.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return super.equals(obj);
+ }
+
+ @NonNull
+ @Override
+ protected Object clone() throws CloneNotSupportedException {
+ return super.clone();
+ }
+
+ @Override
+ public String toString() {
+ return super.toString();
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ super.finalize();
+ }
+ };
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java
index ad74901ece2c..0bb2d4489b6b 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java
@@ -44,48 +44,66 @@ import java.util.Optional;
@RunWith(JUnit4.class)
public class RuleXmlSerializerTest {
+ private static final String SAMPLE_INSTALLER_NAME = "com.test.installer";
+ private static final String SAMPLE_INSTALLER_CERT = "installer_cert";
+
@Test
- public void testXmlString_serializeEmptyRule() throws Exception {
- Rule rule = null;
+ public void testXmlString_serializeEmptyRuleList() throws Exception {
RuleSerializer xmlSerializer = new RuleXmlSerializer();
String expectedRules = "<RL />";
byte[] actualRules =
xmlSerializer.serialize(
- Collections.singletonList(rule), /* formatVersion= */ Optional.empty());
+ Collections.emptyList(), /* formatVersion= */ Optional.empty());
assertEquals(expectedRules, new String(actualRules, StandardCharsets.UTF_8));
}
@Test
- public void testXmlString_serializeMultipleRules_oneEmpty() throws Exception {
- Rule rule1 = null;
- Rule rule2 =
+ public void testXmlString_serializeMultipleRules_indexingOrderPreserved() throws Exception {
+ String packageNameA = "aaa";
+ String packageNameB = "bbb";
+ String packageNameC = "ccc";
+ String appCert1 = "cert1";
+ String appCert2 = "cert2";
+ String appCert3 = "cert3";
+ Rule installerRule =
new Rule(
- new AtomicFormula.StringAtomicFormula(
- AtomicFormula.PACKAGE_NAME,
- "com.app.test",
- /* isHashedValue= */ false),
+ new CompoundFormula(
+ CompoundFormula.AND,
+ Arrays.asList(
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.INSTALLER_NAME,
+ SAMPLE_INSTALLER_NAME,
+ /* isHashedValue= */ false),
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.INSTALLER_CERTIFICATE,
+ SAMPLE_INSTALLER_CERT,
+ /* isHashedValue= */ false))),
Rule.DENY);
- RuleSerializer xmlSerializer = new RuleXmlSerializer();
- Map<String, String> packageNameAttrs = new LinkedHashMap<>();
- packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
- packageNameAttrs.put("V", "com.app.test");
- packageNameAttrs.put("H", "false");
- String expectedRules =
- "<RL>"
- + generateTagWithAttribute(
- /* tag= */ "R",
- Collections.singletonMap("E", String.valueOf(Rule.DENY)),
- /* closed= */ false)
- + generateTagWithAttribute(
- /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
- + "</R>"
- + "</RL>";
+ RuleSerializer xmlSerializer = new RuleXmlSerializer();
byte[] actualRules =
xmlSerializer.serialize(
- Arrays.asList(rule1, rule2), /* formatVersion= */ Optional.empty());
+ Arrays.asList(
+ installerRule,
+ getRuleWithAppCertificateAndSampleInstallerName(appCert1),
+ getRuleWithPackageNameAndSampleInstallerName(packageNameB),
+ getRuleWithAppCertificateAndSampleInstallerName(appCert3),
+ getRuleWithPackageNameAndSampleInstallerName(packageNameC),
+ getRuleWithAppCertificateAndSampleInstallerName(appCert2),
+ getRuleWithPackageNameAndSampleInstallerName(packageNameA)),
+ /* formatVersion= */ Optional.empty());
+
+ String expectedRules = "<RL>"
+ + getSerializedCompoundRuleWithPackageNameAndSampleInstallerName(packageNameA)
+ + getSerializedCompoundRuleWithPackageNameAndSampleInstallerName(packageNameB)
+ + getSerializedCompoundRuleWithPackageNameAndSampleInstallerName(packageNameC)
+ + getSerializedCompoundRuleWithAppCertificateAndSampleInstallerName(appCert1)
+ + getSerializedCompoundRuleWithAppCertificateAndSampleInstallerName(appCert2)
+ + getSerializedCompoundRuleWithAppCertificateAndSampleInstallerName(appCert3)
+ + getSerializedCompoundRuleWithSampleInstallerNameAndCert()
+ + "</RL>";
assertEquals(expectedRules, new String(actualRules, StandardCharsets.UTF_8));
}
@@ -371,7 +389,7 @@ public class RuleXmlSerializerTest {
assertExpectException(
RuleSerializeException.class,
- /* expectedExceptionMessageRegex */ "Invalid formula type",
+ /* expectedExceptionMessageRegex */ "Malformed rule identified.",
() ->
xmlSerializer.serialize(
Collections.singletonList(rule),
@@ -393,6 +411,124 @@ public class RuleXmlSerializerTest {
return res.toString();
}
+ private Rule getRuleWithPackageNameAndSampleInstallerName(String packageName) {
+ return new Rule(
+ new CompoundFormula(
+ CompoundFormula.AND,
+ Arrays.asList(
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME,
+ packageName,
+ /* isHashedValue= */ false),
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.INSTALLER_NAME,
+ SAMPLE_INSTALLER_NAME,
+ /* isHashedValue= */ false))),
+ Rule.DENY);
+ }
+
+ private String getSerializedCompoundRuleWithPackageNameAndSampleInstallerName(
+ String packageName) {
+
+ Map<String, String> packageNameAttrs = new LinkedHashMap<>();
+ packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
+ packageNameAttrs.put("V", packageName);
+ packageNameAttrs.put("H", "false");
+
+ Map<String, String> installerNameAttrs = new LinkedHashMap<>();
+ installerNameAttrs.put("K", String.valueOf(AtomicFormula.INSTALLER_NAME));
+ installerNameAttrs.put("V", SAMPLE_INSTALLER_NAME);
+ installerNameAttrs.put("H", "false");
+
+ return generateTagWithAttribute(
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(CompoundFormula.AND)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ + generateTagWithAttribute(
+ /* tag= */ "AF", installerNameAttrs, /* closed= */ true)
+ + "</OF>"
+ + "</R>";
+ }
+
+
+ private Rule getRuleWithAppCertificateAndSampleInstallerName(String certificate) {
+ return new Rule(
+ new CompoundFormula(
+ CompoundFormula.AND,
+ Arrays.asList(
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.APP_CERTIFICATE,
+ certificate,
+ /* isHashedValue= */ false),
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.INSTALLER_NAME,
+ SAMPLE_INSTALLER_NAME,
+ /* isHashedValue= */ false))),
+ Rule.DENY);
+ }
+
+ private String getSerializedCompoundRuleWithAppCertificateAndSampleInstallerName(
+ String appCert) {
+
+ Map<String, String> packageNameAttrs = new LinkedHashMap<>();
+ packageNameAttrs.put("K", String.valueOf(AtomicFormula.APP_CERTIFICATE));
+ packageNameAttrs.put("V", appCert);
+ packageNameAttrs.put("H", "false");
+
+ Map<String, String> installerNameAttrs = new LinkedHashMap<>();
+ installerNameAttrs.put("K", String.valueOf(AtomicFormula.INSTALLER_NAME));
+ installerNameAttrs.put("V", SAMPLE_INSTALLER_NAME);
+ installerNameAttrs.put("H", "false");
+
+ return generateTagWithAttribute(
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(CompoundFormula.AND)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ + generateTagWithAttribute(
+ /* tag= */ "AF", installerNameAttrs, /* closed= */ true)
+ + "</OF>"
+ + "</R>";
+ }
+
+ private String getSerializedCompoundRuleWithSampleInstallerNameAndCert() {
+ Map<String, String> installerNameAttrs = new LinkedHashMap<>();
+ installerNameAttrs.put("K", String.valueOf(AtomicFormula.INSTALLER_NAME));
+ installerNameAttrs.put("V", SAMPLE_INSTALLER_NAME);
+ installerNameAttrs.put("H", "false");
+
+ Map<String, String> installerCertAttrs = new LinkedHashMap<>();
+ installerCertAttrs.put("K", String.valueOf(AtomicFormula.INSTALLER_CERTIFICATE));
+ installerCertAttrs.put("V", SAMPLE_INSTALLER_CERT);
+ installerCertAttrs.put("H", "false");
+
+ return generateTagWithAttribute(
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(CompoundFormula.AND)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "AF", installerNameAttrs, /* closed= */ true)
+ + generateTagWithAttribute(
+ /* tag= */ "AF", installerCertAttrs, /* closed= */ true)
+ + "</OF>"
+ + "</R>";
+ }
+
private Formula getInvalidFormula() {
return new Formula() {
@Override
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
index d6ef2d459769..74570671226a 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
@@ -101,30 +101,6 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
return mService.getLong(SYNTHETIC_PASSWORD_HANDLE_KEY, 0, userId) != 0;
}
- @Test
- public void testPasswordMigration() throws RemoteException {
- final LockscreenCredential password = newPassword("testPasswordMigration-password");
-
- disableSyntheticPassword();
- assertTrue(mService.setLockCredential(password, nonePassword(), PRIMARY_USER_ID));
- long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
- final byte[] primaryStorageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
- enableSyntheticPassword();
- // Performs migration
- assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
- password, 0, PRIMARY_USER_ID)
- .getResponseCode());
- assertEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
- assertTrue(hasSyntheticPassword(PRIMARY_USER_ID));
-
- // SP-based verification
- assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
- password, 0, PRIMARY_USER_ID)
- .getResponseCode());
- assertArrayNotEquals(primaryStorageKey,
- mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
- }
-
protected void initializeCredentialUnderSP(LockscreenCredential password, int userId)
throws RemoteException {
enableSyntheticPassword();
@@ -253,81 +229,6 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
}
@Test
- public void testManagedProfileUnifiedChallengeMigration() throws RemoteException {
- LockscreenCredential UnifiedPassword = newPassword("unified-pwd");
- disableSyntheticPassword();
- mService.setLockCredential(UnifiedPassword, nonePassword(), PRIMARY_USER_ID);
- mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
- final long primarySid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
- final long profileSid = mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID);
- byte[] primaryStorageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
- byte[] profileStorageKey = mStorageManager.getUserUnlockToken(MANAGED_PROFILE_USER_ID);
- assertTrue(primarySid != 0);
- assertTrue(profileSid != 0);
- assertTrue(profileSid != primarySid);
-
- // do migration
- enableSyntheticPassword();
- assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
- UnifiedPassword, 0, PRIMARY_USER_ID)
- .getResponseCode());
-
- // verify
- assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
- UnifiedPassword, 0, PRIMARY_USER_ID)
- .getResponseCode());
- assertEquals(primarySid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
- assertEquals(profileSid, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID));
- assertArrayNotEquals(primaryStorageKey,
- mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
- assertArrayNotEquals(profileStorageKey,
- mStorageManager.getUserUnlockToken(MANAGED_PROFILE_USER_ID));
- assertTrue(hasSyntheticPassword(PRIMARY_USER_ID));
- assertTrue(hasSyntheticPassword(MANAGED_PROFILE_USER_ID));
- }
-
- @Test
- public void testManagedProfileSeparateChallengeMigration() throws RemoteException {
- LockscreenCredential primaryPassword = newPassword("primary");
- LockscreenCredential profilePassword = newPassword("profile");
- disableSyntheticPassword();
- mService.setLockCredential(primaryPassword, nonePassword(), PRIMARY_USER_ID);
- mService.setLockCredential(profilePassword, nonePassword(), MANAGED_PROFILE_USER_ID);
- final long primarySid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
- final long profileSid = mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID);
- byte[] primaryStorageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
- byte[] profileStorageKey = mStorageManager.getUserUnlockToken(MANAGED_PROFILE_USER_ID);
- assertTrue(primarySid != 0);
- assertTrue(profileSid != 0);
- assertTrue(profileSid != primarySid);
-
- // do migration
- enableSyntheticPassword();
- assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
- primaryPassword, 0, PRIMARY_USER_ID)
- .getResponseCode());
- assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
- profilePassword, 0, MANAGED_PROFILE_USER_ID)
- .getResponseCode());
-
- // verify
- assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
- primaryPassword, 0, PRIMARY_USER_ID)
- .getResponseCode());
- assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
- profilePassword, 0, MANAGED_PROFILE_USER_ID)
- .getResponseCode());
- assertEquals(primarySid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
- assertEquals(profileSid, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID));
- assertArrayNotEquals(primaryStorageKey,
- mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
- assertArrayNotEquals(profileStorageKey,
- mStorageManager.getUserUnlockToken(MANAGED_PROFILE_USER_ID));
- assertTrue(hasSyntheticPassword(PRIMARY_USER_ID));
- assertTrue(hasSyntheticPassword(MANAGED_PROFILE_USER_ID));
- }
-
- @Test
public void testTokenBasedResetPassword() throws RemoteException {
LockscreenCredential password = newPassword("password");
LockscreenCredential pattern = newPattern("123654");
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
index 545836e9d112..7529bc5cf639 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -124,6 +124,7 @@ import android.os.SystemClock;
import android.os.UserHandle;
import android.platform.test.annotations.Presubmit;
import android.telephony.CarrierConfigManager;
+import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.SubscriptionPlan;
import android.telephony.TelephonyManager;
@@ -261,7 +262,7 @@ public class NetworkPolicyManagerServiceTest {
private static final int USER_ID = 0;
private static final int FAKE_SUB_ID = 3737373;
- private static final String FAKE_SUBSCRIBER_ID = "FAKE_SUB_ID";
+ private static final String FAKE_SUBSCRIBER_ID = "FAKE_SUBSCRIBER_ID";
private static final int DEFAULT_CYCLE_DAY = 1;
private static final int INVALID_CARRIER_CONFIG_VALUE = -9999;
private long mDefaultWarningBytes; // filled in with the actual default before tests are run
@@ -1461,10 +1462,9 @@ public class NetworkPolicyManagerServiceTest {
private PersistableBundle setupUpdateMobilePolicyCycleTests() throws RemoteException {
when(mConnManager.getAllNetworkState()).thenReturn(new NetworkState[0]);
- when(mSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(new int[]{FAKE_SUB_ID});
- when(mTelephonyManager.getSubscriberId(FAKE_SUB_ID)).thenReturn(FAKE_SUBSCRIBER_ID);
- when(mTelephonyManager.createForSubscriptionId(FAKE_SUB_ID))
- .thenReturn(mock(TelephonyManager.class));
+
+ setupTelephonySubscriptionManagers(FAKE_SUB_ID, FAKE_SUBSCRIBER_ID);
+
PersistableBundle bundle = CarrierConfigManager.getDefaultConfig();
when(mCarrierConfigManager.getConfigForSubId(FAKE_SUB_ID)).thenReturn(bundle);
setNetworkPolicies(buildDefaultFakeMobilePolicy());
@@ -1474,10 +1474,9 @@ public class NetworkPolicyManagerServiceTest {
@Test
public void testUpdateMobilePolicyCycleWithNullConfig() throws RemoteException {
when(mConnManager.getAllNetworkState()).thenReturn(new NetworkState[0]);
- when(mSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(new int[]{FAKE_SUB_ID});
- when(mTelephonyManager.getSubscriberId(FAKE_SUB_ID)).thenReturn(FAKE_SUBSCRIBER_ID);
- when(mTelephonyManager.createForSubscriptionId(FAKE_SUB_ID))
- .thenReturn(mock(TelephonyManager.class));
+
+ setupTelephonySubscriptionManagers(FAKE_SUB_ID, FAKE_SUBSCRIBER_ID);
+
when(mCarrierConfigManager.getConfigForSubId(FAKE_SUB_ID)).thenReturn(null);
setNetworkPolicies(buildDefaultFakeMobilePolicy());
// smoke test to make sure no errors are raised
@@ -1930,11 +1929,7 @@ public class NetworkPolicyManagerServiceTest {
}
private void expectMobileDefaults() throws Exception {
- when(mSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(
- new int[] { TEST_SUB_ID });
- when(mTelephonyManager.getSubscriberId(TEST_SUB_ID)).thenReturn(TEST_IMSI);
- when(mTelephonyManager.createForSubscriptionId(TEST_SUB_ID))
- .thenReturn(mock(TelephonyManager.class));
+ setupTelephonySubscriptionManagers(TEST_SUB_ID, TEST_IMSI);
doNothing().when(mTelephonyManager).setPolicyDataEnabled(anyBoolean(), anyInt());
expectNetworkState(false /* roaming */);
}
@@ -2094,6 +2089,38 @@ public class NetworkPolicyManagerServiceTest {
}
/**
+ * Creates a mock {@link TelephonyManager} and {@link SubscriptionManager}.
+ */
+ private void setupTelephonySubscriptionManagers(int subscriptionId, String subscriberId) {
+ when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(
+ createSubscriptionInfoList(subscriptionId));
+
+ TelephonyManager subTelephonyManager;
+ subTelephonyManager = mock(TelephonyManager.class);
+ when(subTelephonyManager.getSubscriptionId()).thenReturn(subscriptionId);
+ when(subTelephonyManager.getSubscriberId()).thenReturn(subscriberId);
+ when(mTelephonyManager.createForSubscriptionId(subscriptionId))
+ .thenReturn(subTelephonyManager);
+ }
+
+ /**
+ * Creates mock {@link SubscriptionInfo} from subscription id.
+ */
+ private List<SubscriptionInfo> createSubscriptionInfoList(int subId) {
+ final List<SubscriptionInfo> sub = new ArrayList<>();
+ sub.add(createSubscriptionInfo(subId));
+ return sub;
+ }
+
+ /**
+ * Creates mock {@link SubscriptionInfo} from subscription id.
+ */
+ private SubscriptionInfo createSubscriptionInfo(int subId) {
+ return new SubscriptionInfo(subId, null, -1, null, null, -1, -1,
+ null, -1, null, null, null, null, false, null, null);
+ }
+
+ /**
* Custom Mockito answer used to verify async {@link INetworkPolicyListener} calls.
*
* <p>Typical usage:
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageVerificationStateTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageVerificationStateTest.java
index ebd363386fa3..1fff4f084fc4 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageVerificationStateTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageVerificationStateTest.java
@@ -17,8 +17,7 @@
package com.android.server.pm;
import android.content.pm.PackageManager;
-import com.android.server.pm.PackageVerificationState;
-
+import android.content.pm.PackageManagerInternal;
import android.test.AndroidTestCase;
public class PackageVerificationStateTest extends AndroidTestCase {
@@ -29,7 +28,8 @@ public class PackageVerificationStateTest extends AndroidTestCase {
private static final int SUFFICIENT_UID_2 = 8938;
public void testPackageVerificationState_OnlyRequiredVerifier_AllowedInstall() {
- PackageVerificationState state = new PackageVerificationState(REQUIRED_UID, null);
+ PackageVerificationState state = new PackageVerificationState(null);
+ state.setRequiredVerifierUid(REQUIRED_UID);
assertFalse("Verification should not be marked as complete yet",
state.isVerificationComplete());
@@ -44,7 +44,8 @@ public class PackageVerificationStateTest extends AndroidTestCase {
}
public void testPackageVerificationState_OnlyRequiredVerifier_DeniedInstall() {
- PackageVerificationState state = new PackageVerificationState(REQUIRED_UID, null);
+ PackageVerificationState state = new PackageVerificationState(null);
+ state.setRequiredVerifierUid(REQUIRED_UID);
assertFalse("Verification should not be marked as complete yet",
state.isVerificationComplete());
@@ -59,7 +60,8 @@ public class PackageVerificationStateTest extends AndroidTestCase {
}
public void testPackageVerificationState_RequiredAndOneSufficient_RequiredDeniedInstall() {
- PackageVerificationState state = new PackageVerificationState(REQUIRED_UID, null);
+ PackageVerificationState state = new PackageVerificationState(null);
+ state.setRequiredVerifierUid(REQUIRED_UID);
assertFalse("Verification should not be marked as complete yet",
state.isVerificationComplete());
@@ -84,7 +86,8 @@ public class PackageVerificationStateTest extends AndroidTestCase {
}
public void testPackageVerificationState_RequiredAndOneSufficient_SufficientDeniedInstall() {
- PackageVerificationState state = new PackageVerificationState(REQUIRED_UID, null);
+ PackageVerificationState state = new PackageVerificationState(null);
+ state.setRequiredVerifierUid(REQUIRED_UID);
assertFalse("Verification should not be marked as complete yet",
state.isVerificationComplete());
@@ -109,7 +112,8 @@ public class PackageVerificationStateTest extends AndroidTestCase {
}
public void testPackageVerificationState_RequiredAndTwoSufficient_OneSufficientIsEnough() {
- PackageVerificationState state = new PackageVerificationState(REQUIRED_UID, null);
+ PackageVerificationState state = new PackageVerificationState(null);
+ state.setRequiredVerifierUid(REQUIRED_UID);
assertFalse("Verification should not be marked as complete yet",
state.isVerificationComplete());
@@ -135,7 +139,8 @@ public class PackageVerificationStateTest extends AndroidTestCase {
}
public void testPackageVerificationState_RequiredAndTwoSufficient_SecondSufficientIsEnough() {
- PackageVerificationState state = new PackageVerificationState(REQUIRED_UID, null);
+ PackageVerificationState state = new PackageVerificationState(null);
+ state.setRequiredVerifierUid(REQUIRED_UID);
assertFalse("Verification should not be marked as complete yet",
state.isVerificationComplete());
@@ -166,7 +171,8 @@ public class PackageVerificationStateTest extends AndroidTestCase {
}
public void testPackageVerificationState_RequiredAndTwoSufficient_RequiredOverrides() {
- PackageVerificationState state = new PackageVerificationState(REQUIRED_UID, null);
+ PackageVerificationState state = new PackageVerificationState(null);
+ state.setRequiredVerifierUid(REQUIRED_UID);
assertFalse("Verification should not be marked as complete yet",
state.isVerificationComplete());
@@ -202,4 +208,55 @@ public class PackageVerificationStateTest extends AndroidTestCase {
assertTrue("Installation should be marked as allowed still",
state.isInstallAllowed());
}
+
+ public void testAreAllVerificationsComplete_onlyVerificationPasses() {
+ PackageVerificationState state = new PackageVerificationState(null);
+ state.setRequiredVerifierUid(REQUIRED_UID);
+ assertFalse(state.areAllVerificationsComplete());
+
+ state.setVerifierResponse(REQUIRED_UID, PackageManager.VERIFICATION_ALLOW);
+
+ assertFalse(state.areAllVerificationsComplete());
+ }
+
+ public void testAreAllVerificationsComplete_onlyIntegrityCheckPasses() {
+ PackageVerificationState state = new PackageVerificationState(null);
+ state.setRequiredVerifierUid(REQUIRED_UID);
+ assertFalse(state.areAllVerificationsComplete());
+
+ state.setIntegrityVerificationResult(PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
+
+ assertFalse(state.areAllVerificationsComplete());
+ }
+
+ public void testAreAllVerificationsComplete_bothPasses() {
+ PackageVerificationState state = new PackageVerificationState(null);
+ state.setRequiredVerifierUid(REQUIRED_UID);
+ assertFalse(state.areAllVerificationsComplete());
+
+ state.setIntegrityVerificationResult(PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
+ state.setVerifierResponse(REQUIRED_UID, PackageManager.VERIFICATION_ALLOW);
+
+ assertTrue(state.areAllVerificationsComplete());
+ }
+
+ public void testAreAllVerificationsComplete_onlyVerificationFails() {
+ PackageVerificationState state = new PackageVerificationState(null);
+ state.setRequiredVerifierUid(REQUIRED_UID);
+ assertFalse(state.areAllVerificationsComplete());
+
+ state.setVerifierResponse(REQUIRED_UID, PackageManager.VERIFICATION_REJECT);
+
+ assertFalse(state.areAllVerificationsComplete());
+ }
+
+ public void testAreAllVerificationsComplete_onlyIntegrityCheckFails() {
+ PackageVerificationState state = new PackageVerificationState(null);
+ state.setRequiredVerifierUid(REQUIRED_UID);
+ assertFalse(state.areAllVerificationsComplete());
+
+ state.setIntegrityVerificationResult(PackageManagerInternal.INTEGRITY_VERIFICATION_REJECT);
+
+ assertFalse(state.areAllVerificationsComplete());
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index b3f1bcd6c3ad..06b3dc1d9deb 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -16,6 +16,12 @@
package com.android.server.pm;
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
+
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.content.BroadcastReceiver;
@@ -29,15 +35,21 @@ import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
-import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.LargeTest;
import android.test.suitebuilder.annotation.MediumTest;
import android.test.suitebuilder.annotation.SmallTest;
-import com.android.internal.util.ArrayUtils;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.google.common.collect.Range;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -45,7 +57,8 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/** Test {@link UserManager} functionality. */
-public class UserManagerTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+public final class UserManagerTest {
// Taken from UserManagerService
private static final long EPOCH_PLUS_30_YEARS = 30L * 365 * 24 * 60 * 60 * 1000L; // 30 years
@@ -58,6 +71,8 @@ public class UserManagerTest extends AndroidTestCase {
"com.android.egg"
};
+ private final Context mContext = InstrumentationRegistry.getInstrumentation().getContext();
+
private final Object mUserRemoveLock = new Object();
private final Object mUserSwitchLock = new Object();
@@ -65,15 +80,14 @@ public class UserManagerTest extends AndroidTestCase {
private PackageManager mPackageManager;
private List<Integer> usersToRemove;
- @Override
+ @Before
public void setUp() throws Exception {
- super.setUp();
- mUserManager = UserManager.get(getContext());
- mPackageManager = getContext().getPackageManager();
+ mUserManager = UserManager.get(mContext);
+ mPackageManager = mContext.getPackageManager();
IntentFilter filter = new IntentFilter(Intent.ACTION_USER_REMOVED);
filter.addAction(Intent.ACTION_USER_SWITCHED);
- getContext().registerReceiver(new BroadcastReceiver() {
+ mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
switch (intent.getAction()) {
@@ -95,36 +109,35 @@ public class UserManagerTest extends AndroidTestCase {
usersToRemove = new ArrayList<>();
}
- @Override
- protected void tearDown() throws Exception {
+ @After
+ public void tearDown() throws Exception {
for (Integer userId : usersToRemove) {
removeUser(userId);
}
- super.tearDown();
}
private void removeExistingUsers() {
+ int currentUser = ActivityManager.getCurrentUser();
List<UserInfo> list = mUserManager.getUsers();
for (UserInfo user : list) {
- // Keep system and primary user.
- // We do not have to keep primary user, but in split system user mode, we need it
- // until http://b/22976637 is fixed. Right now in split system user mode, you need to
- // switch to primary user and run tests under primary user.
- if (user.id != UserHandle.USER_SYSTEM && !user.isPrimary()) {
+ // Keep system and current user
+ if (user.id != UserHandle.USER_SYSTEM && user.id != currentUser) {
removeUser(user.id);
}
}
}
@SmallTest
+ @Test
public void testHasSystemUser() throws Exception {
- assertTrue(findUser(UserHandle.USER_SYSTEM));
+ assertThat(findUser(UserHandle.USER_SYSTEM)).isTrue();
}
@MediumTest
- public void testAddUser() throws Exception {
+ @Test
+ public void testAddGuest() throws Exception {
UserInfo userInfo = createUser("Guest 1", UserInfo.FLAG_GUEST);
- assertTrue(userInfo != null);
+ assertThat(userInfo).isNotNull();
List<UserInfo> list = mUserManager.getUsers();
boolean found = false;
@@ -135,35 +148,39 @@ public class UserManagerTest extends AndroidTestCase {
&& !user.isPrimary()) {
found = true;
Bundle restrictions = mUserManager.getUserRestrictions(user.getUserHandle());
- assertTrue("Guest user should have DISALLOW_CONFIG_WIFI=true by default",
- restrictions.getBoolean(UserManager.DISALLOW_CONFIG_WIFI));
+ assertWithMessage("Guest user should have DISALLOW_CONFIG_WIFI=true by default")
+ .that(restrictions.getBoolean(UserManager.DISALLOW_CONFIG_WIFI))
+ .isTrue();
}
}
- assertTrue(found);
+ assertThat(found).isTrue();
}
@MediumTest
+ @Test
public void testAdd2Users() throws Exception {
UserInfo user1 = createUser("Guest 1", UserInfo.FLAG_GUEST);
UserInfo user2 = createUser("User 2", UserInfo.FLAG_ADMIN);
- assertTrue(user1 != null);
- assertTrue(user2 != null);
+ assertThat(user1).isNotNull();
+ assertThat(user2).isNotNull();
- assertTrue(findUser(0));
- assertTrue(findUser(user1.id));
- assertTrue(findUser(user2.id));
+ assertThat(findUser(UserHandle.USER_SYSTEM)).isTrue();
+ assertThat(findUser(user1.id)).isTrue();
+ assertThat(findUser(user2.id)).isTrue();
}
@MediumTest
+ @Test
public void testRemoveUser() throws Exception {
UserInfo userInfo = createUser("Guest 1", UserInfo.FLAG_GUEST);
removeUser(userInfo.id);
- assertFalse(findUser(userInfo.id));
+ assertThat(findUser(userInfo.id)).isFalse();
}
@MediumTest
+ @Test
public void testRemoveUserByHandle() {
UserInfo userInfo = createUser("Guest 1", UserInfo.FLAG_GUEST);
final UserHandle user = userInfo.getUserHandle();
@@ -183,10 +200,11 @@ public class UserManagerTest extends AndroidTestCase {
}
}
- assertFalse(findUser(userInfo.id));
+ assertThat(findUser(userInfo.id)).isFalse();
}
@MediumTest
+ @Test
public void testRemoveUserByHandle_ThrowsException() {
synchronized (mUserRemoveLock) {
try {
@@ -200,6 +218,7 @@ public class UserManagerTest extends AndroidTestCase {
/** Tests creating a FULL user via specifying userType. */
@MediumTest
+ @Test
public void testCreateUserViaTypes() throws Exception {
createUserWithTypeAndCheckFlags(UserManager.USER_TYPE_FULL_GUEST,
UserInfo.FLAG_GUEST | UserInfo.FLAG_FULL);
@@ -213,6 +232,7 @@ public class UserManagerTest extends AndroidTestCase {
/** Tests creating a FULL user via specifying user flags. */
@MediumTest
+ @Test
public void testCreateUserViaFlags() throws Exception {
createUserWithFlagsAndCheckType(UserInfo.FLAG_GUEST, UserManager.USER_TYPE_FULL_GUEST,
UserInfo.FLAG_FULL);
@@ -231,10 +251,9 @@ public class UserManagerTest extends AndroidTestCase {
private void createUserWithTypeAndCheckFlags(String userType,
@UserIdInt int requiredFlags) {
final UserInfo userInfo = createUser("Name", userType, 0);
- assertEquals("Wrong user type", userType, userInfo.userType);
- assertEquals(
- "Flags " + userInfo.flags + " did not contain expected " + requiredFlags,
- requiredFlags, userInfo.flags & requiredFlags);
+ assertWithMessage("Wrong user type").that(userInfo.userType).isEqualTo(userType);
+ assertWithMessage("Flags %s did not contain expected %s", userInfo.flags, requiredFlags)
+ .that(userInfo.flags & requiredFlags).isEqualTo(requiredFlags);
removeUser(userInfo.id);
}
@@ -245,131 +264,140 @@ public class UserManagerTest extends AndroidTestCase {
private void createUserWithFlagsAndCheckType(@UserIdInt int flags, String expectedUserType,
@UserIdInt int additionalRequiredFlags) {
final UserInfo userInfo = createUser("Name", flags);
- assertEquals("Wrong user type", expectedUserType, userInfo.userType);
+ assertWithMessage("Wrong user type").that(userInfo.userType).isEqualTo(expectedUserType);
additionalRequiredFlags |= flags;
- assertEquals(
- "Flags " + userInfo.flags + " did not contain expected " + additionalRequiredFlags,
- additionalRequiredFlags, userInfo.flags & additionalRequiredFlags);
+ assertWithMessage("Flags %s did not contain expected %s", userInfo.flags,
+ additionalRequiredFlags).that(userInfo.flags & additionalRequiredFlags)
+ .isEqualTo(additionalRequiredFlags);
removeUser(userInfo.id);
}
@MediumTest
- public void testAddGuest() throws Exception {
+ @Test
+ public void testThereCanBeOnlyOneGuest() throws Exception {
UserInfo userInfo1 = createUser("Guest 1", UserInfo.FLAG_GUEST);
+ assertThat(userInfo1).isNotNull();
UserInfo userInfo2 = createUser("Guest 2", UserInfo.FLAG_GUEST);
- assertNotNull(userInfo1);
- assertNull(userInfo2);
+ assertThat(userInfo2).isNull();
}
@MediumTest
+ @Test
public void testFindExistingGuest_guestExists() throws Exception {
UserInfo userInfo1 = createUser("Guest", UserInfo.FLAG_GUEST);
+ assertThat(userInfo1).isNotNull();
UserInfo foundGuest = mUserManager.findCurrentGuestUser();
- assertNotNull(foundGuest);
+ assertThat(foundGuest).isNotNull();
}
@SmallTest
+ @Test
public void testFindExistingGuest_guestDoesNotExist() throws Exception {
UserInfo foundGuest = mUserManager.findCurrentGuestUser();
- assertNull(foundGuest);
+ assertThat(foundGuest).isNull();
}
@MediumTest
+ @Test
public void testSetUserAdmin() throws Exception {
UserInfo userInfo = createUser("SecondaryUser", /*flags=*/ 0);
- assertFalse(userInfo.isAdmin());
+ assertThat(userInfo.isAdmin()).isFalse();
mUserManager.setUserAdmin(userInfo.id);
userInfo = mUserManager.getUserInfo(userInfo.id);
- assertTrue(userInfo.isAdmin());
+ assertThat(userInfo.isAdmin()).isTrue();
}
@MediumTest
+ @Test
public void testGetProfileParent() throws Exception {
+ assumeManagedUsersSupported();
final int primaryUserId = mUserManager.getPrimaryUser().id;
UserInfo userInfo = createProfileForUser("Profile",
UserManager.USER_TYPE_PROFILE_MANAGED, primaryUserId);
- assertNotNull(userInfo);
- assertNull(mUserManager.getProfileParent(primaryUserId));
+ assertThat(userInfo).isNotNull();
+ assertThat(mUserManager.getProfileParent(primaryUserId)).isNull();
UserInfo parentProfileInfo = mUserManager.getProfileParent(userInfo.id);
- assertNotNull(parentProfileInfo);
- assertEquals(parentProfileInfo.id, primaryUserId);
+ assertThat(parentProfileInfo).isNotNull();
+ assertThat(primaryUserId).isEqualTo(parentProfileInfo.id);
removeUser(userInfo.id);
- assertNull(mUserManager.getProfileParent(primaryUserId));
+ assertThat(mUserManager.getProfileParent(primaryUserId)).isNull();
}
/** Test that UserManager returns the correct badge information for a managed profile. */
@MediumTest
+ @Test
public void testProfileTypeInformation() throws Exception {
+ assumeManagedUsersSupported();
final UserTypeDetails userTypeDetails =
UserTypeFactory.getUserTypes().get(UserManager.USER_TYPE_PROFILE_MANAGED);
- assertNotNull("No " + UserManager.USER_TYPE_PROFILE_MANAGED + " type on device",
- userTypeDetails);
- assertEquals(UserManager.USER_TYPE_PROFILE_MANAGED, userTypeDetails.getName());
+ assertWithMessage("No %s type on device", UserManager.USER_TYPE_PROFILE_MANAGED)
+ .that(userTypeDetails).isNotNull();
+ assertThat(userTypeDetails.getName()).isEqualTo(UserManager.USER_TYPE_PROFILE_MANAGED);
final int primaryUserId = mUserManager.getPrimaryUser().id;
UserInfo userInfo = createProfileForUser("Managed",
UserManager.USER_TYPE_PROFILE_MANAGED, primaryUserId);
- assertNotNull(userInfo);
+ assertThat(userInfo).isNotNull();
final int userId = userInfo.id;
final UserHandle userHandle = new UserHandle(userId);
- assertEquals(userTypeDetails.hasBadge(),
- mUserManager.hasBadge(userId));
- assertEquals(userTypeDetails.getIconBadge(),
- mUserManager.getUserIconBadgeResId(userId));
- assertEquals(userTypeDetails.getBadgePlain(),
- mUserManager.getUserBadgeResId(userId));
- assertEquals(userTypeDetails.getBadgeNoBackground(),
- mUserManager.getUserBadgeNoBackgroundResId(userId));
- assertEquals(userTypeDetails.isProfile(),
- mUserManager.isProfile(userId));
- assertEquals(userTypeDetails.getName(),
- mUserManager.getUserTypeForUser(userHandle));
+ assertThat(mUserManager.hasBadge(userId)).isEqualTo(userTypeDetails.hasBadge());
+ assertThat(mUserManager.getUserIconBadgeResId(userId))
+ .isEqualTo(userTypeDetails.getIconBadge());
+ assertThat(mUserManager.getUserBadgeResId(userId))
+ .isEqualTo(userTypeDetails.getBadgePlain());
+ assertThat(mUserManager.getUserBadgeNoBackgroundResId(userId))
+ .isEqualTo(userTypeDetails.getBadgeNoBackground());
+ assertThat(mUserManager.isProfile(userId)).isEqualTo(userTypeDetails.isProfile());
+ assertThat(mUserManager.getUserTypeForUser(userHandle))
+ .isEqualTo(userTypeDetails.getName());
final int badgeIndex = userInfo.profileBadge;
- assertEquals(
- Resources.getSystem().getColor(userTypeDetails.getBadgeColor(badgeIndex), null),
- mUserManager.getUserBadgeColor(userId));
- assertEquals(
- Resources.getSystem().getString(userTypeDetails.getBadgeLabel(badgeIndex), "Test"),
- mUserManager.getBadgedLabelForUser("Test", userHandle));
+ assertThat(mUserManager.getUserBadgeColor(userId)).isEqualTo(
+ Resources.getSystem().getColor(userTypeDetails.getBadgeColor(badgeIndex), null));
+ assertThat(mUserManager.getBadgedLabelForUser("Test", userHandle)).isEqualTo(
+ Resources.getSystem().getString(userTypeDetails.getBadgeLabel(badgeIndex), "Test"));
}
// Make sure only one managed profile can be created
@MediumTest
+ @Test
public void testAddManagedProfile() throws Exception {
+ assumeManagedUsersSupported();
final int primaryUserId = mUserManager.getPrimaryUser().id;
UserInfo userInfo1 = createProfileForUser("Managed 1",
UserManager.USER_TYPE_PROFILE_MANAGED, primaryUserId);
UserInfo userInfo2 = createProfileForUser("Managed 2",
UserManager.USER_TYPE_PROFILE_MANAGED, primaryUserId);
- assertNotNull(userInfo1);
- assertNull(userInfo2);
+ assertThat(userInfo1).isNotNull();
+ assertThat(userInfo2).isNull();
- assertEquals(userInfo1.userType, UserManager.USER_TYPE_PROFILE_MANAGED);
+ assertThat(userInfo1.userType).isEqualTo(UserManager.USER_TYPE_PROFILE_MANAGED);
int requiredFlags = UserInfo.FLAG_MANAGED_PROFILE | UserInfo.FLAG_PROFILE;
- assertEquals("Wrong flags " + userInfo1.flags, requiredFlags,
- userInfo1.flags & requiredFlags);
+ assertWithMessage("Wrong flags %s", userInfo1.flags).that(userInfo1.flags & requiredFlags)
+ .isEqualTo(requiredFlags);
// Verify that current user is not a managed profile
- assertFalse(mUserManager.isManagedProfile());
+ assertThat(mUserManager.isManagedProfile()).isFalse();
}
// Verify that disallowed packages are not installed in the managed profile.
@MediumTest
+ @Test
public void testAddManagedProfile_withDisallowedPackages() throws Exception {
+ assumeManagedUsersSupported();
final int primaryUserId = mUserManager.getPrimaryUser().id;
UserInfo userInfo1 = createProfileForUser("Managed1",
UserManager.USER_TYPE_PROFILE_MANAGED, primaryUserId);
// Verify that the packagesToVerify are installed by default.
for (String pkg : PACKAGES) {
- assertTrue("Package should be installed in managed profile: " + pkg,
- isPackageInstalledForUser(pkg, userInfo1.id));
+ assertWithMessage("Package should be installed in managed profile: %s", pkg)
+ .that(isPackageInstalledForUser(pkg, userInfo1.id)).isTrue();
}
removeUser(userInfo1.id);
@@ -377,50 +405,57 @@ public class UserManagerTest extends AndroidTestCase {
UserManager.USER_TYPE_PROFILE_MANAGED, primaryUserId, PACKAGES);
// Verify that the packagesToVerify are not installed by default.
for (String pkg : PACKAGES) {
- assertFalse("Package should not be installed in managed profile when disallowed: "
- + pkg, isPackageInstalledForUser(pkg, userInfo2.id));
+ assertWithMessage(
+ "Package should not be installed in managed profile when disallowed: %s", pkg)
+ .that(isPackageInstalledForUser(pkg, userInfo2.id)).isFalse();
}
}
// Verify that if any packages are disallowed to install during creation of managed profile can
// still be installed later.
@MediumTest
+ @Test
public void testAddManagedProfile_disallowedPackagesInstalledLater() throws Exception {
+ assumeManagedUsersSupported();
final int primaryUserId = mUserManager.getPrimaryUser().id;
UserInfo userInfo = createProfileForUser("Managed",
UserManager.USER_TYPE_PROFILE_MANAGED, primaryUserId, PACKAGES);
// Verify that the packagesToVerify are not installed by default.
for (String pkg : PACKAGES) {
- assertFalse("Package should not be installed in managed profile when disallowed: "
- + pkg, isPackageInstalledForUser(pkg, userInfo.id));
+ assertWithMessage("Pkg should not be installed in managed profile when disallowed: %s",
+ pkg).that(isPackageInstalledForUser(pkg, userInfo.id)).isFalse();
}
// Verify that the disallowed packages during profile creation can be installed now.
for (String pkg : PACKAGES) {
- assertEquals("Package could not be installed: " + pkg,
- PackageManager.INSTALL_SUCCEEDED,
- mPackageManager.installExistingPackageAsUser(pkg, userInfo.id));
+ assertWithMessage("Package could not be installed: %s", pkg)
+ .that(mPackageManager.installExistingPackageAsUser(pkg, userInfo.id))
+ .isEqualTo(PackageManager.INSTALL_SUCCEEDED);
}
}
// Make sure createUser would fail if we have DISALLOW_ADD_USER.
@MediumTest
+ @Test
public void testCreateUser_disallowAddUser() throws Exception {
- final int primaryUserId = mUserManager.getPrimaryUser().id;
- final UserHandle primaryUserHandle = new UserHandle(primaryUserId);
- mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_USER, true, primaryUserHandle);
+ final int creatorId = isAutomotive() ? ActivityManager.getCurrentUser()
+ : mUserManager.getPrimaryUser().id;
+ final UserHandle creatorHandle = new UserHandle(creatorId);
+ mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_USER, true, creatorHandle);
try {
- UserInfo userInfo = createUser("SecondaryUser", /*flags=*/ 0);
- assertNull(userInfo);
+ UserInfo createadInfo = createUser("SecondaryUser", /*flags=*/ 0);
+ assertThat(createadInfo).isNull();
} finally {
mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_USER, false,
- primaryUserHandle);
+ creatorHandle);
}
}
// Make sure createProfile would fail if we have DISALLOW_ADD_MANAGED_PROFILE.
@MediumTest
+ @Test
public void testCreateProfileForUser_disallowAddManagedProfile() throws Exception {
+ assumeManagedUsersSupported();
final int primaryUserId = mUserManager.getPrimaryUser().id;
final UserHandle primaryUserHandle = new UserHandle(primaryUserId);
mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_MANAGED_PROFILE, true,
@@ -428,7 +463,7 @@ public class UserManagerTest extends AndroidTestCase {
try {
UserInfo userInfo = createProfileForUser("Managed",
UserManager.USER_TYPE_PROFILE_MANAGED, primaryUserId);
- assertNull(userInfo);
+ assertThat(userInfo).isNull();
} finally {
mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_MANAGED_PROFILE, false,
primaryUserHandle);
@@ -437,7 +472,9 @@ public class UserManagerTest extends AndroidTestCase {
// Make sure createProfileEvenWhenDisallowedForUser bypass DISALLOW_ADD_MANAGED_PROFILE.
@MediumTest
+ @Test
public void testCreateProfileForUserEvenWhenDisallowed() throws Exception {
+ assumeManagedUsersSupported();
final int primaryUserId = mUserManager.getPrimaryUser().id;
final UserHandle primaryUserHandle = new UserHandle(primaryUserId);
mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_MANAGED_PROFILE, true,
@@ -445,7 +482,7 @@ public class UserManagerTest extends AndroidTestCase {
try {
UserInfo userInfo = createProfileEvenWhenDisallowedForUser("Managed",
UserManager.USER_TYPE_PROFILE_MANAGED, primaryUserId);
- assertNotNull(userInfo);
+ assertThat(userInfo).isNotNull();
} finally {
mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_MANAGED_PROFILE, false,
primaryUserHandle);
@@ -454,14 +491,16 @@ public class UserManagerTest extends AndroidTestCase {
// createProfile succeeds even if DISALLOW_ADD_USER is set
@MediumTest
+ @Test
public void testCreateProfileForUser_disallowAddUser() throws Exception {
+ assumeManagedUsersSupported();
final int primaryUserId = mUserManager.getPrimaryUser().id;
final UserHandle primaryUserHandle = new UserHandle(primaryUserId);
mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_USER, true, primaryUserHandle);
try {
UserInfo userInfo = createProfileForUser("Managed",
UserManager.USER_TYPE_PROFILE_MANAGED, primaryUserId);
- assertNotNull(userInfo);
+ assertThat(userInfo).isNotNull();
} finally {
mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_USER, false,
primaryUserHandle);
@@ -469,73 +508,85 @@ public class UserManagerTest extends AndroidTestCase {
}
@MediumTest
+ @Test
public void testAddRestrictedProfile() throws Exception {
- assertFalse("There should be no associated restricted profiles before the test",
- mUserManager.hasRestrictedProfiles());
+ if (isAutomotive()) return;
+ assertWithMessage("There should be no associated restricted profiles before the test")
+ .that(mUserManager.hasRestrictedProfiles()).isFalse();
UserInfo userInfo = createRestrictedProfile("Profile");
- assertNotNull(userInfo);
+ assertThat(userInfo).isNotNull();
Bundle restrictions = mUserManager.getUserRestrictions(UserHandle.of(userInfo.id));
- assertTrue("Restricted profile should have DISALLOW_MODIFY_ACCOUNTS restriction by default",
- restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS));
- assertTrue("Restricted profile should have DISALLOW_SHARE_LOCATION restriction by default",
- restrictions.getBoolean(UserManager.DISALLOW_SHARE_LOCATION));
-
- int locationMode = Settings.Secure.getIntForUser(getContext().getContentResolver(),
+ assertWithMessage(
+ "Restricted profile should have DISALLOW_MODIFY_ACCOUNTS restriction by default")
+ .that(restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS))
+ .isTrue();
+ assertWithMessage(
+ "Restricted profile should have DISALLOW_SHARE_LOCATION restriction by default")
+ .that(restrictions.getBoolean(UserManager.DISALLOW_SHARE_LOCATION))
+ .isTrue();
+
+ int locationMode = Settings.Secure.getIntForUser(mContext.getContentResolver(),
Settings.Secure.LOCATION_MODE,
Settings.Secure.LOCATION_MODE_HIGH_ACCURACY,
userInfo.id);
- assertEquals("Restricted profile should have setting LOCATION_MODE set to "
- + "LOCATION_MODE_OFF by default", locationMode, Settings.Secure.LOCATION_MODE_OFF);
+ assertWithMessage("Restricted profile should have setting LOCATION_MODE set to "
+ + "LOCATION_MODE_OFF by default").that(locationMode)
+ .isEqualTo(Settings.Secure.LOCATION_MODE_OFF);
- assertTrue("Newly created profile should be associated with the current user",
- mUserManager.hasRestrictedProfiles());
+ assertWithMessage("Newly created profile should be associated with the current user")
+ .that(mUserManager.hasRestrictedProfiles()).isTrue();
}
@MediumTest
+ @Test
public void testGetUserCreationTime() throws Exception {
+ // TODO: should add a regular user instead of a profile, so it can be tested everywhere
+ assumeManagedUsersSupported();
final int primaryUserId = mUserManager.getPrimaryUser().id;
final long startTime = System.currentTimeMillis();
UserInfo profile = createProfileForUser("Managed 1",
UserManager.USER_TYPE_PROFILE_MANAGED, primaryUserId);
final long endTime = System.currentTimeMillis();
- assertNotNull(profile);
+ assertThat(profile).isNotNull();
if (System.currentTimeMillis() > EPOCH_PLUS_30_YEARS) {
- assertTrue("creationTime must be set when the profile is created",
- profile.creationTime >= startTime && profile.creationTime <= endTime);
+ assertWithMessage("creationTime must be set when the profile is created")
+ .that(profile.creationTime).isIn(Range.closed(startTime, endTime));
} else {
- assertTrue("creationTime must be 0 if the time is not > EPOCH_PLUS_30_years",
- profile.creationTime == 0);
+ assertWithMessage("creationTime must be 0 if the time is not > EPOCH_PLUS_30_years")
+ .that(profile.creationTime).isEqualTo(0);
}
- assertEquals(profile.creationTime, mUserManager.getUserCreationTime(
- new UserHandle(profile.id)));
+ assertThat(mUserManager.getUserCreationTime(
+ new UserHandle(profile.id))).isEqualTo(profile.creationTime);
long ownerCreationTime = mUserManager.getUserInfo(primaryUserId).creationTime;
- assertEquals(ownerCreationTime, mUserManager.getUserCreationTime(
- new UserHandle(primaryUserId)));
+ assertThat(mUserManager.getUserCreationTime(
+ new UserHandle(primaryUserId))).isEqualTo(ownerCreationTime);
}
@SmallTest
+ @Test
public void testGetUserCreationTime_nonExistentUser() throws Exception {
try {
int noSuchUserId = 100500;
mUserManager.getUserCreationTime(new UserHandle(noSuchUserId));
fail("SecurityException should be thrown for nonexistent user");
} catch (Exception e) {
- assertTrue("SecurityException should be thrown for nonexistent user, but was: " + e,
- e instanceof SecurityException);
+ assertWithMessage("SecurityException should be thrown for nonexistent user").that(e)
+ .isInstanceOf(SecurityException.class);
}
}
@SmallTest
+ @Test
public void testGetUserCreationTime_otherUser() throws Exception {
UserInfo user = createUser("User 1", 0);
try {
mUserManager.getUserCreationTime(new UserHandle(user.id));
fail("SecurityException should be thrown for other user");
} catch (Exception e) {
- assertTrue("SecurityException should be thrown for other user, but was: " + e,
- e instanceof SecurityException);
+ assertWithMessage("SecurityException should be thrown for other user").that(e)
+ .isInstanceOf(SecurityException.class);
}
}
@@ -551,56 +602,58 @@ public class UserManagerTest extends AndroidTestCase {
}
@MediumTest
+ @Test
public void testSerialNumber() {
UserInfo user1 = createUser("User 1", 0);
int serialNumber1 = user1.serialNumber;
- assertEquals(serialNumber1, mUserManager.getUserSerialNumber(user1.id));
- assertEquals(user1.id, mUserManager.getUserHandle(serialNumber1));
+ assertThat(mUserManager.getUserSerialNumber(user1.id)).isEqualTo(serialNumber1);
+ assertThat(mUserManager.getUserHandle(serialNumber1)).isEqualTo(user1.id);
UserInfo user2 = createUser("User 2", 0);
int serialNumber2 = user2.serialNumber;
- assertFalse(serialNumber1 == serialNumber2);
- assertEquals(serialNumber2, mUserManager.getUserSerialNumber(user2.id));
- assertEquals(user2.id, mUserManager.getUserHandle(serialNumber2));
+ assertThat(serialNumber1 == serialNumber2).isFalse();
+ assertThat(mUserManager.getUserSerialNumber(user2.id)).isEqualTo(serialNumber2);
+ assertThat(mUserManager.getUserHandle(serialNumber2)).isEqualTo(user2.id);
}
@MediumTest
+ @Test
public void testGetSerialNumbersOfUsers() {
UserInfo user1 = createUser("User 1", 0);
UserInfo user2 = createUser("User 2", 0);
long[] serialNumbersOfUsers = mUserManager.getSerialNumbersOfUsers(false);
- String errMsg = "Array " + Arrays.toString(serialNumbersOfUsers) + " should contain ";
- assertTrue(errMsg + user1.serialNumber,
- ArrayUtils.contains(serialNumbersOfUsers, user1.serialNumber));
- assertTrue(errMsg + user2.serialNumber,
- ArrayUtils.contains(serialNumbersOfUsers, user2.serialNumber));
+ assertThat(serialNumbersOfUsers).asList().containsAllOf(
+ (long) user1.serialNumber, (long) user2.serialNumber);
}
@MediumTest
+ @Test
public void testMaxUsers() {
int N = UserManager.getMaxSupportedUsers();
int count = mUserManager.getUsers().size();
// Create as many users as permitted and make sure creation passes
while (count < N) {
UserInfo ui = createUser("User " + count, 0);
- assertNotNull(ui);
+ assertThat(ui).isNotNull();
count++;
}
// Try to create one more user and make sure it fails
UserInfo extra = createUser("One more", 0);
- assertNull(extra);
+ assertThat(extra).isNull();
}
@MediumTest
+ @Test
public void testGetUserCount() {
int count = mUserManager.getUsers().size();
UserInfo user1 = createUser("User 1", 0);
- assertNotNull(user1);
+ assertThat(user1).isNotNull();
UserInfo user2 = createUser("User 2", 0);
- assertNotNull(user2);
- assertEquals(count + 2, mUserManager.getUserCount());
+ assertThat(user2).isNotNull();
+ assertThat(mUserManager.getUserCount()).isEqualTo(count + 2);
}
@MediumTest
+ @Test
public void testRestrictions() {
UserInfo testUser = createUser("User 1", 0);
@@ -611,12 +664,13 @@ public class UserManagerTest extends AndroidTestCase {
Bundle stored = mUserManager.getUserRestrictions(new UserHandle(testUser.id));
// Note this will fail if DO already sets those restrictions.
- assertEquals(stored.getBoolean(UserManager.DISALLOW_CONFIG_WIFI), false);
- assertEquals(stored.getBoolean(UserManager.DISALLOW_UNINSTALL_APPS), false);
- assertEquals(stored.getBoolean(UserManager.DISALLOW_INSTALL_APPS), true);
+ assertThat(stored.getBoolean(UserManager.DISALLOW_CONFIG_WIFI)).isFalse();
+ assertThat(stored.getBoolean(UserManager.DISALLOW_UNINSTALL_APPS)).isFalse();
+ assertThat(stored.getBoolean(UserManager.DISALLOW_INSTALL_APPS)).isTrue();
}
@MediumTest
+ @Test
public void testDefaultRestrictionsApplied() throws Exception {
final UserInfo userInfo = createUser("Useroid", UserManager.USER_TYPE_FULL_SECONDARY, 0);
final UserTypeDetails userTypeDetails =
@@ -625,13 +679,14 @@ public class UserManagerTest extends AndroidTestCase {
// Note this can fail if DO unset those restrictions.
for (String restriction : expectedRestrictions.keySet()) {
if (expectedRestrictions.getBoolean(restriction)) {
- assertTrue(
- mUserManager.hasUserRestriction(restriction, UserHandle.of(userInfo.id)));
+ assertThat(mUserManager.hasUserRestriction(restriction, UserHandle.of(userInfo.id)))
+ .isTrue();
}
}
}
@MediumTest
+ @Test
public void testSetDefaultGuestRestrictions() {
final Bundle origGuestRestrictions = mUserManager.getDefaultGuestRestrictions();
Bundle restrictions = new Bundle();
@@ -640,26 +695,28 @@ public class UserManagerTest extends AndroidTestCase {
try {
UserInfo guest = createUser("Guest", UserInfo.FLAG_GUEST);
- assertNotNull(guest);
- assertTrue(mUserManager.hasUserRestriction(UserManager.DISALLOW_FUN,
- guest.getUserHandle()));
+ assertThat(guest).isNotNull();
+ assertThat(mUserManager.hasUserRestriction(UserManager.DISALLOW_FUN,
+ guest.getUserHandle())).isTrue();
} finally {
mUserManager.setDefaultGuestRestrictions(origGuestRestrictions);
}
}
+ @Test
public void testGetUserSwitchability() {
int userSwitchable = mUserManager.getUserSwitchability();
- assertEquals("Expected users to be switchable", UserManager.SWITCHABILITY_STATUS_OK,
- userSwitchable);
+ assertWithMessage("Expected users to be switchable").that(userSwitchable)
+ .isEqualTo(UserManager.SWITCHABILITY_STATUS_OK);
}
@LargeTest
+ @Test
public void testSwitchUser() {
- ActivityManager am = getContext().getSystemService(ActivityManager.class);
+ ActivityManager am = mContext.getSystemService(ActivityManager.class);
final int startUser = am.getCurrentUser();
UserInfo user = createUser("User", 0);
- assertNotNull(user);
+ assertThat(user).isNotNull();
// Switch to the user just created.
switchUser(user.id, null, true);
// Switch back to the starting user.
@@ -667,21 +724,23 @@ public class UserManagerTest extends AndroidTestCase {
}
@LargeTest
+ @Test
public void testSwitchUserByHandle() {
- ActivityManager am = getContext().getSystemService(ActivityManager.class);
+ ActivityManager am = mContext.getSystemService(ActivityManager.class);
final int startUser = am.getCurrentUser();
UserInfo user = createUser("User", 0);
- assertNotNull(user);
+ assertThat(user).isNotNull();
// Switch to the user just created.
switchUser(-1, user.getUserHandle(), false);
// Switch back to the starting user.
switchUser(-1, UserHandle.of(startUser), false);
}
+ @Test
public void testSwitchUserByHandle_ThrowsException() {
synchronized (mUserSwitchLock) {
try {
- ActivityManager am = getContext().getSystemService(ActivityManager.class);
+ ActivityManager am = mContext.getSystemService(ActivityManager.class);
am.switchUser(null);
fail("Expected IllegalArgumentException on passing in a null UserHandle.");
} catch (IllegalArgumentException expected) {
@@ -691,6 +750,7 @@ public class UserManagerTest extends AndroidTestCase {
}
@MediumTest
+ @Test
public void testConcurrentUserCreate() throws Exception {
int userCount = mUserManager.getUserCount();
int maxSupportedUsers = UserManager.getMaxSupportedUsers();
@@ -713,11 +773,12 @@ public class UserManagerTest extends AndroidTestCase {
}
es.shutdown();
es.awaitTermination(20, TimeUnit.SECONDS);
- assertEquals(maxSupportedUsers, mUserManager.getUserCount());
- assertEquals(canBeCreatedCount, created.get());
+ assertThat(mUserManager.getUserCount()).isEqualTo(maxSupportedUsers);
+ assertThat(created.get()).isEqualTo(canBeCreatedCount);
}
@MediumTest
+ @Test
public void testGetUserHandles_createNewUser_shouldFindNewUser() {
UserInfo user = createUser("Guest 1", UserManager.USER_TYPE_FULL_GUEST, /*flags*/ 0);
@@ -729,7 +790,7 @@ public class UserManagerTest extends AndroidTestCase {
}
}
- assertTrue(found);
+ assertThat(found).isTrue();
}
private boolean isPackageInstalledForUser(String packageName, int userId) {
@@ -748,7 +809,7 @@ public class UserManagerTest extends AndroidTestCase {
*/
private void switchUser(int userId, UserHandle user, boolean ignoreHandle) {
synchronized (mUserSwitchLock) {
- ActivityManager am = getContext().getSystemService(ActivityManager.class);
+ ActivityManager am = mContext.getSystemService(ActivityManager.class);
if (ignoreHandle) {
am.switchUser(userId);
} else {
@@ -834,4 +895,12 @@ public class UserManagerTest extends AndroidTestCase {
return profile;
}
+ private void assumeManagedUsersSupported() {
+ assumeTrue("device doesn't support managed users",
+ mPackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS));
+ }
+
+ private boolean isAutomotive() {
+ return mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java
index 683278b699c0..3db832b24236 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java
@@ -26,6 +26,7 @@ import static com.android.server.pm.UserSystemPackageInstaller.USER_TYPE_PACKAGE
import static com.android.server.pm.UserSystemPackageInstaller.USER_TYPE_PACKAGE_WHITELIST_MODE_ENFORCE;
import static com.android.server.pm.UserSystemPackageInstaller.USER_TYPE_PACKAGE_WHITELIST_MODE_IGNORE_OTA;
import static com.android.server.pm.UserSystemPackageInstaller.USER_TYPE_PACKAGE_WHITELIST_MODE_IMPLICIT_WHITELIST;
+import static com.android.server.pm.UserSystemPackageInstaller.USER_TYPE_PACKAGE_WHITELIST_MODE_IMPLICIT_WHITELIST_SYSTEM;
import static com.android.server.pm.UserSystemPackageInstaller.USER_TYPE_PACKAGE_WHITELIST_MODE_LOG;
import static org.junit.Assert.assertEquals;
@@ -262,39 +263,25 @@ public class UserSystemPackageInstallerTest {
// No implicit whitelist, so only install pkg1.
boolean implicit = false;
- boolean isSysUser = false;
assertTrue(UserSystemPackageInstaller.shouldInstallPackage(
- pkg1, pkgBitSetMap, userWhitelist, implicit, isSysUser));
+ pkg1, pkgBitSetMap, userWhitelist, implicit));
assertFalse(UserSystemPackageInstaller.shouldInstallPackage(
- pkg2, pkgBitSetMap, userWhitelist, implicit, isSysUser));
+ pkg2, pkgBitSetMap, userWhitelist, implicit));
assertFalse(UserSystemPackageInstaller.shouldInstallPackage(
- pkg3, pkgBitSetMap, userWhitelist, implicit, isSysUser));
+ pkg3, pkgBitSetMap, userWhitelist, implicit));
assertFalse(UserSystemPackageInstaller.shouldInstallPackage(
- pkg4, pkgBitSetMap, userWhitelist, implicit, isSysUser));
+ pkg4, pkgBitSetMap, userWhitelist, implicit));
// Use implicit whitelist, so install pkg1 and pkg4
implicit = true;
- isSysUser = false;
assertTrue(UserSystemPackageInstaller.shouldInstallPackage(
- pkg1, pkgBitSetMap, userWhitelist, implicit, isSysUser));
+ pkg1, pkgBitSetMap, userWhitelist, implicit));
assertFalse(UserSystemPackageInstaller.shouldInstallPackage(
- pkg2, pkgBitSetMap, userWhitelist, implicit, isSysUser));
+ pkg2, pkgBitSetMap, userWhitelist, implicit));
assertFalse(UserSystemPackageInstaller.shouldInstallPackage(
- pkg3, pkgBitSetMap, userWhitelist, implicit, isSysUser));
+ pkg3, pkgBitSetMap, userWhitelist, implicit));
assertTrue(UserSystemPackageInstaller.shouldInstallPackage(
- pkg4, pkgBitSetMap, userWhitelist, implicit, isSysUser));
-
- // For user 0 specifically, we always implicitly whitelist.
- implicit = false;
- isSysUser = true;
- assertTrue(UserSystemPackageInstaller.shouldInstallPackage(
- pkg1, pkgBitSetMap, userWhitelist, implicit, isSysUser));
- assertFalse(UserSystemPackageInstaller.shouldInstallPackage(
- pkg2, pkgBitSetMap, userWhitelist, implicit, isSysUser));
- assertFalse(UserSystemPackageInstaller.shouldInstallPackage(
- pkg3, pkgBitSetMap, userWhitelist, implicit, isSysUser));
- assertTrue(UserSystemPackageInstaller.shouldInstallPackage(
- pkg4, pkgBitSetMap, userWhitelist, implicit, isSysUser));
+ pkg4, pkgBitSetMap, userWhitelist, implicit));
}
/**
@@ -400,30 +387,42 @@ public class UserSystemPackageInstallerTest {
assertFalse(mUserSystemPackageInstaller.isLogMode());
assertFalse(mUserSystemPackageInstaller.isEnforceMode());
assertFalse(mUserSystemPackageInstaller.isImplicitWhitelistMode());
+ assertFalse(mUserSystemPackageInstaller.isImplicitWhitelistSystemMode());
assertFalse(mUserSystemPackageInstaller.isIgnoreOtaMode());
setUserTypePackageWhitelistMode(USER_TYPE_PACKAGE_WHITELIST_MODE_LOG);
assertTrue(mUserSystemPackageInstaller.isLogMode());
assertFalse(mUserSystemPackageInstaller.isEnforceMode());
assertFalse(mUserSystemPackageInstaller.isImplicitWhitelistMode());
+ assertFalse(mUserSystemPackageInstaller.isImplicitWhitelistSystemMode());
assertFalse(mUserSystemPackageInstaller.isIgnoreOtaMode());
setUserTypePackageWhitelistMode(USER_TYPE_PACKAGE_WHITELIST_MODE_ENFORCE);
assertFalse(mUserSystemPackageInstaller.isLogMode());
assertTrue(mUserSystemPackageInstaller.isEnforceMode());
assertFalse(mUserSystemPackageInstaller.isImplicitWhitelistMode());
+ assertFalse(mUserSystemPackageInstaller.isImplicitWhitelistSystemMode());
assertFalse(mUserSystemPackageInstaller.isIgnoreOtaMode());
setUserTypePackageWhitelistMode(USER_TYPE_PACKAGE_WHITELIST_MODE_IMPLICIT_WHITELIST);
assertFalse(mUserSystemPackageInstaller.isLogMode());
assertFalse(mUserSystemPackageInstaller.isEnforceMode());
assertTrue(mUserSystemPackageInstaller.isImplicitWhitelistMode());
+ assertFalse(mUserSystemPackageInstaller.isImplicitWhitelistSystemMode());
+ assertFalse(mUserSystemPackageInstaller.isIgnoreOtaMode());
+
+ setUserTypePackageWhitelistMode(USER_TYPE_PACKAGE_WHITELIST_MODE_IMPLICIT_WHITELIST_SYSTEM);
+ assertFalse(mUserSystemPackageInstaller.isLogMode());
+ assertFalse(mUserSystemPackageInstaller.isEnforceMode());
+ assertFalse(mUserSystemPackageInstaller.isImplicitWhitelistMode());
+ assertTrue(mUserSystemPackageInstaller.isImplicitWhitelistSystemMode());
assertFalse(mUserSystemPackageInstaller.isIgnoreOtaMode());
setUserTypePackageWhitelistMode(USER_TYPE_PACKAGE_WHITELIST_MODE_IGNORE_OTA);
assertFalse(mUserSystemPackageInstaller.isLogMode());
assertFalse(mUserSystemPackageInstaller.isEnforceMode());
assertFalse(mUserSystemPackageInstaller.isImplicitWhitelistMode());
+ assertFalse(mUserSystemPackageInstaller.isImplicitWhitelistSystemMode());
assertTrue(mUserSystemPackageInstaller.isIgnoreOtaMode());
setUserTypePackageWhitelistMode(
@@ -431,6 +430,7 @@ public class UserSystemPackageInstallerTest {
assertTrue(mUserSystemPackageInstaller.isLogMode());
assertTrue(mUserSystemPackageInstaller.isEnforceMode());
assertFalse(mUserSystemPackageInstaller.isImplicitWhitelistMode());
+ assertFalse(mUserSystemPackageInstaller.isImplicitWhitelistSystemMode());
assertFalse(mUserSystemPackageInstaller.isIgnoreOtaMode());
setUserTypePackageWhitelistMode(USER_TYPE_PACKAGE_WHITELIST_MODE_IMPLICIT_WHITELIST
@@ -438,6 +438,7 @@ public class UserSystemPackageInstallerTest {
assertFalse(mUserSystemPackageInstaller.isLogMode());
assertTrue(mUserSystemPackageInstaller.isEnforceMode());
assertTrue(mUserSystemPackageInstaller.isImplicitWhitelistMode());
+ assertFalse(mUserSystemPackageInstaller.isImplicitWhitelistSystemMode());
assertFalse(mUserSystemPackageInstaller.isIgnoreOtaMode());
}
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 81fb0ec3bf53..13643a09daaa 100644
--- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
@@ -62,6 +62,7 @@ import android.os.PowerManager;
import android.os.PowerSaveState;
import android.os.SystemClock;
import android.os.UserHandle;
+import android.platform.test.annotations.FlakyTest;
import android.provider.Settings;
import android.test.mock.MockContentResolver;
import android.view.Display;
@@ -734,6 +735,7 @@ public class PowerManagerServiceTest {
assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_ASLEEP);
}
+ @FlakyTest
@Test
public void testInattentiveSleep_goesToSleepWithWakeLock() throws Exception {
final String pkg = mContextSpy.getOpPackageName();
diff --git a/services/tests/servicestests/src/com/android/server/power/batterysaver/FileUpdaterTest.java b/services/tests/servicestests/src/com/android/server/power/batterysaver/FileUpdaterTest.java
index 89c7dd45e9d3..ecdc58e4549d 100644
--- a/services/tests/servicestests/src/com/android/server/power/batterysaver/FileUpdaterTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/batterysaver/FileUpdaterTest.java
@@ -29,6 +29,7 @@ import static org.mockito.Mockito.verify;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
+import android.platform.test.annotations.FlakyTest;
import android.util.ArrayMap;
import androidx.test.InstrumentationRegistry;
@@ -328,6 +329,7 @@ public class FileUpdaterTest {
veriryWtf(0);
}
+ @FlakyTest
@Test
public void testAll() throws Exception {
// Run multiple tests on the single target instance.
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/ArrayMapWithHistoryTest.java b/services/tests/servicestests/src/com/android/server/timedetector/ArrayMapWithHistoryTest.java
new file mode 100644
index 000000000000..b6eea461d222
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/timedetector/ArrayMapWithHistoryTest.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.timedetector;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import android.util.ArrayMap;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.timezonedetector.ArrayMapWithHistory;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.StringWriter;
+import java.util.concurrent.Callable;
+
+@RunWith(AndroidJUnit4.class)
+public class ArrayMapWithHistoryTest {
+
+ @Test
+ public void testValueHistoryBehavior() {
+ // Create a map that will retain 2 values per key.
+ ArrayMapWithHistory<String, String> historyMap = new ArrayMapWithHistory<>(2 /* history */);
+ ArrayMap<String, String> arrayMap = new ArrayMap<>();
+
+ compareGetAndSizeForKeys(historyMap, arrayMap, entry("K1", null));
+
+ assertEquals(0, historyMap.getHistoryCountForKeyForTests("K1"));
+ assertToStringAndDumpNotNull(historyMap);
+
+ putAndCompareReturnValue(historyMap, arrayMap, "K1", "V1");
+ compareGetAndSizeForKeys(historyMap, arrayMap, entry("K1", "V1"));
+ compareKeyAtAndValueAtForIndex(0, historyMap, arrayMap);
+
+ assertEquals(1, historyMap.getHistoryCountForKeyForTests("K1"));
+ assertToStringAndDumpNotNull(historyMap);
+
+ // put() a new value for the same key.
+ putAndCompareReturnValue(historyMap, arrayMap, "K1", "V2");
+ compareGetAndSizeForKeys(historyMap, arrayMap, entry("K1", "V2"));
+ compareKeyAtAndValueAtForIndex(0, historyMap, arrayMap);
+
+ assertEquals(2, historyMap.getHistoryCountForKeyForTests("K1"));
+ assertToStringAndDumpNotNull(historyMap);
+
+ // put() a new value for the same key. We should have hit the limit of "2 values retained
+ // per key".
+ putAndCompareReturnValue(historyMap, arrayMap, "K1", "V3");
+ compareGetAndSizeForKeys(historyMap, arrayMap, entry("K1", "V3"));
+ compareKeyAtAndValueAtForIndex(0, historyMap, arrayMap);
+
+ assertEquals(2, historyMap.getHistoryCountForKeyForTests("K1"));
+ assertToStringAndDumpNotNull(historyMap);
+ }
+
+ @Test
+ public void testMapBehavior() throws Exception {
+ ArrayMapWithHistory<String, String> historyMap = new ArrayMapWithHistory<>(2);
+ ArrayMap<String, String> arrayMap = new ArrayMap<>();
+
+ compareGetAndSizeForKeys(historyMap, arrayMap, entry("K1", null), entry("K2", null));
+ assertIndexAccessThrowsException(0, historyMap, arrayMap);
+
+ assertEquals(0, historyMap.getHistoryCountForKeyForTests("K1"));
+ assertEquals(0, historyMap.getHistoryCountForKeyForTests("K2"));
+
+ putAndCompareReturnValue(historyMap, arrayMap, "K1", "V1");
+ compareGetAndSizeForKeys(historyMap, arrayMap, entry("K1", "V1"), entry("K2", null));
+ compareKeyAtAndValueAtForIndex(0, historyMap, arrayMap);
+ // TODO Restore after http://b/146563025 is fixed and ArrayMap behaves properly in tests.
+ // assertIndexAccessThrowsException(1, historyMap, arrayMap);
+
+ assertEquals(1, historyMap.getHistoryCountForKeyForTests("K1"));
+ assertToStringAndDumpNotNull(historyMap);
+
+ putAndCompareReturnValue(historyMap, arrayMap, "K2", "V2");
+ compareGetAndSizeForKeys(historyMap, arrayMap, entry("K1", "V1"), entry("K2", "V2"));
+ compareKeyAtAndValueAtForIndex(0, historyMap, arrayMap);
+ compareKeyAtAndValueAtForIndex(1, historyMap, arrayMap);
+ // TODO Restore after http://b/146563025 is fixed and ArrayMap behaves properly in tests.
+ // assertIndexAccessThrowsException(2, historyMap, arrayMap);
+
+ assertEquals(1, historyMap.getHistoryCountForKeyForTests("K1"));
+ assertEquals(1, historyMap.getHistoryCountForKeyForTests("K2"));
+ assertToStringAndDumpNotNull(historyMap);
+ }
+
+ private static String dumpHistoryMap(ArrayMapWithHistory<?, ?> historyMap) {
+ StringWriter stringWriter = new StringWriter();
+ try (IndentingPrintWriter ipw = new IndentingPrintWriter(stringWriter, " ")) {
+ historyMap.dump(ipw);
+ return stringWriter.toString();
+ }
+ }
+
+ private static <K, V> void putAndCompareReturnValue(ArrayMapWithHistory<K, V> historyMap,
+ ArrayMap<K, V> arrayMap, K key, V value) {
+ assertEquals(arrayMap.put(key, value), historyMap.put(key, value));
+ }
+
+ private static class Entry<K, V> {
+ public final K key;
+ public final V value;
+
+ Entry(K key, V value) {
+ this.key = key;
+ this.value = value;
+ }
+ }
+
+ private static <K, V> Entry<K, V> entry(K key, V value) {
+ return new Entry<>(key, value);
+ }
+
+ @SafeVarargs
+ private static <K, V> void compareGetAndSizeForKeys(ArrayMapWithHistory<K, V> historyMap,
+ ArrayMap<K, V> arrayMap, Entry<K, V>... expectedEntries) {
+ for (Entry<K, V> expectedEntry : expectedEntries) {
+ assertEquals(arrayMap.get(expectedEntry.key), historyMap.get(expectedEntry.key));
+ assertEquals(expectedEntry.value, historyMap.get(expectedEntry.key));
+ }
+ assertEquals(arrayMap.size(), historyMap.size());
+ }
+
+ private static void compareKeyAtAndValueAtForIndex(
+ int index, ArrayMapWithHistory<?, ?> historyMap, ArrayMap<?, ?> arrayMap) {
+ assertEquals(arrayMap.keyAt(index), historyMap.keyAt(index));
+ assertEquals(arrayMap.valueAt(index), historyMap.valueAt(index));
+ }
+
+ private static void assertIndexAccessThrowsException(
+ int index, ArrayMapWithHistory<?, ?> historyMap, ArrayMap<?, ?> arrayMap)
+ throws Exception {
+ assertThrowsArrayIndexOutOfBoundsException(
+ "ArrayMap.keyAt(" + index + ")", () -> arrayMap.keyAt(index));
+ assertThrowsArrayIndexOutOfBoundsException(
+ "ArrayMapWithHistory.keyAt(" + index + ")", () -> historyMap.keyAt(index));
+ assertThrowsArrayIndexOutOfBoundsException(
+ "ArrayMap.keyAt(" + index + ")", () -> arrayMap.valueAt(index));
+ assertThrowsArrayIndexOutOfBoundsException(
+ "ArrayMapWithHistory.keyAt(" + index + ")", () -> historyMap.valueAt(index));
+ }
+
+ private static void assertThrowsArrayIndexOutOfBoundsException(
+ String description, Callable<?> callable) throws Exception {
+ try {
+ callable.call();
+ fail("Expected exception for " + description);
+ } catch (ArrayIndexOutOfBoundsException expected) {
+ // This is fine.
+ } catch (Exception e) {
+ // Any other exception is just rethrown.
+ throw e;
+ }
+ }
+
+ private static void assertToStringAndDumpNotNull(ArrayMapWithHistory<?, ?> historyMap) {
+ assertNotNull(historyMap.toString());
+ assertNotNull(dumpHistoryMap(historyMap));
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/ReferenceWithHistoryTest.java b/services/tests/servicestests/src/com/android/server/timedetector/ReferenceWithHistoryTest.java
new file mode 100644
index 000000000000..ce72499007ba
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/timedetector/ReferenceWithHistoryTest.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.timedetector;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.timezonedetector.ReferenceWithHistory;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.StringWriter;
+
+@RunWith(AndroidJUnit4.class)
+public class ReferenceWithHistoryTest {
+
+ @Test
+ public void testBasicReferenceBehavior() {
+ // Create a reference that will retain 2 history values.
+ ReferenceWithHistory<String> referenceWithHistory =
+ new ReferenceWithHistory<>(2 /* history */);
+ TestRef<String> reference = new TestRef<>();
+
+ // Check unset behavior.
+ compareGet(referenceWithHistory, reference, null);
+ assertNotNull(dumpReferenceWithHistory(referenceWithHistory));
+ compareToString(referenceWithHistory, reference, "null");
+
+ // Try setting null.
+ setAndCompareReturnValue(referenceWithHistory, reference, null);
+ compareGet(referenceWithHistory, reference, null);
+ assertNotNull(dumpReferenceWithHistory(referenceWithHistory));
+ compareToString(referenceWithHistory, reference, "null");
+
+ // Try setting a non-null value.
+ setAndCompareReturnValue(referenceWithHistory, reference, "Foo");
+ compareGet(referenceWithHistory, reference, "Foo");
+ assertNotNull(dumpReferenceWithHistory(referenceWithHistory));
+ compareToString(referenceWithHistory, reference, "Foo");
+
+ // Try setting null again.
+ setAndCompareReturnValue(referenceWithHistory, reference, "Foo");
+ compareGet(referenceWithHistory, reference, "Foo");
+ assertNotNull(dumpReferenceWithHistory(referenceWithHistory));
+ compareToString(referenceWithHistory, reference, "Foo");
+
+ // Try a non-null value again.
+ setAndCompareReturnValue(referenceWithHistory, reference, "Bar");
+ compareGet(referenceWithHistory, reference, "Bar");
+ assertNotNull(dumpReferenceWithHistory(referenceWithHistory));
+ compareToString(referenceWithHistory, reference, "Bar");
+ }
+
+ @Test
+ public void testValueHistoryBehavior() {
+ // Create a reference that will retain 2 history values.
+ ReferenceWithHistory<String> referenceWithHistory =
+ new ReferenceWithHistory<>(2 /* history */);
+ TestRef<String> reference = new TestRef<>();
+
+ // Assert behavior before anything is set.
+ assertEquals(0, referenceWithHistory.getHistoryCount());
+
+ // Set a value (1).
+ setAndCompareReturnValue(referenceWithHistory, reference, "V1");
+ assertEquals(1, referenceWithHistory.getHistoryCount());
+
+ // Set a value (2).
+ setAndCompareReturnValue(referenceWithHistory, reference, "V2");
+ assertEquals(2, referenceWithHistory.getHistoryCount());
+
+ // Set a value (3).
+ // We should have hit the limit of "2 history values retained per key".
+ setAndCompareReturnValue(referenceWithHistory, reference, "V3");
+ assertEquals(2, referenceWithHistory.getHistoryCount());
+ }
+
+ /**
+ * A simple class that has the same behavior as ReferenceWithHistory without the history. Used
+ * in tests for comparison.
+ */
+ private static class TestRef<V> {
+ private V mValue;
+
+ public V get() {
+ return mValue;
+ }
+
+ public V set(V value) {
+ V previous = mValue;
+ mValue = value;
+ return previous;
+ }
+
+ public String toString() {
+ return String.valueOf(mValue);
+ }
+ }
+
+ private static void compareGet(
+ ReferenceWithHistory<?> referenceWithHistory, TestRef<?> reference, Object value) {
+ assertEquals(reference.get(), referenceWithHistory.get());
+ assertEquals(value, reference.get());
+ }
+
+ private static <T> void setAndCompareReturnValue(
+ ReferenceWithHistory<T> referenceWithHistory, TestRef<T> reference, T newValue) {
+ assertEquals(reference.set(newValue), referenceWithHistory.set(newValue));
+ }
+
+ private static void compareToString(
+ ReferenceWithHistory<?> referenceWithHistory, TestRef<?> reference, String expected) {
+ assertEquals(reference.toString(), referenceWithHistory.toString());
+ assertEquals(expected, referenceWithHistory.toString());
+ }
+
+ private static String dumpReferenceWithHistory(ReferenceWithHistory<?> referenceWithHistory) {
+ StringWriter stringWriter = new StringWriter();
+ try (IndentingPrintWriter ipw = new IndentingPrintWriter(stringWriter, " ")) {
+ referenceWithHistory.dump(ipw);
+ return stringWriter.toString();
+ }
+ }
+}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryManagerTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryManagerTest.java
index 92c05466deb5..3b6a4bde8e20 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryManagerTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryManagerTest.java
@@ -41,6 +41,7 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.server.UiServiceTestCase;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -124,6 +125,8 @@ public class NotificationHistoryManagerTest extends UiServiceTestCase {
verify(mDb, times(1)).init();
}
+ @Test
+ @Ignore("b/147012298")
public void testOnUserUnlocked_historyDisabled() {
Settings.Secure.putIntForUser(getContext().getContentResolver(),
Settings.Secure.NOTIFICATION_HISTORY_ENABLED, 0, USER_SYSTEM);
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 876e77acde86..95617b1162a8 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -4502,6 +4502,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
assertEquals(0, mService.countLogSmartSuggestionsVisible);
}
+ @Test
public void testReportSeen_delegated() {
Notification.Builder nb =
new Notification.Builder(mContext, mTestNotificationChannel.getId())
@@ -5767,6 +5768,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
verify(mUsageStats, times(5)).registerImageRemoved(PKG);
}
+ @Test
public void testNotificationBubbles_flagAutoExpandForeground_fails_notForeground()
throws Exception {
// Bubbles are allowed!
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
index 9c17de9954c4..ed9cdf4caa94 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
@@ -61,9 +61,9 @@ public class ActivityDisplayTests extends ActivityTestsBase {
@Test
public void testLastFocusedStackIsUpdatedWhenMovingStack() {
// Create a stack at bottom.
- final DisplayContent display = mRootActivityContainer.getDefaultDisplay();
+ final DisplayContent display = mRootWindowContainer.getDefaultDisplay();
final ActivityStack stack =
- new StackBuilder(mRootActivityContainer).setOnTop(!ON_TOP).build();
+ new StackBuilder(mRootWindowContainer).setOnTop(!ON_TOP).build();
final ActivityStack prevFocusedStack = display.getFocusedStack();
stack.moveToFront("moveStackToFront");
@@ -83,7 +83,7 @@ public class ActivityDisplayTests extends ActivityTestsBase {
@Test
public void testFullscreenStackCanBeFocusedWhenFocusablePinnedStackExists() {
// Create a pinned stack and move to front.
- final ActivityStack pinnedStack = mRootActivityContainer.getDefaultDisplay().createStack(
+ final ActivityStack pinnedStack = mRootWindowContainer.getDefaultDisplay().createStack(
WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, ON_TOP);
final Task pinnedTask = new TaskBuilder(mService.mStackSupervisor)
.setStack(pinnedStack).build();
@@ -96,7 +96,7 @@ public class ActivityDisplayTests extends ActivityTestsBase {
// Create a fullscreen stack and move to front.
final ActivityStack fullscreenStack = createFullscreenStackWithSimpleActivityAt(
- mRootActivityContainer.getDefaultDisplay());
+ mRootWindowContainer.getDefaultDisplay());
fullscreenStack.moveToFront("moveFullscreenStackToFront");
// The focused stack should be the fullscreen stack.
@@ -140,7 +140,7 @@ public class ActivityDisplayTests extends ActivityTestsBase {
doReturn(false).when(display).shouldDestroyContentOnRemove();
// Put home stack on the display.
- final ActivityStack homeStack = new StackBuilder(mRootActivityContainer)
+ final ActivityStack homeStack = new StackBuilder(mRootWindowContainer)
.setDisplay(display).setActivityType(ACTIVITY_TYPE_HOME).build();
// Put a finishing standard activity which will be reparented.
@@ -169,14 +169,14 @@ public class ActivityDisplayTests extends ActivityTestsBase {
*/
@Test
public void testTopRunningActivity() {
- final DisplayContent display = mRootActivityContainer.getDefaultDisplay();
+ final DisplayContent display = mRootWindowContainer.getDefaultDisplay();
final KeyguardController keyguard = mSupervisor.getKeyguardController();
- final ActivityStack stack = new StackBuilder(mRootActivityContainer).build();
+ final ActivityStack stack = new StackBuilder(mRootWindowContainer).build();
final ActivityRecord activity = stack.getTopNonFinishingActivity();
// Create empty stack on top.
final ActivityStack emptyStack =
- new StackBuilder(mRootActivityContainer).setCreateActivity(false).build();
+ new StackBuilder(mRootWindowContainer).setCreateActivity(false).build();
// Make sure the top running activity is not affected when keyguard is not locked.
assertTopRunningActivity(activity, display);
@@ -219,7 +219,7 @@ public class ActivityDisplayTests extends ActivityTestsBase {
*/
@Test
public void testAlwaysOnTopStackLocation() {
- final DisplayContent display = mRootActivityContainer.getDefaultDisplay();
+ final DisplayContent display = mRootWindowContainer.getDefaultDisplay();
final ActivityStack alwaysOnTopStack = display.createStack(WINDOWING_MODE_FREEFORM,
ACTIVITY_TYPE_STANDARD, true /* onTop */);
final ActivityRecord activity = new ActivityBuilder(mService).setCreateTask(true)
@@ -273,18 +273,18 @@ public class ActivityDisplayTests extends ActivityTestsBase {
@Test
public void testRemoveStackInWindowingModes() {
- removeStackTests(() -> mRootActivityContainer.removeStacksInWindowingModes(
+ removeStackTests(() -> mRootWindowContainer.removeStacksInWindowingModes(
WINDOWING_MODE_FULLSCREEN));
}
@Test
public void testRemoveStackWithActivityTypes() {
removeStackTests(
- () -> mRootActivityContainer.removeStacksWithActivityTypes(ACTIVITY_TYPE_STANDARD));
+ () -> mRootWindowContainer.removeStacksWithActivityTypes(ACTIVITY_TYPE_STANDARD));
}
private void removeStackTests(Runnable runnable) {
- final DisplayContent display = mRootActivityContainer.getDefaultDisplay();
+ final DisplayContent display = mRootWindowContainer.getDefaultDisplay();
final ActivityStack stack1 = display.createStack(WINDOWING_MODE_FULLSCREEN,
ACTIVITY_TYPE_STANDARD, ON_TOP);
final ActivityStack stack2 = display.createStack(WINDOWING_MODE_FULLSCREEN,
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
index 12074dc381cf..7204a811fbe2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
@@ -44,6 +44,7 @@ import com.android.server.wm.ActivityMetricsLaunchObserver.ActivityRecordProto;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import org.junit.runner.RunWith;
import org.mockito.ArgumentMatcher;
import java.util.Arrays;
@@ -57,6 +58,7 @@ import java.util.concurrent.TimeUnit;
*/
@SmallTest
@Presubmit
+@RunWith(WindowTestRunner.class)
public class ActivityMetricsLaunchObserverTests extends ActivityTestsBase {
private ActivityMetricsLogger mActivityMetricsLogger;
private ActivityMetricsLogger.LaunchingState mLaunchingState;
@@ -116,11 +118,18 @@ public class ActivityMetricsLaunchObserverTests extends ActivityTestsBase {
return argThat(new ActivityRecordMatcher(record));
}
- static <T> T verifyAsync(T mock) {
+ private <T> T verifyAsync(T mock) {
+ // With WindowTestRunner, all test methods are inside WM lock, so we have to unblock any
+ // messages that are waiting for the lock.
+ waitHandlerIdle(mService.mH);
// AMLO callbacks happen on a separate thread than AML calls, so we need to use a timeout.
return verify(mock, timeout(TimeUnit.SECONDS.toMillis(5)));
}
+ private void verifyOnActivityLaunchFinished(ActivityRecord activity) {
+ verifyAsync(mLaunchObserver).onActivityLaunchFinished(eqProto(activity), anyLong());
+ }
+
private void onIntentStarted(Intent intent) {
notifyActivityLaunching(intent);
@@ -159,7 +168,7 @@ public class ActivityMetricsLaunchObserverTests extends ActivityTestsBase {
notifyTransitionStarting(mTopActivity);
notifyWindowsDrawn(mTopActivity);
- verifyAsync(mLaunchObserver).onActivityLaunchFinished(eqProto(mTopActivity), anyLong());
+ verifyOnActivityLaunchFinished(mTopActivity);
verifyNoMoreInteractions(mLaunchObserver);
}
@@ -210,7 +219,7 @@ public class ActivityMetricsLaunchObserverTests extends ActivityTestsBase {
notifyWindowsDrawn(mTopActivity);
verifyAsync(mLaunchObserver).onReportFullyDrawn(eqProto(mTopActivity), anyLong());
- verifyAsync(mLaunchObserver).onActivityLaunchFinished(eqProto(mTopActivity), anyLong());
+ verifyOnActivityLaunchFinished(mTopActivity);
verifyNoMoreInteractions(mLaunchObserver);
}
@@ -267,7 +276,7 @@ public class ActivityMetricsLaunchObserverTests extends ActivityTestsBase {
notifyWindowsDrawn(mTopActivity);
- verifyAsync(mLaunchObserver).onActivityLaunchFinished(eqProto(mTopActivity), anyLong());
+ verifyOnActivityLaunchFinished(mTopActivity);
verifyNoMoreInteractions(mLaunchObserver);
}
@@ -322,16 +331,40 @@ public class ActivityMetricsLaunchObserverTests extends ActivityTestsBase {
assertWithMessage("Different callers should get 2 indepedent launching states")
.that(previousState).isNotEqualTo(mLaunchingState);
+ transitToDrawnAndVerifyOnLaunchFinished(otherActivity);
- notifyTransitionStarting(otherActivity);
- notifyWindowsDrawn(otherActivity);
+ // The first transition should still be valid.
+ transitToDrawnAndVerifyOnLaunchFinished(mTopActivity);
+ }
- verifyAsync(mLaunchObserver).onActivityLaunchFinished(eqProto(otherActivity), anyLong());
+ @Test
+ public void testConsecutiveLaunchOnDifferentDisplay() {
+ onActivityLaunched(mTopActivity);
- // The first transition should still be valid.
- notifyTransitionStarting(mTopActivity);
- notifyWindowsDrawn(mTopActivity);
+ final ActivityStack stack = new StackBuilder(mRootWindowContainer)
+ .setDisplay(addNewDisplayContentAt(DisplayContent.POSITION_BOTTOM))
+ .setCreateActivity(false)
+ .build();
+ final ActivityRecord activityOnNewDisplay = new ActivityBuilder(mService)
+ .setStack(stack)
+ .setCreateTask(true)
+ .setProcessName("new")
+ .build();
+
+ // Before TopActivity is drawn, it launches another activity on a different display.
+ mActivityMetricsLogger.notifyActivityLaunching(activityOnNewDisplay.intent,
+ mTopActivity /* caller */);
+ notifyActivityLaunched(START_SUCCESS, activityOnNewDisplay);
+
+ // There should be 2 events instead of coalescing as one event.
+ transitToDrawnAndVerifyOnLaunchFinished(mTopActivity);
+ transitToDrawnAndVerifyOnLaunchFinished(activityOnNewDisplay);
+ }
+
+ private void transitToDrawnAndVerifyOnLaunchFinished(ActivityRecord activity) {
+ notifyTransitionStarting(activity);
+ notifyWindowsDrawn(activity);
- verifyAsync(mLaunchObserver).onActivityLaunchFinished(eqProto(mTopActivity), anyLong());
+ verifyOnActivityLaunchFinished(activity);
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 89723d14090b..d6bd1d07a786 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -19,6 +19,7 @@ package com.android.server.wm;
import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.os.Process.NOBODY_UID;
@@ -62,6 +63,7 @@ import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.never;
import android.app.ActivityOptions;
+import android.app.WindowConfiguration;
import android.app.servertransaction.ActivityConfigurationChangeItem;
import android.app.servertransaction.ClientTransaction;
import android.app.servertransaction.PauseActivityItem;
@@ -70,6 +72,7 @@ import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.graphics.Rect;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.platform.test.annotations.Presubmit;
@@ -106,7 +109,7 @@ public class ActivityRecordTests extends ActivityTestsBase {
@Before
public void setUp() throws Exception {
- mStack = new StackBuilder(mRootActivityContainer).build();
+ mStack = new StackBuilder(mRootWindowContainer).build();
mTask = mStack.getBottomMostTask();
mActivity = mTask.getTopNonFinishingActivity();
@@ -130,7 +133,7 @@ public class ActivityRecordTests extends ActivityTestsBase {
public void testStackCleanupOnTaskRemoval() {
mStack.removeChild(mTask, null /*reason*/);
// Stack should be gone on task removal.
- assertNull(mService.mRootActivityContainer.getStack(mStack.mStackId));
+ assertNull(mService.mRootWindowContainer.getStack(mStack.mStackId));
}
@Test
@@ -376,6 +379,64 @@ public class ActivityRecordTests extends ActivityTestsBase {
}
@Test
+ public void ignoreRequestedOrientationInFreeformWindows() {
+ mStack.setWindowingMode(WindowConfiguration.WINDOWING_MODE_FREEFORM);
+ final Rect stableRect = new Rect();
+ mStack.getDisplay().mDisplayContent.getStableRect(stableRect);
+ final boolean isScreenPortrait = stableRect.width() <= stableRect.height();
+ final Rect bounds = new Rect(stableRect);
+ if (isScreenPortrait) {
+ // Landscape bounds
+ final int newHeight = stableRect.width() - 10;
+ bounds.top = stableRect.top + (stableRect.height() - newHeight) / 2;
+ bounds.bottom = bounds.top + newHeight;
+ } else {
+ // Portrait bounds
+ final int newWidth = stableRect.height() - 10;
+ bounds.left = stableRect.left + (stableRect.width() - newWidth) / 2;
+ bounds.right = bounds.left + newWidth;
+ }
+ mTask.setBounds(bounds);
+
+ // Requests orientation that's different from its bounds.
+ mActivity.setRequestedOrientation(
+ isScreenPortrait ? SCREEN_ORIENTATION_PORTRAIT : SCREEN_ORIENTATION_LANDSCAPE);
+
+ // Asserts it has orientation derived from bounds.
+ assertEquals(isScreenPortrait ? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT,
+ mActivity.getConfiguration().orientation);
+ }
+
+ @Test
+ public void ignoreRequestedOrientationInSplitWindows() {
+ mStack.setWindowingMode(WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
+ final Rect stableRect = new Rect();
+ mStack.getDisplay().mDisplayContent.getStableRect(stableRect);
+ final boolean isScreenPortrait = stableRect.width() <= stableRect.height();
+ final Rect bounds = new Rect(stableRect);
+ if (isScreenPortrait) {
+ // Landscape bounds
+ final int newHeight = stableRect.width() - 10;
+ bounds.top = stableRect.top + (stableRect.height() - newHeight) / 2;
+ bounds.bottom = bounds.top + newHeight;
+ } else {
+ // Portrait bounds
+ final int newWidth = stableRect.height() - 10;
+ bounds.left = stableRect.left + (stableRect.width() - newWidth) / 2;
+ bounds.right = bounds.left + newWidth;
+ }
+ mTask.setBounds(bounds);
+
+ // Requests orientation that's different from its bounds.
+ mActivity.setRequestedOrientation(
+ isScreenPortrait ? SCREEN_ORIENTATION_PORTRAIT : SCREEN_ORIENTATION_LANDSCAPE);
+
+ // Asserts it has orientation derived from bounds.
+ assertEquals(isScreenPortrait ? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT,
+ mActivity.getConfiguration().orientation);
+ }
+
+ @Test
public void testShouldMakeActive_deferredResume() {
mActivity.setState(ActivityStack.ActivityState.STOPPED, "Testing");
@@ -424,7 +485,7 @@ public class ActivityRecordTests extends ActivityTestsBase {
.build();
mActivity.setState(ActivityStack.ActivityState.STOPPED, "Testing");
- final ActivityStack stack = new StackBuilder(mRootActivityContainer).build();
+ final ActivityStack stack = new StackBuilder(mRootWindowContainer).build();
try {
doReturn(false).when(stack).isStackTranslucent(any());
assertFalse(mStack.shouldBeVisible(null /* starting */));
@@ -540,7 +601,7 @@ public class ActivityRecordTests extends ActivityTestsBase {
// Set state to STOPPING, or ActivityRecord#activityStoppedLocked() call will be ignored.
mActivity.setState(STOPPING, "test");
- mActivity.activityStoppedLocked(savedState, persistentSavedState, "desc");
+ mActivity.activityStopped(savedState, persistentSavedState, "desc");
assertTrue(mActivity.hasSavedState());
assertEquals(savedState, mActivity.getSavedState());
assertEquals(persistentSavedState, mActivity.getPersistentSavedState());
@@ -548,7 +609,7 @@ public class ActivityRecordTests extends ActivityTestsBase {
// Sending 'null' for saved state can only happen due to timeout, so previously stored saved
// states should not be overridden.
mActivity.setState(STOPPING, "test");
- mActivity.activityStoppedLocked(null /* savedState */, null /* persistentSavedState */,
+ mActivity.activityStopped(null /* savedState */, null /* persistentSavedState */,
"desc");
assertTrue(mActivity.hasSavedState());
assertEquals(savedState, mActivity.getSavedState());
@@ -632,14 +693,14 @@ public class ActivityRecordTests extends ActivityTestsBase {
@Test
public void testFinishActivityIfPossible_adjustStackOrder() {
// Prepare the stacks with order (top to bottom): mStack, stack1, stack2.
- final ActivityStack stack1 = new StackBuilder(mRootActivityContainer).build();
+ final ActivityStack stack1 = new StackBuilder(mRootWindowContainer).build();
mStack.moveToFront("test");
// The stack2 is needed here for moving back to simulate the
// {@link DisplayContent#mPreferredTopFocusableStack} is cleared, so
// {@link DisplayContent#getFocusedStack} will rely on the order of focusable-and-visible
// stacks. Then when mActivity is finishing, its stack will be invisible (no running
// activities in the stack) that is the key condition to verify.
- final ActivityStack stack2 = new StackBuilder(mRootActivityContainer).build();
+ final ActivityStack stack2 = new StackBuilder(mRootWindowContainer).build();
stack2.moveToBack("test", stack2.getBottomMostTask());
assertTrue(mStack.isTopStackOnDisplay());
@@ -791,7 +852,7 @@ public class ActivityRecordTests extends ActivityTestsBase {
// Simulates that {@code currentTop} starts an existing activity from background (so its
// state is stopped) and the starting flow just goes to place it at top.
- final ActivityStack nextStack = new StackBuilder(mRootActivityContainer).build();
+ final ActivityStack nextStack = new StackBuilder(mRootWindowContainer).build();
final ActivityRecord nextTop = nextStack.getTopNonFinishingActivity();
nextTop.setState(STOPPED, "test");
@@ -913,7 +974,7 @@ public class ActivityRecordTests extends ActivityTestsBase {
// Add another stack to become focused and make the activity there visible. This way it
// simulates finishing in non-focused stack in split-screen.
- final ActivityStack stack = new StackBuilder(mRootActivityContainer).build();
+ final ActivityStack stack = new StackBuilder(mRootWindowContainer).build();
final ActivityRecord focusedActivity = stack.getTopMostActivity();
focusedActivity.nowVisible = true;
focusedActivity.mVisibleRequested = true;
@@ -930,7 +991,7 @@ public class ActivityRecordTests extends ActivityTestsBase {
*/
@Test
public void testDestroyIfPossible() {
- doReturn(false).when(mRootActivityContainer).resumeFocusedStacksTopActivities();
+ doReturn(false).when(mRootWindowContainer).resumeFocusedStacksTopActivities();
spyOn(mStack);
mActivity.destroyIfPossible("test");
@@ -950,7 +1011,7 @@ public class ActivityRecordTests extends ActivityTestsBase {
final ActivityStack homeStack = mActivity.getDisplay().getHomeStack();
homeStack.forAllTasks((t) -> { homeStack.removeChild(t, "test"); });
mActivity.finishing = true;
- doReturn(false).when(mRootActivityContainer).resumeFocusedStacksTopActivities();
+ doReturn(false).when(mRootWindowContainer).resumeFocusedStacksTopActivities();
spyOn(mStack);
// Try to destroy the last activity above the home stack.
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java
index 530adb590f75..9647178e6f9b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java
@@ -60,7 +60,7 @@ public class ActivityStackSupervisorTests extends ActivityTestsBase {
@Before
public void setUp() throws Exception {
- mFullscreenStack = mRootActivityContainer.getDefaultDisplay().createStack(
+ mFullscreenStack = mRootWindowContainer.getDefaultDisplay().createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
}
@@ -113,7 +113,7 @@ public class ActivityStackSupervisorTests extends ActivityTestsBase {
public void testHandleNonResizableTaskOnSecondaryDisplay() {
// Create an unresizable task on secondary display.
final DisplayContent newDisplay = addNewDisplayContentAt(DisplayContent.POSITION_TOP);
- final ActivityStack stack = new StackBuilder(mRootActivityContainer)
+ final ActivityStack stack = new StackBuilder(mRootWindowContainer)
.setDisplay(newDisplay).build();
final ActivityRecord unresizableActivity = stack.getTopNonFinishingActivity();
final Task task = unresizableActivity.getTask();
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
index 8a1a10d6139a..c24ce2bf7473 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -83,7 +83,7 @@ public class ActivityStackTests extends ActivityTestsBase {
@Before
public void setUp() throws Exception {
- mDefaultDisplay = mRootActivityContainer.getDefaultDisplay();
+ mDefaultDisplay = mRootWindowContainer.getDefaultDisplay();
mStack = mDefaultDisplay.createStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD,
true /* onTop */);
spyOn(mStack);
@@ -107,7 +107,7 @@ public class ActivityStackTests extends ActivityTestsBase {
r.setState(RESUMED, "testResumedActivityFromTaskReparenting");
assertEquals(r, mStack.getResumedActivity());
- final ActivityStack destStack = mRootActivityContainer.getDefaultDisplay().createStack(
+ final ActivityStack destStack = mRootWindowContainer.getDefaultDisplay().createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
mTask.reparent(destStack, true /* toTop */, Task.REPARENT_KEEP_STACK_AT_FRONT,
@@ -125,7 +125,7 @@ public class ActivityStackTests extends ActivityTestsBase {
r.setState(RESUMED, "testResumedActivityFromActivityReparenting");
assertEquals(r, mStack.getResumedActivity());
- final ActivityStack destStack = mRootActivityContainer.getDefaultDisplay().createStack(
+ final ActivityStack destStack = mRootWindowContainer.getDefaultDisplay().createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
mTask.reparent(destStack, true /*toTop*/, REPARENT_MOVE_STACK_TO_FRONT, false, false,
"testResumedActivityFromActivityReparenting");
@@ -238,8 +238,8 @@ public class ActivityStackTests extends ActivityTestsBase {
.setUid(UserHandle.PER_USER_RANGE * 2).build();
taskOverlay.mTaskOverlay = true;
- final RootActivityContainer.FindTaskResult result =
- new RootActivityContainer.FindTaskResult();
+ final RootWindowContainer.FindTaskResult result =
+ new RootWindowContainer.FindTaskResult();
result.process(r, mStack);
assertEquals(r, task.getTopNonFinishingActivity(false /* includeOverlays */));
@@ -264,14 +264,14 @@ public class ActivityStackTests extends ActivityTestsBase {
// Using target activity to find task.
final ActivityRecord r1 = new ActivityBuilder(mService).setComponent(
target).setTargetActivity(targetActivity).build();
- RootActivityContainer.FindTaskResult result = new RootActivityContainer.FindTaskResult();
+ RootWindowContainer.FindTaskResult result = new RootWindowContainer.FindTaskResult();
result.process(r1, mStack);
assertThat(result.mRecord).isNotNull();
// Using alias activity to find task.
final ActivityRecord r2 = new ActivityBuilder(mService).setComponent(
alias).setTargetActivity(targetActivity).build();
- result = new RootActivityContainer.FindTaskResult();
+ result = new RootWindowContainer.FindTaskResult();
result.process(r2, mStack);
assertThat(result.mRecord).isNotNull();
}
@@ -825,7 +825,7 @@ public class ActivityStackTests extends ActivityTestsBase {
mDefaultDisplay.positionStackAtBottom(stack);
}
} else {
- stack = new StackBuilder(mRootActivityContainer)
+ stack = new StackBuilder(mRootWindowContainer)
.setDisplay(display)
.setWindowingMode(windowingMode)
.setActivityType(activityType)
@@ -845,7 +845,7 @@ public class ActivityStackTests extends ActivityTestsBase {
mStack.mResumedActivity = secondActivity;
// Note the activities have non-null ActivityRecord.app, so it won't remove directly.
- mRootActivityContainer.mFinishDisabledPackageActivitiesHelper.process(
+ mRootWindowContainer.mFinishDisabledPackageActivitiesHelper.process(
firstActivity.packageName, null /* filterByClasses */, true /* doit */,
true /* evenPersistent */, UserHandle.USER_ALL);
@@ -874,7 +874,7 @@ public class ActivityStackTests extends ActivityTestsBase {
assertEquals(2, mTask.getChildCount());
- mRootActivityContainer.mFinishDisabledPackageActivitiesHelper.process(
+ mRootWindowContainer.mFinishDisabledPackageActivitiesHelper.process(
activity.packageName, null /* filterByClasses */, true /* doit */,
true /* evenPersistent */, UserHandle.USER_ALL);
@@ -901,7 +901,7 @@ public class ActivityStackTests extends ActivityTestsBase {
assertEquals(2, mTask.getChildCount());
- mStack.handleAppDiedLocked(secondActivity.app);
+ mRootWindowContainer.handleAppDied(secondActivity.app);
assertFalse(mTask.hasChild());
assertFalse(mStack.hasChild());
@@ -915,7 +915,7 @@ public class ActivityStackTests extends ActivityTestsBase {
activity.launchCount = 1;
activity.setSavedState(null /* savedState */);
- mStack.handleAppDiedLocked(activity.app);
+ mRootWindowContainer.handleAppDied(activity.app);
assertEquals(1, mTask.getChildCount());
assertEquals(1, mStack.getChildCount());
@@ -929,7 +929,7 @@ public class ActivityStackTests extends ActivityTestsBase {
activity.launchCount = 3;
activity.setSavedState(null /* savedState */);
- mStack.handleAppDiedLocked(activity.app);
+ mRootWindowContainer.handleAppDied(activity.app);
assertFalse(mTask.hasChild());
assertFalse(mStack.hasChild());
@@ -943,7 +943,7 @@ public class ActivityStackTests extends ActivityTestsBase {
activity.launchCount = 1;
activity.setSavedState(null /* savedState */);
- mStack.handleAppDiedLocked(activity.app);
+ mRootWindowContainer.handleAppDied(activity.app);
assertEquals(1, mTask.getChildCount());
assertEquals(1, mStack.getChildCount());
@@ -957,7 +957,7 @@ public class ActivityStackTests extends ActivityTestsBase {
activity.launchCount = 3;
activity.setSavedState(null /* savedState */);
- mStack.handleAppDiedLocked(activity.app);
+ mRootWindowContainer.handleAppDied(activity.app);
assertFalse(mTask.hasChild());
assertFalse(mStack.hasChild());
@@ -1014,7 +1014,7 @@ public class ActivityStackTests extends ActivityTestsBase {
// should be destroyed immediately with updating configuration to restore original state.
final ActivityRecord activity1 = finishTopActivity(stack1);
assertEquals(DESTROYING, activity1.getState());
- verify(mRootActivityContainer).ensureVisibilityAndConfig(eq(null) /* starting */,
+ verify(mRootWindowContainer).ensureVisibilityAndConfig(eq(null) /* starting */,
eq(display.mDisplayId), anyBoolean(), anyBoolean());
}
@@ -1129,7 +1129,7 @@ public class ActivityStackTests extends ActivityTestsBase {
assertFalse(unknownAppVisibilityController.allResolved());
// Assume the top activity is going to resume and
- // {@link RootActivityContainer#cancelInitializingActivities} should clear the unknown
+ // {@link RootWindowContainer#cancelInitializingActivities} should clear the unknown
// visibility records that are occluded.
mStack.resumeTopActivityUncheckedLocked(null /* prev */, null /* options */);
// Assume the top activity relayouted, just remove it directly.
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java
index 11aac3cf046b..76a761ce0e10 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java
@@ -77,7 +77,7 @@ public class ActivityStartControllerTests extends ActivityTestsBase {
.setCreateTask(true)
.build();
final int startFlags = random.nextInt();
- final ActivityStack stack = mService.mRootActivityContainer.getDefaultDisplay().createStack(
+ final ActivityStack stack = mService.mRootWindowContainer.getDefaultDisplay().createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
final WindowProcessController wpc = new WindowProcessController(mService,
mService.mContext.getApplicationInfo(), "name", 12345,
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
index d78e3af85e96..399cf49ac06f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
@@ -90,7 +90,7 @@ public class ActivityStartInterceptorTest {
@Mock
private ActivityTaskManagerService mService;
@Mock
- private RootActivityContainer mRootActivityContainer;
+ private RootWindowContainer mRootWindowContainer;
@Mock
private ActivityStackSupervisor mSupervisor;
@Mock
@@ -114,7 +114,7 @@ public class ActivityStartInterceptorTest {
MockitoAnnotations.initMocks(this);
mService.mAmInternal = mAmInternal;
mInterceptor = new ActivityStartInterceptor(
- mService, mSupervisor, mRootActivityContainer, mContext);
+ mService, mSupervisor, mRootWindowContainer, mContext);
mInterceptor.setStates(TEST_USER_ID, TEST_REAL_CALLING_PID, TEST_REAL_CALLING_UID,
TEST_START_FLAGS, TEST_CALLING_PACKAGE);
@@ -137,8 +137,8 @@ public class ActivityStartInterceptorTest {
// Mock KeyguardManager
when(mContext.getSystemService(Context.KEYGUARD_SERVICE)).thenReturn(mKeyguardManager);
when(mKeyguardManager.createConfirmDeviceCredentialIntent(
- nullable(CharSequence.class), nullable(CharSequence.class), eq(TEST_USER_ID)))
- .thenReturn(CONFIRM_CREDENTIALS_INTENT);
+ nullable(CharSequence.class), nullable(CharSequence.class), eq(TEST_USER_ID),
+ eq(true))).thenReturn(CONFIRM_CREDENTIALS_INTENT);
// Mock PackageManager
when(mService.getPackageManager()).thenReturn(mPackageManager);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index 7e22dfcabc8e..b1132f6599fb 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -134,7 +134,7 @@ public class ActivityStarterTests extends ActivityTestsBase {
public void testUpdateLaunchBounds() {
// When in a non-resizeable stack, the task bounds should be updated.
final Task task = new TaskBuilder(mService.mStackSupervisor)
- .setStack(mService.mRootActivityContainer.getDefaultDisplay().createStack(
+ .setStack(mService.mRootWindowContainer.getDefaultDisplay().createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */))
.build();
final Rect bounds = new Rect(10, 10, 100, 100);
@@ -145,7 +145,7 @@ public class ActivityStarterTests extends ActivityTestsBase {
// When in a resizeable stack, the stack bounds should be updated as well.
final Task task2 = new TaskBuilder(mService.mStackSupervisor)
- .setStack(mService.mRootActivityContainer.getDefaultDisplay().createStack(
+ .setStack(mService.mRootWindowContainer.getDefaultDisplay().createStack(
WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */))
.build();
assertThat((Object) task2.getStack()).isInstanceOf(ActivityStack.class);
@@ -336,7 +336,7 @@ public class ActivityStarterTests extends ActivityTestsBase {
* Creates a {@link ActivityStarter} with default parameters and necessary mocks.
*
* @param launchFlags The intent flags to launch activity.
- * @param mockGetLaunchStack Whether to mock {@link RootActivityContainer#getLaunchStack} for
+ * @param mockGetLaunchStack Whether to mock {@link RootWindowContainer#getLaunchStack} for
* always launching to the testing stack. Set to false when allowing
* the activity can be launched to any stack that is decided by real
* implementation.
@@ -351,13 +351,13 @@ public class ActivityStarterTests extends ActivityTestsBase {
if (mockGetLaunchStack) {
// Instrument the stack and task used.
- final ActivityStack stack = mRootActivityContainer.getDefaultDisplay().createStack(
+ final ActivityStack stack = mRootWindowContainer.getDefaultDisplay().createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
// Direct starter to use spy stack.
- doReturn(stack).when(mRootActivityContainer)
+ doReturn(stack).when(mRootWindowContainer)
.getLaunchStack(any(), any(), any(), anyBoolean());
- doReturn(stack).when(mRootActivityContainer)
+ doReturn(stack).when(mRootWindowContainer)
.getLaunchStack(any(), any(), any(), anyBoolean(), any(), anyInt(), anyInt());
}
@@ -457,7 +457,7 @@ public class ActivityStarterTests extends ActivityTestsBase {
final ActivityStack focusStack = focusActivity.getActivityStack();
focusStack.moveToFront("testSplitScreenDeliverToTop");
- doReturn(reusableActivity).when(mRootActivityContainer).findTask(any(), anyInt());
+ doReturn(reusableActivity).when(mRootWindowContainer).findTask(any(), anyInt());
final int result = starter.setReason("testSplitScreenDeliverToTop").execute();
@@ -489,7 +489,7 @@ public class ActivityStarterTests extends ActivityTestsBase {
// Enter split-screen. Primary stack should have focus.
focusActivity.getActivityStack().setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
- doReturn(reusableActivity).when(mRootActivityContainer).findTask(any(), anyInt());
+ doReturn(reusableActivity).when(mRootWindowContainer).findTask(any(), anyInt());
final int result = starter.setReason("testSplitScreenMoveToFront").execute();
@@ -502,7 +502,7 @@ public class ActivityStarterTests extends ActivityTestsBase {
*/
@Test
public void testTaskModeViolation() {
- final DisplayContent display = mService.mRootActivityContainer.getDefaultDisplay();
+ final DisplayContent display = mService.mRootWindowContainer.getDefaultDisplay();
display.removeAllTasks();
assertNoTasks(display);
@@ -738,7 +738,7 @@ public class ActivityStarterTests extends ActivityTestsBase {
.setCreateTask(true).build();
finishingTopActivity.getActivityStack().moveToFront("finishingTopActivity");
- assertEquals(finishingTopActivity, mRootActivityContainer.topRunningActivity());
+ assertEquals(finishingTopActivity, mRootWindowContainer.topRunningActivity());
finishingTopActivity.finishing = true;
// Launch the bottom task of the target stack.
@@ -747,7 +747,7 @@ public class ActivityStarterTests extends ActivityTestsBase {
.setIntent(activity.intent)
.execute();
// The hierarchies of the activity should move to front.
- assertEquals(activity, mRootActivityContainer.topRunningActivity());
+ assertEquals(activity, mRootWindowContainer.topRunningActivity());
}
/**
@@ -802,7 +802,8 @@ public class ActivityStarterTests extends ActivityTestsBase {
// Create a secondary display with an activity.
final TestDisplayContent secondaryDisplay =
new TestDisplayContent.Builder(mService, 1000, 1500).build();
- mRootActivityContainer.addChild(secondaryDisplay, POSITION_TOP);
+ mRootWindowContainer.positionChildAt(POSITION_TOP, secondaryDisplay,
+ false /* includingParents */);
final ActivityRecord singleTaskActivity = createSingleTaskActivityOn(
secondaryDisplay.createStack(WINDOWING_MODE_FULLSCREEN,
ACTIVITY_TYPE_STANDARD, false /* onTop */));
@@ -969,7 +970,7 @@ public class ActivityStarterTests extends ActivityTestsBase {
final ActivityStarter starter = prepareStarter(0 /* flags */);
starter.mStartActivity = new ActivityBuilder(mService).build();
final Task task = new TaskBuilder(mService.mStackSupervisor)
- .setStack(mService.mRootActivityContainer.getDefaultDisplay().createStack(
+ .setStack(mService.mRootWindowContainer.getDefaultDisplay().createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */))
.setUserId(10)
.build();
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
index 591ed51efdb2..079c49f060ce 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
@@ -19,15 +19,31 @@ package com.android.server.wm;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.when;
import android.app.Activity;
import android.app.ActivityManager;
+import android.app.PictureInPictureParams;
+import android.app.servertransaction.ClientTransaction;
+import android.app.servertransaction.EnterPipRequestedItem;
import android.content.res.Configuration;
import android.graphics.Rect;
+import android.os.IBinder;
+import android.os.RemoteException;
import android.view.IDisplayWindowListener;
import android.view.WindowContainerTransaction;
@@ -36,6 +52,8 @@ import androidx.test.filters.MediumTest;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.MockitoSession;
import java.util.ArrayList;
@@ -49,6 +67,9 @@ import java.util.ArrayList;
@RunWith(WindowTestRunner.class)
public class ActivityTaskManagerServiceTests extends ActivityTestsBase {
+ private final ArgumentCaptor<ClientTransaction> mClientTransactionCaptor =
+ ArgumentCaptor.forClass(ClientTransaction.class);
+
@Before
public void setUp() throws Exception {
doReturn(false).when(mService).isBooting();
@@ -58,7 +79,7 @@ public class ActivityTaskManagerServiceTests extends ActivityTestsBase {
/** Verify that activity is finished correctly upon request. */
@Test
public void testActivityFinish() {
- final ActivityStack stack = new StackBuilder(mRootActivityContainer).build();
+ final ActivityStack stack = new StackBuilder(mRootWindowContainer).build();
final ActivityRecord activity = stack.getBottomMostTask().getTopNonFinishingActivity();
assertTrue("Activity must be finished", mService.finishActivity(activity.appToken,
0 /* resultCode */, null /* resultData */,
@@ -71,9 +92,42 @@ public class ActivityTaskManagerServiceTests extends ActivityTestsBase {
}
@Test
+ public void testOnPictureInPictureRequested() throws RemoteException {
+ final ActivityStack stack = new StackBuilder(mRootWindowContainer).build();
+ final ActivityRecord activity = stack.getBottomMostTask().getTopNonFinishingActivity();
+ ClientLifecycleManager lifecycleManager = mService.getLifecycleManager();
+ doNothing().when(lifecycleManager).scheduleTransaction(any());
+ doReturn(true).when(activity).checkEnterPictureInPictureState(anyString(), anyBoolean());
+
+ mService.requestPictureInPictureMode(activity.token);
+
+ verify(lifecycleManager).scheduleTransaction(mClientTransactionCaptor.capture());
+ final ClientTransaction transaction = mClientTransactionCaptor.getValue();
+ // Check that only an enter pip request item callback was scheduled.
+ assertEquals(1, transaction.getCallbacks().size());
+ assertTrue(transaction.getCallbacks().get(0) instanceof EnterPipRequestedItem);
+ // Check the activity lifecycle state remains unchanged.
+ assertNull(transaction.getLifecycleStateRequest());
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testOnPictureInPictureRequested_cannotEnterPip() throws RemoteException {
+ final ActivityStack stack = new StackBuilder(mRootWindowContainer).build();
+ final ActivityRecord activity = stack.getBottomMostTask().getTopNonFinishingActivity();
+ ClientLifecycleManager lifecycleManager = mService.getLifecycleManager();
+ doNothing().when(lifecycleManager).scheduleTransaction(any());
+ doReturn(false).when(activity).checkEnterPictureInPictureState(anyString(), anyBoolean());
+
+ mService.requestPictureInPictureMode(activity.token);
+
+ // Check enter no transactions with enter pip requests are made.
+ verify(lifecycleManager, times(0)).scheduleTransaction(any());
+ }
+
+ @Test
public void testTaskTransaction() {
removeGlobalMinSizeRestriction();
- final ActivityStack stack = new StackBuilder(mRootActivityContainer)
+ final ActivityStack stack = new StackBuilder(mRootWindowContainer)
.setWindowingMode(WINDOWING_MODE_FREEFORM).build();
final Task task = stack.getTopMostTask();
WindowContainerTransaction t = new WindowContainerTransaction();
@@ -86,7 +140,7 @@ public class ActivityTaskManagerServiceTests extends ActivityTestsBase {
@Test
public void testStackTransaction() {
removeGlobalMinSizeRestriction();
- final ActivityStack stack = new StackBuilder(mRootActivityContainer)
+ final ActivityStack stack = new StackBuilder(mRootWindowContainer)
.setWindowingMode(WINDOWING_MODE_FREEFORM).build();
ActivityManager.StackInfo info =
mService.getStackInfo(WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD);
@@ -135,7 +189,7 @@ public class ActivityTaskManagerServiceTests extends ActivityTestsBase {
Configuration c = new Configuration(newDisp1.getRequestedOverrideConfiguration());
c.windowConfiguration.setBounds(new Rect(0, 0, 1000, 1300));
newDisp1.onRequestedOverrideConfigurationChanged(c);
- mService.mRootActivityContainer.ensureVisibilityAndConfig(null /* starting */,
+ mService.mRootWindowContainer.ensureVisibilityAndConfig(null /* starting */,
newDisp1.mDisplayId, false /* markFrozenIfConfigChanged */,
false /* deferResume */);
assertEquals(0, added.size());
@@ -148,5 +202,43 @@ public class ActivityTaskManagerServiceTests extends ActivityTestsBase {
assertEquals(0, changed.size());
assertEquals(1, removed.size());
}
+
+ /*
+ a test to verify b/144045134 - ignore PIP mode request for destroyed activity.
+ mocks r.getParent() to return null to cause NPE inside enterPipRunnable#run() in
+ ActivityTaskMangerservice#enterPictureInPictureMode(), which rebooted the device.
+ It doesn't fully simulate the issue's reproduce steps, but this should suffice.
+ */
+ @Test
+ public void testEnterPipModeWhenRecordParentChangesToNull() {
+ MockitoSession mockSession = mockitoSession()
+ .initMocks(this)
+ .mockStatic(ActivityRecord.class)
+ .startMocking();
+
+ ActivityRecord record = mock(ActivityRecord.class);
+ IBinder token = mock(IBinder.class);
+ PictureInPictureParams params = mock(PictureInPictureParams.class);
+ record.pictureInPictureArgs = params;
+
+ //mock operations in private method ensureValidPictureInPictureActivityParamsLocked()
+ when(ActivityRecord.forTokenLocked(token)).thenReturn(record);
+ doReturn(true).when(record).supportsPictureInPicture();
+ doReturn(false).when(params).hasSetAspectRatio();
+
+ //mock other operations
+ doReturn(true).when(record)
+ .checkEnterPictureInPictureState("enterPictureInPictureMode", false);
+ doReturn(false).when(mService).isInPictureInPictureMode(any());
+ doReturn(false).when(mService).isKeyguardLocked();
+
+ //to simulate NPE
+ doReturn(null).when(record).getParent();
+
+ mService.enterPictureInPictureMode(token, params);
+ //if record's null parent is not handled gracefully, test will fail with NPE
+
+ mockSession.finishMocking();
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
index b72cc942594f..0f227246b468 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
@@ -18,7 +18,6 @@ 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_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
@@ -56,7 +55,7 @@ class ActivityTestsBase extends SystemServiceTestsBase {
final Context mContext = getInstrumentation().getTargetContext();
ActivityTaskManagerService mService;
- RootActivityContainer mRootActivityContainer;
+ RootWindowContainer mRootWindowContainer;
ActivityStackSupervisor mSupervisor;
// Default package name
@@ -74,7 +73,7 @@ class ActivityTestsBase extends SystemServiceTestsBase {
public void setUpBase() {
mService = mSystemServicesTestRule.getActivityTaskManagerService();
mSupervisor = mService.mStackSupervisor;
- mRootActivityContainer = mService.mRootActivityContainer;
+ mRootWindowContainer = mService.mRootWindowContainer;
}
/** Creates and adds a {@link TestDisplayContent} to supervisor at the given position. */
@@ -84,7 +83,7 @@ class ActivityTestsBase extends SystemServiceTestsBase {
/** Sets the default minimum task size to 1 so that tests can use small task sizes */
public void removeGlobalMinSizeRestriction() {
- mService.mRootActivityContainer.mDefaultMinSizeOfResizeableTaskDp = 1;
+ mService.mRootWindowContainer.mDefaultMinSizeOfResizeableTaskDp = 1;
}
/**
@@ -274,7 +273,7 @@ class ActivityTestsBase extends SystemServiceTestsBase {
activity.processName, activity.info.applicationInfo.uid);
// Resume top activities to make sure all other signals in the system are connected.
- mService.mRootActivityContainer.resumeFocusedStacksTopActivities();
+ mService.mRootWindowContainer.resumeFocusedStacksTopActivities();
return activity;
}
}
@@ -346,7 +345,7 @@ class ActivityTestsBase extends SystemServiceTestsBase {
Task build() {
if (mStack == null && mCreateStack) {
- mStack = mSupervisor.mRootActivityContainer.getDefaultDisplay().createStack(
+ mStack = mSupervisor.mRootWindowContainer.getDefaultDisplay().createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
spyOn(mStack);
}
@@ -380,7 +379,7 @@ class ActivityTestsBase extends SystemServiceTestsBase {
}
static class StackBuilder {
- private final RootActivityContainer mRootActivityContainer;
+ private final RootWindowContainer mRootWindowContainer;
private DisplayContent mDisplay;
private int mStackId = -1;
private int mWindowingMode = WINDOWING_MODE_UNDEFINED;
@@ -388,9 +387,9 @@ class ActivityTestsBase extends SystemServiceTestsBase {
private boolean mOnTop = true;
private boolean mCreateActivity = true;
- StackBuilder(RootActivityContainer root) {
- mRootActivityContainer = root;
- mDisplay = mRootActivityContainer.getDefaultDisplay();
+ StackBuilder(RootWindowContainer root) {
+ mRootWindowContainer = root;
+ mDisplay = mRootWindowContainer.getDefaultDisplay();
}
StackBuilder setWindowingMode(int windowingMode) {
@@ -426,32 +425,26 @@ class ActivityTestsBase extends SystemServiceTestsBase {
ActivityStack build() {
final int stackId = mStackId >= 0 ? mStackId : mDisplay.getNextStackId();
final ActivityStack stack;
- final ActivityStackSupervisor supervisor = mRootActivityContainer.mStackSupervisor;
- if (mWindowingMode == WINDOWING_MODE_PINNED) {
- stack = new ActivityStack(mDisplay, stackId, supervisor,
- mWindowingMode, ACTIVITY_TYPE_STANDARD, mOnTop);
- } else {
- stack = new ActivityStack(mDisplay, stackId, supervisor,
- mWindowingMode, mActivityType, mOnTop);
-
- if (mCreateActivity) {
- new ActivityBuilder(supervisor.mService)
- .setCreateTask(true)
- .setStack(stack)
- .build();
- if (mOnTop) {
- // We move the task to front again in order to regain focus after activity
- // added to the stack.
- // Or {@link DisplayContent#mPreferredTopFocusableStack} could be other
- // stacks (e.g. home stack).
- stack.moveToFront("createActivityStack");
- } else {
- stack.moveToBack("createActivityStack", null);
- }
+ final ActivityStackSupervisor supervisor = mRootWindowContainer.mStackSupervisor;
+
+ stack = mDisplay.createStackUnchecked(mWindowingMode, mActivityType, stackId, mOnTop);
+
+ if (mCreateActivity) {
+ new ActivityBuilder(supervisor.mService)
+ .setCreateTask(true)
+ .setStack(stack)
+ .build();
+ if (mOnTop) {
+ // We move the task to front again in order to regain focus after activity
+ // added to the stack. Or {@link DisplayContent#mPreferredTopFocusableStack}
+ // could be other stacks (e.g. home stack).
+ stack.moveToFront("createActivityStack");
+ } else {
+ stack.moveToBack("createActivityStack", null);
}
}
-
spyOn(stack);
+
doNothing().when(stack).startActivityLocked(
any(), any(), anyBoolean(), anyBoolean(), any());
diff --git a/services/tests/wmtests/src/com/android/server/wm/AnimatingActivityRegistryTest.java b/services/tests/wmtests/src/com/android/server/wm/AnimatingActivityRegistryTest.java
index c6203c5736fc..a39be565121f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AnimatingActivityRegistryTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AnimatingActivityRegistryTest.java
@@ -60,6 +60,7 @@ public class AnimatingActivityRegistryTest extends WindowTestsBase {
}
@Test
+ @FlakyTest(bugId = 144611135)
public void testDeferring() {
final ActivityRecord activity1 = createActivityRecord(mDisplayContent,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
index d415f25baab9..1311889d5605 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
@@ -19,6 +19,7 @@ package com.android.server.wm;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
import static android.view.WindowManager.TRANSIT_TASK_CHANGE_WINDOWING_MODE;
import static android.view.WindowManager.TRANSIT_TASK_CLOSE;
@@ -29,6 +30,7 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import android.platform.test.annotations.Presubmit;
+import android.util.ArraySet;
import android.view.WindowManager;
import androidx.test.filters.FlakyTest;
@@ -116,4 +118,358 @@ public class AppTransitionControllerTest extends WindowTestsBase {
assertTrue(mAppTransitionController.isTransitWithinTask(TRANSIT_ACTIVITY_OPEN, task));
assertFalse(mAppTransitionController.isTransitWithinTask(TRANSIT_TASK_OPEN, task));
}
+
+ @Test
+ public void testGetAnimationTargets_noHierarchicalAnimations() {
+ WindowManagerService.sHierarchicalAnimations = false;
+
+ // [DisplayContent] -+- [TaskStack1] - [Task1] - [ActivityRecord1] (opening, invisible)
+ // +- [TaskStack2] - [Task2] - [ActivityRecord2] (closing, visible)
+ final ActivityStack stack1 = createTaskStackOnDisplay(mDisplayContent);
+ final ActivityRecord activity1 = WindowTestUtils.createTestActivityRecord(stack1);
+ activity1.setVisible(false);
+ activity1.mVisibleRequested = true;
+
+ final ActivityStack stack2 = createTaskStackOnDisplay(mDisplayContent);
+ final ActivityRecord activity2 = WindowTestUtils.createTestActivityRecord(stack2);
+
+ final ArraySet<ActivityRecord> opening = new ArraySet<>();
+ opening.add(activity1);
+ final ArraySet<ActivityRecord> closing = new ArraySet<>();
+ closing.add(activity2);
+
+ // Don't promote when the flag is disabled.
+ assertEquals(
+ new ArraySet<>(new WindowContainer[]{activity1}),
+ AppTransitionController.getAnimationTargets(
+ opening, closing, true /* visible */));
+ assertEquals(
+ new ArraySet<>(new WindowContainer[]{activity2}),
+ AppTransitionController.getAnimationTargets(
+ opening, closing, false /* visible */));
+ }
+
+ @Test
+ public void testGetAnimationTargets_visibilityAlreadyUpdated() {
+ // [DisplayContent] -+- [TaskStack1] - [Task1] - [ActivityRecord1] (opening, visible)
+ // +- [TaskStack2] - [Task2] - [ActivityRecord2] (closing, invisible)
+ final ActivityStack stack1 = createTaskStackOnDisplay(mDisplayContent);
+ final ActivityRecord activity1 = WindowTestUtils.createTestActivityRecord(stack1);
+
+ final ActivityStack stack2 = createTaskStackOnDisplay(mDisplayContent);
+ final ActivityRecord activity2 = WindowTestUtils.createTestActivityRecord(stack2);
+ activity2.setVisible(false);
+ activity2.mVisibleRequested = false;
+
+ final ArraySet<ActivityRecord> opening = new ArraySet<>();
+ opening.add(activity1);
+ final ArraySet<ActivityRecord> closing = new ArraySet<>();
+ closing.add(activity2);
+
+ // No animation, since visibility of the opening and closing apps are already updated
+ // outside of AppTransition framework.
+ WindowManagerService.sHierarchicalAnimations = false;
+ assertEquals(
+ new ArraySet<>(),
+ AppTransitionController.getAnimationTargets(
+ opening, closing, true /* visible */));
+ assertEquals(
+ new ArraySet<>(),
+ AppTransitionController.getAnimationTargets(
+ opening, closing, false /* visible */));
+
+ WindowManagerService.sHierarchicalAnimations = true;
+ assertEquals(
+ new ArraySet<>(),
+ AppTransitionController.getAnimationTargets(
+ opening, closing, true /* visible */));
+ assertEquals(
+ new ArraySet<>(),
+ AppTransitionController.getAnimationTargets(
+ opening, closing, false /* visible */));
+ }
+
+ @Test
+ public void testGetAnimationTargets_exitingBeforeTransition() {
+ final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
+ final ActivityRecord activity = WindowTestUtils.createTestActivityRecord(stack);
+ activity.setVisible(false);
+ activity.mIsExiting = true;
+
+ final ArraySet<ActivityRecord> closing = new ArraySet<>();
+ closing.add(activity);
+
+ // Animate closing apps even if it's not visible when it is exiting before we had a chance
+ // to play the transition animation.
+ WindowManagerService.sHierarchicalAnimations = false;
+ assertEquals(
+ new ArraySet<>(new WindowContainer[]{activity}),
+ AppTransitionController.getAnimationTargets(
+ new ArraySet<>(), closing, false /* visible */));
+
+ WindowManagerService.sHierarchicalAnimations = true;
+ assertEquals(
+ new ArraySet<>(new WindowContainer[]{stack}),
+ AppTransitionController.getAnimationTargets(
+ new ArraySet<>(), closing, false /* visible */));
+ }
+
+ @Test
+ public void testGetAnimationTargets_windowsAreBeingReplaced() {
+ // [DisplayContent] -+- [TaskStack1] - [Task1] - [ActivityRecord1] (opening, visible)
+ // +- [AppWindow1] (being-replaced)
+ // +- [TaskStack2] - [Task2] - [ActivityRecord2] (closing, invisible)
+ // +- [AppWindow2] (being-replaced)
+ final ActivityStack stack1 = createTaskStackOnDisplay(mDisplayContent);
+ final ActivityRecord activity1 = WindowTestUtils.createTestActivityRecord(stack1);
+ final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(
+ TYPE_BASE_APPLICATION);
+ attrs.setTitle("AppWindow1");
+ final WindowTestUtils.TestWindowState appWindow1 = createWindowState(attrs, activity1);
+ appWindow1.mWillReplaceWindow = true;
+ activity1.addWindow(appWindow1);
+
+ final ActivityStack stack2 = createTaskStackOnDisplay(mDisplayContent);
+ final ActivityRecord activity2 = WindowTestUtils.createTestActivityRecord(stack2);
+ activity2.setVisible(false);
+ activity2.mVisibleRequested = false;
+ attrs.setTitle("AppWindow2");
+ final WindowTestUtils.TestWindowState appWindow2 = createWindowState(attrs, activity2);
+ appWindow2.mWillReplaceWindow = true;
+ activity2.addWindow(appWindow2);
+
+ final ArraySet<ActivityRecord> opening = new ArraySet<>();
+ opening.add(activity1);
+ final ArraySet<ActivityRecord> closing = new ArraySet<>();
+ closing.add(activity2);
+
+ // Animate opening apps even if it's already visible in case its windows are being replaced.
+ // Don't animate closing apps if it's already invisible even though its windows are being
+ // replaced.
+ WindowManagerService.sHierarchicalAnimations = false;
+ assertEquals(
+ new ArraySet<>(new WindowContainer[]{activity1}),
+ AppTransitionController.getAnimationTargets(
+ opening, closing, true /* visible */));
+ assertEquals(
+ new ArraySet<>(new WindowContainer[]{}),
+ AppTransitionController.getAnimationTargets(
+ opening, closing, false /* visible */));
+
+ WindowManagerService.sHierarchicalAnimations = true;
+ assertEquals(
+ new ArraySet<>(new WindowContainer[]{stack1}),
+ AppTransitionController.getAnimationTargets(
+ opening, closing, true /* visible */));
+ assertEquals(
+ new ArraySet<>(new WindowContainer[]{}),
+ AppTransitionController.getAnimationTargets(
+ opening, closing, false /* visible */));
+ }
+
+ @Test
+ public void testGetAnimationTargets_openingClosingInDifferentTask() {
+ WindowManagerService.sHierarchicalAnimations = true;
+
+ // [DisplayContent] -+- [TaskStack1] - [Task1] -+- [ActivityRecord1] (opening, invisible)
+ // | +- [ActivityRecord2] (invisible)
+ // |
+ // +- [TaskStack2] - [Task2] -+- [ActivityRecord3] (closing, visible)
+ // +- [ActivityRecord4] (invisible)
+ final ActivityStack stack1 = createTaskStackOnDisplay(mDisplayContent);
+ final Task task1 = createTaskInStack(stack1, 0 /* userId */);
+ final ActivityRecord activity1 = WindowTestUtils.createActivityRecordInTask(
+ mDisplayContent, task1);
+ activity1.setVisible(false);
+ activity1.mVisibleRequested = true;
+ final ActivityRecord activity2 = WindowTestUtils.createActivityRecordInTask(
+ mDisplayContent, task1);
+ activity2.setVisible(false);
+ activity2.mVisibleRequested = false;
+
+ final ActivityStack stack2 = createTaskStackOnDisplay(mDisplayContent);
+ final Task task2 = createTaskInStack(stack2, 0 /* userId */);
+ final ActivityRecord activity3 = WindowTestUtils.createActivityRecordInTask(
+ mDisplayContent, task2);
+ final ActivityRecord activity4 = WindowTestUtils.createActivityRecordInTask(
+ mDisplayContent, task2);
+ activity4.setVisible(false);
+ activity4.mVisibleRequested = false;
+
+ final ArraySet<ActivityRecord> opening = new ArraySet<>();
+ opening.add(activity1);
+ final ArraySet<ActivityRecord> closing = new ArraySet<>();
+ closing.add(activity3);
+
+ // Promote animation targets to TaskStack level. Invisible ActivityRecords don't affect
+ // promotion decision.
+ assertEquals(
+ new ArraySet<>(new WindowContainer[]{stack1}),
+ AppTransitionController.getAnimationTargets(
+ opening, closing, true /* visible */));
+ assertEquals(
+ new ArraySet<>(new WindowContainer[]{stack2}),
+ AppTransitionController.getAnimationTargets(
+ opening, closing, false /* visible */));
+ }
+
+ @Test
+ public void testGetAnimationTargets_openingClosingInSameTask() {
+ WindowManagerService.sHierarchicalAnimations = true;
+
+ // [DisplayContent] - [TaskStack] - [Task] -+- [ActivityRecord1] (opening, invisible)
+ // +- [ActivityRecord2] (closing, visible)
+ final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
+ final Task task = createTaskInStack(stack, 0 /* userId */);
+ final ActivityRecord activity1 = WindowTestUtils.createActivityRecordInTask(
+ mDisplayContent, task);
+ activity1.setVisible(false);
+ activity1.mVisibleRequested = true;
+ final ActivityRecord activity2 = WindowTestUtils.createActivityRecordInTask(
+ mDisplayContent, task);
+
+ final ArraySet<ActivityRecord> opening = new ArraySet<>();
+ opening.add(activity1);
+ final ArraySet<ActivityRecord> closing = new ArraySet<>();
+ closing.add(activity2);
+
+ // Don't promote an animation target to Task level, since the same task contains both
+ // opening and closing app.
+ assertEquals(
+ new ArraySet<>(new WindowContainer[]{activity1}),
+ AppTransitionController.getAnimationTargets(
+ opening, closing, true /* visible */));
+ assertEquals(
+ new ArraySet<>(new WindowContainer[]{activity2}),
+ AppTransitionController.getAnimationTargets(
+ opening, closing, false /* visible */));
+ }
+
+ @Test
+ public void testGetAnimationTargets_animateOnlyTranslucentApp() {
+ WindowManagerService.sHierarchicalAnimations = true;
+
+ // [DisplayContent] -+- [TaskStack1] - [Task1] -+- [ActivityRecord1] (opening, invisible)
+ // | +- [ActivityRecord2] (visible)
+ // |
+ // +- [TaskStack2] - [Task2] -+- [ActivityRecord3] (closing, visible)
+ // +- [ActivityRecord4] (visible)
+
+ final ActivityStack stack1 = createTaskStackOnDisplay(mDisplayContent);
+ final Task task1 = createTaskInStack(stack1, 0 /* userId */);
+ final ActivityRecord activity1 = WindowTestUtils.createActivityRecordInTask(
+ mDisplayContent, task1);
+ activity1.setVisible(false);
+ activity1.mVisibleRequested = true;
+ activity1.setOccludesParent(false);
+
+ final ActivityRecord activity2 = WindowTestUtils.createActivityRecordInTask(
+ mDisplayContent, task1);
+
+ final ActivityStack stack2 = createTaskStackOnDisplay(mDisplayContent);
+ final Task task2 = createTaskInStack(stack2, 0 /* userId */);
+ final ActivityRecord activity3 = WindowTestUtils.createActivityRecordInTask(
+ mDisplayContent, task2);
+ activity3.setOccludesParent(false);
+ final ActivityRecord activity4 = WindowTestUtils.createActivityRecordInTask(
+ mDisplayContent, task2);
+
+ final ArraySet<ActivityRecord> opening = new ArraySet<>();
+ opening.add(activity1);
+ final ArraySet<ActivityRecord> closing = new ArraySet<>();
+ closing.add(activity3);
+
+ // Don't promote an animation target to Task level, since opening (closing) app is
+ // translucent and is displayed over other non-animating app.
+ assertEquals(
+ new ArraySet<>(new WindowContainer[]{activity1}),
+ AppTransitionController.getAnimationTargets(
+ opening, closing, true /* visible */));
+ assertEquals(
+ new ArraySet<>(new WindowContainer[]{activity3}),
+ AppTransitionController.getAnimationTargets(
+ opening, closing, false /* visible */));
+ }
+
+ @Test
+ public void testGetAnimationTargets_animateTranslucentAndOpaqueApps() {
+ WindowManagerService.sHierarchicalAnimations = true;
+
+ // [DisplayContent] -+- [TaskStack1] - [Task1] -+- [ActivityRecord1] (opening, invisible)
+ // | +- [ActivityRecord2] (opening, invisible)
+ // |
+ // +- [TaskStack2] - [Task2] -+- [ActivityRecord3] (closing, visible)
+ // +- [ActivityRecord4] (closing, visible)
+
+ final ActivityStack stack1 = createTaskStackOnDisplay(mDisplayContent);
+ final Task task1 = createTaskInStack(stack1, 0 /* userId */);
+ final ActivityRecord activity1 = WindowTestUtils.createActivityRecordInTask(
+ mDisplayContent, task1);
+ activity1.setVisible(false);
+ activity1.mVisibleRequested = true;
+ activity1.setOccludesParent(false);
+
+ final ActivityRecord activity2 = WindowTestUtils.createActivityRecordInTask(
+ mDisplayContent, task1);
+ activity2.setVisible(false);
+ activity2.mVisibleRequested = true;
+
+ final ActivityStack stack2 = createTaskStackOnDisplay(mDisplayContent);
+ final Task task2 = createTaskInStack(stack2, 0 /* userId */);
+ final ActivityRecord activity3 = WindowTestUtils.createActivityRecordInTask(
+ mDisplayContent, task2);
+ activity3.setOccludesParent(false);
+ final ActivityRecord activity4 = WindowTestUtils.createActivityRecordInTask(
+ mDisplayContent, task2);
+
+ final ArraySet<ActivityRecord> opening = new ArraySet<>();
+ opening.add(activity1);
+ opening.add(activity2);
+ final ArraySet<ActivityRecord> closing = new ArraySet<>();
+ closing.add(activity3);
+ closing.add(activity4);
+
+ // Promote animation targets to TaskStack level even though opening (closing) app is
+ // translucent as long as all visible siblings animate at the same time.
+ assertEquals(
+ new ArraySet<>(new WindowContainer[]{stack1}),
+ AppTransitionController.getAnimationTargets(
+ opening, closing, true /* visible */));
+ assertEquals(
+ new ArraySet<>(new WindowContainer[]{stack2}),
+ AppTransitionController.getAnimationTargets(
+ opening, closing, false /* visible */));
+ }
+
+ @Test
+ public void testGetAnimationTargets_stackContainsMultipleTasks() {
+ WindowManagerService.sHierarchicalAnimations = true;
+
+ // [DisplayContent] - [TaskStack] -+- [Task1] - [ActivityRecord1] (opening, invisible)
+ // +- [Task2] - [ActivityRecord2] (closing, visible)
+ final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
+ final Task task1 = createTaskInStack(stack, 0 /* userId */);
+ final ActivityRecord activity1 = WindowTestUtils.createActivityRecordInTask(
+ mDisplayContent, task1);
+ activity1.setVisible(false);
+ activity1.mVisibleRequested = true;
+ final Task task2 = createTaskInStack(stack, 0 /* userId */);
+ final ActivityRecord activity2 = WindowTestUtils.createActivityRecordInTask(
+ mDisplayContent, task2);
+
+ final ArraySet<ActivityRecord> opening = new ArraySet<>();
+ opening.add(activity1);
+ final ArraySet<ActivityRecord> closing = new ArraySet<>();
+ closing.add(activity2);
+
+ // Promote animation targets up to Task level, not beyond.
+ assertEquals(
+ new ArraySet<>(new WindowContainer[]{task1}),
+ AppTransitionController.getAnimationTargets(
+ opening, closing, true /* visible */));
+ assertEquals(
+ new ArraySet<>(new WindowContainer[]{task2}),
+ AppTransitionController.getAnimationTargets(
+ opening, closing, false /* visible */));
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
index 0c7fad46804c..70e5ee71b448 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -135,17 +135,19 @@ public class AppWindowTokenTests extends WindowTestsBase {
@Test
@Presubmit
- public void testGetTopFullscreenWindow() {
- assertNull(mActivity.getTopFullscreenWindow());
+ public void testGetTopFullscreenOpaqueWindow() {
+ assertNull(mActivity.getTopFullscreenOpaqueWindow());
final WindowState window1 = createWindow(null, TYPE_BASE_APPLICATION, mActivity, "window1");
final WindowState window11 = createWindow(null, TYPE_APPLICATION, mActivity, "window11");
final WindowState window12 = createWindow(null, TYPE_APPLICATION, mActivity, "window12");
- assertEquals(window12, mActivity.getTopFullscreenWindow());
+ assertEquals(window12, mActivity.getTopFullscreenOpaqueWindow());
window12.mAttrs.width = 500;
- assertEquals(window11, mActivity.getTopFullscreenWindow());
+ assertEquals(window11, mActivity.getTopFullscreenOpaqueWindow());
window11.mAttrs.width = 500;
- assertEquals(window1, mActivity.getTopFullscreenWindow());
+ assertEquals(window1, mActivity.getTopFullscreenOpaqueWindow());
+ window1.mAttrs.alpha = 0f;
+ assertNull(mActivity.getTopFullscreenOpaqueWindow());
mActivity.removeImmediately();
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index ccbafd4768c3..0758eeb6d418 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -514,6 +514,13 @@ public class DisplayContentTests extends WindowTestsBase {
// Prevent mInitialDisplayCutout from being updated from real display (e.g. null
// if the device has no cutout).
final DisplayContent dc = createDisplayNoUpdateDisplayInfo();
+ // This test assumes it's a top cutout on a portrait display, so if it happens to be a
+ // landscape display let's rotate it.
+ if (dc.mInitialDisplayHeight < dc.mInitialDisplayWidth) {
+ int tmp = dc.mInitialDisplayHeight;
+ dc.mInitialDisplayHeight = dc.mInitialDisplayWidth;
+ dc.mInitialDisplayWidth = tmp;
+ }
// Rotation may use real display info to compute bound, so here also uses the
// same width and height.
final int displayWidth = dc.mInitialDisplayWidth;
@@ -706,13 +713,13 @@ public class DisplayContentTests extends WindowTestsBase {
IWindowManager.FIXED_TO_USER_ROTATION_DISABLED);
final ActivityStack stack =
- new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootActivityContainer)
+ new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootWindowContainer)
.setDisplay(dc)
.build();
doReturn(true).when(stack).isVisible();
final ActivityStack freeformStack =
- new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootActivityContainer)
+ new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootWindowContainer)
.setDisplay(dc)
.setWindowingMode(WINDOWING_MODE_FREEFORM)
.build();
@@ -740,7 +747,7 @@ public class DisplayContentTests extends WindowTestsBase {
: SCREEN_ORIENTATION_LANDSCAPE;
final ActivityStack stack =
- new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootActivityContainer)
+ new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootWindowContainer)
.setDisplay(dc).build();
final ActivityRecord activity = stack.getTopMostTask().getTopNonFinishingActivity();
@@ -762,7 +769,7 @@ public class DisplayContentTests extends WindowTestsBase {
: SCREEN_ORIENTATION_LANDSCAPE;
final ActivityStack stack =
- new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootActivityContainer)
+ new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootWindowContainer)
.setDisplay(dc).build();
final ActivityRecord activity = stack.getTopMostTask().getTopNonFinishingActivity();
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
index de73645833de..5aece4577c52 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
@@ -272,7 +272,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase {
assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL);
final InsetsState state =
- mDisplayContent.getInsetsStateController().getInsetsForDispatch(mWindow);
+ mDisplayContent.getInsetsPolicy().getInsetsForDispatch(mWindow);
state.getSource(InsetsState.ITYPE_STATUS_BAR).setVisible(false);
state.getSource(InsetsState.ITYPE_NAVIGATION_BAR).setVisible(false);
mWindow.mAttrs.setFitIgnoreVisibility(true);
@@ -294,7 +294,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase {
assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL);
final InsetsState state =
- mDisplayContent.getInsetsStateController().getInsetsForDispatch(mWindow);
+ mDisplayContent.getInsetsPolicy().getInsetsForDispatch(mWindow);
state.getSource(InsetsState.ITYPE_STATUS_BAR).setVisible(false);
state.getSource(InsetsState.ITYPE_NAVIGATION_BAR).setVisible(false);
mWindow.mAttrs.setFitIgnoreVisibility(false);
@@ -452,7 +452,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase {
mWindow.mAttrs.flags =
FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
mWindow.mAttrs.subtreeSystemUiVisibility |= SYSTEM_UI_FLAG_FULLSCREEN;
- mDisplayContent.getInsetsStateController().getInsetsForDispatch(mWindow)
+ mDisplayContent.getInsetsPolicy().getInsetsForDispatch(mWindow)
.getSource(InsetsState.ITYPE_STATUS_BAR).setVisible(false);
addWindow(mWindow);
@@ -473,7 +473,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase {
mWindow.mAttrs.flags =
FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
mWindow.mAttrs.subtreeSystemUiVisibility |= SYSTEM_UI_FLAG_FULLSCREEN;
- mDisplayContent.getInsetsStateController().getInsetsForDispatch(mWindow)
+ mDisplayContent.getInsetsPolicy().getInsetsForDispatch(mWindow)
.getSource(InsetsState.ITYPE_STATUS_BAR).setVisible(false);
mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
addWindow(mWindow);
diff --git a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
index 84914bb8899b..ac4c228fda9a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
@@ -106,7 +106,7 @@ public class LaunchParamsPersisterTests extends ActivityTestsBase {
mDisplayUniqueId = "test:" + Integer.toString(sNextUniqueId++);
mTestDisplay = new TestDisplayContent.Builder(mService, 1000, 1500)
.setUniqueId(mDisplayUniqueId).build();
- when(mRootActivityContainer.getDisplayContent(eq(mDisplayUniqueId)))
+ when(mRootWindowContainer.getDisplayContent(eq(mDisplayUniqueId)))
.thenReturn(mTestDisplay);
ActivityStack stack = mTestDisplay.createStack(TEST_WINDOWING_MODE,
@@ -180,7 +180,7 @@ public class LaunchParamsPersisterTests extends ActivityTestsBase {
public void testReturnsEmptyDisplayIfDisplayIsNotFound() {
mTarget.saveTask(mTestTask);
- when(mRootActivityContainer.getDisplayContent(eq(mDisplayUniqueId))).thenReturn(null);
+ when(mRootWindowContainer.getDisplayContent(eq(mDisplayUniqueId))).thenReturn(null);
mTarget.getLaunchParams(mTestTask, null, mResult);
diff --git a/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java
index 0cc2626d9f89..039ff604f3f1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java
@@ -105,7 +105,6 @@ public class LockTaskControllerTest {
new DexmakerShareClassLoaderRule();
@Mock private ActivityStackSupervisor mSupervisor;
- @Mock private RootActivityContainer mRootActivityContainer;
@Mock private RootWindowContainer mRootWindowContainer;
@Mock private IDevicePolicyManager mDevicePolicyManager;
@Mock private IStatusBarService mStatusBarService;
@@ -134,8 +133,7 @@ public class LockTaskControllerTest {
}
mSupervisor.mRecentTasks = mRecentTasks;
- mSupervisor.mRootActivityContainer = mRootActivityContainer;
- mRootActivityContainer.mRootWindowContainer = mRootWindowContainer;
+ mSupervisor.mRootWindowContainer = mRootWindowContainer;
mLockTaskController = new LockTaskController(mContext, mSupervisor,
new ImmediatelyExecuteHandler());
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
index eaf4aa34a0a4..55a139ac5645 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
@@ -45,7 +45,6 @@ import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -117,7 +116,7 @@ public class RecentTasksTest extends ActivityTestsBase {
public void setUp() throws Exception {
mTaskPersister = new TestTaskPersister(mContext.getFilesDir());
spyOn(mTaskPersister);
- mDisplay = mRootActivityContainer.getDisplayContent(DEFAULT_DISPLAY);
+ mDisplay = mRootWindowContainer.getDisplayContent(DEFAULT_DISPLAY);
// Set the recent tasks we should use for testing in this class.
mRecentTasks = new TestRecentTasks(mService, mTaskPersister);
@@ -773,7 +772,7 @@ public class RecentTasksTest extends ActivityTestsBase {
ActivityStack stack = mTasks.get(2).getStack();
stack.moveToFront("", mTasks.get(2));
- doReturn(stack).when(mService.mRootActivityContainer).getTopDisplayFocusedStack();
+ doReturn(stack).when(mService.mRootWindowContainer).getTopDisplayFocusedStack();
// Simulate the reset from the timeout
mRecentTasks.resetFreezeTaskListReorderingOnTimeout();
@@ -1327,7 +1326,7 @@ public class RecentTasksTest extends ActivityTestsBase {
@Override
void getTasks(int maxNum, List<RunningTaskInfo> list, int ignoreActivityType,
- int ignoreWindowingMode, RootActivityContainer root,
+ int ignoreWindowingMode, RootWindowContainer root,
int callingUid, boolean allowed, boolean crossUser, ArraySet<Integer> profileIds) {
mLastAllowed = allowed;
super.getTasks(maxNum, list, ignoreActivityType, ignoreWindowingMode, root,
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
index 07be3e47859b..7e42c62d5ee2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
@@ -88,7 +88,7 @@ public class RecentsAnimationTest extends ActivityTestsBase {
@Test
public void testRecentsActivityVisiblility() {
- DisplayContent display = mRootActivityContainer.getDefaultDisplay();
+ DisplayContent display = mRootWindowContainer.getDefaultDisplay();
ActivityStack recentsStack = display.createStack(WINDOWING_MODE_FULLSCREEN,
ACTIVITY_TYPE_RECENTS, true /* onTop */);
ActivityRecord recentActivity = new ActivityBuilder(mService)
@@ -99,9 +99,9 @@ public class RecentsAnimationTest extends ActivityTestsBase {
ActivityRecord topActivity = new ActivityBuilder(mService).setCreateTask(true).build();
topActivity.getActivityStack().moveToFront("testRecentsActivityVisiblility");
- doCallRealMethod().when(mRootActivityContainer).ensureActivitiesVisible(
+ doCallRealMethod().when(mRootWindowContainer).ensureActivitiesVisible(
any() /* starting */, anyInt() /* configChanges */,
- anyBoolean() /* preserveWindows */);
+ anyBoolean() /* preserveWindows */, anyBoolean() /* notifyClients */);
RecentsAnimationCallbacks recentsAnimation = startRecentsActivity(
mRecentsComponent, true /* getRecentsAnimation */);
@@ -116,7 +116,7 @@ public class RecentsAnimationTest extends ActivityTestsBase {
@Test
public void testPreloadRecentsActivity() {
- final DisplayContent defaultDisplay = mRootActivityContainer.getDefaultDisplay();
+ final DisplayContent defaultDisplay = mRootWindowContainer.getDefaultDisplay();
final ActivityStack homeStack =
defaultDisplay.getStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME);
defaultDisplay.positionStackAtTop(homeStack, false /* includingParents */);
@@ -149,7 +149,7 @@ public class RecentsAnimationTest extends ActivityTestsBase {
mService.startRecentsActivity(recentsIntent, null /* assistDataReceiver */,
null /* recentsAnimationRunner */);
- DisplayContent display = mRootActivityContainer.getDefaultDisplay();
+ DisplayContent display = mRootWindowContainer.getDefaultDisplay();
ActivityStack recentsStack = display.getStack(WINDOWING_MODE_FULLSCREEN,
ACTIVITY_TYPE_RECENTS);
assertThat(recentsStack).isNotNull();
@@ -161,7 +161,7 @@ public class RecentsAnimationTest extends ActivityTestsBase {
assertFalse(recentsActivity.mVisibleRequested);
// Assume it is stopped to test next use case.
- recentsActivity.activityStoppedLocked(null /* newIcicle */, null /* newPersistentState */,
+ recentsActivity.activityStopped(null /* newIcicle */, null /* newPersistentState */,
null /* description */);
mSupervisor.mStoppingActivities.remove(recentsActivity);
@@ -178,7 +178,7 @@ public class RecentsAnimationTest extends ActivityTestsBase {
@Test
public void testRestartRecentsActivity() throws Exception {
// Have a recents activity that is not attached to its process (ActivityRecord.app = null).
- DisplayContent display = mRootActivityContainer.getDefaultDisplay();
+ DisplayContent display = mRootWindowContainer.getDefaultDisplay();
ActivityStack recentsStack = display.createStack(WINDOWING_MODE_FULLSCREEN,
ACTIVITY_TYPE_RECENTS, true /* onTop */);
ActivityRecord recentActivity = new ActivityBuilder(mService).setComponent(
@@ -190,9 +190,9 @@ public class RecentsAnimationTest extends ActivityTestsBase {
new ActivityBuilder(mService).setCreateTask(true).build().getActivityStack().moveToFront(
"testRestartRecentsActivity");
- doCallRealMethod().when(mRootActivityContainer).ensureActivitiesVisible(
+ doCallRealMethod().when(mRootWindowContainer).ensureActivitiesVisible(
any() /* starting */, anyInt() /* configChanges */,
- anyBoolean() /* preserveWindows */);
+ anyBoolean() /* preserveWindows */, anyBoolean() /* notifyClients */);
doReturn(app).when(mService).getProcessController(eq(recentActivity.processName), anyInt());
ClientLifecycleManager lifecycleManager = mService.getLifecycleManager();
doNothing().when(lifecycleManager).scheduleTransaction(any());
@@ -200,14 +200,14 @@ public class RecentsAnimationTest extends ActivityTestsBase {
startRecentsActivity();
// Recents activity must be restarted, but not be resumed while running recents animation.
- verify(mRootActivityContainer.mStackSupervisor).startSpecificActivity(
+ verify(mRootWindowContainer.mStackSupervisor).startSpecificActivity(
eq(recentActivity), eq(false), anyBoolean());
assertThat(recentActivity.getState()).isEqualTo(PAUSED);
}
@Test
public void testSetLaunchTaskBehindOfTargetActivity() {
- DisplayContent display = mRootActivityContainer.getDefaultDisplay();
+ DisplayContent display = mRootWindowContainer.getDefaultDisplay();
display.mDisplayContent.mBoundsAnimationController = mock(BoundsAnimationController.class);
ActivityStack homeStack = display.getHomeStack();
// Assume the home activity support recents.
@@ -253,7 +253,7 @@ public class RecentsAnimationTest extends ActivityTestsBase {
@Test
public void testCancelAnimationOnVisibleStackOrderChange() {
- DisplayContent display = mService.mRootActivityContainer.getDefaultDisplay();
+ DisplayContent display = mService.mRootWindowContainer.getDefaultDisplay();
display.mDisplayContent.mBoundsAnimationController = mock(BoundsAnimationController.class);
ActivityStack fullscreenStack = display.createStack(WINDOWING_MODE_FULLSCREEN,
ACTIVITY_TYPE_STANDARD, true /* onTop */);
@@ -299,7 +299,7 @@ public class RecentsAnimationTest extends ActivityTestsBase {
@Test
public void testKeepAnimationOnHiddenStackOrderChange() {
- DisplayContent display = mService.mRootActivityContainer.getDefaultDisplay();
+ DisplayContent display = mService.mRootWindowContainer.getDefaultDisplay();
ActivityStack fullscreenStack = display.createStack(WINDOWING_MODE_FULLSCREEN,
ACTIVITY_TYPE_STANDARD, true /* onTop */);
new ActivityBuilder(mService)
@@ -335,7 +335,7 @@ public class RecentsAnimationTest extends ActivityTestsBase {
@Test
public void testMultipleUserHomeActivity_findUserHomeTask() {
- DisplayContent display = mService.mRootActivityContainer.getDefaultDisplay();
+ DisplayContent display = mService.mRootWindowContainer.getDefaultDisplay();
ActivityStack homeStack = display.getStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME);
ActivityRecord otherUserHomeActivity = new ActivityBuilder(mService)
.setStack(homeStack)
@@ -353,9 +353,9 @@ public class RecentsAnimationTest extends ActivityTestsBase {
.build();
doReturn(TEST_USER_ID).when(mService).getCurrentUserId();
- doCallRealMethod().when(mRootActivityContainer).ensureActivitiesVisible(
+ doCallRealMethod().when(mRootWindowContainer).ensureActivitiesVisible(
any() /* starting */, anyInt() /* configChanges */,
- anyBoolean() /* preserveWindows */);
+ anyBoolean() /* preserveWindows */, anyBoolean() /* notifyClients */);
startRecentsActivity(otherUserHomeActivity.getTask().getBaseIntent().getComponent(),
true);
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
index 2d45a59d3fc5..9f092835b8d3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
@@ -27,6 +27,7 @@ import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.TYPE_VIRTUAL;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
@@ -36,7 +37,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
-import static com.android.server.wm.RootActivityContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE;
+import static com.android.server.wm.RootWindowContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -76,7 +77,7 @@ import java.util.List;
import java.util.function.Consumer;
/**
- * Tests for the {@link RootActivityContainer} class.
+ * Tests for the {@link RootWindowContainer} class.
*
* Build/Install/Run:
* atest WmTests:RootActivityContainerTests
@@ -89,8 +90,9 @@ public class RootActivityContainerTests extends ActivityTestsBase {
@Before
public void setUp() throws Exception {
- mFullscreenStack = mRootActivityContainer.getDefaultDisplay().createStack(
+ mFullscreenStack = mRootWindowContainer.getDefaultDisplay().createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+ doNothing().when(mService).updateSleepIfNeededLocked();
}
/**
@@ -99,8 +101,8 @@ public class RootActivityContainerTests extends ActivityTestsBase {
*/
@Test
public void testRestoringInvalidTask() {
- mRootActivityContainer.getDefaultDisplay().removeAllTasks();
- Task task = mRootActivityContainer.anyTaskForId(0 /*taskId*/,
+ mRootWindowContainer.getDefaultDisplay().removeAllTasks();
+ Task task = mRootWindowContainer.anyTaskForId(0 /*taskId*/,
MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE, null, false /* onTop */);
assertNull(task);
}
@@ -125,7 +127,7 @@ public class RootActivityContainerTests extends ActivityTestsBase {
// Move first activity to pinned stack.
final Rect sourceBounds = new Rect();
- mRootActivityContainer.moveActivityToPinnedStack(firstActivity, sourceBounds,
+ mRootWindowContainer.moveActivityToPinnedStack(firstActivity, sourceBounds,
0f /*aspectRatio*/, "initialMove");
final DisplayContent display = mFullscreenStack.getDisplay();
@@ -135,7 +137,7 @@ public class RootActivityContainerTests extends ActivityTestsBase {
ensureStackPlacement(mFullscreenStack, secondActivity);
// Move second activity to pinned stack.
- mRootActivityContainer.moveActivityToPinnedStack(secondActivity, sourceBounds,
+ mRootWindowContainer.moveActivityToPinnedStack(secondActivity, sourceBounds,
0f /*aspectRatio*/, "secondMove");
// Need to get stacks again as a new instance might have been created.
@@ -166,9 +168,9 @@ public class RootActivityContainerTests extends ActivityTestsBase {
@Test
public void testApplySleepTokens() {
- final DisplayContent display = mRootActivityContainer.getDefaultDisplay();
+ final DisplayContent display = mRootWindowContainer.getDefaultDisplay();
final KeyguardController keyguard = mSupervisor.getKeyguardController();
- final ActivityStack stack = new StackBuilder(mRootActivityContainer)
+ final ActivityStack stack = new StackBuilder(mRootWindowContainer)
.setCreateActivity(false)
.setDisplay(display)
.setOnTop(false)
@@ -214,7 +216,7 @@ public class RootActivityContainerTests extends ActivityTestsBase {
doReturn(isFocusedStack).when(stack).isFocusedStackOnDisplay();
doReturn(isFocusedStack ? stack : null).when(display).getFocusedStack();
- mRootActivityContainer.applySleepTokens(true);
+ mRootWindowContainer.applySleepTokens(true);
verify(stack, times(expectWakeFromSleep ? 1 : 0)).awakeFromSleepingLocked();
verify(stack, times(expectResumeTopActivity ? 1 : 0)).resumeTopActivityUncheckedLocked(
null /* target */, null /* targetOptions */);
@@ -225,9 +227,9 @@ public class RootActivityContainerTests extends ActivityTestsBase {
*/
@Test
public void testRemovingStackOnAppCrash() {
- final DisplayContent defaultDisplay = mRootActivityContainer.getDefaultDisplay();
+ final DisplayContent defaultDisplay = mRootWindowContainer.getDefaultDisplay();
final int originalStackCount = defaultDisplay.getStackCount();
- final ActivityStack stack = mRootActivityContainer.getDefaultDisplay().createStack(
+ final ActivityStack stack = mRootWindowContainer.getDefaultDisplay().createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */);
final ActivityRecord firstActivity = new ActivityBuilder(mService).setCreateTask(true)
.setStack(stack).build();
@@ -236,7 +238,7 @@ public class RootActivityContainerTests extends ActivityTestsBase {
// Let's pretend that the app has crashed.
firstActivity.app.setThread(null);
- mRootActivityContainer.finishTopCrashedActivities(firstActivity.app, "test");
+ mRootWindowContainer.finishTopCrashedActivities(firstActivity.app, "test");
// Verify that the stack was removed.
assertEquals(originalStackCount, defaultDisplay.getStackCount());
@@ -244,22 +246,22 @@ public class RootActivityContainerTests extends ActivityTestsBase {
@Test
public void testFocusability() {
- final ActivityStack stack = mRootActivityContainer.getDefaultDisplay().createStack(
+ final ActivityStack stack = mRootWindowContainer.getDefaultDisplay().createStack(
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, true /* onTop */);
final ActivityRecord activity = new ActivityBuilder(mService).setCreateTask(true)
.setStack(stack).build();
// Under split screen primary we should be focusable when not minimized
- mRootActivityContainer.setDockedStackMinimized(false);
+ mRootWindowContainer.setDockedStackMinimized(false);
assertTrue(stack.isFocusable());
assertTrue(activity.isFocusable());
// Under split screen primary we should not be focusable when minimized
- mRootActivityContainer.setDockedStackMinimized(true);
+ mRootWindowContainer.setDockedStackMinimized(true);
assertFalse(stack.isFocusable());
assertFalse(activity.isFocusable());
- final ActivityStack pinnedStack = mRootActivityContainer.getDefaultDisplay().createStack(
+ final ActivityStack pinnedStack = mRootWindowContainer.getDefaultDisplay().createStack(
WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
final ActivityRecord pinnedActivity = new ActivityBuilder(mService).setCreateTask(true)
.setStack(pinnedStack).build();
@@ -288,7 +290,7 @@ public class RootActivityContainerTests extends ActivityTestsBase {
@Test
public void testSplitScreenPrimaryChosenWhenTopActivityLaunchedToSecondary() {
// Create primary split-screen stack with a task and an activity.
- final ActivityStack primaryStack = mRootActivityContainer.getDefaultDisplay()
+ final ActivityStack primaryStack = mRootWindowContainer.getDefaultDisplay()
.createStack(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD,
true /* onTop */);
final Task task = new TaskBuilder(mSupervisor).setStack(primaryStack).build();
@@ -299,7 +301,7 @@ public class RootActivityContainerTests extends ActivityTestsBase {
final ActivityOptions options = ActivityOptions.makeBasic();
options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
final ActivityStack result =
- mRootActivityContainer.getLaunchStack(r, options, task, true /* onTop */);
+ mRootWindowContainer.getLaunchStack(r, options, task, true /* onTop */);
// Assert that the primary stack is returned.
assertEquals(primaryStack, result);
@@ -315,7 +317,7 @@ public class RootActivityContainerTests extends ActivityTestsBase {
final Rect stackSize = new Rect(0, 0, 300, 300);
// Create primary split-screen stack with a task.
- final ActivityStack primaryStack = new StackBuilder(mRootActivityContainer)
+ final ActivityStack primaryStack = new StackBuilder(mRootWindowContainer)
.setActivityType(ACTIVITY_TYPE_STANDARD)
.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)
.setOnTop(true)
@@ -336,14 +338,14 @@ public class RootActivityContainerTests extends ActivityTestsBase {
@Test
public void testFindTaskToMoveToFrontWhenRecentsOnTop() {
// Create stack/task on default display.
- final DisplayContent display = mRootActivityContainer.getDefaultDisplay();
- final ActivityStack targetStack = new StackBuilder(mRootActivityContainer)
+ final DisplayContent display = mRootWindowContainer.getDefaultDisplay();
+ final ActivityStack targetStack = new StackBuilder(mRootWindowContainer)
.setOnTop(false)
.build();
final Task targetTask = targetStack.getBottomMostTask();
// Create Recents on top of the display.
- final ActivityStack stack = new StackBuilder(mRootActivityContainer).setActivityType(
+ final ActivityStack stack = new StackBuilder(mRootWindowContainer).setActivityType(
ACTIVITY_TYPE_RECENTS).build();
final String reason = "findTaskToMoveToFront";
@@ -360,7 +362,7 @@ public class RootActivityContainerTests extends ActivityTestsBase {
@Test
public void testFindTaskToMoveToFrontWhenRecentsOnOtherDisplay() {
// Create stack/task on default display.
- final DisplayContent display = mRootActivityContainer.getDefaultDisplay();
+ final DisplayContent display = mRootWindowContainer.getDefaultDisplay();
final ActivityStack targetStack = display.createStack(WINDOWING_MODE_FULLSCREEN,
ACTIVITY_TYPE_STANDARD, false /* onTop */);
final Task targetTask = new TaskBuilder(mSupervisor).setStack(targetStack).build();
@@ -387,7 +389,7 @@ public class RootActivityContainerTests extends ActivityTestsBase {
@Test
public void testResumeActivityWhenNonTopmostStackIsTopFocused() {
// Create a stack at bottom.
- final DisplayContent display = mRootActivityContainer.getDefaultDisplay();
+ final DisplayContent display = mRootWindowContainer.getDefaultDisplay();
final ActivityStack targetStack = spy(display.createStack(WINDOWING_MODE_FULLSCREEN,
ACTIVITY_TYPE_STANDARD, false /* onTop */));
final Task task = new TaskBuilder(mSupervisor).setStack(targetStack).build();
@@ -397,10 +399,10 @@ public class RootActivityContainerTests extends ActivityTestsBase {
// Assume the stack is not at the topmost position (e.g. behind always-on-top stacks) but it
// is the current top focused stack.
assertFalse(targetStack.isTopStackOnDisplay());
- doReturn(targetStack).when(mRootActivityContainer).getTopDisplayFocusedStack();
+ doReturn(targetStack).when(mRootWindowContainer).getTopDisplayFocusedStack();
// Use the stack as target to resume.
- mRootActivityContainer.resumeFocusedStacksTopActivities(
+ mRootWindowContainer.resumeFocusedStacksTopActivities(
targetStack, activity, null /* targetOptions */);
// Verify the target stack should resume its activity.
@@ -415,20 +417,20 @@ public class RootActivityContainerTests extends ActivityTestsBase {
@Test
public void testResumeFocusedStacksStartsHomeActivity_NoActivities() {
mFullscreenStack.removeIfPossible();
- mService.mRootActivityContainer.getDisplayContent(DEFAULT_DISPLAY).getHomeStack()
+ mService.mRootWindowContainer.getDisplayContent(DEFAULT_DISPLAY).getHomeStack()
.removeIfPossible();
- mService.mRootActivityContainer.getDisplayContent(DEFAULT_DISPLAY)
+ mService.mRootWindowContainer.getDisplayContent(DEFAULT_DISPLAY)
.createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
- doReturn(true).when(mRootActivityContainer).resumeHomeActivity(any(), any(), anyInt());
+ doReturn(true).when(mRootWindowContainer).resumeHomeActivity(any(), any(), anyInt());
mService.setBooted(true);
// Trigger resume on all displays
- mRootActivityContainer.resumeFocusedStacksTopActivities();
+ mRootWindowContainer.resumeFocusedStacksTopActivities();
// Verify that home activity was started on the default display
- verify(mRootActivityContainer).resumeHomeActivity(any(), any(), eq(DEFAULT_DISPLAY));
+ verify(mRootWindowContainer).resumeHomeActivity(any(), any(), eq(DEFAULT_DISPLAY));
}
/**
@@ -438,9 +440,9 @@ public class RootActivityContainerTests extends ActivityTestsBase {
@Test
public void testResumeFocusedStacksStartsHomeActivity_ActivityOnSecondaryScreen() {
mFullscreenStack.removeIfPossible();
- mService.mRootActivityContainer.getDisplayContent(DEFAULT_DISPLAY).getHomeStack()
+ mService.mRootWindowContainer.getDisplayContent(DEFAULT_DISPLAY).getHomeStack()
.removeIfPossible();
- mService.mRootActivityContainer.getDisplayContent(DEFAULT_DISPLAY)
+ mService.mRootWindowContainer.getDisplayContent(DEFAULT_DISPLAY)
.createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
// Create an activity on secondary display.
@@ -451,15 +453,15 @@ public class RootActivityContainerTests extends ActivityTestsBase {
final Task task = new TaskBuilder(mSupervisor).setStack(stack).build();
new ActivityBuilder(mService).setTask(task).build();
- doReturn(true).when(mRootActivityContainer).resumeHomeActivity(any(), any(), anyInt());
+ doReturn(true).when(mRootWindowContainer).resumeHomeActivity(any(), any(), anyInt());
mService.setBooted(true);
// Trigger resume on all displays
- mRootActivityContainer.resumeFocusedStacksTopActivities();
+ mRootWindowContainer.resumeFocusedStacksTopActivities();
// Verify that home activity was started on the default display
- verify(mRootActivityContainer).resumeHomeActivity(any(), any(), eq(DEFAULT_DISPLAY));
+ verify(mRootWindowContainer).resumeHomeActivity(any(), any(), eq(DEFAULT_DISPLAY));
}
/**
@@ -469,7 +471,7 @@ public class RootActivityContainerTests extends ActivityTestsBase {
@Test
public void testResumeActivityLingeringTransition() {
// Create a stack at top.
- final DisplayContent display = mRootActivityContainer.getDefaultDisplay();
+ final DisplayContent display = mRootWindowContainer.getDefaultDisplay();
final ActivityStack targetStack = spy(display.createStack(WINDOWING_MODE_FULLSCREEN,
ACTIVITY_TYPE_STANDARD, false /* onTop */));
final Task task = new TaskBuilder(mSupervisor).setStack(targetStack).build();
@@ -480,7 +482,7 @@ public class RootActivityContainerTests extends ActivityTestsBase {
assertTrue(targetStack.isTopStackOnDisplay());
// Use the stack as target to resume.
- mRootActivityContainer.resumeFocusedStacksTopActivities();
+ mRootWindowContainer.resumeFocusedStacksTopActivities();
// Verify the lingering app transition is being executed because it's already resumed
verify(targetStack, times(1)).executeAppTransition(any());
@@ -489,7 +491,7 @@ public class RootActivityContainerTests extends ActivityTestsBase {
@Test
public void testResumeActivityLingeringTransition_notExecuted() {
// Create a stack at bottom.
- final DisplayContent display = mRootActivityContainer.getDefaultDisplay();
+ final DisplayContent display = mRootWindowContainer.getDefaultDisplay();
final ActivityStack targetStack = spy(display.createStack(WINDOWING_MODE_FULLSCREEN,
ACTIVITY_TYPE_STANDARD, false /* onTop */));
final Task task = new TaskBuilder(mSupervisor).setStack(targetStack).build();
@@ -499,10 +501,10 @@ public class RootActivityContainerTests extends ActivityTestsBase {
// Assume the stack is at the topmost position
assertFalse(targetStack.isTopStackOnDisplay());
- doReturn(targetStack).when(mRootActivityContainer).getTopDisplayFocusedStack();
+ doReturn(targetStack).when(mRootWindowContainer).getTopDisplayFocusedStack();
// Use the stack as target to resume.
- mRootActivityContainer.resumeFocusedStacksTopActivities();
+ mRootWindowContainer.resumeFocusedStacksTopActivities();
// Verify the lingering app transition is being executed because it's already resumed
verify(targetStack, never()).executeAppTransition(any());
@@ -521,14 +523,14 @@ public class RootActivityContainerTests extends ActivityTestsBase {
new TestDisplayContent.Builder(mService, 1000, 1500)
.setSystemDecorations(true).build();
- doReturn(true).when(mRootActivityContainer)
+ doReturn(true).when(mRootWindowContainer)
.ensureVisibilityAndConfig(any(), anyInt(), anyBoolean(), anyBoolean());
- doReturn(true).when(mRootActivityContainer).canStartHomeOnDisplay(
+ doReturn(true).when(mRootWindowContainer).canStartHomeOnDisplay(
any(), anyInt(), anyBoolean());
- mRootActivityContainer.startHomeOnAllDisplays(0, "testStartHome");
+ mRootWindowContainer.startHomeOnAllDisplays(0, "testStartHome");
- assertTrue(mRootActivityContainer.getDefaultDisplay().getTopStack().isActivityTypeHome());
+ assertTrue(mRootWindowContainer.getDefaultDisplay().getTopStack().isActivityTypeHome());
assertNotNull(secondDisplay.getTopStack());
assertTrue(secondDisplay.getTopStack().isActivityTypeHome());
}
@@ -544,8 +546,8 @@ public class RootActivityContainerTests extends ActivityTestsBase {
try {
mService.mAmInternal.setBooting(false);
mService.mAmInternal.setBooted(false);
- mRootActivityContainer.onDisplayAdded(displayId);
- verify(mRootActivityContainer, never()).startHomeOnDisplay(anyInt(), any(), anyInt());
+ mRootWindowContainer.onDisplayAdded(displayId);
+ verify(mRootWindowContainer, never()).startHomeOnDisplay(anyInt(), any(), anyInt());
} finally {
mService.mAmInternal.setBooting(isBooting);
mService.mAmInternal.setBooted(isBooted);
@@ -564,17 +566,17 @@ public class RootActivityContainerTests extends ActivityTestsBase {
// Can not start home if we don't want to start home while home is being instrumented.
doReturn(true).when(app).isInstrumenting();
- assertFalse(mRootActivityContainer.canStartHomeOnDisplay(info, DEFAULT_DISPLAY,
+ assertFalse(mRootWindowContainer.canStartHomeOnDisplay(info, DEFAULT_DISPLAY,
false /* allowInstrumenting*/));
// Can start home for other cases.
- assertTrue(mRootActivityContainer.canStartHomeOnDisplay(info, DEFAULT_DISPLAY,
+ assertTrue(mRootWindowContainer.canStartHomeOnDisplay(info, DEFAULT_DISPLAY,
true /* allowInstrumenting*/));
doReturn(false).when(app).isInstrumenting();
- assertTrue(mRootActivityContainer.canStartHomeOnDisplay(info, DEFAULT_DISPLAY,
+ assertTrue(mRootWindowContainer.canStartHomeOnDisplay(info, DEFAULT_DISPLAY,
false /* allowInstrumenting*/));
- assertTrue(mRootActivityContainer.canStartHomeOnDisplay(info, DEFAULT_DISPLAY,
+ assertTrue(mRootWindowContainer.canStartHomeOnDisplay(info, DEFAULT_DISPLAY,
true /* allowInstrumenting*/));
}
@@ -589,17 +591,17 @@ public class RootActivityContainerTests extends ActivityTestsBase {
.setSystemDecorations(true).build();
// Use invalid user id to let StorageManager.isUserKeyUnlocked() return false.
- final int currentUser = mRootActivityContainer.mCurrentUser;
- mRootActivityContainer.mCurrentUser = -1;
+ final int currentUser = mRootWindowContainer.mCurrentUser;
+ mRootWindowContainer.mCurrentUser = -1;
- mRootActivityContainer.startHomeOnDisplay(0 /* userId */, "testStartSecondaryHome",
+ mRootWindowContainer.startHomeOnDisplay(0 /* userId */, "testStartSecondaryHome",
secondDisplay.mDisplayId, true /* allowInstrumenting */, true /* fromHomeKey */);
try {
- verify(mRootActivityContainer, never()).resolveSecondaryHomeActivity(anyInt(),
+ verify(mRootWindowContainer, never()).resolveSecondaryHomeActivity(anyInt(),
anyInt());
} finally {
- mRootActivityContainer.mCurrentUser = currentUser;
+ mRootWindowContainer.mCurrentUser = currentUser;
}
}
@@ -614,10 +616,10 @@ public class RootActivityContainerTests extends ActivityTestsBase {
new TestDisplayContent.Builder(mService, 1000, 1500)
.setSystemDecorations(false).build();
- mRootActivityContainer.startHomeOnDisplay(0 /* userId */, "testStartSecondaryHome",
+ mRootWindowContainer.startHomeOnDisplay(0 /* userId */, "testStartSecondaryHome",
secondDisplay.mDisplayId, true /* allowInstrumenting */, true /* fromHomeKey */);
- verify(mRootActivityContainer, never()).resolveSecondaryHomeActivity(anyInt(), anyInt());
+ verify(mRootWindowContainer, never()).resolveSecondaryHomeActivity(anyInt(), anyInt());
}
/**
@@ -630,10 +632,10 @@ public class RootActivityContainerTests extends ActivityTestsBase {
info.applicationInfo = new ApplicationInfo();
info.applicationInfo.packageName = "android";
info.name = ResolverActivity.class.getName();
- doReturn(info).when(mRootActivityContainer).resolveHomeActivity(anyInt(), any());
+ doReturn(info).when(mRootWindowContainer).resolveHomeActivity(anyInt(), any());
- mRootActivityContainer.startHomeOnDisplay(0 /* userId */, "test", DEFAULT_DISPLAY);
- final ActivityRecord resolverActivity = mRootActivityContainer.topRunningActivity();
+ mRootWindowContainer.startHomeOnDisplay(0 /* userId */, "test", DEFAULT_DISPLAY);
+ final ActivityRecord resolverActivity = mRootWindowContainer.topRunningActivity();
assertEquals(info, resolverActivity.info);
assertEquals(ACTIVITY_TYPE_STANDARD, resolverActivity.getActivityStack().getActivityType());
@@ -647,7 +649,7 @@ public class RootActivityContainerTests extends ActivityTestsBase {
final Intent defaultHomeIntent = mService.getHomeIntent();
final ActivityInfo aInfoDefault = new ActivityInfo();
aInfoDefault.name = ResolverActivity.class.getName();
- doReturn(aInfoDefault).when(mRootActivityContainer).resolveHomeActivity(anyInt(),
+ doReturn(aInfoDefault).when(mRootWindowContainer).resolveHomeActivity(anyInt(),
refEq(defaultHomeIntent));
final String secondaryHomeComponent = mService.mContext.getResources().getString(
@@ -656,11 +658,11 @@ public class RootActivityContainerTests extends ActivityTestsBase {
final Intent secondaryHomeIntent = mService.getSecondaryHomeIntent(null);
final ActivityInfo aInfoSecondary = new ActivityInfo();
aInfoSecondary.name = comp.getClassName();
- doReturn(aInfoSecondary).when(mRootActivityContainer).resolveHomeActivity(anyInt(),
+ doReturn(aInfoSecondary).when(mRootWindowContainer).resolveHomeActivity(anyInt(),
refEq(secondaryHomeIntent));
// Should fallback to secondary home if default home not set.
- final Pair<ActivityInfo, Intent> resolvedInfo = mRootActivityContainer
+ final Pair<ActivityInfo, Intent> resolvedInfo = mRootWindowContainer
.resolveSecondaryHomeActivity(0 /* userId */, 1 /* displayId */);
assertEquals(comp.getClassName(), resolvedInfo.first.name);
@@ -690,14 +692,14 @@ public class RootActivityContainerTests extends ActivityTestsBase {
aInfoSecondary.name = secondaryComp.getClassName();
aInfoSecondary.applicationInfo = new ApplicationInfo();
aInfoSecondary.applicationInfo.packageName = secondaryComp.getPackageName();
- doReturn(aInfoSecondary).when(mRootActivityContainer).resolveHomeActivity(anyInt(),
+ doReturn(aInfoSecondary).when(mRootWindowContainer).resolveHomeActivity(anyInt(),
refEq(secondaryHomeIntent));
final Intent homeIntent = mService.getHomeIntent();
final ActivityInfo aInfoDefault = new ActivityInfo();
aInfoDefault.name = "fakeHomeActivity";
aInfoDefault.applicationInfo = new ApplicationInfo();
aInfoDefault.applicationInfo.packageName = "fakeHomePackage";
- doReturn(aInfoDefault).when(mRootActivityContainer).resolveHomeActivity(anyInt(),
+ doReturn(aInfoDefault).when(mRootWindowContainer).resolveHomeActivity(anyInt(),
refEq(homeIntent));
// Let resolveActivities call to validate both main launcher and second launcher so that
// resolveActivities call does not work as enabler for secondary.
@@ -707,7 +709,7 @@ public class RootActivityContainerTests extends ActivityTestsBase {
resolveInfo1.activityInfo.name = aInfoDefault.name;
resolveInfo1.activityInfo.applicationInfo = aInfoDefault.applicationInfo;
resolutions1.add(resolveInfo1);
- doReturn(resolutions1).when(mRootActivityContainer).resolveActivities(anyInt(),
+ doReturn(resolutions1).when(mRootWindowContainer).resolveActivities(anyInt(),
refEq(homeIntent));
final List<ResolveInfo> resolutions2 = new ArrayList<>();
final ResolveInfo resolveInfo2 = new ResolveInfo();
@@ -715,13 +717,13 @@ public class RootActivityContainerTests extends ActivityTestsBase {
resolveInfo2.activityInfo.name = aInfoSecondary.name;
resolveInfo2.activityInfo.applicationInfo = aInfoSecondary.applicationInfo;
resolutions2.add(resolveInfo2);
- doReturn(resolutions2).when(mRootActivityContainer).resolveActivities(anyInt(),
+ doReturn(resolutions2).when(mRootWindowContainer).resolveActivities(anyInt(),
refEq(secondaryHomeIntent));
- doReturn(true).when(mRootActivityContainer).canStartHomeOnDisplay(
+ doReturn(true).when(mRootWindowContainer).canStartHomeOnDisplay(
any(), anyInt(), anyBoolean());
// Run the test
- final Pair<ActivityInfo, Intent> resolvedInfo = mRootActivityContainer
+ final Pair<ActivityInfo, Intent> resolvedInfo = mRootWindowContainer
.resolveSecondaryHomeActivity(0 /* userId */, 1 /* displayId */);
assertEquals(secondaryComp.getClassName(), resolvedInfo.first.name);
assertEquals(secondaryComp.getPackageName(),
@@ -742,7 +744,7 @@ public class RootActivityContainerTests extends ActivityTestsBase {
mockResolveHomeActivity();
final List<ResolveInfo> resolutions = new ArrayList<>();
- doReturn(resolutions).when(mRootActivityContainer).resolveActivities(anyInt(), any());
+ doReturn(resolutions).when(mRootWindowContainer).resolveActivities(anyInt(), any());
final String secondaryHomeComponent = mService.mContext.getResources().getString(
com.android.internal.R.string.config_secondaryHomeComponent);
@@ -750,12 +752,12 @@ public class RootActivityContainerTests extends ActivityTestsBase {
final Intent secondaryHomeIntent = mService.getSecondaryHomeIntent(null);
final ActivityInfo aInfoSecondary = new ActivityInfo();
aInfoSecondary.name = comp.getClassName();
- doReturn(aInfoSecondary).when(mRootActivityContainer).resolveHomeActivity(anyInt(),
+ doReturn(aInfoSecondary).when(mRootWindowContainer).resolveHomeActivity(anyInt(),
refEq(secondaryHomeIntent));
// Should fallback to secondary home if selected default home not support secondary displays
// or there is no matched activity in the same package as selected default home.
- final Pair<ActivityInfo, Intent> resolvedInfo = mRootActivityContainer
+ final Pair<ActivityInfo, Intent> resolvedInfo = mRootWindowContainer
.resolveSecondaryHomeActivity(0 /* userId */, 1 /* displayId */);
assertEquals(comp.getClassName(), resolvedInfo.first.name);
@@ -778,13 +780,13 @@ public class RootActivityContainerTests extends ActivityTestsBase {
infoFake2.activityInfo = aInfoDefault;
resolutions.add(infoFake1);
resolutions.add(infoFake2);
- doReturn(resolutions).when(mRootActivityContainer).resolveActivities(anyInt(), any());
+ doReturn(resolutions).when(mRootWindowContainer).resolveActivities(anyInt(), any());
- doReturn(true).when(mRootActivityContainer).canStartHomeOnDisplay(
+ doReturn(true).when(mRootWindowContainer).canStartHomeOnDisplay(
any(), anyInt(), anyBoolean());
// Use default home activity if it support secondary displays.
- final Pair<ActivityInfo, Intent> resolvedInfo = mRootActivityContainer
+ final Pair<ActivityInfo, Intent> resolvedInfo = mRootWindowContainer
.resolveSecondaryHomeActivity(0 /* userId */, 1 /* displayId */);
assertEquals(aInfoDefault.applicationInfo.packageName,
@@ -812,13 +814,13 @@ public class RootActivityContainerTests extends ActivityTestsBase {
infoFake2.activityInfo.applicationInfo.packageName = "fakePackage2";
resolutions.add(infoFake1);
resolutions.add(infoFake2);
- doReturn(resolutions).when(mRootActivityContainer).resolveActivities(anyInt(), any());
+ doReturn(resolutions).when(mRootWindowContainer).resolveActivities(anyInt(), any());
- doReturn(true).when(mRootActivityContainer).canStartHomeOnDisplay(
+ doReturn(true).when(mRootWindowContainer).canStartHomeOnDisplay(
any(), anyInt(), anyBoolean());
// Use the first one of matched activities in the same package as selected default home.
- final Pair<ActivityInfo, Intent> resolvedInfo = mRootActivityContainer
+ final Pair<ActivityInfo, Intent> resolvedInfo = mRootWindowContainer
.resolveSecondaryHomeActivity(0 /* userId */, 1 /* displayId */);
assertEquals(infoFake1.activityInfo.applicationInfo.packageName,
@@ -827,7 +829,7 @@ public class RootActivityContainerTests extends ActivityTestsBase {
}
/**
- * Test that {@link RootActivityContainer#getLaunchStack} with the real caller id will get the
+ * Test that {@link RootWindowContainer#getLaunchStack} with the real caller id will get the
* expected stack when requesting the activity launch on the secondary display.
*/
@Test
@@ -848,7 +850,7 @@ public class RootActivityContainerTests extends ActivityTestsBase {
options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);
doReturn(true).when(mSupervisor).canPlaceEntityOnDisplay(secondaryDisplay.mDisplayId,
300 /* test realCallerPid */, 300 /* test realCallerUid */, r.info);
- final ActivityStack result = mRootActivityContainer.getLaunchStack(r, options,
+ final ActivityStack result = mRootWindowContainer.getLaunchStack(r, options,
null /* task */, true /* onTop */, null, 300 /* test realCallerPid */,
300 /* test realCallerUid */);
@@ -859,7 +861,7 @@ public class RootActivityContainerTests extends ActivityTestsBase {
}
/**
- * Mock {@link RootActivityContainer#resolveHomeActivity} for returning consistent activity
+ * Mock {@link RootWindowContainer#resolveHomeActivity} for returning consistent activity
* info for test cases (the original implementation will resolve from the real package manager).
*/
private ActivityInfo mockResolveHomeActivity() {
@@ -868,13 +870,13 @@ public class RootActivityContainerTests extends ActivityTestsBase {
aInfoDefault.name = "fakeHomeActivity";
aInfoDefault.applicationInfo = new ApplicationInfo();
aInfoDefault.applicationInfo.packageName = "fakeHomePackage";
- doReturn(aInfoDefault).when(mRootActivityContainer).resolveHomeActivity(anyInt(),
+ doReturn(aInfoDefault).when(mRootWindowContainer).resolveHomeActivity(anyInt(),
refEq(homeIntent));
return aInfoDefault;
}
/**
- * Mock {@link RootActivityContainer#resolveSecondaryHomeActivity} for returning consistent
+ * Mock {@link RootWindowContainer#resolveSecondaryHomeActivity} for returning consistent
* activity info for test cases (the original implementation will resolve from the real package
* manager).
*/
@@ -885,7 +887,7 @@ public class RootActivityContainerTests extends ActivityTestsBase {
aInfoSecondary.name = "fakeSecondaryHomeActivity";
aInfoSecondary.applicationInfo = new ApplicationInfo();
aInfoSecondary.applicationInfo.packageName = "fakeSecondaryHomePackage";
- doReturn(Pair.create(aInfoSecondary, secondaryHomeIntent)).when(mRootActivityContainer)
+ doReturn(Pair.create(aInfoSecondary, secondaryHomeIntent)).when(mRootWindowContainer)
.resolveSecondaryHomeActivity(anyInt(), anyInt());
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java
index b32cb8b5e637..6272070efea7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java
@@ -64,7 +64,7 @@ public class RunningTasksTest extends ActivityTestsBase {
final int numStacks = 2;
for (int stackIndex = 0; stackIndex < numStacks; stackIndex++) {
- final ActivityStack stack = new StackBuilder(mRootActivityContainer)
+ final ActivityStack stack = new StackBuilder(mRootWindowContainer)
.setCreateActivity(false)
.setDisplay(display)
.setOnTop(false)
@@ -82,7 +82,7 @@ public class RunningTasksTest extends ActivityTestsBase {
final int numFetchTasks = 5;
ArrayList<RunningTaskInfo> tasks = new ArrayList<>();
mRunningTasks.getTasks(5, tasks, ACTIVITY_TYPE_UNDEFINED, WINDOWING_MODE_UNDEFINED,
- mRootActivityContainer, -1 /* callingUid */, true /* allowed */,
+ mRootWindowContainer, -1 /* callingUid */, true /* allowed */,
true /*crossUser */, PROFILE_IDS);
assertThat(tasks).hasSize(numFetchTasks);
for (int i = 0; i < numFetchTasks; i++) {
@@ -93,7 +93,7 @@ public class RunningTasksTest extends ActivityTestsBase {
// and does not crash
tasks.clear();
mRunningTasks.getTasks(100, tasks, ACTIVITY_TYPE_UNDEFINED, WINDOWING_MODE_UNDEFINED,
- mRootActivityContainer, -1 /* callingUid */, true /* allowed */,
+ mRootWindowContainer, -1 /* callingUid */, true /* allowed */,
true /* crossUser */, PROFILE_IDS);
assertThat(tasks).hasSize(numTasks);
for (int i = 0; i < numTasks; i++) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index be0fd2b26f7c..64db89706d39 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -68,7 +68,7 @@ public class SizeCompatTests extends ActivityTestsBase {
private ActivityRecord mActivity;
private void setUpApp(DisplayContent display) {
- mStack = new StackBuilder(mRootActivityContainer).setDisplay(display).build();
+ mStack = new StackBuilder(mRootWindowContainer).setDisplay(display).build();
mTask = mStack.getBottomMostTask();
mActivity = mTask.getTopNonFinishingActivity();
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
index 3008a75740e8..e0112809b22b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
@@ -88,6 +88,7 @@ public class SurfaceAnimationRunnerTest extends WindowTestsBase {
mFinishCallbackLatch.countDown();
}
+ @FlakyTest(bugId = 144611135)
@Test
public void testAnimation() throws Exception {
mSurfaceAnimationRunner
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index 811f46f9112a..f90eca35d22a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -269,6 +269,14 @@ public class SystemServicesTestRule implements TestRule {
mContext, mImService, false, false, mWMPolicy, mAtmService, StubTransaction::new,
() -> mock(Surface.class), (unused) -> new MockSurfaceControlBuilder());
spyOn(mWmService);
+ spyOn(mWmService.mRoot);
+ // Invoked during {@link ActivityStack} creation.
+ doNothing().when(mWmService.mRoot).updateUIDsPresentOnDisplay();
+ // Always keep things awake.
+ doReturn(true).when(mWmService.mRoot).hasAwakeDisplay();
+ // Called when moving activity to pinned stack.
+ doNothing().when(mWmService.mRoot).ensureActivitiesVisible(any(),
+ anyInt(), anyBoolean(), anyBoolean());
// Setup factory classes to prevent calls to native code.
mTransaction = spy(StubTransaction.class);
@@ -284,9 +292,8 @@ public class SystemServicesTestRule implements TestRule {
// Set configuration for default display
mWmService.getDefaultDisplayContentLocked().reconfigureDisplayLocked();
- // Mock root, some default display, and home stack.
- spyOn(mWmService.mRoot);
- final DisplayContent display = mAtmService.mRootActivityContainer.getDefaultDisplay();
+ // Mock default display, and home stack.
+ final DisplayContent display = mAtmService.mRootWindowContainer.getDefaultDisplay();
// Set default display to be in fullscreen mode. Devices with PC feature may start their
// default display in freeform mode but some of tests in WmTests have implicit assumption on
// that the default display is in fullscreen mode.
@@ -300,7 +307,7 @@ public class SystemServicesTestRule implements TestRule {
private void tearDown() {
// Unregister display listener from root to avoid issues with subsequent tests.
mContext.getSystemService(DisplayManager.class)
- .unregisterDisplayListener(mAtmService.mRootActivityContainer);
+ .unregisterDisplayListener(mAtmService.mRootWindowContainer);
// The constructor of WindowManagerService registers WindowManagerConstants and
// HighRefreshRateBlacklist with DeviceConfig. We need to undo that here to avoid
// leaking mWmService.
@@ -311,9 +318,12 @@ public class SystemServicesTestRule implements TestRule {
// Needs to explicitly dispose current static threads because there could be messages
// scheduled at a later time, and all mocks are invalid when it's executed.
DisplayThread.dispose();
+ // Dispose SurfaceAnimationThread before AnimationThread does, so it won't create a new
+ // AnimationThread after AnimationThread disposed, see {@link
+ // AnimatorListenerAdapter#onAnimationEnd()}
+ SurfaceAnimationThread.dispose();
AnimationThread.dispose();
UiThread.dispose();
- SurfaceAnimationThread.dispose();
mInputChannel.dispose();
tearDownLocalServices();
@@ -443,24 +453,12 @@ public class SystemServicesTestRule implements TestRule {
spyOn(getLifecycleManager());
spyOn(getLockTaskController());
spyOn(getTaskChangeNotificationController());
- initRootActivityContainerMocks();
AppWarnings appWarnings = getAppWarningsLocked();
spyOn(appWarnings);
doNothing().when(appWarnings).onStartActivity(any());
}
- void initRootActivityContainerMocks() {
- spyOn(mRootActivityContainer);
- // Invoked during {@link ActivityStack} creation.
- doNothing().when(mRootActivityContainer).updateUIDsPresentOnDisplay();
- // Always keep things awake.
- doReturn(true).when(mRootActivityContainer).hasAwakeDisplay();
- // Called when moving activity to pinned stack.
- doNothing().when(mRootActivityContainer).ensureActivitiesVisible(any(), anyInt(),
- anyBoolean());
- }
-
@Override
int handleIncomingUser(int callingPid, int callingUid, int userId, String name) {
return userId;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
index 5aa41eb2b856..a3446d16d9f3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
@@ -1047,10 +1047,10 @@ public class TaskLaunchParamsModifierTests extends ActivityTestsBase {
@Test
public void testAdjustBoundsToFitNewDisplay_LargerThanDisplay_RTL() {
final Configuration overrideConfig =
- mRootActivityContainer.getRequestedOverrideConfiguration();
+ mRootWindowContainer.getRequestedOverrideConfiguration();
// Egyptian Arabic is a RTL language.
overrideConfig.setLayoutDirection(new Locale("ar", "EG"));
- mRootActivityContainer.onRequestedOverrideConfigurationChanged(overrideConfig);
+ mRootWindowContainer.onRequestedOverrideConfigurationChanged(overrideConfig);
final TestDisplayContent freeformDisplay = createNewDisplayContent(
WINDOWING_MODE_FREEFORM);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
index 1a18df5b6fcf..9f2bfa7a35e0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
@@ -193,7 +193,7 @@ public class TaskRecordTests extends ActivityTestsBase {
@FlakyTest(bugId = 137879065)
public void testFitWithinBounds() {
final Rect parentBounds = new Rect(10, 10, 200, 200);
- DisplayContent display = mService.mRootActivityContainer.getDefaultDisplay();
+ DisplayContent display = mService.mRootWindowContainer.getDefaultDisplay();
ActivityStack stack = display.createStack(WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD,
true /* onTop */);
Task task = new TaskBuilder(mSupervisor).setStack(stack).build();
@@ -232,8 +232,8 @@ public class TaskRecordTests extends ActivityTestsBase {
@Test
@FlakyTest(bugId = 137879065)
public void testBoundsOnModeChangeFreeformToFullscreen() {
- DisplayContent display = mService.mRootActivityContainer.getDefaultDisplay();
- ActivityStack stack = new StackBuilder(mRootActivityContainer).setDisplay(display)
+ DisplayContent display = mService.mRootWindowContainer.getDefaultDisplay();
+ ActivityStack stack = new StackBuilder(mRootWindowContainer).setDisplay(display)
.setWindowingMode(WINDOWING_MODE_FREEFORM).build();
Task task = stack.getBottomMostTask();
task.getRootActivity().setOrientation(SCREEN_ORIENTATION_UNSPECIFIED);
@@ -267,14 +267,14 @@ public class TaskRecordTests extends ActivityTestsBase {
final Rect fullScreenBoundsPort = new Rect(0, 0, 1080, 1920);
DisplayContent display = new TestDisplayContent.Builder(
mService, fullScreenBounds.width(), fullScreenBounds.height()).build();
- assertTrue(mRootActivityContainer.getDisplayContent(display.mDisplayId) != null);
+ assertTrue(mRootWindowContainer.getDisplayContent(display.mDisplayId) != null);
// Fix the display orientation to landscape which is the natural rotation (0) for the test
// display.
final DisplayRotation dr = display.mDisplayContent.getDisplayRotation();
dr.setFixedToUserRotation(FIXED_TO_USER_ROTATION_ENABLED);
dr.setUserRotation(USER_ROTATION_FREE, ROTATION_0);
- ActivityStack stack = new StackBuilder(mRootActivityContainer)
+ ActivityStack stack = new StackBuilder(mRootWindowContainer)
.setWindowingMode(WINDOWING_MODE_FULLSCREEN).setDisplay(display).build();
Task task = stack.getBottomMostTask();
ActivityRecord root = task.getTopNonFinishingActivity();
@@ -335,7 +335,7 @@ public class TaskRecordTests extends ActivityTestsBase {
Configuration.ORIENTATION_LANDSCAPE;
display.onRequestedOverrideConfigurationChanged(
display.getRequestedOverrideConfiguration());
- ActivityStack stack = new StackBuilder(mRootActivityContainer)
+ ActivityStack stack = new StackBuilder(mRootWindowContainer)
.setWindowingMode(WINDOWING_MODE_FULLSCREEN).setDisplay(display).build();
Task task = stack.getBottomMostTask();
ActivityRecord root = task.getTopNonFinishingActivity();
@@ -427,6 +427,61 @@ public class TaskRecordTests extends ActivityTestsBase {
assertNotEquals(origScreenH, task.getConfiguration().screenHeightDp);
}
+ @Test
+ public void testInsetDisregardedWhenFreeformOverlapsNavBar() {
+ DisplayContent display = mService.mRootWindowContainer.getDefaultDisplay();
+ ActivityStack stack = display.createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
+ true /* onTop */);
+ DisplayInfo displayInfo = new DisplayInfo();
+ mService.mContext.getDisplay().getDisplayInfo(displayInfo);
+ final int displayHeight = displayInfo.logicalHeight;
+ final Task task = new TaskBuilder(mSupervisor).setStack(stack).build();
+ final Configuration inOutConfig = new Configuration();
+ final Configuration parentConfig = new Configuration();
+ final int longSide = 1200;
+ final int shortSide = 600;
+ parentConfig.densityDpi = 400;
+ parentConfig.screenHeightDp = 200; // 200 * 400 / 160 = 500px
+ parentConfig.screenWidthDp = 100; // 100 * 400 / 160 = 250px
+ parentConfig.windowConfiguration.setRotation(ROTATION_0);
+
+ final float density = 2.5f; // densityDpi / DENSITY_DEFAULT_SCALE = 400 / 160.0f
+ final int longSideDp = 480; // longSide / density = 1200 / 400 * 160
+ final int shortSideDp = 240; // shortSide / density = 600 / 400 * 160
+ final int screenLayout = parentConfig.screenLayout
+ & (Configuration.SCREENLAYOUT_LONG_MASK | Configuration.SCREENLAYOUT_SIZE_MASK);
+ final int reducedScreenLayout =
+ Configuration.reduceScreenLayout(screenLayout, longSideDp, shortSideDp);
+
+ // Portrait bounds overlapping with navigation bar, without insets.
+ inOutConfig.windowConfiguration.getBounds().set(0,
+ displayHeight - 10 - longSide,
+ shortSide,
+ displayHeight - 10);
+ // Set to freeform mode to verify bug fix.
+ inOutConfig.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
+
+ task.computeConfigResourceOverrides(inOutConfig, parentConfig);
+
+ assertEquals(parentConfig.screenWidthDp, inOutConfig.screenWidthDp);
+ assertEquals(parentConfig.screenHeightDp, inOutConfig.screenHeightDp);
+ assertEquals(reducedScreenLayout, inOutConfig.screenLayout);
+
+ inOutConfig.setToDefaults();
+ // Landscape bounds overlapping with navigtion bar, without insets.
+ inOutConfig.windowConfiguration.getBounds().set(0,
+ displayHeight - 10 - shortSide,
+ longSide,
+ displayHeight - 10);
+ inOutConfig.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
+
+ task.computeConfigResourceOverrides(inOutConfig, parentConfig);
+
+ assertEquals(parentConfig.screenWidthDp, inOutConfig.screenWidthDp);
+ assertEquals(parentConfig.screenHeightDp, inOutConfig.screenHeightDp);
+ assertEquals(reducedScreenLayout, inOutConfig.screenLayout);
+ }
+
/** Ensures that the alias intent won't have target component resolved. */
@Test
public void testTaskIntentActivityAlias() {
@@ -802,14 +857,14 @@ public class TaskRecordTests extends ActivityTestsBase {
}
private Task getTestTask() {
- final ActivityStack stack = new StackBuilder(mRootActivityContainer).build();
+ final ActivityStack stack = new StackBuilder(mRootWindowContainer).build();
return stack.getBottomMostTask();
}
private void testStackBoundsConfiguration(int windowingMode, Rect parentBounds, Rect bounds,
Rect expectedConfigBounds) {
- DisplayContent display = mService.mRootActivityContainer.getDefaultDisplay();
+ DisplayContent display = mService.mRootWindowContainer.getDefaultDisplay();
ActivityStack stack = display.createStack(windowingMode, ACTIVITY_TYPE_STANDARD,
true /* onTop */);
Task task = new TaskBuilder(mSupervisor).setStack(stack).build();
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
index 7174e5c8bb48..8fe0cdbbd872 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
@@ -19,13 +19,27 @@ package com.android.server.wm;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
+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.TaskSnapshotController.SNAPSHOT_MODE_APP_THEME;
import static com.android.server.wm.TaskSnapshotController.SNAPSHOT_MODE_REAL;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import android.app.ActivityManager;
+import android.app.WindowConfiguration;
+import android.content.ComponentName;
+import android.content.res.Configuration;
+import android.graphics.ColorSpace;
+import android.graphics.GraphicBuffer;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.util.ArraySet;
+import android.view.View;
import androidx.test.filters.SmallTest;
@@ -33,6 +47,7 @@ import com.google.android.collect.Sets;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mockito;
/**
* Test class for {@link TaskSnapshotController}.
@@ -110,4 +125,75 @@ public class TaskSnapshotControllerTest extends WindowTestsBase {
assertEquals(SNAPSHOT_MODE_APP_THEME,
mWm.mTaskSnapshotController.getSnapshotMode(secureWindow.getTask()));
}
+
+ @Test
+ public void testSnapshotBuilder() {
+ final GraphicBuffer buffer = Mockito.mock(GraphicBuffer.class);
+ final ColorSpace sRGB = ColorSpace.get(ColorSpace.Named.SRGB);
+ final long id = 1234L;
+ final ComponentName activityComponent = new ComponentName("package", ".Class");
+ final int windowingMode = WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+ final int systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN;
+ final int pixelFormat = PixelFormat.RGBA_8888;
+ final int orientation = Configuration.ORIENTATION_PORTRAIT;
+ final float scaleFraction = 0.25f;
+ final Rect contentInsets = new Rect(1, 2, 3, 4);
+
+ try {
+ ActivityManager.TaskSnapshot.Builder builder =
+ new ActivityManager.TaskSnapshot.Builder();
+ builder.setId(id);
+ builder.setTopActivityComponent(activityComponent);
+ builder.setSystemUiVisibility(systemUiVisibility);
+ builder.setWindowingMode(windowingMode);
+ builder.setColorSpace(sRGB);
+ builder.setReducedResolution(true);
+ builder.setOrientation(orientation);
+ builder.setContentInsets(contentInsets);
+ builder.setIsTranslucent(true);
+ builder.setScaleFraction(0.25f);
+ builder.setSnapshot(buffer);
+ builder.setIsRealSnapshot(true);
+ builder.setPixelFormat(pixelFormat);
+
+ // Not part of TaskSnapshot itself, used in screenshot process
+ assertEquals(pixelFormat, builder.getPixelFormat());
+
+ ActivityManager.TaskSnapshot snapshot = builder.build();
+ assertEquals(id, snapshot.getId());
+ assertEquals(activityComponent, snapshot.getTopActivityComponent());
+ assertEquals(systemUiVisibility, snapshot.getSystemUiVisibility());
+ assertEquals(windowingMode, snapshot.getWindowingMode());
+ assertEquals(sRGB, snapshot.getColorSpace());
+ assertTrue(snapshot.isReducedResolution());
+ assertEquals(orientation, snapshot.getOrientation());
+ assertEquals(contentInsets, snapshot.getContentInsets());
+ assertTrue(snapshot.isTranslucent());
+ assertEquals(scaleFraction, builder.getScaleFraction(), 0.001f);
+ assertSame(buffer, snapshot.getSnapshot());
+ assertTrue(snapshot.isRealSnapshot());
+ } finally {
+ if (buffer != null) {
+ buffer.destroy();
+ }
+ }
+ }
+
+ @Test
+ public void testPrepareTaskSnapshot() {
+ mAppWindow.mWinAnimator.mLastAlpha = 1f;
+ spyOn(mAppWindow.mWinAnimator);
+ doReturn(true).when(mAppWindow.mWinAnimator).getShown();
+ doReturn(true).when(mAppWindow.mActivityRecord).isSurfaceShowing();
+
+ final ActivityManager.TaskSnapshot.Builder builder =
+ new ActivityManager.TaskSnapshot.Builder();
+ final float scaleFraction = 0.8f;
+ mWm.mTaskSnapshotController.prepareTaskSnapshot(mAppWindow.mActivityRecord.getTask(),
+ scaleFraction, PixelFormat.UNKNOWN, builder);
+
+ assertEquals(scaleFraction, builder.getScaleFraction(), 0 /* delta */);
+ // The pixel format should be selected automatically.
+ assertNotEquals(PixelFormat.UNKNOWN, builder.getPixelFormat());
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
index f5e65b1385dd..6c3410aa7657 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
@@ -31,6 +31,7 @@ import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.clearInvocations;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
@@ -165,6 +166,7 @@ public class TaskStackTests extends WindowTestsBase {
final ActivityStack stack2 = createTaskStackOnDisplay(dc);
// Reparent
+ clearInvocations(task1); // reset the number of onDisplayChanged for task.
stack1.reparent(dc, true /* onTop */);
assertEquals(dc, stack1.getDisplayContent());
final int stack1PositionInParent = stack1.getParent().mChildren.indexOf(stack1);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
index 9f85e1c083dd..ec77be85aebf 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
@@ -28,6 +28,7 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.clearInvocations;
import android.graphics.Point;
import android.graphics.Rect;
@@ -126,6 +127,7 @@ public class TaskTests extends WindowTestsBase {
final ActivityStack stack2 = createTaskStackOnDisplay(dc);
final Task task2 = createTaskInStack(stack2, 0 /* userId */);
// Reparent and check state
+ clearInvocations(task); // reset the number of onDisplayChanged for task.
task.reparent(stack2, 0, false /* moveParents */, "testReparent_BetweenDisplays");
assertEquals(stack2, task.getParent());
assertEquals(0, task.getParent().mChildren.indexOf(task));
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java b/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java
index 325cea72da24..e5121b9297e6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java
@@ -39,7 +39,7 @@ class TestDisplayContent extends DisplayContent {
private final ActivityStackSupervisor mSupervisor;
private TestDisplayContent(ActivityStackSupervisor supervisor, Display display) {
- super(display, supervisor.mService.mRootActivityContainer);
+ super(display, supervisor.mService.mRootWindowContainer);
// Normally this comes from display-properties as exposed by WM. Without that, just
// hard-code to FULLSCREEN for tests.
setWindowingMode(WINDOWING_MODE_FULLSCREEN);
@@ -68,20 +68,6 @@ class TestDisplayContent extends DisplayContent {
doNothing().when(inputMonitor).resumeDispatchingLw(any());
}
- @SuppressWarnings("TypeParameterUnusedInFormals")
- @Override
- ActivityStack createStackUnchecked(int windowingMode, int activityType,
- int stackId, boolean onTop) {
- return new ActivityTestsBase.StackBuilder(mSupervisor.mRootActivityContainer)
- .setDisplay(this)
- .setWindowingMode(windowingMode)
- .setActivityType(activityType)
- .setStackId(stackId)
- .setOnTop(onTop)
- .setCreateActivity(false)
- .build();
- }
-
public static class Builder {
private final DisplayInfo mInfo;
private boolean mCanRotate = true;
@@ -147,7 +133,6 @@ class TestDisplayContent extends DisplayContent {
final TestDisplayContent newDisplay;
synchronized (mService.mGlobalLock) {
newDisplay = new TestDisplayContent(mService.mStackSupervisor, display);
- mService.mRootActivityContainer.addChild(newDisplay, mPosition);
}
// disable the normal system decorations
final DisplayPolicy displayPolicy = newDisplay.mDisplayContent.getDisplayPolicy();
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
index 13cf22d176ec..248b06b26b6d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
@@ -763,6 +763,25 @@ public class WindowContainerTests extends WindowTestsBase {
assertTrue(child.handlesOrientationChangeFromDescendant());
}
+ @Test
+ public void testOnDisplayChanged() {
+ final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
+ final Task task = createTaskInStack(stack, 0 /* userId */);
+ final ActivityRecord activity =
+ WindowTestUtils.createActivityRecordInTask(mDisplayContent, task);
+
+ final DisplayContent newDc = createNewDisplay();
+ mDisplayContent.removeStack(stack);
+ newDc.setStackOnDisplay(stack, POSITION_TOP);
+
+ verify(stack).onDisplayChanged(newDc);
+ verify(task).onDisplayChanged(newDc);
+ verify(activity).onDisplayChanged(newDc);
+ assertEquals(newDc, stack.mDisplayContent);
+ assertEquals(newDc, task.mDisplayContent);
+ assertEquals(newDc, activity.mDisplayContent);
+ }
+
/* Used so we can gain access to some protected members of the {@link WindowContainer} class */
private static class TestWindowContainer extends WindowContainer<TestWindowContainer> {
private final int mLayer;
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
index 6108db366cad..421a458256af 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
@@ -87,7 +87,7 @@ public class WindowProcessControllerTests extends ActivityTestsBase {
// Unregistration still work even if the display was removed.
mWpc.registerDisplayConfigurationListenerLocked(testDisplayContent1);
assertEquals(testDisplayContent1.mDisplayId, mWpc.getDisplayId());
- mRootActivityContainer.removeChild(testDisplayContent1);
+ mRootWindowContainer.removeChild(testDisplayContent1);
mWpc.unregisterDisplayConfigurationListenerLocked();
assertEquals(INVALID_DISPLAY, mWpc.getDisplayId());
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 8ade4d27e495..6d23b2ebe242 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -32,7 +32,9 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
+import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
@@ -82,7 +84,9 @@ import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.Arrays;
import java.util.LinkedList;
+import java.util.List;
/**
* Tests for the {@link WindowState} class.
@@ -532,6 +536,31 @@ public class WindowStateTests extends WindowTestsBase {
}
@Test
+ public void testRequestDrawIfNeeded() {
+ final WindowState startingApp = createWindow(null /* parent */,
+ TYPE_BASE_APPLICATION, "startingApp");
+ final WindowState startingWindow = createWindow(null /* parent */,
+ TYPE_APPLICATION_STARTING, startingApp.mToken, "starting");
+ startingApp.mActivityRecord.startingWindow = startingWindow;
+ final WindowState keyguardHostWindow = mStatusBarWindow;
+ final WindowState allDrawnApp = mAppWindow;
+ allDrawnApp.mActivityRecord.allDrawn = true;
+
+ // The waiting list is used to ensure the content is ready when turning on screen.
+ final List<WindowState> outWaitingForDrawn = mDisplayContent.mWaitingForDrawn;
+ final List<WindowState> visibleWindows = Arrays.asList(mChildAppWindowAbove,
+ keyguardHostWindow, allDrawnApp, startingApp, startingWindow);
+ visibleWindows.forEach(w -> {
+ w.mHasSurface = true;
+ w.requestDrawIfNeeded(outWaitingForDrawn);
+ });
+
+ // Keyguard host window should be always contained. The drawn app or app with starting
+ // window are unnecessary to draw.
+ assertEquals(Arrays.asList(keyguardHostWindow, startingWindow), outWaitingForDrawn);
+ }
+
+ @Test
public void testGetTransformationMatrix() {
final int PARENT_WINDOW_OFFSET = 1;
final int DISPLAY_IN_PARENT_WINDOW_OFFSET = 2;
@@ -567,7 +596,7 @@ public class WindowStateTests extends WindowTestsBase {
// Mock active recents animation
RecentsAnimationController recentsController = mock(RecentsAnimationController.class);
- when(recentsController.isAnimatingTask(win0.mActivityRecord.getTask())).thenReturn(true);
+ when(recentsController.shouldApplyInputConsumer(win0.mActivityRecord)).thenReturn(true);
mWm.setRecentsAnimationController(recentsController);
assertTrue(win0.cantReceiveTouchInput());
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
index 26743c842122..084216a9a543 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
@@ -52,9 +52,9 @@ class WindowTestUtils {
}
static ActivityRecord createTestActivityRecord(ActivityStack stack) {
- synchronized (stack.mService.mGlobalLock) {
+ synchronized (stack.mAtmService.mGlobalLock) {
final ActivityRecord activity = new ActivityTestsBase.ActivityBuilder(
- stack.mService)
+ stack.mAtmService)
.setStack(stack)
.setCreateTask(true)
.build();
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index 6f53428cc6a6..ea8831571639 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -129,6 +129,7 @@ class WindowTestsBase extends SystemServiceTestsBase {
TYPE_APPLICATION_MEDIA_OVERLAY,
"mChildAppWindowBelow");
}
+
// Adding a display will cause freezing the display. Make sure to wait until it's
// unfrozen to not run into race conditions with the tests.
waitUntilHandlersIdle();
@@ -319,7 +320,7 @@ class WindowTestsBase extends SystemServiceTestsBase {
ActivityStack createTaskStackOnDisplay(int windowingMode, int activityType, DisplayContent dc) {
synchronized (mWm.mGlobalLock) {
return new ActivityTestsBase.StackBuilder(
- dc.mWmService.mAtmService.mRootActivityContainer)
+ dc.mWmService.mAtmService.mRootWindowContainer)
.setDisplay(dc)
.setWindowingMode(windowingMode)
.setActivityType(activityType)
@@ -378,6 +379,6 @@ class WindowTestsBase extends SystemServiceTestsBase {
/** Sets the default minimum task size to 1 so that tests can use small task sizes */
void removeGlobalMinSizeRestriction() {
- mWm.mAtmService.mRootActivityContainer.mDefaultMinSizeOfResizeableTaskDp = 1;
+ mWm.mAtmService.mRootWindowContainer.mDefaultMinSizeOfResizeableTaskDp = 1;
}
}
diff --git a/services/usage/java/com/android/server/usage/StorageStatsService.java b/services/usage/java/com/android/server/usage/StorageStatsService.java
index 0f3050f9e3d3..531a93117752 100644
--- a/services/usage/java/com/android/server/usage/StorageStatsService.java
+++ b/services/usage/java/com/android/server/usage/StorageStatsService.java
@@ -19,6 +19,9 @@ package com.android.server.usage;
import static com.android.internal.util.ArrayUtils.defeatNullable;
import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
import android.app.AppOpsManager;
import android.app.usage.ExternalStorageStats;
import android.app.usage.IStorageStatsManager;
@@ -30,6 +33,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PackageStats;
+import android.content.pm.ParceledListSlice;
import android.content.pm.UserInfo;
import android.net.Uri;
import android.os.Binder;
@@ -44,10 +48,13 @@ import android.os.StatFs;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
+import android.os.storage.CrateInfo;
+import android.os.storage.CrateMetadata;
import android.os.storage.StorageEventListener;
import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
import android.provider.Settings;
+import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.ArrayMap;
import android.util.DataUnit;
@@ -67,6 +74,9 @@ import com.android.server.storage.CacheQuotaStrategy;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
public class StorageStatsService extends IStorageStatsManager.Stub {
private static final String TAG = "StorageStatsService";
@@ -139,7 +149,7 @@ public class StorageStatsService extends IStorageStatsManager.Stub {
}
}
- private void enforcePermission(int callingUid, String callingPackage) {
+ private void enforceStatsPermission(int callingUid, String callingPackage) {
final int mode = mAppOps.noteOp(AppOpsManager.OP_GET_USAGE_STATS,
callingUid, callingPackage);
switch (mode) {
@@ -222,7 +232,7 @@ public class StorageStatsService extends IStorageStatsManager.Stub {
@Override
public long getCacheBytes(String volumeUuid, String callingPackage) {
- enforcePermission(Binder.getCallingUid(), callingPackage);
+ enforceStatsPermission(Binder.getCallingUid(), callingPackage);
long cacheBytes = 0;
for (UserInfo user : mUser.getUsers()) {
@@ -234,7 +244,7 @@ public class StorageStatsService extends IStorageStatsManager.Stub {
@Override
public long getCacheQuotaBytes(String volumeUuid, int uid, String callingPackage) {
- enforcePermission(Binder.getCallingUid(), callingPackage);
+ enforceStatsPermission(Binder.getCallingUid(), callingPackage);
if (mCacheQuotas.containsKey(volumeUuid)) {
final SparseLongArray uidMap = mCacheQuotas.get(volumeUuid);
@@ -263,7 +273,7 @@ public class StorageStatsService extends IStorageStatsManager.Stub {
if (Binder.getCallingUid() == appInfo.uid) {
// No permissions required when asking about themselves
} else {
- enforcePermission(Binder.getCallingUid(), callingPackage);
+ enforceStatsPermission(Binder.getCallingUid(), callingPackage);
}
if (defeatNullable(mPackage.getPackagesForUid(appInfo.uid)).length == 1) {
@@ -307,7 +317,7 @@ public class StorageStatsService extends IStorageStatsManager.Stub {
if (Binder.getCallingUid() == uid) {
// No permissions required when asking about themselves
} else {
- enforcePermission(Binder.getCallingUid(), callingPackage);
+ enforceStatsPermission(Binder.getCallingUid(), callingPackage);
}
final String[] packageNames = defeatNullable(mPackage.getPackagesForUid(uid));
@@ -354,7 +364,7 @@ public class StorageStatsService extends IStorageStatsManager.Stub {
}
// Always require permission to see user-level stats
- enforcePermission(Binder.getCallingUid(), callingPackage);
+ enforceStatsPermission(Binder.getCallingUid(), callingPackage);
final int[] appIds = getAppIds(userId);
final PackageStats stats = new PackageStats(TAG);
@@ -381,7 +391,7 @@ public class StorageStatsService extends IStorageStatsManager.Stub {
}
// Always require permission to see user-level stats
- enforcePermission(Binder.getCallingUid(), callingPackage);
+ enforceStatsPermission(Binder.getCallingUid(), callingPackage);
final int[] appIds = getAppIds(userId);
final long[] stats;
@@ -556,4 +566,143 @@ public class StorageStatsService extends IStorageStatsManager.Stub {
mContext.getContentResolver().notifyChange(
Uri.parse("content://com.android.externalstorage.documents/"), null, false);
}
+
+ /**
+ * To enforce the calling or self to have the {@link android.Manifest.permission#MANAGE_CRATES}
+ * permission.
+ * @param callingUid the calling uid
+ * @param callingPackage the calling package name
+ */
+ private void enforceCratesPermission(int callingUid, String callingPackage) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_CRATES,
+ callingPackage);
+ }
+
+ /**
+ * To copy from CrateMetadata instances into CrateInfo instances.
+ */
+ @NonNull
+ private static List<CrateInfo> convertCrateInfoFrom(@Nullable CrateMetadata[] crateMetadatas) {
+ if (ArrayUtils.isEmpty(crateMetadatas)) {
+ return Collections.EMPTY_LIST;
+ }
+
+ ArrayList<CrateInfo> crateInfos = new ArrayList<>();
+ for (CrateMetadata crateMetadata : crateMetadatas) {
+ if (crateMetadata == null || TextUtils.isEmpty(crateMetadata.id)
+ || TextUtils.isEmpty(crateMetadata.packageName)) {
+ continue;
+ }
+
+ CrateInfo crateInfo = CrateInfo.copyFrom(crateMetadata.uid,
+ crateMetadata.packageName, crateMetadata.id);
+ if (crateInfo == null) {
+ continue;
+ }
+
+ crateInfos.add(crateInfo);
+ }
+
+ return crateInfos;
+ }
+
+ @NonNull
+ private ParceledListSlice<CrateInfo> getAppCrates(String volumeUuid, String[] packageNames,
+ @UserIdInt int userId) {
+ try {
+ CrateMetadata[] crateMetadatas = mInstaller.getAppCrates(volumeUuid,
+ packageNames, userId);
+ return new ParceledListSlice<>(convertCrateInfoFrom(crateMetadatas));
+ } catch (InstallerException e) {
+ throw new ParcelableException(new IOException(e.getMessage()));
+ }
+ }
+
+ @NonNull
+ @Override
+ public ParceledListSlice<CrateInfo> queryCratesForPackage(String volumeUuid,
+ @NonNull String packageName, @UserIdInt int userId, @NonNull String callingPackage) {
+ if (userId != UserHandle.getCallingUserId()) {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.INTERACT_ACROSS_USERS, TAG);
+ }
+
+ final ApplicationInfo appInfo;
+ try {
+ appInfo = mPackage.getApplicationInfoAsUser(packageName,
+ PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
+ } catch (NameNotFoundException e) {
+ throw new ParcelableException(e);
+ }
+
+ if (Binder.getCallingUid() == appInfo.uid) {
+ // No permissions required when asking about themselves
+ } else {
+ enforceCratesPermission(Binder.getCallingUid(), callingPackage);
+ }
+
+ final String[] packageNames = new String[] { packageName };
+ return getAppCrates(volumeUuid, packageNames, userId);
+ }
+
+ @NonNull
+ @Override
+ public ParceledListSlice<CrateInfo> queryCratesForUid(String volumeUuid, int uid,
+ @NonNull String callingPackage) {
+ final int userId = UserHandle.getUserId(uid);
+ if (userId != UserHandle.getCallingUserId()) {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.INTERACT_ACROSS_USERS, TAG);
+ }
+
+ if (Binder.getCallingUid() == uid) {
+ // No permissions required when asking about themselves
+ } else {
+ enforceCratesPermission(Binder.getCallingUid(), callingPackage);
+ }
+
+ final String[] packageNames = defeatNullable(mPackage.getPackagesForUid(uid));
+ String[] validatedPackageNames = new String[0];
+
+ for (String packageName : packageNames) {
+ if (TextUtils.isEmpty(packageName)) {
+ continue;
+ }
+
+ try {
+ final ApplicationInfo appInfo = mPackage.getApplicationInfoAsUser(packageName,
+ PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
+ if (appInfo == null) {
+ continue;
+ }
+
+ validatedPackageNames = ArrayUtils.appendElement(String.class,
+ validatedPackageNames, packageName);
+ } catch (NameNotFoundException e) {
+ throw new ParcelableException(e);
+ }
+ }
+
+ return getAppCrates(volumeUuid, validatedPackageNames, userId);
+ }
+
+ @NonNull
+ @Override
+ public ParceledListSlice<CrateInfo> queryCratesForUser(String volumeUuid, int userId,
+ @NonNull String callingPackage) {
+ if (userId != UserHandle.getCallingUserId()) {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.INTERACT_ACROSS_USERS, TAG);
+ }
+
+ // Always require permission to see user-level stats
+ enforceCratesPermission(Binder.getCallingUid(), callingPackage);
+
+ try {
+ CrateMetadata[] crateMetadatas = mInstaller.getUserCrates(volumeUuid, userId);
+ return new ParceledListSlice<>(convertCrateInfoFrom(crateMetadatas));
+ } catch (InstallerException e) {
+ throw new ParcelableException(new IOException(e.getMessage()));
+ }
+ }
}
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
index 96d2df125a3c..68b16f39e149 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
@@ -74,13 +74,13 @@ import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.ISoundTriggerService;
-import com.android.internal.util.Preconditions;
import com.android.server.SystemService;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Map;
+import java.util.Objects;
import java.util.TreeMap;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
@@ -429,9 +429,9 @@ public class SoundTriggerService extends SystemService {
@Override
public int startRecognitionForService(ParcelUuid soundModelId, Bundle params,
ComponentName detectionService, SoundTrigger.RecognitionConfig config) {
- Preconditions.checkNotNull(soundModelId);
- Preconditions.checkNotNull(detectionService);
- Preconditions.checkNotNull(config);
+ Objects.requireNonNull(soundModelId);
+ Objects.requireNonNull(detectionService);
+ Objects.requireNonNull(config);
enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 6132cc2250b9..e9db31ba3e25 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -76,7 +76,6 @@ import com.android.internal.app.IVoiceInteractor;
import com.android.internal.content.PackageMonitor;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.DumpUtils;
-import com.android.internal.util.Preconditions;
import com.android.server.FgThread;
import com.android.server.LocalServices;
import com.android.server.SystemService;
@@ -89,6 +88,7 @@ import com.android.server.wm.ActivityTaskManagerInternal;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.List;
+import java.util.Objects;
import java.util.concurrent.Executor;
/**
@@ -117,11 +117,11 @@ public class VoiceInteractionManagerService extends SystemService {
mResolver = context.getContentResolver();
mDbHelper = new DatabaseHelper(context);
mServiceStub = new VoiceInteractionManagerServiceStub();
- mAmInternal = Preconditions.checkNotNull(
+ mAmInternal = Objects.requireNonNull(
LocalServices.getService(ActivityManagerInternal.class));
- mAtmInternal = Preconditions.checkNotNull(
+ mAtmInternal = Objects.requireNonNull(
LocalServices.getService(ActivityTaskManagerInternal.class));
- mUserManagerInternal = Preconditions.checkNotNull(
+ mUserManagerInternal = Objects.requireNonNull(
LocalServices.getService(UserManagerInternal.class));
PermissionManagerServiceInternal permissionManagerInternal = LocalServices.getService(
@@ -149,7 +149,7 @@ public class VoiceInteractionManagerService extends SystemService {
@Override
public void onBootPhase(int phase) {
if (PHASE_SYSTEM_SERVICES_READY == phase) {
- mShortcutServiceInternal = Preconditions.checkNotNull(
+ mShortcutServiceInternal = Objects.requireNonNull(
LocalServices.getService(ShortcutServiceInternal.class));
mSoundTriggerInternal = LocalServices.getService(SoundTriggerInternal.class);
} else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
@@ -1291,6 +1291,7 @@ public class VoiceInteractionManagerService extends SystemService {
pw.println(" mCurUser: " + mCurUser);
pw.println(" mCurUserUnlocked: " + mCurUserUnlocked);
pw.println(" mCurUserSupported: " + mCurUserSupported);
+ dumpSupportedUsers(pw, " ");
if (mImpl == null) {
pw.println(" (No active implementation)");
return;
diff --git a/startop/iorap/src/com/google/android/startop/iorap/EventSequenceValidator.java b/startop/iorap/src/com/google/android/startop/iorap/EventSequenceValidator.java
new file mode 100644
index 000000000000..b75510b576f6
--- /dev/null
+++ b/startop/iorap/src/com/google/android/startop/iorap/EventSequenceValidator.java
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.startop.iorap;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Intent;
+import android.util.Log;
+
+import com.android.server.wm.ActivityMetricsLaunchObserver;
+
+/**
+ * A validator to check the correctness of event sequence during app startup.
+ *
+ * <p> A valid state transition of event sequence is shown as the following:
+ *
+ * <pre>
+ *
+ * +--------------------+
+ * | |
+ * | INIT |
+ * | |
+ * +--------------------+
+ * |
+ * |
+ * ↓
+ * +--------------------+
+ * | |
+ * +-------------------| INTENT_STARTED | ←--------------------------------+
+ * | | | |
+ * | +--------------------+ |
+ * | | |
+ * | | |
+ * ↓ ↓ |
+ * +--------------------+ +--------------------+ |
+ * | | | | |
+ * | INTENT_FAILED | | ACTIVITY_LAUNCHED |------------------+ |
+ * | | | | | |
+ * +--------------------+ +--------------------+ | |
+ * | | | |
+ * | ↓ ↓ |
+ * | +--------------------+ +--------------------+ |
+ * | | | | | |
+ * +------------------ | ACTIVITY_FINISHED | | ACTIVITY_CANCELLED | |
+ * | | | | | |
+ * | +--------------------+ +--------------------+ |
+ * | | | |
+ * | | | |
+ * | ↓ | |
+ * | +--------------------+ | |
+ * | | | | |
+ * | | REPORT_FULLY_DRAWN | | |
+ * | | | | |
+ * | +--------------------+ | |
+ * | | | |
+ * | | | |
+ * | ↓ | |
+ * | +--------------------+ | |
+ * | | | | |
+ * +-----------------→ | END |←-----------------+ |
+ * | | |
+ * +--------------------+ |
+ * | |
+ * | |
+ * | |
+ * +---------------------------------------------
+ *
+ * <p> END is not a real state in implementation. All states that points to END directly
+ * could transition to INTENT_STARTED.
+ *
+ * <p> If any bad transition happened, the state becomse UNKNOWN. The UNKNOWN state
+ * could be * accumulated, because during the UNKNOWN state more IntentStarted may
+ * be triggered. To recover from UNKNOWN to INIT, all the accumualted IntentStarted
+ * should termniate.
+ *
+ * <p> During UNKNOWN state, each IntentStarted increases the accumulation, and any of
+ * IntentFailed, ActivityLaunchCancelled and ActivityFinished decreases the accumulation.
+ * ReportFullyDrawn doesn't impact the accumulation.
+ */
+public class EventSequenceValidator implements ActivityMetricsLaunchObserver {
+ static final String TAG = "EventSequenceValidator";
+
+ private State state = State.INIT;
+ private long accIntentStartedEvents = 0;
+
+ @Override
+ public void onIntentStarted(@NonNull Intent intent, long timestampNs) {
+ if (state == State.UNKNOWN) {
+ Log.e(TAG, "IntentStarted during UNKNOWN." + intent);
+ incAccIntentStartedEvents();
+ return;
+ }
+
+ if (state != State.INIT &&
+ state != State.INTENT_FAILED &&
+ state != State.ACTIVITY_CANCELLED &&
+ state != State.ACTIVITY_FINISHED &&
+ state != State.REPORT_FULLY_DRAWN) {
+ Log.e(TAG,
+ String.format("Cannot transition from %s to %s", state, State.INTENT_STARTED));
+ incAccIntentStartedEvents();
+ incAccIntentStartedEvents();
+ return;
+ }
+
+ Log.i(TAG, String.format("Tansition from %s to %s", state, State.INTENT_STARTED));
+ state = State.INTENT_STARTED;
+ }
+
+ @Override
+ public void onIntentFailed() {
+ if (state == State.UNKNOWN) {
+ Log.e(TAG, "IntentFailed during UNKNOWN.");
+ decAccIntentStartedEvents();
+ return;
+ }
+ if (state != State.INTENT_STARTED) {
+ Log.e(TAG,
+ String.format("Cannot transition from %s to %s", state, State.INTENT_FAILED));
+ incAccIntentStartedEvents();
+ return;
+ }
+
+ Log.i(TAG, String.format("Tansition from %s to %s", state, State.INTENT_FAILED));
+ state = State.INTENT_FAILED;
+ }
+
+ @Override
+ public void onActivityLaunched(@NonNull @ActivityRecordProto byte[] activity,
+ @Temperature int temperature) {
+ if (state == State.UNKNOWN) {
+ Log.e(TAG, "onActivityLaunched during UNKNOWN.");
+ return;
+ }
+ if (state != State.INTENT_STARTED) {
+ Log.e(TAG,
+ String.format("Cannot transition from %s to %s", state, State.ACTIVITY_LAUNCHED));
+ incAccIntentStartedEvents();
+ return;
+ }
+
+ Log.i(TAG, String.format("Transition from %s to %s", state, State.ACTIVITY_LAUNCHED));
+ state = State.ACTIVITY_LAUNCHED;
+ }
+
+ @Override
+ public void onActivityLaunchCancelled(@Nullable @ActivityRecordProto byte[] activity) {
+ if (state == State.UNKNOWN) {
+ Log.e(TAG, "onActivityLaunchCancelled during UNKNOWN.");
+ decAccIntentStartedEvents();
+ return;
+ }
+ if (state != State.ACTIVITY_LAUNCHED) {
+ Log.e(TAG,
+ String.format("Cannot transition from %s to %s", state, State.ACTIVITY_CANCELLED));
+ incAccIntentStartedEvents();
+ return;
+ }
+
+ Log.i(TAG, String.format("Transition from %s to %s", state, State.ACTIVITY_CANCELLED));
+ state = State.ACTIVITY_CANCELLED;
+ }
+
+ @Override
+ public void onActivityLaunchFinished(@NonNull @ActivityRecordProto byte[] activity,
+ long timestampNs) {
+ if (state == State.UNKNOWN) {
+ Log.e(TAG, "onActivityLaunchFinished during UNKNOWN.");
+ decAccIntentStartedEvents();
+ return;
+ }
+
+ if (state != State.ACTIVITY_LAUNCHED) {
+ Log.e(TAG,
+ String.format("Cannot transition from %s to %s", state, State.ACTIVITY_FINISHED));
+ incAccIntentStartedEvents();
+ return;
+ }
+
+ Log.i(TAG, String.format("Transition from %s to %s", state, State.ACTIVITY_FINISHED));
+ state = State.ACTIVITY_FINISHED;
+ }
+
+ @Override
+ public void onReportFullyDrawn(@NonNull @ActivityRecordProto byte[] activity,
+ long timestampNs) {
+ if (state == State.UNKNOWN) {
+ Log.e(TAG, "onReportFullyDrawn during UNKNOWN.");
+ return;
+ }
+ if (state == State.INIT) {
+ return;
+ }
+
+ if (state != State.ACTIVITY_FINISHED) {
+ Log.e(TAG,
+ String.format("Cannot transition from %s to %s", state, State.REPORT_FULLY_DRAWN));
+ return;
+ }
+
+ Log.i(TAG, String.format("Transition from %s to %s", state, State.REPORT_FULLY_DRAWN));
+ state = State.REPORT_FULLY_DRAWN;
+ }
+
+ enum State {
+ INIT,
+ INTENT_STARTED,
+ INTENT_FAILED,
+ ACTIVITY_LAUNCHED,
+ ACTIVITY_CANCELLED,
+ ACTIVITY_FINISHED,
+ REPORT_FULLY_DRAWN,
+ UNKNOWN,
+ }
+
+ private void incAccIntentStartedEvents() {
+ if (accIntentStartedEvents < 0) {
+ throw new AssertionError(
+ String.format("The number of unknows cannot be negative"));
+ }
+ if (accIntentStartedEvents == 0) {
+ state = State.UNKNOWN;
+ }
+ ++accIntentStartedEvents;
+ Log.i(TAG,
+ String.format("inc AccIntentStartedEvents to %d", accIntentStartedEvents));
+ }
+
+ private void decAccIntentStartedEvents() {
+ if (accIntentStartedEvents <= 0) {
+ throw new AssertionError(
+ String.format("The number of unknows cannot be negative"));
+ }
+ if(accIntentStartedEvents == 1) {
+ state = State.INIT;
+ }
+ --accIntentStartedEvents;
+ Log.i(TAG,
+ String.format("dec AccIntentStartedEvents to %d", accIntentStartedEvents));
+ }
+}
diff --git a/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java b/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java
index f753548516ef..badff7bc2f8c 100644
--- a/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java
+++ b/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java
@@ -283,6 +283,7 @@ public class IorapForwardingService extends SystemService {
}
private final AppLaunchObserver mAppLaunchObserver = new AppLaunchObserver();
+ private final EventSequenceValidator mEventSequenceValidator = new EventSequenceValidator();
private boolean mRegisteredListeners = false;
private void registerInProcessListenersLocked() {
@@ -303,6 +304,7 @@ public class IorapForwardingService extends SystemService {
ActivityMetricsLaunchObserverRegistry launchObserverRegistry =
provideLaunchObserverRegistry();
launchObserverRegistry.registerLaunchObserver(mAppLaunchObserver);
+ launchObserverRegistry.registerLaunchObserver(mEventSequenceValidator);
mRegisteredListeners = true;
}
diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java
index 58abf0051539..456290cd772a 100644
--- a/telecomm/java/android/telecom/Conference.java
+++ b/telecomm/java/android/telecom/Conference.java
@@ -24,9 +24,6 @@ import android.net.Uri;
import android.os.Bundle;
import android.os.SystemClock;
import android.telecom.Connection.VideoProvider;
-import android.telephony.Annotation.RilRadioTechnology;
-import android.telephony.ServiceState;
-import android.telephony.TelephonyManager;
import android.util.ArraySet;
import java.util.ArrayList;
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 39d741c3d3bf..af3c55abf00c 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -485,6 +485,103 @@ public class TelecomManager {
"android.telecom.extra.START_CALL_WITH_RTT";
/**
+ * Start an activity indicating that the completion of an outgoing call or an incoming call
+ * which was not blocked by the {@link CallScreeningService}, and which was NOT terminated
+ * while the call was in {@link Call#STATE_AUDIO_PROCESSING}.
+ *
+ * The {@link Uri} extra {@link #EXTRA_HANDLE} will contain the uri handle(phone number) for the
+ * call which completed.
+ *
+ * The integer extra {@link #EXTRA_DISCONNECT_CAUSE} will indicate the reason for the call
+ * disconnection. See {@link #EXTRA_DISCONNECT_CAUSE} for more information.
+ *
+ * The integer extra {@link #EXTRA_CALL_DURATION} will indicate the duration of the call. See
+ * {@link #EXTRA_CALL_DURATION} for more information.
+ */
+ public static final String ACTION_POST_CALL = "android.telecom.action.POST_CALL";
+
+ /**
+ * A {@link Uri} extra, which when set on the {@link #ACTION_POST_CALL} intent, indicates the
+ * uri handle(phone number) of the completed call.
+ */
+ public static final String EXTRA_HANDLE = "android.telecom.extra.HANDLE";
+
+ /**
+ * A integer value provided for completed calls to indicate the reason for the call
+ * disconnection.
+ * <p>
+ * Allowed values:
+ * <ul>
+ * <li>{@link DisconnectCause#UNKNOWN}</li>
+ * <li>{@link DisconnectCause#LOCAL}</li>
+ * <li>{@link DisconnectCause#REMOTE}</li>
+ * <li>{@link DisconnectCause#REJECTED}</li>
+ * <li>{@link DisconnectCause#MISSED}</li>
+ * </ul>
+ * </p>
+ */
+ public static final String EXTRA_DISCONNECT_CAUSE = "android.telecom.extra.DISCONNECT_CAUSE";
+
+ /**
+ * A integer value provided for completed calls to indicate the duration of the call.
+ * <p>
+ * Allowed values:
+ * <ul>
+ * <li>{@link #DURATION_VERY_SHORT}</li>
+ * <li>{@link #DURATION_SHORT}</li>
+ * <li>{@link #DURATION_MEDIUM}</li>
+ * <li>{@link #DURATION_LONG}</li>
+ * </ul>
+ * </p>
+ */
+ public static final String EXTRA_CALL_DURATION = "android.telecom.extra.CALL_DURATION";
+
+ /**
+ * A integer value for {@link #EXTRA_CALL_DURATION}, indicates the duration of the completed
+ * call was < 3 seconds.
+ */
+ public static final int DURATION_VERY_SHORT = 0;
+
+ /**
+ * A integer value for {@link #EXTRA_CALL_DURATION}, indicates the duration of the completed
+ * call was >= 3 seconds and < 60 seconds.
+ */
+ public static final int DURATION_SHORT = 1;
+
+ /**
+ * A integer value for {@link #EXTRA_CALL_DURATION}, indicates the duration of the completed
+ * call was >= 60 seconds and < 120 seconds.
+ */
+ public static final int DURATION_MEDIUM = 2;
+
+ /**
+ * A integer value for {@link #EXTRA_CALL_DURATION}, indicates the duration of the completed
+ * call was >= 120 seconds.
+ */
+ public static final int DURATION_LONG = 3;
+
+ /**
+ * The threshold between {@link #DURATION_VERY_SHORT} calls and {@link #DURATION_SHORT} calls in
+ * milliseconds.
+ * @hide
+ */
+ public static final long VERY_SHORT_CALL_TIME_MS = 3000;
+
+ /**
+ * The threshold between {@link #DURATION_SHORT} calls and {@link #DURATION_MEDIUM} calls in
+ * milliseconds.
+ * @hide
+ */
+ public static final long SHORT_CALL_TIME_MS = 60000;
+
+ /**
+ * The threshold between {@link #DURATION_MEDIUM} calls and {@link #DURATION_LONG} calls in
+ * milliseconds.
+ * @hide
+ */
+ public static final long MEDIUM_CALL_TIME_MS = 120000;
+
+ /**
* A boolean meta-data value indicating whether an {@link InCallService} implements an
* in-call user interface. Dialer implementations (see {@link #getDefaultDialerPackage()}) which
* would also like to replace the in-call interface should set this meta-data to {@code true} in
diff --git a/telephony/common/com/android/internal/telephony/SmsNumberUtils.java b/telephony/common/com/android/internal/telephony/SmsNumberUtils.java
index 367aad1837ce..06c08f56aa1f 100644
--- a/telephony/common/com/android/internal/telephony/SmsNumberUtils.java
+++ b/telephony/common/com/android/internal/telephony/SmsNumberUtils.java
@@ -20,8 +20,8 @@ import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.os.Binder;
-import android.os.Build;
import android.os.PersistableBundle;
+import android.os.SystemProperties;
import android.telephony.CarrierConfigManager;
import android.telephony.PhoneNumberUtils;
import android.telephony.Rlog;
@@ -43,7 +43,7 @@ import java.util.HashMap;
*/
public class SmsNumberUtils {
private static final String TAG = "SmsNumberUtils";
- private static final boolean DBG = Build.IS_DEBUGGABLE;
+ private static final boolean DBG = SystemProperties.getInt("ro.debuggable", 0) == 1;
private static final String PLUS_SIGN = "+";
diff --git a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
index fbb1380efcc1..80a55b2a1147 100644
--- a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
@@ -344,7 +344,7 @@ public final class TelephonyPermissions {
DevicePolicyManager devicePolicyManager =
(DevicePolicyManager) context.getSystemService(
Context.DEVICE_POLICY_SERVICE);
- if (devicePolicyManager != null && devicePolicyManager.checkDeviceIdentifierAccess(
+ if (devicePolicyManager != null && devicePolicyManager.hasDeviceIdentifierAccess(
callingPackage, pid, uid)) {
return true;
}
diff --git a/telephony/java/android/telephony/Annotation.java b/telephony/java/android/telephony/Annotation.java
index 3940a3b0a1cf..9e6dfef0608b 100644
--- a/telephony/java/android/telephony/Annotation.java
+++ b/telephony/java/android/telephony/Annotation.java
@@ -98,7 +98,13 @@ public class Annotation {
TelephonyManager.NETWORK_TYPE_GSM,
TelephonyManager.NETWORK_TYPE_TD_SCDMA,
TelephonyManager.NETWORK_TYPE_IWLAN,
- TelephonyManager.NETWORK_TYPE_LTE_CA,
+
+ //TODO: In order for @SystemApi methods to use this class, there cannot be any
+ // public hidden members. This network type is marked as hidden because it is not a
+ // true network type and we are looking to remove it completely from the available list
+ // of network types.
+ //TelephonyManager.NETWORK_TYPE_LTE_CA,
+
TelephonyManager.NETWORK_TYPE_NR,
})
@Retention(RetentionPolicy.SOURCE)
@@ -485,30 +491,85 @@ public class Annotation {
PreciseCallState.PRECISE_CALL_STATE_DISCONNECTING})
public @interface PreciseCallStates {}
+ @IntDef(value = {
+ DisconnectCause.NOT_VALID,
+ DisconnectCause.NOT_DISCONNECTED,
+ DisconnectCause.INCOMING_MISSED,
+ DisconnectCause.NORMAL,
+ DisconnectCause.LOCAL,
+ DisconnectCause.BUSY,
+ DisconnectCause.CONGESTION,
+ DisconnectCause.MMI,
+ DisconnectCause.INVALID_NUMBER,
+ DisconnectCause.NUMBER_UNREACHABLE,
+ DisconnectCause.SERVER_UNREACHABLE,
+ DisconnectCause.INVALID_CREDENTIALS,
+ DisconnectCause.OUT_OF_NETWORK,
+ DisconnectCause.SERVER_ERROR,
+ DisconnectCause.TIMED_OUT,
+ DisconnectCause.LOST_SIGNAL,
+ DisconnectCause.LIMIT_EXCEEDED,
+ DisconnectCause.INCOMING_REJECTED,
+ DisconnectCause.POWER_OFF,
+ DisconnectCause.OUT_OF_SERVICE,
+ DisconnectCause.ICC_ERROR,
+ DisconnectCause.CALL_BARRED,
+ DisconnectCause.FDN_BLOCKED,
+ DisconnectCause.CS_RESTRICTED,
+ DisconnectCause.CS_RESTRICTED_NORMAL,
+ DisconnectCause.CS_RESTRICTED_EMERGENCY,
+ DisconnectCause.UNOBTAINABLE_NUMBER,
+ DisconnectCause.CDMA_LOCKED_UNTIL_POWER_CYCLE,
+ DisconnectCause.CDMA_DROP,
+ DisconnectCause.CDMA_INTERCEPT,
+ DisconnectCause.CDMA_REORDER,
+ DisconnectCause.CDMA_SO_REJECT,
+ DisconnectCause.CDMA_RETRY_ORDER,
+ DisconnectCause.CDMA_ACCESS_FAILURE,
+ DisconnectCause.CDMA_PREEMPTED,
+ DisconnectCause.CDMA_NOT_EMERGENCY,
+ DisconnectCause.CDMA_ACCESS_BLOCKED,
+ DisconnectCause.ERROR_UNSPECIFIED,
+ })
@Retention(RetentionPolicy.SOURCE)
- @IntDef(prefix = {"RIL_RADIO_TECHNOLOGY_" }, value = {
- ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN,
- ServiceState.RIL_RADIO_TECHNOLOGY_GPRS,
- ServiceState.RIL_RADIO_TECHNOLOGY_EDGE,
- ServiceState.RIL_RADIO_TECHNOLOGY_UMTS,
- ServiceState.RIL_RADIO_TECHNOLOGY_IS95A,
- ServiceState.RIL_RADIO_TECHNOLOGY_IS95B,
- ServiceState.RIL_RADIO_TECHNOLOGY_1xRTT,
- ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_0,
- ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_A,
- ServiceState.RIL_RADIO_TECHNOLOGY_HSDPA,
- ServiceState.RIL_RADIO_TECHNOLOGY_HSUPA,
- ServiceState.RIL_RADIO_TECHNOLOGY_HSPA,
- ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_B,
- ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD,
- ServiceState.RIL_RADIO_TECHNOLOGY_LTE,
- ServiceState.RIL_RADIO_TECHNOLOGY_HSPAP,
- ServiceState.RIL_RADIO_TECHNOLOGY_GSM,
- ServiceState.RIL_RADIO_TECHNOLOGY_TD_SCDMA,
- ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN,
- ServiceState.RIL_RADIO_TECHNOLOGY_LTE_CA,
- ServiceState.RIL_RADIO_TECHNOLOGY_NR})
- public @interface RilRadioTechnology {}
+ public @interface DisconnectCauses {
+ }
+
+ @IntDef(value = {
+ PreciseDisconnectCause.NOT_VALID,
+ PreciseDisconnectCause.NO_DISCONNECT_CAUSE_AVAILABLE,
+ PreciseDisconnectCause.UNOBTAINABLE_NUMBER,
+ PreciseDisconnectCause.NORMAL,
+ PreciseDisconnectCause.BUSY,
+ PreciseDisconnectCause.NUMBER_CHANGED,
+ PreciseDisconnectCause.STATUS_ENQUIRY,
+ PreciseDisconnectCause.NORMAL_UNSPECIFIED,
+ PreciseDisconnectCause.NO_CIRCUIT_AVAIL,
+ PreciseDisconnectCause.TEMPORARY_FAILURE,
+ PreciseDisconnectCause.SWITCHING_CONGESTION,
+ PreciseDisconnectCause.CHANNEL_NOT_AVAIL,
+ PreciseDisconnectCause.QOS_NOT_AVAIL,
+ PreciseDisconnectCause.BEARER_NOT_AVAIL,
+ PreciseDisconnectCause.ACM_LIMIT_EXCEEDED,
+ PreciseDisconnectCause.CALL_BARRED,
+ PreciseDisconnectCause.FDN_BLOCKED,
+ PreciseDisconnectCause.IMSI_UNKNOWN_IN_VLR,
+ PreciseDisconnectCause.IMEI_NOT_ACCEPTED,
+ PreciseDisconnectCause.CDMA_LOCKED_UNTIL_POWER_CYCLE,
+ PreciseDisconnectCause.CDMA_DROP,
+ PreciseDisconnectCause.CDMA_INTERCEPT,
+ PreciseDisconnectCause.CDMA_REORDER,
+ PreciseDisconnectCause.CDMA_SO_REJECT,
+ PreciseDisconnectCause.CDMA_RETRY_ORDER,
+ PreciseDisconnectCause.CDMA_ACCESS_FAILURE,
+ PreciseDisconnectCause.CDMA_PREEMPTED,
+ PreciseDisconnectCause.CDMA_NOT_EMERGENCY,
+ PreciseDisconnectCause.CDMA_ACCESS_BLOCKED,
+ PreciseDisconnectCause.ERROR_UNSPECIFIED,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface PreciseDisconnectCauses {
+ }
@IntDef({
Connection.AUDIO_CODEC_NONE,
@@ -535,4 +596,17 @@ public class Annotation {
@Retention(RetentionPolicy.SOURCE)
public @interface ImsAudioCodec {
}
+
+ /**
+ * UICC SIM Application Types
+ */
+ @IntDef(prefix = { "APPTYPE_" }, value = {
+ TelephonyManager.APPTYPE_SIM,
+ TelephonyManager.APPTYPE_USIM,
+ TelephonyManager.APPTYPE_RUIM,
+ TelephonyManager.APPTYPE_CSIM,
+ TelephonyManager.APPTYPE_ISIM
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface UiccAppType{}
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 7381acb36812..eea08dc6c76b 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1855,6 +1855,14 @@ public class CarrierConfigManager {
*/
public static final String KEY_CDMA_ROAMING_MODE_INT = "cdma_roaming_mode_int";
+ /**
+ * Determines whether 1X voice calls is supported for some CDMA carriers.
+ * Default value is true.
+ * @hide
+ */
+ @SystemApi
+ public static final String KEY_SUPPORT_CDMA_1X_VOICE_CALLS_BOOL =
+ "support_cdma_1x_voice_calls_bool";
/**
* Boolean indicating if support is provided for directly dialing FDN number from FDN list.
@@ -2308,13 +2316,41 @@ public class CarrierConfigManager {
/**
* Determine whether to use only RSRP for the number of LTE signal bars.
* @hide
+ *
+ * @deprecated use {@link #KEY_PARAMETERS_USED_FOR_LTE_SIGNAL_BAR_INT}.
*/
// FIXME: this key and related keys must not be exposed without a consistent philosophy for
// all RATs.
+ @Deprecated
public static final String KEY_USE_ONLY_RSRP_FOR_LTE_SIGNAL_BAR_BOOL =
"use_only_rsrp_for_lte_signal_bar_bool";
/**
+ * Bit-field integer to determine whether to use Reference Signal Received Power (RSRP),
+ * Reference Signal Received Quality (RSRQ), or/and Reference Signal Signal to Noise Ratio
+ * (RSSNR) for the number of LTE signal bars and signal criteria reporting enabling.
+ *
+ * <p> If a measure is not set, signal criteria reporting from modem will not be triggered and
+ * not be used for calculating signal level. If multiple measures are set bit, the parameter
+ * whose value is smallest is used to indicate the signal level.
+ *
+ * RSRP = 1 << 0,
+ * RSRQ = 1 << 1,
+ * RSSNR = 1 << 2,
+ *
+ * The value of this key must be bitwise OR of {@link CellSignalStrengthLte#USE_RSRP},
+ * {@link CellSignalStrengthLte#USE_RSRQ}, {@link CellSignalStrengthLte#USE_RSSNR}.
+ *
+ * For example, if both RSRP and RSRQ are used, the value of key is 3 (1 << 0 | 1 << 1).
+ * If the key is invalid or not configured, a default value (RSRP | RSSNR = 1 << 0 | 1 << 2)
+ * will apply.
+ *
+ * @hide
+ */
+ public static final String KEY_PARAMETERS_USED_FOR_LTE_SIGNAL_BAR_INT =
+ "parameters_used_for_lte_signal_bar_int";
+
+ /**
* List of 4 customized 5G SS reference signal received power (SSRSRP) thresholds.
*
* Reference: 3GPP TS 38.215
@@ -2617,6 +2653,42 @@ public class CarrierConfigManager {
"lte_rsrp_thresholds_int_array";
/**
+ * A list of 4 customized LTE Reference Signal Received Quality (RSRQ) thresholds.
+ *
+ * Reference: TS 136.133 v12.6.0 section 9.1.7 - RSRQ Measurement Report Mapping.
+ *
+ * 4 threshold integers must be within the boundaries [-34 dB, 3 dB], and the levels are:
+ * "NONE: [-34, threshold1)"
+ * "POOR: [threshold1, threshold2)"
+ * "MODERATE: [threshold2, threshold3)"
+ * "GOOD: [threshold3, threshold4)"
+ * "EXCELLENT: [threshold4, 3]"
+ *
+ * This key is considered invalid if the format is violated. If the key is invalid or
+ * not configured, a default value set will apply.
+ */
+ public static final String KEY_LTE_RSRQ_THRESHOLDS_INT_ARRAY =
+ "lte_rsrq_thresholds_int_array";
+
+ /**
+ * A list of 4 customized LTE Reference Signal Signal to Noise Ratio (RSSNR) thresholds.
+ *
+ * 4 threshold integers must be within the boundaries [-200, 300], and the levels are:
+ * "NONE: [-200, threshold1)"
+ * "POOR: [threshold1, threshold2)"
+ * "MODERATE: [threshold2, threshold3)"
+ * "GOOD: [threshold3, threshold4)"
+ * "EXCELLENT: [threshold4, 300]"
+ * Note: the unit of the values is 10*db; it is derived by multiplying 10 on the original dB
+ * value reported by modem.
+ *
+ * This key is considered invalid if the format is violated. If the key is invalid or
+ * not configured, a default value set will apply.
+ */
+ public static final String KEY_LTE_RSSNR_THRESHOLDS_INT_ARRAY =
+ "lte_rssnr_thresholds_int_array";
+
+ /**
* Decides when clients try to bind to iwlan network service, which package name will
* the binding intent go to.
* @hide
@@ -3048,16 +3120,18 @@ public class CarrierConfigManager {
"data_switch_validation_timeout_long";
/**
- * GPS configs. See android.hardware.gnss@1.0 IGnssConfiguration.
- * @hide
+ * GPS configs. See the GNSS HAL documentation for more details.
*/
public static final class Gps {
+ private Gps() {}
+
/** Prefix of all Gps.KEY_* constants. */
public static final String KEY_PREFIX = "gps.";
/**
* Location information during (and after) an emergency call is only provided over control
* plane signaling from the network.
+ * @hide
*/
public static final int SUPL_EMERGENCY_MODE_TYPE_CP_ONLY = 0;
@@ -3065,6 +3139,7 @@ public class CarrierConfigManager {
* Location information during (and after) an emergency call is provided over the data
* plane and serviced by the framework GNSS service, but if it fails, the carrier also
* supports control plane backup signaling.
+ * @hide
*/
public static final int SUPL_EMERGENCY_MODE_TYPE_CP_FALLBACK = 1;
@@ -3072,6 +3147,7 @@ public class CarrierConfigManager {
* Location information during (and after) an emergency call is provided over the data plane
* and serviced by the framework GNSS service only. There is no backup signalling over the
* control plane if it fails.
+ * @hide
*/
public static final int SUPL_EMERGENCY_MODE_TYPE_DP_ONLY = 2;
@@ -3088,10 +3164,14 @@ public class CarrierConfigManager {
/**
* SUPL server host for SET Initiated & non-ES Network-Initiated SUPL requests.
* Default to supl.google.com
+ * @hide
*/
public static final String KEY_SUPL_HOST_STRING = KEY_PREFIX + "supl_host";
- /** SUPL server port. Default to 7275. */
+ /**
+ * SUPL server port. Default to 7275.
+ * @hide
+ */
public static final String KEY_SUPL_PORT_STRING = KEY_PREFIX + "supl_port";
/**
@@ -3099,6 +3179,7 @@ public class CarrierConfigManager {
* with bits 0:7 representing a service indicator field, bits 8:15
* representing the minor version and bits 16:23 representing the
* major version. Default to 0x20000.
+ * @hide
*/
public static final String KEY_SUPL_VER_STRING = KEY_PREFIX + "supl_ver";
@@ -3106,6 +3187,7 @@ public class CarrierConfigManager {
* SUPL_MODE configuration bit mask
* 1 - Mobile Station Based. This is default.
* 2 - Mobile Station Assisted.
+ * @hide
*/
public static final String KEY_SUPL_MODE_STRING = KEY_PREFIX + "supl_mode";
@@ -3114,6 +3196,7 @@ public class CarrierConfigManager {
* (e.g. E911), and SUPL non-ES requests to only outside of non user emergency sessions.
* 0 - no.
* 1 - yes. This is default.
+ * @hide
*/
public static final String KEY_SUPL_ES_STRING = KEY_PREFIX + "supl_es";
@@ -3122,6 +3205,7 @@ public class CarrierConfigManager {
* 0 - Radio Resource Location Protocol in user plane and control plane. This is default.
* 1 - Enable LTE Positioning Protocol in user plane.
* 2 - Enable LTE Positioning Protocol in control plane.
+ * @hide
*/
public static final String KEY_LPP_PROFILE_STRING = KEY_PREFIX + "lpp_profile";
@@ -3129,6 +3213,7 @@ public class CarrierConfigManager {
* Determine whether to use emergency PDN for emergency SUPL.
* 0 - no.
* 1 - yes. This is default.
+ * @hide
*/
public static final String KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING =
KEY_PREFIX + "use_emergency_pdn_for_emergency_supl";
@@ -3139,6 +3224,7 @@ public class CarrierConfigManager {
* 1 - Use A-GLONASS in Radio Resource Control(RRC) control-plane.
* 2 - Use A-GLONASS in Radio Resource Location user-plane.
* 4 - Use A-GLONASS in LTE Positioning Protocol User plane.
+ * @hide
*/
public static final String KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING =
KEY_PREFIX + "a_glonass_pos_protocol_select";
@@ -3150,11 +3236,13 @@ public class CarrierConfigManager {
* "1" - Lock Mobile Originated GPS functionalities.
* "2" - Lock Network initiated GPS functionalities.
* "3" - Lock both. This is default.
+ * @hide
*/
public static final String KEY_GPS_LOCK_STRING = KEY_PREFIX + "gps_lock";
/**
* Control Plane / SUPL NI emergency extension time in seconds. Default to "0".
+ * @hide
*/
public static final String KEY_ES_EXTENSION_SEC_STRING = KEY_PREFIX + "es_extension_sec";
@@ -3163,6 +3251,7 @@ public class CarrierConfigManager {
* the non-framework entities requesting location directly from GNSS without involving
* the framework, as managed by IGnssVisibilityControl.hal. For example,
* "com.example.mdt com.example.ims".
+ * @hide
*/
public static final String KEY_NFW_PROXY_APPS_STRING = KEY_PREFIX + "nfw_proxy_apps";
@@ -3178,6 +3267,7 @@ public class CarrierConfigManager {
* {@link #SUPL_EMERGENCY_MODE_TYPE_CP_ONLY}.
* <p>
* The default value for this configuration is {@link #SUPL_EMERGENCY_MODE_TYPE_CP_ONLY}.
+ * @hide
*/
public static final String KEY_ES_SUPL_CONTROL_PLANE_SUPPORT_INT = KEY_PREFIX
+ "es_supl_control_plane_support_int";
@@ -3189,6 +3279,7 @@ public class CarrierConfigManager {
* <p>
* A string array of PLMNs that do not support a control-plane mechanism for getting a
* user's location for SUPL ES.
+ * @hide
*/
public static final String KEY_ES_SUPL_DATA_PLANE_ONLY_ROAMING_PLMN_STRING_ARRAY =
KEY_PREFIX + "es_supl_data_plane_only_roaming_plmn_string_array";
@@ -3603,6 +3694,7 @@ public class CarrierConfigManager {
sDefaults.putBoolean(KEY_FORCE_IMEI_BOOL, false);
sDefaults.putInt(
KEY_CDMA_ROAMING_MODE_INT, TelephonyManager.CDMA_ROAMING_MODE_RADIO_DEFAULT);
+ sDefaults.putBoolean(KEY_SUPPORT_CDMA_1X_VOICE_CALLS_BOOL, true);
sDefaults.putString(KEY_RCS_CONFIG_SERVER_URL_STRING, "");
// Carrier Signalling Receivers
@@ -3721,6 +3813,20 @@ public class CarrierConfigManager {
-108, /* SIGNAL_STRENGTH_GOOD */
-98, /* SIGNAL_STRENGTH_GREAT */
});
+ sDefaults.putIntArray(KEY_LTE_RSRQ_THRESHOLDS_INT_ARRAY,
+ new int[] {
+ -19, /* SIGNAL_STRENGTH_POOR */
+ -17, /* SIGNAL_STRENGTH_MODERATE */
+ -14, /* SIGNAL_STRENGTH_GOOD */
+ -12 /* SIGNAL_STRENGTH_GREAT */
+ });
+ sDefaults.putIntArray(KEY_LTE_RSSNR_THRESHOLDS_INT_ARRAY,
+ new int[] {
+ -30, /* SIGNAL_STRENGTH_POOR */
+ 10, /* SIGNAL_STRENGTH_MODERATE */
+ 45, /* SIGNAL_STRENGTH_GOOD */
+ 130 /* SIGNAL_STRENGTH_GREAT */
+ });
sDefaults.putIntArray(KEY_WCDMA_RSCP_THRESHOLDS_INT_ARRAY,
new int[] {
-115, /* SIGNAL_STRENGTH_POOR */
@@ -3824,6 +3930,34 @@ public class CarrierConfigManager {
new int[] {4 /* BUSY */});
sDefaults.putBoolean(KEY_PREVENT_CLIR_ACTIVATION_AND_DEACTIVATION_CODE_BOOL, false);
sDefaults.putLong(KEY_DATA_SWITCH_VALIDATION_TIMEOUT_LONG, 2000);
+ sDefaults.putInt(KEY_PARAMETERS_USED_FOR_LTE_SIGNAL_BAR_INT,
+ CellSignalStrengthLte.USE_RSRP | CellSignalStrengthLte.USE_RSSNR);
+ // Default wifi configurations.
+ sDefaults.putAll(Wifi.getDefaults());
+ }
+
+ /**
+ * Wi-Fi configs used in WiFi Module.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final class Wifi {
+ /** Prefix of all Wifi.KEY_* constants. */
+ public static final String KEY_PREFIX = "wifi.";
+ /**
+ * It contains the maximum client count definition that the carrier owns.
+ */
+ public static final String KEY_HOTSPOT_MAX_CLIENT_COUNT =
+ KEY_PREFIX + "hotspot_maximum_client_count";
+
+ private static PersistableBundle getDefaults() {
+ PersistableBundle defaults = new PersistableBundle();
+ defaults.putInt(KEY_HOTSPOT_MAX_CLIENT_COUNT, 0);
+ return defaults;
+ }
+
+ private Wifi() {}
}
/**
@@ -4022,13 +4156,28 @@ public class CarrierConfigManager {
}
}
- /** {@hide} */
+ /**
+ * Gets the package name for a default carrier service.
+ * @return the package name for a default carrier service; empty string if not available.
+ *
+ * @hide
+ */
+ @NonNull
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public String getDefaultCarrierServicePackageName() {
try {
- return getICarrierConfigLoader().getDefaultCarrierServicePackageName();
- } catch (Throwable t) {
- return null;
+ ICarrierConfigLoader loader = getICarrierConfigLoader();
+ if (loader == null) {
+ Rlog.w(TAG, "getDefaultCarrierServicePackageName ICarrierConfigLoader is null");
+ return "";
+ }
+ return loader.getDefaultCarrierServicePackageName();
+ } catch (RemoteException ex) {
+ Rlog.e(TAG, "getDefaultCarrierServicePackageName ICarrierConfigLoader is null"
+ + ex.toString());
}
+ return "";
}
/**
diff --git a/telephony/java/android/telephony/CbGeoUtils.java b/telephony/java/android/telephony/CbGeoUtils.java
index d4d4e1374477..84be4e8b9ba4 100644
--- a/telephony/java/android/telephony/CbGeoUtils.java
+++ b/telephony/java/android/telephony/CbGeoUtils.java
@@ -26,12 +26,16 @@ import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
-
/**
- * This utils class is specifically used for geo-targeting of CellBroadcast messages.
+ * This utils class is used for geo-fencing of CellBroadcast messages and is used by the cell
+ * broadcast module.
+ *
* The coordinates used by this utils class are latitude and longitude, but some algorithms in this
* class only use them as coordinates on plane, so the calculation will be inaccurate. So don't use
* this class for anything other then geo-targeting of cellbroadcast messages.
+ *
+ * More information regarding cell broadcast geo-fencing logic is laid out in 3GPP TS 23.041 and
+ * ATIS-0700041.
* @hide
*/
@SystemApi
@@ -82,7 +86,7 @@ public class CbGeoUtils {
/** @hide */
private static final String POLYGON_SYMBOL = "polygon";
- /** Point represent by (latitude, longitude). */
+ /** A point represented by (latitude, longitude). */
public static class LatLng {
public final double lat;
public final double lng;
@@ -98,8 +102,8 @@ public class CbGeoUtils {
}
/**
- * @param p the point use to calculate the subtraction result.
- * @return the result of this point subtract the given point {@code p}.
+ * @param p the point to subtract
+ * @return the result of the subtraction
*/
@NonNull
public LatLng subtract(@NonNull LatLng p) {
@@ -107,9 +111,9 @@ public class CbGeoUtils {
}
/**
- * Calculate the distance in meter between this point and the given point {@code p}.
- * @param p the point use to calculate the distance.
- * @return the distance in meter.
+ * Calculate the distance in meters between this point and the given point {@code p}.
+ * @param p the point used to calculate the distance.
+ * @return the distance in meters.
*/
public double distance(@NonNull LatLng p) {
double dlat = Math.sin(0.5 * Math.toRadians(lat - p.lat));
@@ -126,8 +130,9 @@ public class CbGeoUtils {
}
/**
- * The class represents a simple polygon with at least 3 points.
- * @hide
+ * A class representing a simple polygon with at least 3 points. This is used for geo-fencing
+ * logic with cell broadcasts. More information regarding cell broadcast geo-fencing logic is
+ * laid out in 3GPP TS 23.041 and ATIS-0700041.
*/
public static class Polygon implements Geometry {
/**
@@ -146,7 +151,7 @@ public class CbGeoUtils {
* connected to form an edge of the polygon. The polygon has at least 3 vertices, and the
* last vertices and the first vertices must be adjacent.
*
- * The longitude difference in the vertices should be less than 180 degree.
+ * The longitude difference in the vertices should be less than 180 degrees.
*/
public Polygon(@NonNull List<LatLng> vertices) {
mVertices = vertices;
@@ -165,19 +170,24 @@ public class CbGeoUtils {
.collect(Collectors.toList());
}
- public List<LatLng> getVertices() {
+ /**
+ * Return the list of vertices which compose the polygon.
+ */
+ public @NonNull List<LatLng> getVertices() {
return mVertices;
}
/**
- * Check if the given point {@code p} is inside the polygon. This method counts the number
- * of times the polygon winds around the point P, A.K.A "winding number". The point is
- * outside only when this "winding number" is 0.
+ * Check if the given LatLng is inside the polygon.
*
- * If a point is on the edge of the polygon, it is also considered to be inside the polygon.
+ * If a LatLng is on the edge of the polygon, it is also considered to be inside the
+ * polygon.
*/
@Override
- public boolean contains(LatLng latLng) {
+ public boolean contains(@NonNull LatLng latLng) {
+ // This method counts the number of times the polygon winds around the point P, A.K.A
+ // "winding number". The point is outside only when this "winding number" is 0.
+
Point p = convertAndScaleLatLng(latLng);
int n = mScaledVertices.size();
@@ -246,6 +256,7 @@ public class CbGeoUtils {
return a.x * b.y - a.y * b.x;
}
+ /** @hide */
static final class Point {
public final double x;
public final double y;
@@ -271,29 +282,47 @@ public class CbGeoUtils {
}
/**
- * The class represents a circle.
- * @hide
+ * A class represents a {@link Geometry} in the shape of a Circle. This is used for handling
+ * geo-fenced cell broadcasts. More information regarding cell broadcast geo-fencing logic is
+ * laid out in 3GPP TS 23.041 and ATIS-0700041.
*/
public static class Circle implements Geometry {
private final LatLng mCenter;
private final double mRadiusMeter;
- public Circle(LatLng center, double radiusMeter) {
+ /**
+ * Construct a Circle given a center point and a radius in meters.
+ *
+ * @param center the latitude and longitude of the center of the circle
+ * @param radiusInMeters the radius of the circle in meters
+ */
+ public Circle(@NonNull LatLng center, double radiusInMeters) {
this.mCenter = center;
- this.mRadiusMeter = radiusMeter;
+ this.mRadiusMeter = radiusInMeters;
}
- public LatLng getCenter() {
+ /**
+ * Return the latitude and longitude of the center of the circle;
+ */
+ public @NonNull LatLng getCenter() {
return mCenter;
}
+ /**
+ * Return the radius of the circle in meters.
+ */
public double getRadius() {
return mRadiusMeter;
}
+ /**
+ * Check if the given LatLng is inside the circle.
+ *
+ * If a LatLng is on the edge of the circle, it is also considered to be inside the circle.
+ */
@Override
- public boolean contains(LatLng p) {
- return mCenter.distance(p) <= mRadiusMeter;
+ public boolean contains(@NonNull LatLng latLng) {
+ return mCenter.distance(latLng) <= mRadiusMeter;
}
@Override
diff --git a/telephony/java/android/telephony/CellIdentity.java b/telephony/java/android/telephony/CellIdentity.java
index b7dab161c331..e523fbab2bb0 100644
--- a/telephony/java/android/telephony/CellIdentity.java
+++ b/telephony/java/android/telephony/CellIdentity.java
@@ -19,6 +19,7 @@ package android.telephony;
import android.annotation.CallSuper;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
@@ -181,7 +182,8 @@ public abstract class CellIdentity implements Parcelable {
* @return a CellLocation object for this CellIdentity
* @hide
*/
- public abstract CellLocation asCellLocation();
+ @SystemApi
+ public abstract @NonNull CellLocation asCellLocation();
@Override
public boolean equals(Object other) {
diff --git a/telephony/java/android/telephony/CellIdentityCdma.java b/telephony/java/android/telephony/CellIdentityCdma.java
index 880d3db681b5..54236b426d98 100644
--- a/telephony/java/android/telephony/CellIdentityCdma.java
+++ b/telephony/java/android/telephony/CellIdentityCdma.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.NonNull;
import android.os.Parcel;
import android.telephony.cdma.CdmaCellLocation;
@@ -198,6 +199,7 @@ public final class CellIdentityCdma extends CellIdentity {
}
/** @hide */
+ @NonNull
@Override
public CdmaCellLocation asCellLocation() {
CdmaCellLocation cl = new CdmaCellLocation();
diff --git a/telephony/java/android/telephony/CellIdentityGsm.java b/telephony/java/android/telephony/CellIdentityGsm.java
index 25c6577bdcf5..4e4454d6a1c2 100644
--- a/telephony/java/android/telephony/CellIdentityGsm.java
+++ b/telephony/java/android/telephony/CellIdentityGsm.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
@@ -200,6 +201,7 @@ public final class CellIdentityGsm extends CellIdentity {
}
/** @hide */
+ @NonNull
@Override
public GsmCellLocation asCellLocation() {
GsmCellLocation cl = new GsmCellLocation();
diff --git a/telephony/java/android/telephony/CellIdentityLte.java b/telephony/java/android/telephony/CellIdentityLte.java
index 997b19f3d4eb..c3fc73b775d7 100644
--- a/telephony/java/android/telephony/CellIdentityLte.java
+++ b/telephony/java/android/telephony/CellIdentityLte.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.os.Build;
@@ -232,6 +233,7 @@ public final class CellIdentityLte extends CellIdentity {
*
* @hide
*/
+ @NonNull
@Override
public GsmCellLocation asCellLocation() {
GsmCellLocation cl = new GsmCellLocation();
diff --git a/telephony/java/android/telephony/CellIdentityNr.java b/telephony/java/android/telephony/CellIdentityNr.java
index edc838c163db..e3fec7b7f820 100644
--- a/telephony/java/android/telephony/CellIdentityNr.java
+++ b/telephony/java/android/telephony/CellIdentityNr.java
@@ -17,6 +17,7 @@
package android.telephony;
import android.annotation.IntRange;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
import android.telephony.gsm.GsmCellLocation;
@@ -77,6 +78,7 @@ public final class CellIdentityNr extends CellIdentity {
* @return a CellLocation object for this CellIdentity.
* @hide
*/
+ @NonNull
@Override
public CellLocation asCellLocation() {
return new GsmCellLocation();
diff --git a/telephony/java/android/telephony/CellIdentityTdscdma.java b/telephony/java/android/telephony/CellIdentityTdscdma.java
index 558e346284ea..8f812b6b892e 100644
--- a/telephony/java/android/telephony/CellIdentityTdscdma.java
+++ b/telephony/java/android/telephony/CellIdentityTdscdma.java
@@ -171,6 +171,7 @@ public final class CellIdentityTdscdma extends CellIdentity {
}
/** @hide */
+ @NonNull
@Override
public GsmCellLocation asCellLocation() {
GsmCellLocation cl = new GsmCellLocation();
diff --git a/telephony/java/android/telephony/CellIdentityWcdma.java b/telephony/java/android/telephony/CellIdentityWcdma.java
index 031fed13d9f1..556bc32e7c36 100644
--- a/telephony/java/android/telephony/CellIdentityWcdma.java
+++ b/telephony/java/android/telephony/CellIdentityWcdma.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
@@ -196,6 +197,7 @@ public final class CellIdentityWcdma extends CellIdentity {
}
/** @hide */
+ @NonNull
@Override
public GsmCellLocation asCellLocation() {
GsmCellLocation cl = new GsmCellLocation();
diff --git a/telephony/java/android/telephony/CellSignalStrengthLte.java b/telephony/java/android/telephony/CellSignalStrengthLte.java
index 8336d1b24ddd..8df9d23598eb 100644
--- a/telephony/java/android/telephony/CellSignalStrengthLte.java
+++ b/telephony/java/android/telephony/CellSignalStrengthLte.java
@@ -55,6 +55,25 @@ public final class CellSignalStrengthLte extends CellSignalStrength implements P
private static final int MAX_LTE_RSRP = -44;
private static final int MIN_LTE_RSRP = -140;
+ /**
+ * Indicates RSRP is considered for {@link #getLevel()} and reported from modem.
+ *
+ * @hide
+ */
+ public static final int USE_RSRP = 1 << 0;
+ /**
+ * Indicates RSRQ is considered for {@link #getLevel()} and reported from modem.
+ *
+ * @hide
+ */
+ public static final int USE_RSRQ = 1 << 1;
+ /**
+ * Indicates RSSNR is considered for {@link #getLevel()} and reported from modem.
+ *
+ * @hide
+ */
+ public static final int USE_RSSNR = 1 << 2;
+
@UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.P)
private int mSignalStrength; // To be removed
private int mRssi;
@@ -70,6 +89,21 @@ public final class CellSignalStrengthLte extends CellSignalStrength implements P
private int mTimingAdvance;
private int mLevel;
+ /**
+ * Bit-field integer to determine whether to use Reference Signal Received Power (RSRP),
+ * Reference Signal Received Quality (RSRQ), and/or Reference Signal Signal to Noise Ratio
+ * (RSSNR) for the number of LTE signal bars. If multiple measures are set, the parameter
+ * whose signal level value is smallest is used to indicate the signal level.
+ *
+ * RSRP = 1 << 0,
+ * RSRQ = 1 << 1,
+ * RSSNR = 1 << 2,
+ *
+ * For example, if both RSRP and RSRQ are used, the value of key is 3 (1 << 0 | 1 << 1).
+ * If the key is invalid or not configured, a default value (RSRP = 1 << 0) will apply.
+ */
+ private int mParametersUseForLevel;
+
/** @hide */
@UnsupportedAppUsage
public CellSignalStrengthLte() {
@@ -81,7 +115,7 @@ public final class CellSignalStrengthLte extends CellSignalStrength implements P
*
* @param rssi in dBm [-113,-51], UNKNOWN
* @param rsrp in dBm [-140,-43], UNKNOWN
- * @param rsrq in dB [-20,-3], UNKNOWN
+ * @param rsrq in dB [-34, 3], UNKNOWN
* @param rssnr in 10*dB [-200, +300], UNKNOWN
* @param cqi [0, 15], UNKNOWN
* @param timingAdvance [0, 1282], UNKNOWN
@@ -94,7 +128,7 @@ public final class CellSignalStrengthLte extends CellSignalStrength implements P
mRssi = inRangeOrUnavailable(rssi, -113, -51);
mSignalStrength = mRssi;
mRsrp = inRangeOrUnavailable(rsrp, -140, -43);
- mRsrq = inRangeOrUnavailable(rsrq, -20, -3);
+ mRsrq = inRangeOrUnavailable(rsrq, -34, 3);
mRssnr = inRangeOrUnavailable(rssnr, -200, 300);
mCqi = inRangeOrUnavailable(cqi, 0, 15);
mTimingAdvance = inRangeOrUnavailable(timingAdvance, 0, 1282);
@@ -125,6 +159,7 @@ public final class CellSignalStrengthLte extends CellSignalStrength implements P
mCqi = s.mCqi;
mTimingAdvance = s.mTimingAdvance;
mLevel = s.mLevel;
+ mParametersUseForLevel = s.mParametersUseForLevel;
}
/** @hide */
@@ -144,6 +179,7 @@ public final class CellSignalStrengthLte extends CellSignalStrength implements P
mCqi = CellInfo.UNAVAILABLE;
mTimingAdvance = CellInfo.UNAVAILABLE;
mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+ mParametersUseForLevel = USE_RSRP | USE_RSSNR;
}
/** {@inheritDoc} */
@@ -154,102 +190,153 @@ public final class CellSignalStrengthLte extends CellSignalStrength implements P
}
// Lifted from Default carrier configs and max range of RSRP
- private static final int[] sThresholds = new int[]{-115, -105, -95, -85};
+ private static final int[] sRsrpThresholds = new int[] {
+ -115, /* SIGNAL_STRENGTH_POOR */
+ -105, /* SIGNAL_STRENGTH_MODERATE */
+ -95, /* SIGNAL_STRENGTH_GOOD */
+ -85 /* SIGNAL_STRENGTH_GREAT */
+ };
+
+ // Lifted from Default carrier configs and max range of RSRQ
+ private static final int[] sRsrqThresholds = new int[] {
+ -19, /* SIGNAL_STRENGTH_POOR */
+ -17, /* SIGNAL_STRENGTH_MODERATE */
+ -14, /* SIGNAL_STRENGTH_GOOD */
+ -12 /* SIGNAL_STRENGTH_GREAT */
+ };
+ // Lifted from Default carrier configs and max range of RSSNR
+ private static final int[] sRssnrThresholds = new int[] {
+ -30, /* SIGNAL_STRENGTH_POOR */
+ 10, /* SIGNAL_STRENGTH_MODERATE */
+ 45, /* SIGNAL_STRENGTH_GOOD */
+ 130 /* SIGNAL_STRENGTH_GREAT */
+ };
private static final int sRsrpBoost = 0;
+ /**
+ * Checks if the given parameter type is considered to use for {@link #getLevel()}.
+ *
+ * Note: if multiple parameter types are considered, the smaller level for one of the
+ * parameters would be returned by {@link #getLevel()}
+ *
+ * @param parameterType bitwise OR of {@link #USE_RSRP}, {@link #USE_RSRQ},
+ * {@link #USE_RSSNR}
+ * @return {@code true} if the level is calculated based on the given parameter type;
+ * {@code false} otherwise.
+ */
+ private boolean isLevelForParameter(int parameterType) {
+ return (parameterType & mParametersUseForLevel) == parameterType;
+ }
+
/** @hide */
@Override
public void updateLevel(PersistableBundle cc, ServiceState ss) {
- int[] thresholds;
+ int[] rsrpThresholds, rsrqThresholds, rssnrThresholds;
boolean rsrpOnly;
if (cc == null) {
- thresholds = sThresholds;
+ mParametersUseForLevel = USE_RSRP | USE_RSSNR;
+ rsrpThresholds = sRsrpThresholds;
+ rsrqThresholds = sRsrqThresholds;
+ rssnrThresholds = sRssnrThresholds;
rsrpOnly = false;
} else {
+ mParametersUseForLevel = cc.getInt(
+ CarrierConfigManager.KEY_PARAMETERS_USED_FOR_LTE_SIGNAL_BAR_INT);
+ Rlog.i(LOG_TAG, "Using signal strength level: " + mParametersUseForLevel);
+ rsrpThresholds = cc.getIntArray(
+ CarrierConfigManager.KEY_LTE_RSRP_THRESHOLDS_INT_ARRAY);
+ if (rsrpThresholds == null) rsrpThresholds = sRsrpThresholds;
+ Rlog.i(LOG_TAG, "Applying LTE RSRP Thresholds: " + Arrays.toString(rsrpThresholds));
+ rsrqThresholds = cc.getIntArray(
+ CarrierConfigManager.KEY_LTE_RSRQ_THRESHOLDS_INT_ARRAY);
+ if (rsrqThresholds == null) rsrqThresholds = sRsrqThresholds;
+ Rlog.i(LOG_TAG, "Applying LTE RSRQ Thresholds: " + Arrays.toString(rsrqThresholds));
+ rssnrThresholds = cc.getIntArray(
+ CarrierConfigManager.KEY_LTE_RSSNR_THRESHOLDS_INT_ARRAY);
+ if (rssnrThresholds == null) rssnrThresholds = sRssnrThresholds;
+ Rlog.i(LOG_TAG, "Applying LTE RSSNR Thresholds: " + Arrays.toString(rssnrThresholds));
rsrpOnly = cc.getBoolean(
CarrierConfigManager.KEY_USE_ONLY_RSRP_FOR_LTE_SIGNAL_BAR_BOOL, false);
- thresholds = cc.getIntArray(
- CarrierConfigManager.KEY_LTE_RSRP_THRESHOLDS_INT_ARRAY);
- if (thresholds == null) thresholds = sThresholds;
- if (DBG) log("updateLevel() carrierconfig - rsrpOnly="
- + rsrpOnly + ", thresholds=" + Arrays.toString(thresholds));
}
-
int rsrpBoost = 0;
if (ss != null) {
rsrpBoost = ss.getLteEarfcnRsrpBoost();
}
- int rssiIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
- int rsrpIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
- int snrIconLevel = -1;
-
- int rsrp = mRsrp + rsrpBoost;
-
- if (rsrp < MIN_LTE_RSRP || rsrp > MAX_LTE_RSRP) {
- rsrpIconLevel = -1;
- } else {
- rsrpIconLevel = thresholds.length;
- while (rsrpIconLevel > 0 && rsrp < thresholds[rsrpIconLevel - 1]) rsrpIconLevel--;
- }
+ int rsrp = inRangeOrUnavailable(mRsrp + rsrpBoost, MIN_LTE_RSRP, MAX_LTE_RSRP);
if (rsrpOnly) {
- if (DBG) log("updateLevel() - rsrp = " + rsrpIconLevel);
- if (rsrpIconLevel != -1) {
- mLevel = rsrpIconLevel;
+ int level = updateLevelWithMeasure(rsrp, rsrpThresholds);
+ if (DBG) log("updateLevel() - rsrp = " + level);
+ if (level != SignalStrength.INVALID) {
+ mLevel = level;
return;
}
}
- /*
- * Values are -200 dB to +300 (SNR*10dB) RS_SNR >= 13.0 dB =>4 bars 4.5
- * dB <= RS_SNR < 13.0 dB => 3 bars 1.0 dB <= RS_SNR < 4.5 dB => 2 bars
- * -3.0 dB <= RS_SNR < 1.0 dB 1 bar RS_SNR < -3.0 dB/No Service Antenna
- * Icon Only
- */
- if (mRssnr > 300) snrIconLevel = -1;
- else if (mRssnr >= 130) snrIconLevel = SIGNAL_STRENGTH_GREAT;
- else if (mRssnr >= 45) snrIconLevel = SIGNAL_STRENGTH_GOOD;
- else if (mRssnr >= 10) snrIconLevel = SIGNAL_STRENGTH_MODERATE;
- else if (mRssnr >= -30) snrIconLevel = SIGNAL_STRENGTH_POOR;
- else if (mRssnr >= -200)
- snrIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
-
- if (DBG) log("updateLevel() - rsrp:" + mRsrp + " snr:" + mRssnr + " rsrpIconLevel:"
- + rsrpIconLevel + " snrIconLevel:" + snrIconLevel
- + " lteRsrpBoost:" + sRsrpBoost);
-
- /* Choose a measurement type to use for notification */
- if (snrIconLevel != -1 && rsrpIconLevel != -1) {
- /*
- * The number of bars displayed shall be the smaller of the bars
- * associated with LTE RSRP and the bars associated with the LTE
- * RS_SNR
- */
- mLevel = (rsrpIconLevel < snrIconLevel ? rsrpIconLevel : snrIconLevel);
- return;
- }
+ int rsrpLevel = SignalStrength.INVALID;
+ int rsrqLevel = SignalStrength.INVALID;
+ int rssnrLevel = SignalStrength.INVALID;
- if (snrIconLevel != -1) {
- mLevel = snrIconLevel;
- return;
+ if (isLevelForParameter(USE_RSRP)) {
+ rsrpLevel = updateLevelWithMeasure(rsrp, rsrpThresholds);
+ Rlog.i(LOG_TAG, "Updated 4G LTE RSRP Level: " + rsrpLevel);
}
-
- if (rsrpIconLevel != -1) {
- mLevel = rsrpIconLevel;
- return;
+ if (isLevelForParameter(USE_RSRQ)) {
+ rsrqLevel = updateLevelWithMeasure(mRsrq, rsrqThresholds);
+ Rlog.i(LOG_TAG, "Updated 4G LTE RSRQ Level: " + rsrqLevel);
+ }
+ if (isLevelForParameter(USE_RSSNR)) {
+ rssnrLevel = updateLevelWithMeasure(mRssnr, rssnrThresholds);
+ Rlog.i(LOG_TAG, "Updated 4G LTE RSSNR Level: " + rssnrLevel);
}
+ // Apply the smaller value among three levels of three measures.
+ mLevel = Math.min(Math.min(rsrpLevel, rsrqLevel), rssnrLevel);
+
+ if (mLevel == SignalStrength.INVALID) {
+ int rssiLevel;
+ if (mRssi > -51) {
+ rssiLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+ } else if (mRssi >= -89) {
+ rssiLevel = SIGNAL_STRENGTH_GREAT;
+ } else if (mRssi >= -97) {
+ rssiLevel = SIGNAL_STRENGTH_GOOD;
+ } else if (mRssi >= -103) {
+ rssiLevel = SIGNAL_STRENGTH_MODERATE;
+ } else if (mRssi >= -113) {
+ rssiLevel = SIGNAL_STRENGTH_POOR;
+ } else {
+ rssiLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+ }
+ if (DBG) log("getLteLevel - rssi:" + mRssi + " rssiIconLevel:" + rssiLevel);
+ mLevel = rssiLevel;
+ }
+ }
- if (mRssi > -51) rssiIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
- else if (mRssi >= -89) rssiIconLevel = SIGNAL_STRENGTH_GREAT;
- else if (mRssi >= -97) rssiIconLevel = SIGNAL_STRENGTH_GOOD;
- else if (mRssi >= -103) rssiIconLevel = SIGNAL_STRENGTH_MODERATE;
- else if (mRssi >= -113) rssiIconLevel = SIGNAL_STRENGTH_POOR;
- else rssiIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
- if (DBG) log("getLteLevel - rssi:" + mRssi + " rssiIconLevel:"
- + rssiIconLevel);
- mLevel = rssiIconLevel;
+ /**
+ * Update level with corresponding measure and thresholds.
+ *
+ * @param measure corresponding signal measure
+ * @param thresholds corresponding signal thresholds
+ * @return level of the signal strength
+ */
+ private int updateLevelWithMeasure(int measure, int[] thresholds) {
+ int level;
+ if (measure == CellInfo.UNAVAILABLE) {
+ level = SignalStrength.INVALID;
+ } else if (measure >= thresholds[3]) {
+ level = SIGNAL_STRENGTH_GREAT;
+ } else if (measure >= thresholds[2]) {
+ level = SIGNAL_STRENGTH_GOOD;
+ } else if (measure >= thresholds[1]) {
+ level = SIGNAL_STRENGTH_MODERATE;
+ } else if (measure >= thresholds[0]) {
+ level = SIGNAL_STRENGTH_POOR;
+ } else {
+ level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+ }
+ return level;
}
/**
@@ -386,7 +473,8 @@ public final class CellSignalStrengthLte extends CellSignalStrength implements P
+ " rssnr=" + mRssnr
+ " cqi=" + mCqi
+ " ta=" + mTimingAdvance
- + " level=" + mLevel;
+ + " level=" + mLevel
+ + " parametersUseForLevel=" + mParametersUseForLevel;
}
/** Implement the Parcelable interface */
diff --git a/telephony/java/android/telephony/PreciseCallState.java b/telephony/java/android/telephony/PreciseCallState.java
index 9f75332c4a03..bfa6326c3c18 100644
--- a/telephony/java/android/telephony/PreciseCallState.java
+++ b/telephony/java/android/telephony/PreciseCallState.java
@@ -16,19 +16,18 @@
package android.telephony;
-import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
+import android.telephony.Annotation.DisconnectCauses;
import android.telephony.Annotation.PreciseCallStates;
+import android.telephony.Annotation.PreciseDisconnectCauses;
import android.telephony.DisconnectCause;
import android.telephony.PreciseDisconnectCause;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
/**
@@ -73,19 +72,26 @@ public final class PreciseCallState implements Parcelable {
private @PreciseCallStates int mRingingCallState = PRECISE_CALL_STATE_NOT_VALID;
private @PreciseCallStates int mForegroundCallState = PRECISE_CALL_STATE_NOT_VALID;
private @PreciseCallStates int mBackgroundCallState = PRECISE_CALL_STATE_NOT_VALID;
- private int mDisconnectCause = DisconnectCause.NOT_VALID;
- private int mPreciseDisconnectCause = PreciseDisconnectCause.NOT_VALID;
+ private @DisconnectCauses int mDisconnectCause = DisconnectCause.NOT_VALID;
+ private @PreciseDisconnectCauses int mPreciseDisconnectCause = PreciseDisconnectCause.NOT_VALID;
/**
- * Constructor
+ * Construct PreciseCallState with parameters
+ *
+ * @param ringingCall ring call state
+ * @param foregroundCall foreground call state
+ * @param backgroundCall background call state
+ * @param disconnectCause disconnect cause
+ * @param preciseDisconnectCause precise disconnect cause
*
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public PreciseCallState(@PreciseCallStates int ringingCall,
@PreciseCallStates int foregroundCall,
- @PreciseCallStates int backgroundCall, int disconnectCause,
- int preciseDisconnectCause) {
+ @PreciseCallStates int backgroundCall,
+ @DisconnectCauses int disconnectCause,
+ @PreciseDisconnectCauses int preciseDisconnectCause) {
mRingingCallState = ringingCall;
mForegroundCallState = foregroundCall;
mBackgroundCallState = backgroundCall;
diff --git a/telephony/java/android/telephony/PreciseDataConnectionState.java b/telephony/java/android/telephony/PreciseDataConnectionState.java
index 78ad5c58423c..0610796a0ced 100644
--- a/telephony/java/android/telephony/PreciseDataConnectionState.java
+++ b/telephony/java/android/telephony/PreciseDataConnectionState.java
@@ -81,18 +81,20 @@ public final class PreciseDataConnectionState implements Parcelable {
/**
- * Constructor
+ * Constructor of PreciseDataConnectionState
*
* @param state the state of the data connection
* @param networkType the access network that is/would carry this data connection
* @param apnTypes the APN types that this data connection carries
- * @param apnSetting if there is a valid APN for this Data Connection, then the APN Settings;
- * if there is no valid APN setting for the specific type, then this will be null
+ * @param apn the APN of this data connection
* @param linkProperties if the data connection is connected, the properties of the connection
* @param failCause in case a procedure related to this data connection fails, a non-zero error
* code indicating the cause of the failure.
+ * @param apnSetting if there is a valid APN for this Data Connection, then the APN Settings;
+ * if there is no valid APN setting for the specific type, then this will be null
* @hide
*/
+ @SystemApi
public PreciseDataConnectionState(@DataState int state,
@NetworkType int networkType,
@ApnType int apnTypes, @NonNull String apn,
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index d7d85c280e19..0a6183c13950 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -30,7 +30,6 @@ import android.os.Parcelable;
import android.telephony.AccessNetworkConstants.AccessNetworkType;
import android.telephony.AccessNetworkConstants.TransportType;
import android.telephony.Annotation.NetworkType;
-import android.telephony.Annotation.RilRadioTechnology;
import android.telephony.NetworkRegistrationInfo.Domain;
import android.telephony.NetworkRegistrationInfo.NRState;
import android.text.TextUtils;
@@ -65,6 +64,13 @@ public class ServiceState implements Parcelable {
static final boolean DBG = false;
static final boolean VDBG = false; // STOPSHIP if true
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = "STATE_",
+ value = {STATE_IN_SERVICE, STATE_OUT_OF_SERVICE, STATE_EMERGENCY_ONLY,
+ STATE_POWER_OFF})
+ public @interface RegState {}
+
/**
* Normal operation condition, the phone is registered
* with an operator either in home network or in roaming.
@@ -83,6 +89,7 @@ public class ServiceState implements Parcelable {
/**
* The phone is registered and locked. Only emergency numbers are allowed. {@more}
*/
+ //TODO: This state is not used anymore. It should be deprecated in a future release.
public static final int STATE_EMERGENCY_ONLY =
TelephonyProtoEnums.SERVICE_STATE_EMERGENCY_ONLY; // 2
@@ -221,6 +228,36 @@ public class ServiceState implements Parcelable {
public static final int RIL_RADIO_TECHNOLOGY_NR = 20;
/**
+ * RIL Radio Annotation
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"RIL_RADIO_TECHNOLOGY_" }, value = {
+ ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN,
+ ServiceState.RIL_RADIO_TECHNOLOGY_GPRS,
+ ServiceState.RIL_RADIO_TECHNOLOGY_EDGE,
+ ServiceState.RIL_RADIO_TECHNOLOGY_UMTS,
+ ServiceState.RIL_RADIO_TECHNOLOGY_IS95A,
+ ServiceState.RIL_RADIO_TECHNOLOGY_IS95B,
+ ServiceState.RIL_RADIO_TECHNOLOGY_1xRTT,
+ ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_0,
+ ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_A,
+ ServiceState.RIL_RADIO_TECHNOLOGY_HSDPA,
+ ServiceState.RIL_RADIO_TECHNOLOGY_HSUPA,
+ ServiceState.RIL_RADIO_TECHNOLOGY_HSPA,
+ ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_B,
+ ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD,
+ ServiceState.RIL_RADIO_TECHNOLOGY_LTE,
+ ServiceState.RIL_RADIO_TECHNOLOGY_HSPAP,
+ ServiceState.RIL_RADIO_TECHNOLOGY_GSM,
+ ServiceState.RIL_RADIO_TECHNOLOGY_TD_SCDMA,
+ ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN,
+ ServiceState.RIL_RADIO_TECHNOLOGY_LTE_CA,
+ ServiceState.RIL_RADIO_TECHNOLOGY_NR})
+ public @interface RilRadioTechnology {}
+
+
+ /**
* The number of the radio technologies.
*/
private static final int NEXT_RIL_RADIO_TECHNOLOGY = 21;
@@ -501,13 +538,15 @@ public class ServiceState implements Parcelable {
}
/**
- * Get current data service state
+ * Get current data registration state.
*
* @see #STATE_IN_SERVICE
* @see #STATE_OUT_OF_SERVICE
* @see #STATE_EMERGENCY_ONLY
* @see #STATE_POWER_OFF
*
+ * @return current data registration state {@link RegState}
+ *
* @hide
*/
@UnsupportedAppUsage
@@ -516,6 +555,23 @@ public class ServiceState implements Parcelable {
}
/**
+ * Get current data registration state.
+ *
+ * @see #STATE_IN_SERVICE
+ * @see #STATE_OUT_OF_SERVICE
+ * @see #STATE_EMERGENCY_ONLY
+ * @see #STATE_POWER_OFF
+ *
+ * @return current data registration state {@link RegState}
+ *
+ * @hide
+ */
+ @SystemApi
+ public @RegState int getDataRegistrationState() {
+ return getDataRegState();
+ }
+
+ /**
* Get the current duplex mode
*
* @see #DUPLEX_MODE_UNKNOWN
@@ -1408,7 +1464,15 @@ public class ServiceState implements Parcelable {
return getRilDataRadioTechnology();
}
- /** @hide */
+ /**
+ * Transform RIL radio technology {@link RilRadioTechnology} value to Network
+ * type {@link NetworkType}.
+ *
+ * @param rat The RIL radio technology {@link RilRadioTechnology}.
+ * @return The network type {@link NetworkType}.
+ *
+ * @hide
+ */
public static int rilRadioTechnologyToNetworkType(@RilRadioTechnology int rat) {
switch(rat) {
case RIL_RADIO_TECHNOLOGY_GPRS:
@@ -1490,7 +1554,15 @@ public class ServiceState implements Parcelable {
}
}
- /** @hide */
+ /**
+ * Transform network type {@link NetworkType} value to RIL radio technology
+ * {@link RilRadioTechnology}.
+ *
+ * @param networkType The network type {@link NetworkType}.
+ * @return The RIL radio technology {@link RilRadioTechnology}.
+ *
+ * @hide
+ */
public static int networkTypeToRilRadioTechnology(int networkType) {
switch(networkType) {
case TelephonyManager.NETWORK_TYPE_GPRS:
@@ -1691,7 +1763,14 @@ public class ServiceState implements Parcelable {
return bearerBitmask;
}
- /** @hide */
+ /**
+ * Convert network type bitmask to bearer bitmask.
+ *
+ * @param networkTypeBitmask The network type bitmask value
+ * @return The bearer bitmask value.
+ *
+ * @hide
+ */
public static int convertNetworkTypeBitmaskToBearerBitmask(int networkTypeBitmask) {
if (networkTypeBitmask == 0) {
return 0;
@@ -1705,7 +1784,14 @@ public class ServiceState implements Parcelable {
return bearerBitmask;
}
- /** @hide */
+ /**
+ * Convert bearer bitmask to network type bitmask.
+ *
+ * @param bearerBitmask The bearer bitmask value.
+ * @return The network type bitmask value.
+ *
+ * @hide
+ */
public static int convertBearerBitmaskToNetworkTypeBitmask(int bearerBitmask) {
if (bearerBitmask == 0) {
return 0;
@@ -1864,9 +1950,18 @@ public class ServiceState implements Parcelable {
* Returns a copy of self with location-identifying information removed.
* Always clears the NetworkRegistrationInfo's CellIdentity fields, but if removeCoarseLocation
* is true, clears other info as well.
+ *
+ * @param removeCoarseLocation Whether to also remove coarse location information.
+ * if false, it only clears fine location information such as
+ * NetworkRegistrationInfo's CellIdentity fields; If true, it will
+ * also remove other location information such as operator's MCC
+ * and MNC.
+ * @return the copied ServiceState with location info sanitized.
* @hide
*/
- public ServiceState sanitizeLocationInfo(boolean removeCoarseLocation) {
+ @SystemApi
+ @NonNull
+ public ServiceState createLocationInfoSanitizedCopy(boolean removeCoarseLocation) {
ServiceState state = new ServiceState(this);
synchronized (state.mNetworkRegistrationInfos) {
List<NetworkRegistrationInfo> networkRegistrationInfos =
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index cab5286f53b7..7215ef8fb4c5 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.Manifest;
import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -1635,14 +1636,16 @@ public final class SmsManager {
* operation is performed on the correct subscription.
* </p>
*
- * @param messageIndex is the record index of the message on ICC
- * @return true for success
+ * @param messageIndex This is the same index used to access a message
+ * from {@link #getMessagesFromIcc()}.
+ * @return true for success, false if the operation fails. Failure can be due to IPC failure,
+ * RIL/modem error which results in SMS failed to be deleted on SIM
*
* {@hide}
*/
- @UnsupportedAppUsage
- public boolean
- deleteMessageFromIcc(int messageIndex) {
+ @SystemApi
+ @RequiresPermission(Manifest.permission.ACCESS_MESSAGES_ON_ICC)
+ public boolean deleteMessageFromIcc(int messageIndex) {
boolean success = false;
try {
@@ -1684,6 +1687,7 @@ public final class SmsManager {
* {@hide}
*/
@UnsupportedAppUsage
+ @RequiresPermission(Manifest.permission.ACCESS_MESSAGES_ON_ICC)
public boolean updateMessageOnIcc(int messageIndex, int newStatus, byte[] pdu) {
boolean success = false;
@@ -1716,8 +1720,22 @@ public final class SmsManager {
* operation is performed on the correct subscription.
* </p>
*
+ * @return <code>List</code> of <code>SmsMessage</code> objects
+ *
+ * {@hide}
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.ACCESS_MESSAGES_ON_ICC)
+ public @NonNull List<SmsMessage> getMessagesFromIcc() {
+ return getAllMessagesFromIcc();
+ }
+
+ /**
* @return <code>ArrayList</code> of <code>SmsMessage</code> objects
*
+ * This is similar to {@link #getMessagesFromIcc} except that it will return ArrayList.
+ * Suggested to use {@link #getMessagesFromIcc} instead.
+ *
* {@hide}
*/
@UnsupportedAppUsage
diff --git a/telephony/java/android/telephony/SmsMessage.java b/telephony/java/android/telephony/SmsMessage.java
index b705d71c61d9..289735883094 100644
--- a/telephony/java/android/telephony/SmsMessage.java
+++ b/telephony/java/android/telephony/SmsMessage.java
@@ -344,10 +344,12 @@ public class SmsMessage {
* @param use7bitOnly if true, characters that are not part of the radio-specific 7-bit encoding
* are counted as single space chars. If false, and if the messageBody contains non-7-bit
* encodable characters, length is calculated using a 16-bit encoding.
- * @return an int[4] with int[0] being the number of SMS's required, int[1] the number of code
+ * @return an int[6] with int[0] being the number of SMS's required, int[1] the number of code
* units used, and int[2] is the number of code units remaining until the next message.
* int[3] is an indicator of the encoding code unit size (see the ENCODING_* definitions in
- * SmsConstants).
+ * SmsConstants). int[4] is the GSM national language table to use, or 0 for the default
+ * 7-bit alphabet. int[5] The GSM national language shift table to use, or 0 for the default
+ * 7-bit extension table.
*/
public static int[] calculateLength(CharSequence msgBody, boolean use7bitOnly) {
return calculateLength(msgBody, use7bitOnly, SmsManager.getDefaultSmsSubscriptionId());
@@ -362,10 +364,12 @@ public class SmsMessage {
* are counted as single space chars. If false, and if the messageBody contains non-7-bit
* encodable characters, length is calculated using a 16-bit encoding.
* @param subId Subscription to take SMS format.
- * @return an int[4] with int[0] being the number of SMS's required, int[1] the number of code
+ * @return an int[6] with int[0] being the number of SMS's required, int[1] the number of code
* units used, and int[2] is the number of code units remaining until the next message.
* int[3] is an indicator of the encoding code unit size (see the ENCODING_* definitions in
- * SmsConstants).
+ * SmsConstants). int[4] is the GSM national language table to use, or 0 for the default
+ * 7-bit alphabet. int[5] The GSM national language shift table to use, or 0 for the default
+ * 7-bit extension table.
* @hide
*/
public static int[] calculateLength(CharSequence msgBody, boolean use7bitOnly, int subId) {
@@ -376,11 +380,13 @@ public class SmsMessage {
msgBody, use7bitOnly, true)
: com.android.internal.telephony.gsm.SmsMessage.calculateLength(
msgBody, use7bitOnly);
- int ret[] = new int[4];
+ int[] ret = new int[6];
ret[0] = ted.msgCount;
ret[1] = ted.codeUnitCount;
ret[2] = ted.codeUnitsRemaining;
ret[3] = ted.codeUnitSize;
+ ret[4] = ted.languageTable;
+ ret[5] = ted.languageShiftTable;
return ret;
}
@@ -1032,10 +1038,10 @@ public class SmsMessage {
}
/**
- * {@hide}
* Returns the recipient address(receiver) of this SMS message in String form or null if
* unavailable.
*/
+ @Nullable
public String getRecipientAddress() {
return mWrappedSmsMessage.getRecipientAddress();
}
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 740622dae1d9..7380b31fbc3c 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -21,6 +21,7 @@ import static android.net.NetworkPolicyManager.OVERRIDE_UNMETERED;
import android.Manifest;
import android.annotation.CallbackExecutor;
+import android.annotation.ColorInt;
import android.annotation.DurationMillisLong;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -912,9 +913,9 @@ public class SubscriptionManager {
* <p>
* Contains {@link #EXTRA_SUBSCRIPTION_INDEX} to indicate which subscription
* changed.
- *
* @hide
*/
+ @SystemApi
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
@RequiresPermission(android.Manifest.permission.MANAGE_SUBSCRIPTION_PLANS)
public static final String ACTION_SUBSCRIPTION_PLANS_CHANGED
@@ -1674,14 +1675,15 @@ public class SubscriptionManager {
}
/**
- * Set SIM icon tint color by simInfo index
+ * Set SIM icon tint color for subscription ID
* @param tint the RGB value of icon tint color of the SIM
- * @param subId the unique SubInfoRecord index in database
+ * @param subId the unique Subscritpion ID in database
* @return the number of records updated
* @hide
*/
- @UnsupportedAppUsage
- public int setIconTint(int tint, int subId) {
+ @SystemApi
+ @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+ public int setIconTint(@ColorInt int tint, int subId) {
if (VDBG) logd("[setIconTint]+ tint:" + tint + " subId:" + subId);
return setSubscriptionPropertyHelper(subId, "setIconTint",
(iSub)-> iSub.setIconTint(tint, subId)
@@ -1689,15 +1691,17 @@ public class SubscriptionManager {
}
/**
- * Set display name by simInfo index with name source
+ * Set the display name for a subscription ID
* @param displayName the display name of SIM card
- * @param subId the unique SubscriptionInfo index in database
+ * @param subId the unique Subscritpion ID in database
* @param nameSource SIM display name source
* @return the number of records updated or < 0 if invalid subId
* @hide
*/
- @UnsupportedAppUsage
- public int setDisplayName(String displayName, int subId, @SimDisplayNameSource int nameSource) {
+ @SystemApi
+ @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+ public int setDisplayName(@Nullable String displayName, int subId,
+ @SimDisplayNameSource int nameSource) {
if (VDBG) {
logd("[setDisplayName]+ displayName:" + displayName + " subId:" + subId
+ " nameSource:" + nameSource);
@@ -2655,8 +2659,7 @@ public class SubscriptionManager {
/**
* Checks whether the app with the given context is authorized to manage the given subscription
- * according to its metadata. Only supported for embedded subscriptions (if
- * {@code SubscriptionInfo#isEmbedded} returns true).
+ * according to its metadata.
*
* @param info The subscription to check.
* @return whether the app is authorized to manage this subscription per its metadata.
@@ -2669,16 +2672,16 @@ public class SubscriptionManager {
* Checks whether the given app is authorized to manage the given subscription. An app can only
* be authorized if it is included in the {@link android.telephony.UiccAccessRule} of the
* {@link android.telephony.SubscriptionInfo} with the access status.
- * Only supported for embedded subscriptions (if {@link SubscriptionInfo#isEmbedded}
- * returns true).
*
* @param info The subscription to check.
* @param packageName Package name of the app to check.
* @return whether the app is authorized to manage this subscription per its access rules.
* @hide
*/
- public boolean canManageSubscription(SubscriptionInfo info, String packageName) {
- if (info == null || info.getAllAccessRules() == null) {
+ @SystemApi
+ public boolean canManageSubscription(@Nullable SubscriptionInfo info,
+ @Nullable String packageName) {
+ if (info == null || info.getAllAccessRules() == null || packageName == null) {
return false;
}
PackageManager packageManager = mContext.getPackageManager();
@@ -3175,6 +3178,34 @@ public class SubscriptionManager {
}
/**
+ * Set uicc applications being enabled or disabled.
+ * The value will be remembered on the subscription and will be applied whenever it's present.
+ * If the subscription in currently present, it will also apply the setting to modem
+ * immediately.
+ *
+ * Permissions android.Manifest.permission.MODIFY_PHONE_STATE is required
+ *
+ * @param enabled whether uicc applications are enabled or disabled.
+ * @param subscriptionId which subscription to operate on.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+ public void setUiccApplicationsEnabled(boolean enabled, int subscriptionId) {
+ if (VDBG) {
+ logd("setUiccApplicationsEnabled subId= " + subscriptionId + " enable " + enabled);
+ }
+ try {
+ ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
+ if (iSub != null) {
+ iSub.setUiccApplicationsEnabled(enabled, subscriptionId);
+ }
+ } catch (RemoteException ex) {
+ // ignore it
+ }
+ }
+
+ /**
* Whether it's supported to disable / re-enable a subscription on a physical (non-euicc) SIM.
*
* Physical SIM refers non-euicc, or aka non-programmable SIM.
diff --git a/telephony/java/android/telephony/TelephonyFrameworkInitializer.java b/telephony/java/android/telephony/TelephonyFrameworkInitializer.java
index 407ad19b4364..0d2a8bc14bcb 100644
--- a/telephony/java/android/telephony/TelephonyFrameworkInitializer.java
+++ b/telephony/java/android/telephony/TelephonyFrameworkInitializer.java
@@ -23,6 +23,7 @@ import android.content.Context;
import android.os.TelephonyServiceManager;
import android.telephony.euicc.EuiccCardManager;
import android.telephony.euicc.EuiccManager;
+import android.telephony.ims.ImsManager;
import com.android.internal.util.Preconditions;
@@ -88,6 +89,11 @@ public class TelephonyFrameworkInitializer {
EuiccCardManager.class,
context -> new EuiccCardManager(context)
);
+ SystemServiceRegistry.registerContextAwareService(
+ Context.TELEPHONY_IMS_SERVICE,
+ ImsManager.class,
+ context -> new ImsManager(context)
+ );
}
/** @hide */
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 78c5e43033bb..deafbb3792d3 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -73,7 +73,9 @@ import android.telephony.Annotation.CallState;
import android.telephony.Annotation.NetworkType;
import android.telephony.Annotation.RadioPowerState;
import android.telephony.Annotation.SimActivationState;
+import android.telephony.Annotation.UiccAppType;
import android.telephony.VisualVoicemailService.VisualVoicemailTask;
+import android.telephony.data.ApnSetting.MvnoType;
import android.telephony.emergency.EmergencyNumber;
import android.telephony.emergency.EmergencyNumber.EmergencyServiceCategories;
import android.telephony.ims.ImsMmTelManager;
@@ -757,8 +759,10 @@ public class TelephonyManager {
* Retrieve with
* {@link android.content.Intent#getIntExtra(String name, int defaultValue)}.
*
+ * @deprecated Should use the {@link TelecomManager#EXTRA_DISCONNECT_CAUSE} instead.
* @hide
*/
+ @Deprecated
public static final String EXTRA_DISCONNECT_CAUSE = "disconnect_cause";
/**
@@ -1461,6 +1465,80 @@ public class TelephonyManager {
*/
public static final String EXTRA_SIM_COMBINATION_NAMES =
"android.telephony.extra.SIM_COMBINATION_NAMES";
+
+ /**
+ * Broadcast Action: The time was set by the carrier (typically by the NITZ string).
+ * This is a sticky broadcast.
+ * The intent will have the following extra values:</p>
+ * <ul>
+ * <li><em>time</em> - The time as a long in UTC milliseconds.</li>
+ * </ul>
+ *
+ * <p class="note">
+ * Requires the READ_PHONE_STATE permission.
+ *
+ * <p class="note">This is a protected intent that can only be sent by the system.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String ACTION_NETWORK_SET_TIME = "android.telephony.action.NETWORK_SET_TIME";
+
+ /**
+ * <p>Broadcast Action: The emergency callback mode is changed.
+ * <ul>
+ * <li><em>phoneinECMState</em> - A boolean value,true=phone in ECM, false=ECM off</li>
+ * </ul>
+ * <p class="note">
+ * You can <em>not</em> receive this through components declared
+ * in manifests, only by explicitly registering for it with
+ * {@link android.content.Context#registerReceiver(android.content.BroadcastReceiver,
+ * android.content.IntentFilter) Context.registerReceiver()}.
+ *
+ * <p class="note">This is a protected intent that can only be sent by the system.
+ *
+ * @hide
+ */
+ @SystemApi
+ @SuppressLint("ActionValue")
+ public static final String ACTION_EMERGENCY_CALLBACK_MODE_CHANGED
+ = "android.intent.action.EMERGENCY_CALLBACK_MODE_CHANGED";
+
+ /**
+ * <p>Broadcast Action: The emergency call state is changed.
+ * <ul>
+ * <li><em>phoneInEmergencyCall</em> - A boolean value, true if phone in emergency call,
+ * false otherwise</li>
+ * </ul>
+ * <p class="note">
+ * You can <em>not</em> receive this through components declared
+ * in manifests, only by explicitly registering for it with
+ * {@link android.content.Context#registerReceiver(android.content.BroadcastReceiver,
+ * android.content.IntentFilter) Context.registerReceiver()}.
+ *
+ * <p class="note">This is a protected intent that can only be sent by the system.
+ *
+ * @hide
+ */
+ @SystemApi
+ @SuppressLint("ActionValue")
+ public static final String ACTION_EMERGENCY_CALL_STATE_CHANGED
+ = "android.intent.action.EMERGENCY_CALL_STATE_CHANGED";
+
+ /**
+ * <p>Broadcast Action: It indicates the Emergency callback mode blocks datacall/sms
+ * <p class="note">.
+ * This is to pop up a notice to show user that the phone is in emergency callback mode
+ * and data calls and outgoing sms are blocked.
+ *
+ * <p class="note">This is a protected intent that can only be sent by the system.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS
+ = "android.telephony.action.SHOW_NOTICE_ECM_BLOCK_OTHERS";
+
//
//
// Device Info
@@ -1874,14 +1952,9 @@ public class TelephonyManager {
return null;
}
- Bundle bundle = telephony.getCellLocation(mContext.getOpPackageName(),
+ CellIdentity cellIdentity = telephony.getCellLocation(mContext.getOpPackageName(),
mContext.getFeatureId());
- if (bundle == null || bundle.isEmpty()) {
- Rlog.d(TAG, "getCellLocation returning null because CellLocation is unavailable");
- return null;
- }
-
- CellLocation cl = CellLocation.newFromBundle(bundle);
+ CellLocation cl = cellIdentity.asCellLocation();
if (cl == null || cl.isEmpty()) {
Rlog.d(TAG, "getCellLocation returning null because CellLocation is empty or"
+ " phone type doesn't match CellLocation type");
@@ -4172,7 +4245,7 @@ public class TelephonyManager {
* The returned set of subscriber IDs will include the subscriber ID corresponding to this
* TelephonyManager's subId.
*
- * This is deprecated and {@link #getMergedSubscriberIdsFromGroup()} should be used for data
+ * This is deprecated and {@link #getMergedImsisFromGroup()} should be used for data
* usage merging purpose.
* TODO: remove this API.
*
@@ -4193,25 +4266,27 @@ public class TelephonyManager {
}
/**
- * Return the set of subscriber IDs that should be considered "merged together" for data usage
- * purposes. Unlike {@link #getMergedSubscriberIds()} this API merge subscriberIds based on
- * subscription grouping: subscriberId of those in the same group will all be returned.
+ * Return the set of IMSIs that should be considered "merged together" for data usage
+ * purposes. Unlike {@link #getMergedSubscriberIds()} this API merge IMSIs based on
+ * subscription grouping: IMSI of those in the same group will all be returned.
+ * Return the current IMSI if there is no subscription group.
*
* <p>Requires the calling app to have READ_PRIVILEGED_PHONE_STATE permission.
*
* @hide
*/
+ @SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- public @Nullable String[] getMergedSubscriberIdsFromGroup() {
+ public @NonNull String[] getMergedImsisFromGroup() {
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.getMergedSubscriberIdsFromGroup(getSubId(), getOpPackageName());
+ return telephony.getMergedImsisFromGroup(getSubId(), getOpPackageName());
}
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
}
- return null;
+ return new String[0];
}
/**
@@ -6351,7 +6426,19 @@ public class TelephonyManager {
* Return an appropriate subscription ID for any situation.
*
* If this object has been created with {@link #createForSubscriptionId}, then the provided
- * subId is returned. Otherwise, the default subId will be returned.
+ * subscription ID is returned. Otherwise, the default subscription ID will be returned.
+ *
+ */
+ public int getSubscriptionId() {
+ return getSubId();
+ }
+
+ /**
+ * Return an appropriate subscription ID for any situation.
+ *
+ * If this object has been created with {@link #createForSubscriptionId}, then the provided
+ * subscription ID is returned. Otherwise, the default subscription ID will be returned.
+ *
*/
private int getSubId() {
if (SubscriptionManager.isUsableSubIdValue(mSubId)) {
@@ -6695,19 +6782,6 @@ public class TelephonyManager {
}
}
- /**
- * UICC SIM Application Types
- * @hide
- */
- @IntDef(prefix = { "APPTYPE_" }, value = {
- APPTYPE_SIM,
- APPTYPE_USIM,
- APPTYPE_RUIM,
- APPTYPE_CSIM,
- APPTYPE_ISIM
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface UiccAppType{}
/** UICC application type is SIM */
public static final int APPTYPE_SIM = PhoneConstants.APPTYPE_SIM;
/** UICC application type is USIM */
@@ -11828,6 +11902,8 @@ public class TelephonyManager {
*
* @hide
*/
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public boolean isApnMetered(@ApnType int apnType) {
try {
ITelephony service = getITelephony();
@@ -11843,6 +11919,37 @@ public class TelephonyManager {
}
/**
+ * Verifies whether the input MCC/MNC and MVNO correspond to the current carrier.
+ *
+ * @param mccmnc the carrier's mccmnc that you want to match
+ * @param mvnoType the mvnoType that defined in {@link ApnSetting}
+ * @param mvnoMatchData the MVNO match data
+ * @return {@code true} if input mccmnc and mvno matches with data from sim operator.
+ * {@code false} otherwise.
+ *
+ * {@hide}
+ */
+ @SystemApi
+ public boolean isCurrentSimOperator(@NonNull String mccmnc, @MvnoType int mvnoType,
+ @Nullable String mvnoMatchData) {
+ try {
+ if (!mccmnc.equals(getSimOperator())) {
+ Log.d(TAG, "The mccmnc does not match");
+ return false;
+ }
+ ITelephony service = getITelephony();
+ if (service != null) {
+ return service.isMvnoMatched(getSubId(), mvnoType, mvnoMatchData);
+ }
+ } catch (RemoteException ex) {
+ if (!isSystemProcess()) {
+ ex.rethrowAsRuntimeException();
+ }
+ }
+ return false;
+ }
+
+ /**
* Set allowing mobile data during voice call.
*
* @param allow {@code true} if allowing using data during voice call, {@code false} if
diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java
index b0ff5dc351e2..87e53919c2a1 100644
--- a/telephony/java/android/telephony/ims/ImsCallProfile.java
+++ b/telephony/java/android/telephony/ims/ImsCallProfile.java
@@ -32,6 +32,7 @@ import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.util.TelephonyUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -833,7 +834,7 @@ public final class ImsCallProfile implements Parcelable {
}
int startSize = extras.size();
- Bundle filtered = extras.filterValues();
+ Bundle filtered = TelephonyUtils.filterValues(extras);
int endSize = filtered.size();
if (startSize != endSize) {
Log.i(TAG, "maybeCleanseExtras: " + (startSize - endSize) + " extra values were "
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index c5d58ac24904..cc02a409c16d 100755
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -300,4 +300,6 @@ interface ISub {
int getActiveDataSubscriptionId();
boolean canDisablePhysicalSubscription();
+
+ int setUiccApplicationsEnabled(boolean enabled, int subscriptionId);
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 97b24aef4af5..57fda9b1e3e4 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -30,6 +30,7 @@ import android.service.carrier.CarrierIdentifier;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telephony.CarrierRestrictionRules;
+import android.telephony.CellIdentity;
import android.telephony.CellInfo;
import android.telephony.ClientRequestStats;
import android.telephony.IccOpenLogicalChannelResponse;
@@ -305,7 +306,8 @@ interface ITelephony {
*/
boolean isDataConnectivityPossible(int subId);
- Bundle getCellLocation(String callingPkg, String callingFeatureId);
+ // Uses CellIdentity which is Parcelable here; will convert to CellLocation in client.
+ CellIdentity getCellLocation(String callingPkg, String callingFeatureId);
/**
* Returns the ISO country code equivalent of the current registered
@@ -1134,7 +1136,7 @@ interface ITelephony {
/**
* @hide
*/
- String[] getMergedSubscriberIdsFromGroup(int subId, String callingPackage);
+ String[] getMergedImsisFromGroup(int subId, String callingPackage);
/**
* Override the operator branding for the current ICCID.
@@ -2122,6 +2124,8 @@ interface ITelephony {
boolean isApnMetered(int apnType, int subId);
+ boolean isMvnoMatched(int subId, int mvnoType, String mvnoMatchData);
+
/**
* Enqueue a pending sms Consumer, which will answer with the user specified selection for an
* outgoing SmsManager operation.
diff --git a/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java b/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java
index dcea9bb72c01..d672642b1158 100644
--- a/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java
+++ b/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java
@@ -18,11 +18,11 @@ package com.android.internal.telephony;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
-import android.os.Build;
import android.telephony.Rlog;
import android.util.SparseIntArray;
import com.android.internal.telephony.cdma.sms.UserData;
+import com.android.internal.telephony.util.TelephonyUtils;
import com.android.internal.telephony.util.XmlUtils;
import dalvik.annotation.compat.UnsupportedAppUsage;
@@ -30,7 +30,7 @@ import dalvik.annotation.compat.UnsupportedAppUsage;
public class Sms7BitEncodingTranslator {
private static final String TAG = "Sms7BitEncodingTranslator";
@UnsupportedAppUsage
- private static final boolean DBG = Build.IS_DEBUGGABLE ;
+ private static final boolean DBG = TelephonyUtils.IS_DEBUGGABLE;
private static boolean mIs7BitTranslationTableLoaded = false;
private static SparseIntArray mTranslationTable = null;
@UnsupportedAppUsage
diff --git a/telephony/java/com/android/internal/telephony/SmsMessageBase.java b/telephony/java/com/android/internal/telephony/SmsMessageBase.java
index a3efb75b2ee8..d6632f35caac 100644
--- a/telephony/java/com/android/internal/telephony/SmsMessageBase.java
+++ b/telephony/java/com/android/internal/telephony/SmsMessageBase.java
@@ -18,19 +18,26 @@ package com.android.internal.telephony;
import android.annotation.UnsupportedAppUsage;
import android.os.Build;
-import android.provider.Telephony;
import android.telephony.SmsMessage;
+import android.text.TextUtils;
+import android.util.Patterns;
import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails;
import java.text.BreakIterator;
import java.util.Arrays;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
/**
* Base class declaring the specific methods and members for SmsMessage.
* {@hide}
*/
public abstract class SmsMessageBase {
+ // Copied from Telephony.Mms.NAME_ADDR_EMAIL_PATTERN
+ public static final Pattern NAME_ADDR_EMAIL_PATTERN =
+ Pattern.compile("\\s*(\"[^\"]*\"|[^<>\"]+)\\s*<([^<>]+)>\\s*");
+
/** {@hide} The address of the SMSC. May be null */
@UnsupportedAppUsage
protected String mScAddress;
@@ -355,6 +362,31 @@ public abstract class SmsMessageBase {
}
}
+ private static String extractAddrSpec(String messageHeader) {
+ Matcher match = NAME_ADDR_EMAIL_PATTERN.matcher(messageHeader);
+
+ if (match.matches()) {
+ return match.group(2);
+ }
+ return messageHeader;
+ }
+
+ /**
+ * Returns true if the message header string indicates that the message is from a email address.
+ *
+ * @param messageHeader message header
+ * @return {@code true} if it's a message from an email address, {@code false} otherwise.
+ */
+ public static boolean isEmailAddress(String messageHeader) {
+ if (TextUtils.isEmpty(messageHeader)) {
+ return false;
+ }
+
+ String s = extractAddrSpec(messageHeader);
+ Matcher match = Patterns.EMAIL_ADDRESS.matcher(s);
+ return match.matches();
+ }
+
/**
* Try to parse this message as an email gateway message
* There are two ways specified in TS 23.040 Section 3.8 :
@@ -375,11 +407,11 @@ public abstract class SmsMessageBase {
* -or-
* 2. [x@y][ ]/[body]
*/
- String[] parts = mMessageBody.split("( /)|( )", 2);
- if (parts.length < 2) return;
- mEmailFrom = parts[0];
- mEmailBody = parts[1];
- mIsEmail = Telephony.Mms.isEmailAddress(mEmailFrom);
+ String[] parts = mMessageBody.split("( /)|( )", 2);
+ if (parts.length < 2) return;
+ mEmailFrom = parts[0];
+ mEmailBody = parts[1];
+ mIsEmail = isEmailAddress(mEmailFrom);
}
/**
diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
index b2c3fc79025b..08c536bf44b9 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
@@ -18,6 +18,7 @@ package com.android.internal.telephony;
import android.content.Intent;
import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
/**
* The intents that the telephony services broadcast.
@@ -99,7 +100,7 @@ public class TelephonyIntents {
* by the system.
*/
public static final String ACTION_EMERGENCY_CALLBACK_MODE_CHANGED
- = "android.intent.action.EMERGENCY_CALLBACK_MODE_CHANGED";
+ = TelephonyManager.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED;
/**
* <p>Broadcast Action: The emergency call state is changed.
@@ -120,7 +121,7 @@ public class TelephonyIntents {
* by the system.
*/
public static final String ACTION_EMERGENCY_CALL_STATE_CHANGED
- = "android.intent.action.EMERGENCY_CALL_STATE_CHANGED";
+ = TelephonyManager.ACTION_EMERGENCY_CALL_STATE_CHANGED;
/**
* Broadcast Action: The phone's signal strength has changed. The intent will have the
@@ -172,24 +173,6 @@ public class TelephonyIntents {
= "android.intent.action.ANY_DATA_STATE";
/**
- * Broadcast Action: An attempt to establish a data connection has failed.
- * The intent will have the following extra values:</p>
- * <dl>
- * <dt>phoneName</dt><dd>A string version of the phone name.</dd>
- * <dt>state</dt><dd>One of {@code CONNECTED}, {@code CONNECTING}, or {code DISCONNECTED}.</dd>
- * <dt>reason</dt><dd>A string indicating the reason for the failure, if available.</dd>
- * </dl>
- *
- * <p class="note">
- * Requires the READ_PHONE_STATE permission.
- *
- * <p class="note">This is a protected intent that can only be sent
- * by the system.
- */
- public static final String ACTION_DATA_CONNECTION_FAILED
- = "android.intent.action.DATA_CONNECTION_FAILED";
-
- /**
* Broadcast Action: The sim card state has changed.
* The intent will have the following extra values:</p>
* <dl>
@@ -225,22 +208,6 @@ public class TelephonyIntents {
public static final String EXTRA_REBROADCAST_ON_UNLOCK= "rebroadcastOnUnlock";
/**
- * Broadcast Action: The time was set by the carrier (typically by the NITZ string).
- * This is a sticky broadcast.
- * The intent will have the following extra values:</p>
- * <ul>
- * <li><em>time</em> - The time as a long in UTC milliseconds.</li>
- * </ul>
- *
- * <p class="note">
- * Requires the READ_PHONE_STATE permission.
- *
- * <p class="note">This is a protected intent that can only be sent
- * by the system.
- */
- public static final String ACTION_NETWORK_SET_TIME = "android.intent.action.NETWORK_SET_TIME";
-
- /**
* <p>Broadcast Action: It indicates the Emergency callback mode blocks datacall/sms
* <p class="note">.
* This is to pop up a notice to show user that the phone is in emergency callback mode
@@ -250,7 +217,7 @@ public class TelephonyIntents {
* by the system.
*/
public static final String ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS
- = "com.android.internal.intent.action.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS";
+ = TelephonyManager.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS;
/**
* <p>Broadcast Action: Indicates that the action is forbidden by network.
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java b/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java
deleted file mode 100644
index c16eafb41dde..000000000000
--- a/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java
+++ /dev/null
@@ -1,521 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.telephony.gsm;
-
-import static android.telephony.SmsCbEtwsInfo.ETWS_WARNING_TYPE_EARTHQUAKE;
-import static android.telephony.SmsCbEtwsInfo.ETWS_WARNING_TYPE_EARTHQUAKE_AND_TSUNAMI;
-import static android.telephony.SmsCbEtwsInfo.ETWS_WARNING_TYPE_OTHER_EMERGENCY;
-import static android.telephony.SmsCbEtwsInfo.ETWS_WARNING_TYPE_TEST_MESSAGE;
-import static android.telephony.SmsCbEtwsInfo.ETWS_WARNING_TYPE_TSUNAMI;
-
-import android.annotation.NonNull;
-import android.content.Context;
-import android.content.res.Resources;
-import android.telephony.CbGeoUtils;
-import android.telephony.CbGeoUtils.Circle;
-import android.telephony.CbGeoUtils.Geometry;
-import android.telephony.CbGeoUtils.LatLng;
-import android.telephony.CbGeoUtils.Polygon;
-import android.telephony.Rlog;
-import android.telephony.SmsCbLocation;
-import android.telephony.SmsCbMessage;
-import android.telephony.SubscriptionManager;
-import android.util.Pair;
-
-import com.android.internal.R;
-import com.android.internal.telephony.GsmAlphabet;
-import com.android.internal.telephony.SmsConstants;
-import com.android.internal.telephony.gsm.GsmSmsCbMessage.GeoFencingTriggerMessage.CellBroadcastIdentity;
-import com.android.internal.telephony.gsm.SmsCbHeader.DataCodingScheme;
-
-import java.io.UnsupportedEncodingException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.Collectors;
-
-/**
- * Parses a GSM or UMTS format SMS-CB message into an {@link SmsCbMessage} object. The class is
- * public because {@link #createSmsCbMessage(SmsCbLocation, byte[][])} is used by some test cases.
- */
-public class GsmSmsCbMessage {
- private static final String TAG = GsmSmsCbMessage.class.getSimpleName();
-
- private static final char CARRIAGE_RETURN = 0x0d;
-
- private static final int PDU_BODY_PAGE_LENGTH = 82;
-
- /** Utility class with only static methods. */
- private GsmSmsCbMessage() { }
-
- /**
- * Get built-in ETWS primary messages by category. ETWS primary message does not contain text,
- * so we have to show the pre-built messages to the user.
- *
- * @param context Device context
- * @param category ETWS message category defined in SmsCbConstants
- * @return ETWS text message in string. Return an empty string if no match.
- */
- private static String getEtwsPrimaryMessage(Context context, int category) {
- final Resources r = context.getResources();
- switch (category) {
- case ETWS_WARNING_TYPE_EARTHQUAKE:
- return r.getString(R.string.etws_primary_default_message_earthquake);
- case ETWS_WARNING_TYPE_TSUNAMI:
- return r.getString(R.string.etws_primary_default_message_tsunami);
- case ETWS_WARNING_TYPE_EARTHQUAKE_AND_TSUNAMI:
- return r.getString(R.string.etws_primary_default_message_earthquake_and_tsunami);
- case ETWS_WARNING_TYPE_TEST_MESSAGE:
- return r.getString(R.string.etws_primary_default_message_test);
- case ETWS_WARNING_TYPE_OTHER_EMERGENCY:
- return r.getString(R.string.etws_primary_default_message_others);
- default:
- return "";
- }
- }
-
- /**
- * Create a new SmsCbMessage object from a header object plus one or more received PDUs.
- *
- * @param pdus PDU bytes
- * @slotIndex slotIndex for which received sms cb message
- */
- public static SmsCbMessage createSmsCbMessage(Context context, SmsCbHeader header,
- SmsCbLocation location, byte[][] pdus, int slotIndex)
- throws IllegalArgumentException {
- SubscriptionManager sm = (SubscriptionManager) context.getSystemService(
- Context.TELEPHONY_SUBSCRIPTION_SERVICE);
- int subId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
- int[] subIds = sm.getSubscriptionIds(slotIndex);
- if (subIds != null && subIds.length > 0) {
- subId = subIds[0];
- }
-
- long receivedTimeMillis = System.currentTimeMillis();
- if (header.isEtwsPrimaryNotification()) {
- // ETSI TS 23.041 ETWS Primary Notification message
- // ETWS primary message only contains 4 fields including serial number,
- // message identifier, warning type, and warning security information.
- // There is no field for the content/text so we get the text from the resources.
- return new SmsCbMessage(SmsCbMessage.MESSAGE_FORMAT_3GPP, header.getGeographicalScope(),
- header.getSerialNumber(), location, header.getServiceCategory(), null,
- getEtwsPrimaryMessage(context, header.getEtwsInfo().getWarningType()),
- SmsCbMessage.MESSAGE_PRIORITY_EMERGENCY, header.getEtwsInfo(),
- header.getCmasInfo(), 0, null /* geometries */, receivedTimeMillis, slotIndex,
- subId);
- } else if (header.isUmtsFormat()) {
- // UMTS format has only 1 PDU
- byte[] pdu = pdus[0];
- Pair<String, String> cbData = parseUmtsBody(header, pdu);
- String language = cbData.first;
- String body = cbData.second;
- int priority = header.isEmergencyMessage() ? SmsCbMessage.MESSAGE_PRIORITY_EMERGENCY
- : SmsCbMessage.MESSAGE_PRIORITY_NORMAL;
- int nrPages = pdu[SmsCbHeader.PDU_HEADER_LENGTH];
- int wacDataOffset = SmsCbHeader.PDU_HEADER_LENGTH
- + 1 // number of pages
- + (PDU_BODY_PAGE_LENGTH + 1) * nrPages; // cb data
-
- // Has Warning Area Coordinates information
- List<Geometry> geometries = null;
- int maximumWaitingTimeSec = 255;
- if (pdu.length > wacDataOffset) {
- try {
- Pair<Integer, List<Geometry>> wac = parseWarningAreaCoordinates(pdu,
- wacDataOffset);
- maximumWaitingTimeSec = wac.first;
- geometries = wac.second;
- } catch (Exception ex) {
- // Catch the exception here, the message will be considered as having no WAC
- // information which means the message will be broadcasted directly.
- Rlog.e(TAG, "Can't parse warning area coordinates, ex = " + ex.toString());
- }
- }
-
- return new SmsCbMessage(SmsCbMessage.MESSAGE_FORMAT_3GPP,
- header.getGeographicalScope(), header.getSerialNumber(), location,
- header.getServiceCategory(), language, body, priority,
- header.getEtwsInfo(), header.getCmasInfo(), maximumWaitingTimeSec, geometries,
- receivedTimeMillis, slotIndex, subId);
- } else {
- String language = null;
- StringBuilder sb = new StringBuilder();
- for (byte[] pdu : pdus) {
- Pair<String, String> p = parseGsmBody(header, pdu);
- language = p.first;
- sb.append(p.second);
- }
- int priority = header.isEmergencyMessage() ? SmsCbMessage.MESSAGE_PRIORITY_EMERGENCY
- : SmsCbMessage.MESSAGE_PRIORITY_NORMAL;
-
- return new SmsCbMessage(SmsCbMessage.MESSAGE_FORMAT_3GPP,
- header.getGeographicalScope(), header.getSerialNumber(), location,
- header.getServiceCategory(), language, sb.toString(), priority,
- header.getEtwsInfo(), header.getCmasInfo(), 0, null /* geometries */,
- receivedTimeMillis, slotIndex, subId);
- }
- }
-
- /**
- * Parse WEA Handset Action Message(WHAM) a.k.a geo-fencing trigger message.
- *
- * WEA Handset Action Message(WHAM) is a cell broadcast service message broadcast by the network
- * to direct devices to perform a geo-fencing check on selected alerts.
- *
- * WEA Handset Action Message(WHAM) requirements from ATIS-0700041 section 4
- * 1. The Warning Message contents of a WHAM shall be in Cell Broadcast(CB) data format as
- * defined in TS 23.041.
- * 2. The Warning Message Contents of WHAM shall be limited to one CB page(max 20 referenced
- * WEA messages).
- * 3. The broadcast area for a WHAM shall be the union of the broadcast areas of the referenced
- * WEA message.
- * @param pdu cell broadcast pdu, including the header
- * @return {@link GeoFencingTriggerMessage} instance
- */
- public static GeoFencingTriggerMessage createGeoFencingTriggerMessage(byte[] pdu) {
- try {
- // Header length + 1(number of page). ATIS-0700041 define the number of page of
- // geo-fencing trigger message is 1.
- int whamOffset = SmsCbHeader.PDU_HEADER_LENGTH + 1;
-
- BitStreamReader bitReader = new BitStreamReader(pdu, whamOffset);
- int type = bitReader.read(4);
- int length = bitReader.read(7);
- // Skip the remained 5 bits
- bitReader.skip();
-
- int messageIdentifierCount = (length - 2) * 8 / 32;
- List<CellBroadcastIdentity> cbIdentifiers = new ArrayList<>();
- for (int i = 0; i < messageIdentifierCount; i++) {
- // Both messageIdentifier and serialNumber are 16 bits integers.
- // ATIS-0700041 Section 5.1.6
- int messageIdentifier = bitReader.read(16);
- int serialNumber = bitReader.read(16);
- cbIdentifiers.add(new CellBroadcastIdentity(messageIdentifier, serialNumber));
- }
- return new GeoFencingTriggerMessage(type, cbIdentifiers);
- } catch (Exception ex) {
- Rlog.e(TAG, "create geo-fencing trigger failed, ex = " + ex.toString());
- return null;
- }
- }
-
- /**
- * Parse the broadcast area and maximum wait time from the Warning Area Coordinates TLV.
- *
- * @param pdu Warning Area Coordinates TLV.
- * @param wacOffset the offset of Warning Area Coordinates TLV.
- * @return a pair with the first element is maximum wait time and the second is the broadcast
- * area. The default value of the maximum wait time is 255 which means use the device default
- * value.
- */
- private static Pair<Integer, List<Geometry>> parseWarningAreaCoordinates(
- byte[] pdu, int wacOffset) {
- // little-endian
- int wacDataLength = ((pdu[wacOffset + 1] & 0xff) << 8) | (pdu[wacOffset] & 0xff);
- int offset = wacOffset + 2;
-
- if (offset + wacDataLength > pdu.length) {
- throw new IllegalArgumentException("Invalid wac data, expected the length of pdu at"
- + "least " + offset + wacDataLength + ", actual is " + pdu.length);
- }
-
- BitStreamReader bitReader = new BitStreamReader(pdu, offset);
-
- int maximumWaitTimeSec = SmsCbMessage.MAXIMUM_WAIT_TIME_NOT_SET;
-
- List<Geometry> geo = new ArrayList<>();
- int remainedBytes = wacDataLength;
- while (remainedBytes > 0) {
- int type = bitReader.read(4);
- int length = bitReader.read(10);
- remainedBytes -= length;
- // Skip the 2 remained bits
- bitReader.skip();
-
- switch (type) {
- case CbGeoUtils.GEO_FENCING_MAXIMUM_WAIT_TIME:
- maximumWaitTimeSec = bitReader.read(8);
- break;
- case CbGeoUtils.GEOMETRY_TYPE_POLYGON:
- List<LatLng> latLngs = new ArrayList<>();
- // Each coordinate is represented by 44 bits integer.
- // ATIS-0700041 5.2.4 Coordinate coding
- int n = (length - 2) * 8 / 44;
- for (int i = 0; i < n; i++) {
- latLngs.add(getLatLng(bitReader));
- }
- // Skip the padding bits
- bitReader.skip();
- geo.add(new Polygon(latLngs));
- break;
- case CbGeoUtils.GEOMETRY_TYPE_CIRCLE:
- LatLng center = getLatLng(bitReader);
- // radius = (wacRadius / 2^6). The unit of wacRadius is km, we use meter as the
- // distance unit during geo-fencing.
- // ATIS-0700041 5.2.5 radius coding
- double radius = (bitReader.read(20) * 1.0 / (1 << 6)) * 1000.0;
- geo.add(new Circle(center, radius));
- break;
- default:
- throw new IllegalArgumentException("Unsupported geoType = " + type);
- }
- }
- return new Pair(maximumWaitTimeSec, geo);
- }
-
- /**
- * The coordinate is (latitude, longitude), represented by a 44 bits integer.
- * The coding is defined in ATIS-0700041 5.2.4
- * @param bitReader
- * @return coordinate (latitude, longitude)
- */
- private static LatLng getLatLng(BitStreamReader bitReader) {
- // wacLatitude = floor(((latitude + 90) / 180) * 2^22)
- // wacLongitude = floor(((longitude + 180) / 360) * 2^22)
- int wacLat = bitReader.read(22);
- int wacLng = bitReader.read(22);
-
- // latitude = wacLatitude * 180 / 2^22 - 90
- // longitude = wacLongitude * 360 / 2^22 -180
- return new LatLng((wacLat * 180.0 / (1 << 22)) - 90, (wacLng * 360.0 / (1 << 22) - 180));
- }
-
- /**
- * Parse and unpack the UMTS body text according to the encoding in the data coding scheme.
- *
- * @param header the message header to use
- * @param pdu the PDU to decode
- * @return a pair of string containing the language and body of the message in order
- */
- private static Pair<String, String> parseUmtsBody(SmsCbHeader header, byte[] pdu) {
- // Payload may contain multiple pages
- int nrPages = pdu[SmsCbHeader.PDU_HEADER_LENGTH];
- String language = header.getDataCodingSchemeStructedData().language;
-
- if (pdu.length < SmsCbHeader.PDU_HEADER_LENGTH + 1 + (PDU_BODY_PAGE_LENGTH + 1)
- * nrPages) {
- throw new IllegalArgumentException("Pdu length " + pdu.length + " does not match "
- + nrPages + " pages");
- }
-
- StringBuilder sb = new StringBuilder();
-
- for (int i = 0; i < nrPages; i++) {
- // Each page is 82 bytes followed by a length octet indicating
- // the number of useful octets within those 82
- int offset = SmsCbHeader.PDU_HEADER_LENGTH + 1 + (PDU_BODY_PAGE_LENGTH + 1) * i;
- int length = pdu[offset + PDU_BODY_PAGE_LENGTH];
-
- if (length > PDU_BODY_PAGE_LENGTH) {
- throw new IllegalArgumentException("Page length " + length
- + " exceeds maximum value " + PDU_BODY_PAGE_LENGTH);
- }
-
- Pair<String, String> p = unpackBody(pdu, offset, length,
- header.getDataCodingSchemeStructedData());
- language = p.first;
- sb.append(p.second);
- }
- return new Pair(language, sb.toString());
-
- }
-
- /**
- * Parse and unpack the GSM body text according to the encoding in the data coding scheme.
- * @param header the message header to use
- * @param pdu the PDU to decode
- * @return a pair of string containing the language and body of the message in order
- */
- private static Pair<String, String> parseGsmBody(SmsCbHeader header, byte[] pdu) {
- // Payload is one single page
- int offset = SmsCbHeader.PDU_HEADER_LENGTH;
- int length = pdu.length - offset;
- return unpackBody(pdu, offset, length, header.getDataCodingSchemeStructedData());
- }
-
- /**
- * Unpack body text from the pdu using the given encoding, position and length within the pdu.
- *
- * @param pdu The pdu
- * @param offset Position of the first byte to unpack
- * @param length Number of bytes to unpack
- * @param dcs data coding scheme
- * @return a Pair of Strings containing the language and body of the message
- */
- private static Pair<String, String> unpackBody(byte[] pdu, int offset, int length,
- DataCodingScheme dcs) {
- String body = null;
-
- String language = dcs.language;
- switch (dcs.encoding) {
- case SmsConstants.ENCODING_7BIT:
- body = GsmAlphabet.gsm7BitPackedToString(pdu, offset, length * 8 / 7);
-
- if (dcs.hasLanguageIndicator && body != null && body.length() > 2) {
- // Language is two GSM characters followed by a CR.
- // The actual body text is offset by 3 characters.
- language = body.substring(0, 2);
- body = body.substring(3);
- }
- break;
-
- case SmsConstants.ENCODING_16BIT:
- if (dcs.hasLanguageIndicator && pdu.length >= offset + 2) {
- // Language is two GSM characters.
- // The actual body text is offset by 2 bytes.
- language = GsmAlphabet.gsm7BitPackedToString(pdu, offset, 2);
- offset += 2;
- length -= 2;
- }
-
- try {
- body = new String(pdu, offset, (length & 0xfffe), "utf-16");
- } catch (UnsupportedEncodingException e) {
- // Apparently it wasn't valid UTF-16.
- throw new IllegalArgumentException("Error decoding UTF-16 message", e);
- }
- break;
-
- default:
- break;
- }
-
- if (body != null) {
- // Remove trailing carriage return
- for (int i = body.length() - 1; i >= 0; i--) {
- if (body.charAt(i) != CARRIAGE_RETURN) {
- body = body.substring(0, i + 1);
- break;
- }
- }
- } else {
- body = "";
- }
-
- return new Pair<String, String>(language, body);
- }
-
- /** A class use to facilitate the processing of bits stream data. */
- private static final class BitStreamReader {
- /** The bits stream represent by a bytes array. */
- private final byte[] mData;
-
- /** The offset of the current byte. */
- private int mCurrentOffset;
-
- /**
- * The remained bits of the current byte which have not been read. The most significant
- * will be read first, so the remained bits are always the least significant bits.
- */
- private int mRemainedBit;
-
- /**
- * Constructor
- * @param data bit stream data represent by byte array.
- * @param offset the offset of the first byte.
- */
- BitStreamReader(byte[] data, int offset) {
- mData = data;
- mCurrentOffset = offset;
- mRemainedBit = 8;
- }
-
- /**
- * Read the first {@code count} bits.
- * @param count the number of bits need to read
- * @return {@code bits} represent by an 32-bits integer, therefore {@code count} must be no
- * greater than 32.
- */
- public int read(int count) throws IndexOutOfBoundsException {
- int val = 0;
- while (count > 0) {
- if (count >= mRemainedBit) {
- val <<= mRemainedBit;
- val |= mData[mCurrentOffset] & ((1 << mRemainedBit) - 1);
- count -= mRemainedBit;
- mRemainedBit = 8;
- ++mCurrentOffset;
- } else {
- val <<= count;
- val |= (mData[mCurrentOffset] & ((1 << mRemainedBit) - 1))
- >> (mRemainedBit - count);
- mRemainedBit -= count;
- count = 0;
- }
- }
- return val;
- }
-
- /**
- * Skip the current bytes if the remained bits is less than 8. This is useful when
- * processing the padding or reserved bits.
- */
- public void skip() {
- if (mRemainedBit < 8) {
- mRemainedBit = 8;
- ++mCurrentOffset;
- }
- }
- }
-
- /**
- * Part of a GSM SMS cell broadcast message which may trigger geo-fencing logic.
- * @hide
- */
- public static final class GeoFencingTriggerMessage {
- /**
- * Indicate the list of active alerts share their warning area coordinates which means the
- * broadcast area is the union of the broadcast areas of the active alerts in this list.
- */
- public static final int TYPE_ACTIVE_ALERT_SHARE_WAC = 2;
-
- public final int type;
- public final List<CellBroadcastIdentity> cbIdentifiers;
-
- GeoFencingTriggerMessage(int type, @NonNull List<CellBroadcastIdentity> cbIdentifiers) {
- this.type = type;
- this.cbIdentifiers = cbIdentifiers;
- }
-
- /**
- * Whether the trigger message indicates that the broadcast areas are shared between all
- * active alerts.
- * @return true if broadcast areas are to be shared
- */
- boolean shouldShareBroadcastArea() {
- return type == TYPE_ACTIVE_ALERT_SHARE_WAC;
- }
-
- static final class CellBroadcastIdentity {
- public final int messageIdentifier;
- public final int serialNumber;
- CellBroadcastIdentity(int messageIdentifier, int serialNumber) {
- this.messageIdentifier = messageIdentifier;
- this.serialNumber = serialNumber;
- }
- }
-
- @Override
- public String toString() {
- String identifiers = cbIdentifiers.stream()
- .map(cbIdentifier ->String.format("(msgId = %d, serial = %d)",
- cbIdentifier.messageIdentifier, cbIdentifier.serialNumber))
- .collect(Collectors.joining(","));
- return "triggerType=" + type + " identifiers=" + identifiers;
- }
- }
-}
diff --git a/telephony/java/com/android/internal/telephony/util/TelephonyUtils.java b/telephony/java/com/android/internal/telephony/util/TelephonyUtils.java
index 306b9eeca6e3..2abcc76fdccc 100644
--- a/telephony/java/com/android/internal/telephony/util/TelephonyUtils.java
+++ b/telephony/java/com/android/internal/telephony/util/TelephonyUtils.java
@@ -22,6 +22,8 @@ import android.content.pm.ComponentInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Binder;
+import android.os.Bundle;
+import android.os.PersistableBundle;
import android.os.RemoteException;
import android.os.SystemProperties;
@@ -108,4 +110,31 @@ public final class TelephonyUtils {
Binder.restoreCallingIdentity(callingIdentity);
}
}
+
+ /**
+ * Filter values in bundle to only basic types.
+ */
+ public static Bundle filterValues(Bundle bundle) {
+ Bundle ret = new Bundle(bundle);
+ for (String key : bundle.keySet()) {
+ Object value = bundle.get(key);
+ if ((value instanceof Integer) || (value instanceof Long)
+ || (value instanceof Double) || (value instanceof String)
+ || (value instanceof int[]) || (value instanceof long[])
+ || (value instanceof double[]) || (value instanceof String[])
+ || (value instanceof PersistableBundle) || (value == null)
+ || (value instanceof Boolean) || (value instanceof boolean[])) {
+ continue;
+ }
+ if (value instanceof Bundle) {
+ ret.putBundle(key, filterValues((Bundle) value));
+ continue;
+ }
+ if (value.getClass().getName().startsWith("android.")) {
+ continue;
+ }
+ ret.remove(key);
+ }
+ return ret;
+ }
}
diff --git a/test-mock/Android.bp b/test-mock/Android.bp
index 616b6b005f89..248c117d2e03 100644
--- a/test-mock/Android.bp
+++ b/test-mock/Android.bp
@@ -28,7 +28,7 @@ java_sdk_library {
":framework_native_aidl",
],
libs: [
- "framework-all",
+ "framework",
"app-compat-annotations",
"unsupportedappusage",
],
diff --git a/tests/ApkVerityTest/AndroidTest.xml b/tests/ApkVerityTest/AndroidTest.xml
index 51bcdea21f49..55704eda905e 100644
--- a/tests/ApkVerityTest/AndroidTest.xml
+++ b/tests/ApkVerityTest/AndroidTest.xml
@@ -22,7 +22,7 @@
<target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
<!-- Disable package verifier prevents it holding the target APK's fd that prevents cache
eviction. -->
- <option name="set-global-setting" key="package_verifier_enable" value="0" />
+ <option name="set-global-setting" key="verifier_verify_adb_installs" value="0" />
<option name="restore-settings" value="true" />
<!-- Skip in order to prevent reboot that confuses the test flow. -->
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
index daa85bd06669..f6699faf7a61 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
@@ -31,6 +31,7 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.PackageManager;
import android.content.rollback.RollbackInfo;
import android.content.rollback.RollbackManager;
import android.os.UserManager;
@@ -1122,4 +1123,39 @@ public class RollbackTest {
InstallUtils.dropShellPermissionIdentity();
}
}
+
+ @Test
+ public void testRollbackDataPolicy() throws Exception {
+ try {
+ InstallUtils.adoptShellPermissionIdentity(
+ Manifest.permission.INSTALL_PACKAGES,
+ Manifest.permission.DELETE_PACKAGES,
+ Manifest.permission.TEST_MANAGE_ROLLBACKS);
+
+ Uninstall.packages(TestApp.A, TestApp.B);
+ Install.multi(TestApp.A1, TestApp.B1).commit();
+ // Write user data version = 1
+ InstallUtils.processUserData(TestApp.A);
+ InstallUtils.processUserData(TestApp.B);
+
+ Install a2 = Install.single(TestApp.A2)
+ .setEnableRollback(PackageManager.RollbackDataPolicy.WIPE);
+ Install b2 = Install.single(TestApp.B2)
+ .setEnableRollback(PackageManager.RollbackDataPolicy.RESTORE);
+ Install.multi(a2, b2).setEnableRollback().commit();
+ // Write user data version = 2
+ InstallUtils.processUserData(TestApp.A);
+ InstallUtils.processUserData(TestApp.B);
+
+ RollbackInfo info = RollbackUtils.getAvailableRollback(TestApp.A);
+ RollbackUtils.rollback(info.getRollbackId());
+ // Read user data version from userdata.txt
+ // A's user data version is -1 for user data is wiped.
+ // B's user data version is 1 as rollback committed.
+ assertThat(InstallUtils.getUserDataVersion(TestApp.A)).isEqualTo(-1);
+ assertThat(InstallUtils.getUserDataVersion(TestApp.B)).isEqualTo(1);
+ } finally {
+ InstallUtils.dropShellPermissionIdentity();
+ }
+ }
}
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
index 879ac64c6a55..40169b8cdcd3 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
@@ -185,6 +185,12 @@ public class StagedRollbackTest {
*/
@Test
public void testNativeWatchdogTriggersRollback_Phase1() throws Exception {
+ // When multiple staged sessions are installed on a device which doesn't support checkpoint,
+ // only the 1st one will prevail. We have to check no other rollbacks available to ensure
+ // TestApp.A is always the 1st and the only one to commit so rollback can work as intended.
+ // If there are leftover rollbacks from previous tests, this assertion will fail.
+ assertThat(RollbackUtils.getRollbackManager().getAvailableRollbacks()).isEmpty();
+
Uninstall.packages(TestApp.A);
Install.single(TestApp.A1).commit();
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
@@ -373,6 +379,49 @@ public class StagedRollbackTest {
assertThat(RollbackUtils.getAvailableRollback(getModuleMetadataPackageName())).isNotNull();
}
+ @Test
+ public void testRollbackWhitelistedApp_cleanUp() throws Exception {
+ RollbackUtils.getRollbackManager().expireRollbackForPackage(getModuleMetadataPackageName());
+ }
+
+ @Test
+ public void testRollbackDataPolicy_Phase1() throws Exception {
+ Uninstall.packages(TestApp.A, TestApp.B);
+ Install.multi(TestApp.A1, TestApp.B1).commit();
+ // Write user data version = 1
+ InstallUtils.processUserData(TestApp.A);
+ InstallUtils.processUserData(TestApp.B);
+
+ Install a2 = Install.single(TestApp.A2).setStaged()
+ .setEnableRollback(PackageManager.RollbackDataPolicy.WIPE);
+ Install b2 = Install.single(TestApp.B2).setStaged()
+ .setEnableRollback(PackageManager.RollbackDataPolicy.RESTORE);
+ Install.multi(a2, b2).setEnableRollback().setStaged().commit();
+ }
+
+ @Test
+ public void testRollbackDataPolicy_Phase2() throws Exception {
+ assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
+ assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2);
+ // Write user data version = 2
+ InstallUtils.processUserData(TestApp.A);
+ InstallUtils.processUserData(TestApp.B);
+
+ RollbackInfo info = RollbackUtils.getAvailableRollback(TestApp.A);
+ RollbackUtils.rollback(info.getRollbackId());
+ }
+
+ @Test
+ public void testRollbackDataPolicy_Phase3() throws Exception {
+ assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
+ assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(1);
+ // Read user data version from userdata.txt
+ // A's user data version is -1 for user data is wiped.
+ // B's user data version is 1 as rollback committed.
+ assertThat(InstallUtils.getUserDataVersion(TestApp.A)).isEqualTo(-1);
+ assertThat(InstallUtils.getUserDataVersion(TestApp.B)).isEqualTo(1);
+ }
+
private static void runShellCommand(String cmd) {
ParcelFileDescriptor pfd = InstrumentationRegistry.getInstrumentation().getUiAutomation()
.executeShellCommand(cmd);
diff --git a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
index 07d829d2d0bb..4644d8aee306 100644
--- a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
+++ b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
@@ -180,9 +180,25 @@ public class StagedRollbackTest extends BaseHostJUnit4Test {
*/
@Test
public void testRollbackWhitelistedApp() throws Exception {
- runPhase("testRollbackWhitelistedApp_Phase1");
+ try {
+ runPhase("testRollbackWhitelistedApp_Phase1");
+ getDevice().reboot();
+ runPhase("testRollbackWhitelistedApp_Phase2");
+ } finally {
+ // testNativeWatchdogTriggersRollback will fail if multiple staged sessions are
+ // committed on a device which doesn't support checkpoint. Let's clean up the rollback
+ // so there is only one rollback to commit when testing native crashes.
+ runPhase("testRollbackWhitelistedApp_cleanUp");
+ }
+ }
+
+ @Test
+ public void testRollbackDataPolicy() throws Exception {
+ runPhase("testRollbackDataPolicy_Phase1");
+ getDevice().reboot();
+ runPhase("testRollbackDataPolicy_Phase2");
getDevice().reboot();
- runPhase("testRollbackWhitelistedApp_Phase2");
+ runPhase("testRollbackDataPolicy_Phase3");
}
private void crashProcess(String processName, int numberOfCrashes) throws Exception {
diff --git a/tests/WindowlessWmTest/Android.bp b/tests/SurfaceControlViewHostTest/Android.bp
index 2ace3f363ef9..e4e060010eea 100644
--- a/tests/WindowlessWmTest/Android.bp
+++ b/tests/SurfaceControlViewHostTest/Android.bp
@@ -15,7 +15,7 @@
//
android_test {
- name: "WindowlessWmTest",
+ name: "SurfaceControlViewHostTest",
srcs: ["**/*.java"],
platform_apis: true,
certificate: "platform",
diff --git a/tests/WindowlessWmTest/AndroidManifest.xml b/tests/SurfaceControlViewHostTest/AndroidManifest.xml
index babfd76d91e8..ee95763453f7 100644
--- a/tests/WindowlessWmTest/AndroidManifest.xml
+++ b/tests/SurfaceControlViewHostTest/AndroidManifest.xml
@@ -16,7 +16,7 @@
package="com.android.test.viewembed">
<application>
- <activity android:name="WindowlessWmTest" android:label="View Embedding Test">
+ <activity android:name="SurfaceControlViewHostTest" android:label="View Embedding Test">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
diff --git a/tests/WindowlessWmTest/src/com/android/test/viewembed/WindowlessWmTest.java b/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceControlViewHostTest.java
index 5c1e830e1382..6687f83ad0db 100644
--- a/tests/WindowlessWmTest/src/com/android/test/viewembed/WindowlessWmTest.java
+++ b/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceControlViewHostTest.java
@@ -22,18 +22,19 @@ import android.graphics.Color;
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.view.Gravity;
+import android.view.SurfaceControl;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
-import android.view.WindowlessViewRoot;
+import android.view.SurfaceControlViewHost;
import android.widget.Button;
import android.widget.FrameLayout;
-public class WindowlessWmTest extends Activity implements SurfaceHolder.Callback{
+public class SurfaceControlViewHostTest extends Activity implements SurfaceHolder.Callback{
SurfaceView mView;
- WindowlessViewRoot mVr;
+ SurfaceControlViewHost mVr;
protected void onCreate(Bundle savedInstanceState) {
FrameLayout content = new FrameLayout(this);
@@ -49,8 +50,12 @@ public class WindowlessWmTest extends Activity implements SurfaceHolder.Callback
@Override
public void surfaceCreated(SurfaceHolder holder) {
- mVr = new WindowlessViewRoot(this, this.getDisplay(), mView.getSurfaceControl(),
+ mVr = new SurfaceControlViewHost(this, this.getDisplay(),
mView.getInputToken());
+
+ final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+ t.reparent(mVr.getSurfacePackage().getSurfaceControl(), mView.getSurfaceControl()).apply();
+
Button v = new Button(this);
v.setBackgroundColor(Color.BLUE);
v.setOnClickListener(new View.OnClickListener() {
diff --git a/tests/UsbManagerTests/Android.bp b/tests/UsbManagerTests/Android.bp
new file mode 100644
index 000000000000..a03c6e223b74
--- /dev/null
+++ b/tests/UsbManagerTests/Android.bp
@@ -0,0 +1,32 @@
+//
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_test {
+ name: "UsbManagerTests",
+ srcs: ["src/**/*.java"],
+ static_libs: [
+ "frameworks-base-testutils",
+ "androidx.test.rules",
+ "mockito-target-inline-minus-junit4",
+ "platform-test-annotations",
+ "truth-prebuilt",
+ "UsbManagerTestLib",
+ ],
+ jni_libs: ["libdexmakerjvmtiagent"],
+ certificate: "platform",
+ platform_apis: true,
+ test_suites: ["device-tests"],
+}
diff --git a/tests/UsbManagerTests/AndroidManifest.xml b/tests/UsbManagerTests/AndroidManifest.xml
new file mode 100644
index 000000000000..4e0b790f6dde
--- /dev/null
+++ b/tests/UsbManagerTests/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.server.usbtest" >
+
+ <uses-permission android:name="android.permission.MANAGE_USB" />
+
+ <application android:debuggable="true">
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.server.usbtest"
+ android:label="UsbManagerTests"/>
+</manifest>
diff --git a/tests/UsbManagerTests/AndroidTest.xml b/tests/UsbManagerTests/AndroidTest.xml
new file mode 100644
index 000000000000..c6e22cdc4b37
--- /dev/null
+++ b/tests/UsbManagerTests/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Runs Frameworks USB API instrumentation Tests.">
+ <target_preparer class="com.android.tradefed.targetprep.TestFilePushSetup"/>
+ <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+ <option name="test-file-name" value="UsbManagerTests.apk" />
+ </target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer"/>
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer"/>
+ <option name="test-suite-tag" value="apct"/>
+ <option name="test-tag" value="UsbManagerTests" />
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+ <option name="package" value="com.android.server.usbtest"/>
+ <option name="runner" value="androidx.test.runner.AndroidJUnitRunner"/>
+ <option name="hidden-api-checks" value="false"/>
+ </test>
+</configuration>
diff --git a/tests/UsbManagerTests/lib/Android.bp b/tests/UsbManagerTests/lib/Android.bp
new file mode 100644
index 000000000000..3c5d91b326d0
--- /dev/null
+++ b/tests/UsbManagerTests/lib/Android.bp
@@ -0,0 +1,34 @@
+//
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_library {
+ name: "UsbManagerTestLib",
+ srcs: ["src/**/*.java"],
+ static_libs: [
+ "frameworks-base-testutils",
+ "androidx.test.rules",
+ "mockito-target-inline-minus-junit4",
+ "platform-test-annotations",
+ "services.core",
+ "services.net",
+ "services.usb",
+ "truth-prebuilt",
+ "androidx.core_core",
+ ],
+ libs: [
+ "android.test.mock",
+ ],
+}
diff --git a/tests/UsbManagerTests/lib/AndroidManifest.xml b/tests/UsbManagerTests/lib/AndroidManifest.xml
new file mode 100644
index 000000000000..c8b301ca0298
--- /dev/null
+++ b/tests/UsbManagerTests/lib/AndroidManifest.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.server.usblib">
+
+ <application/>
+
+</manifest>
diff --git a/tests/UsbManagerTests/lib/src/com/android/server/usblib/UsbManagerTestLib.java b/tests/UsbManagerTests/lib/src/com/android/server/usblib/UsbManagerTestLib.java
new file mode 100644
index 000000000000..782439f80fc8
--- /dev/null
+++ b/tests/UsbManagerTests/lib/src/com/android/server/usblib/UsbManagerTestLib.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.usblib;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.hardware.usb.UsbManager;
+import android.os.RemoteException;
+import android.util.Log;
+
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Unit tests lib for {@link android.hardware.usb.UsbManager}.
+ */
+public class UsbManagerTestLib {
+ private static final String TAG = UsbManagerTestLib.class.getSimpleName();
+
+ private Context mContext;
+
+ private UsbManager mUsbManagerSys;
+ private UsbManager mUsbManagerMock;
+ @Mock private android.hardware.usb.IUsbManager mMockUsbService;
+
+ public UsbManagerTestLib(Context context) {
+ MockitoAnnotations.initMocks(this);
+ mContext = context;
+
+ assertNotNull(mUsbManagerSys = mContext.getSystemService(UsbManager.class));
+ assertNotNull(mUsbManagerMock = new UsbManager(mContext, mMockUsbService));
+ }
+
+ private long getCurrentFunctions() {
+ return mUsbManagerMock.getCurrentFunctions();
+ }
+
+ private void setCurrentFunctions(long functions) {
+ mUsbManagerMock.setCurrentFunctions(functions);
+ }
+
+ private long getCurrentFunctionsSys() {
+ return mUsbManagerSys.getCurrentFunctions();
+ }
+
+ private void setCurrentFunctionsSys(long functions) {
+ mUsbManagerSys.setCurrentFunctions(functions);
+ }
+
+ private void testSetGetCurrentFunctions_Matched(long functions) {
+ setCurrentFunctions(functions);
+ assertEquals("CurrentFunctions mismatched: ", functions, getCurrentFunctions());
+ }
+
+ private void testGetCurrentFunctionsMock_Matched(long functions) {
+ try {
+ when(mMockUsbService.getCurrentFunctions()).thenReturn(functions);
+
+ assertEquals("CurrentFunctions mismatched: ", functions, getCurrentFunctions());
+ } catch (RemoteException remEx) {
+ Log.w(TAG, "RemoteException");
+ }
+ }
+
+ private void testSetCurrentFunctionsMock_Matched(long functions) {
+ try {
+ setCurrentFunctions(functions);
+
+ verify(mMockUsbService).setCurrentFunctions(eq(functions));
+ } catch (RemoteException remEx) {
+ Log.w(TAG, "RemoteException");
+ }
+ }
+
+ public void testGetCurrentFunctionsSysEx() throws Exception {
+ getCurrentFunctionsSys();
+ }
+
+ public void testSetCurrentFunctionsSysEx(long functions) throws Exception {
+ setCurrentFunctionsSys(functions);
+ }
+
+ public void testGetCurrentFunctionsEx() throws Exception {
+ getCurrentFunctions();
+
+ verify(mMockUsbService).getCurrentFunctions();
+ }
+
+ public void testSetCurrentFunctionsEx(long functions) throws Exception {
+ setCurrentFunctions(functions);
+
+ verify(mMockUsbService).setCurrentFunctions(eq(functions));
+ }
+
+ public void testGetCurrentFunctions_shouldMatched() {
+ testGetCurrentFunctionsMock_Matched(UsbManager.FUNCTION_NONE);
+ testGetCurrentFunctionsMock_Matched(UsbManager.FUNCTION_MTP);
+ testGetCurrentFunctionsMock_Matched(UsbManager.FUNCTION_PTP);
+ testGetCurrentFunctionsMock_Matched(UsbManager.FUNCTION_MIDI);
+ testGetCurrentFunctionsMock_Matched(UsbManager.FUNCTION_RNDIS);
+ }
+
+ public void testSetCurrentFunctions_shouldMatched() {
+ testSetCurrentFunctionsMock_Matched(UsbManager.FUNCTION_NONE);
+ testSetCurrentFunctionsMock_Matched(UsbManager.FUNCTION_MTP);
+ testSetCurrentFunctionsMock_Matched(UsbManager.FUNCTION_PTP);
+ testSetCurrentFunctionsMock_Matched(UsbManager.FUNCTION_MIDI);
+ testSetCurrentFunctionsMock_Matched(UsbManager.FUNCTION_RNDIS);
+ }
+}
diff --git a/tests/UsbManagerTests/src/com/android/server/usbtest/UsbManagerApiTest.java b/tests/UsbManagerTests/src/com/android/server/usbtest/UsbManagerApiTest.java
new file mode 100644
index 000000000000..8b21763b4a24
--- /dev/null
+++ b/tests/UsbManagerTests/src/com/android/server/usbtest/UsbManagerApiTest.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.usbtest;
+
+import android.content.Context;
+import android.hardware.usb.UsbManager;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import com.android.server.usblib.UsbManagerTestLib;
+
+/**
+ * Unit tests for {@link android.hardware.usb.UsbManager}.
+ * Note: MUST claimed MANAGE_USB permission in Manifest
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class UsbManagerApiTest {
+ private Context mContext;
+
+ private final UsbManagerTestLib mUsbManagerTestLib =
+ new UsbManagerTestLib(mContext = InstrumentationRegistry.getContext());
+
+ /**
+ * Verify NO SecurityException
+ * Go through System Server
+ */
+ @Test
+ public void testUsbApi_GetCurrentFunctionsSys_shouldNoSecurityException() throws Exception {
+ mUsbManagerTestLib.testGetCurrentFunctionsSysEx();
+ }
+
+ /**
+ * Verify NO SecurityException
+ * Go through System Server
+ */
+ @Test
+ public void testUsbApi_SetCurrentFunctionsSys_shouldNoSecurityException() throws Exception {
+ mUsbManagerTestLib.testSetCurrentFunctionsSysEx(UsbManager.FUNCTION_NONE);
+ }
+
+ /**
+ * Verify NO SecurityException
+ * Go through Direct API, will not be denied by @RequiresPermission annotation
+ */
+ @Test
+ public void testUsbApi_GetCurrentFunctions_shouldNoSecurityException() throws Exception {
+ mUsbManagerTestLib.testGetCurrentFunctionsEx();
+ }
+
+ /**
+ * Verify NO SecurityException
+ * Go through Direct API, will not be denied by @RequiresPermission annotation
+ */
+ @Test
+ public void testUsbApi_SetCurrentFunctions_shouldNoSecurityException() throws Exception {
+ mUsbManagerTestLib.testSetCurrentFunctionsEx(UsbManager.FUNCTION_NONE);
+ }
+
+ /**
+ * Verify API path from UsbManager to UsbService
+ */
+ @Test
+ public void testUsbApi_GetCurrentFunctions_shouldMatched() {
+ mUsbManagerTestLib.testGetCurrentFunctions_shouldMatched();
+ }
+
+ /**
+ * Verify API path from UsbManager to UsbService
+ */
+ @Test
+ public void testUsbApi_SetCurrentFunctions_shouldMatched() {
+ mUsbManagerTestLib.testSetCurrentFunctions_shouldMatched();
+ }
+}
diff --git a/tests/UsbTests/Android.bp b/tests/UsbTests/Android.bp
index 1b2cf638f514..7c2be9b63ac3 100644
--- a/tests/UsbTests/Android.bp
+++ b/tests/UsbTests/Android.bp
@@ -26,6 +26,7 @@ android_test {
"services.net",
"services.usb",
"truth-prebuilt",
+ "UsbManagerTestLib",
],
jni_libs: ["libdexmakerjvmtiagent"],
certificate: "platform",
diff --git a/tests/UsbTests/src/com/android/server/usb/UsbManagerNoPermTest.java b/tests/UsbTests/src/com/android/server/usb/UsbManagerNoPermTest.java
new file mode 100644
index 000000000000..a0fd9d40506b
--- /dev/null
+++ b/tests/UsbTests/src/com/android/server/usb/UsbManagerNoPermTest.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.usb;
+
+import android.content.Context;
+import android.hardware.usb.UsbManager;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import com.android.server.usblib.UsbManagerTestLib;
+
+/**
+ * Unit tests for {@link android.hardware.usb.UsbManager}.
+ * Note: NOT claimed MANAGE_USB permission in Manifest
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class UsbManagerNoPermTest {
+ private Context mContext;
+
+ private final UsbManagerTestLib mUsbManagerTestLib =
+ new UsbManagerTestLib(mContext = InstrumentationRegistry.getContext());
+
+ /**
+ * Verify SecurityException resulting from required permissions missing
+ * Go through System Server
+ */
+ @Test(expected = SecurityException.class)
+ public void testUsbApi_GetCurrentFunctionsSys_OnSecurityException() throws Exception {
+ mUsbManagerTestLib.testGetCurrentFunctionsSysEx();
+ }
+
+ /**
+ * Verify SecurityException resulting from required permissions missing
+ * Go through System Server
+ */
+ @Test(expected = SecurityException.class)
+ public void testUsbApi_SetCurrentFunctionsSys_OnSecurityException() throws Exception {
+ mUsbManagerTestLib.testSetCurrentFunctionsSysEx(UsbManager.FUNCTION_NONE);
+ }
+
+ /**
+ * Verify SecurityException resulting from required permissions missing
+ * Go through Direct API, will not be denied by @RequiresPermission annotation
+ */
+ @Test(expected = SecurityException.class)
+ @Ignore
+ public void testUsbApi_GetCurrentFunctions_OnSecurityException() throws Exception {
+ mUsbManagerTestLib.testGetCurrentFunctionsEx();
+ }
+
+ /**
+ * Verify SecurityException resulting from required permissions missing
+ * Go through Direct API, will not be denied by @RequiresPermission annotation
+ */
+ @Test(expected = SecurityException.class)
+ @Ignore
+ public void testUsbApi_SetCurrentFunctions_OnSecurityException() throws Exception {
+ mUsbManagerTestLib.testSetCurrentFunctionsEx(UsbManager.FUNCTION_NONE);
+ }
+}
diff --git a/tests/libs-permissions/Android.bp b/tests/libs-permissions/Android.bp
index 330bfc9022df..66a1f83dc308 100644
--- a/tests/libs-permissions/Android.bp
+++ b/tests/libs-permissions/Android.bp
@@ -2,6 +2,7 @@ java_library {
name: "com.android.test.libs.product",
installable: true,
product_specific: true,
+ sdk_version: "current",
srcs: ["product/java/**/*.java"],
required: ["com.android.test.libs.product.xml"],
}
diff --git a/tests/net/common/java/android/net/LinkPropertiesTest.java b/tests/net/common/java/android/net/LinkPropertiesTest.java
index ae8285b8a908..a7eef055a71c 100644
--- a/tests/net/common/java/android/net/LinkPropertiesTest.java
+++ b/tests/net/common/java/android/net/LinkPropertiesTest.java
@@ -16,7 +16,9 @@
package android.net;
+import static com.android.testutils.ParcelUtilsKt.assertParcelSane;
import static com.android.testutils.ParcelUtilsKt.assertParcelingIsLossless;
+import static com.android.testutils.ParcelUtilsKt.parcelingRoundTrip;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -47,25 +49,22 @@ import java.util.Set;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class LinkPropertiesTest {
- private static final InetAddress ADDRV4 = InetAddresses.parseNumericAddress("75.208.6.1");
- private static final InetAddress ADDRV6 = InetAddresses.parseNumericAddress(
- "2001:0db8:85a3:0000:0000:8a2e:0370:7334");
- private static final InetAddress DNS1 = InetAddresses.parseNumericAddress("75.208.7.1");
- private static final InetAddress DNS2 = InetAddresses.parseNumericAddress("69.78.7.1");
- private static final InetAddress DNS6 = InetAddresses.parseNumericAddress(
- "2001:4860:4860::8888");
- private static final InetAddress PRIVDNS1 = InetAddresses.parseNumericAddress("1.1.1.1");
- private static final InetAddress PRIVDNS2 = InetAddresses.parseNumericAddress("1.0.0.1");
- private static final InetAddress PRIVDNS6 = InetAddresses.parseNumericAddress(
- "2606:4700:4700::1111");
- private static final InetAddress PCSCFV4 = InetAddresses.parseNumericAddress("10.77.25.37");
- private static final InetAddress PCSCFV6 = InetAddresses.parseNumericAddress(
- "2001:0db8:85a3:0000:0000:8a2e:0370:1");
- private static final InetAddress GATEWAY1 = InetAddresses.parseNumericAddress("75.208.8.1");
- private static final InetAddress GATEWAY2 = InetAddresses.parseNumericAddress("69.78.8.1");
- private static final InetAddress GATEWAY61 = InetAddresses.parseNumericAddress(
- "fe80::6:0000:613");
- private static final InetAddress GATEWAY62 = InetAddresses.parseNumericAddress("fe80::6:2222");
+ private static final InetAddress ADDRV4 = address("75.208.6.1");
+ private static final InetAddress ADDRV6 = address("2001:0db8:85a3:0000:0000:8a2e:0370:7334");
+ private static final InetAddress DNS1 = address("75.208.7.1");
+ private static final InetAddress DNS2 = address("69.78.7.1");
+ private static final InetAddress DNS6 = address("2001:4860:4860::8888");
+ private static final InetAddress PRIVDNS1 = address("1.1.1.1");
+ private static final InetAddress PRIVDNS2 = address("1.0.0.1");
+ private static final InetAddress PRIVDNS6 = address("2606:4700:4700::1111");
+ private static final InetAddress PCSCFV4 = address("10.77.25.37");
+ private static final InetAddress PCSCFV6 = address("2001:0db8:85a3:0000:0000:8a2e:0370:1");
+ private static final InetAddress GATEWAY1 = address("75.208.8.1");
+ private static final InetAddress GATEWAY2 = address("69.78.8.1");
+ private static final InetAddress GATEWAY61 = address("fe80::6:0000:613");
+ private static final InetAddress GATEWAY62 = address("fe80::6:22%lo");
+ private static final InetAddress TESTIPV4ADDR = address("192.168.47.42");
+ private static final InetAddress TESTIPV6ADDR = address("fe80::7:33%43");
private static final String NAME = "qmi0";
private static final String DOMAINS = "google.com";
private static final String PRIV_DNS_SERVER_NAME = "private.dns.com";
@@ -75,8 +74,7 @@ public class LinkPropertiesTest {
private static final LinkAddress LINKADDRV6 = new LinkAddress(ADDRV6, 128);
private static final LinkAddress LINKADDRV6LINKLOCAL = new LinkAddress("fe80::1/64");
- // TODO: replace all calls to NetworkUtils.numericToInetAddress with calls to this method.
- private InetAddress Address(String addrString) {
+ private static InetAddress address(String addrString) {
return InetAddresses.parseNumericAddress(addrString);
}
@@ -228,7 +226,7 @@ public class LinkPropertiesTest {
target.clear();
target.setInterfaceName(NAME);
// change link addresses
- target.addLinkAddress(new LinkAddress(Address("75.208.6.2"), 32));
+ target.addLinkAddress(new LinkAddress(address("75.208.6.2"), 32));
target.addLinkAddress(LINKADDRV6);
target.addDnsServer(DNS1);
target.addDnsServer(DNS2);
@@ -243,7 +241,7 @@ public class LinkPropertiesTest {
target.addLinkAddress(LINKADDRV4);
target.addLinkAddress(LINKADDRV6);
// change dnses
- target.addDnsServer(Address("75.208.7.2"));
+ target.addDnsServer(address("75.208.7.2"));
target.addDnsServer(DNS2);
target.addPcscfServer(PCSCFV6);
target.addRoute(new RouteInfo(GATEWAY1));
@@ -255,10 +253,10 @@ public class LinkPropertiesTest {
target.setInterfaceName(NAME);
target.addLinkAddress(LINKADDRV4);
target.addLinkAddress(LINKADDRV6);
- target.addDnsServer(Address("75.208.7.2"));
+ target.addDnsServer(address("75.208.7.2"));
target.addDnsServer(DNS2);
// change pcscf
- target.addPcscfServer(Address("2001::1"));
+ target.addPcscfServer(address("2001::1"));
target.addRoute(new RouteInfo(GATEWAY1));
target.addRoute(new RouteInfo(GATEWAY2));
target.setMtu(MTU);
@@ -271,9 +269,9 @@ public class LinkPropertiesTest {
target.addDnsServer(DNS1);
target.addDnsServer(DNS2);
// change gateway
- target.addRoute(new RouteInfo(Address("75.208.8.2")));
- target.addRoute(new RouteInfo(GATEWAY2));
+ target.addRoute(new RouteInfo(address("75.208.8.2")));
target.setMtu(MTU);
+ target.addRoute(new RouteInfo(GATEWAY2));
assertFalse(source.equals(target));
target.clear();
@@ -349,7 +347,7 @@ public class LinkPropertiesTest {
@Test
public void testRouteInterfaces() {
- LinkAddress prefix = new LinkAddress(Address("2001:db8::"), 32);
+ LinkAddress prefix = new LinkAddress(address("2001:db8::"), 32);
InetAddress address = ADDRV6;
// Add a route with no interface to a LinkProperties with no interface. No errors.
@@ -739,8 +737,7 @@ public class LinkPropertiesTest {
// Add an on-link route, making the on-link DNS server reachable,
// but there is still no IPv4 address.
- assertTrue(v4lp.addRoute(new RouteInfo(
- new IpPrefix(NetworkUtils.numericToInetAddress("75.208.0.0"), 16))));
+ assertTrue(v4lp.addRoute(new RouteInfo(new IpPrefix(address("75.208.0.0"), 16))));
assertFalse(v4lp.isReachable(DNS1));
assertFalse(v4lp.isReachable(DNS2));
@@ -756,9 +753,9 @@ public class LinkPropertiesTest {
assertTrue(v4lp.isReachable(DNS2));
final LinkProperties v6lp = new LinkProperties();
- final InetAddress kLinkLocalDns = Address("fe80::6:1");
- final InetAddress kLinkLocalDnsWithScope = Address("fe80::6:2%43");
- final InetAddress kOnLinkDns = Address("2001:db8:85a3::53");
+ final InetAddress kLinkLocalDns = address("fe80::6:1");
+ final InetAddress kLinkLocalDnsWithScope = address("fe80::6:2%43");
+ final InetAddress kOnLinkDns = address("2001:db8:85a3::53");
assertFalse(v6lp.isReachable(kLinkLocalDns));
assertFalse(v6lp.isReachable(kLinkLocalDnsWithScope));
assertFalse(v6lp.isReachable(kOnLinkDns));
@@ -767,7 +764,7 @@ public class LinkPropertiesTest {
// Add a link-local route, making the link-local DNS servers reachable. Because
// we assume the presence of an IPv6 link-local address, link-local DNS servers
// are considered reachable, but only those with a non-zero scope identifier.
- assertTrue(v6lp.addRoute(new RouteInfo(new IpPrefix(Address("fe80::"), 64))));
+ assertTrue(v6lp.addRoute(new RouteInfo(new IpPrefix(address("fe80::"), 64))));
assertFalse(v6lp.isReachable(kLinkLocalDns));
assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope));
assertFalse(v6lp.isReachable(kOnLinkDns));
@@ -783,7 +780,7 @@ public class LinkPropertiesTest {
// Add a global route on link, but no global address yet. DNS servers reachable
// via a route that doesn't require a gateway: give them the benefit of the
// doubt and hope the link-local source address suffices for communication.
- assertTrue(v6lp.addRoute(new RouteInfo(new IpPrefix(Address("2001:db8:85a3::"), 64))));
+ assertTrue(v6lp.addRoute(new RouteInfo(new IpPrefix(address("2001:db8:85a3::"), 64))));
assertFalse(v6lp.isReachable(kLinkLocalDns));
assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope));
assertTrue(v6lp.isReachable(kOnLinkDns));
@@ -812,7 +809,7 @@ public class LinkPropertiesTest {
stacked.setInterfaceName("v4-test0");
v6lp.addStackedLink(stacked);
- InetAddress stackedAddress = Address("192.0.0.4");
+ InetAddress stackedAddress = address("192.0.0.4");
LinkAddress stackedLinkAddress = new LinkAddress(stackedAddress, 32);
assertFalse(v6lp.isReachable(stackedAddress));
stacked.addLinkAddress(stackedLinkAddress);
@@ -845,7 +842,7 @@ public class LinkPropertiesTest {
LinkProperties rmnet1 = new LinkProperties();
rmnet1.setInterfaceName("rmnet1");
rmnet1.addLinkAddress(new LinkAddress("10.0.0.3/8"));
- RouteInfo defaultRoute1 = new RouteInfo((IpPrefix) null, Address("10.0.0.1"),
+ RouteInfo defaultRoute1 = new RouteInfo((IpPrefix) null, address("10.0.0.1"),
rmnet1.getInterfaceName());
RouteInfo directRoute1 = new RouteInfo(new IpPrefix("10.0.0.0/8"), null,
rmnet1.getInterfaceName());
@@ -864,7 +861,7 @@ public class LinkPropertiesTest {
rmnet2.setInterfaceName("rmnet2");
rmnet2.addLinkAddress(new LinkAddress("fe80::cafe/64"));
rmnet2.addLinkAddress(new LinkAddress("2001:db8::2/64"));
- RouteInfo defaultRoute2 = new RouteInfo((IpPrefix) null, Address("2001:db8::1"),
+ RouteInfo defaultRoute2 = new RouteInfo((IpPrefix) null, address("2001:db8::1"),
rmnet2.getInterfaceName());
RouteInfo directRoute2 = new RouteInfo(new IpPrefix("2001:db8::/64"), null,
rmnet2.getInterfaceName());
@@ -930,24 +927,54 @@ public class LinkPropertiesTest {
public void testLinkPropertiesParcelable() throws Exception {
LinkProperties source = new LinkProperties();
source.setInterfaceName(NAME);
- // set 2 link addresses
+
source.addLinkAddress(LINKADDRV4);
source.addLinkAddress(LINKADDRV6);
- // set 2 dnses
+
source.addDnsServer(DNS1);
source.addDnsServer(DNS2);
- // set 2 gateways
+ source.addDnsServer(GATEWAY62);
+
+ source.addPcscfServer(TESTIPV4ADDR);
+ source.addPcscfServer(TESTIPV6ADDR);
+
+ source.setUsePrivateDns(true);
+ source.setPrivateDnsServerName(PRIV_DNS_SERVER_NAME);
+
+ source.setDomains(DOMAINS);
+
source.addRoute(new RouteInfo(GATEWAY1));
source.addRoute(new RouteInfo(GATEWAY2));
- // set 2 validated private dnses
+
source.addValidatedPrivateDnsServer(DNS6);
source.addValidatedPrivateDnsServer(GATEWAY61);
+ source.addValidatedPrivateDnsServer(TESTIPV6ADDR);
+
+ source.setHttpProxy(ProxyInfo.buildDirectProxy("test", 8888));
source.setMtu(MTU);
+ source.setTcpBufferSizes(TCP_BUFFER_SIZES);
+
source.setNat64Prefix(new IpPrefix("2001:db8:1:2:64:64::/96"));
- assertParcelingIsLossless(source);
+ source.setWakeOnLanSupported(true);
+
+ final LinkProperties stacked = new LinkProperties();
+ stacked.setInterfaceName("test-stacked");
+ source.addStackedLink(stacked);
+
+ assertParcelSane(source, 15 /* fieldCount */);
+ }
+
+ @Test
+ public void testLinkLocalDnsServerParceling() throws Exception {
+ final String strAddress = "fe80::1%lo";
+ final LinkProperties lp = new LinkProperties();
+ lp.addDnsServer(address(strAddress));
+ final LinkProperties unparceled = parcelingRoundTrip(lp);
+ // Inet6Address#equals does not test for the scope id
+ assertEquals(strAddress, unparceled.getDnsServers().get(0).getHostAddress());
}
@Test
diff --git a/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt b/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt
index 25028fb3ca0e..c4801aab5c32 100644
--- a/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt
+++ b/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt
@@ -32,7 +32,6 @@ import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET
import android.net.NetworkCapabilities.TRANSPORT_CELLULAR
import android.net.NetworkRequest
import android.net.TestNetworkStackClient
-import android.net.TetheringManager
import android.net.metrics.IpConnectivityLog
import android.os.ConditionVariable
import android.os.IBinder
@@ -169,7 +168,6 @@ class ConnectivityServiceIntegrationTest {
val deps = spy(ConnectivityService.Dependencies())
doReturn(networkStackClient).`when`(deps).networkStack
doReturn(metricsLogger).`when`(deps).metricsLogger
- doReturn(mock(TetheringManager::class.java)).`when`(deps).getTetheringManager()
doReturn(mock(ProxyTracker::class.java)).`when`(deps).makeProxyTracker(any(), any())
doReturn(mock(MockableSystemProperties::class.java)).`when`(deps).systemProperties
doReturn(TestNetIdManager()).`when`(deps).makeNetIdManager()
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index a24426b43059..b2d363e27839 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -164,7 +164,6 @@ import android.net.ProxyInfo;
import android.net.ResolverParamsParcel;
import android.net.RouteInfo;
import android.net.SocketKeepalive;
-import android.net.TetheringManager;
import android.net.UidRange;
import android.net.metrics.IpConnectivityLog;
import android.net.shared.NetworkMonitorUtils;
@@ -1133,7 +1132,6 @@ public class ConnectivityServiceTest {
doReturn(new TestNetIdManager()).when(deps).makeNetIdManager();
doReturn(mNetworkStack).when(deps).getNetworkStack();
doReturn(systemProperties).when(deps).getSystemProperties();
- doReturn(mock(TetheringManager.class)).when(deps).getTetheringManager();
doReturn(mock(ProxyTracker.class)).when(deps).makeProxyTracker(any(), any());
doReturn(mMetricsService).when(deps).getMetricsLogger();
doReturn(true).when(deps).queryUserAccess(anyInt(), anyInt());
diff --git a/tools/aapt2/Resource.h b/tools/aapt2/Resource.h
index 67ba895e51d1..c49c370bcc44 100644
--- a/tools/aapt2/Resource.h
+++ b/tools/aapt2/Resource.h
@@ -147,10 +147,11 @@ struct ResourceId {
ResourceId(uint32_t res_id); // NOLINT(google-explicit-constructor)
ResourceId(uint8_t p, uint8_t t, uint16_t e);
- bool is_valid() const;
+ // Returns true if the ID is a valid ID that is not dynamic (package ID cannot be 0)
+ bool is_valid_static() const;
// Returns true if the ID is a valid ID or dynamic ID (package ID can be 0).
- bool is_valid_dynamic() const;
+ bool is_valid() const;
uint8_t package_id() const;
uint8_t type_id() const;
@@ -233,11 +234,11 @@ inline ResourceId::ResourceId(uint32_t res_id) : id(res_id) {}
inline ResourceId::ResourceId(uint8_t p, uint8_t t, uint16_t e)
: id((p << 24) | (t << 16) | e) {}
-inline bool ResourceId::is_valid() const {
+inline bool ResourceId::is_valid_static() const {
return (id & 0xff000000u) != 0 && (id & 0x00ff0000u) != 0;
}
-inline bool ResourceId::is_valid_dynamic() const {
+inline bool ResourceId::is_valid() const {
return (id & 0x00ff0000u) != 0;
}
diff --git a/tools/aapt2/ResourceTable.cpp b/tools/aapt2/ResourceTable.cpp
index 1773b5a8addf..e0a9a31eee8b 100644
--- a/tools/aapt2/ResourceTable.cpp
+++ b/tools/aapt2/ResourceTable.cpp
@@ -398,7 +398,7 @@ bool ResourceTable::AddResourceImpl(const ResourceNameRef& name, const ResourceI
// Check for package names appearing twice with two different package ids
ResourceTablePackage* package = FindOrCreatePackage(name.package);
- if (res_id.is_valid_dynamic() && package->id && package->id.value() != res_id.package_id()) {
+ if (res_id.is_valid() && package->id && package->id.value() != res_id.package_id()) {
diag->Error(DiagMessage(source)
<< "trying to add resource '" << name << "' with ID " << res_id
<< " but package '" << package->name << "' already has ID "
@@ -407,9 +407,9 @@ bool ResourceTable::AddResourceImpl(const ResourceNameRef& name, const ResourceI
}
// Whether or not to error on duplicate resources
- bool check_id = validate_resources_ && res_id.is_valid_dynamic();
+ bool check_id = validate_resources_ && res_id.is_valid();
// Whether or not to create a duplicate resource if the id does not match
- bool use_id = !validate_resources_ && res_id.is_valid_dynamic();
+ bool use_id = !validate_resources_ && res_id.is_valid();
ResourceTableType* type = package->FindOrCreateType(name.type, use_id ? res_id.type_id()
: Maybe<uint8_t>());
@@ -463,7 +463,7 @@ bool ResourceTable::AddResourceImpl(const ResourceNameRef& name, const ResourceI
}
}
- if (res_id.is_valid_dynamic()) {
+ if (res_id.is_valid()) {
package->id = res_id.package_id();
type->id = res_id.type_id();
entry->id = res_id.entry_id();
@@ -504,7 +504,7 @@ bool ResourceTable::SetVisibilityImpl(const ResourceNameRef& name, const Visibil
// Check for package names appearing twice with two different package ids
ResourceTablePackage* package = FindOrCreatePackage(name.package);
- if (res_id.is_valid_dynamic() && package->id && package->id.value() != res_id.package_id()) {
+ if (res_id.is_valid() && package->id && package->id.value() != res_id.package_id()) {
diag->Error(DiagMessage(source)
<< "trying to add resource '" << name << "' with ID " << res_id
<< " but package '" << package->name << "' already has ID "
@@ -513,9 +513,9 @@ bool ResourceTable::SetVisibilityImpl(const ResourceNameRef& name, const Visibil
}
// Whether or not to error on duplicate resources
- bool check_id = validate_resources_ && res_id.is_valid_dynamic();
+ bool check_id = validate_resources_ && res_id.is_valid();
// Whether or not to create a duplicate resource if the id does not match
- bool use_id = !validate_resources_ && res_id.is_valid_dynamic();
+ bool use_id = !validate_resources_ && res_id.is_valid();
ResourceTableType* type = package->FindOrCreateType(name.type, use_id ? res_id.type_id()
: Maybe<uint8_t>());
@@ -541,7 +541,7 @@ bool ResourceTable::SetVisibilityImpl(const ResourceNameRef& name, const Visibil
return false;
}
- if (res_id.is_valid_dynamic()) {
+ if (res_id.is_valid()) {
package->id = res_id.package_id();
type->id = res_id.type_id();
entry->id = res_id.entry_id();
diff --git a/tools/aapt2/ResourceUtils.cpp b/tools/aapt2/ResourceUtils.cpp
index bd2ab5377311..3623b1112bc6 100644
--- a/tools/aapt2/ResourceUtils.cpp
+++ b/tools/aapt2/ResourceUtils.cpp
@@ -516,7 +516,7 @@ Maybe<ResourceId> ParseResourceId(const StringPiece& str) {
if (android::ResTable::stringToInt(str16.data(), str16.size(), &value)) {
if (value.dataType == android::Res_value::TYPE_INT_HEX) {
ResourceId id(value.data);
- if (id.is_valid_dynamic()) {
+ if (id.is_valid()) {
return id;
}
}
@@ -738,7 +738,13 @@ std::unique_ptr<Item> ParseBinaryResValue(const ResourceType& type, const Config
const android::Res_value& res_value,
StringPool* dst_pool) {
if (type == ResourceType::kId) {
- return util::make_unique<Id>();
+ if (res_value.dataType != android::Res_value::TYPE_REFERENCE &&
+ res_value.dataType != android::Res_value::TYPE_DYNAMIC_REFERENCE) {
+ // plain "id" resources are actually encoded as dummy values (aapt1 uses an empty string,
+ // while aapt2 uses a false boolean).
+ return util::make_unique<Id>();
+ }
+ // fall through to regular reference deserialization logic
}
const uint32_t data = util::DeviceToHost32(res_value.data);
diff --git a/tools/aapt2/ResourceValues.cpp b/tools/aapt2/ResourceValues.cpp
index 34b46c552e0c..4f0fa8ae29ba 100644
--- a/tools/aapt2/ResourceValues.cpp
+++ b/tools/aapt2/ResourceValues.cpp
@@ -117,7 +117,7 @@ bool Reference::Equals(const Value* value) const {
bool Reference::Flatten(android::Res_value* out_value) const {
const ResourceId resid = id.value_or_default(ResourceId(0));
- const bool dynamic = resid.is_valid_dynamic() && is_dynamic;
+ const bool dynamic = resid.is_valid() && is_dynamic;
if (reference_type == Reference::Type::kResource) {
if (dynamic) {
@@ -159,7 +159,7 @@ void Reference::Print(std::ostream* out) const {
*out << name.value();
}
- if (id && id.value().is_valid_dynamic()) {
+ if (id && id.value().is_valid()) {
if (name) {
*out << " ";
}
@@ -196,7 +196,7 @@ static void PrettyPrintReferenceImpl(const Reference& ref, bool print_package, P
printer->Print("/");
printer->Print(name.entry);
}
- } else if (ref.id && ref.id.value().is_valid_dynamic()) {
+ } else if (ref.id && ref.id.value().is_valid()) {
printer->Print(ref.id.value().to_string());
}
}
diff --git a/tools/aapt2/process/SymbolTable.cpp b/tools/aapt2/process/SymbolTable.cpp
index bc09f19b94d5..83e20b5833b9 100644
--- a/tools/aapt2/process/SymbolTable.cpp
+++ b/tools/aapt2/process/SymbolTable.cpp
@@ -340,7 +340,7 @@ std::unique_ptr<SymbolTable::Symbol> AssetManagerSymbolSource::FindByName(
}
res_id = asset_manager_.GetResourceId(real_name.to_string());
- if (res_id.is_valid() && asset_manager_.GetResourceFlags(res_id.id, &type_spec_flags)) {
+ if (res_id.is_valid_static() && asset_manager_.GetResourceFlags(res_id.id, &type_spec_flags)) {
found = true;
return false;
}
@@ -379,7 +379,7 @@ static Maybe<ResourceName> GetResourceName(android::AssetManager2& am,
std::unique_ptr<SymbolTable::Symbol> AssetManagerSymbolSource::FindById(
ResourceId id) {
- if (!id.is_valid()) {
+ if (!id.is_valid_static()) {
// Exit early and avoid the error logs from AssetManager.
return {};
}
diff --git a/tools/stats_log_api_gen/Android.bp b/tools/stats_log_api_gen/Android.bp
index 15c327852001..d3958a65c704 100644
--- a/tools/stats_log_api_gen/Android.bp
+++ b/tools/stats_log_api_gen/Android.bp
@@ -25,6 +25,8 @@ cc_binary_host {
"java_writer.cpp",
"java_writer_q.cpp",
"main.cpp",
+ "native_writer.cpp",
+ "native_writer_q.cpp",
"utils.cpp",
],
cflags: [
@@ -121,17 +123,5 @@ cc_library {
"libcutils",
],
static_libs: ["libstatssocket"],
- target: {
- android: {
- shared_libs: [
- "libutils",
- ],
- },
- host: {
- static_libs: [
- "libutils",
- ],
- },
- },
}
diff --git a/tools/stats_log_api_gen/Collation.cpp b/tools/stats_log_api_gen/Collation.cpp
index fa556010646c..0b82a3dcebc4 100644
--- a/tools/stats_log_api_gen/Collation.cpp
+++ b/tools/stats_log_api_gen/Collation.cpp
@@ -405,9 +405,9 @@ int collate_atoms(const Descriptor *descriptor, Atoms *atoms) {
atomDecl.whitelisted = true;
}
- if (atomField->options().HasExtension(os::statsd::log_from_module)) {
+ if (atomField->options().HasExtension(os::statsd::module)) {
atomDecl.hasModule = true;
- atomDecl.moduleName = atomField->options().GetExtension(os::statsd::log_from_module);
+ atomDecl.moduleName = atomField->options().GetExtension(os::statsd::module);
}
vector<java_type_t> signature;
diff --git a/tools/stats_log_api_gen/atoms_info_writer.h b/tools/stats_log_api_gen/atoms_info_writer.h
index bc677825181f..12ac862871ef 100644
--- a/tools/stats_log_api_gen/atoms_info_writer.h
+++ b/tools/stats_log_api_gen/atoms_info_writer.h
@@ -27,8 +27,7 @@ namespace stats_log_api_gen {
using namespace std;
int write_atoms_info_cpp(FILE* out, const Atoms& atoms, const string& namespaceStr,
- const string& importHeader, const string& statslogHeader
-);
+ const string& importHeader, const string& statslogHeader);
int write_atoms_info_header(FILE* out, const Atoms& atoms, const string& namespaceStr);
diff --git a/tools/stats_log_api_gen/java_writer.cpp b/tools/stats_log_api_gen/java_writer.cpp
index 712b48edbc1b..7f0872c02613 100644
--- a/tools/stats_log_api_gen/java_writer.cpp
+++ b/tools/stats_log_api_gen/java_writer.cpp
@@ -48,7 +48,8 @@ static int write_java_methods(
FILE* out,
const map<vector<java_type_t>, set<string>>& signatures_to_modules,
const AtomDecl &attributionDecl,
- const string& moduleName
+ const string& moduleName,
+ const bool supportQ
) {
for (auto signature_to_modules_it = signatures_to_modules.begin();
signature_to_modules_it != signatures_to_modules.end(); signature_to_modules_it++) {
@@ -82,8 +83,10 @@ static int write_java_methods(
// Print method body.
string indent("");
- if (DEFAULT_MODULE_NAME != moduleName) {
- fprintf(out, " if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) {\n");
+ if (supportQ) {
+ // TODO(b/146235828): Use just SDK_INT check once it is incremented from Q.
+ fprintf(out, " if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q ||\n");
+ fprintf(out, " Build.VERSION.CODENAME.equals(\"R\")) {\n");
indent = " ";
}
@@ -193,7 +196,7 @@ static int write_java_methods(
fprintf(out, "%s StatsLog.write(builder.build());\n", indent.c_str());
// Add support for writing using Q schema if this is not the default module.
- if (DEFAULT_MODULE_NAME != moduleName) {
+ if (supportQ) {
fprintf(out, " } else {\n");
fprintf(out, " QLogger.write(code");
argIndex = 1;
@@ -225,15 +228,17 @@ static int write_java_methods(
int write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl,
const string& moduleName, const string& javaClass,
- const string& javaPackage) {
+ const string& javaPackage, const bool supportQ) {
// Print prelude
fprintf(out, "// This file is autogenerated\n");
fprintf(out, "\n");
fprintf(out, "package %s;\n", javaPackage.c_str());
fprintf(out, "\n");
fprintf(out, "\n");
- fprintf(out, "import android.os.Build;\n");
- fprintf(out, "import android.os.SystemClock;\n");
+ if (supportQ) {
+ fprintf(out, "import android.os.Build;\n");
+ fprintf(out, "import android.os.SystemClock;\n");
+ }
if (DEFAULT_MODULE_NAME == moduleName) {
// Mainline modules don't use WorkSource logging.
@@ -271,12 +276,15 @@ int write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl &attribut
// Print write methods.
fprintf(out, " // Write methods\n");
- errors += write_java_methods(out, atoms.signatures_to_modules, attributionDecl, moduleName);
+ errors += write_java_methods(
+ out, atoms.signatures_to_modules, attributionDecl, moduleName, supportQ);
errors += write_java_non_chained_methods(
out, atoms.non_chained_signatures_to_modules, moduleName);
if (DEFAULT_MODULE_NAME == moduleName) {
errors += write_java_work_source_methods(out, atoms.signatures_to_modules, moduleName);
- } else {
+ }
+
+ if (supportQ) {
errors += write_java_q_logger_class(
out, atoms.signatures_to_modules, attributionDecl, moduleName);
}
diff --git a/tools/stats_log_api_gen/java_writer.h b/tools/stats_log_api_gen/java_writer.h
index 031266b31d07..9324b23e4025 100644
--- a/tools/stats_log_api_gen/java_writer.h
+++ b/tools/stats_log_api_gen/java_writer.h
@@ -32,8 +32,7 @@ using namespace std;
int write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl,
const string& moduleName, const string& javaClass,
- const string& javaPackage
-);
+ const string& javaPackage, const bool supportQ);
} // namespace stats_log_api_gen
} // namespace android
diff --git a/tools/stats_log_api_gen/java_writer_q.h b/tools/stats_log_api_gen/java_writer_q.h
index c8f4ccf71c91..96ac745beef8 100644
--- a/tools/stats_log_api_gen/java_writer_q.h
+++ b/tools/stats_log_api_gen/java_writer_q.h
@@ -37,22 +37,20 @@ int write_java_methods_q_schema(
const map<vector<java_type_t>, set<string>>& signatures_to_modules,
const AtomDecl &attributionDecl,
const string& moduleName,
- const string& indent
-);
+ const string& indent);
void write_java_helpers_for_q_schema_methods(
FILE * out,
const AtomDecl &attributionDecl,
const int requiredHelpers,
- const string& indent
-);
+ const string& indent);
#if defined(STATS_SCHEMA_LEGACY)
int write_stats_log_java_q(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl);
-int write_stats_log_java_q_for_module(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl,
- const string& moduleName, const string& javaClass,
- const string& javaPackage);
+int write_stats_log_java_q_for_module(FILE* out, const Atoms& atoms,
+ const AtomDecl &attributionDecl, const string& moduleName, const string& javaClass,
+ const string& javaPackage);
#endif
} // namespace stats_log_api_gen
} // namespace android
diff --git a/tools/stats_log_api_gen/main.cpp b/tools/stats_log_api_gen/main.cpp
index ad171da0511c..00a370484823 100644
--- a/tools/stats_log_api_gen/main.cpp
+++ b/tools/stats_log_api_gen/main.cpp
@@ -6,6 +6,7 @@
#include "java_writer.h"
#endif
#include "java_writer_q.h"
+#include "native_writer.h"
#include "utils.h"
#include "frameworks/base/cmds/statsd/src/atoms.pb.h"
@@ -27,496 +28,6 @@ namespace stats_log_api_gen {
using android::os::statsd::Atom;
-static int write_stats_log_cpp(FILE *out, const Atoms &atoms, const AtomDecl &attributionDecl,
- const string& moduleName, const string& cppNamespace,
- const string& importHeader) {
- // Print prelude
- fprintf(out, "// This file is autogenerated\n");
- fprintf(out, "\n");
-
- fprintf(out, "#include <mutex>\n");
- fprintf(out, "#include <chrono>\n");
- fprintf(out, "#include <thread>\n");
- fprintf(out, "#ifdef __ANDROID__\n");
- fprintf(out, "#include <cutils/properties.h>\n");
- fprintf(out, "#endif\n");
- fprintf(out, "#include <stats_event_list.h>\n");
- fprintf(out, "#include <log/log.h>\n");
- fprintf(out, "#include <%s>\n", importHeader.c_str());
- fprintf(out, "#include <utils/SystemClock.h>\n");
- fprintf(out, "\n");
-
- write_namespace(out, cppNamespace);
- fprintf(out, "// the single event tag id for all stats logs\n");
- fprintf(out, "const static int kStatsEventTag = 1937006964;\n");
- fprintf(out, "#ifdef __ANDROID__\n");
- fprintf(out, "const static bool kStatsdEnabled = property_get_bool(\"ro.statsd.enable\", true);\n");
- fprintf(out, "#else\n");
- fprintf(out, "const static bool kStatsdEnabled = false;\n");
- fprintf(out, "#endif\n");
-
- fprintf(out, "int64_t lastRetryTimestampNs = -1;\n");
- fprintf(out, "const int64_t kMinRetryIntervalNs = NS_PER_SEC * 60 * 20; // 20 minutes\n");
- fprintf(out, "static std::mutex mLogdRetryMutex;\n");
-
- // Print write methods
- fprintf(out, "\n");
- for (auto signature_to_modules_it = atoms.signatures_to_modules.begin();
- signature_to_modules_it != atoms.signatures_to_modules.end(); signature_to_modules_it++) {
- if (!signature_needed_for_module(signature_to_modules_it->second, moduleName)) {
- continue;
- }
- vector<java_type_t> signature = signature_to_modules_it->first;
- int argIndex;
-
- fprintf(out, "int\n");
- fprintf(out, "try_stats_write(int32_t code");
- argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature.begin();
- arg != signature.end(); arg++) {
- if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
- for (auto chainField : attributionDecl.fields) {
- if (chainField.javaType == JAVA_TYPE_STRING) {
- fprintf(out, ", const std::vector<%s>& %s",
- cpp_type_name(chainField.javaType),
- chainField.name.c_str());
- } else {
- fprintf(out, ", const %s* %s, size_t %s_length",
- cpp_type_name(chainField.javaType),
- chainField.name.c_str(), chainField.name.c_str());
- }
- }
- } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
- fprintf(out, ", const std::map<int, int32_t>& arg%d_1, "
- "const std::map<int, int64_t>& arg%d_2, "
- "const std::map<int, char const*>& arg%d_3, "
- "const std::map<int, float>& arg%d_4",
- argIndex, argIndex, argIndex, argIndex);
- } else {
- fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
- }
- argIndex++;
- }
- fprintf(out, ")\n");
-
- fprintf(out, "{\n");
- argIndex = 1;
- fprintf(out, " if (kStatsdEnabled) {\n");
- fprintf(out, " stats_event_list event(kStatsEventTag);\n");
- fprintf(out, " event << android::elapsedRealtimeNano();\n\n");
- fprintf(out, " event << code;\n\n");
- for (vector<java_type_t>::const_iterator arg = signature.begin();
- arg != signature.end(); arg++) {
- if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
- for (const auto &chainField : attributionDecl.fields) {
- if (chainField.javaType == JAVA_TYPE_STRING) {
- fprintf(out, " if (%s_length != %s.size()) {\n",
- attributionDecl.fields.front().name.c_str(), chainField.name.c_str());
- fprintf(out, " return -EINVAL;\n");
- fprintf(out, " }\n");
- }
- }
- fprintf(out, "\n event.begin();\n");
- fprintf(out, " for (size_t i = 0; i < %s_length; ++i) {\n",
- attributionDecl.fields.front().name.c_str());
- fprintf(out, " event.begin();\n");
- for (const auto &chainField : attributionDecl.fields) {
- if (chainField.javaType == JAVA_TYPE_STRING) {
- fprintf(out, " if (%s[i] != NULL) {\n", chainField.name.c_str());
- fprintf(out, " event << %s[i];\n", chainField.name.c_str());
- fprintf(out, " } else {\n");
- fprintf(out, " event << \"\";\n");
- fprintf(out, " }\n");
- } else {
- fprintf(out, " event << %s[i];\n", chainField.name.c_str());
- }
- }
- fprintf(out, " event.end();\n");
- fprintf(out, " }\n");
- fprintf(out, " event.end();\n\n");
- } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
- fprintf(out, " event.begin();\n\n");
- fprintf(out, " for (const auto& it : arg%d_1) {\n", argIndex);
- fprintf(out, " event.begin();\n");
- fprintf(out, " event << it.first;\n");
- fprintf(out, " event << it.second;\n");
- fprintf(out, " event.end();\n");
- fprintf(out, " }\n");
-
- fprintf(out, " for (const auto& it : arg%d_2) {\n", argIndex);
- fprintf(out, " event.begin();\n");
- fprintf(out, " event << it.first;\n");
- fprintf(out, " event << it.second;\n");
- fprintf(out, " event.end();\n");
- fprintf(out, " }\n");
-
- fprintf(out, " for (const auto& it : arg%d_3) {\n", argIndex);
- fprintf(out, " event.begin();\n");
- fprintf(out, " event << it.first;\n");
- fprintf(out, " event << it.second;\n");
- fprintf(out, " event.end();\n");
- fprintf(out, " }\n");
-
- fprintf(out, " for (const auto& it : arg%d_4) {\n", argIndex);
- fprintf(out, " event.begin();\n");
- fprintf(out, " event << it.first;\n");
- fprintf(out, " event << it.second;\n");
- fprintf(out, " event.end();\n");
- fprintf(out, " }\n");
-
- fprintf(out, " event.end();\n\n");
- } else if (*arg == JAVA_TYPE_BYTE_ARRAY) {
- fprintf(out,
- " event.AppendCharArray(arg%d.arg, "
- "arg%d.arg_length);\n",
- argIndex, argIndex);
- } else {
- if (*arg == JAVA_TYPE_STRING) {
- fprintf(out, " if (arg%d == NULL) {\n", argIndex);
- fprintf(out, " arg%d = \"\";\n", argIndex);
- fprintf(out, " }\n");
- }
- fprintf(out, " event << arg%d;\n", argIndex);
- }
- argIndex++;
- }
-
- fprintf(out, " return event.write(LOG_ID_STATS);\n");
- fprintf(out, " } else {\n");
- fprintf(out, " return 1;\n");
- fprintf(out, " }\n");
- fprintf(out, "}\n");
- fprintf(out, "\n");
- }
-
- for (auto signature_to_modules_it = atoms.signatures_to_modules.begin();
- signature_to_modules_it != atoms.signatures_to_modules.end(); signature_to_modules_it++) {
- if (!signature_needed_for_module(signature_to_modules_it->second, moduleName)) {
- continue;
- }
- vector<java_type_t> signature = signature_to_modules_it->first;
- int argIndex;
-
- fprintf(out, "int\n");
- fprintf(out, "stats_write(int32_t code");
- argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature.begin();
- arg != signature.end(); arg++) {
- if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
- for (auto chainField : attributionDecl.fields) {
- if (chainField.javaType == JAVA_TYPE_STRING) {
- fprintf(out, ", const std::vector<%s>& %s",
- cpp_type_name(chainField.javaType),
- chainField.name.c_str());
- } else {
- fprintf(out, ", const %s* %s, size_t %s_length",
- cpp_type_name(chainField.javaType),
- chainField.name.c_str(), chainField.name.c_str());
- }
- }
- } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
- fprintf(out,
- ", const std::map<int, int32_t>& arg%d_1, "
- "const std::map<int, int64_t>& arg%d_2, "
- "const std::map<int, char const*>& arg%d_3, "
- "const std::map<int, float>& arg%d_4",
- argIndex, argIndex, argIndex, argIndex);
- } else {
- fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
- }
- argIndex++;
- }
- fprintf(out, ")\n");
-
- fprintf(out, "{\n");
- fprintf(out, " int ret = 0;\n");
-
- fprintf(out, " for(int retry = 0; retry < 2; ++retry) {\n");
- fprintf(out, " ret = try_stats_write(code");
-
- argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature.begin();
- arg != signature.end(); arg++) {
- if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
- for (auto chainField : attributionDecl.fields) {
- if (chainField.javaType == JAVA_TYPE_STRING) {
- fprintf(out, ", %s",
- chainField.name.c_str());
- } else {
- fprintf(out, ", %s, %s_length",
- chainField.name.c_str(), chainField.name.c_str());
- }
- }
- } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
- fprintf(out, ", arg%d_1, arg%d_2, arg%d_3, arg%d_4", argIndex,
- argIndex, argIndex, argIndex);
- } else {
- fprintf(out, ", arg%d", argIndex);
- }
- argIndex++;
- }
- fprintf(out, ");\n");
- fprintf(out, " if (ret >= 0) { break; }\n");
-
- fprintf(out, " {\n");
- fprintf(out, " std::lock_guard<std::mutex> lock(mLogdRetryMutex);\n");
- fprintf(out, " if ((android::elapsedRealtimeNano() - lastRetryTimestampNs) <= "
- "kMinRetryIntervalNs) break;\n");
- fprintf(out, " lastRetryTimestampNs = android::elapsedRealtimeNano();\n");
- fprintf(out, " }\n");
- fprintf(out, " std::this_thread::sleep_for(std::chrono::milliseconds(10));\n");
- fprintf(out, " }\n");
- fprintf(out, " if (ret < 0) {\n");
- fprintf(out, " note_log_drop(ret, code);\n");
- fprintf(out, " }\n");
- fprintf(out, " return ret;\n");
- fprintf(out, "}\n");
- fprintf(out, "\n");
- }
-
- for (auto signature_it = atoms.non_chained_signatures_to_modules.begin();
- signature_it != atoms.non_chained_signatures_to_modules.end(); signature_it++) {
- if (!signature_needed_for_module(signature_it->second, moduleName)) {
- continue;
- }
- vector<java_type_t> signature = signature_it->first;
- int argIndex;
-
- fprintf(out, "int\n");
- fprintf(out, "try_stats_write_non_chained(int32_t code");
- argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature.begin();
- arg != signature.end(); arg++) {
- fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
- argIndex++;
- }
- fprintf(out, ")\n");
-
- fprintf(out, "{\n");
- argIndex = 1;
- fprintf(out, " if (kStatsdEnabled) {\n");
- fprintf(out, " stats_event_list event(kStatsEventTag);\n");
- fprintf(out, " event << android::elapsedRealtimeNano();\n\n");
- fprintf(out, " event << code;\n\n");
- for (vector<java_type_t>::const_iterator arg = signature.begin();
- arg != signature.end(); arg++) {
- if (argIndex == 1) {
- fprintf(out, " event.begin();\n\n");
- fprintf(out, " event.begin();\n");
- }
- if (*arg == JAVA_TYPE_STRING) {
- fprintf(out, " if (arg%d == NULL) {\n", argIndex);
- fprintf(out, " arg%d = \"\";\n", argIndex);
- fprintf(out, " }\n");
- }
- if (*arg == JAVA_TYPE_BYTE_ARRAY) {
- fprintf(out,
- " event.AppendCharArray(arg%d.arg, "
- "arg%d.arg_length);",
- argIndex, argIndex);
- } else {
- fprintf(out, " event << arg%d;\n", argIndex);
- }
- if (argIndex == 2) {
- fprintf(out, " event.end();\n\n");
- fprintf(out, " event.end();\n\n");
- }
- argIndex++;
- }
-
- fprintf(out, " return event.write(LOG_ID_STATS);\n");
- fprintf(out, " } else {\n");
- fprintf(out, " return 1;\n");
- fprintf(out, " }\n");
- fprintf(out, "}\n");
- fprintf(out, "\n");
- }
-
- for (auto signature_it = atoms.non_chained_signatures_to_modules.begin();
- signature_it != atoms.non_chained_signatures_to_modules.end(); signature_it++) {
- if (!signature_needed_for_module(signature_it->second, moduleName)) {
- continue;
- }
- vector<java_type_t> signature = signature_it->first;
- int argIndex;
-
- fprintf(out, "int\n");
- fprintf(out, "stats_write_non_chained(int32_t code");
- argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature.begin();
- arg != signature.end(); arg++) {
- fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
- argIndex++;
- }
- fprintf(out, ")\n");
-
- fprintf(out, "{\n");
-
- fprintf(out, " int ret = 0;\n");
- fprintf(out, " for(int retry = 0; retry < 2; ++retry) {\n");
- fprintf(out, " ret = try_stats_write_non_chained(code");
-
- argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature.begin();
- arg != signature.end(); arg++) {
- fprintf(out, ", arg%d", argIndex);
- argIndex++;
- }
- fprintf(out, ");\n");
- fprintf(out, " if (ret >= 0) { break; }\n");
-
- fprintf(out, " {\n");
- fprintf(out, " std::lock_guard<std::mutex> lock(mLogdRetryMutex);\n");
- fprintf(out, " if ((android::elapsedRealtimeNano() - lastRetryTimestampNs) <= "
- "kMinRetryIntervalNs) break;\n");
- fprintf(out, " lastRetryTimestampNs = android::elapsedRealtimeNano();\n");
- fprintf(out, " }\n");
-
- fprintf(out, " std::this_thread::sleep_for(std::chrono::milliseconds(10));\n");
- fprintf(out, " }\n");
- fprintf(out, " if (ret < 0) {\n");
- fprintf(out, " note_log_drop(ret, code);\n");
- fprintf(out, " }\n");
- fprintf(out, " return ret;\n\n");
- fprintf(out, "}\n");
-
- fprintf(out, "\n");
- }
-
-
- // Print footer
- fprintf(out, "\n");
- write_closing_namespace(out, cppNamespace);
-
- return 0;
-}
-
-static void write_cpp_method_header(
- FILE* out,
- const string& method_name,
- const map<vector<java_type_t>, set<string>>& signatures_to_modules,
- const AtomDecl &attributionDecl, const string& moduleName) {
-
- for (auto signature_to_modules_it = signatures_to_modules.begin();
- signature_to_modules_it != signatures_to_modules.end(); signature_to_modules_it++) {
- // Skip if this signature is not needed for the module.
- if (!signature_needed_for_module(signature_to_modules_it->second, moduleName)) {
- continue;
- }
-
- vector<java_type_t> signature = signature_to_modules_it->first;
- fprintf(out, "int %s(int32_t code", method_name.c_str());
- int argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature.begin();
- arg != signature.end(); arg++) {
- if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
- for (auto chainField : attributionDecl.fields) {
- if (chainField.javaType == JAVA_TYPE_STRING) {
- fprintf(out, ", const std::vector<%s>& %s",
- cpp_type_name(chainField.javaType), chainField.name.c_str());
- } else {
- fprintf(out, ", const %s* %s, size_t %s_length",
- cpp_type_name(chainField.javaType),
- chainField.name.c_str(), chainField.name.c_str());
- }
- }
- } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
- fprintf(out, ", const std::map<int, int32_t>& arg%d_1, "
- "const std::map<int, int64_t>& arg%d_2, "
- "const std::map<int, char const*>& arg%d_3, "
- "const std::map<int, float>& arg%d_4",
- argIndex, argIndex, argIndex, argIndex);
- } else {
- fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
- }
- argIndex++;
- }
- fprintf(out, ");\n");
-
- }
-}
-
-static int
-write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl,
- const string& moduleName, const string& cppNamespace)
-{
- // Print prelude
- fprintf(out, "// This file is autogenerated\n");
- fprintf(out, "\n");
- fprintf(out, "#pragma once\n");
- fprintf(out, "\n");
- fprintf(out, "#include <stdint.h>\n");
- fprintf(out, "#include <vector>\n");
- fprintf(out, "#include <map>\n");
- fprintf(out, "#include <set>\n");
- fprintf(out, "\n");
-
- write_namespace(out, cppNamespace);
- fprintf(out, "\n");
- fprintf(out, "/*\n");
- fprintf(out, " * API For logging statistics events.\n");
- fprintf(out, " */\n");
- fprintf(out, "\n");
-
- write_native_atom_constants(out, atoms, attributionDecl, moduleName);
-
- // Print constants for the enum values.
- fprintf(out, "//\n");
- fprintf(out, "// Constants for enum values\n");
- fprintf(out, "//\n\n");
- for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
- atom != atoms.decls.end(); atom++) {
- // Skip if the atom is not needed for the module.
- if (!atom_needed_for_module(*atom, moduleName)) {
- continue;
- }
-
- for (vector<AtomField>::const_iterator field = atom->fields.begin();
- field != atom->fields.end(); field++) {
- if (field->javaType == JAVA_TYPE_ENUM) {
- fprintf(out, "// Values for %s.%s\n", atom->message.c_str(),
- field->name.c_str());
- for (map<int, string>::const_iterator value = field->enumValues.begin();
- value != field->enumValues.end(); value++) {
- fprintf(out, "const int32_t %s__%s__%s = %d;\n",
- make_constant_name(atom->message).c_str(),
- make_constant_name(field->name).c_str(),
- make_constant_name(value->second).c_str(),
- value->first);
- }
- fprintf(out, "\n");
- }
- }
- }
-
- fprintf(out, "struct BytesField {\n");
- fprintf(out,
- " BytesField(char const* array, size_t len) : arg(array), "
- "arg_length(len) {}\n");
- fprintf(out, " char const* arg;\n");
- fprintf(out, " size_t arg_length;\n");
- fprintf(out, "};\n");
- fprintf(out, "\n");
-
- // Print write methods
- fprintf(out, "//\n");
- fprintf(out, "// Write methods\n");
- fprintf(out, "//\n");
- write_cpp_method_header(out, "stats_write", atoms.signatures_to_modules, attributionDecl,
- moduleName);
-
- fprintf(out, "//\n");
- fprintf(out, "// Write flattened methods\n");
- fprintf(out, "//\n");
- write_cpp_method_header(out, "stats_write_non_chained", atoms.non_chained_signatures_to_modules,
- attributionDecl, moduleName);
-
- fprintf(out, "\n");
- write_closing_namespace(out, cppNamespace);
-
- return 0;
-}
-
// Hide the JNI write helpers that are not used in the new schema.
// TODO(b/145100015): Remove this and other JNI related functionality once StatsEvent migration is
// complete.
@@ -999,7 +510,9 @@ print_usage()
fprintf(stderr, " required for java with module\n");
fprintf(stderr, " --javaClass CLASS the class name of the java class.\n");
fprintf(stderr, " Optional for Java with module.\n");
- fprintf(stderr, " Default is \"StatsLogInternal\"\n");}
+ fprintf(stderr, " Default is \"StatsLogInternal\"\n");
+ fprintf(stderr, " --supportQ Include support for Android Q.\n");
+}
/**
* Do the argument parsing and execute the tasks.
@@ -1020,6 +533,7 @@ run(int argc, char const*const* argv)
string atomsInfoCppHeaderImport = DEFAULT_ATOMS_INFO_CPP_HEADER_IMPORT;
string javaPackage = DEFAULT_JAVA_PACKAGE;
string javaClass = DEFAULT_JAVA_CLASS;
+ bool supportQ = false;
int index = 1;
while (index < argc) {
@@ -1110,6 +624,8 @@ run(int argc, char const*const* argv)
return 1;
}
atomsInfoCppHeaderImport = argv[index];
+ } else if (0 == strcmp("--supportQ", argv[index])) {
+ supportQ = true;
}
index++;
@@ -1125,6 +641,12 @@ run(int argc, char const*const* argv)
return 1;
}
+ if (DEFAULT_MODULE_NAME == moduleName && supportQ) {
+ // Support for Q schema is not needed for default module.
+ fprintf(stderr, "%s cannot support Q schema\n", moduleName.c_str());
+ return 1;
+ }
+
// Collate the parameters
Atoms atoms;
int errorCount = collate_atoms(Atom::descriptor(), &atoms);
@@ -1179,7 +701,7 @@ run(int argc, char const*const* argv)
return 1;
}
errorCount = android::stats_log_api_gen::write_stats_log_cpp(
- out, atoms, attributionDecl, moduleName, cppNamespace, cppHeaderImport);
+ out, atoms, attributionDecl, moduleName, cppNamespace, cppHeaderImport, supportQ);
fclose(out);
}
@@ -1227,7 +749,7 @@ run(int argc, char const*const* argv)
javaPackage = "android.util";
}
errorCount = android::stats_log_api_gen::write_stats_log_java(
- out, atoms, attributionDecl, moduleName, javaClass, javaPackage);
+ out, atoms, attributionDecl, moduleName, javaClass, javaPackage, supportQ);
#endif
fclose(out);
diff --git a/tools/stats_log_api_gen/native_writer.cpp b/tools/stats_log_api_gen/native_writer.cpp
new file mode 100644
index 000000000000..c7a34feff94b
--- /dev/null
+++ b/tools/stats_log_api_gen/native_writer.cpp
@@ -0,0 +1,342 @@
+/*
+ * Copyright (C) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "native_writer.h"
+#include "native_writer_q.h"
+#include "utils.h"
+
+namespace android {
+namespace stats_log_api_gen {
+
+#if !defined(STATS_SCHEMA_LEGACY)
+static void write_native_key_value_pairs_for_type(FILE* out, const int argIndex,
+ const int typeIndex, const string& type, const string& valueFieldName) {
+ fprintf(out, " for (const auto& it : arg%d_%d) {\n", argIndex, typeIndex);
+ fprintf(out, " pairs.push_back("
+ "{ .key = it.first, .valueType = %s, .%s = it.second });\n",
+ type.c_str(), valueFieldName.c_str());
+ fprintf(out, " }\n");
+
+}
+
+static int write_native_stats_write_methods(FILE* out, const Atoms& atoms,
+ const AtomDecl& attributionDecl, const string& moduleName, const bool supportQ) {
+ fprintf(out, "\n");
+ for (auto signature_to_modules_it = atoms.signatures_to_modules.begin();
+ signature_to_modules_it != atoms.signatures_to_modules.end(); signature_to_modules_it++) {
+ if (!signature_needed_for_module(signature_to_modules_it->second, moduleName)) {
+ continue;
+ }
+ vector<java_type_t> signature = signature_to_modules_it->first;
+
+ write_native_method_signature(out, "int stats_write", signature,
+ attributionDecl, " {");
+
+ int argIndex = 1;
+ if (supportQ) {
+ fprintf(out, " StatsEventCompat event;\n");
+ fprintf(out, " event.setAtomId(code);\n");
+ for (vector<java_type_t>::const_iterator arg = signature.begin();
+ arg != signature.end(); arg++) {
+ switch (*arg) {
+ case JAVA_TYPE_ATTRIBUTION_CHAIN: {
+ const char* uidName = attributionDecl.fields.front().name.c_str();
+ const char* tagName = attributionDecl.fields.back().name.c_str();
+ fprintf(out, " event.writeAttributionChain(%s, %s_length, %s);\n",
+ uidName, uidName, tagName);
+ break;
+ }
+ case JAVA_TYPE_KEY_VALUE_PAIR:
+ fprintf(out, " event.writeKeyValuePairs("
+ "arg%d_1, arg%d_2, arg%d_3, arg%d_4);\n",
+ argIndex, argIndex, argIndex, argIndex);
+ break;
+ case JAVA_TYPE_BYTE_ARRAY:
+ fprintf(out, " event.writeByteArray(arg%d.arg, arg%d.arg_length);\n",
+ argIndex, argIndex);
+ break;
+ case JAVA_TYPE_BOOLEAN:
+ fprintf(out, " event.writeBool(arg%d);\n", argIndex);
+ break;
+ case JAVA_TYPE_INT: // Fall through.
+ case JAVA_TYPE_ENUM:
+ fprintf(out, " event.writeInt32(arg%d);\n", argIndex);
+ break;
+ case JAVA_TYPE_FLOAT:
+ fprintf(out, " event.writeFloat(arg%d);\n", argIndex);
+ break;
+ case JAVA_TYPE_LONG:
+ fprintf(out, " event.writeInt64(arg%d);\n", argIndex);
+ break;
+ case JAVA_TYPE_STRING:
+ fprintf(out, " event.writeString(arg%d);\n", argIndex);
+ break;
+ default:
+ // Unsupported types: OBJECT, DOUBLE.
+ fprintf(stderr, "Encountered unsupported type.");
+ return 1;
+ }
+ argIndex++;
+ }
+ fprintf(out, " return event.writeToSocket();\n");
+ } else {
+ fprintf(out, " struct stats_event* event = stats_event_obtain();\n");
+ fprintf(out, " stats_event_set_atom_id(event, code);\n");
+ for (vector<java_type_t>::const_iterator arg = signature.begin();
+ arg != signature.end(); arg++) {
+ switch (*arg) {
+ case JAVA_TYPE_ATTRIBUTION_CHAIN: {
+ const char* uidName = attributionDecl.fields.front().name.c_str();
+ const char* tagName = attributionDecl.fields.back().name.c_str();
+ fprintf(out,
+ " stats_event_write_attribution_chain(event, "
+ "reinterpret_cast<const uint32_t*>(%s), %s.data(), "
+ "static_cast<uint8_t>(%s_length));\n",
+ uidName, tagName, uidName);
+ break;
+ }
+ case JAVA_TYPE_KEY_VALUE_PAIR:
+ fprintf(out, " std::vector<key_value_pair> pairs;\n");
+ write_native_key_value_pairs_for_type(
+ out, argIndex, 1, "INT32_TYPE", "int32Value");
+ write_native_key_value_pairs_for_type(
+ out, argIndex, 2, "INT64_TYPE", "int64Value");
+ write_native_key_value_pairs_for_type(
+ out, argIndex, 3, "STRING_TYPE", "stringValue");
+ write_native_key_value_pairs_for_type(
+ out, argIndex, 4, "FLOAT_TYPE", "floatValue");
+ fprintf(out,
+ " stats_event_write_key_value_pairs(event, pairs.data(), "
+ "static_cast<uint8_t>(pairs.size()));\n");
+ break;
+ case JAVA_TYPE_BYTE_ARRAY:
+ fprintf(out,
+ " stats_event_write_byte_array(event, "
+ "reinterpret_cast<const uint8_t*>(arg%d.arg), arg%d.arg_length);\n",
+ argIndex, argIndex);
+ break;
+ case JAVA_TYPE_BOOLEAN:
+ fprintf(out, " stats_event_write_bool(event, arg%d);\n", argIndex);
+ break;
+ case JAVA_TYPE_INT: // Fall through.
+ case JAVA_TYPE_ENUM:
+ fprintf(out, " stats_event_write_int32(event, arg%d);\n", argIndex);
+ break;
+ case JAVA_TYPE_FLOAT:
+ fprintf(out, " stats_event_write_float(event, arg%d);\n", argIndex);
+ break;
+ case JAVA_TYPE_LONG:
+ fprintf(out, " stats_event_write_int64(event, arg%d);\n", argIndex);
+ break;
+ case JAVA_TYPE_STRING:
+ fprintf(out, " stats_event_write_string8(event, arg%d);\n", argIndex);
+ break;
+ default:
+ // Unsupported types: OBJECT, DOUBLE.
+ fprintf(stderr, "Encountered unsupported type.");
+ return 1;
+ }
+ argIndex++;
+ }
+ fprintf(out, " const int ret = stats_event_write(event);\n");
+ fprintf(out, " stats_event_release(event);\n");
+ fprintf(out, " return ret;\n");
+ }
+ fprintf(out, "}\n\n");
+ }
+ return 0;
+}
+
+static void write_native_stats_write_non_chained_methods(FILE* out, const Atoms& atoms,
+ const AtomDecl& attributionDecl, const string& moduleName) {
+ fprintf(out, "\n");
+ for (auto signature_it = atoms.non_chained_signatures_to_modules.begin();
+ signature_it != atoms.non_chained_signatures_to_modules.end(); signature_it++) {
+ if (!signature_needed_for_module(signature_it->second, moduleName)) {
+ continue;
+ }
+ vector<java_type_t> signature = signature_it->first;
+
+ write_native_method_signature(out, "int stats_write_non_chained", signature,
+ attributionDecl, " {");
+
+ vector<java_type_t> newSignature;
+
+ // First two args form the attribution node so size goes down by 1.
+ newSignature.reserve(signature.size() - 1);
+
+ // First arg is Attribution Chain.
+ newSignature.push_back(JAVA_TYPE_ATTRIBUTION_CHAIN);
+
+ // Followed by the originial signature except the first 2 args.
+ newSignature.insert(newSignature.end(), signature.begin() + 2, signature.end());
+
+ const char* uidName = attributionDecl.fields.front().name.c_str();
+ const char* tagName = attributionDecl.fields.back().name.c_str();
+ fprintf(out, " const int32_t* %s = &arg1;\n", uidName);
+ fprintf(out, " const size_t %s_length = 1;\n", uidName);
+ fprintf(out, " const std::vector<char const*> %s(1, arg2);\n", tagName);
+ fprintf(out, " return ");
+ write_native_method_call(out, "stats_write", newSignature, attributionDecl, 2);
+
+ fprintf(out, "}\n\n");
+ }
+
+}
+#endif
+
+static void write_native_method_header(
+ FILE* out,
+ const string& methodName,
+ const map<vector<java_type_t>, set<string>>& signatures_to_modules,
+ const AtomDecl &attributionDecl, const string& moduleName) {
+
+ for (auto signature_to_modules_it = signatures_to_modules.begin();
+ signature_to_modules_it != signatures_to_modules.end(); signature_to_modules_it++) {
+ // Skip if this signature is not needed for the module.
+ if (!signature_needed_for_module(signature_to_modules_it->second, moduleName)) {
+ continue;
+ }
+
+ vector<java_type_t> signature = signature_to_modules_it->first;
+ write_native_method_signature(out, methodName, signature, attributionDecl, ";");
+ }
+}
+
+int write_stats_log_cpp(FILE *out, const Atoms &atoms, const AtomDecl &attributionDecl,
+ const string& moduleName, const string& cppNamespace,
+ const string& importHeader, const bool supportQ) {
+ // Print prelude
+ fprintf(out, "// This file is autogenerated\n");
+ fprintf(out, "\n");
+
+ fprintf(out, "#include <%s>\n", importHeader.c_str());
+#if defined(STATS_SCHEMA_LEGACY)
+ (void)supportQ; // Workaround for unused parameter error.
+ write_native_cpp_includes_q(out);
+#else
+ if (supportQ) {
+ fprintf(out, "#include <StatsEventCompat.h>\n");
+ } else {
+ fprintf(out, "#include <stats_event.h>\n");
+ }
+#endif
+
+ fprintf(out, "\n");
+ write_namespace(out, cppNamespace);
+
+#if defined(STATS_SCHEMA_LEGACY)
+ write_native_stats_log_cpp_globals_q(out);
+ write_native_get_timestamp_ns_q(out);
+ write_native_try_stats_write_methods_q(out, atoms, attributionDecl, moduleName);
+ write_native_stats_write_methods_q(out, "int stats_write", atoms, attributionDecl, moduleName,
+ "try_stats_write");
+ write_native_try_stats_write_non_chained_methods_q(out, atoms, attributionDecl, moduleName);
+ write_native_stats_write_non_chained_methods_q(out, "int stats_write_non_chained", atoms,
+ attributionDecl, moduleName, "try_stats_write_non_chained");
+#else
+ write_native_stats_write_methods(out, atoms, attributionDecl, moduleName, supportQ);
+ write_native_stats_write_non_chained_methods(out, atoms, attributionDecl, moduleName);
+#endif
+
+ // Print footer
+ fprintf(out, "\n");
+ write_closing_namespace(out, cppNamespace);
+
+ return 0;
+}
+
+int write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl,
+ const string& moduleName, const string& cppNamespace) {
+ // Print prelude
+ fprintf(out, "// This file is autogenerated\n");
+ fprintf(out, "\n");
+ fprintf(out, "#pragma once\n");
+ fprintf(out, "\n");
+ fprintf(out, "#include <stdint.h>\n");
+ fprintf(out, "#include <vector>\n");
+ fprintf(out, "#include <map>\n");
+ fprintf(out, "#include <set>\n");
+ fprintf(out, "\n");
+
+ write_namespace(out, cppNamespace);
+ fprintf(out, "\n");
+ fprintf(out, "/*\n");
+ fprintf(out, " * API For logging statistics events.\n");
+ fprintf(out, " */\n");
+ fprintf(out, "\n");
+
+ write_native_atom_constants(out, atoms, attributionDecl, moduleName);
+
+ // Print constants for the enum values.
+ fprintf(out, "//\n");
+ fprintf(out, "// Constants for enum values\n");
+ fprintf(out, "//\n\n");
+ for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
+ atom != atoms.decls.end(); atom++) {
+ // Skip if the atom is not needed for the module.
+ if (!atom_needed_for_module(*atom, moduleName)) {
+ continue;
+ }
+
+ for (vector<AtomField>::const_iterator field = atom->fields.begin();
+ field != atom->fields.end(); field++) {
+ if (field->javaType == JAVA_TYPE_ENUM) {
+ fprintf(out, "// Values for %s.%s\n", atom->message.c_str(),
+ field->name.c_str());
+ for (map<int, string>::const_iterator value = field->enumValues.begin();
+ value != field->enumValues.end(); value++) {
+ fprintf(out, "const int32_t %s__%s__%s = %d;\n",
+ make_constant_name(atom->message).c_str(),
+ make_constant_name(field->name).c_str(),
+ make_constant_name(value->second).c_str(),
+ value->first);
+ }
+ fprintf(out, "\n");
+ }
+ }
+ }
+
+ fprintf(out, "struct BytesField {\n");
+ fprintf(out,
+ " BytesField(char const* array, size_t len) : arg(array), "
+ "arg_length(len) {}\n");
+ fprintf(out, " char const* arg;\n");
+ fprintf(out, " size_t arg_length;\n");
+ fprintf(out, "};\n");
+ fprintf(out, "\n");
+
+ // Print write methods
+ fprintf(out, "//\n");
+ fprintf(out, "// Write methods\n");
+ fprintf(out, "//\n");
+ write_native_method_header(out, "int stats_write", atoms.signatures_to_modules, attributionDecl,
+ moduleName);
+
+ fprintf(out, "//\n");
+ fprintf(out, "// Write flattened methods\n");
+ fprintf(out, "//\n");
+ write_native_method_header(out, "int stats_write_non_chained",
+ atoms.non_chained_signatures_to_modules, attributionDecl, moduleName);
+
+ fprintf(out, "\n");
+ write_closing_namespace(out, cppNamespace);
+
+ return 0;
+}
+
+} // namespace stats_log_api_gen
+} // namespace android
diff --git a/tools/stats_log_api_gen/native_writer.h b/tools/stats_log_api_gen/native_writer.h
new file mode 100644
index 000000000000..aafa96ece2d0
--- /dev/null
+++ b/tools/stats_log_api_gen/native_writer.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "Collation.h"
+
+#include <stdio.h>
+#include <string.h>
+
+namespace android {
+namespace stats_log_api_gen {
+
+using namespace std;
+
+int write_stats_log_cpp(FILE *out, const Atoms &atoms, const AtomDecl &attributionDecl,
+ const string& moduleName, const string& cppNamespace, const string& importHeader,
+ const bool supportQ);
+
+int write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl,
+ const string& moduleName, const string& cppNamespace);
+
+} // namespace stats_log_api_gen
+} // namespace android
diff --git a/tools/stats_log_api_gen/native_writer_q.cpp b/tools/stats_log_api_gen/native_writer_q.cpp
new file mode 100644
index 000000000000..299873dad975
--- /dev/null
+++ b/tools/stats_log_api_gen/native_writer_q.cpp
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "native_writer_q.h"
+#include "utils.h"
+
+namespace android {
+namespace stats_log_api_gen {
+
+static void write_native_stats_write_body_q(FILE* out, const vector<java_type_t>& signature,
+ const AtomDecl& attributionDecl, const string& indent, const string& tryMethodName) {
+ fprintf(out, "%sint ret = 0;\n", indent.c_str());
+
+ fprintf(out, "%sfor(int retry = 0; retry < 2; ++retry) {\n", indent.c_str());
+ fprintf(out, "%s ret = ", indent.c_str());
+ write_native_method_call(out, tryMethodName, signature, attributionDecl);
+ fprintf(out, "%s if (ret >= 0) { break; }\n", indent.c_str());
+
+ fprintf(out, "%s {\n", indent.c_str());
+ fprintf(out, "%s std::lock_guard<std::mutex> lock(mLogdRetryMutex);\n", indent.c_str());
+ fprintf(out, "%s if ((get_elapsed_realtime_ns() - lastRetryTimestampNs) <= "
+ "kMinRetryIntervalNs) break;\n", indent.c_str());
+ fprintf(out, "%s lastRetryTimestampNs = get_elapsed_realtime_ns();\n",
+ indent.c_str());
+ fprintf(out, "%s }\n", indent.c_str());
+ fprintf(out, "%s std::this_thread::sleep_for(std::chrono::milliseconds(10));\n",
+ indent.c_str());
+ fprintf(out, "%s}\n", indent.c_str());
+ fprintf(out, "%sif (ret < 0) {\n", indent.c_str());
+ fprintf(out, "%s note_log_drop(ret, code);\n", indent.c_str());
+ fprintf(out, "%s}\n", indent.c_str());
+ fprintf(out, "%sreturn ret;\n", indent.c_str());
+}
+
+void write_native_cpp_includes_q(FILE* out) {
+ fprintf(out, "#include <mutex>\n");
+ fprintf(out, "#include <chrono>\n");
+ fprintf(out, "#include <thread>\n");
+ fprintf(out, "#ifdef __ANDROID__\n");
+ fprintf(out, "#include <cutils/properties.h>\n");
+ fprintf(out, "#endif\n");
+ fprintf(out, "#include <stats_event_list.h>\n");
+ fprintf(out, "#include <log/log.h>\n");
+ fprintf(out, "#include <time.h>\n");
+}
+
+void write_native_get_timestamp_ns_q(FILE* out) {
+ fprintf(out, "\n");
+ fprintf(out, "static int64_t get_elapsed_realtime_ns() {\n");
+ fprintf(out, " struct timespec t;\n");
+ fprintf(out, " t.tv_sec = t.tv_nsec = 0;\n");
+ fprintf(out, " clock_gettime(CLOCK_BOOTTIME, &t);\n");
+ fprintf(out, " return (int64_t)t.tv_sec * 1000000000LL + t.tv_nsec;\n");
+ fprintf(out, "}\n");
+}
+
+void write_native_stats_log_cpp_globals_q(FILE* out) {
+ fprintf(out, "// the single event tag id for all stats logs\n");
+ fprintf(out, "const static int kStatsEventTag = 1937006964;\n");
+ fprintf(out, "#ifdef __ANDROID__\n");
+ fprintf(out,
+ "const static bool kStatsdEnabled = property_get_bool(\"ro.statsd.enable\", true);\n");
+ fprintf(out, "#else\n");
+ fprintf(out, "const static bool kStatsdEnabled = false;\n");
+ fprintf(out, "#endif\n");
+
+ fprintf(out, "int64_t lastRetryTimestampNs = -1;\n");
+ fprintf(out, "const int64_t kMinRetryIntervalNs = NS_PER_SEC * 60 * 20; // 20 minutes\n");
+ fprintf(out, "static std::mutex mLogdRetryMutex;\n");
+}
+
+void write_native_try_stats_write_methods_q(FILE* out, const Atoms& atoms,
+ const AtomDecl& attributionDecl, const string& moduleName) {
+ fprintf(out, "\n");
+ for (auto signature_to_modules_it = atoms.signatures_to_modules.begin();
+ signature_to_modules_it != atoms.signatures_to_modules.end(); signature_to_modules_it++) {
+ if (!signature_needed_for_module(signature_to_modules_it->second, moduleName)) {
+ continue;
+ }
+ vector<java_type_t> signature = signature_to_modules_it->first;
+
+ write_native_method_signature(out, "static int try_stats_write", signature,
+ attributionDecl, " {");
+
+ int argIndex = 1;
+ fprintf(out, " if (kStatsdEnabled) {\n");
+ fprintf(out, " stats_event_list event(kStatsEventTag);\n");
+ fprintf(out, " event << get_elapsed_realtime_ns();\n\n");
+ fprintf(out, " event << code;\n\n");
+ for (vector<java_type_t>::const_iterator arg = signature.begin();
+ arg != signature.end(); arg++) {
+ if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
+ for (const auto &chainField : attributionDecl.fields) {
+ if (chainField.javaType == JAVA_TYPE_STRING) {
+ fprintf(out, " if (%s_length != %s.size()) {\n",
+ attributionDecl.fields.front().name.c_str(), chainField.name.c_str());
+ fprintf(out, " return -EINVAL;\n");
+ fprintf(out, " }\n");
+ }
+ }
+ fprintf(out, "\n event.begin();\n");
+ fprintf(out, " for (size_t i = 0; i < %s_length; ++i) {\n",
+ attributionDecl.fields.front().name.c_str());
+ fprintf(out, " event.begin();\n");
+ for (const auto &chainField : attributionDecl.fields) {
+ if (chainField.javaType == JAVA_TYPE_STRING) {
+ fprintf(out, " if (%s[i] != NULL) {\n", chainField.name.c_str());
+ fprintf(out, " event << %s[i];\n", chainField.name.c_str());
+ fprintf(out, " } else {\n");
+ fprintf(out, " event << \"\";\n");
+ fprintf(out, " }\n");
+ } else {
+ fprintf(out, " event << %s[i];\n", chainField.name.c_str());
+ }
+ }
+ fprintf(out, " event.end();\n");
+ fprintf(out, " }\n");
+ fprintf(out, " event.end();\n\n");
+ } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
+ fprintf(out, " event.begin();\n\n");
+ fprintf(out, " for (const auto& it : arg%d_1) {\n", argIndex);
+ fprintf(out, " event.begin();\n");
+ fprintf(out, " event << it.first;\n");
+ fprintf(out, " event << it.second;\n");
+ fprintf(out, " event.end();\n");
+ fprintf(out, " }\n");
+
+ fprintf(out, " for (const auto& it : arg%d_2) {\n", argIndex);
+ fprintf(out, " event.begin();\n");
+ fprintf(out, " event << it.first;\n");
+ fprintf(out, " event << it.second;\n");
+ fprintf(out, " event.end();\n");
+ fprintf(out, " }\n");
+
+ fprintf(out, " for (const auto& it : arg%d_3) {\n", argIndex);
+ fprintf(out, " event.begin();\n");
+ fprintf(out, " event << it.first;\n");
+ fprintf(out, " event << it.second;\n");
+ fprintf(out, " event.end();\n");
+ fprintf(out, " }\n");
+
+ fprintf(out, " for (const auto& it : arg%d_4) {\n", argIndex);
+ fprintf(out, " event.begin();\n");
+ fprintf(out, " event << it.first;\n");
+ fprintf(out, " event << it.second;\n");
+ fprintf(out, " event.end();\n");
+ fprintf(out, " }\n");
+
+ fprintf(out, " event.end();\n\n");
+ } else if (*arg == JAVA_TYPE_BYTE_ARRAY) {
+ fprintf(out,
+ " event.AppendCharArray(arg%d.arg, "
+ "arg%d.arg_length);\n",
+ argIndex, argIndex);
+ } else {
+ if (*arg == JAVA_TYPE_STRING) {
+ fprintf(out, " if (arg%d == NULL) {\n", argIndex);
+ fprintf(out, " arg%d = \"\";\n", argIndex);
+ fprintf(out, " }\n");
+ }
+ fprintf(out, " event << arg%d;\n", argIndex);
+ }
+ argIndex++;
+ }
+
+ fprintf(out, " return event.write(LOG_ID_STATS);\n");
+ fprintf(out, " } else {\n");
+ fprintf(out, " return 1;\n");
+ fprintf(out, " }\n");
+ fprintf(out, "}\n");
+ fprintf(out, "\n");
+ }
+
+}
+
+void write_native_stats_write_methods_q(FILE* out, const string& methodName, const Atoms& atoms,
+ const AtomDecl& attributionDecl, const string& moduleName, const string& tryMethodName) {
+ for (auto signature_to_modules_it = atoms.signatures_to_modules.begin();
+ signature_to_modules_it != atoms.signatures_to_modules.end();
+ signature_to_modules_it++) {
+ if (!signature_needed_for_module(signature_to_modules_it->second, moduleName)) {
+ continue;
+ }
+ vector<java_type_t> signature = signature_to_modules_it->first;
+
+ write_native_method_signature(out, methodName, signature, attributionDecl, " {");
+
+ write_native_stats_write_body_q(out, signature, attributionDecl, " ", tryMethodName);
+ fprintf(out, "}\n\n");
+ }
+}
+
+void write_native_stats_write_non_chained_methods_q(FILE* out, const string& methodName,
+ const Atoms& atoms, const AtomDecl& attributionDecl, const string& moduleName,
+ const string& tryMethodName) {
+ for (auto signature_it = atoms.non_chained_signatures_to_modules.begin();
+ signature_it != atoms.non_chained_signatures_to_modules.end(); signature_it++) {
+ if (!signature_needed_for_module(signature_it->second, moduleName)) {
+ continue;
+ }
+ vector<java_type_t> signature = signature_it->first;
+
+ write_native_method_signature(out, methodName, signature, attributionDecl, " {");
+
+ write_native_stats_write_body_q(out, signature, attributionDecl, " ", tryMethodName);
+ fprintf(out, "}\n\n");
+ }
+}
+
+void write_native_try_stats_write_non_chained_methods_q(FILE* out, const Atoms& atoms,
+ const AtomDecl& attributionDecl, const string& moduleName) {
+ for (auto signature_it = atoms.non_chained_signatures_to_modules.begin();
+ signature_it != atoms.non_chained_signatures_to_modules.end(); signature_it++) {
+ if (!signature_needed_for_module(signature_it->second, moduleName)) {
+ continue;
+ }
+ vector<java_type_t> signature = signature_it->first;
+
+ write_native_method_signature(out, "static int try_stats_write_non_chained", signature,
+ attributionDecl, " {");
+
+ int argIndex = 1;
+ fprintf(out, " if (kStatsdEnabled) {\n");
+ fprintf(out, " stats_event_list event(kStatsEventTag);\n");
+ fprintf(out, " event << get_elapsed_realtime_ns();\n\n");
+ fprintf(out, " event << code;\n\n");
+ for (vector<java_type_t>::const_iterator arg = signature.begin();
+ arg != signature.end(); arg++) {
+ if (argIndex == 1) {
+ fprintf(out, " event.begin();\n\n");
+ fprintf(out, " event.begin();\n");
+ }
+ if (*arg == JAVA_TYPE_STRING) {
+ fprintf(out, " if (arg%d == NULL) {\n", argIndex);
+ fprintf(out, " arg%d = \"\";\n", argIndex);
+ fprintf(out, " }\n");
+ }
+ if (*arg == JAVA_TYPE_BYTE_ARRAY) {
+ fprintf(out,
+ " event.AppendCharArray(arg%d.arg, "
+ "arg%d.arg_length);\n",
+ argIndex, argIndex);
+ } else {
+ fprintf(out, " event << arg%d;\n", argIndex);
+ }
+ if (argIndex == 2) {
+ fprintf(out, " event.end();\n\n");
+ fprintf(out, " event.end();\n\n");
+ }
+ argIndex++;
+ }
+
+ fprintf(out, " return event.write(LOG_ID_STATS);\n");
+ fprintf(out, " } else {\n");
+ fprintf(out, " return 1;\n");
+ fprintf(out, " }\n");
+ fprintf(out, "}\n");
+ fprintf(out, "\n");
+ }
+}
+
+} // namespace stats_log_api_gen
+} // namespace android
diff --git a/tools/stats_log_api_gen/native_writer_q.h b/tools/stats_log_api_gen/native_writer_q.h
new file mode 100644
index 000000000000..a2ab1ae5d5e2
--- /dev/null
+++ b/tools/stats_log_api_gen/native_writer_q.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "Collation.h"
+
+#include <stdio.h>
+#include <string.h>
+
+namespace android {
+namespace stats_log_api_gen {
+
+using namespace std;
+
+void write_native_cpp_includes_q(FILE* out);
+
+void write_native_stats_log_cpp_globals_q(FILE* out);
+
+void write_native_try_stats_write_methods_q(FILE* out, const Atoms& atoms,
+ const AtomDecl& attributionDecl, const string& moduleName);
+
+void write_native_stats_write_methods_q(FILE* out, const string& methodName, const Atoms& atoms,
+ const AtomDecl& attributionDecl, const string& moduleName, const string& tryMethodName);
+
+void write_native_try_stats_write_non_chained_methods_q(FILE* out, const Atoms& atoms,
+ const AtomDecl& attributionDecl, const string& moduleName);
+
+void write_native_stats_write_non_chained_methods_q(FILE* out, const string& methodName,
+ const Atoms& atoms, const AtomDecl& attributionDecl, const string& moduleName,
+ const string& tryMethodName);
+
+void write_native_get_timestamp_ns_q(FILE* out);
+
+} // namespace stats_log_api_gen
+} // namespace android
diff --git a/tools/stats_log_api_gen/test.proto b/tools/stats_log_api_gen/test.proto
index c3e703826be5..c9a47632b4bb 100644
--- a/tools/stats_log_api_gen/test.proto
+++ b/tools/stats_log_api_gen/test.proto
@@ -229,8 +229,8 @@ message NoModuleAtom {
message ModuleAtoms {
oneof event {
- ModuleOneAtom module_one_atom = 1 [(android.os.statsd.log_from_module) = "module1"];
- ModuleTwoAtom module_two_atom = 2 [(android.os.statsd.log_from_module) = "module2"];
+ ModuleOneAtom module_one_atom = 1 [(android.os.statsd.module) = "module1"];
+ ModuleTwoAtom module_two_atom = 2 [(android.os.statsd.module) = "module2"];
NoModuleAtom no_module_atom = 3;
}
-} \ No newline at end of file
+}
diff --git a/tools/stats_log_api_gen/utils.cpp b/tools/stats_log_api_gen/utils.cpp
index d6cfe95a34f5..c65d1901ea7e 100644
--- a/tools/stats_log_api_gen/utils.cpp
+++ b/tools/stats_log_api_gen/utils.cpp
@@ -204,6 +204,65 @@ void write_native_atom_constants(FILE* out, const Atoms& atoms, const AtomDecl&
fprintf(out, "\n");
}
+void write_native_method_signature(FILE* out, const string& methodName,
+ const vector<java_type_t>& signature, const AtomDecl& attributionDecl,
+ const string& closer) {
+ fprintf(out, "%s(int32_t code", methodName.c_str());
+ int argIndex = 1;
+ for (vector<java_type_t>::const_iterator arg = signature.begin();
+ arg != signature.end(); arg++) {
+ if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
+ for (auto chainField : attributionDecl.fields) {
+ if (chainField.javaType == JAVA_TYPE_STRING) {
+ fprintf(out, ", const std::vector<%s>& %s",
+ cpp_type_name(chainField.javaType),
+ chainField.name.c_str());
+ } else {
+ fprintf(out, ", const %s* %s, size_t %s_length",
+ cpp_type_name(chainField.javaType),
+ chainField.name.c_str(), chainField.name.c_str());
+ }
+ }
+ } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
+ fprintf(out, ", const std::map<int, int32_t>& arg%d_1, "
+ "const std::map<int, int64_t>& arg%d_2, "
+ "const std::map<int, char const*>& arg%d_3, "
+ "const std::map<int, float>& arg%d_4",
+ argIndex, argIndex, argIndex, argIndex);
+ } else {
+ fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
+ }
+ argIndex++;
+ }
+ fprintf(out, ")%s\n", closer.c_str());
+}
+
+void write_native_method_call(FILE* out, const string& methodName,
+ const vector<java_type_t>& signature, const AtomDecl& attributionDecl, int argIndex) {
+ fprintf(out, "%s(code", methodName.c_str());
+ for (vector<java_type_t>::const_iterator arg = signature.begin();
+ arg != signature.end(); arg++) {
+ if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
+ for (auto chainField : attributionDecl.fields) {
+ if (chainField.javaType == JAVA_TYPE_STRING) {
+ fprintf(out, ", %s",
+ chainField.name.c_str());
+ } else {
+ fprintf(out, ", %s, %s_length",
+ chainField.name.c_str(), chainField.name.c_str());
+ }
+ }
+ } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
+ fprintf(out, ", arg%d_1, arg%d_2, arg%d_3, arg%d_4", argIndex,
+ argIndex, argIndex, argIndex);
+ } else {
+ fprintf(out, ", arg%d", argIndex);
+ }
+ argIndex++;
+ }
+ fprintf(out, ");\n");
+}
+
// Java
void write_java_atom_codes(FILE* out, const Atoms& atoms, const string& moduleName) {
fprintf(out, " // Constants for atom codes.\n");
diff --git a/tools/stats_log_api_gen/utils.h b/tools/stats_log_api_gen/utils.h
index a89387f00bce..50737a68bf89 100644
--- a/tools/stats_log_api_gen/utils.h
+++ b/tools/stats_log_api_gen/utils.h
@@ -56,8 +56,14 @@ void write_namespace(FILE* out, const string& cppNamespaces);
void write_closing_namespace(FILE* out, const string& cppNamespaces);
void write_native_atom_constants(FILE* out, const Atoms& atoms, const AtomDecl& attributionDecl,
- const string& moduleName
-);
+ const string& moduleName);
+
+void write_native_method_signature(FILE* out, const string& methodName,
+ const vector<java_type_t>& signature, const AtomDecl& attributionDecl,
+ const string& closer);
+
+void write_native_method_call(FILE* out, const string& methodName,
+ const vector<java_type_t>& signature, const AtomDecl& attributionDecl, int argIndex = 1);
// Common Java helpers.
void write_java_atom_codes(FILE* out, const Atoms& atoms, const string& moduleName);
@@ -69,14 +75,12 @@ void write_java_usage(FILE* out, const string& method_name, const string& atom_c
int write_java_non_chained_methods(FILE* out, const map<vector<java_type_t>,
set<string>>& signatures_to_modules,
- const string& moduleName
-);
+ const string& moduleName);
int write_java_work_source_methods(
FILE* out,
const map<vector<java_type_t>, set<string>>& signatures_to_modules,
- const string& moduleName
-);
+ const string& moduleName);
} // namespace stats_log_api_gen
} // namespace android
diff --git a/wifi/Android.bp b/wifi/Android.bp
index 08115ecb6b2b..81559224f700 100644
--- a/wifi/Android.bp
+++ b/wifi/Android.bp
@@ -32,7 +32,6 @@ filegroup {
// framework-wifi.jar. This is not a good idea, should move WifiNetworkScoreCache
// to a separate package.
"java/android/net/wifi/WifiNetworkScoreCache.java",
- "java/android/net/wifi/WifiCondManager.java",
"java/android/net/wifi/wificond/*.java",
":libwificond_ipc_aidl",
],
@@ -43,11 +42,21 @@ filegroup {
srcs: ["java/android/net/wifi/WifiAnnotations.java"],
}
+// list of tests that are allowed to access @hide APIs from framework-wifi
+test_access_hidden_api_whitelist = [
+ "//frameworks/base/wifi/tests",
+ "//frameworks/opt/net/wifi/tests/wifitests:__subpackages__",
+
+ "//frameworks/opt/net/wifi/libs/WifiTrackerLib/tests",
+]
+
java_library {
name: "framework-wifi",
- sdk_version: "core_platform", // TODO(b/140299412) should be core_current
+ // TODO(b/140299412) should be core_current once we build against framework-system-stubs
+ sdk_version: "core_platform",
libs: [
- "framework-minus-apex", // TODO(b/140299412) should be framework-system-stubs
+ // TODO(b/140299412) should be framework-system-stubs once we fix all @hide dependencies
+ "framework-minus-apex",
],
srcs: [
":framework-wifi-updatable-sources",
@@ -55,7 +64,11 @@ java_library {
installable: true,
optimize: {
enabled: false
- }
+ },
+ visibility: [
+ "//frameworks/base", // TODO(b/140299412) remove once all dependencies are fixed
+ "//frameworks/opt/net/wifi/service:__subpackages__",
+ ] + test_access_hidden_api_whitelist,
}
droidstubs {
@@ -85,3 +98,16 @@ java_library {
installable: false,
}
+// defaults for tests that need to build against framework-wifi's @hide APIs
+java_defaults {
+ name: "framework-wifi-test-defaults",
+ sdk_version: "core_platform", // tests can use @CorePlatformApi's
+ libs: [
+ "framework-wifi",
+ "framework-minus-apex",
+
+ // if sdk_version="" this gets automatically included, but here we need to add manually.
+ "framework-res",
+ ],
+ visibility: test_access_hidden_api_whitelist,
+}
diff --git a/wifi/java/android/net/wifi/EasyConnectStatusCallback.java b/wifi/java/android/net/wifi/EasyConnectStatusCallback.java
index b8c82fd9e0ae..8ccf0076f0b0 100644
--- a/wifi/java/android/net/wifi/EasyConnectStatusCallback.java
+++ b/wifi/java/android/net/wifi/EasyConnectStatusCallback.java
@@ -17,32 +17,44 @@
package android.net.wifi;
import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.os.Handler;
+import android.util.SparseArray;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.concurrent.Executor;
/**
* Easy Connect (DPP) Status Callback. Use this callback to get status updates (success, failure,
- * progress) from the Easy Connect operation started with
- * {@link WifiManager#startEasyConnectAsConfiguratorInitiator(String,
- * int, int, Handler, EasyConnectStatusCallback)} or
- * {@link WifiManager#startEasyConnectAsEnrolleeInitiator(String,
- * Handler, EasyConnectStatusCallback)}
- *
- * @hide
+ * progress) from the Easy Connect operations.
*/
-@SystemApi
public abstract class EasyConnectStatusCallback {
/**
- * Easy Connect Success event: Configuration sent (Configurator mode).
+ * Easy Connect R1 Success event: Configuration sent (Configurator mode). This is the last
+ * and final Easy Connect event when either the local device or remote device implement R1.
+ * If both devices implement R2, this event will never be received, and the
+ * {@link #EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_APPLIED} will be received.
+ * @hide
*/
+ @SystemApi
public static final int EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_SENT = 0;
+ /**
+ * East Connect R2 Success event: Configuration applied by Enrollee (Configurator mode).
+ * This is the last and final Easy Connect event when both the local device and remote device
+ * implement R2. If either the local device or remote device implement R1, this event will never
+ * be received, and the {@link #EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_SENT} will be received.
+ * @hide
+ */
+ @SystemApi
+ public static final int EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_APPLIED = 1;
+
/** @hide */
@IntDef(prefix = {"EASY_CONNECT_EVENT_SUCCESS_"}, value = {
EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_SENT,
+ EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_APPLIED,
})
@Retention(RetentionPolicy.SOURCE)
public @interface EasyConnectSuccessStatusCode {
@@ -50,18 +62,38 @@ public abstract class EasyConnectStatusCallback {
/**
* Easy Connect Progress event: Initial authentication with peer succeeded.
+ * @hide
*/
+ @SystemApi
public static final int EASY_CONNECT_EVENT_PROGRESS_AUTHENTICATION_SUCCESS = 0;
/**
* Easy Connect Progress event: Peer requires more time to process bootstrapping.
+ * @hide
*/
+ @SystemApi
public static final int EASY_CONNECT_EVENT_PROGRESS_RESPONSE_PENDING = 1;
+ /**
+ * Easy Connect R2 Progress event: Configuration sent to Enrollee, waiting for response
+ * @hide
+ */
+ @SystemApi
+ public static final int EASY_CONNECT_EVENT_PROGRESS_CONFIGURATION_SENT_WAITING_RESPONSE = 2;
+
+ /**
+ * Easy Connect R2 Progress event: Configuration accepted by Enrollee, waiting for response
+ * @hide
+ */
+ @SystemApi
+ public static final int EASY_CONNECT_EVENT_PROGRESS_CONFIGURATION_ACCEPTED = 3;
+
/** @hide */
@IntDef(prefix = {"EASY_CONNECT_EVENT_PROGRESS_"}, value = {
EASY_CONNECT_EVENT_PROGRESS_AUTHENTICATION_SUCCESS,
EASY_CONNECT_EVENT_PROGRESS_RESPONSE_PENDING,
+ EASY_CONNECT_EVENT_PROGRESS_CONFIGURATION_SENT_WAITING_RESPONSE,
+ EASY_CONNECT_EVENT_PROGRESS_CONFIGURATION_ACCEPTED,
})
@Retention(RetentionPolicy.SOURCE)
public @interface EasyConnectProgressStatusCode {
@@ -114,6 +146,20 @@ public abstract class EasyConnectStatusCallback {
*/
public static final int EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK = -9;
+ /**
+ * Easy Connect R2 Failure event: Enrollee cannot find the network.
+ */
+ public static final int EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK = -10;
+
+ /**
+ * Easy Connect R2 Failure event: Enrollee failed to authenticate with the network.
+ */
+ public static final int EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION = -11;
+
+ /**
+ * Easy Connect R2 Failure event: Enrollee rejected the configuration.
+ */
+ public static final int EASY_CONNECT_EVENT_FAILURE_ENROLLEE_REJECTED_CONFIGURATION = -12;
/** @hide */
@IntDef(prefix = {"EASY_CONNECT_EVENT_FAILURE_"}, value = {
@@ -126,11 +172,20 @@ public abstract class EasyConnectStatusCallback {
EASY_CONNECT_EVENT_FAILURE_GENERIC,
EASY_CONNECT_EVENT_FAILURE_NOT_SUPPORTED,
EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK,
+ EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK,
+ EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION,
+ EASY_CONNECT_EVENT_FAILURE_ENROLLEE_REJECTED_CONFIGURATION,
})
@Retention(RetentionPolicy.SOURCE)
public @interface EasyConnectFailureStatusCode {
}
+ /** @hide */
+ @SystemApi
+ public EasyConnectStatusCallback() {
+ // Fully-static utility classes must not have constructor
+ }
+
/**
* Called when local Easy Connect Enrollee successfully receives a new Wi-Fi configuration from
* the
@@ -138,42 +193,73 @@ public abstract class EasyConnectStatusCallback {
* current Easy Connect
* session, and no further callbacks will be called. This callback is the successful outcome
* of a Easy Connect flow starting with
- * {@link WifiManager#startEasyConnectAsEnrolleeInitiator(String,
- * Handler,
- * EasyConnectStatusCallback)}.
+ * {@link WifiManager#startEasyConnectAsEnrolleeInitiator(String, Executor,
+ * EasyConnectStatusCallback)} .
*
* @param newNetworkId New Wi-Fi configuration with a network ID received from the configurator
+ * @hide
*/
+ @SystemApi
public abstract void onEnrolleeSuccess(int newNetworkId);
/**
* Called when a Easy Connect success event takes place, except for when configuration is
- * received from
- * an external Configurator. The callback onSuccessConfigReceived will be used in this case.
- * This callback marks the successful end of the current Easy Connect session, and no further
- * callbacks will be called. This callback is the successful outcome of a Easy Connect flow
- * starting with
- * {@link WifiManager#startEasyConnectAsConfiguratorInitiator(String, int, int, Handler,
- * EasyConnectStatusCallback)}.
+ * received from an external Configurator. The callback onSuccessConfigReceived will be used in
+ * this case. This callback marks the successful end of the current Easy Connect session, and no
+ * further callbacks will be called. This callback is the successful outcome of a Easy Connect
+ * flow starting with {@link WifiManager#startEasyConnectAsConfiguratorInitiator(String, int,
+ * int, Executor,EasyConnectStatusCallback)}.
*
* @param code Easy Connect success status code.
+ * @hide
*/
+ @SystemApi
public abstract void onConfiguratorSuccess(@EasyConnectSuccessStatusCode int code);
/**
* Called when a Easy Connect Failure event takes place. This callback marks the unsuccessful
- * end of the
- * current Easy Connect session, and no further callbacks will be called.
+ * end of the current Easy Connect session, and no further callbacks will be called.
+ *
+ * @param code Easy Connect failure status code.
+ * @hide
+ */
+ @SystemApi
+ public void onFailure(@EasyConnectFailureStatusCode int code) {}
+
+ /**
+ * Called when a Easy Connect Failure event takes place. This callback marks the unsuccessful
+ * end of the current Easy Connect session, and no further callbacks will be called.
+ *
+ * Note: Easy Connect (DPP) R2, provides additional details for the Configurator when the
+ * remote Enrollee is unable to connect to a network. The ssid, channelList and bandList
+ * inputs are initialized only for the EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK failure
+ * code, and the ssid and bandList are initialized for the
+ * EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION failure code.
*
* @param code Easy Connect failure status code.
+ * @param ssid SSID of the network the Enrollee tried to connect to.
+ * @param channelListArray List of Global Operating classes and channel sets the Enrollee used
+ * to scan to find the network, see the "DPP Connection Status Object"
+ * section in the specification for the format, and Table E-4 in
+ * IEEE Std 802.11-2016 - Global operating classes for more details.
+ * @param operatingClassArray Array of bands the Enrollee supports as expressed as the Global
+ * Operating Class, see Table E-4 in IEEE Std 802.11-2016 - Global
+ * operating classes.
+ * @hide
*/
- public abstract void onFailure(@EasyConnectFailureStatusCode int code);
+ @SystemApi
+ public void onFailure(@EasyConnectFailureStatusCode int code, @Nullable String ssid,
+ @NonNull SparseArray<int[]> channelListArray, @NonNull int[] operatingClassArray) {
+ onFailure(code);
+ }
/**
* Called when Easy Connect events that indicate progress take place. Can be used by UI elements
* to show progress.
*
* @param code Easy Connect progress status code.
+ * @hide
*/
+ @SystemApi
public abstract void onProgress(@EasyConnectProgressStatusCode int code);
}
diff --git a/wifi/java/android/net/wifi/IDppCallback.aidl b/wifi/java/android/net/wifi/IDppCallback.aidl
index c452c7664c12..d7a958a5b4b1 100644
--- a/wifi/java/android/net/wifi/IDppCallback.aidl
+++ b/wifi/java/android/net/wifi/IDppCallback.aidl
@@ -38,7 +38,7 @@ oneway interface IDppCallback
/**
* Called when DPP Failure events take place.
*/
- void onFailure(int status);
+ void onFailure(int status, String ssid, String channelList, in int[] bandArray);
/**
* Called when DPP events that indicate progress take place. Can be used by UI elements
diff --git a/wifi/java/android/net/wifi/ISoftApCallback.aidl b/wifi/java/android/net/wifi/ISoftApCallback.aidl
index 452a655edc7b..482b4910921d 100644
--- a/wifi/java/android/net/wifi/ISoftApCallback.aidl
+++ b/wifi/java/android/net/wifi/ISoftApCallback.aidl
@@ -15,6 +15,7 @@
*/
package android.net.wifi;
+import android.net.wifi.SoftApCapability;
import android.net.wifi.SoftApInfo;
import android.net.wifi.WifiClient;
@@ -51,4 +52,12 @@ oneway interface ISoftApCallback
* @param softApInfo is the softap information. {@link SoftApInfo}
*/
void onInfoChanged(in SoftApInfo softApInfo);
+
+
+ /**
+ * Service to manager callback providing information of softap.
+ *
+ * @param capability is the softap capability. {@link SoftApCapability}
+ */
+ void onCapabilityChanged(in SoftApCapability capability);
}
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index 729ef61f0e4d..83a18008919d 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -103,6 +103,12 @@ public class ScanResult implements Parcelable {
/**
* @hide
+ * Security protocol type: WAPI.
+ */
+ public static final int PROTOCOL_WAPI = 4;
+
+ /**
+ * @hide
* No security key management scheme.
*/
public static final int KEY_MGMT_NONE = 0;
@@ -169,6 +175,18 @@ public class ScanResult implements Parcelable {
public static final int KEY_MGMT_OWE_TRANSITION = 12;
/**
* @hide
+ * Security key management scheme: WAPI_PSK.
+ */
+ @SystemApi
+ public static final int KEY_MGMT_WAPI_PSK = 13;
+ /**
+ * @hide
+ * Security key management scheme: WAPI_CERT.
+ */
+ @SystemApi
+ public static final int KEY_MGMT_WAPI_CERT = 14;
+ /**
+ * @hide
* No cipher suite.
*/
public static final int CIPHER_NONE = 0;
@@ -192,6 +210,11 @@ public class ScanResult implements Parcelable {
* Cipher suite: GCMP
*/
public static final int CIPHER_GCMP_256 = 4;
+ /**
+ * @hide
+ * Cipher suite: SMS4
+ */
+ public static final int CIPHER_SMS4 = 5;
/**
* The detected signal level in dBm, also known as the RSSI.
diff --git a/wifi/java/android/net/wifi/SoftApCapability.aidl b/wifi/java/android/net/wifi/SoftApCapability.aidl
new file mode 100644
index 000000000000..bf30709f15d1
--- /dev/null
+++ b/wifi/java/android/net/wifi/SoftApCapability.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi;
+
+parcelable SoftApCapability;
diff --git a/wifi/java/android/net/wifi/SoftApCapability.java b/wifi/java/android/net/wifi/SoftApCapability.java
new file mode 100644
index 000000000000..c4474e2bc9cc
--- /dev/null
+++ b/wifi/java/android/net/wifi/SoftApCapability.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+
+/**
+ * A class representing capability of the SoftAp.
+ * {@see WifiManager}
+ *
+ * @hide
+ */
+@SystemApi
+public final class SoftApCapability implements Parcelable {
+
+ /**
+ * Support for automatic channel selection in driver (ACS).
+ * Driver will auto select best channel based on interference to optimize performance.
+ *
+ * flag when {@link R.bool.config_wifi_softap_acs_supported)} is true.
+ *
+ * <p>
+ * Use {@link WifiManager.SoftApCallback#onInfoChanged(SoftApInfo)} and
+ * {@link SoftApInfo#getFrequency} and {@link SoftApInfo#getBandwidth} to get
+ * driver channel selection result.
+ */
+ public static final int SOFTAP_FEATURE_ACS_OFFLOAD = 1 << 0;
+
+ /**
+ * Support for client force disconnect.
+ * flag when {@link R.bool.config_wifi_sofap_client_force_disconnect_supported)} is true
+ *
+ * <p>
+ * Several Soft AP client control features, e.g. specifying the maximum number of
+ * Soft AP clients, only work when this feature support is present.
+ * Check feature support before invoking
+ * {@link SoftApConfiguration.Builder#setMaxNumberOfClients(int)}
+ */
+ public static final int SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT = 1 << 1;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = true, prefix = { "SOFTAP_FEATURE_" }, value = {
+ SOFTAP_FEATURE_ACS_OFFLOAD,
+ SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT,
+ })
+ public @interface HotspotFeatures {}
+
+ private @HotspotFeatures int mSupportedFeatures = 0;
+
+ private int mMaximumSupportedClientNumber;
+
+ /**
+ * Get the maximum supported client numbers which AP resides on.
+ */
+ public int getMaxSupportedClients() {
+ return mMaximumSupportedClientNumber;
+ }
+
+ /**
+ * Set the maximum supported client numbers which AP resides on.
+ *
+ * @param maxClient maximum supported client numbers for the softap.
+ * @hide
+ */
+ public void setMaxSupportedClients(int maxClient) {
+ mMaximumSupportedClientNumber = maxClient;
+ }
+
+ /**
+ * Returns true when feature supported, otherwise false.
+ *
+ * @param feature one of feature from {@link HotspotFeatures}
+ */
+ public boolean isFeatureSupported(@HotspotFeatures int feature) {
+ return (mSupportedFeatures & feature) == feature;
+ }
+
+ /**
+ * @hide
+ */
+ public SoftApCapability(@Nullable SoftApCapability source) {
+ if (source != null) {
+ mSupportedFeatures = source.mSupportedFeatures;
+ mMaximumSupportedClientNumber = source.mMaximumSupportedClientNumber;
+ }
+ }
+
+ /**
+ * Constructor with combination of the feature.
+ * Zero to no supported feature.
+ *
+ * @param features One or combination of the feature from {@link @HotspotFeatures}.
+ * @hide
+ */
+ public SoftApCapability(@HotspotFeatures int features) {
+ mSupportedFeatures = features;
+ }
+
+ @Override
+ /** Implement the Parcelable interface. */
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ /** Implement the Parcelable interface */
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mSupportedFeatures);
+ dest.writeInt(mMaximumSupportedClientNumber);
+ }
+
+ @NonNull
+ /** Implement the Parcelable interface */
+ public static final Creator<SoftApCapability> CREATOR = new Creator<SoftApCapability>() {
+ public SoftApCapability createFromParcel(Parcel in) {
+ int supportedFeatures = in.readInt();
+ SoftApCapability capability = new SoftApCapability(supportedFeatures);
+ capability.mMaximumSupportedClientNumber = in.readInt();
+ return capability;
+ }
+
+ public SoftApCapability[] newArray(int size) {
+ return new SoftApCapability[size];
+ }
+ };
+
+ @NonNull
+ @Override
+ public String toString() {
+ StringBuilder sbuf = new StringBuilder();
+ sbuf.append("SupportedFeatures=").append(mSupportedFeatures);
+ sbuf.append("MaximumSupportedClientNumber=").append(mMaximumSupportedClientNumber);
+ return sbuf.toString();
+ }
+
+ @Override
+ public boolean equals(@NonNull Object o) {
+ if (this == o) return true;
+ if (!(o instanceof SoftApCapability)) return false;
+ SoftApCapability capability = (SoftApCapability) o;
+ return mSupportedFeatures == capability.mSupportedFeatures
+ && mMaximumSupportedClientNumber == capability.mMaximumSupportedClientNumber;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mSupportedFeatures, mMaximumSupportedClientNumber);
+ }
+}
diff --git a/wifi/java/android/net/wifi/SoftApConfiguration.java b/wifi/java/android/net/wifi/SoftApConfiguration.java
index d755053e60d2..05e245b8eabc 100644
--- a/wifi/java/android/net/wifi/SoftApConfiguration.java
+++ b/wifi/java/android/net/wifi/SoftApConfiguration.java
@@ -60,32 +60,77 @@ public final class SoftApConfiguration implements Parcelable {
* @hide
*/
@SystemApi
- public static final int BAND_2GHZ = 0;
+ public static final int BAND_2GHZ = 1 << 0;
/**
* 5GHz band.
* @hide
*/
@SystemApi
- public static final int BAND_5GHZ = 1;
+ public static final int BAND_5GHZ = 1 << 1;
/**
- * Device is allowed to choose the optimal band (2Ghz or 5Ghz) based on device capability,
+ * 6GHz band.
+ * @hide
+ */
+ @SystemApi
+ public static final int BAND_6GHZ = 1 << 2;
+
+ /**
+ * Device is allowed to choose the optimal band (2Ghz, 5Ghz, 6Ghz) based on device capability,
* operating country code and current radio conditions.
* @hide
*/
@SystemApi
- public static final int BAND_ANY = -1;
+ public static final int BAND_ANY = BAND_2GHZ | BAND_5GHZ | BAND_6GHZ;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
- @IntDef(prefix = { "BAND_TYPE_" }, value = {
+ @IntDef(flag = true, prefix = { "BAND_TYPE_" }, value = {
BAND_2GHZ,
BAND_5GHZ,
- BAND_ANY,
+ BAND_6GHZ,
})
public @interface BandType {}
+ private static boolean isBandValid(@BandType int band) {
+ return ((band != 0) && ((band & ~BAND_ANY) == 0));
+ }
+
+ private static final int MIN_CH_2G_BAND = 1;
+ private static final int MAX_CH_2G_BAND = 14;
+ private static final int MIN_CH_5G_BAND = 34;
+ private static final int MAX_CH_5G_BAND = 196;
+ private static final int MIN_CH_6G_BAND = 1;
+ private static final int MAX_CH_6G_BAND = 253;
+
+
+
+ private static boolean isChannelBandPairValid(int channel, @BandType int band) {
+ switch (band) {
+ case BAND_2GHZ:
+ if (channel < MIN_CH_2G_BAND || channel > MAX_CH_2G_BAND) {
+ return false;
+ }
+ break;
+
+ case BAND_5GHZ:
+ if (channel < MIN_CH_5G_BAND || channel > MAX_CH_5G_BAND) {
+ return false;
+ }
+ break;
+
+ case BAND_6GHZ:
+ if (channel < MIN_CH_6G_BAND || channel > MAX_CH_6G_BAND) {
+ return false;
+ }
+ break;
+ default:
+ return false;
+ }
+ return true;
+ }
+
/**
* SSID for the AP, or null for a framework-determined SSID.
*/
@@ -119,6 +164,11 @@ public final class SoftApConfiguration implements Parcelable {
private final int mChannel;
/**
+ * The maximim allowed number of clients that can associate to the AP.
+ */
+ private final int mMaxNumberOfClients;
+
+ /**
* The operating security type of the AP.
* One of the security types from {@link @SecurityType}
*/
@@ -146,7 +196,7 @@ public final class SoftApConfiguration implements Parcelable {
/** Private constructor for Builder and Parcelable implementation. */
private SoftApConfiguration(@Nullable String ssid, @Nullable MacAddress bssid,
@Nullable String wpa2Passphrase, boolean hiddenSsid, @BandType int band, int channel,
- @SecurityType int securityType) {
+ @SecurityType int securityType, int maxNumberOfClients) {
mSsid = ssid;
mBssid = bssid;
mWpa2Passphrase = wpa2Passphrase;
@@ -154,6 +204,7 @@ public final class SoftApConfiguration implements Parcelable {
mBand = band;
mChannel = channel;
mSecurityType = securityType;
+ mMaxNumberOfClients = maxNumberOfClients;
}
@Override
@@ -171,13 +222,14 @@ public final class SoftApConfiguration implements Parcelable {
&& mHiddenSsid == other.mHiddenSsid
&& mBand == other.mBand
&& mChannel == other.mChannel
- && mSecurityType == other.mSecurityType;
+ && mSecurityType == other.mSecurityType
+ && mMaxNumberOfClients == other.mMaxNumberOfClients;
}
@Override
public int hashCode() {
return Objects.hash(mSsid, mBssid, mWpa2Passphrase, mHiddenSsid,
- mBand, mChannel, mSecurityType);
+ mBand, mChannel, mSecurityType, mMaxNumberOfClients);
}
@Override
@@ -191,6 +243,7 @@ public final class SoftApConfiguration implements Parcelable {
sbuf.append(" \n Band =").append(mBand);
sbuf.append(" \n Channel =").append(mChannel);
sbuf.append(" \n SecurityType=").append(getSecurityType());
+ sbuf.append(" \n MaxClient=").append(mMaxNumberOfClients);
return sbuf.toString();
}
@@ -203,6 +256,7 @@ public final class SoftApConfiguration implements Parcelable {
dest.writeInt(mBand);
dest.writeInt(mChannel);
dest.writeInt(mSecurityType);
+ dest.writeInt(mMaxNumberOfClients);
}
@Override
@@ -217,7 +271,8 @@ public final class SoftApConfiguration implements Parcelable {
return new SoftApConfiguration(
in.readString(),
in.readParcelable(MacAddress.class.getClassLoader()),
- in.readString(), in.readBoolean(), in.readInt(), in.readInt(), in.readInt());
+ in.readString(), in.readBoolean(), in.readInt(), in.readInt(), in.readInt(),
+ in.readInt());
}
@Override
@@ -237,7 +292,7 @@ public final class SoftApConfiguration implements Parcelable {
/**
* Returns MAC address set to be BSSID for the AP.
- * {@link #setBssid(MacAddress)}.
+ * {@link Builder#setBssid(MacAddress)}.
*/
@Nullable
public MacAddress getBssid() {
@@ -246,7 +301,7 @@ public final class SoftApConfiguration implements Parcelable {
/**
* Returns String set to be passphrase for the WPA2-PSK AP.
- * {@link #setWpa2Passphrase(String)}.
+ * {@link Builder#setWpa2Passphrase(String)}.
*/
@Nullable
public String getWpa2Passphrase() {
@@ -256,7 +311,7 @@ public final class SoftApConfiguration implements Parcelable {
/**
* Returns Boolean set to be indicate hidden (true: doesn't broadcast its SSID) or
* not (false: broadcasts its SSID) for the AP.
- * {@link #setHiddenSsid(boolean)}.
+ * {@link Builder#setHiddenSsid(boolean)}.
*/
public boolean isHiddenSsid() {
return mHiddenSsid;
@@ -264,7 +319,7 @@ public final class SoftApConfiguration implements Parcelable {
/**
* Returns {@link BandType} set to be the band for the AP.
- * {@link #setBand(@BandType int)}.
+ * {@link Builder#setBand(@BandType int)}.
*/
public @BandType int getBand() {
return mBand;
@@ -272,7 +327,7 @@ public final class SoftApConfiguration implements Parcelable {
/**
* Returns Integer set to be the channel for the AP.
- * {@link #setChannel(int)}.
+ * {@link Builder#setChannel(int)}.
*/
public int getChannel() {
return mChannel;
@@ -288,6 +343,14 @@ public final class SoftApConfiguration implements Parcelable {
}
/**
+ * Returns the maximum number of clients that can associate to the AP.
+ * {@link Builder#setMaxNumberOfClients(int)}.
+ */
+ public int getMaxNumberOfClients() {
+ return mMaxNumberOfClients;
+ }
+
+ /**
* Builds a {@link SoftApConfiguration}, which allows an app to configure various aspects of a
* Soft AP.
*
@@ -301,6 +364,7 @@ public final class SoftApConfiguration implements Parcelable {
private boolean mHiddenSsid;
private int mBand;
private int mChannel;
+ private int mMaxNumberOfClients;
private int setSecurityType() {
int securityType = SECURITY_TYPE_OPEN;
@@ -324,6 +388,7 @@ public final class SoftApConfiguration implements Parcelable {
mHiddenSsid = false;
mBand = BAND_2GHZ;
mChannel = 0;
+ mMaxNumberOfClients = 0;
}
/**
@@ -338,6 +403,7 @@ public final class SoftApConfiguration implements Parcelable {
mHiddenSsid = other.mHiddenSsid;
mBand = other.mBand;
mChannel = other.mChannel;
+ mMaxNumberOfClients = other.mMaxNumberOfClients;
}
/**
@@ -348,7 +414,7 @@ public final class SoftApConfiguration implements Parcelable {
@NonNull
public SoftApConfiguration build() {
return new SoftApConfiguration(mSsid, mBssid, mWpa2Passphrase,
- mHiddenSsid, mBand, mChannel, setSecurityType());
+ mHiddenSsid, mBand, mChannel, setSecurityType(), mMaxNumberOfClients);
}
/**
@@ -439,41 +505,89 @@ public final class SoftApConfiguration implements Parcelable {
* <p>
* <li>If not set, defaults to BAND_2GHZ {@link @BandType}.</li>
*
- * @param band One of the band types from {@link @BandType}.
+ * @param band One or combination of the band types from {@link @BandType}.
* @return Builder for chaining.
*/
@NonNull
public Builder setBand(@BandType int band) {
- switch (band) {
- case BAND_2GHZ:
- break;
- case BAND_5GHZ:
- break;
- case BAND_ANY:
- break;
- default:
- throw new IllegalArgumentException("Invalid band type");
+ if (!isBandValid(band)) {
+ throw new IllegalArgumentException("Invalid band type");
}
mBand = band;
+ // Since band preference is specified, no specific channel is selected.
+ mChannel = 0;
return this;
}
/**
- * Specifies the channel for the AP.
+ * Specifies the channel and associated band for the AP.
*
* The channel which AP resides on. Valid channels are country dependent.
- * Use the special channel value 0 to have the framework auto-select a valid channel
- * from the band configured with {@link #setBand(@BandType int)}.
+ * <p>
+ * The default for the channel is a the special value 0 to have the framework
+ * auto-select a valid channel from the band configured with
+ * {@link #setBand(@BandType int)}.
+ *
+ * The channel auto selection will offload to driver when
+ * {@link SoftApCapability#isFeatureSupported(SoftApCapability.SOFTAP_FEATURE_ACS_OFFLOAD)}
+ * return true. Driver will auto select best channel which based on environment
+ * interference to get best performance. Check {@link SoftApCapability} to get more detail.
+ *
+ * Note, since 6GHz band use the same channel numbering of 2.4GHz and 5GHZ bands,
+ * the caller needs to pass the band containing the selected channel.
*
* <p>
* <li>If not set, defaults to 0.</li>
* @param channel operating channel of the AP.
+ * @param band containing this channel.
* @return Builder for chaining.
*/
@NonNull
- public Builder setChannel(int channel) {
+ public Builder setChannel(int channel, @BandType int band) {
+ if (!isChannelBandPairValid(channel, band)) {
+ throw new IllegalArgumentException("Invalid band type");
+ }
+ mBand = band;
mChannel = channel;
return this;
}
+
+ /**
+ * Specifies the maximum number of clients that can associate to the AP.
+ *
+ * The maximum number of clients (STAs) which can associate to the AP.
+ * The AP will reject association from any clients above this number.
+ * Specify a value of 0 to have the framework automatically use the maximum number
+ * which the device can support (based on hardware and carrier constraints).
+ * <p>
+ * Use {@link WifiManager.SoftApCallback#onCapabilityChanged(SoftApCapability)} and
+ * {@link SoftApCapability#getMaxSupportedClients} to get the maximum number of clients
+ * which the device supports (based on hardware and carrier constraints).
+ *
+ * <p>
+ * <li>If not set, defaults to 0.</li>
+ *
+ * This method requires hardware support. If the method is used to set a
+ * non-zero {@code maxNumberOfClients} value then
+ * {@link WifiManager#startTetheredHotspot} will report error code
+ * {@link WifiManager#SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION}.
+ *
+ * <p>
+ * Use {@link WifiManager.SoftApCallback#onCapabilityChanged(SoftApCapability)} and
+ * {@link SoftApCapability#isFeatureSupported(int)}
+ * with {@link SoftApCapability.SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT} to determine whether
+ * or not this feature is supported.
+ *
+ * @param maxNumberOfClients maximum client number of the AP.
+ * @return Builder for chaining.
+ */
+ @NonNull
+ public Builder setMaxNumberOfClients(int maxNumberOfClients) {
+ if (maxNumberOfClients < 0) {
+ throw new IllegalArgumentException("maxNumberOfClients should be not negative");
+ }
+ mMaxNumberOfClients = maxNumberOfClients;
+ return this;
+ }
}
}
diff --git a/wifi/java/android/net/wifi/SoftApInfo.java b/wifi/java/android/net/wifi/SoftApInfo.java
index 375a9774f570..24ed8effe471 100644
--- a/wifi/java/android/net/wifi/SoftApInfo.java
+++ b/wifi/java/android/net/wifi/SoftApInfo.java
@@ -16,15 +16,12 @@
package android.net.wifi;
-import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
/**
@@ -85,26 +82,12 @@ public final class SoftApInfo implements Parcelable {
*/
public static final int CHANNEL_WIDTH_160MHZ = 6;
- /**
- * @hide
- */
- @IntDef(prefix = { "CHANNEL_WIDTH_" }, value = {
- CHANNEL_WIDTH_INVALID,
- CHANNEL_WIDTH_20MHZ_NOHT,
- CHANNEL_WIDTH_20MHZ,
- CHANNEL_WIDTH_40MHZ,
- CHANNEL_WIDTH_80MHZ,
- CHANNEL_WIDTH_80MHZ_PLUS_MHZ,
- CHANNEL_WIDTH_160MHZ,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface Bandwidth {}
/** The frequency which AP resides on. */
private int mFrequency = 0;
- @Bandwidth
+ @WifiAnnotations.Bandwidth
private int mBandwidth = CHANNEL_WIDTH_INVALID;
/**
@@ -127,9 +110,9 @@ public final class SoftApInfo implements Parcelable {
*
* @return One of {@link #CHANNEL_WIDTH_20MHZ}, {@link #CHANNEL_WIDTH_40MHZ},
* {@link #CHANNEL_WIDTH_80MHZ}, {@link #CHANNEL_WIDTH_160MHZ},
- * {@link #CHANNEL_WIDTH_80MHZ_PLUS_MHZ} or {@link #CHANNEL_WIDTH_UNKNOWN}.
+ * {@link #CHANNEL_WIDTH_80MHZ_PLUS_MHZ} or {@link #CHANNEL_WIDTH_INVALID}.
*/
- @Bandwidth
+ @WifiAnnotations.Bandwidth
public int getBandwidth() {
return mBandwidth;
}
@@ -138,7 +121,7 @@ public final class SoftApInfo implements Parcelable {
* Set AP Channel bandwidth.
* @hide
*/
- public void setBandwidth(@Bandwidth int bandwidth) {
+ public void setBandwidth(@WifiAnnotations.Bandwidth int bandwidth) {
mBandwidth = bandwidth;
}
diff --git a/wifi/java/android/net/wifi/WifiAnnotations.java b/wifi/java/android/net/wifi/WifiAnnotations.java
index 4a7dee138971..9223d28836b6 100644
--- a/wifi/java/android/net/wifi/WifiAnnotations.java
+++ b/wifi/java/android/net/wifi/WifiAnnotations.java
@@ -48,4 +48,16 @@ public final class WifiAnnotations {
WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY,
WifiScanner.WIFI_BAND_6_GHZ})
public @interface WifiBandBasic {}
+
+ @IntDef(prefix = { "CHANNEL_WIDTH_" }, value = {
+ SoftApInfo.CHANNEL_WIDTH_INVALID,
+ SoftApInfo.CHANNEL_WIDTH_20MHZ_NOHT,
+ SoftApInfo.CHANNEL_WIDTH_20MHZ,
+ SoftApInfo.CHANNEL_WIDTH_40MHZ,
+ SoftApInfo.CHANNEL_WIDTH_80MHZ,
+ SoftApInfo.CHANNEL_WIDTH_80MHZ_PLUS_MHZ,
+ SoftApInfo.CHANNEL_WIDTH_160MHZ,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Bandwidth {}
}
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index d068fc681ae7..2a165d390494 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -36,14 +36,9 @@ import android.os.SystemClock;
import android.os.UserHandle;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
-import android.util.BackupUtils;
import android.util.Log;
import android.util.SparseArray;
-import java.io.ByteArrayOutputStream;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
@@ -123,7 +118,9 @@ public class WifiConfiguration implements Parcelable {
OWE,
SUITE_B_192,
WPA_PSK_SHA256,
- WPA_EAP_SHA256})
+ WPA_EAP_SHA256,
+ WAPI_PSK,
+ WAPI_CERT})
public @interface KeyMgmtScheme {}
/** WPA is not used; plaintext or static WEP could be used. */
@@ -190,11 +187,26 @@ public class WifiConfiguration implements Parcelable {
*/
public static final int WPA_EAP_SHA256 = 12;
+ /**
+ * WAPI pre-shared key (requires {@code preSharedKey} to be specified).
+ * @hide
+ */
+ @SystemApi
+ public static final int WAPI_PSK = 13;
+
+ /**
+ * WAPI certificate to be specified.
+ * @hide
+ */
+ @SystemApi
+ public static final int WAPI_CERT = 14;
+
public static final String varName = "key_mgmt";
public static final String[] strings = { "NONE", "WPA_PSK", "WPA_EAP",
"IEEE8021X", "WPA2_PSK", "OSEN", "FT_PSK", "FT_EAP",
- "SAE", "OWE", "SUITE_B_192", "WPA_PSK_SHA256", "WPA_EAP_SHA256" };
+ "SAE", "OWE", "SUITE_B_192", "WPA_PSK_SHA256", "WPA_EAP_SHA256",
+ "WAPI_PSK", "WAPI_CERT" };
}
/**
@@ -215,9 +227,14 @@ public class WifiConfiguration implements Parcelable {
*/
public static final int OSEN = 2;
+ /**
+ * WAPI Protocol
+ */
+ public static final int WAPI = 3;
+
public static final String varName = "proto";
- public static final String[] strings = { "WPA", "RSN", "OSEN" };
+ public static final String[] strings = { "WPA", "RSN", "OSEN", "WAPI" };
}
/**
@@ -260,10 +277,14 @@ public class WifiConfiguration implements Parcelable {
* AES in Galois/Counter Mode
*/
public static final int GCMP_256 = 3;
+ /**
+ * SMS4 cipher for WAPI
+ */
+ public static final int SMS4 = 4;
public static final String varName = "pairwise";
- public static final String[] strings = { "NONE", "TKIP", "CCMP", "GCMP_256" };
+ public static final String[] strings = { "NONE", "TKIP", "CCMP", "GCMP_256", "SMS4" };
}
/**
@@ -301,12 +322,17 @@ public class WifiConfiguration implements Parcelable {
* AES in Galois/Counter Mode
*/
public static final int GCMP_256 = 5;
+ /**
+ * SMS4 cipher for WAPI
+ */
+ public static final int SMS4 = 6;
public static final String varName = "group";
public static final String[] strings =
{ /* deprecated */ "WEP40", /* deprecated */ "WEP104",
- "TKIP", "CCMP", "GTK_NOT_USED", "GCMP_256" };
+ "TKIP", "CCMP", "GTK_NOT_USED", "GCMP_256",
+ "SMS4" };
}
/**
@@ -388,6 +414,10 @@ public class WifiConfiguration implements Parcelable {
public static final int SECURITY_TYPE_EAP_SUITE_B = 5;
/** @hide */
public static final int SECURITY_TYPE_OWE = 6;
+ /** @hide */
+ public static final int SECURITY_TYPE_WAPI_PSK = 7;
+ /** @hide */
+ public static final int SECURITY_TYPE_WAPI_CERT = 8;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@@ -398,7 +428,9 @@ public class WifiConfiguration implements Parcelable {
SECURITY_TYPE_EAP,
SECURITY_TYPE_SAE,
SECURITY_TYPE_EAP_SUITE_B,
- SECURITY_TYPE_OWE
+ SECURITY_TYPE_OWE,
+ SECURITY_TYPE_WAPI_PSK,
+ SECURITY_TYPE_WAPI_CERT
})
public @interface SecurityType {}
@@ -450,6 +482,18 @@ public class WifiConfiguration implements Parcelable {
allowedKeyManagement.set(WifiConfiguration.KeyMgmt.OWE);
requirePMF = true;
break;
+ case SECURITY_TYPE_WAPI_PSK:
+ allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WAPI_PSK);
+ allowedProtocols.set(WifiConfiguration.Protocol.WAPI);
+ allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.SMS4);
+ allowedGroupCiphers.set(WifiConfiguration.GroupCipher.SMS4);
+ break;
+ case SECURITY_TYPE_WAPI_CERT:
+ allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WAPI_CERT);
+ allowedProtocols.set(WifiConfiguration.Protocol.WAPI);
+ allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.SMS4);
+ allowedGroupCiphers.set(WifiConfiguration.GroupCipher.SMS4);
+ break;
default:
throw new IllegalArgumentException("unknown security type " + securityType);
}
@@ -2350,6 +2394,10 @@ public class WifiConfiguration implements Parcelable {
return KeyMgmt.OWE;
} else if (allowedKeyManagement.get(KeyMgmt.SUITE_B_192)) {
return KeyMgmt.SUITE_B_192;
+ } else if (allowedKeyManagement.get(KeyMgmt.WAPI_PSK)) {
+ return KeyMgmt.WAPI_PSK;
+ } else if (allowedKeyManagement.get(KeyMgmt.WAPI_CERT)) {
+ return KeyMgmt.WAPI_CERT;
}
return KeyMgmt.NONE;
}
@@ -2388,16 +2436,24 @@ public class WifiConfiguration implements Parcelable {
key = SSID + KeyMgmt.strings[KeyMgmt.SAE];
} else if (allowedKeyManagement.get(KeyMgmt.SUITE_B_192)) {
key = SSID + KeyMgmt.strings[KeyMgmt.SUITE_B_192];
+ } else if (allowedKeyManagement.get(KeyMgmt.WAPI_PSK)) {
+ key = SSID + KeyMgmt.strings[KeyMgmt.WAPI_PSK];
+ } else if (allowedKeyManagement.get(KeyMgmt.WAPI_CERT)) {
+ key = SSID + KeyMgmt.strings[KeyMgmt.WAPI_CERT];
} else {
key = SSID + KeyMgmt.strings[KeyMgmt.NONE];
}
return key;
}
- /** @hide */
- @UnsupportedAppUsage
+ /**
+ * Get the IpConfiguration object associated with this WifiConfiguration.
+ * @hide
+ */
+ @NonNull
+ @SystemApi
public IpConfiguration getIpConfiguration() {
- return mIpConfiguration;
+ return new IpConfiguration(mIpConfiguration);
}
/**
@@ -2768,54 +2824,4 @@ public class WifiConfiguration implements Parcelable {
return new WifiConfiguration[size];
}
};
-
- /**
- * Serialize the Soft AP configuration contained in this object for backup.
- * @hide
- */
- @NonNull
- // TODO(b/144368124): this method should be removed once we migrate to SoftApConfiguration
- public byte[] getBytesForBackup() throws IOException {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- DataOutputStream out = new DataOutputStream(baos);
-
- out.writeInt(BACKUP_VERSION);
- BackupUtils.writeString(out, SSID);
- out.writeInt(apBand);
- out.writeInt(apChannel);
- BackupUtils.writeString(out, preSharedKey);
- out.writeInt(getAuthType());
- out.writeBoolean(hiddenSSID);
- return baos.toByteArray();
- }
-
- /**
- * Deserialize a byte array containing Soft AP configuration into a WifiConfiguration object.
- * @return The deserialized WifiConfiguration containing Soft AP configuration, or null if
- * the version contains a bad dataset e.g. Version 1
- * @throws BackupUtils.BadVersionException if the version is unrecognized
- * @hide
- */
- @Nullable
- // TODO(b/144368124): this method should be removed once we migrate to SoftApConfiguration
- public static WifiConfiguration getWifiConfigFromBackup(@NonNull DataInputStream in)
- throws IOException, BackupUtils.BadVersionException {
- WifiConfiguration config = new WifiConfiguration();
- int version = in.readInt();
- if (version < 1 || version > BACKUP_VERSION) {
- throw new BackupUtils.BadVersionException("Unknown Backup Serialization Version");
- }
-
- if (version == 1) return null; // Version 1 is a bad dataset.
-
- config.SSID = BackupUtils.readString(in);
- config.apBand = in.readInt();
- config.apChannel = in.readInt();
- config.preSharedKey = BackupUtils.readString(in);
- config.allowedKeyManagement.set(in.readInt());
- if (version >= 3) {
- config.hiddenSSID = in.readBoolean();
- }
- return config;
- }
}
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index 66b0590511fc..7a59a4f9be30 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -41,6 +41,36 @@ import java.util.Map;
*/
public class WifiEnterpriseConfig implements Parcelable {
+ /** Key prefix for WAPI AS certificates. */
+ public static final String WAPI_AS_CERTIFICATE = "WAPIAS_";
+
+ /** Key prefix for WAPI user certificates. */
+ public static final String WAPI_USER_CERTIFICATE = "WAPIUSR_";
+
+ /**
+ * Intent extra: name for WAPI AS certificates
+ */
+ public static final String EXTRA_WAPI_AS_CERTIFICATE_NAME =
+ "android.net.wifi.extra.WAPI_AS_CERTIFICATE_NAME";
+
+ /**
+ * Intent extra: data for WAPI AS certificates
+ */
+ public static final String EXTRA_WAPI_AS_CERTIFICATE_DATA =
+ "android.net.wifi.extra.WAPI_AS_CERTIFICATE_DATA";
+
+ /**
+ * Intent extra: name for WAPI AS certificates
+ */
+ public static final String EXTRA_WAPI_USER_CERTIFICATE_NAME =
+ "android.net.wifi.extra.WAPI_USER_CERTIFICATE_NAME";
+
+ /**
+ * Intent extra: data for WAPI AS certificates
+ */
+ public static final String EXTRA_WAPI_USER_CERTIFICATE_DATA =
+ "android.net.wifi.extra.WAPI_USER_CERTIFICATE_DATA";
+
/** @hide */
public static final String EMPTY_VALUE = "NULL";
/** @hide */
@@ -61,6 +91,7 @@ public class WifiEnterpriseConfig implements Parcelable {
public static final String DOM_SUFFIX_MATCH_KEY = "domain_suffix_match";
/** @hide */
public static final String OPP_KEY_CACHING = "proactive_key_caching";
+
/**
* String representing the keystore OpenSSL ENGINE's ID.
* @hide
@@ -130,6 +161,8 @@ public class WifiEnterpriseConfig implements Parcelable {
public static final String PLMN_KEY = "plmn";
/** @hide */
public static final String CA_CERT_ALIAS_DELIMITER = " ";
+ /** @hide */
+ public static final String WAPI_CERT_SUITE_KEY = "wapi_cert_suite";
/**
* Do not use OCSP stapling (TLS certificate status extension)
@@ -348,9 +381,12 @@ public class WifiEnterpriseConfig implements Parcelable {
public static final int AKA_PRIME = 6;
/** Hotspot 2.0 r2 OSEN */
public static final int UNAUTH_TLS = 7;
+ /** WAPI Certificate */
+ public static final int WAPI_CERT = 8;
/** @hide */
public static final String[] strings =
- { "PEAP", "TLS", "TTLS", "PWD", "SIM", "AKA", "AKA'", "WFA-UNAUTH-TLS" };
+ { "PEAP", "TLS", "TTLS", "PWD", "SIM", "AKA", "AKA'", "WFA-UNAUTH-TLS",
+ "WAPI_CERT" };
/** Prevent initialization */
private Eap() {}
@@ -494,6 +530,10 @@ public class WifiEnterpriseConfig implements Parcelable {
public void setEapMethod(int eapMethod) {
switch (eapMethod) {
/** Valid methods */
+ case Eap.WAPI_CERT:
+ mEapMethod = eapMethod;
+ setPhase2Method(Phase2.NONE);
+ break;
case Eap.TLS:
case Eap.UNAUTH_TLS:
setPhase2Method(Phase2.NONE);
@@ -1313,4 +1353,29 @@ public class WifiEnterpriseConfig implements Parcelable {
}
return false;
}
+
+ /**
+ * Set the WAPI certificate suite name on wpa_supplicant.
+ *
+ * If this field is not specified, WAPI-CERT uses ASU ID from WAI packet
+ * as the certificate suite name automatically.
+ *
+ * @param wapiCertSuite The name for WAPI certificate suite, or null/empty string to clear.
+ * @hide
+ */
+ @SystemApi
+ public void setWapiCertSuite(@Nullable String wapiCertSuite) {
+ setFieldValue(WAPI_CERT_SUITE_KEY, wapiCertSuite);
+ }
+
+ /**
+ * Get the WAPI certificate suite name
+ * @return the certificate suite name
+ * @hide
+ */
+ @Nullable
+ @SystemApi
+ public String getWapiCertSuite() {
+ return getFieldValue(WAPI_CERT_SUITE_KEY);
+ }
}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 9691bda2cf73..7693f9a1a79a 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -54,6 +54,7 @@ import android.text.TextUtils;
import android.util.CloseGuard;
import android.util.Log;
import android.util.Pair;
+import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
@@ -70,6 +71,7 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
+import java.util.StringTokenizer;
import java.util.concurrent.Executor;
/**
@@ -547,6 +549,7 @@ public class WifiManager {
* currently support general and no_channel
* @see #SAP_START_FAILURE_GENERAL
* @see #SAP_START_FAILURE_NO_CHANNEL
+ * @see #SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION
*
* @hide
*/
@@ -650,6 +653,7 @@ public class WifiManager {
@IntDef(flag = false, prefix = { "SAP_START_FAILURE_" }, value = {
SAP_START_FAILURE_GENERAL,
SAP_START_FAILURE_NO_CHANNEL,
+ SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION,
})
@Retention(RetentionPolicy.SOURCE)
public @interface SapStartFailure {}
@@ -671,6 +675,15 @@ public class WifiManager {
@SystemApi
public static final int SAP_START_FAILURE_NO_CHANNEL = 1;
+ /**
+ * If Wi-Fi AP start failed, this reason code means that the specified configuration
+ * is not supported by the current HAL version.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION = 2;
+
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = {"IFACE_IP_MODE_"}, value = {
@@ -1153,6 +1166,7 @@ public class WifiManager {
@UnsupportedAppUsage
public static final int RSSI_LEVELS = 5;
+ //TODO (b/146346676): This needs to be removed, not used in the code.
/**
* Auto settings in the driver. The driver could choose to operate on both
* 2.4 GHz and 5 GHz or make a dynamic decision on selecting the band.
@@ -2225,6 +2239,8 @@ public class WifiManager {
public static final long WIFI_FEATURE_MBO = 0x800000000L; // MBO Support
/** @hide */
public static final long WIFI_FEATURE_OCE = 0x1000000000L; // OCE Support
+ /** @hide */
+ public static final long WIFI_FEATURE_WAPI = 0x2000000000L; // WAPI
private long getSupportedFeatures() {
try {
@@ -2600,10 +2616,10 @@ public class WifiManager {
* Check if the device is dual mode capable i.e. supports concurrent STA + Soft AP.
*
* If the device is dual mode capable, it may require conversion of the user's Soft AP band
- * selection {@link WifiConfiguration#apBand} from {@link WifiConfiguration#AP_BAND_5GHZ} to
- * {@link WifiConfiguration#AP_BAND_ANY}, since if the device is connected to a 5GHz DFS
- * channel as a STA, it may be unable to honor a request to start Soft AP on the same DFS
- * channel.
+ * selection {@link SoftApConfiguration#mBand} from {@link SoftApConfiguration#BAND_5GHZ} to
+ * include also {@link SoftApConfiguration#BAND_2GHZ}, since if the device is connected to a
+ * 5GHz DFS channel as a STA, it may be unable to honor a request to start Soft AP on the same
+ * DFS channel.
*
* @return {@code true} if dual mode STA + AP is supported by this device, {@code false}
* otherwise.
@@ -3426,6 +3442,16 @@ public class WifiManager {
default void onInfoChanged(@NonNull SoftApInfo softApInfo) {
// Do nothing: can be updated to add SoftApInfo details (e.g. channel) to the UI.
}
+
+ /**
+ * Called when capability of softap changes.
+ *
+ * @param softApCapability is the softap capability. {@link SoftApCapability}
+ */
+ default void onCapabilityChanged(@NonNull SoftApCapability softApCapability) {
+ // Do nothing: can be updated to add SoftApCapability details (e.g. meximum supported
+ // client number) to the UI.
+ }
}
/**
@@ -3479,6 +3505,19 @@ public class WifiManager {
mCallback.onInfoChanged(softApInfo);
});
}
+
+ @Override
+ public void onCapabilityChanged(SoftApCapability capability) {
+ if (mVerboseLoggingEnabled) {
+ Log.v(TAG, "SoftApCallbackProxy: onCapabilityChanged: SoftApCapability="
+ + capability);
+ }
+
+ Binder.clearCallingIdentity();
+ mExecutor.execute(() -> {
+ mCallback.onCapabilityChanged(capability);
+ });
+ }
}
/**
@@ -4961,6 +5000,13 @@ public class WifiManager {
}
/**
+ * @return true if this device supports WAPI.
+ */
+ public boolean isWapiSupported() {
+ return isFeatureSupported(WIFI_FEATURE_WAPI);
+ }
+
+ /**
* Gets the factory Wi-Fi MAC addresses.
* @return Array of String representing Wi-Fi MAC addresses sorted lexically or an empty Array
* if failed.
@@ -5167,6 +5213,7 @@ public class WifiManager {
@Override
public void onSuccessConfigReceived(int newNetworkId) {
Log.d(TAG, "Easy Connect onSuccessConfigReceived callback");
+ Binder.clearCallingIdentity();
mExecutor.execute(() -> {
mEasyConnectStatusCallback.onEnrolleeSuccess(newNetworkId);
});
@@ -5175,22 +5222,28 @@ public class WifiManager {
@Override
public void onSuccess(int status) {
Log.d(TAG, "Easy Connect onSuccess callback");
+ Binder.clearCallingIdentity();
mExecutor.execute(() -> {
mEasyConnectStatusCallback.onConfiguratorSuccess(status);
});
}
@Override
- public void onFailure(int status) {
+ public void onFailure(int status, String ssid, String channelList,
+ int[] operatingClassArray) {
Log.d(TAG, "Easy Connect onFailure callback");
+ Binder.clearCallingIdentity();
mExecutor.execute(() -> {
- mEasyConnectStatusCallback.onFailure(status);
+ SparseArray<int[]> channelListArray = parseDppChannelList(channelList);
+ mEasyConnectStatusCallback.onFailure(status, ssid, channelListArray,
+ operatingClassArray);
});
}
@Override
public void onProgress(int status) {
Log.d(TAG, "Easy Connect onProgress callback");
+ Binder.clearCallingIdentity();
mExecutor.execute(() -> {
mEasyConnectStatusCallback.onProgress(status);
});
@@ -5522,4 +5575,77 @@ public class WifiManager {
throw e.rethrowFromSystemServer();
}
}
+
+ /**
+ * Parse the list of channels the DPP enrollee reports when it fails to find an AP.
+ *
+ * @param channelList List of channels in the format defined in the DPP specification.
+ * @return A parsed sparse array, where the operating class is the key.
+ * @hide
+ */
+ @VisibleForTesting
+ public static SparseArray<int[]> parseDppChannelList(String channelList) {
+ SparseArray<int[]> channelListArray = new SparseArray<>();
+
+ if (TextUtils.isEmpty(channelList)) {
+ return channelListArray;
+ }
+ StringTokenizer str = new StringTokenizer(channelList, ",");
+ String classStr = null;
+ List<Integer> channelsInClass = new ArrayList<>();
+
+ try {
+ while (str.hasMoreElements()) {
+ String cur = str.nextToken();
+
+ /**
+ * Example for a channel list:
+ *
+ * 81/1,2,3,4,5,6,7,8,9,10,11,115/36,40,44,48,118/52,56,60,64,121/100,104,108,112,
+ * 116,120,124,128,132,136,140,0/144,124/149,153,157,161,125/165
+ *
+ * Detect operating class by the delimiter of '/' and use a string tokenizer with
+ * ',' as a delimiter.
+ */
+ int classDelim = cur.indexOf('/');
+ if (classDelim != -1) {
+ if (classStr != null) {
+ // Store the last channel array in the sparse array, where the operating
+ // class is the key (as an integer).
+ int[] channelsArray = new int[channelsInClass.size()];
+ for (int i = 0; i < channelsInClass.size(); i++) {
+ channelsArray[i] = channelsInClass.get(i);
+ }
+ channelListArray.append(Integer.parseInt(classStr), channelsArray);
+ channelsInClass = new ArrayList<>();
+ }
+
+ // Init a new operating class and store the first channel
+ classStr = cur.substring(0, classDelim);
+ String channelStr = cur.substring(classDelim + 1);
+ channelsInClass.add(Integer.parseInt(channelStr));
+ } else {
+ if (classStr == null) {
+ // Invalid format
+ Log.e(TAG, "Cannot parse DPP channel list");
+ return new SparseArray<>();
+ }
+ channelsInClass.add(Integer.parseInt(cur));
+ }
+ }
+
+ // Store the last array
+ if (classStr != null) {
+ int[] channelsArray = new int[channelsInClass.size()];
+ for (int i = 0; i < channelsInClass.size(); i++) {
+ channelsArray[i] = channelsInClass.get(i);
+ }
+ channelListArray.append(Integer.parseInt(classStr), channelsArray);
+ }
+ return channelListArray;
+ } catch (NumberFormatException e) {
+ Log.e(TAG, "Cannot parse DPP channel list");
+ return new SparseArray<>();
+ }
+ }
}
diff --git a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
index 9fd29ae8d14a..9c1475ffc8cd 100644
--- a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
+++ b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
@@ -122,6 +122,16 @@ public final class WifiNetworkSuggestion implements Parcelable {
* Whether the setIsUserAllowedToManuallyConnect have been called.
*/
private boolean mIsUserAllowedBeenSet;
+ /**
+ * Pre-shared key for use with WAPI-PSK networks.
+ */
+ private @Nullable String mWapiPskPassphrase;
+
+ /**
+ * The enterprise configuration details specifying the EAP method,
+ * certificates and other settings associated with the WAPI networks.
+ */
+ private @Nullable WifiEnterpriseConfig mWapiEnterpriseConfig;
public Builder() {
mSsid = null;
@@ -140,6 +150,8 @@ public final class WifiNetworkSuggestion implements Parcelable {
mIsUserAllowedBeenSet = false;
mPriority = UNASSIGNED_PRIORITY;
mCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
+ mWapiPskPassphrase = null;
+ mWapiEnterpriseConfig = null;
}
/**
@@ -294,6 +306,39 @@ public final class WifiNetworkSuggestion implements Parcelable {
}
/**
+ * Set the ASCII WAPI passphrase for this network. Needed for authenticating to
+ * WAPI-PSK networks.
+ *
+ * @param passphrase passphrase of the network.
+ * @return Instance of {@link Builder} to enable chaining of the builder method.
+ * @throws IllegalArgumentException if the passphrase is not ASCII encodable.
+ *
+ */
+ public @NonNull Builder setWapiPassphrase(@NonNull String passphrase) {
+ checkNotNull(passphrase);
+ final CharsetEncoder asciiEncoder = StandardCharsets.US_ASCII.newEncoder();
+ if (!asciiEncoder.canEncode(passphrase)) {
+ throw new IllegalArgumentException("passphrase not ASCII encodable");
+ }
+ mWapiPskPassphrase = passphrase;
+ return this;
+ }
+
+ /**
+ * Set the associated enterprise configuration for this network. Needed for authenticating
+ * to WAPI-CERT networks. See {@link WifiEnterpriseConfig} for description.
+ *
+ * @param enterpriseConfig Instance of {@link WifiEnterpriseConfig}.
+ * @return Instance of {@link Builder} to enable chaining of the builder method.
+ */
+ public @NonNull Builder setWapiEnterpriseConfig(
+ @NonNull WifiEnterpriseConfig enterpriseConfig) {
+ checkNotNull(enterpriseConfig);
+ mWapiEnterpriseConfig = new WifiEnterpriseConfig(enterpriseConfig);
+ return this;
+ }
+
+ /**
* Specifies whether this represents a hidden network.
* <p>
* <li>If not set, defaults to false (i.e not a hidden network).</li>
@@ -413,6 +458,13 @@ public final class WifiNetworkSuggestion implements Parcelable {
configuration.enterpriseConfig = mWpa3EnterpriseConfig;
} else if (mIsEnhancedOpen) { // OWE network
configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OWE);
+ } else if (!TextUtils.isEmpty(mWapiPskPassphrase)) { // WAPI-PSK network.
+ configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_WAPI_PSK);
+ // WifiConfiguration.preSharedKey needs quotes around ASCII password.
+ configuration.preSharedKey = "\"" + mWapiPskPassphrase + "\"";
+ } else if (mWapiEnterpriseConfig != null) { // WAPI-CERT network
+ configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_WAPI_CERT);
+ configuration.enterpriseConfig = mWapiEnterpriseConfig;
} else { // Open network
configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OPEN);
}
@@ -446,13 +498,16 @@ public final class WifiNetworkSuggestion implements Parcelable {
numSecurityTypes += mIsEnhancedOpen ? 1 : 0;
numSecurityTypes += !TextUtils.isEmpty(mWpa2PskPassphrase) ? 1 : 0;
numSecurityTypes += !TextUtils.isEmpty(mWpa3SaePassphrase) ? 1 : 0;
+ numSecurityTypes += !TextUtils.isEmpty(mWapiPskPassphrase) ? 1 : 0;
numSecurityTypes += mWpa2EnterpriseConfig != null ? 1 : 0;
numSecurityTypes += mWpa3EnterpriseConfig != null ? 1 : 0;
+ numSecurityTypes += mWapiEnterpriseConfig != null ? 1 : 0;
numSecurityTypes += mPasspointConfiguration != null ? 1 : 0;
if (numSecurityTypes > 1) {
throw new IllegalStateException("only one of setIsEnhancedOpen, setWpa2Passphrase,"
- + "setWpa3Passphrase, setWpa2EnterpriseConfig, setWpa3EnterpriseConfig"
- + "or setPasspointConfig can be invoked for network suggestion");
+ + " setWpa3Passphrase, setWpa2EnterpriseConfig, setWpa3EnterpriseConfig"
+ + " setWapiPassphrase, setWapiCertSuite, setIsWapiCertSuiteAuto"
+ + " or setPasspointConfig can be invoked for network suggestion");
}
}
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index 8fedda48aa0d..8badcc0c2552 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -724,21 +724,6 @@ public class WifiScanner {
public int min24GHzRssi;
/** Minimum 6GHz RSSI for a BSSID to be considered */
public int min6GHzRssi;
- /** Maximum score that a network can have before bonuses */
- public int initialScoreMax;
- /**
- * Only report when there is a network's score this much higher
- * than the current connection.
- */
- public int currentConnectionBonus;
- /** score bonus for all networks with the same network flag */
- public int sameNetworkBonus;
- /** score bonus for networks that are not open */
- public int secureBonus;
- /** 5GHz RSSI score bonus (applied to all 5GHz networks) */
- public int band5GHzBonus;
- /** 6GHz RSSI score bonus (applied to all 5GHz networks) */
- public int band6GHzBonus;
/** Pno Network filter list */
public PnoNetwork[] networkList;
@@ -753,12 +738,6 @@ public class WifiScanner {
dest.writeInt(min5GHzRssi);
dest.writeInt(min24GHzRssi);
dest.writeInt(min6GHzRssi);
- dest.writeInt(initialScoreMax);
- dest.writeInt(currentConnectionBonus);
- dest.writeInt(sameNetworkBonus);
- dest.writeInt(secureBonus);
- dest.writeInt(band5GHzBonus);
- dest.writeInt(band6GHzBonus);
if (networkList != null) {
dest.writeInt(networkList.length);
for (int i = 0; i < networkList.length; i++) {
@@ -781,12 +760,6 @@ public class WifiScanner {
settings.min5GHzRssi = in.readInt();
settings.min24GHzRssi = in.readInt();
settings.min6GHzRssi = in.readInt();
- settings.initialScoreMax = in.readInt();
- settings.currentConnectionBonus = in.readInt();
- settings.sameNetworkBonus = in.readInt();
- settings.secureBonus = in.readInt();
- settings.band5GHzBonus = in.readInt();
- settings.band6GHzBonus = in.readInt();
int numNetworks = in.readInt();
settings.networkList = new PnoNetwork[numNetworks];
for (int i = 0; i < numNetworks; i++) {
diff --git a/wifi/java/android/net/wifi/aware/Characteristics.java b/wifi/java/android/net/wifi/aware/Characteristics.java
index e2cf4dc02659..d5fd48e9e7b3 100644
--- a/wifi/java/android/net/wifi/aware/Characteristics.java
+++ b/wifi/java/android/net/wifi/aware/Characteristics.java
@@ -16,10 +16,14 @@
package android.net.wifi.aware;
+import android.annotation.IntDef;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* The characteristics of the Wi-Fi Aware implementation.
*/
@@ -31,6 +35,8 @@ public final class Characteristics implements Parcelable {
"key_max_service_specific_info_length";
/** @hide */
public static final String KEY_MAX_MATCH_FILTER_LENGTH = "key_max_match_filter_length";
+ /** @hide */
+ public static final String KEY_SUPPORTED_CIPHER_SUITES = "key_supported_cipher_suites";
private Bundle mCharacteristics = new Bundle();
@@ -71,12 +77,41 @@ public final class Characteristics implements Parcelable {
* {@link PublishConfig.Builder#setMatchFilter(java.util.List)} and
* {@link SubscribeConfig.Builder#setMatchFilter(java.util.List)}.
*
- * @return A positive integer, maximum legngth of byte array for Aware discovery match filter.
+ * @return A positive integer, maximum length of byte array for Aware discovery match filter.
*/
public int getMaxMatchFilterLength() {
return mCharacteristics.getInt(KEY_MAX_MATCH_FILTER_LENGTH);
}
+ /** @hide */
+ @IntDef(flag = true, prefix = { "WIFI_AWARE_CIPHER_SUITE_" }, value = {
+ WIFI_AWARE_CIPHER_SUITE_NCS_SK_128,
+ WIFI_AWARE_CIPHER_SUITE_NCS_SK_256,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface WifiAwareCipherSuites {}
+
+ /**
+ * Wi-Fi Aware supported ciphier suite representing NCS SK 128: 128 bit shared-key.
+ */
+ public static final int WIFI_AWARE_CIPHER_SUITE_NCS_SK_128 = 1 << 0;
+
+ /**
+ * Wi-Fi Aware supported ciphier suite representing NCS SK 256: 256 bit shared-key.
+ */
+ public static final int WIFI_AWARE_CIPHER_SUITE_NCS_SK_256 = 1 << 1;
+
+ /**
+ * Returns the set of cipher suites supported by the device for use in Wi-Fi Aware data-paths.
+ * The device automatically picks the strongest cipher suite when initiating a data-path setup.
+ *
+ * @return A set of flags from {@link #WIFI_AWARE_CIPHER_SUITE_NCS_SK_128}, or
+ * {@link #WIFI_AWARE_CIPHER_SUITE_NCS_SK_256}.
+ */
+ public @WifiAwareCipherSuites int getSupportedCipherSuites() {
+ return mCharacteristics.getInt(KEY_SUPPORTED_CIPHER_SUITES);
+ }
+
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeBundle(mCharacteristics);
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
index 495b1bb9ba82..c9bca4f20f03 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
@@ -48,21 +48,29 @@ public class WifiP2pConfig implements Parcelable {
*/
public WpsInfo wps;
- /**
- * The network name of a group, should be configured by helper method
- */
+ /** Get the network name of this P2P configuration, or null if unset. */
+ @Nullable
+ public String getNetworkName() {
+ return networkName;
+ }
+
/** @hide */
public String networkName = "";
- /**
- * The passphrase of a group, should be configured by helper method
- */
+ /** Get the passphrase of this P2P configuration, or null if unset. */
+ @Nullable
+ public String getPassphrase() {
+ return passphrase;
+ }
+
/** @hide */
public String passphrase = "";
- /**
- * The required band for Group Owner
- */
+ /** Get the required band for the group owner. */
+ public int getGroupOwnerBand() {
+ return groupOwnerBand;
+ }
+
/** @hide */
public int groupOwnerBand = GROUP_OWNER_BAND_AUTO;
@@ -123,6 +131,15 @@ public class WifiP2pConfig implements Parcelable {
@UnsupportedAppUsage
public int netId = WifiP2pGroup.PERSISTENT_NET_ID;
+ /**
+ * Get the network ID of this P2P configuration.
+ * @return either a non-negative network ID, or one of {@link WifiP2pGroup#PERSISTENT_NET_ID} or
+ * {@link WifiP2pGroup#TEMPORARY_NET_ID}.
+ */
+ public int getNetworkId() {
+ return netId;
+ }
+
public WifiP2pConfig() {
//set defaults
wps = new WpsInfo();
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java b/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java
index f9d1266cf804..d8c50f2ed5f8 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java
@@ -39,18 +39,15 @@ public class WifiP2pGroup implements Parcelable {
/**
* The temporary network id.
- *
- * @hide
+ * @see #getNetworkId()
*/
- @UnsupportedAppUsage
public static final int TEMPORARY_NET_ID = -1;
/**
* The persistent network id.
* If a matching persistent profile is found, use it.
* Otherwise, create a new persistent profile.
- *
- * @hide
+ * @see #getNetworkId()
*/
public static final int PERSISTENT_NET_ID = -2;
diff --git a/wifi/java/android/net/wifi/wificond/NativeScanResult.java b/wifi/java/android/net/wifi/wificond/NativeScanResult.java
index ff8e935da8c0..6ed17081bdb5 100644
--- a/wifi/java/android/net/wifi/wificond/NativeScanResult.java
+++ b/wifi/java/android/net/wifi/wificond/NativeScanResult.java
@@ -16,46 +16,163 @@
package android.net.wifi.wificond;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;
/**
- * ScanResult from wificond
+ * Raw scan result data from the wificond daemon.
*
* @hide
*/
-public class NativeScanResult implements Parcelable {
+@SystemApi
+public final class NativeScanResult implements Parcelable {
private static final int CAPABILITY_SIZE = 16;
+ /** @hide */
+ @VisibleForTesting
public byte[] ssid;
+ /** @hide */
+ @VisibleForTesting
public byte[] bssid;
+ /** @hide */
+ @VisibleForTesting
public byte[] infoElement;
+ /** @hide */
+ @VisibleForTesting
public int frequency;
+ /** @hide */
+ @VisibleForTesting
public int signalMbm;
+ /** @hide */
+ @VisibleForTesting
public long tsf;
+ /** @hide */
+ @VisibleForTesting
public BitSet capability;
+ /** @hide */
+ @VisibleForTesting
public boolean associated;
+ /** @hide */
+ @VisibleForTesting
public List<RadioChainInfo> radioChainInfos;
- /** public constructor */
- public NativeScanResult() { }
+ /**
+ * Returns the SSID raw byte array of the AP represented by this scan result.
+ *
+ * @return A byte array.
+ */
+ @NonNull public byte[] getSsid() {
+ return ssid;
+ }
+
+ /**
+ * Returns raw bytes representing the MAC address (BSSID) of the AP represented by this scan
+ * result.
+ *
+ * @return a byte array, possibly null or containing the incorrect number of bytes for a MAC
+ * address.
+ */
+ @NonNull public byte[] getBssid() {
+ return bssid;
+ }
+
+ /**
+ * Returns the raw bytes of the information element advertised by the AP represented by this
+ * scan result.
+ *
+ * @return A byte array, possibly null or containing an invalid TLV configuration.
+ */
+ @NonNull public byte[] getInformationElements() {
+ return infoElement;
+ }
+
+ /**
+ * Returns the frequency (in MHz) on which the AP represented by this scan result was observed.
+ *
+ * @return The frequency in MHz.
+ */
+ public int getFrequencyMhz() {
+ return frequency;
+ }
+
+ /**
+ * Return the signal strength of probe response/beacon in (100 * dBm).
+ *
+ * @return Signal strenght in (100 * dBm).
+ */
+ public int getSignalMbm() {
+ return signalMbm;
+ }
- /** copy constructor */
- public NativeScanResult(NativeScanResult source) {
- ssid = source.ssid.clone();
- bssid = source.bssid.clone();
- infoElement = source.infoElement.clone();
- frequency = source.frequency;
- signalMbm = source.signalMbm;
- tsf = source.tsf;
- capability = (BitSet) source.capability.clone();
- associated = source.associated;
+ /**
+ * Return the TSF (Timing Synchronization Function) of the received probe response/beacon.
+ * @return
+ */
+ public long getTsf() {
+ return tsf;
}
+ /**
+ * Return a boolean indicating whether or not we're associated to the AP represented by this
+ * scan result.
+ *
+ * @return A boolean indicating association.
+ */
+ public boolean isAssociated() {
+ return associated;
+ }
+
+ /**
+ * Returns the capabilities of the AP repseresented by this scan result as advertised in the
+ * received probe response or beacon.
+ *
+ * This is a bit mask describing the capabilities of a BSS. See IEEE Std 802.11: 8.4.1.4:
+ * Bit 0 - ESS
+ * Bit 1 - IBSS
+ * Bit 2 - CF Pollable
+ * Bit 3 - CF-Poll Request
+ * Bit 4 - Privacy
+ * Bit 5 - Short Preamble
+ * Bit 6 - PBCC
+ * Bit 7 - Channel Agility
+ * Bit 8 - Spectrum Mgmt
+ * Bit 9 - QoS
+ * Bit 10 - Short Slot Time
+ * Bit 11 - APSD
+ * Bit 12 - Radio Measurement
+ * Bit 13 - DSSS-OFDM
+ * Bit 14 - Delayed Block Ack
+ * Bit 15 - Immediate Block Ack
+ *
+ * @return a bit mask of capabilities.
+ */
+ @NonNull public BitSet getCapabilities() {
+ return capability;
+ }
+
+ /**
+ * Returns details of the signal received on each radio chain for the AP represented by this
+ * scan result in a list of {@link RadioChainInfo} elements.
+ *
+ * @return A list of {@link RadioChainInfo} - possibly empty in case of error.
+ */
+ @NonNull public List<RadioChainInfo> getRadioChainInfos() {
+ return radioChainInfos;
+ }
+
+ /**
+ * @hide
+ */
+ public NativeScanResult() { }
+
/** implement Parcelable interface */
@Override
public int describeContents() {
@@ -64,7 +181,7 @@ public class NativeScanResult implements Parcelable {
/** implement Parcelable interface */
@Override
- public void writeToParcel(Parcel out, int flags) {
+ public void writeToParcel(@NonNull Parcel out, int flags) {
out.writeByteArray(ssid);
out.writeByteArray(bssid);
out.writeByteArray(infoElement);
@@ -83,14 +200,23 @@ public class NativeScanResult implements Parcelable {
}
/** implement Parcelable interface */
- public static final Parcelable.Creator<NativeScanResult> CREATOR =
+ @NonNull public static final Parcelable.Creator<NativeScanResult> CREATOR =
new Parcelable.Creator<NativeScanResult>() {
@Override
public NativeScanResult createFromParcel(Parcel in) {
NativeScanResult result = new NativeScanResult();
result.ssid = in.createByteArray();
+ if (result.ssid == null) {
+ result.ssid = new byte[0];
+ }
result.bssid = in.createByteArray();
+ if (result.bssid == null) {
+ result.bssid = new byte[0];
+ }
result.infoElement = in.createByteArray();
+ if (result.infoElement == null) {
+ result.infoElement = new byte[0];
+ }
result.frequency = in.readInt();
result.signalMbm = in.readInt();
result.tsf = in.readLong();
diff --git a/wifi/java/android/net/wifi/wificond/NativeWifiClient.java b/wifi/java/android/net/wifi/wificond/NativeWifiClient.java
index 4994ebd33216..554f9295ef0d 100644
--- a/wifi/java/android/net/wifi/wificond/NativeWifiClient.java
+++ b/wifi/java/android/net/wifi/wificond/NativeWifiClient.java
@@ -16,21 +16,32 @@
package android.net.wifi.wificond;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.Arrays;
/**
- * NativeWifiClient for wificond
+ * Structure providing information about clients (STAs) associated with a SoftAp.
*
* @hide
*/
-public class NativeWifiClient implements Parcelable {
- public byte[] macAddress;
+@SystemApi
+public final class NativeWifiClient implements Parcelable {
+ /**
+ * The raw bytes of the MAC address of the client (STA) represented by this object.
+ */
+ @NonNull public final byte[] macAddress;
- /** public constructor */
- public NativeWifiClient() { }
+ /**
+ * public constructor
+ * @hide
+ */
+ public NativeWifiClient(@NonNull byte[] macAddress) {
+ this.macAddress = macAddress;
+ }
/** override comparator */
@Override
@@ -60,18 +71,20 @@ public class NativeWifiClient implements Parcelable {
* |flag| is ignored.
*/
@Override
- public void writeToParcel(Parcel out, int flags) {
+ public void writeToParcel(@NonNull Parcel out, int flags) {
out.writeByteArray(macAddress);
}
/** implement Parcelable interface */
- public static final Parcelable.Creator<NativeWifiClient> CREATOR =
+ @NonNull public static final Parcelable.Creator<NativeWifiClient> CREATOR =
new Parcelable.Creator<NativeWifiClient>() {
@Override
public NativeWifiClient createFromParcel(Parcel in) {
- NativeWifiClient result = new NativeWifiClient();
- result.macAddress = in.createByteArray();
- return result;
+ byte[] macAddress = in.createByteArray();
+ if (macAddress == null) {
+ macAddress = new byte[0];
+ }
+ return new NativeWifiClient(macAddress);
}
@Override
diff --git a/wifi/java/android/net/wifi/wificond/PnoNetwork.java b/wifi/java/android/net/wifi/wificond/PnoNetwork.java
index f923fd384a90..ca0b1cfb6223 100644
--- a/wifi/java/android/net/wifi/wificond/PnoNetwork.java
+++ b/wifi/java/android/net/wifi/wificond/PnoNetwork.java
@@ -16,6 +16,8 @@
package android.net.wifi.wificond;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -23,17 +25,85 @@ import java.util.Arrays;
import java.util.Objects;
/**
- * PnoNetwork for wificond
+ * Configuration for a PNO (preferred network offload) network used in {@link PnoSettings}. A PNO
+ * network allows configuration of a specific network to search for.
*
* @hide
*/
-public class PnoNetwork implements Parcelable {
+@SystemApi
+public final class PnoNetwork implements Parcelable {
+ private boolean mIsHidden;
+ private byte[] mSsid;
+ private int[] mFrequencies;
- public boolean isHidden;
- public byte[] ssid;
- public int[] frequencies;
+ /**
+ * Indicates whether the PNO network configuration is for a hidden SSID - i.e. a network which
+ * does not broadcast its SSID and must be queried explicitly.
+ *
+ * @return True if the configuration is for a hidden network, false otherwise.
+ */
+ public boolean isHidden() {
+ return mIsHidden;
+ }
+
+ /**
+ * Configure whether the PNO network configuration is for a hidden SSID - i.e. a network which
+ * does not broadcast its SSID and must be queried explicitly.
+ *
+ * @param isHidden True if the configuration is for a hidden network, false otherwise.
+ */
+ public void setHidden(boolean isHidden) {
+ mIsHidden = isHidden;
+ }
+
+ /**
+ * Get the raw bytes for the SSID of the PNO network being scanned for.
+ *
+ * @return A byte array.
+ */
+ @NonNull public byte[] getSsid() {
+ return mSsid;
+ }
+
+ /**
+ * Set the raw bytes for the SSID of the PNO network being scanned for.
+ *
+ * @param ssid A byte array.
+ */
+ public void setSsid(@NonNull byte[] ssid) {
+ if (ssid == null) {
+ throw new IllegalArgumentException("null argument");
+ }
+ this.mSsid = ssid;
+ }
+
+ /**
+ * Get the frequencies (in MHz) on which to PNO scan for the current network is being searched
+ * for. A null return (i.e. no frequencies configured) indicates that the network is search for
+ * on all supported frequencies.
+ *
+ * @return A array of frequencies (in MHz), a null indicates no configured frequencies.
+ */
+ @NonNull public int[] getFrequenciesMhz() {
+ return mFrequencies;
+ }
+
+ /**
+ * Set the frequencies (in MHz) on which to PNO scan for the current network is being searched
+ * for. A null configuration (i.e. no frequencies configured) indicates that the network is
+ * search for on all supported frequencies.
+ *
+ * @param frequenciesMhz an array of frequencies (in MHz), null indicating no configured
+ * frequencies.
+ */
+ public void setFrequenciesMhz(@NonNull int[] frequenciesMhz) {
+ if (frequenciesMhz == null) {
+ throw new IllegalArgumentException("null argument");
+ }
+ this.mFrequencies = frequenciesMhz;
+ }
- /** public constructor */
+ /** Construct an uninitialized PnoNetwork object */
public PnoNetwork() { }
/** override comparator */
@@ -44,18 +114,18 @@ public class PnoNetwork implements Parcelable {
return false;
}
PnoNetwork network = (PnoNetwork) rhs;
- return Arrays.equals(ssid, network.ssid)
- && Arrays.equals(frequencies, network.frequencies)
- && isHidden == network.isHidden;
+ return Arrays.equals(mSsid, network.mSsid)
+ && Arrays.equals(mFrequencies, network.mFrequencies)
+ && mIsHidden == network.mIsHidden;
}
/** override hash code */
@Override
public int hashCode() {
return Objects.hash(
- isHidden,
- Arrays.hashCode(ssid),
- Arrays.hashCode(frequencies));
+ mIsHidden,
+ Arrays.hashCode(mSsid),
+ Arrays.hashCode(mFrequencies));
}
/** implement Parcelable interface */
@@ -69,21 +139,27 @@ public class PnoNetwork implements Parcelable {
* |flag| is ignored.
*/
@Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(isHidden ? 1 : 0);
- out.writeByteArray(ssid);
- out.writeIntArray(frequencies);
+ public void writeToParcel(@NonNull Parcel out, int flags) {
+ out.writeInt(mIsHidden ? 1 : 0);
+ out.writeByteArray(mSsid);
+ out.writeIntArray(mFrequencies);
}
/** implement Parcelable interface */
- public static final Parcelable.Creator<PnoNetwork> CREATOR =
+ @NonNull public static final Parcelable.Creator<PnoNetwork> CREATOR =
new Parcelable.Creator<PnoNetwork>() {
@Override
public PnoNetwork createFromParcel(Parcel in) {
PnoNetwork result = new PnoNetwork();
- result.isHidden = in.readInt() != 0 ? true : false;
- result.ssid = in.createByteArray();
- result.frequencies = in.createIntArray();
+ result.mIsHidden = in.readInt() != 0 ? true : false;
+ result.mSsid = in.createByteArray();
+ if (result.mSsid == null) {
+ result.mSsid = new byte[0];
+ }
+ result.mFrequencies = in.createIntArray();
+ if (result.mFrequencies == null) {
+ result.mFrequencies = new int[0];
+ }
return result;
}
diff --git a/wifi/java/android/net/wifi/wificond/PnoSettings.java b/wifi/java/android/net/wifi/wificond/PnoSettings.java
index 96cf24fdfb81..57c9ca5fd302 100644
--- a/wifi/java/android/net/wifi/wificond/PnoSettings.java
+++ b/wifi/java/android/net/wifi/wificond/PnoSettings.java
@@ -16,27 +16,130 @@
package android.net.wifi.wificond;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.ArrayList;
+import java.util.List;
import java.util.Objects;
/**
- * PnoSettings for wificond
+ * Configuration for a PNO (preferred network offload). A mechanism by which scans are offloaded
+ * from the host device to the Wi-Fi chip.
*
* @hide
*/
-public class PnoSettings implements Parcelable {
- public int intervalMs;
- public int min2gRssi;
- public int min5gRssi;
- public int min6gRssi;
- public ArrayList<PnoNetwork> pnoNetworks;
-
- /** public constructor */
+@SystemApi
+public final class PnoSettings implements Parcelable {
+ private int mIntervalMs;
+ private int mMin2gRssi;
+ private int mMin5gRssi;
+ private int mMin6gRssi;
+ private List<PnoNetwork> mPnoNetworks;
+
+ /** Construct an uninitialized PnoSettings object */
public PnoSettings() { }
+ /**
+ * Get the requested PNO scan interval in milliseconds.
+ *
+ * @return An interval in milliseconds.
+ */
+ public int getIntervalMillis() {
+ return mIntervalMs;
+ }
+
+ /**
+ * Set the requested PNO scan interval in milliseconds.
+ *
+ * @param intervalMs An interval in milliseconds.
+ */
+ public void setIntervalMillis(int intervalMs) {
+ this.mIntervalMs = intervalMs;
+ }
+
+ /**
+ * Get the requested minimum RSSI threshold (in dBm) for APs to report in scan results in the
+ * 2.4GHz band.
+ *
+ * @return An RSSI value in dBm.
+ */
+ public int getMin2gRssiDbm() {
+ return mMin2gRssi;
+ }
+
+ /**
+ * Set the requested minimum RSSI threshold (in dBm) for APs to report in scan scan results in
+ * the 2.4GHz band.
+ *
+ * @param min2gRssiDbm An RSSI value in dBm.
+ */
+ public void setMin2gRssiDbm(int min2gRssiDbm) {
+ this.mMin2gRssi = min2gRssiDbm;
+ }
+
+ /**
+ * Get the requested minimum RSSI threshold (in dBm) for APs to report in scan results in the
+ * 5GHz band.
+ *
+ * @return An RSSI value in dBm.
+ */
+ public int getMin5gRssiDbm() {
+ return mMin5gRssi;
+ }
+
+ /**
+ * Set the requested minimum RSSI threshold (in dBm) for APs to report in scan scan results in
+ * the 5GHz band.
+ *
+ * @param min5gRssiDbm An RSSI value in dBm.
+ */
+ public void setMin5gRssiDbm(int min5gRssiDbm) {
+ this.mMin5gRssi = min5gRssiDbm;
+ }
+
+ /**
+ * Get the requested minimum RSSI threshold (in dBm) for APs to report in scan results in the
+ * 6GHz band.
+ *
+ * @return An RSSI value in dBm.
+ */
+ public int getMin6gRssiDbm() {
+ return mMin6gRssi;
+ }
+
+ /**
+ * Set the requested minimum RSSI threshold (in dBm) for APs to report in scan scan results in
+ * the 6GHz band.
+ *
+ * @param min6gRssiDbm An RSSI value in dBm.
+ */
+ public void setMin6gRssiDbm(int min6gRssiDbm) {
+ this.mMin6gRssi = min6gRssiDbm;
+ }
+
+ /**
+ * Return the configured list of specific networks to search for in a PNO scan.
+ *
+ * @return A list of {@link PnoNetwork} objects, possibly empty if non configured.
+ */
+ @NonNull public List<PnoNetwork> getPnoNetworks() {
+ return mPnoNetworks;
+ }
+
+ /**
+ * Set the list of specified networks to scan for in a PNO scan. The networks (APs) are
+ * specified using {@link PnoNetwork}s. An empty list indicates that all networks are scanned
+ * for.
+ *
+ * @param pnoNetworks A (possibly empty) list of {@link PnoNetwork} objects.
+ */
+ public void setPnoNetworks(@NonNull List<PnoNetwork> pnoNetworks) {
+ this.mPnoNetworks = pnoNetworks;
+ }
+
/** override comparator */
@Override
public boolean equals(Object rhs) {
@@ -48,17 +151,17 @@ public class PnoSettings implements Parcelable {
if (settings == null) {
return false;
}
- return intervalMs == settings.intervalMs
- && min2gRssi == settings.min2gRssi
- && min5gRssi == settings.min5gRssi
- && min6gRssi == settings.min6gRssi
- && pnoNetworks.equals(settings.pnoNetworks);
+ return mIntervalMs == settings.mIntervalMs
+ && mMin2gRssi == settings.mMin2gRssi
+ && mMin5gRssi == settings.mMin5gRssi
+ && mMin6gRssi == settings.mMin6gRssi
+ && mPnoNetworks.equals(settings.mPnoNetworks);
}
/** override hash code */
@Override
public int hashCode() {
- return Objects.hash(intervalMs, min2gRssi, min5gRssi, min6gRssi, pnoNetworks);
+ return Objects.hash(mIntervalMs, mMin2gRssi, mMin5gRssi, mMin6gRssi, mPnoNetworks);
}
/** implement Parcelable interface */
@@ -72,27 +175,27 @@ public class PnoSettings implements Parcelable {
* |flag| is ignored.
**/
@Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(intervalMs);
- out.writeInt(min2gRssi);
- out.writeInt(min5gRssi);
- out.writeInt(min6gRssi);
- out.writeTypedList(pnoNetworks);
+ public void writeToParcel(@NonNull Parcel out, int flags) {
+ out.writeInt(mIntervalMs);
+ out.writeInt(mMin2gRssi);
+ out.writeInt(mMin5gRssi);
+ out.writeInt(mMin6gRssi);
+ out.writeTypedList(mPnoNetworks);
}
/** implement Parcelable interface */
- public static final Parcelable.Creator<PnoSettings> CREATOR =
+ @NonNull public static final Parcelable.Creator<PnoSettings> CREATOR =
new Parcelable.Creator<PnoSettings>() {
@Override
public PnoSettings createFromParcel(Parcel in) {
PnoSettings result = new PnoSettings();
- result.intervalMs = in.readInt();
- result.min2gRssi = in.readInt();
- result.min5gRssi = in.readInt();
- result.min6gRssi = in.readInt();
+ result.mIntervalMs = in.readInt();
+ result.mMin2gRssi = in.readInt();
+ result.mMin5gRssi = in.readInt();
+ result.mMin6gRssi = in.readInt();
- result.pnoNetworks = new ArrayList<PnoNetwork>();
- in.readTypedList(result.pnoNetworks, PnoNetwork.CREATOR);
+ result.mPnoNetworks = new ArrayList<>();
+ in.readTypedList(result.mPnoNetworks, PnoNetwork.CREATOR);
return result;
}
diff --git a/wifi/java/android/net/wifi/wificond/RadioChainInfo.java b/wifi/java/android/net/wifi/wificond/RadioChainInfo.java
index 2b03450b1357..64102dde94c0 100644
--- a/wifi/java/android/net/wifi/wificond/RadioChainInfo.java
+++ b/wifi/java/android/net/wifi/wificond/RadioChainInfo.java
@@ -16,26 +16,52 @@
package android.net.wifi.wificond;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.util.Objects;
/**
- * RadioChainInfo for wificond
+ * A class representing the radio chains of the Wi-Fi modems. Use to provide raw information about
+ * signals received on different radio chains.
*
* @hide
*/
-public class RadioChainInfo implements Parcelable {
+@SystemApi
+public final class RadioChainInfo implements Parcelable {
private static final String TAG = "RadioChainInfo";
+ /** @hide */
+ @VisibleForTesting
public int chainId;
+ /** @hide */
+ @VisibleForTesting
public int level;
+ /**
+ * Return an identifier for this radio chain. This is an arbitrary ID which is consistent for
+ * the same device.
+ *
+ * @return The radio chain ID.
+ */
+ public int getChainId() {
+ return chainId;
+ }
- /** public constructor */
- public RadioChainInfo() { }
+ /**
+ * Returns the detected signal level on this radio chain in dBm (aka RSSI).
+ *
+ * @return A signal level in dBm.
+ */
+ public int getLevelDbm() {
+ return level;
+ }
+ /** @hide */
public RadioChainInfo(int chainId, int level) {
this.chainId = chainId;
this.level = level;
@@ -73,23 +99,20 @@ public class RadioChainInfo implements Parcelable {
* |flags| is ignored.
*/
@Override
- public void writeToParcel(Parcel out, int flags) {
+ public void writeToParcel(@NonNull Parcel out, int flags) {
out.writeInt(chainId);
out.writeInt(level);
}
/** implement Parcelable interface */
- public static final Parcelable.Creator<RadioChainInfo> CREATOR =
+ @NonNull public static final Parcelable.Creator<RadioChainInfo> CREATOR =
new Parcelable.Creator<RadioChainInfo>() {
/**
* Caller is responsible for providing a valid parcel.
*/
@Override
public RadioChainInfo createFromParcel(Parcel in) {
- RadioChainInfo result = new RadioChainInfo();
- result.chainId = in.readInt();
- result.level = in.readInt();
- return result;
+ return new RadioChainInfo(in.readInt(), in.readInt());
}
@Override
diff --git a/wifi/java/android/net/wifi/wificond/SingleScanSettings.java b/wifi/java/android/net/wifi/wificond/SingleScanSettings.java
index 8065c01a7f89..8c341b8bd916 100644
--- a/wifi/java/android/net/wifi/wificond/SingleScanSettings.java
+++ b/wifi/java/android/net/wifi/wificond/SingleScanSettings.java
@@ -16,7 +16,6 @@
package android.net.wifi.wificond;
-import android.net.wifi.IWifiScannerImpl;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
diff --git a/wifi/java/android/net/wifi/WifiCondManager.java b/wifi/java/android/net/wifi/wificond/WifiCondManager.java
index c05ba347ab5c..283f2dd78abb 100644
--- a/wifi/java/android/net/wifi/WifiCondManager.java
+++ b/wifi/java/android/net/wifi/wificond/WifiCondManager.java
@@ -14,18 +14,19 @@
* limitations under the License.
*/
-package android.net.wifi;
+package android.net.wifi.wificond;
+import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.annotation.SystemService;
import android.app.AlarmManager;
import android.content.Context;
-import android.net.wifi.wificond.ChannelSettings;
-import android.net.wifi.wificond.HiddenNetwork;
-import android.net.wifi.wificond.NativeScanResult;
-import android.net.wifi.wificond.NativeWifiClient;
-import android.net.wifi.wificond.PnoSettings;
-import android.net.wifi.wificond.SingleScanSettings;
+import android.net.wifi.SoftApInfo;
+import android.net.wifi.WifiAnnotations;
+import android.net.wifi.WifiScanner;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
@@ -44,37 +45,48 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
/**
- * This class provides methods for WifiNative to send control commands to wificond.
- * NOTE: This class should only be used from WifiNative.
+ * This class encapsulates the interface the wificond daemon presents to the Wi-Fi framework. The
+ * interface is only for use by the Wi-Fi framework and access is protected by SELinux permissions.
+ *
* @hide
*/
-public class WifiCondManager implements IBinder.DeathRecipient {
+@SystemApi
+@SystemService(Context.WIFI_COND_SERVICE)
+public class WifiCondManager {
private static final String TAG = "WifiCondManager";
private boolean mVerboseLoggingEnabled = false;
/**
- * The {@link #sendMgmtFrame(String, byte[], SendMgmtFrameCallback, int) sendMgmtFrame()}
+ * The {@link #sendMgmtFrame(String, byte[], int, Executor, SendMgmtFrameCallback)}
* timeout, in milliseconds, after which
* {@link SendMgmtFrameCallback#onFailure(int)} will be called with reason
* {@link #SEND_MGMT_FRAME_ERROR_TIMEOUT}.
*/
- public static final int SEND_MGMT_FRAME_TIMEOUT_MS = 1000;
+ private static final int SEND_MGMT_FRAME_TIMEOUT_MS = 1000;
private static final String TIMEOUT_ALARM_TAG = TAG + " Send Management Frame Timeout";
+ /** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = {"SCAN_TYPE_"},
value = {SCAN_TYPE_SINGLE_SCAN,
SCAN_TYPE_PNO_SCAN})
public @interface ScanResultType {}
- /** Get scan results for a single scan */
+ /**
+ * Specifies a scan type: single scan initiated by the framework. Can be used in
+ * {@link #getScanResults(String, int)} to specify the type of scan result to fetch.
+ */
public static final int SCAN_TYPE_SINGLE_SCAN = 0;
- /** Get scan results for Pno Scan */
+ /**
+ * Specifies a scan type: PNO scan. Can be used in {@link #getScanResults(String, int)} to
+ * specify the type of scan result to fetch.
+ */
public static final int SCAN_TYPE_PNO_SCAN = 1;
private AlarmManager mAlarmManager;
@@ -95,11 +107,12 @@ public class WifiCondManager implements IBinder.DeathRecipient {
private AtomicBoolean mSendMgmtFrameInProgress = new AtomicBoolean(false);
/**
- * Interface for a callback to be used to handle scan results.
+ * Interface used when waiting for scans to be completed (with results).
*/
public interface ScanEventCallback {
/**
- * Called when scan results are available.
+ * Called when scan results are available. Scans results should then be obtained from
+ * {@link #getScanResults(String, int)}.
*/
void onScanResultReady();
@@ -110,11 +123,14 @@ public class WifiCondManager implements IBinder.DeathRecipient {
}
/**
- * Interface for a callback to provide information about PNO scan request.
+ * Interface for a callback to provide information about PNO scan request requested with
+ * {@link #startPnoScan(String, PnoSettings, Executor, PnoScanRequestCallback)}. Note that the
+ * callback are for the status of the request - not the scan itself. The results of the scan
+ * are returned with {@link ScanEventCallback}.
*/
public interface PnoScanRequestCallback {
/**
- * Called when the PNO scan is requested.
+ * Called when a PNO scan request has been successfully submitted.
*/
void onPnoRequestSucceeded();
@@ -125,73 +141,116 @@ public class WifiCondManager implements IBinder.DeathRecipient {
}
private class ScanEventHandler extends IScanEvent.Stub {
+ private Executor mExecutor;
private ScanEventCallback mCallback;
- ScanEventHandler(@NonNull ScanEventCallback callback) {
+ ScanEventHandler(@NonNull Executor executor, @NonNull ScanEventCallback callback) {
+ mExecutor = executor;
mCallback = callback;
}
@Override
public void OnScanResultReady() {
Log.d(TAG, "Scan result ready event");
- mCallback.onScanResultReady();
+ Binder.clearCallingIdentity();
+ mExecutor.execute(() -> mCallback.onScanResultReady());
}
@Override
public void OnScanFailed() {
Log.d(TAG, "Scan failed event");
- mCallback.onScanFailed();
+ Binder.clearCallingIdentity();
+ mExecutor.execute(() -> mCallback.onScanFailed());
}
}
/**
- * Result of a signal poll.
+ * Result of a signal poll requested using {@link #signalPoll(String)}.
*/
public static class SignalPollResult {
- // RSSI value in dBM.
- public int currentRssi;
- //Transmission bit rate in Mbps.
- public int txBitrate;
- // Association frequency in MHz.
- public int associationFrequency;
- //Last received packet bit rate in Mbps.
- public int rxBitrate;
+ /** @hide */
+ public SignalPollResult(int currentRssiDbm, int txBitrateMbps, int rxBitrateMbps,
+ int associationFrequencyMHz) {
+ this.currentRssiDbm = currentRssiDbm;
+ this.txBitrateMbps = txBitrateMbps;
+ this.rxBitrateMbps = rxBitrateMbps;
+ this.associationFrequencyMHz = associationFrequencyMHz;
+ }
+
+ /**
+ * RSSI value in dBM.
+ */
+ public final int currentRssiDbm;
+
+ /**
+ * Transmission bit rate in Mbps.
+ */
+ public final int txBitrateMbps;
+
+ /**
+ * Last received packet bit rate in Mbps.
+ */
+ public final int rxBitrateMbps;
+
+ /**
+ * Association frequency in MHz.
+ */
+ public final int associationFrequencyMHz;
}
/**
- * WiFi interface transimission counters.
+ * Transmission counters obtained using {@link #getTxPacketCounters(String)}.
*/
public static class TxPacketCounters {
- // Number of successfully transmitted packets.
- public int txSucceeded;
- // Number of tramsmission failures.
- public int txFailed;
+ /** @hide */
+ public TxPacketCounters(int txPacketSucceeded, int txPacketFailed) {
+ this.txPacketSucceeded = txPacketSucceeded;
+ this.txPacketFailed = txPacketFailed;
+ }
+
+ /**
+ * Number of successfully transmitted packets.
+ */
+ public final int txPacketSucceeded;
+
+ /**
+ * Number of packet transmission failures.
+ */
+ public final int txPacketFailed;
}
/**
- * Callbacks for SoftAp interface.
+ * Callbacks for SoftAp interface registered using
+ * {@link #registerApCallback(String, Executor, SoftApCallback)}.
*/
- public interface SoftApListener {
+ public interface SoftApCallback {
/**
- * Invoked when there is some fatal failure in the lower layers.
+ * Invoked when there is a fatal failure and the SoftAp is shutdown.
*/
void onFailure();
/**
- * Invoked when the associated stations changes.
+ * Invoked when there is a change in the associated station (STA).
+ * @param client Information about the client whose status has changed.
+ * @param isConnected Indication as to whether the client is connected (true), or
+ * disconnected (false).
*/
- void onConnectedClientsChanged(NativeWifiClient client, boolean isConnected);
+ void onConnectedClientsChanged(@NonNull NativeWifiClient client, boolean isConnected);
/**
- * Invoked when the channel switch event happens.
+ * Invoked when a channel switch event happens - i.e. the SoftAp is moved to a different
+ * channel. Also called on initial registration.
+ * @param frequencyMhz The new frequency of the SoftAp. A value of 0 is invalid and is an
+ * indication that the SoftAp is not enabled.
+ * @param bandwidth The new bandwidth of the SoftAp.
*/
- void onSoftApChannelSwitched(int frequency, int bandwidth);
+ void onSoftApChannelSwitched(int frequencyMhz, @WifiAnnotations.Bandwidth int bandwidth);
}
/**
* Callback to notify the results of a
- * {@link #sendMgmtFrame(String, byte[], SendMgmtFrameCallback, int) sendMgmtFrame()} call.
- * Note: no callbacks will be triggered if the iface dies while sending a frame.
+ * {@link #sendMgmtFrame(String, byte[], int, Executor, SendMgmtFrameCallback)} call.
+ * Note: no callbacks will be triggered if the interface dies while sending a frame.
*/
public interface SendMgmtFrameCallback {
/**
@@ -211,6 +270,7 @@ public class WifiCondManager implements IBinder.DeathRecipient {
void onFailure(@SendMgmtFrameError int reason);
}
+ /** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = {"SEND_MGMT_FRAME_ERROR_"},
value = {SEND_MGMT_FRAME_ERROR_UNKNOWN,
@@ -224,43 +284,44 @@ public class WifiCondManager implements IBinder.DeathRecipient {
/**
* Unknown error occurred during call to
- * {@link #sendMgmtFrame(String, byte[], SendMgmtFrameCallback, int) sendMgmtFrame()}.
+ * {@link #sendMgmtFrame(String, byte[], int, Executor, SendMgmtFrameCallback)}.
*/
public static final int SEND_MGMT_FRAME_ERROR_UNKNOWN = 1;
/**
* Specifying the MCS rate in
- * {@link #sendMgmtFrame(String, byte[], SendMgmtFrameCallback, int) sendMgmtFrame()} is not
+ * {@link #sendMgmtFrame(String, byte[], int, Executor, SendMgmtFrameCallback)} is not
* supported by this device.
*/
public static final int SEND_MGMT_FRAME_ERROR_MCS_UNSUPPORTED = 2;
/**
* Driver reported that no ACK was received for the frame transmitted using
- * {@link #sendMgmtFrame(String, byte[], SendMgmtFrameCallback, int) sendMgmtFrame()}.
+ * {@link #sendMgmtFrame(String, byte[], int, Executor, SendMgmtFrameCallback)}.
*/
public static final int SEND_MGMT_FRAME_ERROR_NO_ACK = 3;
/**
* Error code for when the driver fails to report on the status of the frame sent by
- * {@link #sendMgmtFrame(String, byte[], SendMgmtFrameCallback, int) sendMgmtFrame()}
+ * {@link #sendMgmtFrame(String, byte[], int, Executor, SendMgmtFrameCallback)}
* after {@link #SEND_MGMT_FRAME_TIMEOUT_MS} milliseconds.
*/
public static final int SEND_MGMT_FRAME_ERROR_TIMEOUT = 4;
/**
* An existing call to
- * {@link #sendMgmtFrame(String, byte[], SendMgmtFrameCallback, int) sendMgmtFrame()}
+ * {@link #sendMgmtFrame(String, byte[], int, Executor, SendMgmtFrameCallback)}
* is in progress. Another frame cannot be sent until the first call completes.
*/
public static final int SEND_MGMT_FRAME_ERROR_ALREADY_STARTED = 5;
-
+ /** @hide */
public WifiCondManager(Context context) {
- mAlarmManager = (AlarmManager) context.getSystemService(AlarmManager.class);
+ mAlarmManager = context.getSystemService(AlarmManager.class);
mEventHandler = new Handler(context.getMainLooper());
}
+ /** @hide */
@VisibleForTesting
public WifiCondManager(Context context, IWificond wificond) {
this(context);
@@ -268,22 +329,26 @@ public class WifiCondManager implements IBinder.DeathRecipient {
}
private class PnoScanEventHandler extends IPnoScanEvent.Stub {
+ private Executor mExecutor;
private ScanEventCallback mCallback;
- PnoScanEventHandler(@NonNull ScanEventCallback callback) {
+ PnoScanEventHandler(@NonNull Executor executor, @NonNull ScanEventCallback callback) {
+ mExecutor = executor;
mCallback = callback;
}
@Override
public void OnPnoNetworkFound() {
Log.d(TAG, "Pno scan result event");
- mCallback.onScanResultReady();
+ Binder.clearCallingIdentity();
+ mExecutor.execute(() -> mCallback.onScanResultReady());
}
@Override
public void OnPnoScanFailed() {
Log.d(TAG, "Pno Scan failed event");
- mCallback.onScanFailed();
+ Binder.clearCallingIdentity();
+ mExecutor.execute(() -> mCallback.onScanFailed());
}
}
@@ -291,9 +356,11 @@ public class WifiCondManager implements IBinder.DeathRecipient {
* Listener for AP Interface events.
*/
private class ApInterfaceEventCallback extends IApInterfaceEventCallback.Stub {
- private SoftApListener mSoftApListener;
+ private Executor mExecutor;
+ private SoftApCallback mSoftApListener;
- ApInterfaceEventCallback(SoftApListener listener) {
+ ApInterfaceEventCallback(Executor executor, SoftApCallback listener) {
+ mExecutor = executor;
mSoftApListener = listener;
}
@@ -304,12 +371,36 @@ public class WifiCondManager implements IBinder.DeathRecipient {
+ client.macAddress + " isConnected: " + isConnected);
}
- mSoftApListener.onConnectedClientsChanged(client, isConnected);
+ Binder.clearCallingIdentity();
+ mExecutor.execute(() -> mSoftApListener.onConnectedClientsChanged(client, isConnected));
}
@Override
public void onSoftApChannelSwitched(int frequency, int bandwidth) {
- mSoftApListener.onSoftApChannelSwitched(frequency, bandwidth);
+ Binder.clearCallingIdentity();
+ mExecutor.execute(() -> mSoftApListener.onSoftApChannelSwitched(frequency,
+ toFrameworkBandwidth(bandwidth)));
+ }
+
+ private @WifiAnnotations.Bandwidth int toFrameworkBandwidth(int bandwidth) {
+ switch(bandwidth) {
+ case IApInterfaceEventCallback.BANDWIDTH_INVALID:
+ return SoftApInfo.CHANNEL_WIDTH_INVALID;
+ case IApInterfaceEventCallback.BANDWIDTH_20_NOHT:
+ return SoftApInfo.CHANNEL_WIDTH_20MHZ_NOHT;
+ case IApInterfaceEventCallback.BANDWIDTH_20:
+ return SoftApInfo.CHANNEL_WIDTH_20MHZ;
+ case IApInterfaceEventCallback.BANDWIDTH_40:
+ return SoftApInfo.CHANNEL_WIDTH_40MHZ;
+ case IApInterfaceEventCallback.BANDWIDTH_80:
+ return SoftApInfo.CHANNEL_WIDTH_80MHZ;
+ case IApInterfaceEventCallback.BANDWIDTH_80P80:
+ return SoftApInfo.CHANNEL_WIDTH_80MHZ_PLUS_MHZ;
+ case IApInterfaceEventCallback.BANDWIDTH_160:
+ return SoftApInfo.CHANNEL_WIDTH_160MHZ;
+ default:
+ return SoftApInfo.CHANNEL_WIDTH_INVALID;
+ }
}
}
@@ -317,6 +408,7 @@ public class WifiCondManager implements IBinder.DeathRecipient {
* Callback triggered by wificond.
*/
private class SendMgmtFrameEvent extends ISendMgmtFrameEvent.Stub {
+ private Executor mExecutor;
private SendMgmtFrameCallback mCallback;
private AlarmManager.OnAlarmListener mTimeoutCallback;
/**
@@ -332,14 +424,16 @@ public class WifiCondManager implements IBinder.DeathRecipient {
r.run();
}
- SendMgmtFrameEvent(@NonNull SendMgmtFrameCallback callback) {
+ SendMgmtFrameEvent(@NonNull Executor executor, @NonNull SendMgmtFrameCallback callback) {
+ mExecutor = executor;
mCallback = callback;
// called in main thread
mTimeoutCallback = () -> runIfFirstCall(() -> {
if (mVerboseLoggingEnabled) {
Log.e(TAG, "Timed out waiting for ACK");
}
- mCallback.onFailure(SEND_MGMT_FRAME_ERROR_TIMEOUT);
+ Binder.clearCallingIdentity();
+ mExecutor.execute(() -> mCallback.onFailure(SEND_MGMT_FRAME_ERROR_TIMEOUT));
});
mWasCalled = false;
@@ -354,7 +448,8 @@ public class WifiCondManager implements IBinder.DeathRecipient {
// post to main thread
mEventHandler.post(() -> runIfFirstCall(() -> {
mAlarmManager.cancel(mTimeoutCallback);
- mCallback.onAck(elapsedTimeMs);
+ Binder.clearCallingIdentity();
+ mExecutor.execute(() -> mCallback.onAck(elapsedTimeMs));
}));
}
@@ -364,7 +459,8 @@ public class WifiCondManager implements IBinder.DeathRecipient {
// post to main thread
mEventHandler.post(() -> runIfFirstCall(() -> {
mAlarmManager.cancel(mTimeoutCallback);
- mCallback.onFailure(reason);
+ Binder.clearCallingIdentity();
+ mExecutor.execute(() -> mCallback.onFailure(reason));
}));
}
}
@@ -372,8 +468,9 @@ public class WifiCondManager implements IBinder.DeathRecipient {
/**
* Called by the binder subsystem upon remote object death.
* Invoke all the register death handlers and clear state.
+ * @hide
*/
- @Override
+ @VisibleForTesting
public void binderDied() {
mEventHandler.post(() -> {
Log.e(TAG, "Wificond died!");
@@ -387,17 +484,22 @@ public class WifiCondManager implements IBinder.DeathRecipient {
});
}
- /** Enable or disable verbose logging of WificondControl.
- * @param enable True to enable verbose logging. False to disable verbose logging.
+ /**
+ * Enable or disable verbose logging of the WifiCondManager module.
+ * @param enable True to enable verbose logging. False to disable verbose logging.
*/
public void enableVerboseLogging(boolean enable) {
mVerboseLoggingEnabled = enable;
}
/**
- * Initializes wificond & registers a death notification for wificond.
- * This method clears any existing state in wificond daemon.
+ * Initializes WifiCondManager & registers a death notification for the WifiCondManager which
+ * acts as a proxy for the wificond daemon (i.e. the death listener will be called when and if
+ * the wificond daemon dies).
+ *
+ * Note: This method clears any existing state in wificond daemon.
*
+ * @param deathEventHandler A {@link Runnable} to be called whenever the wificond daemon dies.
* @return Returns true on success.
*/
public boolean initialize(@NonNull Runnable deathEventHandler) {
@@ -428,7 +530,7 @@ public class WifiCondManager implements IBinder.DeathRecipient {
return false;
}
try {
- mWificond.asBinder().linkToDeath(this, 0);
+ mWificond.asBinder().linkToDeath(() -> binderDied(), 0);
} catch (RemoteException e) {
Log.e(TAG, "Failed to register death notification for wificond");
// The remote has already died.
@@ -438,16 +540,27 @@ public class WifiCondManager implements IBinder.DeathRecipient {
}
/**
- * Setup interface for client mode via wificond.
- * @return true on success.
- */
+ * Set up an interface for client (STA) mode.
+ *
+ * @param ifaceName Name of the interface to configure.
+ * @param executor The Executor on which to execute the callbacks.
+ * @param scanCallback A callback for framework initiated scans.
+ * @param pnoScanCallback A callback for PNO (offloaded) scans.
+ * @return true on success.
+ */
public boolean setupInterfaceForClientMode(@NonNull String ifaceName,
+ @NonNull @CallbackExecutor Executor executor,
@NonNull ScanEventCallback scanCallback, @NonNull ScanEventCallback pnoScanCallback) {
Log.d(TAG, "Setting up interface for client mode");
if (!retrieveWificondAndRegisterForDeath()) {
return false;
}
+ if (scanCallback == null || pnoScanCallback == null || executor == null) {
+ Log.e(TAG, "setupInterfaceForClientMode invoked with null callbacks");
+ return false;
+ }
+
IClientInterface clientInterface = null;
try {
clientInterface = mWificond.createClientInterface(ifaceName);
@@ -472,10 +585,11 @@ public class WifiCondManager implements IBinder.DeathRecipient {
}
mWificondScanners.put(ifaceName, wificondScanner);
Binder.allowBlocking(wificondScanner.asBinder());
- ScanEventHandler scanEventHandler = new ScanEventHandler(scanCallback);
+ ScanEventHandler scanEventHandler = new ScanEventHandler(executor, scanCallback);
mScanEventHandlers.put(ifaceName, scanEventHandler);
wificondScanner.subscribeScanEvents(scanEventHandler);
- PnoScanEventHandler pnoScanEventHandler = new PnoScanEventHandler(pnoScanCallback);
+ PnoScanEventHandler pnoScanEventHandler = new PnoScanEventHandler(executor,
+ pnoScanCallback);
mPnoScanEventHandlers.put(ifaceName, pnoScanEventHandler);
wificondScanner.subscribePnoScanEvents(pnoScanEventHandler);
} catch (RemoteException e) {
@@ -486,8 +600,10 @@ public class WifiCondManager implements IBinder.DeathRecipient {
}
/**
- * Teardown a specific STA interface configured in wificond.
+ * Tear down a specific client (STA) interface, initially configured using
+ * {@link #setupInterfaceForClientMode(String, Executor, ScanEventCallback, ScanEventCallback)}.
*
+ * @param ifaceName Name of the interface to tear down.
* @return Returns true on success.
*/
public boolean tearDownClientInterface(@NonNull String ifaceName) {
@@ -531,9 +647,11 @@ public class WifiCondManager implements IBinder.DeathRecipient {
}
/**
- * Setup interface for softAp mode via wificond.
- * @return true on success.
- */
+ * Set up interface as a Soft AP.
+ *
+ * @param ifaceName Name of the interface to configure.
+ * @return true on success.
+ */
public boolean setupInterfaceForSoftApMode(@NonNull String ifaceName) {
Log.d(TAG, "Setting up interface for soft ap mode");
if (!retrieveWificondAndRegisterForDeath()) {
@@ -560,8 +678,10 @@ public class WifiCondManager implements IBinder.DeathRecipient {
}
/**
- * Teardown a specific AP interface configured in wificond.
+ * Tear down a Soft AP interface initially configured using
+ * {@link #setupInterfaceForSoftApMode(String)}.
*
+ * @param ifaceName Name of the interface to tear down.
* @return Returns true on success.
*/
public boolean tearDownSoftApInterface(@NonNull String ifaceName) {
@@ -592,7 +712,8 @@ public class WifiCondManager implements IBinder.DeathRecipient {
}
/**
- * Teardown all interfaces configured in wificond.
+ * Tear down all interfaces, whether clients (STA) or Soft AP.
+ *
* @return Returns true on success.
*/
public boolean tearDownInterfaces() {
@@ -624,12 +745,13 @@ public class WifiCondManager implements IBinder.DeathRecipient {
}
/**
- * Request signal polling to wificond.
- * @param ifaceName Name of the interface.
- * Returns an SignalPollResult object.
- * Returns null on failure.
+ * Request signal polling.
+ *
+ * @param ifaceName Name of the interface on which to poll.
+ * @return A {@link SignalPollResult} object containing interface statistics, or a null on
+ * error.
*/
- public SignalPollResult signalPoll(@NonNull String ifaceName) {
+ @Nullable public SignalPollResult signalPoll(@NonNull String ifaceName) {
IClientInterface iface = getClientInterface(ifaceName);
if (iface == null) {
Log.e(TAG, "No valid wificond client interface handler");
@@ -647,21 +769,16 @@ public class WifiCondManager implements IBinder.DeathRecipient {
Log.e(TAG, "Failed to do signal polling due to remote exception");
return null;
}
- SignalPollResult pollResult = new SignalPollResult();
- pollResult.currentRssi = resultArray[0];
- pollResult.txBitrate = resultArray[1];
- pollResult.associationFrequency = resultArray[2];
- pollResult.rxBitrate = resultArray[3];
- return pollResult;
+ return new SignalPollResult(resultArray[0], resultArray[1], resultArray[3], resultArray[2]);
}
/**
- * Fetch TX packet counters on current connection from wificond.
+ * Get current transmit (Tx) packet counters of the specified interface.
+ *
* @param ifaceName Name of the interface.
- * Returns an TxPacketCounters object.
- * Returns null on failure.
+ * @return {@link TxPacketCounters} of the current interface or null on error.
*/
- public TxPacketCounters getTxPacketCounters(@NonNull String ifaceName) {
+ @Nullable public TxPacketCounters getTxPacketCounters(@NonNull String ifaceName) {
IClientInterface iface = getClientInterface(ifaceName);
if (iface == null) {
Log.e(TAG, "No valid wificond client interface handler");
@@ -679,10 +796,7 @@ public class WifiCondManager implements IBinder.DeathRecipient {
Log.e(TAG, "Failed to do signal polling due to remote exception");
return null;
}
- TxPacketCounters counters = new TxPacketCounters();
- counters.txSucceeded = resultArray[0];
- counters.txFailed = resultArray[1];
- return counters;
+ return new TxPacketCounters(resultArray[0], resultArray[1]);
}
/** Helper function to look up the scanner impl handle using name */
@@ -691,10 +805,16 @@ public class WifiCondManager implements IBinder.DeathRecipient {
}
/**
- * Fetch the latest scan result from kernel via wificond.
- * @param ifaceName Name of the interface.
- * @return Returns an array of native scan results or an empty array on failure.
- */
+ * Fetch the latest scan results of the indicated type for the specified interface. Note that
+ * this method fetches the latest results - it does not initiate a scan. Initiating a scan can
+ * be done using {@link #startScan(String, int, Set, List)} or
+ * {@link #startPnoScan(String, PnoSettings, Executor, PnoScanRequestCallback)}.
+ *
+ * @param ifaceName Name of the interface.
+ * @param scanType The type of scan result to be returned, can be
+ * {@link #SCAN_TYPE_SINGLE_SCAN} or {@link #SCAN_TYPE_PNO_SCAN}.
+ * @return Returns an array of {@link NativeScanResult} or an empty array on failure.
+ */
@NonNull public List<NativeScanResult> getScanResults(@NonNull String ifaceName,
@ScanResultType int scanType) {
IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
@@ -739,15 +859,23 @@ public class WifiCondManager implements IBinder.DeathRecipient {
}
/**
- * Start a scan using wificond for the given parameters.
- * @param ifaceName Name of the interface.
- * @param scanType Type of scan to perform.
+ * Start a scan using the specified parameters. A scan is an asynchronous operation. The
+ * result of the operation is returned in the {@link ScanEventCallback} registered when
+ * setting up an interface using
+ * {@link #setupInterfaceForClientMode(String, Executor, ScanEventCallback, ScanEventCallback)}.
+ * The latest scans can be obtained using {@link #getScanResults(String, int)} and using a
+ * {@link #SCAN_TYPE_SINGLE_SCAN} for the {@code scanType}.
+ *
+ * @param ifaceName Name of the interface on which to initiate the scan.
+ * @param scanType Type of scan to perform, can be any of
+ * {@link WifiScanner#SCAN_TYPE_HIGH_ACCURACY}, {@link WifiScanner#SCAN_TYPE_LOW_POWER}, or
+ * {@link WifiScanner#SCAN_TYPE_LOW_LATENCY}.
* @param freqs list of frequencies to scan for, if null scan all supported channels.
* @param hiddenNetworkSSIDs List of hidden networks to be scanned for.
* @return Returns true on success.
*/
- public boolean scan(@NonNull String ifaceName, @WifiAnnotations.ScanType int scanType,
- Set<Integer> freqs, List<byte[]> hiddenNetworkSSIDs) {
+ public boolean startScan(@NonNull String ifaceName, @WifiAnnotations.ScanType int scanType,
+ @Nullable Set<Integer> freqs, @Nullable List<byte[]> hiddenNetworkSSIDs) {
IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
if (scannerImpl == null) {
Log.e(TAG, "No valid wificond scanner interface handler");
@@ -792,25 +920,40 @@ public class WifiCondManager implements IBinder.DeathRecipient {
}
/**
- * Start PNO scan.
- * @param ifaceName Name of the interface.
- * @param pnoSettings Pno scan configuration.
+ * Request a PNO (Preferred Network Offload). The offload request and the scans are asynchronous
+ * operations. The result of the request are returned in the {@code callback} parameter which
+ * is an {@link PnoScanRequestCallback}. The scan results are are return in the
+ * {@link ScanEventCallback} which is registered when setting up an interface using
+ * {@link #setupInterfaceForClientMode(String, Executor, ScanEventCallback, ScanEventCallback)}.
+ * The latest PNO scans can be obtained using {@link #getScanResults(String, int)} with the
+ * {@code scanType} set to {@link #SCAN_TYPE_PNO_SCAN}.
+ *
+ * @param ifaceName Name of the interface on which to request a PNO.
+ * @param pnoSettings PNO scan configuration.
+ * @param executor The Executor on which to execute the callback.
+ * @param callback Callback for the results of the offload request.
* @return true on success.
*/
- public boolean startPnoScan(@NonNull String ifaceName, PnoSettings pnoSettings,
- PnoScanRequestCallback callback) {
+ public boolean startPnoScan(@NonNull String ifaceName, @NonNull PnoSettings pnoSettings,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull PnoScanRequestCallback callback) {
IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
if (scannerImpl == null) {
Log.e(TAG, "No valid wificond scanner interface handler");
return false;
}
+ if (callback == null || executor == null) {
+ Log.e(TAG, "startPnoScan called with a null callback");
+ return false;
+ }
+
try {
boolean success = scannerImpl.startPnoScan(pnoSettings);
if (success) {
- callback.onPnoRequestSucceeded();
+ executor.execute(callback::onPnoRequestSucceeded);
} else {
- callback.onPnoRequestFailed();
+ executor.execute(callback::onPnoRequestFailed);
}
return success;
} catch (RemoteException e1) {
@@ -820,8 +963,10 @@ public class WifiCondManager implements IBinder.DeathRecipient {
}
/**
- * Stop PNO scan.
- * @param ifaceName Name of the interface.
+ * Stop PNO scan configured with
+ * {@link #startPnoScan(String, PnoSettings, Executor, PnoScanRequestCallback)}.
+ *
+ * @param ifaceName Name of the interface on which the PNO scan was configured.
* @return true on success.
*/
public boolean stopPnoScan(@NonNull String ifaceName) {
@@ -839,8 +984,9 @@ public class WifiCondManager implements IBinder.DeathRecipient {
}
/**
- * Abort ongoing single scan.
- * @param ifaceName Name of the interface.
+ * Abort ongoing single scan started with {@link #startScan(String, int, Set, List)}.
+ *
+ * @param ifaceName Name of the interface on which the scan was started.
*/
public void abortScan(@NonNull String ifaceName) {
IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
@@ -856,7 +1002,7 @@ public class WifiCondManager implements IBinder.DeathRecipient {
}
/**
- * Query the list of valid frequencies for the provided band.
+ * Query the list of valid frequencies (in MHz) for the provided band.
* The result depends on the on the country code that has been set.
*
* @param band as specified by one of the WifiScanner.WIFI_BAND_* constants.
@@ -865,31 +1011,39 @@ public class WifiCondManager implements IBinder.DeathRecipient {
* WifiScanner.WIFI_BAND_5_GHZ
* WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY
* WifiScanner.WIFI_BAND_6_GHZ
- * @return frequencies vector of valid frequencies (MHz), or null for error.
+ * @return frequencies vector of valid frequencies (MHz), or an empty array for error.
* @throws IllegalArgumentException if band is not recognized.
*/
- public int [] getChannelsForBand(@WifiAnnotations.WifiBandBasic int band) {
+ public @NonNull int[] getChannelsMhzForBand(@WifiAnnotations.WifiBandBasic int band) {
if (mWificond == null) {
Log.e(TAG, "No valid wificond scanner interface handler");
- return null;
+ return new int[0];
}
+ int[] result = null;
try {
switch (band) {
case WifiScanner.WIFI_BAND_24_GHZ:
- return mWificond.getAvailable2gChannels();
+ result = mWificond.getAvailable2gChannels();
+ break;
case WifiScanner.WIFI_BAND_5_GHZ:
- return mWificond.getAvailable5gNonDFSChannels();
+ result = mWificond.getAvailable5gNonDFSChannels();
+ break;
case WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY:
- return mWificond.getAvailableDFSChannels();
+ result = mWificond.getAvailableDFSChannels();
+ break;
case WifiScanner.WIFI_BAND_6_GHZ:
- return mWificond.getAvailable6gChannels();
+ result = mWificond.getAvailable6gChannels();
+ break;
default:
throw new IllegalArgumentException("unsupported band " + band);
}
} catch (RemoteException e1) {
Log.e(TAG, "Failed to request getChannelsForBand due to remote exception");
}
- return null;
+ if (result == null) {
+ result = new int[0];
+ }
+ return result;
}
/** Helper function to look up the interface handle using name */
@@ -898,22 +1052,33 @@ public class WifiCondManager implements IBinder.DeathRecipient {
}
/**
- * Register the provided listener for SoftAp events.
+ * Register the provided callback handler for SoftAp events. Note that the Soft AP itself is
+ * configured using {@link #setupInterfaceForSoftApMode(String)}.
*
- * @param ifaceName Name of the interface.
- * @param listener Callback for AP events.
+ * @param ifaceName Name of the interface on which to register the callback.
+ * @param executor The Executor on which to execute the callbacks.
+ * @param callback Callback for AP events.
* @return true on success, false otherwise.
*/
- public boolean registerApListener(@NonNull String ifaceName, SoftApListener listener) {
+ public boolean registerApCallback(@NonNull String ifaceName,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull SoftApCallback callback) {
IApInterface iface = getApInterface(ifaceName);
if (iface == null) {
Log.e(TAG, "No valid ap interface handler");
return false;
}
+
+ if (callback == null || executor == null) {
+ Log.e(TAG, "registerApCallback called with a null callback");
+ return false;
+ }
+
try {
- IApInterfaceEventCallback callback = new ApInterfaceEventCallback(listener);
- mApInterfaceListeners.put(ifaceName, callback);
- boolean success = iface.registerCallback(callback);
+ IApInterfaceEventCallback wificondCallback = new ApInterfaceEventCallback(executor,
+ callback);
+ mApInterfaceListeners.put(ifaceName, wificondCallback);
+ boolean success = iface.registerCallback(wificondCallback);
if (!success) {
Log.e(TAG, "Failed to register ap callback.");
return false;
@@ -926,19 +1091,28 @@ public class WifiCondManager implements IBinder.DeathRecipient {
}
/**
- * See {@link #sendMgmtFrame(String, byte[], SendMgmtFrameCallback, int)}
+ * Send a management frame on the specified interface at the specified rate. Useful for probing
+ * the link with arbitrary frames.
+ *
+ * @param ifaceName The interface on which to send the frame.
+ * @param frame The raw byte array of the management frame to tramit.
+ * @param mcs The MCS (modulation and coding scheme), i.e. rate, at which to transmit the
+ * frame. Specified per IEEE 802.11.
+ * @param executor The Executor on which to execute the callbacks.
+ * @param callback A {@link SendMgmtFrameCallback} callback for results of the operation.
*/
- public void sendMgmtFrame(@NonNull String ifaceName, @NonNull byte[] frame,
- @NonNull SendMgmtFrameCallback callback, int mcs) {
+ public void sendMgmtFrame(@NonNull String ifaceName, @NonNull byte[] frame, int mcs,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull SendMgmtFrameCallback callback) {
- if (callback == null) {
+ if (callback == null || executor == null) {
Log.e(TAG, "callback cannot be null!");
return;
}
if (frame == null) {
Log.e(TAG, "frame cannot be null!");
- callback.onFailure(SEND_MGMT_FRAME_ERROR_UNKNOWN);
+ executor.execute(() -> callback.onFailure(SEND_MGMT_FRAME_ERROR_UNKNOWN));
return;
}
@@ -946,17 +1120,17 @@ public class WifiCondManager implements IBinder.DeathRecipient {
IClientInterface clientInterface = getClientInterface(ifaceName);
if (clientInterface == null) {
Log.e(TAG, "No valid wificond client interface handler");
- callback.onFailure(SEND_MGMT_FRAME_ERROR_UNKNOWN);
+ executor.execute(() -> callback.onFailure(SEND_MGMT_FRAME_ERROR_UNKNOWN));
return;
}
if (!mSendMgmtFrameInProgress.compareAndSet(false, true)) {
Log.e(TAG, "An existing management frame transmission is in progress!");
- callback.onFailure(SEND_MGMT_FRAME_ERROR_ALREADY_STARTED);
+ executor.execute(() -> callback.onFailure(SEND_MGMT_FRAME_ERROR_ALREADY_STARTED));
return;
}
- SendMgmtFrameEvent sendMgmtFrameEvent = new SendMgmtFrameEvent(callback);
+ SendMgmtFrameEvent sendMgmtFrameEvent = new SendMgmtFrameEvent(executor, callback);
try {
clientInterface.SendMgmtFrame(frame, sendMgmtFrameEvent, mcs);
} catch (RemoteException e) {
diff --git a/wifi/tests/src/android/net/wifi/EasyConnectStatusCallbackTest.java b/wifi/tests/src/android/net/wifi/EasyConnectStatusCallbackTest.java
new file mode 100644
index 000000000000..b10141434b0b
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/EasyConnectStatusCallbackTest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.util.SparseArray;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link android.net.wifi.EasyConnectStatusCallbackTest}.
+ */
+@SmallTest
+public class EasyConnectStatusCallbackTest {
+ private EasyConnectStatusCallback mEasyConnectStatusCallback = new EasyConnectStatusCallback() {
+ @Override
+ public void onEnrolleeSuccess(int newNetworkId) {
+
+ }
+
+ @Override
+ public void onConfiguratorSuccess(int code) {
+
+ }
+
+ @Override
+ public void onProgress(int code) {
+
+ }
+
+ @Override
+ public void onFailure(int code) {
+ mOnFailureR1EventReceived = true;
+ mLastCode = code;
+ }
+ };
+ private boolean mOnFailureR1EventReceived;
+ private int mLastCode;
+
+ @Before
+ public void setUp() {
+ mOnFailureR1EventReceived = false;
+ mLastCode = 0;
+ }
+
+ /**
+ * Test that the legacy R1 onFailure is called by default if the R2 onFailure is not overridden
+ * by the app.
+ */
+ @Test
+ public void testR1OnFailureCalled() {
+
+ SparseArray<int[]> channelList = new SparseArray<>();
+ int[] channelArray = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
+
+ channelList.append(81, channelArray);
+ mEasyConnectStatusCallback.onFailure(
+ EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK,
+ "SomeSSID", channelList, new int[] {81});
+
+ assertTrue(mOnFailureR1EventReceived);
+ assertEquals(mLastCode,
+ EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK);
+ }
+}
diff --git a/wifi/tests/src/android/net/wifi/SoftApCapabilityTest.java b/wifi/tests/src/android/net/wifi/SoftApCapabilityTest.java
new file mode 100644
index 000000000000..ef476ebc2667
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/SoftApCapabilityTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi;
+
+import android.os.Parcel;
+
+import static org.junit.Assert.assertEquals;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link android.net.wifi.SoftApCapability}.
+ */
+@SmallTest
+public class SoftApCapabilityTest {
+
+ /**
+ * Verifies copy constructor.
+ */
+ @Test
+ public void testCopyOperator() throws Exception {
+ int testSoftApFeature = SoftApCapability.SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT
+ | SoftApCapability.SOFTAP_FEATURE_ACS_OFFLOAD;
+ SoftApCapability capability = new SoftApCapability(testSoftApFeature);
+ capability.setMaxSupportedClients(10);
+
+ SoftApCapability copiedCapability = new SoftApCapability(capability);
+
+ assertEquals(capability, copiedCapability);
+ assertEquals(capability.hashCode(), copiedCapability.hashCode());
+ }
+
+ /**
+ * Verifies parcel serialization/deserialization.
+ */
+ @Test
+ public void testParcelOperation() throws Exception {
+ int testSoftApFeature = SoftApCapability.SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT
+ | SoftApCapability.SOFTAP_FEATURE_ACS_OFFLOAD;
+ SoftApCapability capability = new SoftApCapability(testSoftApFeature);
+ capability.setMaxSupportedClients(10);
+
+ Parcel parcelW = Parcel.obtain();
+ capability.writeToParcel(parcelW, 0);
+ byte[] bytes = parcelW.marshall();
+ parcelW.recycle();
+
+ Parcel parcelR = Parcel.obtain();
+ parcelR.unmarshall(bytes, 0, bytes.length);
+ parcelR.setDataPosition(0);
+ SoftApCapability fromParcel = SoftApCapability.CREATOR.createFromParcel(parcelR);
+
+ assertEquals(capability, fromParcel);
+ assertEquals(capability.hashCode(), fromParcel.hashCode());
+ }
+
+}
diff --git a/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java b/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java
index b8d3e413f1d2..1f601036a718 100644
--- a/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java
@@ -50,6 +50,7 @@ public class SoftApConfigurationTest {
assertThat(original.getBand()).isEqualTo(SoftApConfiguration.BAND_2GHZ);
assertThat(original.getChannel()).isEqualTo(0);
assertThat(original.isHiddenSsid()).isEqualTo(false);
+ assertThat(original.getMaxNumberOfClients()).isEqualTo(0);
SoftApConfiguration unparceled = parcelUnparcel(original);
assertThat(unparceled).isNotSameAs(original);
@@ -73,7 +74,7 @@ public class SoftApConfigurationTest {
assertThat(original.getBand()).isEqualTo(SoftApConfiguration.BAND_2GHZ);
assertThat(original.getChannel()).isEqualTo(0);
assertThat(original.isHiddenSsid()).isEqualTo(false);
-
+ assertThat(original.getMaxNumberOfClients()).isEqualTo(0);
SoftApConfiguration unparceled = parcelUnparcel(original);
assertThat(unparceled).isNotSameAs(original);
@@ -87,20 +88,21 @@ public class SoftApConfigurationTest {
}
@Test
- public void testWpa2WithBandAndChannelAndHiddenNetwork() {
+ public void testWpa2WithAllFieldCustomized() {
SoftApConfiguration original = new SoftApConfiguration.Builder()
.setWpa2Passphrase("secretsecret")
.setBand(SoftApConfiguration.BAND_ANY)
- .setChannel(149)
+ .setChannel(149, SoftApConfiguration.BAND_5GHZ)
.setHiddenSsid(true)
+ .setMaxNumberOfClients(10)
.build();
assertThat(original.getWpa2Passphrase()).isEqualTo("secretsecret");
assertThat(original.getSecurityType()).isEqualTo(
SoftApConfiguration.SECURITY_TYPE_WPA2_PSK);
- assertThat(original.getBand()).isEqualTo(SoftApConfiguration.BAND_ANY);
+ assertThat(original.getBand()).isEqualTo(SoftApConfiguration.BAND_5GHZ);
assertThat(original.getChannel()).isEqualTo(149);
assertThat(original.isHiddenSsid()).isEqualTo(true);
-
+ assertThat(original.getMaxNumberOfClients()).isEqualTo(10);
SoftApConfiguration unparceled = parcelUnparcel(original);
assertThat(unparceled).isNotSameAs(original);
diff --git a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
index 7e38e147427f..5d6549ed5f13 100644
--- a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
@@ -32,9 +32,6 @@ import androidx.test.filters.SmallTest;
import org.junit.Before;
import org.junit.Test;
-import java.io.ByteArrayInputStream;
-import java.io.DataInputStream;
-
/**
* Unit tests for {@link android.net.wifi.WifiConfiguration}.
*/
@@ -196,33 +193,6 @@ public class WifiConfigurationTest {
}
/**
- * Verifies that the serialization/de-serialization for softap config works.
- */
- @Test
- public void testSoftApConfigBackupAndRestore() throws Exception {
- WifiConfiguration config = new WifiConfiguration();
- config.SSID = "TestAP";
- config.apBand = WifiConfiguration.AP_BAND_5GHZ;
- config.apChannel = 40;
- config.allowedKeyManagement.set(KeyMgmt.WPA2_PSK);
- config.preSharedKey = "TestPsk";
- config.hiddenSSID = true;
-
- byte[] data = config.getBytesForBackup();
- ByteArrayInputStream bais = new ByteArrayInputStream(data);
- DataInputStream in = new DataInputStream(bais);
- WifiConfiguration restoredConfig = WifiConfiguration.getWifiConfigFromBackup(in);
-
- assertEquals(config.SSID, restoredConfig.SSID);
- assertEquals(config.preSharedKey, restoredConfig.preSharedKey);
- assertEquals(config.getAuthType(), restoredConfig.getAuthType());
- assertEquals(config.apBand, restoredConfig.apBand);
- assertEquals(config.apChannel, restoredConfig.apChannel);
- assertEquals(config.hiddenSSID, restoredConfig.hiddenSSID);
- }
-
-
- /**
* Verifies that getKeyIdForCredentials returns the expected string for Enterprise networks
* @throws Exception
*/
@@ -317,6 +287,16 @@ public class WifiConfigurationTest {
config.allowedKeyManagement.clear();
config.allowedKeyManagement.set(KeyMgmt.NONE);
assertEquals(mSsid + KeyMgmt.strings[KeyMgmt.NONE], config.getSsidAndSecurityTypeString());
+
+ config.allowedKeyManagement.clear();
+ config.allowedKeyManagement.set(KeyMgmt.WAPI_PSK);
+ assertEquals(mSsid + KeyMgmt.strings[KeyMgmt.WAPI_PSK],
+ config.getSsidAndSecurityTypeString());
+
+ config.allowedKeyManagement.clear();
+ config.allowedKeyManagement.set(KeyMgmt.WAPI_CERT);
+ assertEquals(mSsid + KeyMgmt.strings[KeyMgmt.WAPI_CERT],
+ config.getSsidAndSecurityTypeString());
}
/**
diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
index 62ff9f65a1a7..f9bd31d57ffc 100644
--- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
@@ -89,6 +89,7 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.os.connectivity.WifiActivityEnergyInfo;
import android.os.test.TestLooper;
+import android.util.SparseArray;
import androidx.test.filters.SmallTest;
@@ -876,6 +877,25 @@ public class WifiManagerTest {
verify(mSoftApCallback).onInfoChanged(testSoftApInfo);
}
+
+ /*
+ * Verify client-provided callback is being called through callback proxy
+ */
+ @Test
+ public void softApCallbackProxyCallsOnCapabilityChanged() throws Exception {
+ SoftApCapability testSoftApCapability = new SoftApCapability(0);
+ testSoftApCapability.setMaxSupportedClients(10);
+ ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
+ ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
+ mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
+ verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture(),
+ anyInt());
+
+ callbackCaptor.getValue().onCapabilityChanged(testSoftApCapability);
+ mLooper.dispatchAll();
+ verify(mSoftApCallback).onCapabilityChanged(testSoftApCapability);
+ }
+
/*
* Verify client-provided callback is being called through callback proxy on multiple events
*/
@@ -884,6 +904,8 @@ public class WifiManagerTest {
SoftApInfo testSoftApInfo = new SoftApInfo();
testSoftApInfo.setFrequency(TEST_AP_FREQUENCY);
testSoftApInfo.setBandwidth(TEST_AP_BANDWIDTH);
+ SoftApCapability testSoftApCapability = new SoftApCapability(0);
+ testSoftApCapability.setMaxSupportedClients(10);
ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
@@ -895,12 +917,15 @@ public class WifiManagerTest {
callbackCaptor.getValue().onConnectedClientsChanged(testClients);
callbackCaptor.getValue().onInfoChanged(testSoftApInfo);
callbackCaptor.getValue().onStateChanged(WIFI_AP_STATE_FAILED, SAP_START_FAILURE_GENERAL);
+ callbackCaptor.getValue().onCapabilityChanged(testSoftApCapability);
+
mLooper.dispatchAll();
verify(mSoftApCallback).onStateChanged(WIFI_AP_STATE_ENABLING, 0);
verify(mSoftApCallback).onConnectedClientsChanged(testClients);
verify(mSoftApCallback).onInfoChanged(testSoftApInfo);
verify(mSoftApCallback).onStateChanged(WIFI_AP_STATE_FAILED, SAP_START_FAILURE_GENERAL);
+ verify(mSoftApCallback).onCapabilityChanged(testSoftApCapability);
}
/*
@@ -2075,4 +2100,77 @@ public class WifiManagerTest {
verify(mWifiService).calculateSignalLevel(Integer.MAX_VALUE);
assertEquals(4, actual);
}
+
+ /*
+ * Test behavior of isWapiSupported
+ * @throws Exception
+ */
+ @Test
+ public void testIsWapiSupported() throws Exception {
+ when(mWifiService.getSupportedFeatures())
+ .thenReturn(new Long(WifiManager.WIFI_FEATURE_WAPI));
+ assertTrue(mWifiManager.isWapiSupported());
+ when(mWifiService.getSupportedFeatures())
+ .thenReturn(new Long(~WifiManager.WIFI_FEATURE_WAPI));
+ assertFalse(mWifiManager.isWapiSupported());
+ }
+
+ /*
+ * Test that DPP channel list is parsed correctly
+ */
+ @Test
+ public void testparseDppChannelList() throws Exception {
+ String channelList = "81/1,2,3,4,5,6,7,8,9,10,11,115/36,40,44,48";
+ SparseArray<int[]> expectedResult = new SparseArray<>();
+ expectedResult.append(81, new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11});
+ expectedResult.append(115, new int[]{36, 40, 44, 48});
+
+ SparseArray<int[]> result = WifiManager.parseDppChannelList(channelList);
+ assertEquals(expectedResult.size(), result.size());
+
+ int index = 0;
+ int key;
+
+ // Compare the two primitive int arrays
+ do {
+ try {
+ key = result.keyAt(index);
+ } catch (java.lang.ArrayIndexOutOfBoundsException e) {
+ break;
+ }
+ int[] expected = expectedResult.get(key);
+ int[] output = result.get(key);
+ assertEquals(expected.length, output.length);
+ for (int i = 0; i < output.length; i++) {
+ assertEquals(expected[i], output[i]);
+ }
+ index++;
+ } while (true);
+ }
+
+ /*
+ * Test that DPP channel list parser gracefully fails for invalid input
+ */
+ @Test
+ public void testparseDppChannelListWithInvalidFormats() throws Exception {
+ String channelList = "1,2,3,4,5,6,7,8,9,10,11,36,40,44,48";
+ SparseArray<int[]> result = WifiManager.parseDppChannelList(channelList);
+ assertEquals(result.size(), 0);
+
+ channelList = "ajgalskgjalskjg3-09683dh";
+ result = WifiManager.parseDppChannelList(channelList);
+ assertEquals(result.size(), 0);
+
+ channelList = "13/abc,46////";
+ result = WifiManager.parseDppChannelList(channelList);
+ assertEquals(result.size(), 0);
+
+ channelList = "11/4,5,13/";
+ result = WifiManager.parseDppChannelList(channelList);
+ assertEquals(result.size(), 0);
+
+ channelList = "/24,6";
+ result = WifiManager.parseDppChannelList(channelList);
+ assertEquals(result.size(), 0);
+ }
}
diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
index 04aaa0bbcad0..4cdc4bc2ad48 100644
--- a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
@@ -39,6 +39,7 @@ public class WifiNetworkSuggestionTest {
private static final String TEST_SSID_1 = "\"Test1234\"";
private static final String TEST_PRESHARED_KEY = "Test123";
private static final String TEST_FQDN = "fqdn";
+ private static final String TEST_WAPI_CERT_SUITE = "suite";
/**
* Validate correctness of WifiNetworkSuggestion object created by
@@ -194,6 +195,87 @@ public class WifiNetworkSuggestionTest {
/**
* Validate correctness of WifiNetworkSuggestion object created by
+ * {@link WifiNetworkSuggestion.Builder#build()} for WAPI-PSK network.
+ */
+ @Test
+ public void testWifiNetworkSuggestionBuilderForWapiPskNetwork() {
+ WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+ .setSsid(TEST_SSID)
+ .setWapiPassphrase(TEST_PRESHARED_KEY)
+ .build();
+
+ assertEquals("\"" + TEST_SSID + "\"", suggestion.wifiConfiguration.SSID);
+ assertTrue(suggestion.wifiConfiguration.allowedKeyManagement
+ .get(WifiConfiguration.KeyMgmt.WAPI_PSK));
+ assertTrue(suggestion.wifiConfiguration.allowedPairwiseCiphers
+ .get(WifiConfiguration.PairwiseCipher.SMS4));
+ assertTrue(suggestion.wifiConfiguration.allowedGroupCiphers
+ .get(WifiConfiguration.GroupCipher.SMS4));
+ assertEquals("\"" + TEST_PRESHARED_KEY + "\"",
+ suggestion.wifiConfiguration.preSharedKey);
+ }
+
+
+ /**
+ * Validate correctness of WifiNetworkSuggestion object created by
+ * {@link WifiNetworkSuggestion.Builder#build()} for WAPI-CERT network.
+ */
+ @Test
+ public void testWifiNetworkSuggestionBuilderForWapiCertNetwork() {
+ WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
+ enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.WAPI_CERT);
+ enterpriseConfig.setWapiCertSuite(TEST_WAPI_CERT_SUITE);
+ WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+ .setSsid(TEST_SSID)
+ .setWapiEnterpriseConfig(enterpriseConfig)
+ .build();
+
+ assertEquals("\"" + TEST_SSID + "\"", suggestion.wifiConfiguration.SSID);
+ assertTrue(suggestion.wifiConfiguration.allowedKeyManagement
+ .get(WifiConfiguration.KeyMgmt.WAPI_CERT));
+ assertTrue(suggestion.wifiConfiguration.allowedPairwiseCiphers
+ .get(WifiConfiguration.PairwiseCipher.SMS4));
+ assertTrue(suggestion.wifiConfiguration.allowedGroupCiphers
+ .get(WifiConfiguration.GroupCipher.SMS4));
+ assertNull(suggestion.wifiConfiguration.preSharedKey);
+ assertNotNull(suggestion.wifiConfiguration.enterpriseConfig);
+ assertEquals(WifiEnterpriseConfig.Eap.WAPI_CERT,
+ suggestion.wifiConfiguration.enterpriseConfig.getEapMethod());
+ assertEquals(TEST_WAPI_CERT_SUITE,
+ suggestion.wifiConfiguration.enterpriseConfig.getWapiCertSuite());
+ }
+
+ /**
+ * Validate correctness of WifiNetworkSuggestion object created by
+ * {@link WifiNetworkSuggestion.Builder#build()} for WAPI-CERT network
+ * which selects the certificate suite automatically.
+ */
+ @Test
+ public void testWifiNetworkSuggestionBuilderForWapiCertAutoNetwork() {
+ WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
+ enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.WAPI_CERT);
+ WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+ .setSsid(TEST_SSID)
+ .setWapiEnterpriseConfig(enterpriseConfig)
+ .build();
+
+ assertEquals("\"" + TEST_SSID + "\"", suggestion.wifiConfiguration.SSID);
+ assertTrue(suggestion.wifiConfiguration.allowedKeyManagement
+ .get(WifiConfiguration.KeyMgmt.WAPI_CERT));
+ assertTrue(suggestion.wifiConfiguration.allowedPairwiseCiphers
+ .get(WifiConfiguration.PairwiseCipher.SMS4));
+ assertTrue(suggestion.wifiConfiguration.allowedGroupCiphers
+ .get(WifiConfiguration.GroupCipher.SMS4));
+ assertNull(suggestion.wifiConfiguration.preSharedKey);
+ assertNotNull(suggestion.wifiConfiguration.enterpriseConfig);
+ assertEquals(WifiEnterpriseConfig.Eap.WAPI_CERT,
+ suggestion.wifiConfiguration.enterpriseConfig.getEapMethod());
+ assertEquals("",
+ suggestion.wifiConfiguration.enterpriseConfig.getWapiCertSuite());
+ }
+
+ /**
+ * Validate correctness of WifiNetworkSuggestion object created by
* {@link WifiNetworkSuggestion.Builder#build()} for Passpoint network which requires
* app interaction and metered.
*/
diff --git a/wifi/tests/src/android/net/wifi/WifiScannerTest.java b/wifi/tests/src/android/net/wifi/WifiScannerTest.java
index fa4f711056db..1af0bcbf3f30 100644
--- a/wifi/tests/src/android/net/wifi/WifiScannerTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiScannerTest.java
@@ -80,12 +80,6 @@ public class WifiScannerTest {
private static final int TEST_PNOSETTINGS_MIN_5GHZ_RSSI = -60;
private static final int TEST_PNOSETTINGS_MIN_2GHZ_RSSI = -70;
private static final int TEST_PNOSETTINGS_MIN_6GHZ_RSSI = -55;
- private static final int TEST_PNOSETTINGS_INITIAL_SCORE_MAX = 50;
- private static final int TEST_PNOSETTINGS_CURRENT_CONNECTION_BONUS = 10;
- private static final int TEST_PNOSETTINGS_SAME_NETWORK_BONUS = 11;
- private static final int TEST_PNOSETTINGS_SECURE_BONUS = 12;
- private static final int TEST_PNOSETTINGS_BAND_5GHZ_BONUS = 13;
- private static final int TEST_PNOSETTINGS_BAND_6GHZ_BONUS = 15;
private static final String TEST_SSID_1 = "TEST1";
private static final String TEST_SSID_2 = "TEST2";
private static final int[] TEST_FREQUENCIES_1 = {};
@@ -186,12 +180,6 @@ public class WifiScannerTest {
pnoSettings.min5GHzRssi = TEST_PNOSETTINGS_MIN_5GHZ_RSSI;
pnoSettings.min24GHzRssi = TEST_PNOSETTINGS_MIN_2GHZ_RSSI;
pnoSettings.min6GHzRssi = TEST_PNOSETTINGS_MIN_6GHZ_RSSI;
- pnoSettings.initialScoreMax = TEST_PNOSETTINGS_INITIAL_SCORE_MAX;
- pnoSettings.currentConnectionBonus = TEST_PNOSETTINGS_CURRENT_CONNECTION_BONUS;
- pnoSettings.sameNetworkBonus = TEST_PNOSETTINGS_SAME_NETWORK_BONUS;
- pnoSettings.secureBonus = TEST_PNOSETTINGS_SECURE_BONUS;
- pnoSettings.band5GHzBonus = TEST_PNOSETTINGS_BAND_5GHZ_BONUS;
- pnoSettings.band6GHzBonus = TEST_PNOSETTINGS_BAND_6GHZ_BONUS;
Parcel parcel = Parcel.obtain();
pnoSettings.writeToParcel(parcel, 0);
@@ -205,14 +193,6 @@ public class WifiScannerTest {
assertEquals(TEST_PNOSETTINGS_MIN_5GHZ_RSSI, pnoSettingsDeserialized.min5GHzRssi);
assertEquals(TEST_PNOSETTINGS_MIN_2GHZ_RSSI, pnoSettingsDeserialized.min24GHzRssi);
assertEquals(TEST_PNOSETTINGS_MIN_6GHZ_RSSI, pnoSettingsDeserialized.min6GHzRssi);
- assertEquals(TEST_PNOSETTINGS_INITIAL_SCORE_MAX, pnoSettingsDeserialized.initialScoreMax);
- assertEquals(TEST_PNOSETTINGS_CURRENT_CONNECTION_BONUS,
- pnoSettingsDeserialized.currentConnectionBonus);
- assertEquals(TEST_PNOSETTINGS_SAME_NETWORK_BONUS,
- pnoSettingsDeserialized.sameNetworkBonus);
- assertEquals(TEST_PNOSETTINGS_SECURE_BONUS, pnoSettingsDeserialized.secureBonus);
- assertEquals(TEST_PNOSETTINGS_BAND_5GHZ_BONUS, pnoSettingsDeserialized.band5GHzBonus);
- assertEquals(TEST_PNOSETTINGS_BAND_6GHZ_BONUS, pnoSettingsDeserialized.band6GHzBonus);
// Test parsing of PnoNetwork
assertEquals(pnoSettings.networkList.length, pnoSettingsDeserialized.networkList.length);
diff --git a/wifi/tests/src/android/net/wifi/wificond/PnoSettingsTest.java b/wifi/tests/src/android/net/wifi/wificond/PnoSettingsTest.java
index 775acc70d134..9439c796e1a5 100644
--- a/wifi/tests/src/android/net/wifi/wificond/PnoSettingsTest.java
+++ b/wifi/tests/src/android/net/wifi/wificond/PnoSettingsTest.java
@@ -30,7 +30,7 @@ import java.util.Arrays;
import java.util.HashMap;
/**
- * Unit tests for {@link android.net.wifi.wificond.PnoSettingsResult}.
+ * Unit tests for {@link android.net.wifi.wificond.PnoSettings}.
*/
@SmallTest
public class PnoSettingsTest {
@@ -52,14 +52,14 @@ public class PnoSettingsTest {
@Before
public void setUp() {
mPnoNetwork1 = new PnoNetwork();
- mPnoNetwork1.ssid = TEST_SSID_1;
- mPnoNetwork1.isHidden = true;
- mPnoNetwork1.frequencies = TEST_FREQUENCIES_1;
+ mPnoNetwork1.setSsid(TEST_SSID_1);
+ mPnoNetwork1.setHidden(true);
+ mPnoNetwork1.setFrequenciesMhz(TEST_FREQUENCIES_1);
mPnoNetwork2 = new PnoNetwork();
- mPnoNetwork2.ssid = TEST_SSID_2;
- mPnoNetwork2.isHidden = false;
- mPnoNetwork2.frequencies = TEST_FREQUENCIES_2;
+ mPnoNetwork2.setSsid(TEST_SSID_2);
+ mPnoNetwork2.setHidden(false);
+ mPnoNetwork2.setFrequenciesMhz(TEST_FREQUENCIES_2);
}
/**
@@ -69,10 +69,10 @@ public class PnoSettingsTest {
@Test
public void canSerializeAndDeserialize() {
PnoSettings pnoSettings = new PnoSettings();
- pnoSettings.intervalMs = TEST_INTERVAL_MS;
- pnoSettings.min2gRssi = TEST_MIN_2G_RSSI;
- pnoSettings.min5gRssi = TEST_MIN_5G_RSSI;
- pnoSettings.pnoNetworks = new ArrayList<>(Arrays.asList(mPnoNetwork1, mPnoNetwork2));
+ pnoSettings.setIntervalMillis(TEST_INTERVAL_MS);
+ pnoSettings.setMin2gRssiDbm(TEST_MIN_2G_RSSI);
+ pnoSettings.setMin5gRssiDbm(TEST_MIN_5G_RSSI);
+ pnoSettings.setPnoNetworks(new ArrayList<>(Arrays.asList(mPnoNetwork1, mPnoNetwork2)));
Parcel parcel = Parcel.obtain();
pnoSettings.writeToParcel(parcel, 0);
@@ -90,16 +90,16 @@ public class PnoSettingsTest {
@Test
public void testAsHashMapKey() {
PnoSettings pnoSettings1 = new PnoSettings();
- pnoSettings1.intervalMs = TEST_INTERVAL_MS;
- pnoSettings1.min2gRssi = TEST_MIN_2G_RSSI;
- pnoSettings1.min5gRssi = TEST_MIN_5G_RSSI;
- pnoSettings1.pnoNetworks = new ArrayList<>(Arrays.asList(mPnoNetwork1, mPnoNetwork2));
+ pnoSettings1.setIntervalMillis(TEST_INTERVAL_MS);
+ pnoSettings1.setMin2gRssiDbm(TEST_MIN_2G_RSSI);
+ pnoSettings1.setMin5gRssiDbm(TEST_MIN_5G_RSSI);
+ pnoSettings1.setPnoNetworks(new ArrayList<>(Arrays.asList(mPnoNetwork1, mPnoNetwork2)));
PnoSettings pnoSettings2 = new PnoSettings();
- pnoSettings2.intervalMs = TEST_INTERVAL_MS;
- pnoSettings2.min2gRssi = TEST_MIN_2G_RSSI;
- pnoSettings2.min5gRssi = TEST_MIN_5G_RSSI;
- pnoSettings2.pnoNetworks = new ArrayList<>(Arrays.asList(mPnoNetwork1, mPnoNetwork2));
+ pnoSettings2.setIntervalMillis(TEST_INTERVAL_MS);
+ pnoSettings2.setMin2gRssiDbm(TEST_MIN_2G_RSSI);
+ pnoSettings2.setMin5gRssiDbm(TEST_MIN_5G_RSSI);
+ pnoSettings2.setPnoNetworks(new ArrayList<>(Arrays.asList(mPnoNetwork1, mPnoNetwork2)));
assertEquals(pnoSettings1, pnoSettings2);
assertEquals(pnoSettings1.hashCode(), pnoSettings2.hashCode());
diff --git a/wifi/tests/src/android/net/wifi/wificond/SingleScanSettingsTest.java b/wifi/tests/src/android/net/wifi/wificond/SingleScanSettingsTest.java
index ef598397c12e..f20ec4788655 100644
--- a/wifi/tests/src/android/net/wifi/wificond/SingleScanSettingsTest.java
+++ b/wifi/tests/src/android/net/wifi/wificond/SingleScanSettingsTest.java
@@ -18,7 +18,6 @@ package android.net.wifi.wificond;
import static org.junit.Assert.assertEquals;
-import android.net.wifi.IWifiScannerImpl;
import android.os.Parcel;
import androidx.test.filters.SmallTest;
diff --git a/wifi/tests/src/android/net/wifi/WifiCondManagerTest.java b/wifi/tests/src/android/net/wifi/wificond/WifiCondManagerTest.java
index 48a9afa1d961..f3867c1c3fdf 100644
--- a/wifi/tests/src/android/net/wifi/WifiCondManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/wificond/WifiCondManagerTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.net.wifi;
+package android.net.wifi.wificond;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -38,13 +38,10 @@ import static org.mockito.Mockito.when;
import android.app.AlarmManager;
import android.app.test.TestAlarmManager;
import android.content.Context;
+import android.net.wifi.SoftApInfo;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiScanner;
import android.net.wifi.util.HexEncoding;
-import android.net.wifi.wificond.ChannelSettings;
-import android.net.wifi.wificond.HiddenNetwork;
-import android.net.wifi.wificond.NativeWifiClient;
-import android.net.wifi.wificond.PnoNetwork;
-import android.net.wifi.wificond.PnoSettings;
-import android.net.wifi.wificond.SingleScanSettings;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
@@ -67,7 +64,6 @@ import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -88,7 +84,7 @@ public class WifiCondManagerTest {
@Mock
private IApInterface mApInterface;
@Mock
- private WifiCondManager.SoftApListener mSoftApListener;
+ private WifiCondManager.SoftApCallback mSoftApListener;
@Mock
private WifiCondManager.SendMgmtFrameCallback mSendMgmtFrameCallback;
@Mock
@@ -122,6 +118,7 @@ public class WifiCondManagerTest {
private static final String TEST_QUOTED_SSID_2 = "\"testSsid2\"";
private static final int[] TEST_FREQUENCIES_1 = {};
private static final int[] TEST_FREQUENCIES_2 = {2500, 5124};
+ private static final byte[] TEST_RAW_MAC_BYTES = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05};
private static final List<byte[]> SCAN_HIDDEN_NETWORK_SSID_LIST =
new ArrayList<byte[]>() {{
@@ -131,22 +128,23 @@ public class WifiCondManagerTest {
LocalNativeUtil.decodeSsid(TEST_QUOTED_SSID_2)));
}};
- private static final PnoSettings TEST_PNO_SETTINGS =
- new PnoSettings() {{
- intervalMs = 6000;
- pnoNetworks = new ArrayList<>();
- PnoNetwork network = new PnoNetwork();
- network.ssid = LocalNativeUtil.byteArrayFromArrayList(
- LocalNativeUtil.decodeSsid(TEST_QUOTED_SSID_1));
- network.isHidden = true;
- network.frequencies = TEST_FREQUENCIES_1;
- pnoNetworks.add(network);
- network.ssid = LocalNativeUtil.byteArrayFromArrayList(
- LocalNativeUtil.decodeSsid(TEST_QUOTED_SSID_2));
- network.isHidden = false;
- network.frequencies = TEST_FREQUENCIES_2;
- pnoNetworks.add(network);
- }};
+ private static final PnoSettings TEST_PNO_SETTINGS = new PnoSettings();
+ static {
+ TEST_PNO_SETTINGS.setIntervalMillis(6000);
+ List<PnoNetwork> initPnoNetworks = new ArrayList<>();
+ PnoNetwork network = new PnoNetwork();
+ network.setSsid(LocalNativeUtil.byteArrayFromArrayList(
+ LocalNativeUtil.decodeSsid(TEST_QUOTED_SSID_1)));
+ network.setHidden(true);
+ network.setFrequenciesMhz(TEST_FREQUENCIES_1);
+ initPnoNetworks.add(network);
+ network.setSsid(LocalNativeUtil.byteArrayFromArrayList(
+ LocalNativeUtil.decodeSsid(TEST_QUOTED_SSID_2)));
+ network.setHidden(false);
+ network.setFrequenciesMhz(TEST_FREQUENCIES_2);
+ initPnoNetworks.add(network);
+ TEST_PNO_SETTINGS.setPnoNetworks(initPnoNetworks);
+ }
private static final int TEST_MCS_RATE = 5;
private static final int TEST_SEND_MGMT_FRAME_ELAPSED_TIME_MS = 100;
@@ -180,8 +178,9 @@ public class WifiCondManagerTest {
when(mClientInterface.getWifiScannerImpl()).thenReturn(mWifiScannerImpl);
when(mClientInterface.getInterfaceName()).thenReturn(TEST_INTERFACE_NAME);
mWificondControl = new WifiCondManager(mContext, mWificond);
- assertEquals(true, mWificondControl.setupInterfaceForClientMode(TEST_INTERFACE_NAME,
- mNormalScanCallback, mPnoScanCallback));
+ assertEquals(true,
+ mWificondControl.setupInterfaceForClientMode(TEST_INTERFACE_NAME, Runnable::run,
+ mNormalScanCallback, mPnoScanCallback));
}
/**
@@ -264,7 +263,7 @@ public class WifiCondManagerTest {
assertNull(mWificondControl.signalPoll(TEST_INTERFACE_NAME));
verify(mClientInterface, never()).signalPoll();
- assertFalse(mWificondControl.scan(
+ assertFalse(mWificondControl.startScan(
TEST_INTERFACE_NAME, WifiScanner.SCAN_TYPE_LOW_LATENCY,
SCAN_FREQ_SET, SCAN_HIDDEN_NETWORK_SSID_LIST));
verify(mWifiScannerImpl, never()).scan(any());
@@ -348,8 +347,8 @@ public class WifiCondManagerTest {
public void testTeardownSoftApInterfaceClearsHandles() throws Exception {
testTeardownSoftApInterface();
- assertFalse(mWificondControl.registerApListener(
- TEST_INTERFACE_NAME, mSoftApListener));
+ assertFalse(mWificondControl.registerApCallback(
+ TEST_INTERFACE_NAME, Runnable::run, mSoftApListener));
verify(mApInterface, never()).registerCallback(any());
}
@@ -417,8 +416,8 @@ public class WifiCondManagerTest {
public void testSignalPoll() throws Exception {
when(mWificond.createClientInterface(TEST_INTERFACE_NAME)).thenReturn(mClientInterface);
- mWificondControl.setupInterfaceForClientMode(TEST_INTERFACE_NAME, mNormalScanCallback,
- mPnoScanCallback);
+ mWificondControl.setupInterfaceForClientMode(TEST_INTERFACE_NAME, Runnable::run,
+ mNormalScanCallback, mPnoScanCallback);
mWificondControl.signalPoll(TEST_INTERFACE_NAME);
verify(mClientInterface).signalPoll();
}
@@ -432,7 +431,7 @@ public class WifiCondManagerTest {
// Configure client interface.
assertEquals(true, mWificondControl.setupInterfaceForClientMode(TEST_INTERFACE_NAME,
- mNormalScanCallback, mPnoScanCallback));
+ Runnable::run, mNormalScanCallback, mPnoScanCallback));
// Tear down interfaces.
assertTrue(mWificondControl.tearDownInterfaces());
@@ -448,8 +447,8 @@ public class WifiCondManagerTest {
public void testGetTxPacketCounters() throws Exception {
when(mWificond.createClientInterface(TEST_INTERFACE_NAME)).thenReturn(mClientInterface);
- mWificondControl.setupInterfaceForClientMode(TEST_INTERFACE_NAME, mNormalScanCallback,
- mPnoScanCallback);
+ mWificondControl.setupInterfaceForClientMode(TEST_INTERFACE_NAME, Runnable::run,
+ mNormalScanCallback, mPnoScanCallback);
mWificondControl.getTxPacketCounters(TEST_INTERFACE_NAME);
verify(mClientInterface).getPacketCounters();
}
@@ -464,7 +463,7 @@ public class WifiCondManagerTest {
// Configure client interface.
assertEquals(true, mWificondControl.setupInterfaceForClientMode(TEST_INTERFACE_NAME,
- mNormalScanCallback, mPnoScanCallback));
+ Runnable::run, mNormalScanCallback, mPnoScanCallback));
// Tear down interfaces.
assertTrue(mWificondControl.tearDownInterfaces());
@@ -483,7 +482,7 @@ public class WifiCondManagerTest {
// Configure client interface.
assertEquals(true, mWificondControl.setupInterfaceForClientMode(TEST_INTERFACE_NAME,
- mNormalScanCallback, mPnoScanCallback));
+ Runnable::run, mNormalScanCallback, mPnoScanCallback));
// Tear down interfaces.
assertTrue(mWificondControl.tearDownInterfaces());
@@ -500,7 +499,7 @@ public class WifiCondManagerTest {
@Test
public void testScan() throws Exception {
when(mWifiScannerImpl.scan(any(SingleScanSettings.class))).thenReturn(true);
- assertTrue(mWificondControl.scan(
+ assertTrue(mWificondControl.startScan(
TEST_INTERFACE_NAME, WifiScanner.SCAN_TYPE_LOW_POWER,
SCAN_FREQ_SET, SCAN_HIDDEN_NETWORK_SSID_LIST));
verify(mWifiScannerImpl).scan(argThat(new ScanMatcher(
@@ -520,7 +519,7 @@ public class WifiCondManagerTest {
assertEquals(hiddenSsidWithDup.get(0),
hiddenSsidWithDup.get(hiddenSsidWithDup.size() - 1));
// Pass the List with duplicate elements into scan()
- assertTrue(mWificondControl.scan(
+ assertTrue(mWificondControl.startScan(
TEST_INTERFACE_NAME, WifiScanner.SCAN_TYPE_LOW_POWER,
SCAN_FREQ_SET, hiddenSsidWithDup));
// But the argument passed down should have the duplicate removed.
@@ -535,7 +534,7 @@ public class WifiCondManagerTest {
@Test
public void testScanNullParameters() throws Exception {
when(mWifiScannerImpl.scan(any(SingleScanSettings.class))).thenReturn(true);
- assertTrue(mWificondControl.scan(
+ assertTrue(mWificondControl.startScan(
TEST_INTERFACE_NAME, WifiScanner.SCAN_TYPE_HIGH_ACCURACY, null, null));
verify(mWifiScannerImpl).scan(argThat(new ScanMatcher(
IWifiScannerImpl.SCAN_TYPE_HIGH_ACCURACY, null, null)));
@@ -547,7 +546,7 @@ public class WifiCondManagerTest {
@Test
public void testScanFailure() throws Exception {
when(mWifiScannerImpl.scan(any(SingleScanSettings.class))).thenReturn(false);
- assertFalse(mWificondControl.scan(
+ assertFalse(mWificondControl.startScan(
TEST_INTERFACE_NAME, WifiScanner.SCAN_TYPE_LOW_LATENCY,
SCAN_FREQ_SET, SCAN_HIDDEN_NETWORK_SSID_LIST));
verify(mWifiScannerImpl).scan(any(SingleScanSettings.class));
@@ -558,7 +557,7 @@ public class WifiCondManagerTest {
*/
@Test
public void testScanFailureDueToInvalidType() throws Exception {
- assertFalse(mWificondControl.scan(
+ assertFalse(mWificondControl.startScan(
TEST_INTERFACE_NAME, 100,
SCAN_FREQ_SET, SCAN_HIDDEN_NETWORK_SSID_LIST));
verify(mWifiScannerImpl, never()).scan(any(SingleScanSettings.class));
@@ -570,9 +569,10 @@ public class WifiCondManagerTest {
@Test
public void testStartPnoScan() throws Exception {
when(mWifiScannerImpl.startPnoScan(any(PnoSettings.class))).thenReturn(true);
- assertTrue(mWificondControl.startPnoScan(TEST_INTERFACE_NAME, TEST_PNO_SETTINGS,
- mPnoScanRequestCallback));
- verify(mWifiScannerImpl).startPnoScan(argThat(new PnoScanMatcher(TEST_PNO_SETTINGS)));
+ assertTrue(
+ mWificondControl.startPnoScan(TEST_INTERFACE_NAME, TEST_PNO_SETTINGS, Runnable::run,
+ mPnoScanRequestCallback));
+ verify(mWifiScannerImpl).startPnoScan(eq(TEST_PNO_SETTINGS));
verify(mPnoScanRequestCallback).onPnoRequestSucceeded();
}
@@ -665,8 +665,9 @@ public class WifiCondManagerTest {
public void testStartPnoScanForMetrics() throws Exception {
when(mWifiScannerImpl.startPnoScan(any(PnoSettings.class))).thenReturn(false);
- assertFalse(mWificondControl.startPnoScan(TEST_INTERFACE_NAME, TEST_PNO_SETTINGS,
- mPnoScanRequestCallback));
+ assertFalse(
+ mWificondControl.startPnoScan(TEST_INTERFACE_NAME, TEST_PNO_SETTINGS, Runnable::run,
+ mPnoScanRequestCallback));
verify(mPnoScanRequestCallback).onPnoRequestFailed();
}
@@ -695,11 +696,11 @@ public class WifiCondManagerTest {
final ArgumentCaptor<IApInterfaceEventCallback> apInterfaceCallbackCaptor =
ArgumentCaptor.forClass(IApInterfaceEventCallback.class);
- assertTrue(mWificondControl.registerApListener(
- TEST_INTERFACE_NAME, mSoftApListener));
+ assertTrue(mWificondControl.registerApCallback(
+ TEST_INTERFACE_NAME, Runnable::run, mSoftApListener));
verify(mApInterface).registerCallback(apInterfaceCallbackCaptor.capture());
- final NativeWifiClient testClient = new NativeWifiClient();
+ final NativeWifiClient testClient = new NativeWifiClient(TEST_RAW_MAC_BYTES);
apInterfaceCallbackCaptor.getValue().onConnectedClientsChanged(testClient, true);
verify(mSoftApListener).onConnectedClientsChanged(eq(testClient), eq(true));
@@ -707,7 +708,8 @@ public class WifiCondManagerTest {
int channelBandwidth = IApInterfaceEventCallback.BANDWIDTH_20;
apInterfaceCallbackCaptor.getValue().onSoftApChannelSwitched(channelFrequency,
channelBandwidth);
- verify(mSoftApListener).onSoftApChannelSwitched(eq(channelFrequency), eq(channelBandwidth));
+ verify(mSoftApListener).onSoftApChannelSwitched(eq(channelFrequency),
+ eq(SoftApInfo.CHANNEL_WIDTH_20MHZ));
}
/**
@@ -739,7 +741,7 @@ public class WifiCondManagerTest {
verify(deathHandler).run();
// The handles should be cleared after death.
- assertNull(mWificondControl.getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ));
+ assertEquals(0, mWificondControl.getChannelsMhzForBand(WifiScanner.WIFI_BAND_5_GHZ).length);
verify(mWificond, never()).getAvailable5gNonDFSChannels();
}
@@ -748,7 +750,8 @@ public class WifiCondManagerTest {
*/
@Test
public void testSendMgmtFrameNullCallback() throws Exception {
- mWificondControl.sendMgmtFrame(TEST_INTERFACE_NAME, TEST_PROBE_FRAME, null, TEST_MCS_RATE);
+ mWificondControl.sendMgmtFrame(TEST_INTERFACE_NAME, TEST_PROBE_FRAME, TEST_MCS_RATE,
+ Runnable::run, null);
verify(mClientInterface, never()).SendMgmtFrame(any(), any(), anyInt());
}
@@ -758,8 +761,8 @@ public class WifiCondManagerTest {
*/
@Test
public void testSendMgmtFrameNullFrame() throws Exception {
- mWificondControl.sendMgmtFrame(TEST_INTERFACE_NAME, null,
- mSendMgmtFrameCallback, TEST_MCS_RATE);
+ mWificondControl.sendMgmtFrame(TEST_INTERFACE_NAME, null, TEST_MCS_RATE, Runnable::run,
+ mSendMgmtFrameCallback);
verify(mClientInterface, never()).SendMgmtFrame(any(), any(), anyInt());
verify(mSendMgmtFrameCallback).onFailure(anyInt());
@@ -770,8 +773,8 @@ public class WifiCondManagerTest {
*/
@Test
public void testSendMgmtFrameInvalidInterfaceName() throws Exception {
- mWificondControl.sendMgmtFrame(TEST_INVALID_INTERFACE_NAME, TEST_PROBE_FRAME,
- mSendMgmtFrameCallback, TEST_MCS_RATE);
+ mWificondControl.sendMgmtFrame(TEST_INVALID_INTERFACE_NAME, TEST_PROBE_FRAME, TEST_MCS_RATE,
+ Runnable::run, mSendMgmtFrameCallback);
verify(mClientInterface, never()).SendMgmtFrame(any(), any(), anyInt());
verify(mSendMgmtFrameCallback).onFailure(anyInt());
@@ -787,13 +790,15 @@ public class WifiCondManagerTest {
WifiCondManager.SendMgmtFrameCallback cb2 = mock(
WifiCondManager.SendMgmtFrameCallback.class);
- mWificondControl.sendMgmtFrame(TEST_INTERFACE_NAME, TEST_PROBE_FRAME, cb1, TEST_MCS_RATE);
+ mWificondControl.sendMgmtFrame(TEST_INTERFACE_NAME, TEST_PROBE_FRAME, TEST_MCS_RATE,
+ Runnable::run, cb1);
verify(cb1, never()).onFailure(anyInt());
verify(mClientInterface, times(1))
.SendMgmtFrame(AdditionalMatchers.aryEq(TEST_PROBE_FRAME),
any(), eq(TEST_MCS_RATE));
- mWificondControl.sendMgmtFrame(TEST_INTERFACE_NAME, TEST_PROBE_FRAME, cb2, TEST_MCS_RATE);
+ mWificondControl.sendMgmtFrame(TEST_INTERFACE_NAME, TEST_PROBE_FRAME, TEST_MCS_RATE,
+ Runnable::run, cb2);
verify(cb2).onFailure(WifiCondManager.SEND_MGMT_FRAME_ERROR_ALREADY_STARTED);
// verify SendMgmtFrame() still was only called once i.e. not called again
verify(mClientInterface, times(1))
@@ -820,8 +825,8 @@ public class WifiCondManagerTest {
doNothing().when(mAlarmManager).set(anyInt(), anyLong(), any(),
alarmListenerCaptor.capture(), handlerCaptor.capture());
- mWificondControl.sendMgmtFrame(TEST_INTERFACE_NAME, TEST_PROBE_FRAME,
- cb, TEST_MCS_RATE);
+ mWificondControl.sendMgmtFrame(TEST_INTERFACE_NAME, TEST_PROBE_FRAME, TEST_MCS_RATE,
+ Runnable::run, cb);
mLooper.dispatchAll();
verify(cb).onFailure(anyInt());
@@ -854,7 +859,8 @@ public class WifiCondManagerTest {
final ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class);
doNothing().when(mAlarmManager).set(anyInt(), anyLong(), any(),
alarmListenerCaptor.capture(), handlerCaptor.capture());
- mWificondControl.sendMgmtFrame(TEST_INTERFACE_NAME, TEST_PROBE_FRAME, cb, TEST_MCS_RATE);
+ mWificondControl.sendMgmtFrame(TEST_INTERFACE_NAME, TEST_PROBE_FRAME, TEST_MCS_RATE,
+ Runnable::run, cb);
sendMgmtFrameEventCaptor.getValue().OnAck(TEST_SEND_MGMT_FRAME_ELAPSED_TIME_MS);
mLooper.dispatchAll();
@@ -887,7 +893,8 @@ public class WifiCondManagerTest {
final ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class);
doNothing().when(mAlarmManager).set(anyInt(), anyLong(), any(),
alarmListenerCaptor.capture(), handlerCaptor.capture());
- mWificondControl.sendMgmtFrame(TEST_INTERFACE_NAME, TEST_PROBE_FRAME, cb, TEST_MCS_RATE);
+ mWificondControl.sendMgmtFrame(TEST_INTERFACE_NAME, TEST_PROBE_FRAME, TEST_MCS_RATE,
+ Runnable::run, cb);
sendMgmtFrameEventCaptor.getValue().OnFailure(
WifiCondManager.SEND_MGMT_FRAME_ERROR_UNKNOWN);
@@ -921,7 +928,8 @@ public class WifiCondManagerTest {
final ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class);
doNothing().when(mAlarmManager).set(anyInt(), anyLong(), any(),
alarmListenerCaptor.capture(), handlerCaptor.capture());
- mWificondControl.sendMgmtFrame(TEST_INTERFACE_NAME, TEST_PROBE_FRAME, cb, TEST_MCS_RATE);
+ mWificondControl.sendMgmtFrame(TEST_INTERFACE_NAME, TEST_PROBE_FRAME, TEST_MCS_RATE,
+ Runnable::run, cb);
handlerCaptor.getValue().post(() -> alarmListenerCaptor.getValue().onAlarm());
mLooper.dispatchAll();
@@ -987,8 +995,8 @@ public class WifiCondManagerTest {
final ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class);
doNothing().when(mAlarmManager).set(anyInt(), anyLong(), any(),
alarmListenerCaptor.capture(), handlerCaptor.capture());
- mWificondControl.sendMgmtFrame(TEST_INTERFACE_NAME, TEST_PROBE_FRAME,
- mSendMgmtFrameCallback, TEST_MCS_RATE);
+ mWificondControl.sendMgmtFrame(TEST_INTERFACE_NAME, TEST_PROBE_FRAME, TEST_MCS_RATE,
+ Runnable::run, mSendMgmtFrameCallback);
// AlarmManager should post the onAlarm() callback onto the handler, but since we are
// triggering onAlarm() ourselves during the test, manually post onto handler
@@ -1015,8 +1023,8 @@ public class WifiCondManagerTest {
final ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class);
doNothing().when(mAlarmManager).set(anyInt(), anyLong(), any(),
alarmListenerCaptor.capture(), handlerCaptor.capture());
- mWificondControl.sendMgmtFrame(TEST_INTERFACE_NAME, TEST_PROBE_FRAME,
- mSendMgmtFrameCallback, TEST_MCS_RATE);
+ mWificondControl.sendMgmtFrame(TEST_INTERFACE_NAME, TEST_PROBE_FRAME, TEST_MCS_RATE,
+ Runnable::run, mSendMgmtFrameCallback);
// AlarmManager should post the onAlarm() callback onto the handler, but since we are
// triggering onAlarm() ourselves during the test, manually post onto handler
@@ -1086,56 +1094,6 @@ public class WifiCondManagerTest {
}
}
- // Create a ArgumentMatcher which captures a PnoSettings parameter and checks if it
- // matches the WifiNative.PnoSettings;
- private class PnoScanMatcher implements ArgumentMatcher<PnoSettings> {
- private final PnoSettings mExpectedPnoSettings;
-
- PnoScanMatcher(PnoSettings expectedPnoSettings) {
- this.mExpectedPnoSettings = expectedPnoSettings;
- }
-
- @Override
- public boolean matches(PnoSettings settings) {
- if (mExpectedPnoSettings == null) {
- return false;
- }
- if (settings.intervalMs != mExpectedPnoSettings.intervalMs
- || settings.min2gRssi != mExpectedPnoSettings.min2gRssi
- || settings.min5gRssi != mExpectedPnoSettings.min5gRssi
- || settings.min6gRssi != mExpectedPnoSettings.min6gRssi) {
- return false;
- }
- if (settings.pnoNetworks == null || mExpectedPnoSettings.pnoNetworks == null) {
- return false;
- }
- if (settings.pnoNetworks.size() != mExpectedPnoSettings.pnoNetworks.size()) {
- return false;
- }
-
- for (int i = 0; i < settings.pnoNetworks.size(); i++) {
- if (!Arrays.equals(settings.pnoNetworks.get(i).ssid,
- mExpectedPnoSettings.pnoNetworks.get(i).ssid)) {
- return false;
- }
- if (settings.pnoNetworks.get(i).isHidden != mExpectedPnoSettings.pnoNetworks.get(
- i).isHidden) {
- return false;
- }
- if (!Arrays.equals(settings.pnoNetworks.get(i).frequencies,
- mExpectedPnoSettings.pnoNetworks.get(i).frequencies)) {
- return false;
- }
- }
- return true;
- }
-
- @Override
- public String toString() {
- return "PnoScanMatcher{" + "mExpectedPnoSettings=" + mExpectedPnoSettings + '}';
- }
- }
-
private static class LocalNativeUtil {
private static final int SSID_BYTES_MAX_LEN = 32;